* see [[gardening]]
* gardening is also fun without electronics, but it is also fun to experiment with electronics to care for the plants better
* [[#207​ Why most Arduino Soil Moisture Sensors suck (incl. solution)|https://www.youtube.com/watch?v=udmJyncDvw0]]
* [[Build an Automated Hydroponic System|https://www.youtube.com/watch?v=nyqykZK2Ev4]]
* [[Arduino Garden Controller - Automatic Watering and Data Logging|https://www.youtube.com/watch?v=O_Q1WKCtWiA]]
* [[Automating a Greenhouse with LoRa! (Part 1) -- Sensors (Temperature, Humidity, Soil Moisture)|https://www.youtube.com/watch?v=2YJHcGQnpAk]]
** [[Automating a Greenhouse with LoRa! (Part 2) -- Motorized Window Opener|https://www.youtube.com/watch?v=gsMqwNi4wT4]]
* https://en.wikipedia.org/wiki/Category:Permaculture
** https://de.wikipedia.org/wiki/Kategorie:Permakultur
* [[Greenhouse -- DIY or Buy -- Building a STURDY DIY Greenhouse in 5 days!|https://www.youtube.com/watch?v=pOsgXDpUQdM]]
* [[How to make an Automated Watering System! Automating a Greenhouse with LoRa! (Part 3)|https://www.youtube.com/watch?v=iN6j1AbUbYo]]
* https://farmos.org/
* [[Can Rockets be used to Plant Trees?|https://www.youtube.com/watch?v=NEwBxcGAJwI]]
* http://positron.org/projects/basscannon/
* https://www.instructables.com/id/800watt-12-long-16quot-diameter-Bass-Cannon/
* https://makezine.com/2014/09/09/bass-cannon-the-portable-party/
* https://adammunich.com/the-bass-cannon/
* Bose Acoustic Wave Cannon system
Kritik bzw. der ursprung von problemen wird gerne verallgemeinert bzw. iwie zusammen gefasst und simplifiziert, sodass am ende nur noch die halbe wahrheit übrig ist... ich denke man muss komplexe zusammenhänge wie unsere gesellschaft auch komplex denken... advers zu der überzeugung bzw. zu den aussagen von populisten. das ist jedoch leider nicht so einfach, verständlich und nicht so einprägsam wie populistische ideologien...
"Eckport Bassreflex Gehäuse"

* Jobst Audio JL sub 15n Eminence Kappa 15LFA
* https://www.ebay-kleinanzeigen.de/s-anzeige/15-subwoofer-rcf-18sound-pa-cnc-gef-/1329137498-172-17298

<<<
15“ Subwoofer Gehäuse aus 18mm Birke Multiplex.
CNC gefertigt.
- Maße 457x500x580
- Grenzfrequenz 45HZ
- Netto Volumen. 100l
- Gewicht etwa 24 kg
- 2 Griffe
- M20
- 10mm Frontschaum
- gekantetes Gitter (Wahlweise Hexagonal oder Qg10-12)
- Anschlussfeld fertig verlötet
Empfohlene Lautsprecher
18 Sound 15ND930
Rcf LF15G401
<<<

* https://www.ebay-kleinanzeigen.de/s-anzeige/subwoofer-15-18-21-rcf-l18p300-18sound-cnc-gef-gehaeuse-pa/1180681262-172-17298?simcid=162883d3-a97d-48f8-903a-089cfec42c83

<<<
18“ Subwoofer Gehäuse aus Birke Multiplex.
- Maße 60x60x70
- Fr 46hz / alternativ mit anderer Abstimmung 35Hz
- Netto Volumen. 155Liter
- Gewicht 31kg.
- 4 Griffe
- M20
<<<

* Jobst audio JM Sub 18N

referenz/vergleich: https://www.thomann.de/de/the_box_pro_tp2181600_mkiii.htm


andere

* Lbh 118
* https://www.ebay-kleinanzeigen.de/s-anzeige/2-x-limmer-115-pa-bass-bandpasshorn-horn-b-c-15nw100-limmerbass/2377633054-172-1485 - 2 x Limmer 115 PA Bass Bandpasshorn Horn B&C 15NW100 Limmerbass
<<<Limmerbass 115
Bandpasshorn mit 15" Chassis.
Bestückt mit B&C 15NW100
Professionell gefertigt mit 3fach Speakon auf der Rückseite sowie 2fach Speakon im Horn für Cardioid Aufstellung.
Seitlich Griffe an allen 4 Ecken sowie Stapelfräsungen und Stativflansch.
Außenmaße 61x47x77cm BxHxT
<<<
* limmer basshorn
* https://vimeo.com/152280896
* https://www.open-electronics.org/an-open-source-3d-printable-guerilla-projector-guerrillabeam/
amplifiers mostly designed into an IC package

* https://www.ti.com/product/TAS5825M
* TI has a lot
* Infineon
* Analog Devices
* used mostly on cheap "chinese" amplifier boards or in highly integrated devices such as laptops, TVs, bloetooth/smart speakers
just a list, these channels might share bullshit, i can't review it, some comercially promote products

* [[ALPHA SOUND|https://www.youtube.com/channel/UCOkU9tlJ6EdtZbLXtjg0cIw]]
* [[Dave Rat|https://www.youtube.com/channel/UC_nJM07b0k7C9CvcM-9OH6w]]
* [[Audio University|https://www.youtube.com/channel/UCH3_Mmyv5OFV0vkyF1tz_Iw]]
* [[EventelevatorDe|https://www.youtube.com/c/EventelevatorDe/videos]]
* [[MusiciansPro|https://www.youtube.com/user/MusiciansPro/videos]]
* [[behringerofficial|https://www.youtube.com/c/behringerofficial/videos]]
** [[BehringerKnowledgeBaseOfficial|https://www.youtube.com/c/BehringerKnowledgeBaseOfficial/videos]]
* [[stageleftaudio|https://www.youtube.com/user/stageleftaudio/videos]]
* [[Acousticfields101|https://www.youtube.com/c/Acousticfields101/videos]]
* [[Michael Curtis|https://www.youtube.com/channel/UCrJ_l4YMvsCXGkAwhOjLZdQ]]
* [[Sound Advice with Rob|https://www.youtube.com/channel/UCepIavD0Gu54Vl68iuhroxA/videos]]
* [[LiveSoundTips|https://www.youtube.com/c/LiveSoundTips/videos]]
* [[DIYAudioGuy|https://www.youtube.com/c/DIYAudioGuy/videos]]
* [[sweetwater|https://www.youtube.com/c/sweetwater/videos]]
* [[AttawayAudio|https://www.youtube.com/c/AttawayAudio/videos]]
* [[mothergrid_veranstaltungstechnik_news|https://www.youtube.com/c/mothergrid_veranstaltungstechnik_news/videos]]
* [[inthemix|https://www.youtube.com/c/inthemix/videos]]
* [[speakerscott|https://www.youtube.com/user/speakerscott/videos]]
* [[Auftrag Sound!|https://www.youtube.com/channel/UCbDZO8Vh_md52hec9jp-Piw]]
* [[Rational Acoustics|https://www.youtube.com/user/RationalAcoustics]]
* [[Podcastage|https://www.youtube.com/c/Podcastage/videos]]
* [[MusicRepo|https://www.youtube.com/c/MusicRepo/videos]]
* [[SoundBlab|https://www.youtube.com/c/SoundBlab/videos]]
* [[simplyspeakers|https://www.youtube.com/user/simplyspeakers/videos]]
* [[The Power Place Production|https://www.youtube.com/channel/UCg2U-bBRNQOOFylPe0JIuRQ/videos]]
* [[NicosGigs|https://www.youtube.com/c/NicosGigs]]
* [[ThomannStudioRecording|https://www.youtube.com/c/ThomannStudioRecording/playlists]]
* https://www.youtube.com/@MichaelCurtisAudio

* https://www.youtube.com/@frankswerkstatt



stuff

* [[Phil's Lab - Audio Electronics Playlist|https://www.youtube.com/playlist?list=PLXSyc11qLa1ZGY3nD7to5eQGKGMREhNGl]]
"smart" batteries are batteries or battery packs with a BMS or similar monitoring circuit and communication to the host device.

every battery-pack using lithium-based batteries should have a thermal cutout / thermal protection, which shuts off the power delivery if the pack overheats. but even some single cell batteries, most commonly in phones, have thermistors, so the power management chip can detect overheating and shut it off.

but many packs don't just have such a thermistor, many also have additional, digital, data lines to communicate other information, like serial-number, charge status, etc., to the host device.

there are several standards/protocols which might be used:

* MIPI Battery Interface (BIF)
* https://en.wikipedia.org/wiki/Power_Management_Bus
* https://en.wikipedia.org/wiki/System_Management_Bus
* https://mpoweruk.com/communications.htm

stuff:

* https://media.blackhat.com/bh-us-11/Miller/BH_US_11_Miller_Battery_Firmware_Public_WP.pdf
* http://sbs-forum.org/
* Gm328 Transistor / component tester with encoder (seems to be an improved version of the single button one, more features)
** https://www.youtube.com/watch?v=C38eSPOF1o0
** bought one (kit)
** might reverse engineer it
** [["transistor tester" reverse engineering]]
* https://github.com/search?q=transistortester
** https://github.com/maugsburger/avr-component-tester
** https://github.com/BackupGGCode/avr-component-tester
* https://www.mikrocontroller.net/articles/AVR_Transistortester#Einleitung_.28deutsch.29
* https://www.slideshare.net/dpavlin/cheap-good-hackable-tools-from-china-avr-component-tester
* https://www.instructables.com/AVR-Transistor-Tester/
* https://www.eevblog.com/forum/testgear/$20-lcr-esr-transistor-checker-project/
* [[Full Circuit Schematic Draft 2017 AVR Transistor Tester Component ESR LCR Meter Frequency Generator|https://www.youtube.com/watch?v=T8Fl7HL0c0c]]
* [[#290​ How do Transistor Testers work (and some other insights)|https://www.youtube.com/watch?v=4Xsg8lpP75s]]
* https://hackaday.com/2015/04/24/review-transistor-tester/

* https://raw.githubusercontent.com/Mikrocontroller-net/transistortester/master/Doku/trunk/pdftex/german/ttester.pdf#section.3.3 - kalibrierung
* https://github.com/Mikrocontroller-net/transistortester/
* [["transistor tester" (avr) component tester]]
* uses atmega328p
* might be possible to read the flash contents of the atmega328p and disassemble it
** [[atmega/atmel/avr/arduino disassembling]]
* silkscreen: "K120263BSJH" and "2578AY-AT"
* some presumably chinese characters are on the copper layers
* some unknown/unsure components
** 6-pin smd chip; marked SVR5-04 on silkscreen; marked .V05 on chip
** 7550A-1 (marked on component), TO-92 package
*** maybe: https://pdf1.alldatasheet.com/datasheet-pdf/view/1139972/BOOKLY/7550.html?
** not sure of what type the small capacitors are... ceramic?
** S9014 (C331) (2x); TO-92 package; npn transistor?
** S9012 (H331); TO-92 package; PNP transistor?
** WS TL431A 1535SD in TO-92 package; voltage reference
*** maybe http://www.ti.com/lit/ds/symlink/tl431.pdf
** some diode-like 2-pin package (marked 6V8C with some logo) parallel a ceramic smd cap next to the SVR5-04
* display assembly
** display glued directly to a pcb, flat-flex soldered directly to the back
** 8 pins/connections for interfacing with main-board
** AMS1117, probably 3.3V linear regulator
* [[Full Circuit Schematic Draft 2017 AVR Transistor Tester Component ESR LCR Meter Frequency Generator|https://www.youtube.com/watch?v=T8Fl7HL0c0c]]
* [[#290​ How do Transistor Testers work (and some other insights)|https://www.youtube.com/watch?v=4Xsg8lpP75s]]
* https://www.rapiddirect.com/blog/die-casting-mold/
* https://www.reddit.com/r/Metalfoundry/comments/9bb2hv/diy_die_casting/
* https://www.ehow.com/how_10070325_make-diecast-toys.html
* https://diecasting.com/blog/die-cast-tooling-101/

* https://en.wikipedia.org/wiki/Die_casting
* https://de.wikipedia.org/wiki/Druckguss
** https://de.wikipedia.org/wiki/Aluminiumdruckguss
* https://www.youtube.com/watch?v=-vDFWND0zHM
* https://www.youtube.com/watch?v=pks96GSnjbo
* https://www.youtube.com/watch?v=sEc5Jak9jsg
* https://www.youtube.com/watch?v=hp3EjcLSXAk
* https://www.youtube.com/shorts/NME0Xpj_-Dk

schweißen - welding

* [[ Wie schweißt man richtig Aluminium Guss - Tutorial für Beginner |https://www.youtube.com/watch?v=VF-npEsJuE4]]
* https://www.youtube.com/watch?v=XTxMrkRNzJo
you need a pretty high current for spot welding, voltage ist not as importand.
modules from china use either some lithium battery or big mains transformers (modified microwave transformers) as main supply.

* [[BitBastelei #412 - Sunkko 737G Punktschweißgerät|https://www.youtube.com/watch?v=I8dtf0ydr2U]]
* [[Voltlog #198 - SUNKKO 737G Battery Spot Welding Machine Review & Teardown|https://www.youtube.com/watch?v=FPTofhPgHqY]]
* https://www.pedelecforum.de/wiki/doku.php?id=akku:eigenbau-punktschweissgeraete
* https://hackaday.com/2022/10/17/hackaday-prize-2022-a-not-so-smart-spot-welder/

lead acid "car" battery based

* [[Make your own Crude Battery Spot Welder with a Car Battery!|https://www.youtube.com/watch?v=VrcmvmM7h3Y]]
* [[I spent $100 to save 20 bucks... and it was TOTALLY worth it!|https://www.youtube.com/watch?v=aHNmVV7THBs]]
* the cheap red ones with supercap
** [[Super Cheap Spot Welder|https://www.youtube.com/watch?v=UF3GtD67jPQ]]
*** Das Problkem liegt darin, dass der Controller stürzt wenn man schweißt und dann nicht abschaltet und da muss man einfach nur n zusätzlichen Kondensator einbauen
*** [[Repair Attempt - Super Cheap Spot Welder|https://www.youtube.com/watch?v=Zk_ir69kB5Q]]
** [[Mini Spot Welder - watch/modify before use it|https://www.youtube.com/watch?v=fdnO0Z-scjA]]
** [[Cheap Battery Spot Welder 18650, Yes its awesome!|https://www.youtube.com/watch?v=231qtaRIs3M]]
** [[Cheap 18650 Spot Welder Reliability Mods and Test|https://www.youtube.com/watch?v=u5khY6d3qds]]
** there seem to be different versions... e.g. Adam Welch shows a different version than the one i got... every version seems to have its own flaws lol
*** [[Follow up Mini Spot Welder revised/different edition (BK11-1K)|https://www.youtube.com/watch?v=slU0oCKENLI]]
*** [[New Mini Spot Welder Bl18-2k vs Bk11-1k|https://www.youtube.com/watch?v=0A3sDXM8jQQ]]
*** [[Another Flaw in the Bk11-BL18 Mini Spot Welder!|https://www.youtube.com/watch?v=ec4dpBrU4v4]]
*** [[All "Mini Spot Welder" versions: circuit Analysis, differences and faults|https://www.youtube.com/watch?v=RSrlXqFxhp8]]
*** i got CA04-2k
** https://www.youtube.com/c/Luca_Techy/videos - this great channel explores these spot welders and their flaws in-depth

LiPo-based

* [[EBike Battery Pack ~ DIY or Buy ~ Electric Bike Conversion (Part 2)|https://www.youtube.com/watch?v=b2sBhDxmPmA]] - using k-weld
* [[Awesome $50 Tiny Spot Welder - Better than Expected - 1031|https://www.youtube.com/watch?v=TI_ZV-5WHi4]]
* [[DC Spot Welders - which is better?|https://www.youtube.com/watch?v=ERF7XwCcli0]]
* [[Spot Welder compare|https://www.youtube.com/watch?v=K1HZs4ix_6s]]

~SuperCAP based

* [[Battery Spot Welder (CD Welder) -- DIY or Buy|https://www.youtube.com/watch?v=5TVNdMqVZpk]]

Microwave transformer-based

* [[Building a Spot Welder from a Microwave Transformer!|https://www.youtube.com/watch?v=dRTplGUzw28]]
** [[Don't Build a Spot Welder Without Watching This First!|https://www.youtube.com/watch?v=PW-RbgmcPHo]]
* [[DIY Spot Welder From Microwave Transformer - HOW TO|https://www.youtube.com/watch?v=UseccvORpk8]]
* [[HACKED!: Microwave Transformer becomes a High Current Transformer|https://www.youtube.com/watch?v=fQXBNkaB1tU]]
* [[Voltlog #207 - Making a DIY Spot Welder From A Microwave Transformer|https://www.youtube.com/watch?v=nUR-giwn4z0]]
* [[Spot Welder from microwave - how to increase the power|https://www.youtube.com/watch?v=A7CHQbWcFZ0]]
* https://avdweb.nl/popular/spotwelder/diy-spot-welder
* [[DIY Spot Welding Machine|https://www.youtube.com/watch?v=hTaGa93lOGU]]
* [[Microwave Oven Transformer Spot Welder 1|https://www.youtube.com/watch?v=uoSChZxZuAs]]

!! my 1st attempt:

''WARNING: This build uses mains voltage which can be lethal if not handled correctly; make sure mains connections are isolated correctly and use an propperly isolated or grounded case''

* parts
** "NY-D01" 100A Thyristor-based controll board
** microwave transformer
** old footswitch with 6.3mm jack from audio equipment
** 9-12V trafo als versorgung für das board
** some copper-like welding rod as electrodes
** 2m thick copper cable, like 25mm² (AWG 3)
** mains cable and plug
** some insulated crimp-on connectors
* remove the high-voltage secondary winding of the transformer
* replace it with thick cable as secondary winding
** how many windings are needed has to be tested
** 2cm height means 2 windings max for 25mm² (AWG3)
** it seems 2 windings aren't enough, so thinner cable has to be tested
* i used insulated crimp connectors to connect the mains cable to the transformer primary and board
** the plug i used is a CEE 7/7 that means live an neutral can be mixed up and are not as important to follow
** i connected one mains wire directly to the transformer primary and one to the Thyristor pin labeled "1"
** then the thyristor pin "2" to the transformer primary with a single cable
* improvements:
** meassure mains inrush current and add a fuse for the transformer
** case, maybe case of a broken PC PSU
*** cheap furniture glider as feet for the lab bench

!! my 2nd attempt

my second  attempt was using a mosfet board for 
!! Idee

ich hatte die Idee LED leisten die adressier- und ansteuerbar sind selbst zu bauen statt zu kaufen, vor allem weil ich die idee hatte ein logo für den Tolerave mit Neon-LED Streifen zu machen. siehe auch: 
[[YT: bigclivedotcom: Make custom LED neon shapes|https://www.youtube.com/watch?v=y9bSzE9ir1Q]]
mir waren dann einfarbige neon LED streifen zu einfach und zu langweilig, also wollte ich nach RGB und ansteuerbar schauen, gibts. und dann war veranstaltung mit dem sonnensystem in der robotron kantine und wir hatten DIY LED leisten von den Irrlichtern ausgeliehen und ich war ziemlich begeistert... nun meine ideensammlung:

mit tipps und hilfe von https://irrlicht.uber.space/

siehe https://irrlicht.uber.space/technik

* https://hackaday.com/2019/05/06/getting-that-neon-sign-look-without-all-the-hassle/
* https://gvmled.com/bd100d-exp/ / https://gvmledeu.com/bd100d-exp/

!! Protokolle überblick, kabelgebunden/kabellos

DMX (richtiger DMX512) kann über 5-pol XLR Kabel transportiert werden, manchmal wird aber nur 3-pol XLR benutzt weil 2 leiter nicht wirklich genutzt sind. Es gibt auch systeme um DMX über CAT5 ethernet kabel zu leiten, das erhöht die reichweite. wireless systeme für DMX sind alle proprietär und es scheint da keine offenen standards zu geben, alles recht proprietär und das mag ich nicht. es gibt zwar ein recht großes monopol, aber das mag ich noch weniger.

kabel möchte ich vermeiden weswegen DMX und RDM rausfallen. RDMNet (RDM über netzwerk) ist noch in entwicklung und nicht verbreitet.

kontrollprotokolle die in frage kommen sind (s)ACN oder ~ArtNet, weil die sind IP basiert und funktionieren damit auch über Wlan, außerdem sind beide offene standards und es gibt offene implementationen, sie sind weit verbreitet. beide transportieren im grunde normale DMX steuersignale.

* https://wiki.openlighting.org/index.php/Comparison_of_DMX_over_IP_protocols
** https://wiki.openlighting.org/index.php/Category:ArtNet
* https://wiki.openlighting.org/index.php/Category:E1.31
* see [[DMX]]


!! controller firmware

writing specialized firmware for this task is possible, but i think WLED is just the best option. it supports pretty much every protocol and means of control and it completely customizeable through a ton of settings and features, if thats not enough there are allready existing usermods and it seems pretty easy to write mods. its just to versatile not to use.

* ''https://github.com/Aircoookie/WLED''
** https://electric-junkie.de/2020/08/wled-quickstart/
** [[WLED for Beginners in 2022 (PLUG n' PLAY!)|https://www.youtube.com/watch?v=FvPuiWTE6ic]]
* https://github.com/MartyMacGyver/ESP32-Digital-RGB-LED-Drivers
* https://github.com/atuline/WLED - wled sound reactive fork

supported programmers: https://kno.wled.ge/basics/compatible-hardware/#usbttl-adapters habe einen kompatiblen

writing own firmware:

* https://fastled.io/
** https://github.com/FastLED/FastLED/wiki/Overview
** https://github.com/FastLED/FastLED/wiki/ESP8266-notes
* https://github.com/mtongnz/ESP8266_ArtNetNode_v2
* https://github.com/natcl/Artnet
* https://github.com/rstephan/ArtnetWifi


!! Controller

see also [[microcontroller]]

als controller für leisten oder tolerave logo ziehe ich verschiedene microcontroller mit integriertem WLAN in betracht primar ESP8266/ESP32 (vlt. sogar die RISCV versionen) oder vlt. Raspberry Pi Pico W.  die stm32 fallen fast raus, weil die eh kaum zu bekommen sind momentan.
für esp8266/esp32 gibt es auch schon gute auswahl an fertiger firmware.

proprietär:

* https://www.ulrichradig.de/home/index.php/dmx
** https://www.ulrichradig.de/home/index.php/dmx/art-net-pixel-con-neu
* https://github.com/twischer/WLAN-IO
* https://www.discohat.com/qlc/
* https://www.advateklights.com/products/pixel-control
* https://opendmx.net/index.php/KarateLight


!! verkabelung/controller pcb design etc.

es gibt schon einige hardware und controller designs die mit WLED kompatibel sind

https://kno.wled.ge/basics/compatible-hardware/

basics

* esp32 oder esp8266
* 3,3V stromversorgung für den ESP
** e.g. AMS1117 oder kleiner
* level converter/shifter
** https://kno.wled.ge/basics/compatible-hardware/#levelshifters
** TXS0108(E), TXS0102, TXS0104 - verbreitet, 2 kanal version auch recht klein
** SN74AHCT125(N)
** SN74LVC2T45
** 74AHCT32
** PCA9306?
** dicrete - not viable for small designs
* LED data / strip input protection
** resistor
** https://wled.shop/produkt/ws2812-protect/
*** https://wled.shop/wp-content/uploads/2021/11/SK6812_Datenv10.pdf
* lamp input protection
** fuse
** capacitor
** reverse polarity protection?
* programming connector
** only ground&data lines to save space
** maybe use pogo-pins to save space?


stuff

* Level shifter für 3.3V uC
** https://www.addicore.com/Logic-Level-Converter-Bi-Directional-5V-to-3-3V-p/227.htm
** https://www.adafruit.com/product/1787
** https://www.adafruit.com/product/1779
* resistor für daten line an LEDs
** https://learn.adafruit.com/adafruit-neopixel-uberguide/powering-neopixels
** https://forum.arduino.cc/t/arduino-ws2812b-data-pin-resistor/533031/3
** https://forums.parallax.com/discussion/158590/ws2812b-and-series-resistor
** tutorials with unknows quality suggest ~220-510Ohm
** https://learn.adafruit.com/adafruit-neopixel-uberguide/best-practices
** adafruit states 300-500 Ohm
* elko für pufferung an LEDs
* https://github.com/Hasenpups/WLED_ESP32_Controller
* mit wled ist es möglich mehrere strips mit den selben daten anzusteuern, aber bei WS2812 o.Ä. kann man auch die datenleitungen parallel schalten: https://www.reddit.com/r/arduino/comments/jvqkuq/addressing_ws2812b_strips_in_parallel_individually/


!! LED Typen

was die LEDs angeht bin ich noch am schauen, am verbreitetsten sind die WS2812(x) und WS2813(x) rgb led streifen, der controll chip ist da in den led chips integriert, die laufen aber auf 5V und da ist die stromstärke schnell sehr groß.
die WS2811 streifen haben zwar einen externen chip, laufen aber auf 12V und sind damit auch praktischer.
es gibt SK2812 die auch noch einen weiß ton (entweder natur, warm, kalt oder "bernstein") integrieren, laufen aber auch auf 5V und ich weiß nicht ob es einfach ist software darauf zu mappen.
relativ neu und am besten scheinen WS2815, integrierter Chip aber laufen auf 12V, aber keine ahnung wie gut man die bekommt, habe die noch nicht viel gesehen.
es könnte sein das das steuerprotokoll anfällig ist, aber da die so verbreitet sind und die Neon led streifen scheinbar nur mit solchen LEDs existieren werde ich das erstmal testen.

* https://www.advateklights.com/knowledge-base/pixel-leds
* https://www.ulrichradig.de/home/index.php/dmx/art-net-pixel-con-neu - has listing of common LED/controller types
* [[LED Strips, what's the difference? WS2811, WS2812B, 2812Eco, WS2813, WS2815, SK6812, SK9822.|https://www.youtube.com/watch?v=QnvircC22hU&list=PL-51DG-VULPq5w_n4T6gVqc8q8TkA2B8m&index=5]]
* [[7 Common LED Strip FAILS and How To Avoid Them|https://www.youtube.com/watch?v=Fu4qZW0pQm4&list=PL-51DG-VULPq5w_n4T6gVqc8q8TkA2B8m&index=9]]
* https://kno.wled.ge/basics/compatible-hardware/#addressable-led-strips

Neon

* a lot of those neon LED strips use 3535 LEDs which require an external controller
* but there are some using the WS2811 controller internally

!! LED Alu Profile/Leisten/Diffuser / Gehäuse

es gibt viele kompakte profile für den einbau ins haus oder in/an möbel. stabile für professionelle nutzung scheinbar eher weniger

für die neon led streifen reichen vlt auch einfache alu U-profile

* https://www.isolicht.com/led-streifen/led-profile/led-aufbauprofile-led-montageprofile/aufbauprofil-mini-24-flach/profi-led-set-4m-2x2m-aufbauprofil-mini-24-schwarz-mit-runder-opaler-abdeckung
** https://www.isolicht.com/catalogsearch/result/index/?p=2&q=profi+led+set
** https://www.isolicht.com/led-streifen/led-profile/led-aufbauprofile-led-montageprofile
*** https://www.isolicht.com/led-streifen/led-profile/led-aufbauprofile-led-montageprofile/aufbauprofil-maxi-24?product_list_limit=60&product_list_order=price_asc
** https://www.isolicht.com/led-streifen/led-profile/led-einbauprofile/einbauprofil-mini-24-flach/endkappe-ec46b-alu-fur-auf-einbauprofil-mini-24-flach-2-stk-inkl-schrauben

* [[I bought every LED Diffuser channel on Amazon to find the best one. Mission Accomplished.|https://www.youtube.com/watch?v=DKOWeuV1FWE]]

die profile müssen auch genug platz für den controller haben

schwarze channel innen am besten weiß ansprühen

hab jemensch gefunden der LED röhren mit normalen LED strips und WLED controller in 5cm acrylglas rohr gebaut hat.

polycarbonat rohr wäre sehr bruchfest. gibt es aber nicht diffus/milchig so wie es aussieht
milchglasfolie oder schleifen könnte vlt. funktionieren, ist aber nicht perfekt

* PC mit schleifen milchig machen testen
** https://www.instructables.com/Sanding-polycarbonate-for-frosty-affect/
* einfach acrylglas testen
* [[Alle Unterschiede zwischen Hobbyglas, Plexiglas, Polycarbonat, Polystyrolglas in einem Video!|https://www.youtube.com/watch?v=Pq1knBcrEWQ]]
* mit farbe milchig machen
** [[ I found a really easy way to make milky frosted glass for light fixtures |https://www.youtube.com/watch?v=ed8QTKtLxKs]]
* https://www.homeownershub.com/woodworking/frosting-transparent-polycarbonate-217187-.htm
* sandblasting?


Acryl / PMMA / PETG:

* [[This is why I recommend PMMA Tubing...|https://www.youtube.com/watch?v=HAtAyXOnv2Y]]


rohr bauart, meine ideen:

* 1m oder 0,5m länge
* 3d gedruckte endkappen
* 3d-gedruckte channel innen (am besten weißes filament oder ansprühen)
* supports/standoffs/spacer die den channel in der mitte halten am besten aus transparentem acryl lasern/schneiden oder transparentem resin 3d drucken damit sie möglichst wenig auffallen
* 3 oder 4 strips (testen) für gleichmäßige 360° beleuchtung, LEDs haben ja auch leuchtwinkel angaben
* rohr dicke nicht unbedingt 5cm, sondern vlt. auch dünner, testen mit abständen LED-diffusor und jenachdem wie es mit den channeln möglich ist.
* in channel können kabel für stromversorgung durchgeführt werden
* controller könnte in channel versteckt werden
* 60leds pro meter oder vlt. mehr
* die channel bzw. die halterungen für die LED strips intern weiß, 3d gedruckt
* die zentrier-pins bzw. abstandshalter (am besten vlt. 3) am besten möglichst dünn (aber stabil) und transparent
* channel stecken oder schrauben?
** schrauben mit langen gewindestangen einfacher zu designen
** nur gesteckt wäre vlt. etwas locker und verkleben wäre auch mist
* Endkappen für das Rohr aus Transparentem ABS?
** relativ stabil, mit transparentem kleber festkleben, oder o-Ring und schrauben?
* ABS Teile könnten vlt. in einer DIY Azeton-Dampf-Kammer glatt und noch transparenter gemacht werden
* verschiedene rohr materialien testen
** [[This is why I recommend PMMA Tubing...|https://www.youtube.com/watch?v=HAtAyXOnv2Y]]
** Verkäufer nach datenblättern fragen falls nicht selbst angegeben.

!! DMX/ACN/~ArtNet Steuersoftware

software für den PC ist bisschen rar was open source angeht, aber QLC+ kann da scheinbar alles, ist denke ich auch eine spende an den entwickler wert.
led/pixel mapping software gibts da weniger. es gibt zwar mapmap, aber das ist nur video projection mapping und supported keine einzelnen LEDs oder andere outputs als beamer, also nicht richtig vergleichbar zu ~MadMapper.

see [[open VJ, projection/Video Mapping]]



* https://www.churchtechideas.com/qlc-led-matrix-tutorial/
* https://en.wikipedia.org/wiki/Show_control


!! Stromversorgung

* [[The BEST way to join LED strips with no gaps or seams + make waterproof power injection connections.|https://www.youtube.com/watch?v=WGgzWWrCIhY]]
* [[7 Common LED Strip FAILS and How To Avoid Them|https://www.youtube.com/watch?v=Fu4qZW0pQm4&list=PL-51DG-VULPq5w_n4T6gVqc8q8TkA2B8m&index=9]]
* [[Power LED Lights + Injection. Complete Walkthrough|https://www.youtube.com/watch?v=KFtjf5mD6tA]]
* [[3 Quick Fixes for LED Color Issues - Power Injection, Voltage Drop, Brightness Regulation and More.|https://www.youtube.com/watch?v=apwQ5Jh4VyE]]


!! "dumme" RGB(W) LEDs ansteuern

* WLED hat die option PWM RGB(W) auszugeben
* es gibt einfache mosfet module fertig aus china zu kaufen


!! stuff

* https://www.youtube.com/results?search_query=esp32+artnet
* https://www.instructables.com/Artnet-LED-Pixels-With-ESP8266/
* https://github.com/polyfloyd/ledcat
* [[Playlist: Individually Addressable RGB LEDs|https://www.youtube.com/playlist?list=PL-51DG-VULPq5w_n4T6gVqc8q8TkA2B8m]]
* [[SDG #048 DMX Controlled RGB Linear Light Strips|https://www.youtube.com/watch?v=bDFkVJ4jwTE]]
* https://present.readthedocs.io/en/latest/
* https://asciimatics.readthedocs.io/en/stable/index.html
** https://github.com/peterbrittain/asciimatics
* [[Engineering Drawings: How to Make Prints a Machinist Will Love|https://www.youtube.com/watch?v=32CXeJVgiLA]]
* [[Limits and Fits: The ISO System|https://www.youtube.com/watch?v=wvVMs2BZdeU]]
* [[Intro to Mechanical Engineering Drawing|https://www.youtube.com/watch?v=1Hm5Zyjmjac]]
* [[Blueprint Reading: Unit 2: Multiview Drawing|https://www.youtube.com/watch?v=1roPfzjHXnM]]
* https://wiki.analog.com/resources/app-notes/an-1112
* https://www.sweetwater.com/insync/equivalent-input-noise-ein/
* https://en.wikipedia.org/wiki/Equivalent_input
* balanced input is important for PA stuff
* https://de.wikipedia.org/wiki/Vorverst%C3%A4rker
* https://de.wikipedia.org/wiki/Mikrofonvorverst%C3%A4rker
* https://de.wikipedia.org/wiki/Mikrofonverst%C3%A4rker

DIY

* https://harc.org.za/projects/Low%20noise%20Microphone%20amp.pdf
* https://www.electroschematics.com/low-noise-microphone-preamplifier/
* https://www.eleccircuit.com/low-noise-pre-microphone-amplifier/
* https://www.youtube.com/watch?v=LoQu3XXIayc
* https://sound-au.com/p-cat.htm#mic
* https://sound-au.com/p-cat.htm#pre
* [[EEVblog #629 - How To Design a Microphone Preamplifier|https://www.youtube.com/watch?v=niZizzHBanA]]
* [[ Building a Microphone and Line Level Amplifier - Part 1 |https://www.youtube.com/watch?v=AjAkfLb1_H8]]
see also [[zeug das ich gebrauchen könnte]]

* diverse lose festplatten, Computernetzteile, laufwerke, grafikkarten
* DVD Spieler
* RAM
** Kingston 2GB (2 x 1GB) DDR 400 (PC 3200) (KVR400X64C3AK2/2G)
** 2x 1 GB DDR2 SODIMM PC2–5300 667 MHz CL5 NANYA nt1gt64u8hb0bn-3 C
**exceleram DIMM Kit 4GB (2x 2GB), DDR2-1066, CL5-5-5-15 (EX2-41066C2-RX)
** Samsung 512MB Pc2-5300U
** 4x Samsung 512MB PC2-4200U
* CPUs
** [[AMD Duron 950 - D950AUT1B|https://www.cpu-world.com/CPUs/K7/AMD-Duron%20950%20-%20D950AUT1B.html]]
** [[AMD K&-2/500AFX|https://www.cpu-world.com/CPUs/K6-2/AMD-K6-2%20500%20-%20AMD-K6-2-500AFX.html]]
** [[AMD Athlon XP 2600+ - AXDA2600DKV3D|https://www.cpu-world.com/CPUs/K7/AMD-Athlon%20XP%202600%2B%20-%20AXDA2600DKV3D.html]]
** 2x [[AMD Athlon XP 2000+ - AX2000DMT3C|https://www.cpu-world.com/CPUs/K7/AMD-Athlon%20XP%202000%2B%20-%20AX2000DMT3C.html]]
** [[AMD Athlon XP 2000+ - AXDA2000DUT3C|https://www.cpu-world.com/CPUs/K7/AMD-Athlon%20XP%202000+%20-%20AXDA2000DUT3C.html]]
** [[AMD Athlon XP 1800+ - AXDA1800DUT3C|https://www.cpu-world.com/CPUs/K7/AMD-Athlon%20XP%201800+%20-%20AXDA1800DUT3C.html]]
** 2x [[AMD Sempron 2600+ - SDA2600DUT3D|https://www.cpu-world.com/CPUs/K7/AMD-Sempron%202600+%20-%20SDA2600DUT3D%20(SDA2600BOX).html]]
** [[AMD Duron 1800 - DHD1800DLV1C|https://www.cpu-world.com/CPUs/K7/AMD-Duron%201800%20-%20DHD1800DLV1C.html]]
** [[AMD Athlon XP 2200+ - AXDA2200DUV3C|https://www.cpu-world.com/CPUs/K7/AMD-Athlon%20XP%202200+%20-%20AXDA2200DUV3C.html]]
** [[SL6C7 (Intel Celeron 1.3 GHz)|https://www.cpu-world.com/sspec/SL/SL6C7.html]]
** [[SL5ZF (Intel Celeron 1000A)|https://www.cpu-world.com/sspec/SL/SL5ZF.html]]
** [[AMD Athlon 64 X2 4800+ - ADO4800IAA5DD|https://www.cpu-world.com/CPUs/K8/AMD-Athlon%2064%20X2%204800+%20-%20ADO4800IAA5DD%20(ADO4800DDBOX).html]]
** [[AMD Athlon 64 3500+ - ADA3500IAA4CW|https://www.cpu-world.com/CPUs/K8/AMD-Athlon%2064%203500+%20-%20ADA3500IAA4CW%20(ADA3500CWBOX).html]]
** [[AMD Sempron 64 2600+ - SDA2600AIO2BX|https://www.cpu-world.com/CPUs/K8/AMD-Sempron%2064%202600+%20-%20SDA2600AIO2BX%20(SDA2600BXBOX).html]]
** 3x [[AMD Sempron 64 3000+ - SDA3000AIO2BX|https://www.cpu-world.com/CPUs/K8/AMD-Sempron%2064%203000+%20-%20SDA3000AIO2BX%20(SDA3000BXBOX).html]]
** [[AMD Sempron 64 3200+ - SDA3200IAA2CW|https://www.cpu-world.com/CPUs/K8/AMD-Sempron%2064%203200+%20-%20SDA3200IAA2CW%20(SDA3200CWBOX%20-%20SDA3200CWWOF).html]]
** 2x [[AMD Athlon 64 X2 5000+ - ADA5000IAA5CS|https://www.cpu-world.com/CPUs/K8/AMD-Athlon%2064%20X2%205000+%20-%20ADA5000IAA5CS%20(ADA5000CSBOX).html]] - 1x kaputte pins
** [[SL7E2 (Intel Pentium 4 2.8 GHz)|https://www.cpu-world.com/sspec/SL/SL7E2.html]]
** 2x [[SL6RZ (Intel Pentium 4 2.4 GHz)|https://www.cpu-world.com/sspec/SL/SL6RZ.html]]
** [[SL6DX (Intel Pentium 4 2.667 GHz)|https://www.cpu-world.com/sspec/SL/SL6DX.html]]
** [[SL6YL (Intel Xeon 2.8 GHz)|https://www.cpu-world.com/sspec/SL/SL6YL.html]]
** [[SL8HZ (Intel Pentium 4 531)|https://www.cpu-world.com/sspec/SL/SL8HZ.html]]
** 9x [[SL7Z9 (Intel Pentium 4 630)|https://www.cpu-world.com/sspec/SL/SL7Z9.html]]
** 4x [[SL8Q7 (Intel Pentium 4 630)|https://www.cpu-world.com/sspec/SL/SL8Q7.html]]
** [[SL9CB (Intel Pentium 4 531)|https://www.cpu-world.com/sspec/SL/SL9CB.html]]
** [[SL95W (Intel Pentium D 940)|https://www.cpu-world.com/sspec/SL/SL95W.html]]
** [[SLGTH (Intel Pentium E5700)|https://www.cpu-world.com/sspec/SL/SLGTH.html]]
* Motherboards
** ASRock B75 Pro3 (ATX, DDR3, LGA1155, SATA, PCIe)
** MSI K8T Neo-V (MS-7032) (ATX, Socket 754, DDR SDRAM, SATA, PCIe)
** Asus P5QL Pro (ATX, LGA775, DDR2, PCIe, Sata)
general information

* https://www.youtube.com/playlist?list=PLTZM4MrZKfW-ftqKGSbO-DwDiOGqNmq53

* http://www.nicolabortignon.com/the-operative-system-for-a-decarbonised-decentralised-digitised-energy-system/

* https://opensource.com/article/16/12/open-smart-grid-platform
* https://github.com/OpenEMS/openems
* https://www.zdnet.com/article/open-source-takes-on-managing-and-securing-the-electrical-grid/
* see also [[powerlogging / power meter / AC power analysis / energy monitor]]
* https://media.ccc.de/v/32c3-7323-wie_man_einen_blackout_verursacht
* https://www.hackster.io/mehrsun/smart-microgrid-monitoring-b80c58
* https://hackaday.com/2021/06/26/emulating-a-power-grid/
* https://www.lfenergy.org/projects/

stuff

* https://www.ti.com/applications/industrial/grid-infrastructure/overview.html
* https://en.wikipedia.org/wiki/SCADA
** https://de.wikipedia.org/wiki/Supervisory_Control_and_Data_Acquisition
* https://www.hackster.io/dougal/energy-storage-unit-582cff
* https://github.com/openeemeter/eemeter/
redox flow batterys are great for stationary energy storage because of their high volume/Wh (which means it takes up a lot of space) and relatively low cost/Wh (cheap).

organig flow batteries using for example lignin as electrolyte are very cheap and sustainable because lignin is basically a waste product of the paper industry.

and the electrolytes can be recycled, they are "cleaned" and get reused as electrolytes again.

* https://wiki.opensourceecology.de/Zn/O-Brennstoffzelle
** seems to be more like a redox-flow cell than a fuel cell, i migt be wrong tho
* https://de.wikipedia.org/wiki/Redox-Flow-Batterie
* https://en.wikipedia.org/wiki/Flow_battery

especially interresting is [[Lignin]] as anolyte (electrolyte for the anode)

* https://doi.org/10.1021/acssuschemeng.8b00221
* https://www.klarageist.com/ - custom loudspeakers and cargobikes with speaker systems
* http://www.cathodecorner.com/bikeboombox/index.html
* http://www.cathodecorner.com/loudbike/index.html
* https://www.flickr.com/photos/coconino/1428758479/in/photostream/
* https://www.flickr.com/groups/503215@N24/
* https://www.ponoko.com/blog/how-to-make/diy-bike-beats/
** https://twitter.com/OriginCycling/status/1458831635034615814
** https://www.youtube.com/watch?v=GsoL7NBScNY
** [[Future Shock Bike Crew: 1,500 pounds of music|https://www.youtube.com/watch?v=T_pa1T4OMiY]]
* [[The worlds loudest bike|https://www.youtube.com/watch?v=ksVt1MjHm_E]]
* https://www.flickr.com/photos/mediaimran/3537783298/in/photostream/
** https://www.flickr.com/photos/mediaimran/3537777812/in/photostream/
** https://www.flickr.com/photos/mediaimran/3537771322/in/photostream/
* https://www.flickr.com/search/?text=bike%20sound%20system
* https://www.frohfroh.de/6128/mobile-rave
** https://www.centralstation-darmstadt.de/event/6019001/swing-ride-darmstaedter-fahrradtour-mit-tanzeinlagen/
** https://eurobean-festival.org/de/line-up-buehne-und-leinwand-2019.html
* https://pixel.tchncs.de/dillkuh

parts

* used [[speakers]] from a cheap stereo (mine have 6Ohm 80W each)
* [[cheap "chinese" amplifier boards]] (i got a 100W one, it's close to the speaker powerrating)
* maybe some speaker cable (the speakers allready had some)
* cardboard box (fitting the amplifier and battery)
* laptop battery from a broken or old used laptop (often 11.1V)
* metal angle plates to bend to hooks and screw to the speakers (like in [[diy bicycle bag (fahrradtasche)]])
* maybe straps, bungee straps or similar to secure the speakers a bit more
* velcro fasteners to secure the cables
* 

additions/modifications i want to make:

* step-up converter so get closer to the full power of amplifier/speakers
* a better box for putting the stuff in, maybe a plastic lunchbox (better than cardboard)
* banana plugs so the speakers can be disconnected from the amplifier (needs nicer box)
* some kind of handles or other ease-of-transportation or stuff for better securing it to the bike
* https://de.wikipedia.org/wiki/Spaceframe
* https://en.wikipedia.org/wiki/Space_frame
* https://en.wikipedia.org/wiki/Truss
* https://de.wikipedia.org/wiki/Fachwerk
* https://de.wikipedia.org/wiki/Traverse_(Veranstaltungstechnik)
* https://en.wikipedia.org/wiki/Civil_engineering

https://wiki.freecadweb.org/FEM_Tutorial_Python

Youtube:

* https://www.youtube.com/watch?v=gJIChIs4g6A
* https://www.youtube.com/watch?v=X_RrKBXV-Ww
* https://www.youtube.com/watch?v=BHZALtqAjeM
* [[YT: Understanding and Analysing Trusses|https://www.youtube.com/watch?v=Hn_iozUo9m4]]
* [[Analysis Of Trusses And Frames - Applications Of Trusses - Engineering Mechanics|https://www.youtube.com/watch?v=eRngUmq94iA]]
* [[Introduction to Frames and Types of Frames -- Structural Analysis - I -- Civil Engineering|https://www.youtube.com/watch?v=vdI3ogbOBuk]]
* [[What are Trusses And Frames I - Applications of Trusses - Method of Joints - Solved Problems|https://www.youtube.com/watch?v=PoV96VJwdL8]]
* [[Design Behind the Bike|https://www.youtube.com/playlist?list=PLhQpDGfX5e7CkFmNjuwdPjNAmZm6xyCMi]]
** [[Frame Design - Design Behind the Bike (5/5)|https://www.youtube.com/watch?v=3uXtiK5nDvo]]
* [[How to solve frame and machine problems (statics)|https://www.youtube.com/watch?v=jtdGj-Jq3Yk]]
* [[Understanding Stresses in Beams|https://www.youtube.com/watch?v=f08Y39UiC-o]]
*[[Lateral Force-Resisting Systems - braced frame, shear wall, and moment-resisting frame|https://www.youtube.com/watch?v=kaKUHU3YYzY]]
* [[Difference between Truss Structure & Frame Structure|https://www.youtube.com/watch?v=rIlEH0bYkgA]]
* [[ASK THE ENGINEER - WHAT IS A MOMENT CONNECTION?|https://www.youtube.com/watch?v=06rfB6BBlCs]]
* [[Understanding Shear Force and Bending Moment Diagrams|https://www.youtube.com/watch?v=C-FEVzI8oe8]]
* [[Chassis frame & Construction. Engineer's Academy|https://www.youtube.com/watch?v=PjenO8nihaM]]
* [[Crash Course Engineering|https://www.youtube.com/watch?v=ToC8rFFp88Y&list=PLH2l6uzC4UEVUmJdTMStYXad_sI73_T0x]]
* [[Mechanical Engineering|https://www.youtube.com/watch?v=qbv2rOEMyiA&list=PLuUdFsbOK_8pIX0p_roLRdfvY7Ax8u-jE]]
* [[Technische Mechanik 1|https://www.youtube.com/watch?v=CLBAG4RzNeM&list=PLTrE8KgxfrZd2vHPaBAimaeTQVFmL0uUo]]
* [[Fachwerke und statisches Gleichgewicht|https://www.youtube.com/watch?v=RaNgtp4qFoA&list=PLTrE8KgxfrZdG8S-CamORRyT-q6AGViH3]]
** [[Stabkräfte bestimmen - Fachwerke und statisches Gleichgewicht 4|https://www.youtube.com/watch?v=Ez7y8BoUXfQ]]
* https://hackaday.com/2018/06/20/analog-discovery-2-as-a-vector-network-analyzer/
* [[Digilent Analog Discovery 2]]
gas discharge tubes are pretty inefficient, converting a projector to led might make it more efficient with more output.

problems: LEDs don't have a nice spectrum, most of the light is in the blue part of the spectrum and little in the red part
so a combination of LEDs has to be tuned to get a good output.

a spectroscope is needed to characterise the output of the original lamp, of the whole projector and of the LEDs... see [[DIY/open hardware light spectroscope / spectrometer]]

* https://www.eevblog.com/forum/projects/replacing-a-projector-bulb-with-leds/
* https://www.instructables.com/LED-Projector-Lamp-v20-in-progress/
* https://www.instructables.com/Convert-A-Projector-To-An-LED-Light-Source/
* [[Inside a cheap LED projector.|https://www.youtube.com/watch?v=itrc38JgvRk]]
* https://www.youtube.com/watch?v=dxbDYQZm68o
* https://de.wikipedia.org/wiki/Farbwiedergabeindex
* example: [[MACHINING The HARDEST METAL On EARTH|https://youtu.be/976WchjGzyU]]
* [[Drill through anything (conductive) with Electrical Discharge Machining|https://www.youtube.com/watch?v=rpHYBz7ToII]]
* [[Diy EDM success!|https://www.youtube.com/watch?v=kRc1NFO8uwo]]
* [[How We Made A Wire EDM Machine At Home|https://www.youtube.com/watch?v=2ewSbI52ICc]]

open source edm

* https://github.com/Rack-Robotics - https://github.com/orgs/Rack-Robotics/repositories
** https://github.com/Rack-Robotics/Powercore-V1-Hardware
** https://github.com/Rack-Robotics/Powercore-V1-Manual
** https://www.rackrobo.io/
** https://www.kickstarter.com/projects/rackrobotics/powercore-cut-through-solid-metal-with-edm

stuff

* https://hackaday.com/blog/?s=edm
* https://hackaday.io/project/181551-sinker-edm-machine
* https://hackaday.com/2023/03/07/powercore-aims-to-bring-the-power-of-edm-to-any-3d-printer/#more-579539
* https://hackaday.com/2022/07/20/cut-just-about-anything-with-this-combination-lathe-and-wire-edm/
* https://de.wikipedia.org/wiki/Funkenerodieren
* https://en.wikipedia.org/wiki/Electrical_discharge_machining
* https://www.youtube.com/results?search_query=diy+edm
* https://hackaday.com/tag/electrical-discharge-machining/
* https://hackaday.com/2023/07/05/exploring-a-new-frontier-desktop-edm-is-coming/
* https://hackaday.com/tag/edm/
* https://www.youtube.com/watch?v=MZm-mvxa2qo
* https://hackaday.com/2021/04/30/homemade-edm-machine-moves-from-prototype-to-production/
* https://wiki.opensourceecology.org/wiki/Open_Source_EDM
** https://wiki.opensourceecology.org/wiki/EDM
** https://wiki.opensourceecology.org/wiki/Open_Source_3_Axis_Wire-Cut_EDM_Machine
** https://wiki.opensourceecology.org/wiki/Open_Source_EDM_Drill
** https://wiki.opensourceecology.org/wiki/Open_Source_Die-Sink_EDM_Machine
yes
{
    "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-2020, 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": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\"><path 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-.37.58-.936.785-1.54 1.01l-.82.11zm-40.097-8.85l.553.14c.694-.27 2.09.15 2.83.353-1.363-1.31-3.417-3.24-4.897-4.46-.485-1.47-.278-2.96-.174-4.46l.02-.123c-.582 1.205-1.322 2.376-1.72 3.645-.465 1.71 2.07 3.557 3.052 4.615l.336.3z\" fill-rule=\"evenodd\"/></svg>"
        },
        "$:/core/images/add-comment": {
            "title": "$:/core/images/add-comment",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-add-comment tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M56 56H36a8 8 0 100 16h20v20a8 8 0 1016 0V72h20a8 8 0 100-16H72V36a8 8 0 10-16 0v20zm-12.595 58.362c-6.683 7.659-20.297 12.903-36.006 12.903-2.196 0-4.35-.102-6.451-.3 9.652-3.836 17.356-12.24 21.01-22.874C8.516 94.28 0 79.734 0 63.5 0 33.953 28.206 10 63 10s63 23.953 63 53.5S97.794 117 63 117c-6.841 0-13.428-.926-19.595-2.638z\"/></svg>"
        },
        "$:/core/images/advanced-search-button": {
            "title": "$:/core/images/advanced-search-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-advanced-search-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M74.565 87.985A47.776 47.776 0 0148 96C21.49 96 0 74.51 0 48S21.49 0 48 0s48 21.49 48 48c0 9.854-2.97 19.015-8.062 26.636l34.347 34.347a9.443 9.443 0 010 13.36 9.446 9.446 0 01-13.36 0l-34.36-34.358zM48 80c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32z\"/><circle cx=\"48\" cy=\"48\" r=\"8\"/><circle cx=\"28\" cy=\"48\" r=\"8\"/><circle cx=\"68\" cy=\"48\" r=\"8\"/></g></svg>"
        },
        "$:/core/images/auto-height": {
            "title": "$:/core/images/auto-height",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-auto-height tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M67.987 114.356l-.029-14.477a4 4 0 00-2.067-3.494l-15.966-8.813-1.933 7.502H79.9c4.222 0 5.564-5.693 1.786-7.58L49.797 71.572 48.01 79.15h31.982c4.217 0 5.564-5.682 1.795-7.575L49.805 55.517l-1.795 7.575h31.982c4.212 0 5.563-5.67 1.805-7.57l-16.034-8.105 2.195 3.57V35.614l9.214 9.213a4 4 0 105.656-5.656l-16-16a4 4 0 00-5.656 0l-16 16a4 4 0 105.656 5.656l9.13-9.13v15.288a4 4 0 002.195 3.57l16.035 8.106 1.804-7.57H48.01c-4.217 0-5.564 5.682-1.795 7.574l31.982 16.059 1.795-7.575H48.01c-4.222 0-5.564 5.693-1.787 7.579l31.89 15.923 1.787-7.578H47.992c-4.133 0-5.552 5.504-1.933 7.501l15.966 8.813-2.067-3.494.029 14.436-9.159-9.158a4 4 0 00-5.656 5.656l16 16a4 4 0 005.656 0l16-16a4 4 0 10-5.656-5.656l-9.185 9.184zM16 20h96a4 4 0 100-8H16a4 4 0 100 8z\"/></svg>"
        },
        "$:/core/images/blank": {
            "title": "$:/core/images/blank",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-blank tc-image-button\" viewBox=\"0 0 128 128\"/>"
        },
        "$:/core/images/bold": {
            "title": "$:/core/images/bold",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-bold tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M41.146 51.81V21.87h26.353c2.51 0 4.93.21 7.26.628 2.33.418 4.392 1.165 6.185 2.24 1.793 1.076 3.227 2.57 4.302 4.482 1.076 1.913 1.614 4.363 1.614 7.35 0 5.379-1.613 9.263-4.84 11.653-3.227 2.39-7.35 3.586-12.37 3.586H41.146zM13 0v128h62.028a65.45 65.45 0 0016.762-2.151c5.438-1.434 10.278-3.645 14.52-6.633 4.244-2.988 7.62-6.842 10.13-11.563 2.51-4.721 3.764-10.308 3.764-16.762 0-8.008-1.942-14.85-5.826-20.527-3.884-5.677-9.77-9.65-17.658-11.921 5.737-2.75 10.069-6.275 12.997-10.577 2.928-4.303 4.392-9.681 4.392-16.135 0-5.976-.986-10.995-2.958-15.059-1.972-4.063-4.75-7.32-8.336-9.77-3.585-2.45-7.888-4.213-12.907-5.289C84.888.538 79.33 0 73.235 0H13zm28.146 106.129V70.992H71.8c6.095 0 10.995 1.404 14.7 4.212 3.705 2.81 5.558 7.5 5.558 14.073 0 3.347-.568 6.096-1.703 8.247-1.136 2.151-2.66 3.854-4.572 5.11-1.912 1.254-4.123 2.15-6.633 2.688-2.51.538-5.139.807-7.888.807H41.146z\"/></svg>"
        },
        "$:/core/images/cancel-button": {
            "title": "$:/core/images/cancel-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-cancel-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M64 76.314l-16.97 16.97a7.999 7.999 0 01-11.314 0c-3.118-3.118-3.124-8.19 0-11.313L52.686 65l-16.97-16.97a7.999 7.999 0 010-11.314c3.118-3.118 8.19-3.124 11.313 0L64 53.686l16.97-16.97a7.999 7.999 0 0111.314 0c3.118 3.118 3.124 8.19 0 11.313L75.314 65l16.97 16.97a7.999 7.999 0 010 11.314c-3.118 3.118-8.19 3.124-11.313 0L64 76.314zM64 129c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 1 0 29.654 0 65c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 17 64 17 16 38.49 16 65s21.49 48 48 48z\"/></svg>"
        },
        "$:/core/images/chevron-down": {
            "title": "$:/core/images/chevron-down",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-chevron-down tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M64.053 85.456a7.889 7.889 0 01-5.6-2.316L2.473 27.16a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0L64.05 66.344l50.382-50.382a7.92 7.92 0 0111.195 0c3.085 3.086 3.092 8.105 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.317z\"/><path d=\"M64.053 124.069a7.889 7.889 0 01-5.6-2.316l-55.98-55.98a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0l50.382 50.382 50.382-50.382a7.92 7.92 0 0111.195 0c3.085 3.086 3.092 8.104 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.316z\"/></g></svg>"
        },
        "$:/core/images/chevron-left": {
            "title": "$:/core/images/chevron-left",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-chevron-left tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M47.544 64.053c0-2.027.77-4.054 2.316-5.6l55.98-55.98a7.92 7.92 0 0111.196 0c3.085 3.086 3.092 8.105 0 11.196L66.656 64.05l50.382 50.382a7.92 7.92 0 010 11.195c-3.086 3.085-8.105 3.092-11.196 0l-55.98-55.98a7.892 7.892 0 01-2.317-5.595z\"/><path d=\"M8.931 64.053c0-2.027.77-4.054 2.316-5.6l55.98-55.98a7.92 7.92 0 0111.196 0c3.085 3.086 3.092 8.105 0 11.196L28.041 64.05l50.382 50.382a7.92 7.92 0 010 11.195c-3.086 3.085-8.104 3.092-11.196 0l-55.98-55.98a7.892 7.892 0 01-2.316-5.595z\"/></g></svg>"
        },
        "$:/core/images/chevron-right": {
            "title": "$:/core/images/chevron-right",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-chevron-right tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M83.456 63.947c0 2.027-.77 4.054-2.316 5.6l-55.98 55.98a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196L64.344 63.95 13.963 13.567a7.92 7.92 0 010-11.195c3.086-3.085 8.105-3.092 11.196 0l55.98 55.98a7.892 7.892 0 012.317 5.595z\"/><path d=\"M122.069 63.947c0 2.027-.77 4.054-2.316 5.6l-55.98 55.98a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196l50.382-50.382-50.382-50.382a7.92 7.92 0 010-11.195c3.086-3.085 8.104-3.092 11.196 0l55.98 55.98a7.892 7.892 0 012.316 5.595z\"/></g></svg>"
        },
        "$:/core/images/chevron-up": {
            "title": "$:/core/images/chevron-up",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-chevron-up tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M63.947 44.544c2.027 0 4.054.77 5.6 2.316l55.98 55.98a7.92 7.92 0 010 11.196c-3.086 3.085-8.105 3.092-11.196 0L63.95 63.656l-50.382 50.382a7.92 7.92 0 01-11.195 0c-3.085-3.086-3.092-8.105 0-11.196l55.98-55.98a7.892 7.892 0 015.595-2.317z\"/><path d=\"M63.947 5.931c2.027 0 4.054.77 5.6 2.316l55.98 55.98a7.92 7.92 0 010 11.196c-3.086 3.085-8.105 3.092-11.196 0L63.95 25.041 13.567 75.423a7.92 7.92 0 01-11.195 0c-3.085-3.086-3.092-8.104 0-11.196l55.98-55.98a7.892 7.892 0 015.595-2.316z\"/></g></svg>"
        },
        "$:/core/images/clone-button": {
            "title": "$:/core/images/clone-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-clone-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M32.265 96v24.002A7.996 7.996 0 0040.263 128h79.74a7.996 7.996 0 007.997-7.998v-79.74a7.996 7.996 0 00-7.998-7.997H96V48h12.859a2.99 2.99 0 012.994 2.994v57.865a2.99 2.99 0 01-2.994 2.994H50.994A2.99 2.99 0 0148 108.859V96H32.265z\"/><path d=\"M40 56h-7.993C27.588 56 24 52.418 24 48c0-4.41 3.585-8 8.007-8H40v-7.993C40 27.588 43.582 24 48 24c4.41 0 8 3.585 8 8.007V40h7.993C68.412 40 72 43.582 72 48c0 4.41-3.585 8-8.007 8H56v7.993C56 68.412 52.418 72 48 72c-4.41 0-8-3.585-8-8.007V56zM8 0C3.58 0 0 3.588 0 8v80c0 4.419 3.588 8 8 8h80c4.419 0 8-3.588 8-8V8c0-4.419-3.588-8-8-8H8zM19 16A2.997 2.997 0 0016 19.001v57.998A2.997 2.997 0 0019.001 80h57.998A2.997 2.997 0 0080 76.999V19.001A2.997 2.997 0 0076.999 16H19.001z\"/></g></svg>"
        },
        "$:/core/images/close-all-button": {
            "title": "$:/core/images/close-all-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-close-all-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M28 111.314l-14.144 14.143a8 8 0 01-11.313-11.313L16.686 100 2.543 85.856a8 8 0 0111.313-11.313L28 88.686l14.144-14.143a8 8 0 0111.313 11.313L39.314 100l14.143 14.144a8 8 0 01-11.313 11.313L28 111.314zM28 39.314L13.856 53.457A8 8 0 012.543 42.144L16.686 28 2.543 13.856A8 8 0 0113.856 2.543L28 16.686 42.144 2.543a8 8 0 0111.313 11.313L39.314 28l14.143 14.144a8 8 0 01-11.313 11.313L28 39.314zM100 39.314L85.856 53.457a8 8 0 01-11.313-11.313L88.686 28 74.543 13.856A8 8 0 0185.856 2.543L100 16.686l14.144-14.143a8 8 0 0111.313 11.313L111.314 28l14.143 14.144a8 8 0 01-11.313 11.313L100 39.314zM100 111.314l-14.144 14.143a8 8 0 01-11.313-11.313L88.686 100 74.543 85.856a8 8 0 0111.313-11.313L100 88.686l14.144-14.143a8 8 0 0111.313 11.313L111.314 100l14.143 14.144a8 8 0 01-11.313 11.313L100 111.314z\"/></g></svg>"
        },
        "$:/core/images/close-button": {
            "title": "$:/core/images/close-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-close-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M65.086 75.41l-50.113 50.113c-3.121 3.121-8.192 3.126-11.316.002-3.118-3.118-3.123-8.19.002-11.316l50.114-50.114L3.659 13.982C.538 10.86.533 5.79 3.657 2.666c3.118-3.118 8.19-3.123 11.316.002l50.113 50.114L115.2 2.668c3.121-3.121 8.192-3.126 11.316-.002 3.118 3.118 3.123 8.19-.002 11.316L76.4 64.095l50.114 50.114c3.121 3.121 3.126 8.192.002 11.316-3.118 3.118-8.19 3.123-11.316-.002L65.086 75.409z\"/></svg>"
        },
        "$:/core/images/close-others-button": {
            "title": "$:/core/images/close-others-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-close-others-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M64 128c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 16 64 16 16 37.49 16 64s21.49 48 48 48zm0-16c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32zm0-16c8.837 0 16-7.163 16-16s-7.163-16-16-16-16 7.163-16 16 7.163 16 16 16z\"/></svg>"
        },
        "$:/core/images/copy-clipboard": {
            "title": "$:/core/images/copy-clipboard",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-copy-clipboard tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"33\" height=\"8\" x=\"40\" y=\"40\" rx=\"4\"/><rect width=\"17\" height=\"8\" x=\"40\" y=\"82\" rx=\"4\"/><rect width=\"17\" height=\"8\" x=\"40\" y=\"54\" rx=\"4\"/><rect width=\"33\" height=\"8\" x=\"40\" y=\"96\" rx=\"4\"/><rect width=\"12\" height=\"8\" x=\"40\" y=\"68\" rx=\"4\"/><path d=\"M40 16H24c-4.419 0-8 3.59-8 8a8.031 8.031 0 000 .01v95.98a8.03 8.03 0 000 .01c0 4.41 3.581 8 8 8h80a7.975 7.975 0 005.652-2.34 7.958 7.958 0 002.348-5.652v-16.016c0-4.414-3.582-7.992-8-7.992-4.41 0-8 3.578-8 7.992V112H32V32h64v8.008C96 44.422 99.582 48 104 48c4.41 0 8-3.578 8-7.992V23.992a7.963 7.963 0 00-2.343-5.651A7.995 7.995 0 00104.001 16H88c0-4.41-3.585-8-8.007-8H48.007C43.588 8 40 11.582 40 16zm4-1.004A4.001 4.001 0 0148 11h32c2.21 0 4 1.797 4 3.996v4.008A4.001 4.001 0 0180 23H48c-2.21 0-4-1.797-4-3.996v-4.008z\"/><rect width=\"66\" height=\"16\" x=\"62\" y=\"64\" rx=\"8\"/><path d=\"M84.657 82.343l-16-16v11.314l16-16a8 8 0 10-11.314-11.314l-16 16a8 8 0 000 11.314l16 16a8 8 0 1011.314-11.314z\"/></g></svg>"
        },
        "$:/core/images/delete-button": {
            "title": "$:/core/images/delete-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-delete-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\" transform=\"translate(12)\"><rect width=\"105\" height=\"16\" y=\"11\" rx=\"8\"/><rect width=\"48\" height=\"16\" x=\"28\" rx=\"8\"/><rect width=\"16\" height=\"112\" x=\"8\" y=\"16\" rx=\"8\"/><rect width=\"88\" height=\"16\" x=\"8\" y=\"112\" rx=\"8\"/><rect width=\"16\" height=\"112\" x=\"80\" y=\"16\" rx=\"8\"/><rect width=\"16\" height=\"112\" x=\"56\" y=\"16\" rx=\"8\"/><rect width=\"16\" height=\"112\" x=\"32\" y=\"16\" rx=\"8\"/></g></svg>"
        },
        "$:/core/images/done-button": {
            "title": "$:/core/images/done-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-done-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M42.26 111.032c-2.051.001-4.103-.78-5.668-2.345L2.662 74.758a8 8 0 01-.005-11.32c3.118-3.117 8.192-3.12 11.32.007l28.278 28.278 72.124-72.124a8.002 8.002 0 0111.314-.001c3.118 3.118 3.124 8.19 0 11.315l-77.78 77.78a7.978 7.978 0 01-5.658 2.343z\"/></svg>"
        },
        "$:/core/images/down-arrow": {
            "title": "$:/core/images/down-arrow",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-down-arrow tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M64.177 100.069a7.889 7.889 0 01-5.6-2.316l-55.98-55.98a7.92 7.92 0 010-11.196c3.086-3.085 8.105-3.092 11.196 0l50.382 50.382 50.382-50.382a7.92 7.92 0 0111.195 0c3.086 3.086 3.092 8.104 0 11.196l-55.98 55.98a7.892 7.892 0 01-5.595 2.316z\"/></svg>"
        },
        "$:/core/images/download-button": {
            "title": "$:/core/images/download-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-download-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M64 128c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 16 64 16 16 37.49 16 64s21.49 48 48 48z\" class=\"tc-image-download-button-ring\"/><path d=\"M34.35 66.43l26.892 27.205a4.57 4.57 0 006.516 0L94.65 66.43a4.7 4.7 0 000-6.593 4.581 4.581 0 00-3.258-1.365h-8.46c-2.545 0-4.608-2.087-4.608-4.661v-15.15c0-2.575-2.063-4.662-4.608-4.662H55.284c-2.545 0-4.608 2.087-4.608 4.662v15.15c0 2.574-2.063 4.661-4.608 4.661h-8.46c-2.545 0-4.608 2.087-4.608 4.662a4.69 4.69 0 001.35 3.296z\"/></g></svg>"
        },
        "$:/core/images/edit-button": {
            "title": "$:/core/images/edit-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-edit-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M95.627 10.059l-5.656 5.657 11.313 11.313 5.657-5.656-11.314-11.314zm5.657-5.657l1.966-1.966c3.123-3.122 8.194-3.129 11.319-.005 3.117 3.118 3.122 8.192-.005 11.32l-1.966 1.965-11.314-11.314zm-16.97 16.97l-60.25 60.25a8.12 8.12 0 00-.322.342c-.1.087-.198.179-.295.275-5.735 5.735-10.702 22.016-10.702 22.016s16.405-5.09 22.016-10.702c.095-.096.186-.193.272-.292a8.12 8.12 0 00.345-.325l60.25-60.25-11.314-11.313zM35.171 124.19c6.788-.577 13.898-2.272 23.689-5.348 1.825-.573 3.57-1.136 6.336-2.04 16-5.226 21.877-6.807 28.745-7.146 8.358-.413 13.854 2.13 17.58 8.699a4 4 0 006.959-3.946c-5.334-9.406-13.745-13.296-24.933-12.744-7.875.39-14.057 2.052-30.835 7.533-2.739.894-4.46 1.45-6.25 2.012-19.46 6.112-30.77 7.072-39.597 1.747a4 4 0 10-4.132 6.85c6.333 3.82 13.754 5.12 22.438 4.383z\"/></g></svg>"
        },
        "$:/core/images/erase": {
            "title": "$:/core/images/erase",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-erase tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M60.087 127.996l63.015-63.015c6.535-6.535 6.528-17.115-.003-23.646L99.466 17.702c-6.539-6.538-17.117-6.532-23.646-.003L4.898 88.62c-6.535 6.534-6.528 17.115.003 23.646l15.73 15.73h39.456zm-34.95-7.313l-14.324-14.325c-3.267-3.268-3.268-8.564-.008-11.824L46.269 59.07l35.462 35.462-26.15 26.15H25.137z\"/></svg>"
        },
        "$:/core/images/excise": {
            "title": "$:/core/images/excise",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-excise tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M56 107.314l-2.343 2.343a8 8 0 11-11.314-11.314l16-16a8 8 0 0111.314 0l16 16a8 8 0 11-11.314 11.314L72 107.314v14.284c0 3.536-3.582 6.402-8 6.402s-8-2.866-8-6.402v-14.284zM0 40.007C0 35.585 3.59 32 8 32c4.418 0 8 3.588 8 8.007v31.986C16 76.415 12.41 80 8 80c-4.418 0-8-3.588-8-8.007V40.007zm32 0C32 35.585 35.59 32 40 32c4.418 0 8 3.588 8 8.007v31.986C48 76.415 44.41 80 40 80c-4.418 0-8-3.588-8-8.007V40.007zm48 0C80 35.585 83.59 32 88 32c4.418 0 8 3.588 8 8.007v31.986C96 76.415 92.41 80 88 80c-4.418 0-8-3.588-8-8.007V40.007zm-24-32C56 3.585 59.59 0 64 0c4.418 0 8 3.588 8 8.007v31.986C72 44.415 68.41 48 64 48c-4.418 0-8-3.588-8-8.007V8.007zm56 32c0-4.422 3.59-8.007 8-8.007 4.418 0 8 3.588 8 8.007v31.986c0 4.422-3.59 8.007-8 8.007-4.418 0-8-3.588-8-8.007V40.007z\"/></svg>"
        },
        "$:/core/images/export-button": {
            "title": "$:/core/images/export-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-export-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M8.003 128H119.993a7.984 7.984 0 005.664-2.349v.007A7.975 7.975 0 00128 120V56c0-4.418-3.59-8-8-8-4.418 0-8 3.58-8 8v56H16V56c0-4.418-3.59-8-8-8-4.418 0-8 3.58-8 8v64c0 4.418 3.59 8 8 8h.003zm48.62-100.689l-8.965 8.966c-3.125 3.125-8.195 3.13-11.319.005-3.118-3.118-3.122-8.192.005-11.319L58.962 2.346A7.986 7.986 0 0164.625 0l-.006.002c2.05-.001 4.102.78 5.666 2.344l22.618 22.617c3.124 3.125 3.129 8.195.005 11.319-3.118 3.118-8.192 3.122-11.319-.005l-8.965-8.966v61.256c0 4.411-3.582 8-8 8-4.41 0-8-3.582-8-8V27.311z\"/></svg>"
        },
        "$:/core/images/file": {
            "title": "$:/core/images/file",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-file tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M111.968 30.5H112V120a8 8 0 01-8 8H24a8 8 0 01-8-8V8a8 8 0 018-8h57v.02a7.978 7.978 0 015.998 2.337l22.627 22.627a7.975 7.975 0 012.343 5.516zM81 8H24v112h80V30.5H89c-4.418 0-8-3.578-8-8V8z\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"36\" rx=\"4\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"52\" rx=\"4\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"68\" rx=\"4\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"84\" rx=\"4\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"100\" rx=\"4\"/><rect width=\"40\" height=\"8\" x=\"32\" y=\"20\" rx=\"4\"/></svg>"
        },
        "$:/core/images/fixed-height": {
            "title": "$:/core/images/fixed-height",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-fixed-height tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M60 35.657l-9.172 9.171a4 4 0 11-5.656-5.656l16-16a4 4 0 015.656 0l16 16a4 4 0 01-5.656 5.656L68 35.657v57.686l9.172-9.171a4 4 0 115.656 5.656l-16 16a4 4 0 01-5.656 0l-16-16a4 4 0 115.656-5.656L60 93.343V35.657zM16 116h96a4 4 0 100-8H16a4 4 0 100 8zm0-96h96a4 4 0 100-8H16a4 4 0 100 8z\"/></svg>"
        },
        "$:/core/images/fold-all-button": {
            "title": "$:/core/images/fold-all-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-fold-all tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"128\" height=\"16\" rx=\"8\"/><rect width=\"128\" height=\"16\" y=\"64\" rx=\"8\"/><path d=\"M64.03 20.004c-2.05 0-4.102.78-5.667 2.344L35.746 44.966c-3.125 3.124-3.13 8.194-.005 11.318 3.118 3.118 8.192 3.122 11.319-.005l16.965-16.965 16.966 16.965c3.124 3.125 8.194 3.13 11.318.005 3.118-3.118 3.122-8.191-.005-11.318L69.687 22.348a7.986 7.986 0 00-5.663-2.346zM64.03 85.002c-2.05-.001-4.102.78-5.667 2.344l-22.617 22.617c-3.125 3.125-3.13 8.195-.005 11.319 3.118 3.118 8.192 3.122 11.319-.005l16.965-16.966 16.966 16.966c3.124 3.125 8.194 3.13 11.318.005 3.118-3.118 3.122-8.192-.005-11.319L69.687 87.346A7.986 7.986 0 0064.024 85z\"/></g></svg>"
        },
        "$:/core/images/fold-button": {
            "title": "$:/core/images/fold-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-fold tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"128\" height=\"16\" rx=\"8\"/><path d=\"M64.03 25.004c-2.05 0-4.102.78-5.667 2.344L35.746 49.966c-3.125 3.124-3.13 8.194-.005 11.318 3.118 3.118 8.192 3.122 11.319-.005l16.965-16.965 16.966 16.965c3.124 3.125 8.194 3.13 11.318.005 3.118-3.118 3.122-8.191-.005-11.318L69.687 27.348a7.986 7.986 0 00-5.663-2.346zM64.005 67.379c-2.05 0-4.102.78-5.666 2.344L35.722 92.34c-3.125 3.125-3.13 8.195-.006 11.32 3.118 3.117 8.192 3.121 11.32-.006L64 86.69l16.965 16.965c3.125 3.125 8.195 3.13 11.319.005 3.118-3.118 3.122-8.192-.005-11.319L69.663 69.723A7.986 7.986 0 0064 67.377z\"/></g></svg>"
        },
        "$:/core/images/fold-others-button": {
            "title": "$:/core/images/fold-others-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-fold-others tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"128\" height=\"16\" y=\"56.031\" rx=\"8\"/><path d=\"M86.632 79.976c-2.05 0-4.102.78-5.666 2.345L64 99.286 47.034 82.321a7.986 7.986 0 00-5.662-2.346l.005.001c-2.05 0-4.102.78-5.666 2.345l-22.618 22.617c-3.124 3.125-3.129 8.195-.005 11.319 3.118 3.118 8.192 3.122 11.319-.005l16.966-16.966 16.965 16.966a7.986 7.986 0 005.663 2.346l-.005-.002c2.05 0 4.102-.78 5.666-2.344l16.965-16.966 16.966 16.966c3.125 3.124 8.194 3.129 11.319.005 3.118-3.118 3.122-8.192-.005-11.319L92.289 82.321a7.986 7.986 0 00-5.663-2.346zM86.7 48.024c-2.05 0-4.102-.78-5.666-2.345L64.07 28.714 47.103 45.679a7.986 7.986 0 01-5.663 2.346l.005-.001c-2.05 0-4.101-.78-5.666-2.345L13.162 23.062c-3.125-3.125-3.13-8.195-.005-11.319 3.118-3.118 8.192-3.122 11.319.005L41.44 28.714l16.966-16.966a7.986 7.986 0 015.662-2.346l-.005.002c2.05 0 4.102.78 5.666 2.344l16.966 16.966 16.966-16.966c3.124-3.124 8.194-3.129 11.318-.005 3.118 3.118 3.122 8.192-.005 11.319L92.358 45.679a7.986 7.986 0 01-5.663 2.346z\"/></g></svg>"
        },
        "$:/core/images/folder": {
            "title": "$:/core/images/folder",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-folder tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M55.694 128H8C3.58 128 0 124.414 0 119.996V48.004C0 43.584 3.584 40 7.999 40H16v-8c0-4.418 3.578-8 8-8h32a8 8 0 018 8v8h40.001c4.418 0 7.999 3.586 7.999 8.004V59.83l-8-.082v-7.749A4 4 0 0099.997 48H56V36c0-2.21-1.793-4-4.004-4H28.004A4 4 0 0024 36v12H12.003A4 4 0 008 52v64a4 4 0 004.003 4h46.76l-3.069 8z\"/><path d=\"M23.873 55.5h96.003c4.417 0 7.004 4.053 5.774 9.063l-13.344 54.374c-1.228 5.005-5.808 9.063-10.223 9.063H6.08c-4.417 0-7.003-4.053-5.774-9.063L13.65 64.563c1.228-5.005 5.808-9.063 10.223-9.063zm1.78 8.5h87.994c2.211 0 3.504 2.093 2.891 4.666l-11.12 46.668c-.614 2.577-2.902 4.666-5.115 4.666H12.31c-2.211 0-3.504-2.093-2.891-4.666l11.12-46.668C21.152 66.09 23.44 64 25.653 64z\"/></g></svg>"
        },
        "$:/core/images/full-screen-button": {
            "title": "$:/core/images/full-screen-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-full-screen-button tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M0 8a8 8 0 018-8h32a8 8 0 110 16H16v24a8 8 0 11-16 0V8zM128 120a8 8 0 01-8 8H88a8 8 0 110-16h24V88a8 8 0 1116 0v32zM8 128a8 8 0 01-8-8V88a8 8 0 1116 0v24h24a8 8 0 110 16H8zM120 0a8 8 0 018 8v32a8 8 0 11-16 0V16H88a8 8 0 110-16h32z\"/></svg>"
        },
        "$:/core/images/github": {
            "title": "$:/core/images/github",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-github tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M63.938 1.607c-35.336 0-63.994 28.69-63.994 64.084 0 28.312 18.336 52.329 43.768 60.802 3.202.59 4.37-1.388 4.37-3.088 0-1.518-.056-5.55-.087-10.897-17.802 3.871-21.558-8.591-21.558-8.591-2.911-7.404-7.108-9.375-7.108-9.375-5.81-3.973.44-3.895.44-3.895 6.424.453 9.803 6.606 9.803 6.606 5.709 9.791 14.981 6.963 18.627 5.322.582-4.138 2.236-6.963 4.063-8.564-14.211-1.617-29.153-7.117-29.153-31.672 0-6.995 2.495-12.718 6.589-17.195-.66-1.621-2.856-8.14.629-16.96 0 0 5.37-1.722 17.597 6.57 5.104-1.424 10.58-2.132 16.022-2.16 5.438.028 10.91.736 16.022 2.16 12.22-8.292 17.582-6.57 17.582-6.57 3.493 8.82 1.297 15.339.64 16.96 4.102 4.477 6.578 10.2 6.578 17.195 0 24.618-14.966 30.035-29.22 31.62 2.295 1.98 4.342 5.89 4.342 11.87 0 8.564-.079 15.476-.079 17.576 0 1.715 1.155 3.71 4.4 3.084 25.413-8.493 43.733-32.494 43.733-60.798 0-35.394-28.657-64.084-64.006-64.084\"/></svg>"
        },
        "$:/core/images/gitter": {
            "title": "$:/core/images/gitter",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-gitter tc-image-button\" viewBox=\"0 0 18 25\"><path d=\"M15 5h2v10h-2zM10 5h2v20h-2zM5 5h2v20H5zM0 0h2v15H0z\"/></svg>"
        },
        "$:/core/images/globe": {
            "title": "$:/core/images/globe",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-globe tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M72.811 37.128v2.554c0 2.196.978 6.881 0 8.832-1.466 2.928-4.65 3.54-6.394 5.867-1.182 1.577-4.618 10.601-3.69 12.92 3.969 9.922 11.534 3.187 17.962 9.293.864.821 2.887 2.273 3.296 3.296 3.29 8.223-7.576 15.009 3.757 26.3 1.245 1.24 3.813-3.817 4.079-4.614.852-2.563 6.725-5.45 9.088-7.053 2.02-1.37 4.873-2.667 6.328-4.745 2.27-3.244 1.48-7.514 3.098-10.745 2.139-4.274 3.828-9.635 5.998-13.966 3.898-7.781 4.721 2.093 5.067 2.439.358.357 1.011 0 1.517 0 .094 0 1.447.099 1.516 0 .65-.935-1.043-17.92-1.318-19.297-1.404-7.01-6.944-15.781-11.865-20.5-6.274-6.015-7.09-16.197-18.259-14.954-.204.022-5.084 10.148-7.777 13.512-3.728 4.657-2.47-4.153-6.526-4.153-.081 0-1.183-.103-1.253 0-.586.88-1.44 3.896-2.306 4.417-.265.16-1.722-.239-1.846 0-2.243 4.3 8.256 2.212 5.792 7.952-2.352 5.481-6.328-1.997-6.328 8.56M44.467 7.01c9.685 6.13.682 12.198 2.694 16.215 1.655 3.303 4.241 5.395 1.714 9.814-2.063 3.608-6.87 3.966-9.623 6.723-3.04 3.044-5.464 8.94-6.79 12.911-1.617 4.843 14.547 6.866 12.063 11.008-1.386 2.311-6.746 1.466-8.437.198-1.165-.873-3.593-.546-4.417-1.78-2.613-3.915-2.26-8.023-3.625-12.128-.938-2.822-6.313-2.12-7.844-.593-.523.522-.33 1.792-.33 2.505 0 5.285 7.12 3.316 7.12 6.46 0 14.636 3.927 6.534 11.14 11.336 10.036 6.683 7.844 7.303 14.946 14.404 3.673 3.673 7.741 3.686 9.425 9.294 1.602 5.331-9.327 5.339-11.716 7.448-1.123.991-2.813 4.146-4.219 4.615-1.792.598-3.234.496-4.944 1.78-2.427 1.82-3.9 4.932-4.02 4.81-2.148-2.147-3.52-15.479-3.89-18.257-.588-4.42-5.59-5.54-6.986-9.03-1.57-3.927 1.524-9.52-1.129-13.761-6.52-10.424-11.821-14.5-15.35-26.292-.942-3.148 3.342-6.529 4.877-8.833 1.877-2.816 2.662-5.854 4.746-8.635C22.147 24.19 40.855 9.461 43.857 8.635l.61-1.625z\"/><path d=\"M64 126c34.242 0 62-27.758 62-62 0-34.242-27.758-62-62-62C29.758 2 2 29.758 2 64c0 34.242 27.758 62 62 62zm0-6c30.928 0 56-25.072 56-56S94.928 8 64 8 8 33.072 8 64s25.072 56 56 56z\"/></g></svg>"
        },
        "$:/core/images/heading-1": {
            "title": "$:/core/images/heading-1",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-1 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M14 30h13.25v30.104H61.7V30h13.25v75.684H61.7V71.552H27.25v34.132H14V30zm70.335 13.78c2.544 0 5.017-.212 7.42-.636 2.403-.424 4.576-1.13 6.52-2.12 1.942-.99 3.603-2.261 4.981-3.816 1.378-1.555 2.28-3.463 2.703-5.724h9.858v74.2h-13.25V53.32H84.335v-9.54z\"/></svg>"
        },
        "$:/core/images/heading-2": {
            "title": "$:/core/images/heading-2",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-2 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M6 30h13.25v30.104H53.7V30h13.25v75.684H53.7V71.552H19.25v34.132H6V30zm119.52 75.684H74.85c.07-6.148 1.555-11.519 4.452-16.112 2.897-4.593 6.855-8.586 11.872-11.978a133.725 133.725 0 017.526-5.141 59.6 59.6 0 007.208-5.353c2.19-1.908 3.993-3.975 5.406-6.201 1.413-2.226 2.155-4.788 2.226-7.685 0-1.343-.159-2.774-.477-4.293a11.357 11.357 0 00-1.855-4.24c-.919-1.307-2.19-2.403-3.816-3.286-1.625-.883-3.745-1.325-6.36-1.325-2.403 0-4.399.477-5.989 1.431-1.59.954-2.862 2.261-3.816 3.922-.954 1.66-1.66 3.622-2.12 5.883-.46 2.261-.724 4.7-.795 7.314H76.23c0-4.099.548-7.897 1.643-11.395 1.095-3.498 2.738-6.519 4.93-9.063 2.19-2.544 4.857-4.54 8.002-5.989C93.95 30.724 97.606 30 101.775 30c4.523 0 8.303.742 11.342 2.226 3.039 1.484 5.494 3.357 7.367 5.618 1.873 2.261 3.198 4.717 3.975 7.367.777 2.65 1.166 5.176 1.166 7.579 0 2.968-.46 5.653-1.378 8.056a25.942 25.942 0 01-3.71 6.625 37.5 37.5 0 01-5.3 5.565 79.468 79.468 0 01-6.148 4.77 165.627 165.627 0 01-6.36 4.24 94.28 94.28 0 00-5.883 4.028c-1.802 1.343-3.374 2.738-4.717 4.187-1.343 1.449-2.261 2.986-2.756 4.611h36.146v10.812z\"/></svg>"
        },
        "$:/core/images/heading-3": {
            "title": "$:/core/images/heading-3",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-3 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M6 30h13.25v30.104H53.7V30h13.25v75.684H53.7V71.552H19.25v34.132H6V30zm88.885 32.224c1.979.07 3.957-.07 5.936-.424 1.979-.353 3.745-.972 5.3-1.855a10.365 10.365 0 003.763-3.657c.954-1.555 1.431-3.463 1.431-5.724 0-3.18-1.078-5.724-3.233-7.632-2.155-1.908-4.929-2.862-8.32-2.862-2.12 0-3.958.424-5.513 1.272a11.318 11.318 0 00-3.869 3.445c-1.025 1.449-1.784 3.074-2.279 4.876a18.335 18.335 0 00-.636 5.565H75.381c.141-3.604.813-6.943 2.014-10.017 1.201-3.074 2.844-5.742 4.93-8.003 2.084-2.261 4.61-4.028 7.578-5.3C92.871 30.636 96.228 30 99.973 30a29.2 29.2 0 018.533 1.272c2.791.848 5.3 2.085 7.526 3.71s4.01 3.692 5.353 6.201c1.343 2.509 2.014 5.388 2.014 8.639 0 3.745-.848 7.014-2.544 9.805-1.696 2.791-4.346 4.823-7.95 6.095v.212c4.24.848 7.544 2.95 9.911 6.307s3.551 7.438 3.551 12.243c0 3.533-.707 6.696-2.12 9.487a21.538 21.538 0 01-5.724 7.102c-2.403 1.943-5.194 3.445-8.374 4.505-3.18 1.06-6.537 1.59-10.07 1.59-4.31 0-8.074-.618-11.289-1.855s-5.9-2.986-8.056-5.247c-2.155-2.261-3.798-4.982-4.929-8.162-1.13-3.18-1.731-6.713-1.802-10.6h12.084c-.141 4.523.972 8.286 3.34 11.289 2.366 3.003 5.917 4.505 10.652 4.505 4.028 0 7.402-1.148 10.123-3.445 2.72-2.297 4.081-5.565 4.081-9.805 0-2.897-.565-5.194-1.696-6.89a10.97 10.97 0 00-4.452-3.869c-1.837-.883-3.904-1.431-6.2-1.643a58.067 58.067 0 00-7.05-.212v-9.01z\"/></svg>"
        },
        "$:/core/images/heading-4": {
            "title": "$:/core/images/heading-4",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-4 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M8 30h13.25v30.104H55.7V30h13.25v75.684H55.7V71.552H21.25v34.132H8V30zm76.59 48.548h22.471V45.9h-.212L84.59 78.548zm43.46 9.54h-9.54v17.596H107.06V88.088h-31.8V76.11l31.8-44.626h11.448v47.064h9.54v9.54z\"/></svg>"
        },
        "$:/core/images/heading-5": {
            "title": "$:/core/images/heading-5",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-5 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M6 30h13.25v30.104H53.7V30h13.25v75.684H53.7V71.552H19.25v34.132H6V30zm77.755 1.484h38.372v10.812H92.765L88.95 61.164l.212.212c1.625-1.837 3.692-3.233 6.201-4.187 2.509-.954 5-1.431 7.473-1.431 3.675 0 6.96.618 9.858 1.855 2.897 1.237 5.335 2.968 7.314 5.194s3.48 4.858 4.505 7.897c1.025 3.039 1.537 6.325 1.537 9.858 0 2.968-.477 6.024-1.43 9.169a25.161 25.161 0 01-4.559 8.586c-2.085 2.58-4.752 4.7-8.003 6.36-3.25 1.66-7.137 2.491-11.66 2.491-3.604 0-6.943-.477-10.017-1.431-3.074-.954-5.777-2.385-8.109-4.293-2.332-1.908-4.187-4.258-5.565-7.049-1.378-2.791-2.138-6.06-2.279-9.805h12.084c.353 4.028 1.731 7.12 4.134 9.275 2.403 2.155 5.583 3.233 9.54 3.233 2.544 0 4.7-.424 6.466-1.272 1.767-.848 3.198-2.014 4.293-3.498 1.095-1.484 1.873-3.215 2.332-5.194.46-1.979.69-4.099.69-6.36 0-2.05-.284-4.01-.849-5.883-.565-1.873-1.413-3.516-2.544-4.929-1.13-1.413-2.597-2.544-4.399-3.392-1.802-.848-3.904-1.272-6.307-1.272-2.544 0-4.929.477-7.155 1.431-2.226.954-3.834 2.738-4.823 5.353H75.805l7.95-40.598z\"/></svg>"
        },
        "$:/core/images/heading-6": {
            "title": "$:/core/images/heading-6",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-heading-6 tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M6 30h13.25v30.104H53.7V30h13.25v75.684H53.7V71.552H19.25v34.132H6V30zm106.587 20.246c-.283-3.039-1.36-5.494-3.233-7.367-1.873-1.873-4.399-2.809-7.579-2.809-2.19 0-4.08.406-5.67 1.219a12.435 12.435 0 00-4.029 3.233c-1.095 1.343-1.979 2.88-2.65 4.611a37.696 37.696 0 00-1.643 5.459 46.08 46.08 0 00-.9 5.671 722.213 722.213 0 00-.478 5.247l.212.212c1.625-2.968 3.87-5.176 6.731-6.625 2.862-1.449 5.954-2.173 9.275-2.173 3.675 0 6.96.636 9.858 1.908 2.897 1.272 5.353 3.021 7.367 5.247 2.014 2.226 3.551 4.858 4.611 7.897 1.06 3.039 1.59 6.325 1.59 9.858 0 3.604-.583 6.943-1.749 10.017-1.166 3.074-2.844 5.76-5.035 8.056-2.19 2.297-4.805 4.081-7.844 5.353-3.039 1.272-6.395 1.908-10.07 1.908-5.441 0-9.91-1.007-13.409-3.021-3.498-2.014-6.254-4.77-8.268-8.268-2.014-3.498-3.41-7.597-4.187-12.296-.777-4.7-1.166-9.77-1.166-15.211 0-4.452.477-8.94 1.431-13.462.954-4.523 2.526-8.639 4.717-12.349 2.19-3.71 5.07-6.731 8.64-9.063C92.676 31.166 97.075 30 102.304 30c2.968 0 5.76.495 8.374 1.484 2.615.99 4.93 2.367 6.943 4.134 2.014 1.767 3.657 3.887 4.93 6.36 1.271 2.473 1.978 5.23 2.12 8.268h-12.085zm-11.66 46.852c2.19 0 4.099-.442 5.724-1.325a12.869 12.869 0 004.081-3.445c1.095-1.413 1.908-3.056 2.438-4.929.53-1.873.795-3.798.795-5.777s-.265-3.887-.795-5.724c-.53-1.837-1.343-3.445-2.438-4.823-1.095-1.378-2.456-2.491-4.08-3.339-1.626-.848-3.534-1.272-5.725-1.272-2.19 0-4.116.406-5.777 1.219-1.66.813-3.056 1.908-4.187 3.286-1.13 1.378-1.979 2.986-2.544 4.823-.565 1.837-.848 3.78-.848 5.83 0 2.05.283 3.993.848 5.83.565 1.837 1.413 3.48 2.544 4.929a12.39 12.39 0 004.187 3.445c1.66.848 3.586 1.272 5.777 1.272z\"/></svg>"
        },
        "$:/core/images/help": {
            "title": "$:/core/images/help",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-help tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M36.055 111.441c-5.24 4.396-15.168 7.362-26.555 7.362-1.635 0-3.24-.06-4.806-.179 7.919-2.64 14.062-8.6 16.367-16.014C8.747 92.845 1.05 78.936 1.05 63.5c0-29.547 28.206-53.5 63-53.5s63 23.953 63 53.5-28.206 53.5-63 53.5c-10.055 0-19.56-2-27.994-5.559zm35.35-33.843a536.471 536.471 0 00.018-4.682 199.02 199.02 0 00-.023-3.042c.008-1.357.595-2.087 3.727-4.235.112-.077 1.085-.74 1.386-.948 3.093-2.133 5.022-3.786 6.762-6.187 2.34-3.228 3.558-7.077 3.558-11.649 0-13.292-9.86-21.952-21.455-21.952-11.103 0-22.499 9.609-24.066 22.295a6.023 6.023 0 1011.956 1.477c.806-6.527 6.972-11.726 12.11-11.726 5.265 0 9.408 3.64 9.408 9.906 0 3.634-1.1 5.153-5.111 7.919l-1.362.93c-2.682 1.84-4.227 3.1-5.7 4.931-2.109 2.62-3.242 5.717-3.258 9.314.013.892.02 1.86.022 2.981a470.766 470.766 0 01-.022 4.943 6.023 6.023 0 1012.046.12l.003-.395zm-6.027 24.499a7.529 7.529 0 100-15.058 7.529 7.529 0 000 15.058z\"/></svg>"
        },
        "$:/core/images/home-button": {
            "title": "$:/core/images/home-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-home-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M112.985 119.502c.01-.165.015-.331.015-.499V67.568c3.137 2.948 8.076 2.884 11.134-.174a7.999 7.999 0 00-.002-11.316L70.396 2.343A7.978 7.978 0 0064.734 0a7.957 7.957 0 00-5.656 2.343L33 28.42V8.007C33 3.585 29.41 0 25 0c-4.418 0-8 3.59-8 8.007V44.42L5.342 56.078c-3.125 3.125-3.12 8.198-.002 11.316a7.999 7.999 0 0011.316-.003l.344-.343v52.945a8.11 8.11 0 000 .007c0 4.418 3.588 8 8 8h80c4.419 0 8-3.59 8-8a8.11 8.11 0 00-.015-.498zM97 112V51.574L64.737 19.31 33 51.048V112h64z\"/></svg>"
        },
        "$:/core/images/import-button": {
            "title": "$:/core/images/import-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-import-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M114.832 60.436s3.235-3.27 6.921.417c3.686 3.686.231 7.14.231 7.14l-42.153 42.92s-30.765 32.367-58.798 4.333C-7 87.213 24.59 55.623 24.59 55.623L67.363 12.85s22.725-24.6 43.587-3.738c20.862 20.862-3.96 43.09-3.96 43.09l-35.04 35.04S49.903 112.546 36.426 99.07c-13.476-13.477 11.83-35.523 11.83-35.523l35.04-35.04s3.902-3.902 7.78-.023c3.879 3.878.118 7.921.118 7.921l-35.04 35.04s-13.212 13.212-8.872 17.551c4.34 4.34 16.77-9.653 16.77-9.653l35.04-35.04s16.668-14.598 3.966-27.3c-13.893-13.892-27.565 3.702-27.565 3.702l-42.91 42.91s-23.698 23.698-3.658 43.738 43.012-4.385 43.012-4.385l42.895-42.533z\"/></svg>"
        },
        "$:/core/images/info-button": {
            "title": "$:/core/images/info-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-info-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\" transform=\"translate(.05)\"><path d=\"M64 128c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64c0 35.346 28.654 64 64 64zm0-16c26.51 0 48-21.49 48-48S90.51 16 64 16 16 37.49 16 64s21.49 48 48 48z\"/><circle cx=\"64\" cy=\"32\" r=\"8\"/><rect width=\"16\" height=\"56\" x=\"56\" y=\"48\" rx=\"8\"/></g></svg>"
        },
        "$:/core/images/italic": {
            "title": "$:/core/images/italic",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-italic tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M66.711 0h22.41L62.408 128H40z\"/></svg>"
        },
        "$:/core/images/left-arrow": {
            "title": "$:/core/images/left-arrow",
            "created": "20150315234410875",
            "modified": "20150315235324760",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-left-arrow tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M0 64.177c0-2.026.771-4.054 2.317-5.6l55.98-55.98a7.92 7.92 0 0111.195.001c3.086 3.085 3.092 8.104.001 11.195L19.111 64.175l50.382 50.382a7.92 7.92 0 010 11.195c-3.086 3.086-8.105 3.092-11.196.001l-55.98-55.98A7.892 7.892 0 010 64.177z\"/></svg>"
        },
        "$:/core/images/line-width": {
            "title": "$:/core/images/line-width",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-line-width tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M16 18h96a2 2 0 000-4H16a2 2 0 100 4zm0 17h96a4 4 0 100-8H16a4 4 0 100 8zm0 21h96a6 6 0 000-12H16a6 6 0 100 12zm0 29h96c5.523 0 10-4.477 10-10s-4.477-10-10-10H16c-5.523 0-10 4.477-10 10s4.477 10 10 10zm0 43h96c8.837 0 16-7.163 16-16s-7.163-16-16-16H16c-8.837 0-16 7.163-16 16s7.163 16 16 16z\"/></svg>"
        },
        "$:/core/images/link": {
            "title": "$:/core/images/link",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-link tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M42.263 69.38a31.919 31.919 0 006.841 10.13c12.5 12.5 32.758 12.496 45.255 0l22.627-22.628c12.502-12.501 12.497-32.758 0-45.255-12.5-12.5-32.758-12.496-45.254 0L49.104 34.255a32.333 32.333 0 00-2.666 3.019 36.156 36.156 0 0121.94.334l14.663-14.663c6.25-6.25 16.382-6.254 22.632-.004 6.248 6.249 6.254 16.373-.004 22.631l-22.62 22.62c-6.25 6.25-16.381 6.254-22.631.004a15.93 15.93 0 01-4.428-8.433 11.948 11.948 0 00-7.59 3.48l-6.137 6.137z\"/><path d=\"M86.35 59.234a31.919 31.919 0 00-6.84-10.13c-12.5-12.5-32.758-12.497-45.255 0L11.627 71.732c-12.501 12.5-12.496 32.758 0 45.254 12.5 12.5 32.758 12.497 45.255 0L79.51 94.36a32.333 32.333 0 002.665-3.02 36.156 36.156 0 01-21.94-.333l-14.663 14.663c-6.25 6.25-16.381 6.253-22.63.004-6.25-6.249-6.255-16.374.003-22.632l22.62-22.62c6.25-6.25 16.381-6.253 22.631-.003a15.93 15.93 0 014.428 8.432 11.948 11.948 0 007.59-3.48l6.137-6.136z\"/></g></svg>"
        },
        "$:/core/images/linkify": {
            "title": "$:/core/images/linkify",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-linkify-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M17.031 31.919H9.048V96.85h7.983v6.92H0V25h17.031v6.919zm24.66 0h-7.983V96.85h7.983v6.92H24.66V25h17.03v6.919zM67.77 56.422l11.975-3.903 2.306 7.096-12.063 3.903 7.628 10.379-6.12 4.435-7.63-10.467-7.45 10.2-5.943-4.523L58.1 63.518 45.95 59.35l2.306-7.096 12.064 4.17V43.825h7.45v12.596zM86.31 96.85h7.982V31.92H86.31V25h17.031v78.77H86.31v-6.92zm24.659 0h7.983V31.92h-7.983V25H128v78.77h-17.031v-6.92z\"/></svg>"
        },
        "$:/core/images/list-bullet": {
            "title": "$:/core/images/list-bullet",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-list-bullet tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M11.636 40.273c6.427 0 11.637-5.21 11.637-11.637C23.273 22.21 18.063 17 11.636 17 5.21 17 0 22.21 0 28.636c0 6.427 5.21 11.637 11.636 11.637zm0 34.909c6.427 0 11.637-5.21 11.637-11.637 0-6.426-5.21-11.636-11.637-11.636C5.21 51.91 0 57.12 0 63.545c0 6.427 5.21 11.637 11.636 11.637zm0 34.909c6.427 0 11.637-5.21 11.637-11.636 0-6.427-5.21-11.637-11.637-11.637C5.21 86.818 0 92.028 0 98.455c0 6.426 5.21 11.636 11.636 11.636zM34.91 22.818H128v11.637H34.91V22.818zm0 34.91H128v11.636H34.91V57.727zm0 34.908H128v11.637H34.91V92.636z\"/></svg>"
        },
        "$:/core/images/list-number": {
            "title": "$:/core/images/list-number",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-list-number tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M33.84 22.356H128v11.77H33.84v-11.77zm0 35.31H128v11.77H33.84v-11.77zm0 35.311H128v11.77H33.84v-11.77zM.38 42.631v-2.223h.998c.826 0 1.445-.14 1.858-.42.413-.28.619-.948.619-2.002V22.769c0-1.442-.193-2.336-.58-2.683-.385-.347-1.477-.52-3.275-.52v-2.143c3.502-.147 6.252-.955 8.25-2.423h2.117v22.865c0 .921.15 1.575.449 1.963.3.387.949.58 1.948.58h.998v2.223H.38zm-.3 35.356v-1.902c7.19-6.554 10.786-12.58 10.786-18.08 0-1.562-.326-2.81-.979-3.744-.652-.934-1.524-1.402-2.616-1.402-.893 0-1.655.317-2.287.952-.633.634-.95 1.364-.95 2.192 0 .974.247 1.829.74 2.563.106.16.16.28.16.36 0 .147-.16.28-.48.4-.213.08-.752.308-1.618.681-.839.374-1.358.561-1.558.561-.24 0-.512-.37-.819-1.111A6.2 6.2 0 010 57.064c0-1.949.849-3.544 2.547-4.785 1.698-1.242 3.798-1.862 6.302-1.862 2.463 0 4.53.67 6.202 2.012 1.67 1.341 2.506 3.093 2.506 5.256a8.644 8.644 0 01-.849 3.724c-.566 1.201-1.92 3.053-4.064 5.556a165.471 165.471 0 01-6.272 6.938h11.445l-1.019 5.726h-2.117c.08-.28.12-.534.12-.76 0-.388-.1-.631-.3-.731-.2-.1-.599-.15-1.198-.15H.08zm12.124 19.207c1.745.04 3.236.637 4.474 1.792 1.239 1.154 1.858 2.773 1.858 4.855 0 2.99-1.132 5.393-3.396 7.208-2.263 1.815-5 2.723-8.209 2.723-2.01 0-3.669-.384-4.974-1.151C.652 111.853 0 110.849 0 109.607c0-.774.27-1.398.809-1.872.54-.474 1.128-.71 1.768-.71.639 0 1.162.2 1.568.6.406.4.782 1.055 1.128 1.962.466 1.268 1.239 1.902 2.317 1.902 1.265 0 2.287-.477 3.066-1.431.78-.955 1.169-2.686 1.169-5.196 0-1.709-.12-3.023-.36-3.944-.24-.921-.792-1.382-1.658-1.382-.586 0-1.185.307-1.797.921-.493.494-.932.741-1.319.741-.333 0-.602-.147-.809-.44-.206-.294-.31-.574-.31-.841 0-.32.104-.594.31-.821.207-.227.69-.594 1.449-1.102 2.876-1.922 4.314-4.017 4.314-6.287 0-1.188-.306-2.092-.919-2.713a3.001 3.001 0 00-2.217-.93c-.799 0-1.525.263-2.177.79-.653.528-.979 1.158-.979 1.892 0 .641.253 1.235.76 1.782.172.2.259.367.259.5 0 .121-.57.428-1.708.922-1.139.494-1.854.74-2.147.74-.413 0-.75-.333-1.009-1-.26-.668-.39-1.282-.39-1.842 0-1.749.93-3.224 2.787-4.425 1.858-1.202 3.965-1.802 6.322-1.802 2.064 0 3.851.447 5.363 1.341 1.511.895 2.267 2.116 2.267 3.664 0 1.362-.57 2.623-1.708 3.784a13.387 13.387 0 01-3.945 2.784z\"/></svg>"
        },
        "$:/core/images/list": {
            "title": "$:/core/images/list",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-list tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M87.748 128H23.999c-4.418 0-7.999-3.59-7.999-8.007V8.007C16 3.585 19.588 0 24 0h80c4.419 0 8 3.59 8 8.007V104H91.25c-.965 0-1.84.392-2.473 1.025a3.476 3.476 0 00-1.029 2.476V128zm8-.12l15.88-15.88h-15.88v15.88zM40 15.508A3.502 3.502 0 0143.5 12h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 20h-55a3.498 3.498 0 01-3.5-3.509v-.982zM32 22a6 6 0 100-12 6 6 0 000 12zm8 9.509A3.502 3.502 0 0143.5 28h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 36h-55a3.498 3.498 0 01-3.5-3.509v-.982zm0 16A3.502 3.502 0 0143.5 44h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 52h-55a3.498 3.498 0 01-3.5-3.509v-.982zm0 16A3.502 3.502 0 0143.5 60h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 68h-55a3.498 3.498 0 01-3.5-3.509v-.982zm0 16A3.502 3.502 0 0143.5 76h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 84h-55a3.498 3.498 0 01-3.5-3.509v-.982zm0 16A3.502 3.502 0 0143.5 92h55c1.933 0 3.5 1.561 3.5 3.509v.982A3.502 3.502 0 0198.5 100h-55a3.498 3.498 0 01-3.5-3.509v-.982zm0 16A3.505 3.505 0 0143.497 108h33.006A3.497 3.497 0 0180 111.509v.982A3.505 3.505 0 0176.503 116H43.497A3.497 3.497 0 0140 112.491v-.982zM32 38a6 6 0 100-12 6 6 0 000 12zm0 16a6 6 0 100-12 6 6 0 000 12zm0 16a6 6 0 100-12 6 6 0 000 12zm0 16a6 6 0 100-12 6 6 0 000 12zm0 16a6 6 0 100-12 6 6 0 000 12zm0 16a6 6 0 100-12 6 6 0 000 12z\"/></svg>"
        },
        "$:/core/images/locked-padlock": {
            "title": "$:/core/images/locked-padlock",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-locked-padlock tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M96.472 64H105v32.01C105 113.674 90.674 128 73.001 128H56C38.318 128 24 113.677 24 96.01V64h8c.003-15.723.303-47.731 32.16-47.731 31.794 0 32.305 32.057 32.312 47.731zm-15.897 0H48.44c.002-16.287.142-32 15.719-32 15.684 0 16.977 16.136 16.415 32zM67.732 92.364A8.503 8.503 0 0064.5 76a8.5 8.5 0 00-3.498 16.25l-5.095 22.77H72.8l-5.07-22.656z\"/></svg>"
        },
        "$:/core/images/mail": {
            "title": "$:/core/images/mail",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-mail tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M122.827 104.894a7.986 7.986 0 01-2.834.516H8.007c-.812 0-1.597-.12-2.335-.345l34.163-34.163 20.842 20.842a3.998 3.998 0 003.418 1.134 4.003 4.003 0 003.395-1.134L88.594 70.64c.075.09.155.176.24.26l33.993 33.994zm5.076-6.237c.064-.406.097-.823.097-1.247v-64c0-.669-.082-1.318-.237-1.94L94.23 65.006c.09.075.177.154.261.239l33.413 33.413zm-127.698.56A8.023 8.023 0 010 97.41v-64c0-.716.094-1.41.271-2.071l33.907 33.906L.205 99.218zM5.93 25.684a8.012 8.012 0 012.078-.273h111.986c.766 0 1.507.108 2.209.308L64.083 83.837 5.93 25.683z\"/></svg>"
        },
        "$:/core/images/menu-button": {
            "title": "$:/core/images/menu-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-menu-button tc-image-button\" viewBox=\"0 0 128 128\"><rect width=\"128\" height=\"16\" y=\"16\" rx=\"8\"/><rect width=\"128\" height=\"16\" y=\"56\" rx=\"8\"/><rect width=\"128\" height=\"16\" y=\"96\" rx=\"8\"/></svg>"
        },
        "$:/core/images/mono-block": {
            "title": "$:/core/images/mono-block",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-mono-block tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M23.965 32.967h.357c.755 0 1.328.192 1.72.577.39.384.586.947.586 1.688 0 .824-.206 1.418-.618 1.782-.413.363-1.094.545-2.045.545h-6.31c-.965 0-1.65-.178-2.056-.535-.405-.356-.608-.954-.608-1.792 0-.811.203-1.391.608-1.74.406-.35 1.09-.525 2.055-.525h.734l-.86-2.453H8.471l-.902 2.453h.734c.95 0 1.632.178 2.044.535.413.356.619.933.619 1.73 0 .824-.206 1.418-.619 1.782-.412.363-1.094.545-2.044.545h-5.41c-.964 0-1.649-.182-2.054-.545-.406-.364-.608-.958-.608-1.782 0-.741.195-1.304.587-1.688.391-.385.964-.577 1.719-.577h.356l5.62-15.641H6.835c-.95 0-1.632-.182-2.044-.546-.412-.363-.619-.95-.619-1.76 0-.825.207-1.42.619-1.783.412-.363 1.094-.545 2.044-.545h7.863c1.244 0 2.118.67 2.62 2.013v.063l6.647 18.2zM12.98 17.326l-3.04 8.848h6.08l-3.04-8.848zm22.402 9.372v6.395h3.145c2.223 0 3.788-.245 4.697-.734.908-.49 1.362-1.307 1.362-2.453 0-1.16-.433-1.985-1.3-2.474-.866-.49-2.383-.734-4.55-.734h-3.354zm10.693-2.327c1.524.559 2.642 1.324 3.355 2.295.713.972 1.07 2.212 1.07 3.722 0 1.272-.308 2.432-.923 3.48-.615 1.049-1.496 1.909-2.642 2.58a7.499 7.499 0 01-2.254.849c-.832.174-2.01.262-3.533.262H30.202c-.922 0-1.583-.182-1.981-.545-.399-.364-.598-.958-.598-1.782 0-.741.189-1.304.566-1.688.378-.385.93-.577 1.657-.577h.356V17.326h-.356c-.727 0-1.28-.196-1.657-.587-.377-.392-.566-.965-.566-1.72 0-.81.203-1.401.608-1.771.406-.37 1.062-.556 1.971-.556h9.645c2.95 0 5.19.573 6.72 1.72 1.53 1.145 2.296 2.823 2.296 5.031 0 1.09-.234 2.052-.703 2.883-.468.832-1.163 1.513-2.086 2.045zM35.381 17.2v5.284h2.83c1.72 0 2.932-.203 3.638-.609.706-.405 1.06-1.09 1.06-2.054 0-.909-.319-1.573-.955-1.992-.636-.42-1.667-.63-3.093-.63h-3.48zm35.863-3.816c.28-.503.566-.86.86-1.07.293-.21.664-.314 1.111-.314.685 0 1.17.182 1.457.545.287.364.43.986.43 1.866l.042 5.452c0 .964-.157 1.614-.472 1.95-.314.335-.884.503-1.709.503-.587 0-1.037-.14-1.352-.42-.314-.28-.584-.796-.807-1.551-.364-1.328-.944-2.282-1.74-2.862-.797-.58-1.901-.87-3.313-.87-2.153 0-3.802.727-4.948 2.18-1.147 1.454-1.72 3.558-1.72 6.311 0 2.74.58 4.844 1.74 6.311 1.16 1.468 2.817 2.202 4.97 2.202 1.467 0 3.085-.49 4.854-1.468 1.768-.978 2.883-1.467 3.344-1.467.545 0 1.003.23 1.373.692.37.46.556 1.034.556 1.719 0 1.23-1.084 2.39-3.25 3.48-2.167 1.09-4.606 1.636-7.318 1.636-3.662 0-6.625-1.21-8.89-3.627-2.264-2.419-3.396-5.578-3.396-9.478 0-3.76 1.146-6.884 3.438-9.372 2.293-2.488 5.2-3.732 8.723-3.732.992 0 1.97.112 2.935.335.964.224 1.992.574 3.082 1.049zm10.22 19.583V17.326h-.356c-.755 0-1.328-.196-1.72-.587-.39-.392-.586-.965-.586-1.72 0-.81.21-1.401.629-1.771.42-.37 1.097-.556 2.034-.556h5.178c2.922 0 5.06.126 6.416.377 1.356.252 2.51.671 3.46 1.258 1.691 1.007 2.988 2.443 3.89 4.31.9 1.865 1.352 4.021 1.352 6.467 0 2.586-.514 4.847-1.541 6.783-1.028 1.936-2.485 3.4-4.372 4.393-.853.447-1.852.772-2.998.975-1.147.203-2.852.304-5.116.304h-6.269c-.965 0-1.65-.178-2.055-.535-.406-.356-.608-.954-.608-1.792 0-.741.195-1.304.587-1.688.391-.385.964-.577 1.72-.577h.356zm5.41-15.725v15.725h1.195c2.642 0 4.592-.646 5.85-1.94 1.258-1.292 1.887-3.28 1.887-5.965 0-2.641-.64-4.612-1.918-5.912-1.28-1.3-3.205-1.95-5.777-1.95-.335 0-.59.003-.765.01a7.992 7.992 0 00-.472.032zm35.067-.126h-9.75v5.368h3.69v-.252c0-.797.175-1.39.524-1.782.35-.392.88-.587 1.594-.587.629 0 1.142.178 1.54.534.4.357.598.808.598 1.353 0 .028.007.118.021.272.014.154.021.308.021.462v4.34c0 .936-.167 1.607-.503 2.013-.335.405-.88.608-1.635.608-.713 0-1.251-.19-1.615-.567-.363-.377-.545-.936-.545-1.677v-.377h-3.69v6.269h9.75v-2.495c0-.937.178-1.608.534-2.013.357-.405.94-.608 1.75-.608.798 0 1.367.2 1.71.597.342.399.513 1.073.513 2.024v5.074c0 .755-.146 1.258-.44 1.51-.293.251-.873.377-1.74.377h-17.172c-.923 0-1.583-.182-1.982-.545-.398-.364-.597-.958-.597-1.782 0-.741.189-1.304.566-1.688.377-.385.93-.577 1.656-.577h.357V17.326h-.357c-.712 0-1.261-.2-1.646-.598-.384-.398-.576-.968-.576-1.709 0-.81.203-1.401.608-1.771.405-.37 1.062-.556 1.97-.556h17.173c.853 0 1.43.13 1.73.388.3.258.45.772.45 1.54v4.698c0 .95-.174 1.631-.524 2.044-.35.412-.915.618-1.698.618-.81 0-1.394-.21-1.75-.629-.357-.419-.535-1.097-.535-2.033v-2.202zM19.77 47.641c.267-.504.55-.86.85-1.07.3-.21.675-.314 1.122-.314.685 0 1.17.181 1.457.545.287.363.43.985.43 1.866l.042 5.451c0 .965-.157 1.615-.472 1.95-.314.336-.891.504-1.73.504-.587 0-1.045-.144-1.373-.43-.329-.287-.598-.8-.807-1.541-.378-1.342-.958-2.3-1.74-2.873-.783-.573-1.88-.86-3.292-.86-2.153 0-3.799.727-4.938 2.181-1.14 1.454-1.709 3.557-1.709 6.311s.598 4.882 1.793 6.385C10.599 67.248 12.294 68 14.488 68c.503 0 1.077-.06 1.72-.179a23.809 23.809 0 002.264-.555v-3.313h-2.37c-.95 0-1.624-.175-2.023-.524-.398-.35-.597-.93-.597-1.74 0-.84.199-1.437.597-1.793.399-.357 1.073-.535 2.024-.535h7.569c.978 0 1.667.175 2.065.524.398.35.598.937.598 1.762 0 .74-.2 1.31-.598 1.708-.398.399-.975.598-1.73.598h-.335v5.242c0 .447-.05.758-.147.933-.098.174-.293.353-.587.534-.797.476-2.062.895-3.795 1.258a25.576 25.576 0 01-5.263.546c-3.662 0-6.625-1.21-8.89-3.628-2.264-2.418-3.397-5.577-3.397-9.477 0-3.76 1.147-6.884 3.44-9.372 2.292-2.488 5.199-3.732 8.721-3.732.979 0 1.954.112 2.925.335.972.224 2.003.573 3.093 1.049zm15.84 3.941v4.823h6.857v-4.823h-.336c-.754 0-1.331-.195-1.73-.587-.398-.391-.597-.964-.597-1.719 0-.825.206-1.419.619-1.782.412-.364 1.093-.545 2.044-.545h5.41c.95 0 1.624.181 2.023.545.398.363.597.957.597 1.782 0 .755-.192 1.328-.576 1.72-.385.39-.947.586-1.688.586h-.357v15.642h.357c.755 0 1.328.192 1.719.576.391.385.587.947.587 1.688 0 .825-.203 1.419-.608 1.782-.405.364-1.09.546-2.055.546h-5.41c-.964 0-1.649-.179-2.054-.535-.405-.357-.608-.954-.608-1.793 0-.74.2-1.303.598-1.688.398-.384.975-.576 1.73-.576h.335v-6.186h-6.856v6.186h.335c.755 0 1.331.192 1.73.576.398.385.597.947.597 1.688 0 .825-.206 1.419-.618 1.782-.412.364-1.094.546-2.044.546h-5.41c-.964 0-1.65-.179-2.055-.535-.405-.357-.608-.954-.608-1.793 0-.74.196-1.303.587-1.688.392-.384.965-.576 1.72-.576h.356V51.582h-.356c-.741 0-1.304-.195-1.688-.587-.385-.391-.577-.964-.577-1.719 0-.825.2-1.419.598-1.782.398-.364 1.073-.545 2.023-.545h5.41c.936 0 1.614.181 2.033.545.42.363.63.957.63 1.782 0 .755-.2 1.328-.598 1.72-.399.39-.975.586-1.73.586h-.335zm31.754 0v15.642h3.523c.95 0 1.632.178 2.044.534.412.357.618.933.618 1.73 0 .811-.21 1.402-.629 1.772-.419.37-1.097.556-2.033.556H58.433c-.95 0-1.632-.182-2.044-.546-.412-.363-.619-.957-.619-1.782 0-.81.203-1.39.608-1.74.406-.35 1.09-.524 2.055-.524h3.523V51.582h-3.523c-.95 0-1.632-.181-2.044-.545-.412-.363-.619-.95-.619-1.761 0-.825.203-1.412.608-1.761.406-.35 1.09-.524 2.055-.524h12.455c.992 0 1.684.174 2.075.524.392.35.587.936.587 1.761 0 .81-.202 1.398-.608 1.761-.405.364-1.09.545-2.054.545h-3.523zm30.496 0v11.994c0 1.873-.122 3.228-.367 4.067a5.876 5.876 0 01-1.227 2.244c-.74.852-1.768 1.495-3.082 1.929-1.314.433-2.893.65-4.738.65-1.3 0-2.555-.126-3.764-.378a16.843 16.843 0 01-3.491-1.132c-.615-.28-1.017-.643-1.206-1.09-.188-.448-.283-1.175-.283-2.18v-4.32c0-1.202.175-2.04.525-2.516.349-.475.957-.713 1.824-.713 1.244 0 1.929.915 2.054 2.747.014.321.035.566.063.733.168 1.622.545 2.73 1.133 3.324.587.594 1.523.89 2.81.89 1.593 0 2.714-.422 3.364-1.268.65-.845.975-2.386.975-4.623V51.582H88.93c-.95 0-1.632-.181-2.044-.545-.413-.363-.619-.95-.619-1.761 0-.825.2-1.412.598-1.761.398-.35 1.086-.524 2.065-.524h10.693c.979 0 1.667.174 2.065.524.399.35.598.936.598 1.761 0 .81-.206 1.398-.619 1.761-.412.364-1.093.545-2.044.545h-1.761zm14.644 0v6.353l6.48-6.478c-.728-.084-1.238-.29-1.531-.619-.294-.328-.44-.85-.44-1.562 0-.825.198-1.419.597-1.782.398-.364 1.073-.545 2.023-.545h5.137c.95 0 1.625.181 2.023.545.399.363.598.957.598 1.782 0 .769-.2 1.345-.598 1.73-.398.384-.982.576-1.75.576h-.483l-6.101 6.06c1.132.839 2.167 1.94 3.103 3.302.937 1.363 2.034 3.456 3.292 6.28h.692c.825 0 1.44.188 1.845.566.405.377.608.943.608 1.698 0 .825-.206 1.419-.619 1.782-.412.364-1.093.546-2.044.546h-2.579c-1.132 0-2.048-.762-2.746-2.286-.126-.28-.224-.503-.294-.67-.923-1.958-1.768-3.467-2.537-4.53a16.616 16.616 0 00-2.705-2.914l-1.97 1.887v3.92h.335c.755 0 1.331.193 1.73.577.398.385.597.947.597 1.688 0 .825-.206 1.419-.618 1.782-.413.364-1.094.546-2.045.546h-5.41c-.964 0-1.649-.179-2.054-.535-.405-.357-.608-.954-.608-1.793 0-.74.196-1.303.587-1.688.391-.384.965-.576 1.72-.576h.356V51.582h-.357c-.74 0-1.303-.195-1.687-.587-.385-.391-.577-.964-.577-1.719 0-.825.2-1.419.598-1.782.398-.364 1.072-.545 2.023-.545h5.41c.936 0 1.614.181 2.033.545.42.363.63.957.63 1.782 0 .755-.2 1.328-.598 1.72-.399.39-.975.586-1.73.586h-.336zM13.44 96.326l4.005-11.889c.251-.782.6-1.352 1.048-1.709.447-.356 1.041-.534 1.782-.534h3.271c.95 0 1.632.182 2.044.545.413.363.619.957.619 1.782 0 .755-.2 1.328-.598 1.72-.398.39-.975.587-1.73.587h-.335l.587 15.641h.357c.754 0 1.32.192 1.698.577.377.384.566.947.566 1.687 0 .825-.2 1.42-.598 1.783-.398.363-1.072.545-2.023.545h-4.718c-.95 0-1.624-.178-2.023-.535-.398-.356-.597-.954-.597-1.793 0-.74.192-1.303.576-1.687.385-.385.954-.577 1.709-.577h.335l-.293-12.79-3.061 9.52c-.224.712-.542 1.226-.954 1.54-.413.315-.982.472-1.709.472-.727 0-1.303-.157-1.73-.472-.426-.314-.751-.828-.975-1.54l-3.04-9.52-.294 12.79h.336c.755 0 1.324.192 1.709.577.384.384.576.947.576 1.687 0 .825-.202 1.42-.608 1.783-.405.363-1.076.545-2.013.545H2.621c-.937 0-1.608-.182-2.013-.545-.405-.364-.608-.958-.608-1.783 0-.74.192-1.303.577-1.687.384-.385.954-.577 1.708-.577h.336l.608-15.641h-.336c-.754 0-1.331-.196-1.73-.588-.398-.39-.597-.964-.597-1.719 0-.825.206-1.419.619-1.782.412-.363 1.093-.545 2.044-.545h3.27c.728 0 1.311.175 1.752.524.44.35.8.923 1.08 1.72l4.109 11.888zm30.454 2.054V86.828H42.74c-.922 0-1.583-.182-1.981-.546-.398-.363-.598-.95-.598-1.76 0-.812.2-1.402.598-1.773.398-.37 1.059-.555 1.981-.555h5.955c.909 0 1.566.185 1.97.555.406.37.609.961.609 1.772 0 .741-.192 1.31-.577 1.709-.384.398-.933.598-1.646.598h-.356v19.038c0 .657-.07 1.069-.21 1.237-.14.167-.454.251-.943.251h-2.097c-.67 0-1.143-.07-1.415-.21-.273-.14-.507-.384-.703-.733l-8.722-15.327v11.385h1.216c.909 0 1.559.175 1.95.524.392.35.587.93.587 1.74 0 .825-.199 1.42-.597 1.783-.399.363-1.045.545-1.94.545h-6.017c-.909 0-1.566-.182-1.971-.545-.406-.364-.608-.958-.608-1.783 0-.74.188-1.303.566-1.687.377-.385.936-.577 1.677-.577h.336V86.828h-.336c-.713 0-1.265-.2-1.656-.598-.392-.398-.587-.968-.587-1.709 0-.81.206-1.401.618-1.772.413-.37 1.066-.555 1.96-.555h3.44c.824 0 1.383.108 1.677.325.293.216.622.653.985 1.31l7.989 14.551zM64.66 86.366c-1.803 0-3.218.727-4.245 2.18-1.028 1.455-1.541 3.474-1.541 6.06 0 2.586.517 4.613 1.551 6.08 1.034 1.468 2.446 2.202 4.235 2.202 1.804 0 3.222-.73 4.257-2.19 1.034-1.461 1.551-3.492 1.551-6.092 0-2.586-.513-4.605-1.54-6.06-1.028-1.453-2.45-2.18-4.268-2.18zm0-4.864c3.44 0 6.27 1.23 8.492 3.69 2.223 2.46 3.334 5.598 3.334 9.414 0 3.844-1.104 6.99-3.313 9.436-2.208 2.446-5.046 3.669-8.513 3.669-3.424 0-6.255-1.234-8.491-3.701-2.237-2.467-3.355-5.602-3.355-9.404 0-3.83 1.108-6.971 3.323-9.424 2.216-2.454 5.057-3.68 8.523-3.68zM87.461 98.17v4.298h2.16c.908 0 1.555.175 1.94.524.384.35.576.93.576 1.74 0 .825-.196 1.42-.587 1.783-.392.363-1.035.545-1.93.545h-7.254c-.922 0-1.583-.182-1.981-.545-.399-.364-.598-.958-.598-1.783 0-.74.189-1.303.566-1.687.378-.385.93-.577 1.657-.577h.356V86.828h-.356c-.713 0-1.262-.2-1.646-.598-.385-.398-.577-.968-.577-1.709 0-.81.203-1.401.608-1.772.406-.37 1.063-.555 1.971-.555h8.66c3.424 0 6.014.657 7.768 1.97 1.754 1.315 2.631 3.25 2.631 5.809 0 2.697-.873 4.738-2.62 6.122-1.748 1.384-4.34 2.076-7.78 2.076h-3.564zm0-11.343v6.625h2.977c1.65 0 2.89-.28 3.722-.839.832-.559 1.248-1.397 1.248-2.516 0-1.048-.43-1.855-1.29-2.421-.86-.566-2.086-.85-3.68-.85h-2.977zm27.267 20.568l-1.636 1.636a12.37 12.37 0 011.772-.44c.58-.098 1.15-.147 1.709-.147 1.104 0 2.268.164 3.491.492 1.223.329 1.967.493 2.233.493.447 0 1.03-.15 1.75-.45.72-.301 1.206-.452 1.458-.452.517 0 .947.2 1.29.598.342.398.513.898.513 1.5 0 .796-.472 1.474-1.415 2.033-.944.56-2.1.839-3.47.839-.937 0-2.139-.22-3.607-.66-1.467-.441-2.53-.661-3.187-.661-.992 0-2.11.272-3.354.817-1.244.546-2.013.818-2.307.818a2.14 2.14 0 01-1.53-.597c-.42-.399-.63-.878-.63-1.437 0-.391.134-.807.4-1.247.265-.44.733-1.01 1.404-1.709l2.118-2.139c-2.335-.852-4.194-2.386-5.578-4.602-1.384-2.215-2.075-4.763-2.075-7.642 0-3.802 1.104-6.909 3.312-9.32 2.209-2.411 5.053-3.617 8.534-3.617 3.467 0 6.304 1.209 8.513 3.627 2.208 2.418 3.312 5.522 3.312 9.31 0 3.774-1.097 6.884-3.291 9.33-2.195 2.446-4.977 3.67-8.345 3.67a22.5 22.5 0 01-1.384-.043zm1.195-21.03c-1.803 0-3.218.727-4.246 2.18-1.027 1.455-1.54 3.474-1.54 6.06 0 2.586.516 4.613 1.55 6.08 1.035 1.468 2.447 2.202 4.236 2.202 1.803 0 3.222-.73 4.256-2.19 1.035-1.461 1.552-3.492 1.552-6.092 0-2.586-.514-4.605-1.541-6.06-1.028-1.453-2.45-2.18-4.267-2.18z\"/></svg>"
        },
        "$:/core/images/mono-line": {
            "title": "$:/core/images/mono-line",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-mono-line tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M60.437 84.523h.908c1.922 0 3.381.489 4.378 1.468.997.979 1.495 2.411 1.495 4.298 0 2.1-.525 3.612-1.575 4.538-1.05.925-2.785 1.388-5.206 1.388h-16.07c-2.456 0-4.2-.454-5.232-1.361-1.032-.908-1.548-2.43-1.548-4.565 0-2.065.516-3.542 1.548-4.432 1.032-.89 2.776-1.334 5.232-1.334h1.869l-2.19-6.247H20.983l-2.296 6.247h1.87c2.42 0 4.155.453 5.205 1.361 1.05.908 1.575 2.376 1.575 4.405 0 2.1-.525 3.612-1.575 4.538-1.05.925-2.785 1.388-5.206 1.388H6.781c-2.456 0-4.2-.463-5.233-1.388C.516 93.9 0 92.389 0 90.289c0-1.887.498-3.32 1.495-4.298.997-.979 2.456-1.468 4.378-1.468h.908l14.308-39.83h-4.271c-2.42 0-4.156-.462-5.206-1.387-1.05-.926-1.575-2.42-1.575-4.485 0-2.1.525-3.613 1.575-4.538 1.05-.926 2.785-1.388 5.206-1.388h20.021c3.168 0 5.392 1.708 6.674 5.125v.16l16.924 46.343zm-27.976-39.83L24.72 67.225h15.483l-7.742-22.53zM89.506 68.56v16.284h8.008c5.66 0 9.646-.623 11.96-1.869 2.313-1.245 3.47-3.328 3.47-6.246 0-2.955-1.103-5.055-3.31-6.3-2.207-1.246-6.069-1.869-11.586-1.869h-8.542zm27.229-5.926c3.88 1.423 6.727 3.372 8.542 5.846 1.815 2.474 2.723 5.633 2.723 9.477 0 3.239-.783 6.193-2.35 8.862-1.565 2.67-3.808 4.859-6.726 6.567-1.709.997-3.622 1.718-5.74 2.163-2.118.445-5.116.667-8.996.667h-27.87c-2.349 0-4.03-.463-5.045-1.388-1.014-.926-1.521-2.438-1.521-4.538 0-1.887.48-3.32 1.441-4.298.961-.979 2.367-1.468 4.218-1.468h.907v-39.83h-.907c-1.851 0-3.257-.498-4.218-1.494-.961-.997-1.441-2.456-1.441-4.378 0-2.065.516-3.568 1.548-4.512 1.032-.943 2.705-1.414 5.018-1.414h24.56c7.51 0 13.214 1.459 17.111 4.377 3.898 2.92 5.847 7.19 5.847 12.814 0 2.776-.597 5.223-1.789 7.341-1.192 2.118-2.963 3.853-5.312 5.206zm-27.23-18.26v13.455h7.208c4.378 0 7.466-.516 9.264-1.549 1.797-1.032 2.696-2.776 2.696-5.232 0-2.313-.81-4.004-2.43-5.072-1.619-1.068-4.244-1.602-7.874-1.602h-8.863z\"/></svg>"
        },
        "$:/core/images/new-button": {
            "title": "$:/core/images/new-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-new-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M56 72H8.007C3.591 72 0 68.418 0 64c0-4.41 3.585-8 8.007-8H56V8.007C56 3.591 59.582 0 64 0c4.41 0 8 3.585 8 8.007V56h47.993c4.416 0 8.007 3.582 8.007 8 0 4.41-3.585 8-8.007 8H72v47.993c0 4.416-3.582 8.007-8 8.007-4.41 0-8-3.585-8-8.007V72z\"/></svg>"
        },
        "$:/core/images/new-here-button": {
            "title": "$:/core/images/new-here-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-new-here-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M55.838 20.935l-3.572.938c-3.688.968-8.23 4.43-10.136 7.731L3.37 96.738c-1.905 3.3-.771 7.524 2.534 9.432l33.717 19.466c3.297 1.904 7.53.78 9.435-2.521l38.76-67.134c1.905-3.3 2.632-8.963 1.623-12.646L83.285 20.88c-1.009-3.68-4.821-5.884-8.513-4.915l-7.603 1.995.043.287c.524 3.394 2.053 7.498 4.18 11.55.418.163.829.36 1.23.59a8.864 8.864 0 014.438 8.169c.104.132.21.264.316.395l-.386.318a8.663 8.663 0 01-1.082 3.137c-2.42 4.192-7.816 5.608-12.051 3.163-4.12-2.379-5.624-7.534-3.476-11.671-2.177-4.394-3.788-8.874-4.543-12.964z\"/><path d=\"M69.554 44.76c-5.944-7.476-10.74-17.196-11.955-25.059-1.68-10.875 3.503-18.216 15.082-18.04 10.407.158 19.975 5.851 24.728 13.785 5.208 8.695 2.95 17.868-6.855 20.496l-2.037-7.601c4.232-1.134 4.999-4.248 2.24-8.853-3.37-5.626-10.465-9.848-18.146-9.965-6.392-.097-8.31 2.62-7.323 9.01.999 6.465 5.318 15.138 10.582 21.65l-.072.06c.559 1.553-4.17 6.44-5.938 4.888l-.005.004-.028-.034a1.323 1.323 0 01-.124-.135 2.618 2.618 0 01-.149-.205z\"/><rect width=\"16\" height=\"48\" x=\"96\" y=\"80\" rx=\"8\"/><rect width=\"48\" height=\"16\" x=\"80\" y=\"96\" rx=\"8\"/></g></svg>"
        },
        "$:/core/images/new-image-button": {
            "title": "$:/core/images/new-image-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-new-image-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M81.362 73.627l15.826-27.41a2.626 2.626 0 00-.962-3.59l-50.01-28.872a2.626 2.626 0 00-3.588.961L30.058 36.49l10.04-5.261c3.042-1.595 6.771.114 7.55 3.46l3.607 17.702 9.88.85a5.25 5.25 0 014.571 3.77c.034.115.1.344.199.671.165.553.353 1.172.562 1.843.595 1.914 1.23 3.85 1.872 5.678.207.588.412 1.156.614 1.701.625 1.685 1.209 3.114 1.725 4.207.255.54.485.977.726 1.427.214.212.547.425 1.011.622 1.141.482 2.784.74 4.657.758.864.008 1.71-.034 2.492-.11.448-.043.753-.085.871-.104.315-.053.625-.077.927-.076zM37.47 2.649A5.257 5.257 0 0144.649.725l63.645 36.746a5.257 5.257 0 011.923 7.178L73.47 108.294a5.257 5.257 0 01-7.177 1.923L2.649 73.47a5.257 5.257 0 01-1.924-7.177L37.471 2.649zm42.837 50.49a5.25 5.25 0 105.25-9.092 5.25 5.25 0 00-5.25 9.093zM96 112h-7.993c-4.419 0-8.007-3.582-8.007-8 0-4.41 3.585-8 8.007-8H96v-7.993C96 83.588 99.582 80 104 80c4.41 0 8 3.585 8 8.007V96h7.993c4.419 0 8.007 3.582 8.007 8 0 4.41-3.585 8-8.007 8H112v7.993c0 4.419-3.582 8.007-8 8.007-4.41 0-8-3.585-8-8.007V112zM33.347 51.791c7.428 7.948 9.01 10.69 7.449 13.394-1.56 2.703-13.838-2.328-16.094 1.58-2.256 3.908-.907 3.258-2.437 5.908l19.73 11.39s-5.605-8.255-4.235-10.628c2.515-4.356 8.77-1.256 10.365-4.019 2.414-4.181-5.103-9.639-14.778-17.625z\"/></svg>"
        },
        "$:/core/images/new-journal-button": {
            "title": "$:/core/images/new-journal-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-new-journal-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M102.545 112.818v11.818c0 1.306 1.086 2.364 2.425 2.364h6.06c1.34 0 2.425-1.058 2.425-2.364v-11.818h12.12c1.34 0 2.425-1.058 2.425-2.363v-5.91c0-1.305-1.085-2.363-2.424-2.363h-12.121V90.364c0-1.306-1.086-2.364-2.425-2.364h-6.06c-1.34 0-2.425 1.058-2.425 2.364v11.818h-12.12c-1.34 0-2.425 1.058-2.425 2.363v5.91c0 1.305 1.085 2.363 2.424 2.363h12.121zM60.016 4.965c-4.781-2.76-10.897-1.118-13.656 3.66L5.553 79.305A9.993 9.993 0 009.21 92.963l51.04 29.468c4.78 2.76 10.897 1.118 13.655-3.66l40.808-70.681a9.993 9.993 0 00-3.658-13.656L60.016 4.965zm-3.567 27.963a6 6 0 106-10.393 6 6 0 00-6 10.393zm31.697 17.928a6 6 0 106-10.392 6 6 0 00-6 10.392z\"/><text class=\"tc-fill-background\" font-family=\"Helvetica\" font-size=\"47.172\" font-weight=\"bold\" transform=\"rotate(30 25.742 95.82)\"><tspan x=\"42\" y=\"77.485\" text-anchor=\"middle\"><<now \"DD\">></tspan></text></g></svg>"
        },
        "$:/core/images/opacity": {
            "title": "$:/core/images/opacity",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-opacity tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M102.362 65a51.595 51.595 0 01-1.942 6H82.584a35.867 35.867 0 002.997-6h16.78zm.472-2c.423-1.961.734-3.963.929-6H87.656a35.78 35.78 0 01-1.368 6h16.546zm-3.249 10a51.847 51.847 0 01-3.135 6H75.812a36.205 36.205 0 005.432-6h18.341zm-4.416 8c-1.424 2.116-3 4.12-4.71 6H60.46a35.843 35.843 0 0012.874-6h21.834zm-7.513-34h16.107C101.247 20.627 79.033 0 52 0 23.281 0 0 23.281 0 52c0 25.228 17.965 46.26 41.8 51h20.4a51.66 51.66 0 0015.875-6H39v-2h42.25a52.257 52.257 0 007.288-6H39v-2h4.539C27.739 83.194 16 68.968 16 52c0-19.882 16.118-36 36-36 18.186 0 33.222 13.484 35.656 31zm.22 2h16.039a52.823 52.823 0 010 6H87.877a36.483 36.483 0 000-6z\"/><path d=\"M76 128c28.719 0 52-23.281 52-52s-23.281-52-52-52-52 23.281-52 52 23.281 52 52 52zm0-16c19.882 0 36-16.118 36-36S95.882 40 76 40 40 56.118 40 76s16.118 36 36 36z\"/><path d=\"M37 58h53v4H37v-4zm3-8h53v4H40v-4zm0-8h53v4H40v-4zm-8 24h53v4H32v-4zm-2 8h53v4H30v-4zm-3 8h53v4H27v-4z\"/></g></svg>"
        },
        "$:/core/images/open-window": {
            "title": "$:/core/images/open-window",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-open-window tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M16 112h88.994c3.87 0 7.006 3.59 7.006 8 0 4.418-3.142 8-7.006 8H7.006C3.136 128 0 124.41 0 120a9.321 9.321 0 010-.01V24.01C0 19.586 3.59 16 8 16c4.418 0 8 3.584 8 8.01V112z\"/><path d=\"M96 43.196V56a8 8 0 1016 0V24c0-4.41-3.585-8-8.007-8H72.007C67.588 16 64 19.582 64 24c0 4.41 3.585 8 8.007 8H84.57l-36.3 36.299a8 8 0 00-.001 11.316c3.117 3.117 8.19 3.123 11.316-.003L96 43.196zM32 7.999C32 3.581 35.588 0 40 0h80c4.419 0 8 3.588 8 8v80c0 4.419-3.588 8-8 8H40c-4.419 0-8-3.588-8-8V8z\"/></g></svg>"
        },
        "$:/core/images/options-button": {
            "title": "$:/core/images/options-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-options-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M110.488 76a47.712 47.712 0 01-5.134 12.384l6.724 6.724c3.123 3.123 3.132 8.192.011 11.313l-5.668 5.668c-3.12 3.12-8.186 3.117-11.313-.01l-6.724-6.725c-3.82 2.258-7.98 4-12.384 5.134v9.505c0 4.417-3.578 8.007-7.992 8.007h-8.016C55.58 128 52 124.415 52 119.993v-9.505a47.712 47.712 0 01-12.384-5.134l-6.724 6.725c-3.123 3.122-8.192 3.131-11.313.01l-5.668-5.668c-3.12-3.12-3.116-8.186.01-11.313l6.725-6.724c-2.257-3.82-4-7.98-5.134-12.384H8.007C3.591 76 0 72.422 0 68.01v-8.017C0 55.58 3.585 52 8.007 52h9.505a47.712 47.712 0 015.134-12.383l-6.724-6.725c-3.123-3.122-3.132-8.191-.011-11.312l5.668-5.669c3.12-3.12 8.186-3.116 11.313.01l6.724 6.725c3.82-2.257 7.98-4 12.384-5.134V8.007C52 3.591 55.578 0 59.992 0h8.016C72.42 0 76 3.585 76 8.007v9.505a47.712 47.712 0 0112.384 5.134l6.724-6.724c3.123-3.123 8.192-3.132 11.313-.01l5.668 5.668c3.12 3.12 3.116 8.186-.01 11.312l-6.725 6.725c2.257 3.82 4 7.979 5.134 12.383h9.505c4.416 0 8.007 3.578 8.007 7.992v8.017c0 4.411-3.585 7.991-8.007 7.991h-9.505zM64 96c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32z\"/></svg>"
        },
        "$:/core/images/paint": {
            "title": "$:/core/images/paint",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-paint tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M83.527 76.19C90.43 69.287 91.892 59 87.91 50.665l37.903-37.902c2.919-2.92 2.913-7.659 0-10.572a7.474 7.474 0 00-10.572 0L77.338 40.093c-8.335-3.982-18.622-2.521-25.526 4.383l31.715 31.715zm-2.643 2.644L49.169 47.119S8.506 81.243 0 80.282c0 0 3.782 5.592 6.827 8.039 14.024-5.69 37.326-24.6 37.326-24.6l.661.66S19.45 90.222 9.18 92.047c1.222 1.44 4.354 4.053 6.247 5.776 5.417-1.488 34.733-28.57 34.733-28.57l.661.66-32.407 31.022 5.285 5.286L56.106 75.2l.662.66s-27.864 30.536-28.684 32.432c0 0 6.032 6.853 7.569 7.824.702-2.836 27.884-33.485 27.884-33.485l.661.66s-20.597 23.755-24.964 36.732c3.21 3.549 7.5 5.137 10.926 6.298-2.19-11.817 30.724-47.487 30.724-47.487z\"/></svg>"
        },
        "$:/core/images/palette": {
            "title": "$:/core/images/palette",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-palette tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M80.247 39.182a93.52 93.52 0 00-16.228-1.4C28.662 37.781 0 57.131 0 81.002c0 9.642 4.676 18.546 12.58 25.735C23.504 91.19 26.34 72.395 36.89 63.562c15.183-12.713 26.538-7.828 26.538-7.828l16.82-16.552zm26.535 9.655c13.049 7.913 21.257 19.392 21.257 32.166 0 9.35.519 17.411-11.874 25.08-10.797 6.681-3.824-6.536-11.844-10.898s-19.946 1.308-18.213 7.906c3.2 12.181 19.422 11.455 6.314 16.658-13.107 5.202-18.202 4.476-28.403 4.476-7.821 0-15.315-.947-22.243-2.68 9.844-4.197 27.88-12.539 33.354-19.456C82.788 92.409 87.37 80 83.324 72.484c-.194-.359 11.215-11.668 23.458-23.647zM1.134 123.867l-.66.002c33.479-14.94 22.161-64.226 58.818-64.226.317 1.418.644 2.944 1.062 4.494-25.907-4.166-23.567 48.031-59.22 59.73zm.713-.007c38.872-.506 78.152-22.347 78.152-44.813-9.27 0-14.073-3.48-16.816-7.942-16.597-7.003-30.365 45.715-61.336 52.755zm65.351-64.008c-4.45 4.115 4.886 16.433 11.318 11.318l45.27-45.27c11.317-11.318 0-22.635-11.318-11.318-11.317 11.318-33.518 34.405-45.27 45.27z\"/></svg>"
        },
        "$:/core/images/permalink-button": {
            "title": "$:/core/images/permalink-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-permalink-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M80.483 48l-7.387 32h-25.58l7.388-32h25.58zm3.694-16l5.624-24.358c.993-4.303 5.29-6.996 9.596-6.002 4.296.992 6.988 5.293 5.994 9.602L100.598 32h3.403c4.41 0 7.999 3.582 7.999 8 0 4.41-3.581 8-8 8h-7.096l-7.387 32H104c4.41 0 7.999 3.582 7.999 8 0 4.41-3.581 8-8 8H85.824l-5.624 24.358c-.993 4.303-5.29 6.996-9.596 6.002-4.296-.992-6.988-5.293-5.994-9.602L69.402 96h-25.58L38.2 120.358c-.993 4.303-5.29 6.996-9.596 6.002-4.296-.992-6.988-5.293-5.994-9.602L27.402 96h-3.403C19.59 96 16 92.418 16 88c0-4.41 3.581-8 8-8h7.096l7.387-32H24C19.59 48 16 44.418 16 40c0-4.41 3.581-8 8-8h18.177l5.624-24.358c.993-4.303 5.29-6.996 9.596-6.002 4.296.992 6.988 5.293 5.994 9.602L58.598 32h25.58z\"/></svg>"
        },
        "$:/core/images/permaview-button": {
            "title": "$:/core/images/permaview-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-permaview-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M81.483 48l-1.846 8h-5.58l1.847-8h5.58zm3.694-16l5.624-24.358c.993-4.303 5.29-6.996 9.596-6.002 4.296.992 6.988 5.293 5.994 9.602L101.598 32h2.403c4.41 0 7.999 3.582 7.999 8 0 4.41-3.581 8-8 8h-6.096l-1.847 8h7.944c4.41 0 7.999 3.582 7.999 8 0 4.41-3.581 8-8 8H92.364l-1.846 8H104c4.41 0 7.999 3.582 7.999 8 0 4.41-3.581 8-8 8H86.824l-5.624 24.358c-.993 4.303-5.29 6.996-9.596 6.002-4.296-.992-6.988-5.293-5.994-9.602L70.402 96h-5.58L59.2 120.358c-.993 4.303-5.29 6.996-9.596 6.002-4.296-.992-6.988-5.293-5.994-9.602L48.402 96h-5.58L37.2 120.358c-.993 4.303-5.29 6.996-9.596 6.002-4.296-.992-6.988-5.293-5.994-9.602L26.402 96h-2.403C19.59 96 16 92.418 16 88c0-4.41 3.581-8 8-8h6.096l1.847-8h-7.944C19.59 72 16 68.418 16 64c0-4.41 3.581-8 8-8h11.637l1.846-8H24C19.59 48 16 44.418 16 40c0-4.41 3.581-8 8-8h17.177l5.624-24.358c.993-4.303 5.29-6.996 9.596-6.002 4.296.992 6.988 5.293 5.994 9.602L57.598 32h5.58L68.8 7.642c.993-4.303 5.29-6.996 9.596-6.002 4.296.992 6.988 5.293 5.994 9.602L79.598 32h5.58zM53.904 48l-1.847 8h5.58l1.846-8h-5.579zm22.039 24l-1.847 8h-5.58l1.847-8h5.58zm-27.58 0l-1.846 8h5.579l1.847-8h-5.58z\"/></svg>"
        },
        "$:/core/images/picture": {
            "title": "$:/core/images/picture",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-picture tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M112 68.233v-48.23A4.001 4.001 0 00107.997 16H20.003A4.001 4.001 0 0016 20.003v38.31l9.241-14.593c2.8-4.422 9.023-5.008 12.6-1.186l18.247 20.613 13.687-6.407a8 8 0 018.903 1.492 264.97 264.97 0 002.92 2.739 249.44 249.44 0 006.798 6.066 166.5 166.5 0 002.106 1.778c2.108 1.747 3.967 3.188 5.482 4.237.748.518 1.383.92 2.044 1.33.444.117 1.046.144 1.809.05 1.873-.233 4.238-1.144 6.723-2.547a36.016 36.016 0 003.205-2.044c.558-.4.93-.686 1.07-.802.376-.31.765-.577 1.165-.806zM0 8.007A8.01 8.01 0 018.007 0h111.986A8.01 8.01 0 01128 8.007v111.986a8.01 8.01 0 01-8.007 8.007H8.007A8.01 8.01 0 010 119.993V8.007zM95 42a8 8 0 100-16 8 8 0 000 16zM32 76c15.859 4.83 20.035 7.244 20.035 12S32 95.471 32 102.347c0 6.876 1.285 4.99 1.285 9.653H68s-13.685-6.625-13.685-10.8c0-7.665 10.615-8.34 10.615-13.2 0-7.357-14.078-8.833-32.93-12z\"/></svg>"
        },
        "$:/core/images/plugin-generic-language": {
            "title": "$:/core/images/plugin-generic-language",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M61.207 68.137c-4.324 2.795-6.999 6.656-6.999 10.921 0 7.906 9.19 14.424 21.042 15.336 2.162 3.902 8.598 6.785 16.318 7.01-5.126-1.125-9.117-3.742-10.62-7.01C92.805 93.487 102 86.967 102 79.059c0-8.53-10.699-15.445-23.896-15.445-6.599 0-12.572 1.729-16.897 4.524zm12.794-14.158c-4.324 2.795-10.298 4.524-16.897 4.524-2.619 0-5.14-.272-7.497-.775-3.312 2.25-8.383 3.69-14.067 3.69l-.255-.002c4.119-.892 7.511-2.747 9.478-5.13-6.925-2.704-11.555-7.617-11.555-13.228 0-8.53 10.699-15.445 23.896-15.445C70.301 27.613 81 34.528 81 43.058c0 4.265-2.675 8.126-6.999 10.921zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z\"/></svg>"
        },
        "$:/core/images/plugin-generic-plugin": {
            "title": "$:/core/images/plugin-generic-plugin",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M40.397 76.446V95.34h14.12l-.001-.005a6.912 6.912 0 005.364-11.593l.046-.023a6.912 6.912 0 119.979.526l.086.055a6.914 6.914 0 004.408 10.948l-.023.092h21.32V75.568l-.15.038a6.912 6.912 0 00-11.593-5.364l-.022-.046a6.912 6.912 0 11.526-9.979l.055-.086a6.914 6.914 0 0010.948-4.408c.079.018.158.038.236.059v-15.74h-21.32l.023-.094a6.914 6.914 0 01-4.408-10.947 10.23 10.23 0 00-.086-.055 6.912 6.912 0 10-9.979-.526l-.046.023a6.912 6.912 0 01-5.364 11.593l.001.005h-14.12v12.847A6.912 6.912 0 0129.5 59.843l-.054.086a6.912 6.912 0 10-.526 9.979l.023.046a6.912 6.912 0 0111.455 6.492zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z\"/></svg>"
        },
        "$:/core/images/plugin-generic-theme": {
            "title": "$:/core/images/plugin-generic-theme",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M29.408 91.472L51.469 69.41l-.004-.005a2.22 2.22 0 01.004-3.146c.87-.87 2.281-.872 3.147-.005l9.465 9.464a2.22 2.22 0 01-.005 3.147c-.87.87-2.28.871-3.147.005l-.005-.005-22.061 22.062a6.686 6.686 0 11-9.455-9.455zM60.802 66.38c-2.436-2.704-4.465-5.091-5.817-6.869-6.855-9.014-10.313-4.268-14.226 0-3.913 4.268 1.03 7.726-2.683 10.741-3.713 3.015-3.484 4.06-9.752-1.455-6.267-5.516-6.7-7.034-3.823-10.181 2.877-3.147 5.281 1.808 11.159-3.785 5.877-5.593.94-10.55.94-10.55s12.237-25.014 28.588-23.167c16.351 1.848-6.186-2.392-11.792 17.226-2.4 8.4.447 6.42 4.998 9.968 1.394 1.086 6.03 4.401 11.794 8.685l20.677-20.676 1.615-4.766 7.84-4.689 3.151 3.152-4.688 7.84-4.766 1.615-20.224 20.223c12.663 9.547 28.312 22.146 28.312 26.709 0 7.217-3.071 11.526-9.535 9.164-4.693-1.715-18.768-15.192-28.753-25.897l-2.893 2.893-3.151-3.152 3.029-3.029zM63.953 0l54.56 32v64l-54.56 32-54.56-32V32l54.56-32z\"/></svg>"
        },
        "$:/core/images/preview-closed": {
            "title": "$:/core/images/preview-closed",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-preview-closed tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M.088 64a7.144 7.144 0 001.378 5.458C16.246 88.818 39.17 100.414 64 100.414c24.83 0 47.753-11.596 62.534-30.956A7.144 7.144 0 00127.912 64C110.582 78.416 88.304 87.086 64 87.086 39.696 87.086 17.418 78.416.088 64z\"/><rect width=\"4\" height=\"16\" x=\"62\" y=\"96\" rx=\"4\"/><rect width=\"4\" height=\"16\" x=\"78\" y=\"93\" rx=\"4\" transform=\"rotate(-5 80 101)\"/><rect width=\"4\" height=\"16\" x=\"46\" y=\"93\" rx=\"4\" transform=\"rotate(5 48 101)\"/><rect width=\"4\" height=\"16\" x=\"30\" y=\"88\" rx=\"4\" transform=\"rotate(10 32 96)\"/><rect width=\"4\" height=\"16\" x=\"94\" y=\"88\" rx=\"4\" transform=\"rotate(-10 96 96)\"/><rect width=\"4\" height=\"16\" x=\"110\" y=\"80\" rx=\"4\" transform=\"rotate(-20 112 88)\"/><rect width=\"4\" height=\"16\" x=\"14\" y=\"80\" rx=\"4\" transform=\"rotate(20 16 88)\"/></g></svg>"
        },
        "$:/core/images/preview-open": {
            "title": "$:/core/images/preview-open",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-preview-open tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M64.11 99.588c-24.83 0-47.754-11.596-62.534-30.957a7.148 7.148 0 010-8.675C16.356 40.596 39.28 29 64.11 29c24.83 0 47.753 11.596 62.534 30.956a7.148 7.148 0 010 8.675c-14.78 19.36-37.703 30.957-62.534 30.957zm46.104-32.007c1.44-1.524 1.44-3.638 0-5.162C99.326 50.9 82.439 44 64.147 44S28.968 50.9 18.08 62.42c-1.44 1.523-1.44 3.637 0 5.16C28.968 79.1 45.855 86 64.147 86s35.179-6.9 46.067-18.42z\"/><path d=\"M63.5 88C76.479 88 87 77.479 87 64.5S76.479 41 63.5 41 40 51.521 40 64.5 50.521 88 63.5 88z\"/></g></svg>"
        },
        "$:/core/images/print-button": {
            "title": "$:/core/images/print-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-print-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M112 71V30.5h-.032c-.035-2-.816-3.99-2.343-5.516L86.998 2.357A7.978 7.978 0 0081 .02V0H24a8 8 0 00-8 8v63h8V8h57v14.5c0 4.422 3.582 8 8 8h15V71h8z\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"36\" rx=\"4\"/><rect width=\"64\" height=\"8\" x=\"32\" y=\"52\" rx=\"4\"/><rect width=\"40\" height=\"8\" x=\"32\" y=\"20\" rx=\"4\"/><path d=\"M0 80.005C0 71.165 7.156 64 16 64h96c8.836 0 16 7.155 16 16.005v31.99c0 8.84-7.156 16.005-16 16.005H16c-8.836 0-16-7.155-16-16.005v-31.99zM104 96a8 8 0 100-16 8 8 0 000 16z\"/></g></svg>"
        },
        "$:/core/images/quote": {
            "title": "$:/core/images/quote",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-quote tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M51.219 117.713V62.199H27.427c0-8.891 1.683-16.401 5.047-22.53 3.365-6.127 9.613-10.754 18.745-13.878V2c-7.45.961-14.36 3.184-20.728 6.669-6.368 3.484-11.835 7.87-16.401 13.157C9.524 27.113 5.98 33.241 3.456 40.21.933 47.18-.21 54.63.03 62.56v55.153H51.22zm76.781 0V62.199h-23.791c0-8.891 1.682-16.401 5.046-22.53 3.365-6.127 9.613-10.754 18.745-13.878V2c-7.45.961-14.359 3.184-20.727 6.669-6.369 3.484-11.836 7.87-16.402 13.157-4.566 5.287-8.11 11.415-10.634 18.384-2.523 6.97-3.665 14.42-3.424 22.35v55.153H128z\"/></svg>"
        },
        "$:/core/images/refresh-button": {
            "title": "$:/core/images/refresh-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-refresh-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M106.369 39.433c10.16 20.879 6.57 46.764-10.771 64.106-21.87 21.87-57.327 21.87-79.196 0-21.87-21.87-21.87-57.326 0-79.196a8 8 0 1111.314 11.314c-15.621 15.62-15.621 40.947 0 56.568 15.62 15.621 40.947 15.621 56.568 0C97.72 78.79 99.6 58.175 89.924 42.73l-6.44 12.264a8 8 0 11-14.166-7.437L84.435 18.76a8 8 0 0110.838-3.345l28.873 15.345a8 8 0 11-7.51 14.129l-10.267-5.457zm-8.222-12.368c-.167-.19-.336-.38-.506-.57l.96-.296-.454.866z\"/></svg>"
        },
        "$:/core/images/right-arrow": {
            "title": "$:/core/images/right-arrow",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-right-arrow tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M99.069 64.173c0 2.027-.77 4.054-2.316 5.6l-55.98 55.98a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196l50.382-50.382-50.382-50.382a7.92 7.92 0 010-11.195c3.086-3.085 8.104-3.092 11.196 0l55.98 55.98a7.892 7.892 0 012.316 5.595z\"/></svg>"
        },
        "$:/core/images/rotate-left": {
            "title": "$:/core/images/rotate-left",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-rotate-left tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"32\" height=\"80\" rx=\"8\"/><rect width=\"80\" height=\"32\" x=\"48\" y=\"96\" rx=\"8\"/><path d=\"M61.32 36.65c19.743 2.45 35.023 19.287 35.023 39.693a4 4 0 01-8 0c0-15.663-11.254-28.698-26.117-31.46l3.916 3.916a4 4 0 11-5.657 5.657L49.172 43.142a4 4 0 010-5.657l11.313-11.313a4 4 0 115.657 5.656l-4.821 4.822z\"/></g></svg>"
        },
        "$:/core/images/save-button": {
            "title": "$:/core/images/save-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-save-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M120.783 34.33c4.641 8.862 7.266 18.948 7.266 29.646 0 35.347-28.653 64-64 64-35.346 0-64-28.653-64-64 0-35.346 28.654-64 64-64 18.808 0 35.72 8.113 47.43 21.03l2.68-2.68c3.13-3.13 8.197-3.132 11.321-.008 3.118 3.118 3.121 8.193-.007 11.32l-4.69 4.691zm-12.058 12.058a47.876 47.876 0 013.324 17.588c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48c14.39 0 27.3 6.332 36.098 16.362L58.941 73.544 41.976 56.578c-3.127-3.127-8.201-3.123-11.32-.005-3.123 3.124-3.119 8.194.006 11.319l22.617 22.617a7.992 7.992 0 005.659 2.347c2.05 0 4.101-.783 5.667-2.349l44.12-44.12z\"/></svg>"
        },
        "$:/core/images/size": {
            "title": "$:/core/images/size",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-size tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M92.343 26l-9.171 9.172a4 4 0 105.656 5.656l16-16a4 4 0 000-5.656l-16-16a4 4 0 10-5.656 5.656L92.343 18H22a4 4 0 00-4 4v70.343l-9.172-9.171a4 4 0 10-5.656 5.656l16 16a4 4 0 005.656 0l16-16a4 4 0 10-5.656-5.656L26 92.343V22l-4 4h70.343zM112 52v64l4-4H52a4 4 0 100 8h64a4 4 0 004-4V52a4 4 0 10-8 0z\"/></svg>"
        },
        "$:/core/images/spiral": {
            "title": "$:/core/images/spiral",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-spiral tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M64.534 68.348c3.39 0 6.097-2.62 6.476-5.968l-4.755-.538 4.75.583c.377-3.07-1.194-6.054-3.89-7.78-2.757-1.773-6.34-2.01-9.566-.7-3.46 1.403-6.14 4.392-7.35 8.148l-.01.026c-1.3 4.08-.72 8.64 1.58 12.52 2.5 4.2 6.77 7.2 11.76 8.27 5.37 1.15 11.11-.05 15.83-3.31 5.04-3.51 8.46-9.02 9.45-15.3 1.05-6.7-.72-13.63-4.92-19.19l.02.02c-4.42-5.93-11.2-9.82-18.78-10.78-7.96-1.01-16.13 1.31-22.59 6.43-6.81 5.39-11.18 13.41-12.11 22.26-.98 9.27 1.87 18.65 7.93 26.02 6.32 7.69 15.6 12.56 25.74 13.48 10.54.96 21.15-2.42 29.45-9.4l.01-.01c8.58-7.25 13.94-17.78 14.86-29.21.94-11.84-2.96-23.69-10.86-32.9-8.19-9.5-19.95-15.36-32.69-16.27-13.16-.94-26.24 3.49-36.34 12.34l.01-.01c-10.41 9.08-16.78 22.1-17.68 36.15-.93 14.44 4.03 28.77 13.79 39.78 10.03 11.32 24.28 18.2 39.6 19.09 15.73.92 31.31-4.56 43.24-15.234 12.23-10.954 19.61-26.44 20.5-43.074a4.785 4.785 0 00-4.52-5.03 4.778 4.778 0 00-5.03 4.52c-.75 14.1-7 27.2-17.33 36.45-10.03 8.98-23.11 13.58-36.3 12.81-12.79-.75-24.67-6.48-33-15.89-8.07-9.11-12.17-20.94-11.41-32.827.74-11.52 5.942-22.15 14.43-29.54l.01-.01c8.18-7.17 18.74-10.75 29.35-9.998 10.21.726 19.6 5.41 26.11 12.96 6.24 7.273 9.32 16.61 8.573 25.894-.718 8.9-4.88 17.064-11.504 22.66l.01-.007c-6.36 5.342-14.44 7.92-22.425 7.19-7.604-.68-14.52-4.314-19.21-10.027-4.44-5.4-6.517-12.23-5.806-18.94.67-6.3 3.76-11.977 8.54-15.766 4.46-3.54 10.05-5.128 15.44-4.44 5.03.63 9.46 3.18 12.32 7.01l.02.024c2.65 3.5 3.75 7.814 3.1 11.92-.59 3.71-2.58 6.925-5.45 8.924-2.56 1.767-5.61 2.403-8.38 1.81-2.42-.516-4.42-1.92-5.53-3.79-.93-1.56-1.15-3.3-.69-4.75l-4.56-1.446L59.325 65c.36-1.12 1.068-1.905 1.84-2.22.25-.103.48-.14.668-.13.06.006.11.015.14.025.01 0 .01 0-.01-.01a1.047 1.047 0 01-.264-.332c-.15-.29-.23-.678-.18-1.11l-.005.04c.15-1.332 1.38-2.523 3.035-2.523-2.65 0-4.79 2.144-4.79 4.787s2.14 4.785 4.78 4.785z\"/></svg>"
        },
        "$:/core/images/stamp": {
            "title": "$:/core/images/stamp",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-stamp tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M49.733 64H16.01C11.584 64 8 67.583 8 72.003V97h112V72.003A8 8 0 00111.99 64H78.267A22.813 22.813 0 0175.5 53.077c0-6.475 2.687-12.324 7.009-16.497A22.818 22.818 0 0087 22.952C87 10.276 76.703 0 64 0S41 10.276 41 22.952c0 5.103 1.669 9.817 4.491 13.628 4.322 4.173 7.009 10.022 7.009 16.497 0 3.954-1.002 7.675-2.767 10.923zM8 104h112v8H8v-8z\"/></svg>"
        },
        "$:/core/images/star-filled": {
            "title": "$:/core/images/star-filled",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-star-filled tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M61.836 96.823l37.327 27.287c2.72 1.99 6.379-.69 5.343-3.912L90.29 75.988l-1.26 3.91 37.285-27.345c2.718-1.993 1.32-6.327-2.041-6.33l-46.113-.036 3.3 2.416L67.176 4.416c-1.04-3.221-5.563-3.221-6.604 0L46.29 48.603l3.3-2.416-46.113.036c-3.362.003-4.759 4.337-2.04 6.33L38.72 79.898l-1.26-3.91-14.216 44.21c-1.036 3.223 2.622 5.901 5.343 3.912l37.326-27.287h-4.078z\"/></svg>"
        },
        "$:/core/images/storyview-classic": {
            "title": "$:/core/images/storyview-classic",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-storyview-classic tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M8.007 0A8.01 8.01 0 000 8.007v111.986A8.01 8.01 0 008.007 128h111.986a8.01 8.01 0 008.007-8.007V8.007A8.01 8.01 0 00119.993 0H8.007zm15.992 16C19.581 16 16 19.578 16 23.992v16.016C16 44.422 19.588 48 24 48h80c4.419 0 8-3.578 8-7.992V23.992c0-4.414-3.588-7.992-8-7.992H24zm0 48C19.581 64 16 67.59 16 72c0 4.418 3.588 8 8 8h80c4.419 0 8-3.59 8-8 0-4.418-3.588-8-8-8H24zm0 32C19.581 96 16 99.59 16 104c0 4.418 3.588 8 8 8h80c4.419 0 8-3.59 8-8 0-4.418-3.588-8-8-8H24z\"/></svg>"
        },
        "$:/core/images/storyview-pop": {
            "title": "$:/core/images/storyview-pop",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-storyview-pop tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M8.007 0A8.01 8.01 0 000 8.007v111.986A8.01 8.01 0 008.007 128h111.986a8.01 8.01 0 008.007-8.007V8.007A8.01 8.01 0 00119.993 0H8.007zm15.992 16C19.581 16 16 19.578 16 23.992v16.016C16 44.422 19.588 48 24 48h80c4.419 0 8-3.578 8-7.992V23.992c0-4.414-3.588-7.992-8-7.992H24zm-7.99 40C11.587 56 8 59.578 8 63.992v16.016C8 84.422 11.584 88 16.01 88h95.98c4.424 0 8.01-3.578 8.01-7.992V63.992c0-4.414-3.584-7.992-8.01-7.992H16.01zM24 96C19.581 96 16 99.59 16 104c0 4.418 3.588 8 8 8h80c4.419 0 8-3.59 8-8 0-4.418-3.588-8-8-8H24zm0-32C19.581 64 16 67.59 16 72c0 4.418 3.588 8 8 8h80c4.419 0 8-3.59 8-8 0-4.418-3.588-8-8-8H24z\"/></svg>"
        },
        "$:/core/images/storyview-zoomin": {
            "title": "$:/core/images/storyview-zoomin",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-storyview-zoomin tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M8.007 0A8.01 8.01 0 000 8.007v111.986A8.01 8.01 0 008.007 128h111.986a8.01 8.01 0 008.007-8.007V8.007A8.01 8.01 0 00119.993 0H8.007zm15.992 16A8 8 0 0016 24.009V71.99C16 76.414 19.588 80 24 80h80a8 8 0 008-8.009V24.01c0-4.423-3.588-8.009-8-8.009H24z\"/></svg>"
        },
        "$:/core/images/strikethrough": {
            "title": "$:/core/images/strikethrough",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-strikethrough tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M92.794 38.726h15.422c-.229-6.74-1.514-12.538-3.856-17.393-2.342-4.855-5.54-8.881-9.596-12.08-4.055-3.199-8.767-5.54-14.136-7.025C75.258.743 69.433 0 63.15 0a62.76 62.76 0 00-16.364 2.142C41.474 3.57 36.733 5.74 32.564 8.653c-4.17 2.913-7.511 6.626-10.025 11.138-2.513 4.512-3.77 9.853-3.77 16.022 0 5.597 1.115 10.252 3.342 13.965 2.228 3.712 5.198 6.74 8.91 9.081 3.713 2.342 7.911 4.227 12.595 5.655a194.641 194.641 0 0014.308 3.77c4.855 1.085 9.624 2.142 14.308 3.17 4.683 1.028 8.881 2.37 12.594 4.027 3.713 1.656 6.683 3.798 8.91 6.425 2.228 2.628 3.342 6.055 3.342 10.281 0 4.456-.914 8.111-2.742 10.967a19.953 19.953 0 01-7.197 6.768c-2.97 1.657-6.311 2.828-10.024 3.513a60.771 60.771 0 01-11.052 1.028c-4.57 0-9.025-.571-13.366-1.713-4.34-1.143-8.139-2.913-11.394-5.312-3.256-2.4-5.884-5.455-7.883-9.168-1.999-3.712-2.998-8.139-2.998-13.28H15c0 7.426 1.342 13.852 4.027 19.278 2.684 5.426 6.34 9.881 10.966 13.365 4.627 3.484 9.996 6.083 16.107 7.797 6.112 1.713 12.595 2.57 19.449 2.57 5.597 0 11.223-.657 16.878-1.97 5.655-1.314 10.767-3.428 15.336-6.34 4.57-2.914 8.31-6.683 11.224-11.31 2.913-4.626 4.37-10.195 4.37-16.707 0-6.054-1.115-11.08-3.342-15.079-2.228-3.998-5.198-7.31-8.91-9.938-3.713-2.627-7.911-4.712-12.595-6.254a170.83 170.83 0 00-14.308-4.027 549.669 549.669 0 00-14.308-3.17c-4.683-.971-8.881-2.2-12.594-3.684-3.713-1.485-6.683-3.399-8.91-5.74-2.228-2.342-3.342-5.398-3.342-9.168 0-3.998.771-7.34 2.313-10.024 1.543-2.685 3.599-4.826 6.17-6.426 2.57-1.599 5.51-2.741 8.824-3.427a49.767 49.767 0 0110.11-1.028c8.453 0 15.393 1.97 20.819 5.912 5.426 3.94 8.596 10.31 9.51 19.106z\"/><path d=\"M5 54h118v16H5z\"/></g></svg>"
        },
        "$:/core/images/subscript": {
            "title": "$:/core/images/subscript",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-subscript tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M2.272 16h19.91l21.649 33.675L66.414 16h18.708L53.585 61.969l33.809 49.443H67.082L43.296 74.93l-24.187 36.48H0L33.808 61.97 2.272 16zM127.91 128.412H85.328c.059-5.168 1.306-9.681 3.741-13.542 2.435-3.86 5.761-7.216 9.978-10.066a112.388 112.388 0 016.325-4.321 50.09 50.09 0 006.058-4.499c1.841-1.603 3.356-3.34 4.543-5.211 1.188-1.871 1.812-4.024 1.871-6.46 0-1.128-.133-2.33-.4-3.607a9.545 9.545 0 00-1.56-3.564c-.772-1.098-1.84-2.019-3.207-2.761-1.366-.743-3.148-1.114-5.345-1.114-2.02 0-3.697.4-5.033 1.203-1.337.801-2.406 1.9-3.208 3.296-.801 1.396-1.395 3.044-1.781 4.944-.386 1.9-.609 3.95-.668 6.147H86.486c0-3.445.46-6.637 1.38-9.577.921-2.94 2.302-5.478 4.143-7.617 1.841-2.138 4.083-3.815 6.726-5.033 2.643-1.217 5.716-1.826 9.22-1.826 3.802 0 6.979.623 9.533 1.87 2.554 1.248 4.617 2.822 6.191 4.722 1.574 1.9 2.688 3.965 3.341 6.192.653 2.227.98 4.35.98 6.37 0 2.494-.386 4.75-1.158 6.77a21.803 21.803 0 01-3.118 5.568 31.516 31.516 0 01-4.454 4.677 66.788 66.788 0 01-5.167 4.009 139.198 139.198 0 01-5.346 3.563 79.237 79.237 0 00-4.944 3.386c-1.514 1.128-2.836 2.3-3.964 3.518-1.129 1.218-1.9 2.51-2.317 3.876h30.379v9.087z\"/></svg>"
        },
        "$:/core/images/superscript": {
            "title": "$:/core/images/superscript",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-superscript tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M2.272 16h19.91l21.649 33.675L66.414 16h18.708L53.585 61.969l33.809 49.443H67.082L43.296 74.93l-24.187 36.48H0L33.808 61.97 2.272 16zM127.91 63.412H85.328c.059-5.168 1.306-9.681 3.741-13.542 2.435-3.86 5.761-7.216 9.978-10.066a112.388 112.388 0 016.325-4.321 50.09 50.09 0 006.058-4.499c1.841-1.603 3.356-3.34 4.543-5.211 1.188-1.871 1.812-4.024 1.871-6.46 0-1.128-.133-2.33-.4-3.607a9.545 9.545 0 00-1.56-3.564c-.772-1.098-1.84-2.019-3.207-2.761-1.366-.743-3.148-1.114-5.345-1.114-2.02 0-3.697.4-5.033 1.203-1.337.801-2.406 1.9-3.208 3.296-.801 1.396-1.395 3.044-1.781 4.944-.386 1.9-.609 3.95-.668 6.147H86.486c0-3.445.46-6.637 1.38-9.577.921-2.94 2.302-5.478 4.143-7.617 1.841-2.138 4.083-3.815 6.726-5.033 2.643-1.217 5.716-1.826 9.22-1.826 3.802 0 6.979.623 9.533 1.87 2.554 1.248 4.617 2.822 6.191 4.722 1.574 1.9 2.688 3.965 3.341 6.192.653 2.227.98 4.35.98 6.37 0 2.494-.386 4.75-1.158 6.77a21.803 21.803 0 01-3.118 5.568 31.516 31.516 0 01-4.454 4.677 66.788 66.788 0 01-5.167 4.009 139.198 139.198 0 01-5.346 3.563 79.237 79.237 0 00-4.944 3.386c-1.514 1.128-2.836 2.3-3.964 3.518-1.129 1.218-1.9 2.51-2.317 3.876h30.379v9.087z\"/></svg>"
        },
        "$:/core/images/tag-button": {
            "title": "$:/core/images/tag-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-tag-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M18.164 47.66l.004 4.105c.003 3.823 2.19 9.097 4.885 11.792l61.85 61.85c2.697 2.697 7.068 2.69 9.769-.01L125.767 94.3a6.903 6.903 0 00.01-9.77L63.928 22.683c-2.697-2.697-7.976-4.88-11.796-4.881l-27.076-.007a6.902 6.902 0 00-6.91 6.91l.008 9.96.287.033c3.73.411 8.489-.044 13.365-1.153a9.702 9.702 0 0111.14-3.662l.291-.13.128.285a9.7 9.7 0 013.3 2.17c3.796 3.796 3.801 9.945.012 13.734-3.618 3.618-9.386 3.777-13.204.482-5.365 1.122-10.674 1.596-15.309 1.237z\"/><path d=\"M47.633 39.532l.023.051c-9.689 4.356-21.584 6.799-30.396 5.828C5.273 44.089-1.028 36.43 2.443 24.078 5.562 12.976 14.3 4.361 24.047 1.548c10.68-3.083 19.749 1.968 19.749 13.225h-8.623c0-4.859-3.078-6.573-8.735-4.94-6.91 1.995-13.392 8.383-15.694 16.577-1.915 6.818.417 9.653 7.46 10.43 7.126.785 17.531-1.352 25.917-5.121l.027.06.036-.017c1.76-.758 6.266 6.549 3.524 7.74a2.8 2.8 0 01-.075.03z\"/></g></svg>"
        },
        "$:/core/images/theme-button": {
            "title": "$:/core/images/theme-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-theme-button tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M55.854 66.945a122.626 122.626 0 01-3.9-4.819c-11.064-14.548-16.645-6.888-22.96 0-6.315 6.888 1.664 12.47-4.33 17.335-5.993 4.866-5.623 6.552-15.737-2.35-10.115-8.9-10.815-11.351-6.172-16.43 4.644-5.08 8.524 2.918 18.01-6.108 9.485-9.026 1.517-17.026 1.517-17.026S42.03-2.824 68.42.157c26.39 2.982-9.984-3.86-19.031 27.801-3.874 13.556.72 10.362 8.066 16.087 1.707 1.33 6.428 4.732 12.671 9.318-6.129 5.879-11.157 10.669-14.273 13.582zm11.641 12.947c16.013 17.036 37.742 37.726 45.117 40.42 10.432 3.813 15.388-3.141 15.388-14.79 0-7.151-23.83-26.542-43.924-41.769-7.408 7.156-13.376 12.953-16.58 16.139z\"/><path d=\"M11.069 109.828L46.31 74.587a3.56 3.56 0 115.037-5.032l15.098 15.098a3.56 3.56 0 11-5.032 5.037l-35.24 35.241c-4.171 4.17-10.933 4.17-15.104 0-4.17-4.17-4.17-10.933 0-15.103zM124.344 6.622l5.034 5.034-7.49 12.524-7.613 2.58L61.413 79.62l-5.034-5.034 52.861-52.862 2.58-7.614 12.524-7.49z\"/></g></svg>"
        },
        "$:/core/images/timestamp-off": {
            "title": "$:/core/images/timestamp-off",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-timestamp-off tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M58.25 11C26.08 11 0 37.082 0 69.25s26.08 58.25 58.25 58.25c32.175 0 58.25-26.082 58.25-58.25S90.425 11 58.25 11zm0 100.5C34.914 111.5 16 92.586 16 69.25 16 45.92 34.914 27 58.25 27s42.25 18.92 42.25 42.25c0 23.336-18.914 42.25-42.25 42.25zM49.704 10a5 5 0 010-10H66.69a5 5 0 015 5c.006 2.757-2.238 5-5 5H49.705z\"/><path d=\"M58.25 35.88c-18.777 0-33.998 15.224-33.998 33.998 0 18.773 15.22 34.002 33.998 34.002 18.784 0 34.002-15.23 34.002-34.002 0-18.774-15.218-33.998-34.002-33.998zm-3.03 50.123H44.196v-34H55.22v34zm16.976 0H61.17v-34h11.025v34z\"/></g></svg>"
        },
        "$:/core/images/timestamp-on": {
            "title": "$:/core/images/timestamp-on",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-timestamp-on tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path d=\"M58.25 11C26.08 11 0 37.082 0 69.25s26.08 58.25 58.25 58.25c32.175 0 58.25-26.082 58.25-58.25S90.425 11 58.25 11zm0 100.5C34.914 111.5 16 92.586 16 69.25 16 45.92 34.914 27 58.25 27s42.25 18.92 42.25 42.25c0 23.336-18.914 42.25-42.25 42.25zM49.704 10a5 5 0 010-10H66.69a5 5 0 015 5c.006 2.757-2.238 5-5 5H49.705z\"/><path d=\"M13.41 27.178a5.005 5.005 0 01-7.045-.613 5.008 5.008 0 01.616-7.047l9.95-8.348a5 5 0 016.429 7.661l-9.95 8.348zm89.573 0a5.005 5.005 0 007.045-.613 5.008 5.008 0 00-.616-7.047l-9.95-8.348a5 5 0 00-6.428 7.661l9.95 8.348zM65.097 71.072c0 3.826-3.09 6.928-6.897 6.928-3.804.006-6.9-3.102-6.903-6.928 0 0 4.76-39.072 6.903-39.072s6.897 39.072 6.897 39.072z\"/></g></svg>"
        },
        "$:/core/images/tip": {
            "title": "$:/core/images/tip",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-tip tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M64 128.242c35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64 0 35.346 28.654 64 64 64zm11.936-36.789c-.624 4.129-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349C54.33 94.05 58.824 95.82 64 95.82c5.175 0 9.67-1.769 11.936-4.366zm0 4.492c-.624 4.13-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349 2.266 2.597 6.76 4.366 11.936 4.366 5.175 0 9.67-1.769 11.936-4.366zm0 4.456c-.624 4.129-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349 2.266 2.597 6.76 4.366 11.936 4.366 5.175 0 9.67-1.769 11.936-4.366zm0 4.492c-.624 4.13-5.73 7.349-11.936 7.349-6.206 0-11.312-3.22-11.936-7.349 2.266 2.597 6.76 4.366 11.936 4.366 5.175 0 9.67-1.769 11.936-4.366zM64.3 24.242c11.618 0 23.699 7.82 23.699 24.2S75.92 71.754 75.92 83.576c0 5.873-5.868 9.26-11.92 9.26s-12.027-3.006-12.027-9.26C51.973 71.147 40 65.47 40 48.442s12.683-24.2 24.301-24.2z\"/></svg>"
        },
        "$:/core/images/transcludify": {
            "title": "$:/core/images/transcludify",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-transcludify-button tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M0 59.482c.591 0 1.36-.089 2.306-.266a10.417 10.417 0 002.75-.932 6.762 6.762 0 002.306-1.907c.651-.828.976-1.863.976-3.104V35.709c0-2.01.414-3.74 1.242-5.19.828-1.448 1.833-2.66 3.016-3.636s2.425-1.7 3.726-2.173c1.3-.473 2.424-.71 3.37-.71h8.073v7.451h-4.88c-1.241 0-2.232.207-2.97.621-.74.414-1.302.932-1.686 1.552a4.909 4.909 0 00-.71 1.996c-.089.71-.133 1.39-.133 2.04v16.677c0 1.715-.325 3.134-.976 4.258-.65 1.123-1.434 2.025-2.35 2.705-.917.68-1.863 1.168-2.839 1.464-.976.296-1.818.473-2.528.532v.178c.71.059 1.552.207 2.528.443.976.237 1.922.68 2.839 1.33.916.651 1.7 1.583 2.35 2.795.65 1.212.976 2.853.976 4.923v16.144c0 .65.044 1.33.133 2.04.089.71.325 1.375.71 1.996.384.621.946 1.139 1.685 1.553.74.414 1.73.62 2.972.62h4.879v7.452h-8.073c-.946 0-2.07-.237-3.37-.71-1.301-.473-2.543-1.197-3.726-2.173-1.183-.976-2.188-2.188-3.016-3.637-.828-1.449-1.242-3.179-1.242-5.19V74.119c0-1.42-.325-2.572-.976-3.46-.65-.886-1.419-1.581-2.306-2.084a8.868 8.868 0 00-2.75-1.02C1.36 67.377.591 67.288 0 67.288v-7.806zm24.66 0c.591 0 1.36-.089 2.306-.266a10.417 10.417 0 002.75-.932 6.762 6.762 0 002.306-1.907c.65-.828.976-1.863.976-3.104V35.709c0-2.01.414-3.74 1.242-5.19.828-1.448 1.833-2.66 3.016-3.636s2.425-1.7 3.726-2.173c1.3-.473 2.424-.71 3.37-.71h8.073v7.451h-4.88c-1.241 0-2.232.207-2.97.621-.74.414-1.302.932-1.686 1.552a4.909 4.909 0 00-.71 1.996c-.089.71-.133 1.39-.133 2.04v16.677c0 1.715-.325 3.134-.976 4.258-.65 1.123-1.434 2.025-2.35 2.705-.917.68-1.863 1.168-2.839 1.464-.976.296-1.818.473-2.528.532v.178c.71.059 1.552.207 2.528.443.976.237 1.922.68 2.839 1.33.916.651 1.7 1.583 2.35 2.795.65 1.212.976 2.853.976 4.923v16.144c0 .65.044 1.33.133 2.04.089.71.325 1.375.71 1.996.384.621.946 1.139 1.685 1.553.74.414 1.73.62 2.972.62h4.879v7.452h-8.073c-.946 0-2.07-.237-3.37-.71-1.301-.473-2.543-1.197-3.726-2.173-1.183-.976-2.188-2.188-3.016-3.637-.828-1.449-1.242-3.179-1.242-5.19V74.119c0-1.42-.325-2.572-.976-3.46-.65-.886-1.419-1.581-2.306-2.084a8.868 8.868 0 00-2.75-1.02c-.946-.177-1.715-.266-2.306-.266v-7.806zm43.965-3.538L80.6 52.041l2.306 7.097-12.063 3.903 7.628 10.378-6.12 4.435-7.63-10.467-7.45 10.201-5.943-4.524 7.628-10.023-12.152-4.17 2.306-7.096 12.064 4.17V43.347h7.451v12.596zm34.425 11.344c-.65 0-1.449.089-2.395.266-.946.177-1.863.488-2.75.931a6.356 6.356 0 00-2.262 1.908c-.62.828-.931 1.862-.931 3.104v17.564c0 2.01-.414 3.74-1.242 5.189-.828 1.449-1.833 2.661-3.016 3.637s-2.425 1.7-3.726 2.173c-1.3.473-2.424.71-3.37.71h-8.073v-7.451h4.88c1.241 0 2.232-.207 2.97-.621.74-.414 1.302-.932 1.686-1.553a4.9 4.9 0 00.71-1.995c.089-.71.133-1.39.133-2.04V72.432c0-1.715.325-3.134.976-4.258.65-1.124 1.434-2.01 2.35-2.661.917-.65 1.863-1.124 2.839-1.42.976-.295 1.818-.502 2.528-.62v-.178c-.71-.059-1.552-.207-2.528-.443-.976-.237-1.922-.68-2.839-1.33-.916-.651-1.7-1.583-2.35-2.795-.65-1.212-.976-2.853-.976-4.923V37.66c0-.651-.044-1.331-.133-2.04a4.909 4.909 0 00-.71-1.997c-.384-.62-.946-1.138-1.685-1.552-.74-.414-1.73-.62-2.972-.62h-4.879V24h8.073c.946 0 2.07.237 3.37.71 1.301.473 2.543 1.197 3.726 2.173 1.183.976 2.188 2.188 3.016 3.637.828 1.449 1.242 3.178 1.242 5.189v16.943c0 1.419.31 2.572.931 3.46a6.897 6.897 0 002.262 2.084 8.868 8.868 0 002.75 1.02c.946.177 1.745.266 2.395.266v7.806zm24.66 0c-.65 0-1.449.089-2.395.266-.946.177-1.863.488-2.75.931a6.356 6.356 0 00-2.262 1.908c-.62.828-.931 1.862-.931 3.104v17.564c0 2.01-.414 3.74-1.242 5.189-.828 1.449-1.833 2.661-3.016 3.637s-2.425 1.7-3.726 2.173c-1.3.473-2.424.71-3.37.71h-8.073v-7.451h4.88c1.241 0 2.232-.207 2.97-.621.74-.414 1.302-.932 1.686-1.553a4.9 4.9 0 00.71-1.995c.089-.71.133-1.39.133-2.04V72.432c0-1.715.325-3.134.976-4.258.65-1.124 1.434-2.01 2.35-2.661.917-.65 1.863-1.124 2.839-1.42.976-.295 1.818-.502 2.528-.62v-.178c-.71-.059-1.552-.207-2.528-.443-.976-.237-1.922-.68-2.839-1.33-.916-.651-1.7-1.583-2.35-2.795-.65-1.212-.976-2.853-.976-4.923V37.66c0-.651-.044-1.331-.133-2.04a4.909 4.909 0 00-.71-1.997c-.384-.62-.946-1.138-1.685-1.552-.74-.414-1.73-.62-2.972-.62h-4.879V24h8.073c.946 0 2.07.237 3.37.71 1.301.473 2.543 1.197 3.726 2.173 1.183.976 2.188 2.188 3.016 3.637.828 1.449 1.242 3.178 1.242 5.189v16.943c0 1.419.31 2.572.931 3.46a6.897 6.897 0 002.262 2.084 8.868 8.868 0 002.75 1.02c.946.177 1.745.266 2.395.266v7.806z\"/></svg>"
        },
        "$:/core/images/twitter": {
            "title": "$:/core/images/twitter",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-twitter tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M41.626 115.803A73.376 73.376 0 012 104.235c2.022.238 4.08.36 6.166.36 12.111 0 23.258-4.117 32.105-11.023-11.312-.208-20.859-7.653-24.148-17.883a25.98 25.98 0 0011.674-.441C15.971 72.881 7.061 62.474 7.061 49.997c0-.108 0-.216.002-.323a25.824 25.824 0 0011.709 3.22c-6.936-4.617-11.5-12.5-11.5-21.433 0-4.719 1.274-9.142 3.5-12.945 12.75 15.579 31.797 25.83 53.281 26.904-.44-1.884-.67-3.85-.67-5.868 0-14.22 11.575-25.75 25.852-25.75a25.865 25.865 0 0118.869 8.132 51.892 51.892 0 0016.415-6.248c-1.93 6.012-6.029 11.059-11.366 14.246A51.844 51.844 0 00128 25.878a52.428 52.428 0 01-12.9 13.33c.05 1.104.075 2.214.075 3.33 0 34.028-26 73.265-73.549 73.265\"/></svg>"
        },
        "$:/core/images/underline": {
            "title": "$:/core/images/underline",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-underline tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M7 117.421h114.248V128H7v-10.579zm97.871-18.525V0h-16.26v55.856c0 4.463-.605 8.576-1.816 12.338-1.212 3.762-3.03 7.046-5.452 9.851-2.423 2.806-5.452 4.974-9.086 6.504-3.635 1.53-7.939 2.296-12.912 2.296-6.25 0-11.159-1.786-14.73-5.356-3.57-3.571-5.356-8.417-5.356-14.538V0H23v65.038c0 5.356.542 10.234 1.626 14.633 1.084 4.4 2.965 8.194 5.643 11.382 2.678 3.188 6.185 5.643 10.52 7.365 4.337 1.721 9.756 2.582 16.26 2.582 7.27 0 13.582-1.435 18.938-4.304 5.356-2.87 9.755-7.365 13.199-13.486h.382v15.686h15.303z\"/></svg>"
        },
        "$:/core/images/unfold-all-button": {
            "title": "$:/core/images/unfold-all-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-unfold-all tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"128\" height=\"16\" rx=\"8\"/><rect width=\"128\" height=\"16\" y=\"64\" rx=\"8\"/><path d=\"M63.945 60.624c-2.05 0-4.101-.78-5.666-2.345L35.662 35.662c-3.125-3.125-3.13-8.195-.005-11.319 3.118-3.118 8.192-3.122 11.319.005L63.94 41.314l16.966-16.966c3.124-3.124 8.194-3.129 11.318-.005 3.118 3.118 3.122 8.192-.005 11.319L69.603 58.279a7.986 7.986 0 01-5.663 2.346zM64.004 124.565c-2.05 0-4.102-.78-5.666-2.345L35.721 99.603c-3.125-3.125-3.13-8.195-.005-11.319 3.118-3.118 8.191-3.122 11.318.005L64 105.255l16.966-16.966c3.124-3.124 8.194-3.129 11.318-.005 3.118 3.118 3.122 8.192-.005 11.319L69.662 122.22a7.986 7.986 0 01-5.663 2.346z\"/></g></svg>"
        },
        "$:/core/images/unfold-button": {
            "title": "$:/core/images/unfold-button",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-unfold tc-image-button\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><rect width=\"128\" height=\"16\" rx=\"8\"/><path d=\"M63.945 63.624c-2.05 0-4.101-.78-5.666-2.345L35.662 38.662c-3.125-3.125-3.13-8.195-.005-11.319 3.118-3.118 8.192-3.122 11.319.005L63.94 44.314l16.966-16.966c3.124-3.124 8.194-3.129 11.318-.005 3.118 3.118 3.122 8.192-.005 11.319L69.603 61.279a7.986 7.986 0 01-5.663 2.346zM64.004 105.682c-2.05.001-4.102-.78-5.666-2.344L35.721 80.721c-3.125-3.125-3.13-8.195-.005-11.319 3.118-3.118 8.191-3.122 11.318.005L64 86.373l16.966-16.966c3.124-3.125 8.194-3.13 11.318-.005 3.118 3.118 3.122 8.192-.005 11.319l-22.617 22.617a7.986 7.986 0 01-5.663 2.346z\"/></g></svg>"
        },
        "$:/core/images/unlocked-padlock": {
            "title": "$:/core/images/unlocked-padlock",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-unlocked-padlock tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M48.627 64H105v32.01C105 113.674 90.674 128 73.001 128H56C38.318 128 24 113.677 24 96.01V64h6.136c-10.455-12.651-27.364-35.788-4.3-55.142 24.636-20.672 45.835 4.353 55.777 16.201 9.943 11.85-2.676 22.437-12.457 9.892-9.78-12.545-21.167-24.146-33.207-14.043-12.041 10.104-1.757 22.36 8.813 34.958 2.467 2.94 3.641 5.732 3.865 8.134zm19.105 28.364A8.503 8.503 0 0064.5 76a8.5 8.5 0 00-3.498 16.25l-5.095 22.77H72.8l-5.07-22.656z\"/></svg>"
        },
        "$:/core/images/up-arrow": {
            "title": "$:/core/images/up-arrow",
            "created": "20150316000544368",
            "modified": "20150316000831867",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-up-arrow tc-image-button\" viewBox=\"0 0 128 128\"><path d=\"M63.892.281c2.027 0 4.054.77 5.6 2.316l55.98 55.98a7.92 7.92 0 010 11.196c-3.086 3.085-8.104 3.092-11.196 0L63.894 19.393 13.513 69.774a7.92 7.92 0 01-11.196 0c-3.085-3.086-3.092-8.105 0-11.196l55.98-55.98A7.892 7.892 0 0163.893.28z\"/></svg>"
        },
        "$:/core/images/video": {
            "title": "$:/core/images/video",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-video tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M64 12c-34.91 0-55.273 2.917-58.182 5.833C2.91 20.75 0 41.167 0 64.5c0 23.333 2.91 43.75 5.818 46.667C8.728 114.083 29.091 117 64 117c34.91 0 55.273-2.917 58.182-5.833C125.09 108.25 128 87.833 128 64.5c0-23.333-2.91-43.75-5.818-46.667C119.272 14.917 98.909 12 64 12zm-9.084 32.618c-3.813-2.542-6.905-.879-6.905 3.698v31.368c0 4.585 3.099 6.235 6.905 3.698l22.168-14.779c3.813-2.542 3.806-6.669 0-9.206L54.916 44.618z\"/></svg>"
        },
        "$:/core/images/warning": {
            "title": "$:/core/images/warning",
            "tags": "$:/tags/Image",
            "text": "<svg width=\"22pt\" height=\"22pt\" class=\"tc-image-warning tc-image-button\" viewBox=\"0 0 128 128\"><path fill-rule=\"evenodd\" d=\"M57.072 11c3.079-5.333 10.777-5.333 13.856 0l55.426 96c3.079 5.333-.77 12-6.928 12H8.574c-6.158 0-10.007-6.667-6.928-12l55.426-96zM64 37c-4.418 0-8 3.582-8 7.994v28.012C56 77.421 59.59 81 64 81c4.418 0 8-3.582 8-7.994V44.994C72 40.579 68.41 37 64 37zm0 67a8 8 0 100-16 8 8 0 000 16z\"/></svg>"
        },
        "$:/language/Buttons/AdvancedSearch/Caption": {
            "title": "$:/language/Buttons/AdvancedSearch/Caption",
            "text": "advanced search"
        },
        "$:/language/Buttons/AdvancedSearch/Hint": {
            "title": "$:/language/Buttons/AdvancedSearch/Hint",
            "text": "Advanced search"
        },
        "$:/language/Buttons/Cancel/Caption": {
            "title": "$:/language/Buttons/Cancel/Caption",
            "text": "cancel"
        },
        "$:/language/Buttons/Cancel/Hint": {
            "title": "$:/language/Buttons/Cancel/Hint",
            "text": "Discard changes to this tiddler"
        },
        "$:/language/Buttons/Clone/Caption": {
            "title": "$:/language/Buttons/Clone/Caption",
            "text": "clone"
        },
        "$:/language/Buttons/Clone/Hint": {
            "title": "$:/language/Buttons/Clone/Hint",
            "text": "Clone this tiddler"
        },
        "$:/language/Buttons/Close/Caption": {
            "title": "$:/language/Buttons/Close/Caption",
            "text": "close"
        },
        "$:/language/Buttons/Close/Hint": {
            "title": "$:/language/Buttons/Close/Hint",
            "text": "Close this tiddler"
        },
        "$:/language/Buttons/CloseAll/Caption": {
            "title": "$:/language/Buttons/CloseAll/Caption",
            "text": "close all"
        },
        "$:/language/Buttons/CloseAll/Hint": {
            "title": "$:/language/Buttons/CloseAll/Hint",
            "text": "Close all tiddlers"
        },
        "$:/language/Buttons/CloseOthers/Caption": {
            "title": "$:/language/Buttons/CloseOthers/Caption",
            "text": "close others"
        },
        "$:/language/Buttons/CloseOthers/Hint": {
            "title": "$:/language/Buttons/CloseOthers/Hint",
            "text": "Close other tiddlers"
        },
        "$:/language/Buttons/ControlPanel/Caption": {
            "title": "$:/language/Buttons/ControlPanel/Caption",
            "text": "control panel"
        },
        "$:/language/Buttons/ControlPanel/Hint": {
            "title": "$:/language/Buttons/ControlPanel/Hint",
            "text": "Open control panel"
        },
        "$:/language/Buttons/CopyToClipboard/Caption": {
            "title": "$:/language/Buttons/CopyToClipboard/Caption",
            "text": "copy to clipboard"
        },
        "$:/language/Buttons/CopyToClipboard/Hint": {
            "title": "$:/language/Buttons/CopyToClipboard/Hint",
            "text": "Copy this text to the clipboard"
        },
        "$:/language/Buttons/Delete/Caption": {
            "title": "$:/language/Buttons/Delete/Caption",
            "text": "delete"
        },
        "$:/language/Buttons/Delete/Hint": {
            "title": "$:/language/Buttons/Delete/Hint",
            "text": "Delete this tiddler"
        },
        "$:/language/Buttons/Edit/Caption": {
            "title": "$:/language/Buttons/Edit/Caption",
            "text": "edit"
        },
        "$:/language/Buttons/Edit/Hint": {
            "title": "$:/language/Buttons/Edit/Hint",
            "text": "Edit this tiddler"
        },
        "$:/language/Buttons/Encryption/Caption": {
            "title": "$:/language/Buttons/Encryption/Caption",
            "text": "encryption"
        },
        "$:/language/Buttons/Encryption/Hint": {
            "title": "$:/language/Buttons/Encryption/Hint",
            "text": "Set or clear a password for saving this wiki"
        },
        "$:/language/Buttons/Encryption/ClearPassword/Caption": {
            "title": "$:/language/Buttons/Encryption/ClearPassword/Caption",
            "text": "clear password"
        },
        "$:/language/Buttons/Encryption/ClearPassword/Hint": {
            "title": "$:/language/Buttons/Encryption/ClearPassword/Hint",
            "text": "Clear the password and save this wiki without encryption"
        },
        "$:/language/Buttons/Encryption/SetPassword/Caption": {
            "title": "$:/language/Buttons/Encryption/SetPassword/Caption",
            "text": "set password"
        },
        "$:/language/Buttons/Encryption/SetPassword/Hint": {
            "title": "$:/language/Buttons/Encryption/SetPassword/Hint",
            "text": "Set a password for saving this wiki with encryption"
        },
        "$:/language/Buttons/ExportPage/Caption": {
            "title": "$:/language/Buttons/ExportPage/Caption",
            "text": "export all"
        },
        "$:/language/Buttons/ExportPage/Hint": {
            "title": "$:/language/Buttons/ExportPage/Hint",
            "text": "Export all tiddlers"
        },
        "$:/language/Buttons/ExportTiddler/Caption": {
            "title": "$:/language/Buttons/ExportTiddler/Caption",
            "text": "export tiddler"
        },
        "$:/language/Buttons/ExportTiddler/Hint": {
            "title": "$:/language/Buttons/ExportTiddler/Hint",
            "text": "Export tiddler"
        },
        "$:/language/Buttons/ExportTiddlers/Caption": {
            "title": "$:/language/Buttons/ExportTiddlers/Caption",
            "text": "export tiddlers"
        },
        "$:/language/Buttons/ExportTiddlers/Hint": {
            "title": "$:/language/Buttons/ExportTiddlers/Hint",
            "text": "Export tiddlers"
        },
        "$:/language/Buttons/SidebarSearch/Hint": {
            "title": "$:/language/Buttons/SidebarSearch/Hint",
            "text": "Select the sidebar search field"
        },
        "$:/language/Buttons/Fold/Caption": {
            "title": "$:/language/Buttons/Fold/Caption",
            "text": "fold tiddler"
        },
        "$:/language/Buttons/Fold/Hint": {
            "title": "$:/language/Buttons/Fold/Hint",
            "text": "Fold the body of this tiddler"
        },
        "$:/language/Buttons/Fold/FoldBar/Caption": {
            "title": "$:/language/Buttons/Fold/FoldBar/Caption",
            "text": "fold-bar"
        },
        "$:/language/Buttons/Fold/FoldBar/Hint": {
            "title": "$:/language/Buttons/Fold/FoldBar/Hint",
            "text": "Optional bars to fold and unfold tiddlers"
        },
        "$:/language/Buttons/Unfold/Caption": {
            "title": "$:/language/Buttons/Unfold/Caption",
            "text": "unfold tiddler"
        },
        "$:/language/Buttons/Unfold/Hint": {
            "title": "$:/language/Buttons/Unfold/Hint",
            "text": "Unfold the body of this tiddler"
        },
        "$:/language/Buttons/FoldOthers/Caption": {
            "title": "$:/language/Buttons/FoldOthers/Caption",
            "text": "fold other tiddlers"
        },
        "$:/language/Buttons/FoldOthers/Hint": {
            "title": "$:/language/Buttons/FoldOthers/Hint",
            "text": "Fold the bodies of other opened tiddlers"
        },
        "$:/language/Buttons/FoldAll/Caption": {
            "title": "$:/language/Buttons/FoldAll/Caption",
            "text": "fold all tiddlers"
        },
        "$:/language/Buttons/FoldAll/Hint": {
            "title": "$:/language/Buttons/FoldAll/Hint",
            "text": "Fold the bodies of all opened tiddlers"
        },
        "$:/language/Buttons/UnfoldAll/Caption": {
            "title": "$:/language/Buttons/UnfoldAll/Caption",
            "text": "unfold all tiddlers"
        },
        "$:/language/Buttons/UnfoldAll/Hint": {
            "title": "$:/language/Buttons/UnfoldAll/Hint",
            "text": "Unfold the bodies of all opened tiddlers"
        },
        "$:/language/Buttons/FullScreen/Caption": {
            "title": "$:/language/Buttons/FullScreen/Caption",
            "text": "full-screen"
        },
        "$:/language/Buttons/FullScreen/Hint": {
            "title": "$:/language/Buttons/FullScreen/Hint",
            "text": "Enter or leave full-screen mode"
        },
        "$:/language/Buttons/Help/Caption": {
            "title": "$:/language/Buttons/Help/Caption",
            "text": "help"
        },
        "$:/language/Buttons/Help/Hint": {
            "title": "$:/language/Buttons/Help/Hint",
            "text": "Show help panel"
        },
        "$:/language/Buttons/Import/Caption": {
            "title": "$:/language/Buttons/Import/Caption",
            "text": "import"
        },
        "$:/language/Buttons/Import/Hint": {
            "title": "$:/language/Buttons/Import/Hint",
            "text": "Import many types of file including text, image, TiddlyWiki or JSON"
        },
        "$:/language/Buttons/Info/Caption": {
            "title": "$:/language/Buttons/Info/Caption",
            "text": "info"
        },
        "$:/language/Buttons/Info/Hint": {
            "title": "$:/language/Buttons/Info/Hint",
            "text": "Show information for this tiddler"
        },
        "$:/language/Buttons/Home/Caption": {
            "title": "$:/language/Buttons/Home/Caption",
            "text": "home"
        },
        "$:/language/Buttons/Home/Hint": {
            "title": "$:/language/Buttons/Home/Hint",
            "text": "Open the default tiddlers"
        },
        "$:/language/Buttons/Language/Caption": {
            "title": "$:/language/Buttons/Language/Caption",
            "text": "language"
        },
        "$:/language/Buttons/Language/Hint": {
            "title": "$:/language/Buttons/Language/Hint",
            "text": "Choose the user interface language"
        },
        "$:/language/Buttons/Manager/Caption": {
            "title": "$:/language/Buttons/Manager/Caption",
            "text": "tiddler manager"
        },
        "$:/language/Buttons/Manager/Hint": {
            "title": "$:/language/Buttons/Manager/Hint",
            "text": "Open tiddler manager"
        },
        "$:/language/Buttons/More/Caption": {
            "title": "$:/language/Buttons/More/Caption",
            "text": "more"
        },
        "$:/language/Buttons/More/Hint": {
            "title": "$:/language/Buttons/More/Hint",
            "text": "More actions"
        },
        "$:/language/Buttons/NewHere/Caption": {
            "title": "$:/language/Buttons/NewHere/Caption",
            "text": "new here"
        },
        "$:/language/Buttons/NewHere/Hint": {
            "title": "$:/language/Buttons/NewHere/Hint",
            "text": "Create a new tiddler tagged with this one"
        },
        "$:/language/Buttons/NewJournal/Caption": {
            "title": "$:/language/Buttons/NewJournal/Caption",
            "text": "new journal"
        },
        "$:/language/Buttons/NewJournal/Hint": {
            "title": "$:/language/Buttons/NewJournal/Hint",
            "text": "Create a new journal tiddler"
        },
        "$:/language/Buttons/NewJournalHere/Caption": {
            "title": "$:/language/Buttons/NewJournalHere/Caption",
            "text": "new journal here"
        },
        "$:/language/Buttons/NewJournalHere/Hint": {
            "title": "$:/language/Buttons/NewJournalHere/Hint",
            "text": "Create a new journal tiddler tagged with this one"
        },
        "$:/language/Buttons/NewImage/Caption": {
            "title": "$:/language/Buttons/NewImage/Caption",
            "text": "new image"
        },
        "$:/language/Buttons/NewImage/Hint": {
            "title": "$:/language/Buttons/NewImage/Hint",
            "text": "Create a new image tiddler"
        },
        "$:/language/Buttons/NewMarkdown/Caption": {
            "title": "$:/language/Buttons/NewMarkdown/Caption",
            "text": "new Markdown tiddler"
        },
        "$:/language/Buttons/NewMarkdown/Hint": {
            "title": "$:/language/Buttons/NewMarkdown/Hint",
            "text": "Create a new Markdown tiddler"
        },
        "$:/language/Buttons/NewTiddler/Caption": {
            "title": "$:/language/Buttons/NewTiddler/Caption",
            "text": "new tiddler"
        },
        "$:/language/Buttons/NewTiddler/Hint": {
            "title": "$:/language/Buttons/NewTiddler/Hint",
            "text": "Create a new tiddler"
        },
        "$:/language/Buttons/OpenWindow/Caption": {
            "title": "$:/language/Buttons/OpenWindow/Caption",
            "text": "open in new window"
        },
        "$:/language/Buttons/OpenWindow/Hint": {
            "title": "$:/language/Buttons/OpenWindow/Hint",
            "text": "Open tiddler in new window"
        },
        "$:/language/Buttons/Palette/Caption": {
            "title": "$:/language/Buttons/Palette/Caption",
            "text": "palette"
        },
        "$:/language/Buttons/Palette/Hint": {
            "title": "$:/language/Buttons/Palette/Hint",
            "text": "Choose the colour palette"
        },
        "$:/language/Buttons/Permalink/Caption": {
            "title": "$:/language/Buttons/Permalink/Caption",
            "text": "permalink"
        },
        "$:/language/Buttons/Permalink/Hint": {
            "title": "$:/language/Buttons/Permalink/Hint",
            "text": "Set browser address bar to a direct link to this tiddler"
        },
        "$:/language/Buttons/Permaview/Caption": {
            "title": "$:/language/Buttons/Permaview/Caption",
            "text": "permaview"
        },
        "$:/language/Buttons/Permaview/Hint": {
            "title": "$:/language/Buttons/Permaview/Hint",
            "text": "Set browser address bar to a direct link to all the tiddlers in this story"
        },
        "$:/language/Buttons/Print/Caption": {
            "title": "$:/language/Buttons/Print/Caption",
            "text": "print page"
        },
        "$:/language/Buttons/Print/Hint": {
            "title": "$:/language/Buttons/Print/Hint",
            "text": "Print the current page"
        },
        "$:/language/Buttons/Refresh/Caption": {
            "title": "$:/language/Buttons/Refresh/Caption",
            "text": "refresh"
        },
        "$:/language/Buttons/Refresh/Hint": {
            "title": "$:/language/Buttons/Refresh/Hint",
            "text": "Perform a full refresh of the wiki"
        },
        "$:/language/Buttons/Save/Caption": {
            "title": "$:/language/Buttons/Save/Caption",
            "text": "ok"
        },
        "$:/language/Buttons/Save/Hint": {
            "title": "$:/language/Buttons/Save/Hint",
            "text": "Confirm changes to this tiddler"
        },
        "$:/language/Buttons/SaveWiki/Caption": {
            "title": "$:/language/Buttons/SaveWiki/Caption",
            "text": "save changes"
        },
        "$:/language/Buttons/SaveWiki/Hint": {
            "title": "$:/language/Buttons/SaveWiki/Hint",
            "text": "Save changes"
        },
        "$:/language/Buttons/StoryView/Caption": {
            "title": "$:/language/Buttons/StoryView/Caption",
            "text": "storyview"
        },
        "$:/language/Buttons/StoryView/Hint": {
            "title": "$:/language/Buttons/StoryView/Hint",
            "text": "Choose the story visualisation"
        },
        "$:/language/Buttons/HideSideBar/Caption": {
            "title": "$:/language/Buttons/HideSideBar/Caption",
            "text": "hide sidebar"
        },
        "$:/language/Buttons/HideSideBar/Hint": {
            "title": "$:/language/Buttons/HideSideBar/Hint",
            "text": "Hide sidebar"
        },
        "$:/language/Buttons/ShowSideBar/Caption": {
            "title": "$:/language/Buttons/ShowSideBar/Caption",
            "text": "show sidebar"
        },
        "$:/language/Buttons/ShowSideBar/Hint": {
            "title": "$:/language/Buttons/ShowSideBar/Hint",
            "text": "Show sidebar"
        },
        "$:/language/Buttons/TagManager/Caption": {
            "title": "$:/language/Buttons/TagManager/Caption",
            "text": "tag manager"
        },
        "$:/language/Buttons/TagManager/Hint": {
            "title": "$:/language/Buttons/TagManager/Hint",
            "text": "Open tag manager"
        },
        "$:/language/Buttons/Timestamp/Caption": {
            "title": "$:/language/Buttons/Timestamp/Caption",
            "text": "timestamps"
        },
        "$:/language/Buttons/Timestamp/Hint": {
            "title": "$:/language/Buttons/Timestamp/Hint",
            "text": "Choose whether modifications update timestamps"
        },
        "$:/language/Buttons/Timestamp/On/Caption": {
            "title": "$:/language/Buttons/Timestamp/On/Caption",
            "text": "timestamps are on"
        },
        "$:/language/Buttons/Timestamp/On/Hint": {
            "title": "$:/language/Buttons/Timestamp/On/Hint",
            "text": "Update timestamps when tiddlers are modified"
        },
        "$:/language/Buttons/Timestamp/Off/Caption": {
            "title": "$:/language/Buttons/Timestamp/Off/Caption",
            "text": "timestamps are off"
        },
        "$:/language/Buttons/Timestamp/Off/Hint": {
            "title": "$:/language/Buttons/Timestamp/Off/Hint",
            "text": "Don't update timestamps when tiddlers are modified"
        },
        "$:/language/Buttons/Theme/Caption": {
            "title": "$:/language/Buttons/Theme/Caption",
            "text": "theme"
        },
        "$:/language/Buttons/Theme/Hint": {
            "title": "$:/language/Buttons/Theme/Hint",
            "text": "Choose the display theme"
        },
        "$:/language/Buttons/Bold/Caption": {
            "title": "$:/language/Buttons/Bold/Caption",
            "text": "bold"
        },
        "$:/language/Buttons/Bold/Hint": {
            "title": "$:/language/Buttons/Bold/Hint",
            "text": "Apply bold formatting to selection"
        },
        "$:/language/Buttons/Clear/Caption": {
            "title": "$:/language/Buttons/Clear/Caption",
            "text": "clear"
        },
        "$:/language/Buttons/Clear/Hint": {
            "title": "$:/language/Buttons/Clear/Hint",
            "text": "Clear image to solid colour"
        },
        "$:/language/Buttons/EditorHeight/Caption": {
            "title": "$:/language/Buttons/EditorHeight/Caption",
            "text": "editor height"
        },
        "$:/language/Buttons/EditorHeight/Caption/Auto": {
            "title": "$:/language/Buttons/EditorHeight/Caption/Auto",
            "text": "Automatically adjust height to fit content"
        },
        "$:/language/Buttons/EditorHeight/Caption/Fixed": {
            "title": "$:/language/Buttons/EditorHeight/Caption/Fixed",
            "text": "Fixed height:"
        },
        "$:/language/Buttons/EditorHeight/Hint": {
            "title": "$:/language/Buttons/EditorHeight/Hint",
            "text": "Choose the height of the text editor"
        },
        "$:/language/Buttons/Excise/Caption": {
            "title": "$:/language/Buttons/Excise/Caption",
            "text": "excise"
        },
        "$:/language/Buttons/Excise/Caption/Excise": {
            "title": "$:/language/Buttons/Excise/Caption/Excise",
            "text": "Perform excision"
        },
        "$:/language/Buttons/Excise/Caption/MacroName": {
            "title": "$:/language/Buttons/Excise/Caption/MacroName",
            "text": "Macro name:"
        },
        "$:/language/Buttons/Excise/Caption/NewTitle": {
            "title": "$:/language/Buttons/Excise/Caption/NewTitle",
            "text": "Title of new tiddler:"
        },
        "$:/language/Buttons/Excise/Caption/Replace": {
            "title": "$:/language/Buttons/Excise/Caption/Replace",
            "text": "Replace excised text with:"
        },
        "$:/language/Buttons/Excise/Caption/Replace/Macro": {
            "title": "$:/language/Buttons/Excise/Caption/Replace/Macro",
            "text": "macro"
        },
        "$:/language/Buttons/Excise/Caption/Replace/Link": {
            "title": "$:/language/Buttons/Excise/Caption/Replace/Link",
            "text": "link"
        },
        "$:/language/Buttons/Excise/Caption/Replace/Transclusion": {
            "title": "$:/language/Buttons/Excise/Caption/Replace/Transclusion",
            "text": "transclusion"
        },
        "$:/language/Buttons/Excise/Caption/Tag": {
            "title": "$:/language/Buttons/Excise/Caption/Tag",
            "text": "Tag new tiddler with the title of this tiddler"
        },
        "$:/language/Buttons/Excise/Caption/TiddlerExists": {
            "title": "$:/language/Buttons/Excise/Caption/TiddlerExists",
            "text": "Warning: tiddler already exists"
        },
        "$:/language/Buttons/Excise/Hint": {
            "title": "$:/language/Buttons/Excise/Hint",
            "text": "Excise the selected text into a new tiddler"
        },
        "$:/language/Buttons/Heading1/Caption": {
            "title": "$:/language/Buttons/Heading1/Caption",
            "text": "heading 1"
        },
        "$:/language/Buttons/Heading1/Hint": {
            "title": "$:/language/Buttons/Heading1/Hint",
            "text": "Apply heading level 1 formatting to lines containing selection"
        },
        "$:/language/Buttons/Heading2/Caption": {
            "title": "$:/language/Buttons/Heading2/Caption",
            "text": "heading 2"
        },
        "$:/language/Buttons/Heading2/Hint": {
            "title": "$:/language/Buttons/Heading2/Hint",
            "text": "Apply heading level 2 formatting to lines containing selection"
        },
        "$:/language/Buttons/Heading3/Caption": {
            "title": "$:/language/Buttons/Heading3/Caption",
            "text": "heading 3"
        },
        "$:/language/Buttons/Heading3/Hint": {
            "title": "$:/language/Buttons/Heading3/Hint",
            "text": "Apply heading level 3 formatting to lines containing selection"
        },
        "$:/language/Buttons/Heading4/Caption": {
            "title": "$:/language/Buttons/Heading4/Caption",
            "text": "heading 4"
        },
        "$:/language/Buttons/Heading4/Hint": {
            "title": "$:/language/Buttons/Heading4/Hint",
            "text": "Apply heading level 4 formatting to lines containing selection"
        },
        "$:/language/Buttons/Heading5/Caption": {
            "title": "$:/language/Buttons/Heading5/Caption",
            "text": "heading 5"
        },
        "$:/language/Buttons/Heading5/Hint": {
            "title": "$:/language/Buttons/Heading5/Hint",
            "text": "Apply heading level 5 formatting to lines containing selection"
        },
        "$:/language/Buttons/Heading6/Caption": {
            "title": "$:/language/Buttons/Heading6/Caption",
            "text": "heading 6"
        },
        "$:/language/Buttons/Heading6/Hint": {
            "title": "$:/language/Buttons/Heading6/Hint",
            "text": "Apply heading level 6 formatting to lines containing selection"
        },
        "$:/language/Buttons/Italic/Caption": {
            "title": "$:/language/Buttons/Italic/Caption",
            "text": "italic"
        },
        "$:/language/Buttons/Italic/Hint": {
            "title": "$:/language/Buttons/Italic/Hint",
            "text": "Apply italic formatting to selection"
        },
        "$:/language/Buttons/LineWidth/Caption": {
            "title": "$:/language/Buttons/LineWidth/Caption",
            "text": "line width"
        },
        "$:/language/Buttons/LineWidth/Hint": {
            "title": "$:/language/Buttons/LineWidth/Hint",
            "text": "Set line width for painting"
        },
        "$:/language/Buttons/Link/Caption": {
            "title": "$:/language/Buttons/Link/Caption",
            "text": "link"
        },
        "$:/language/Buttons/Link/Hint": {
            "title": "$:/language/Buttons/Link/Hint",
            "text": "Create wikitext link"
        },
        "$:/language/Buttons/Linkify/Caption": {
            "title": "$:/language/Buttons/Linkify/Caption",
            "text": "wikilink"
        },
        "$:/language/Buttons/Linkify/Hint": {
            "title": "$:/language/Buttons/Linkify/Hint",
            "text": "Wrap selection in square brackets"
        },
        "$:/language/Buttons/ListBullet/Caption": {
            "title": "$:/language/Buttons/ListBullet/Caption",
            "text": "bulleted list"
        },
        "$:/language/Buttons/ListBullet/Hint": {
            "title": "$:/language/Buttons/ListBullet/Hint",
            "text": "Apply bulleted list formatting to lines containing selection"
        },
        "$:/language/Buttons/ListNumber/Caption": {
            "title": "$:/language/Buttons/ListNumber/Caption",
            "text": "numbered list"
        },
        "$:/language/Buttons/ListNumber/Hint": {
            "title": "$:/language/Buttons/ListNumber/Hint",
            "text": "Apply numbered list formatting to lines containing selection"
        },
        "$:/language/Buttons/MonoBlock/Caption": {
            "title": "$:/language/Buttons/MonoBlock/Caption",
            "text": "monospaced block"
        },
        "$:/language/Buttons/MonoBlock/Hint": {
            "title": "$:/language/Buttons/MonoBlock/Hint",
            "text": "Apply monospaced block formatting to lines containing selection"
        },
        "$:/language/Buttons/MonoLine/Caption": {
            "title": "$:/language/Buttons/MonoLine/Caption",
            "text": "monospaced"
        },
        "$:/language/Buttons/MonoLine/Hint": {
            "title": "$:/language/Buttons/MonoLine/Hint",
            "text": "Apply monospaced character formatting to selection"
        },
        "$:/language/Buttons/Opacity/Caption": {
            "title": "$:/language/Buttons/Opacity/Caption",
            "text": "opacity"
        },
        "$:/language/Buttons/Opacity/Hint": {
            "title": "$:/language/Buttons/Opacity/Hint",
            "text": "Set painting opacity"
        },
        "$:/language/Buttons/Paint/Caption": {
            "title": "$:/language/Buttons/Paint/Caption",
            "text": "paint colour"
        },
        "$:/language/Buttons/Paint/Hint": {
            "title": "$:/language/Buttons/Paint/Hint",
            "text": "Set painting colour"
        },
        "$:/language/Buttons/Picture/Caption": {
            "title": "$:/language/Buttons/Picture/Caption",
            "text": "picture"
        },
        "$:/language/Buttons/Picture/Hint": {
            "title": "$:/language/Buttons/Picture/Hint",
            "text": "Insert picture"
        },
        "$:/language/Buttons/Preview/Caption": {
            "title": "$:/language/Buttons/Preview/Caption",
            "text": "preview"
        },
        "$:/language/Buttons/Preview/Hint": {
            "title": "$:/language/Buttons/Preview/Hint",
            "text": "Show preview pane"
        },
        "$:/language/Buttons/PreviewType/Caption": {
            "title": "$:/language/Buttons/PreviewType/Caption",
            "text": "preview type"
        },
        "$:/language/Buttons/PreviewType/Hint": {
            "title": "$:/language/Buttons/PreviewType/Hint",
            "text": "Choose preview type"
        },
        "$:/language/Buttons/Quote/Caption": {
            "title": "$:/language/Buttons/Quote/Caption",
            "text": "quote"
        },
        "$:/language/Buttons/Quote/Hint": {
            "title": "$:/language/Buttons/Quote/Hint",
            "text": "Apply quoted text formatting to lines containing selection"
        },
        "$:/language/Buttons/RotateLeft/Caption": {
            "title": "$:/language/Buttons/RotateLeft/Caption",
            "text": "rotate left"
        },
        "$:/language/Buttons/RotateLeft/Hint": {
            "title": "$:/language/Buttons/RotateLeft/Hint",
            "text": "Rotate image left by 90 degrees"
        },
        "$:/language/Buttons/Size/Caption": {
            "title": "$:/language/Buttons/Size/Caption",
            "text": "image size"
        },
        "$:/language/Buttons/Size/Caption/Height": {
            "title": "$:/language/Buttons/Size/Caption/Height",
            "text": "Height:"
        },
        "$:/language/Buttons/Size/Caption/Resize": {
            "title": "$:/language/Buttons/Size/Caption/Resize",
            "text": "Resize image"
        },
        "$:/language/Buttons/Size/Caption/Width": {
            "title": "$:/language/Buttons/Size/Caption/Width",
            "text": "Width:"
        },
        "$:/language/Buttons/Size/Hint": {
            "title": "$:/language/Buttons/Size/Hint",
            "text": "Set image size"
        },
        "$:/language/Buttons/Stamp/Caption": {
            "title": "$:/language/Buttons/Stamp/Caption",
            "text": "stamp"
        },
        "$:/language/Buttons/Stamp/Caption/New": {
            "title": "$:/language/Buttons/Stamp/Caption/New",
            "text": "Add your own"
        },
        "$:/language/Buttons/Stamp/Hint": {
            "title": "$:/language/Buttons/Stamp/Hint",
            "text": "Insert a preconfigured snippet of text"
        },
        "$:/language/Buttons/Stamp/New/Title": {
            "title": "$:/language/Buttons/Stamp/New/Title",
            "text": "Name as shown in menu"
        },
        "$:/language/Buttons/Stamp/New/Text": {
            "title": "$:/language/Buttons/Stamp/New/Text",
            "text": "Text of snippet. (Remember to add a descriptive title in the caption field)."
        },
        "$:/language/Buttons/Strikethrough/Caption": {
            "title": "$:/language/Buttons/Strikethrough/Caption",
            "text": "strikethrough"
        },
        "$:/language/Buttons/Strikethrough/Hint": {
            "title": "$:/language/Buttons/Strikethrough/Hint",
            "text": "Apply strikethrough formatting to selection"
        },
        "$:/language/Buttons/Subscript/Caption": {
            "title": "$:/language/Buttons/Subscript/Caption",
            "text": "subscript"
        },
        "$:/language/Buttons/Subscript/Hint": {
            "title": "$:/language/Buttons/Subscript/Hint",
            "text": "Apply subscript formatting to selection"
        },
        "$:/language/Buttons/Superscript/Caption": {
            "title": "$:/language/Buttons/Superscript/Caption",
            "text": "superscript"
        },
        "$:/language/Buttons/Superscript/Hint": {
            "title": "$:/language/Buttons/Superscript/Hint",
            "text": "Apply superscript formatting to selection"
        },
        "$:/language/Buttons/ToggleSidebar/Hint": {
            "title": "$:/language/Buttons/ToggleSidebar/Hint",
            "text": "Toggle the sidebar visibility"
        },
        "$:/language/Buttons/Transcludify/Caption": {
            "title": "$:/language/Buttons/Transcludify/Caption",
            "text": "transclusion"
        },
        "$:/language/Buttons/Transcludify/Hint": {
            "title": "$:/language/Buttons/Transcludify/Hint",
            "text": "Wrap selection in curly brackets"
        },
        "$:/language/Buttons/Underline/Caption": {
            "title": "$:/language/Buttons/Underline/Caption",
            "text": "underline"
        },
        "$:/language/Buttons/Underline/Hint": {
            "title": "$:/language/Buttons/Underline/Hint",
            "text": "Apply underline formatting to selection"
        },
        "$:/language/ControlPanel/Advanced/Caption": {
            "title": "$:/language/ControlPanel/Advanced/Caption",
            "text": "Advanced"
        },
        "$:/language/ControlPanel/Advanced/Hint": {
            "title": "$:/language/ControlPanel/Advanced/Hint",
            "text": "Internal information about this TiddlyWiki"
        },
        "$:/language/ControlPanel/Appearance/Caption": {
            "title": "$:/language/ControlPanel/Appearance/Caption",
            "text": "Appearance"
        },
        "$:/language/ControlPanel/Appearance/Hint": {
            "title": "$:/language/ControlPanel/Appearance/Hint",
            "text": "Ways to customise the appearance of your TiddlyWiki."
        },
        "$:/language/ControlPanel/Basics/AnimDuration/Prompt": {
            "title": "$:/language/ControlPanel/Basics/AnimDuration/Prompt",
            "text": "Animation duration"
        },
        "$:/language/ControlPanel/Basics/AutoFocus/Prompt": {
            "title": "$:/language/ControlPanel/Basics/AutoFocus/Prompt",
            "text": "Default focus field for new tiddlers"
        },
        "$:/language/ControlPanel/Basics/Caption": {
            "title": "$:/language/ControlPanel/Basics/Caption",
            "text": "Basics"
        },
        "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint": {
            "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint",
            "text": "Use &#91;&#91;double square brackets&#93;&#93; for titles with spaces. Or you can choose to <$button set=\"$:/DefaultTiddlers\" setTo=\"[list[$:/StoryList]]\">retain story ordering</$button>"
        },
        "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt",
            "text": "Default tiddlers"
        },
        "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint": {
            "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint",
            "text": "Choose which tiddlers are displayed at startup"
        },
        "$:/language/ControlPanel/Basics/Language/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Language/Prompt",
            "text": "Hello! Current language:"
        },
        "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt",
            "text": "Title of new journal tiddlers"
        },
        "$:/language/ControlPanel/Basics/NewJournal/Text/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewJournal/Text/Prompt",
            "text": "Text for new journal tiddlers"
        },
        "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt",
            "text": "Tags for new journal tiddlers"
        },
        "$:/language/ControlPanel/Basics/NewTiddler/Title/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewTiddler/Title/Prompt",
            "text": "Title of new tiddlers"
        },
        "$:/language/ControlPanel/Basics/NewTiddler/Tags/Prompt": {
            "title": "$:/language/ControlPanel/Basics/NewTiddler/Tags/Prompt",
            "text": "Tags for new tiddlers"
        },
        "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt",
            "text": "Number of overridden shadow tiddlers"
        },
        "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt",
            "text": "Number of shadow tiddlers"
        },
        "$:/language/ControlPanel/Basics/Subtitle/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Subtitle/Prompt",
            "text": "Subtitle"
        },
        "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt",
            "text": "Number of system tiddlers"
        },
        "$:/language/ControlPanel/Basics/Tags/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Tags/Prompt",
            "text": "Number of tags"
        },
        "$:/language/ControlPanel/Basics/Tiddlers/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Tiddlers/Prompt",
            "text": "Number of tiddlers"
        },
        "$:/language/ControlPanel/Basics/Title/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Title/Prompt",
            "text": "Title of this ~TiddlyWiki"
        },
        "$:/language/ControlPanel/Basics/Username/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Username/Prompt",
            "text": "Username for signing edits"
        },
        "$:/language/ControlPanel/Basics/Version/Prompt": {
            "title": "$:/language/ControlPanel/Basics/Version/Prompt",
            "text": "~TiddlyWiki version"
        },
        "$:/language/ControlPanel/EditorTypes/Caption": {
            "title": "$:/language/ControlPanel/EditorTypes/Caption",
            "text": "Editor Types"
        },
        "$:/language/ControlPanel/EditorTypes/Editor/Caption": {
            "title": "$:/language/ControlPanel/EditorTypes/Editor/Caption",
            "text": "Editor"
        },
        "$:/language/ControlPanel/EditorTypes/Hint": {
            "title": "$:/language/ControlPanel/EditorTypes/Hint",
            "text": "These tiddlers determine which editor is used to edit specific tiddler types."
        },
        "$:/language/ControlPanel/EditorTypes/Type/Caption": {
            "title": "$:/language/ControlPanel/EditorTypes/Type/Caption",
            "text": "Type"
        },
        "$:/language/ControlPanel/Info/Caption": {
            "title": "$:/language/ControlPanel/Info/Caption",
            "text": "Info"
        },
        "$:/language/ControlPanel/Info/Hint": {
            "title": "$:/language/ControlPanel/Info/Hint",
            "text": "Information about this TiddlyWiki"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt",
            "text": "Type shortcut here"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Add/Caption": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Add/Caption",
            "text": "add shortcut"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Caption": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Caption",
            "text": "Keyboard Shortcuts"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Hint": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Hint",
            "text": "Manage keyboard shortcut assignments"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/NoShortcuts/Caption": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/NoShortcuts/Caption",
            "text": "No keyboard shortcuts assigned"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint",
            "text": "remove keyboard shortcut"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/All": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/All",
            "text": "All platforms"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/Mac": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Mac",
            "text": "Macintosh platform only"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonMac": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonMac",
            "text": "Non-Macintosh platforms only"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/Linux": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Linux",
            "text": "Linux platform only"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonLinux": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonLinux",
            "text": "Non-Linux platforms only"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/Windows": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Windows",
            "text": "Windows platform only"
        },
        "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonWindows": {
            "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonWindows",
            "text": "Non-Windows platforms only"
        },
        "$:/language/ControlPanel/LoadedModules/Caption": {
            "title": "$:/language/ControlPanel/LoadedModules/Caption",
            "text": "Loaded Modules"
        },
        "$:/language/ControlPanel/LoadedModules/Hint": {
            "title": "$:/language/ControlPanel/LoadedModules/Hint",
            "text": "These are the currently loaded tiddler modules linked to their source tiddlers. Any italicised modules lack a source tiddler, typically because they were setup during the boot process."
        },
        "$:/language/ControlPanel/Palette/Caption": {
            "title": "$:/language/ControlPanel/Palette/Caption",
            "text": "Palette"
        },
        "$:/language/ControlPanel/Palette/Editor/Clone/Caption": {
            "title": "$:/language/ControlPanel/Palette/Editor/Clone/Caption",
            "text": "clone"
        },
        "$:/language/ControlPanel/Palette/Editor/Clone/Prompt": {
            "title": "$:/language/ControlPanel/Palette/Editor/Clone/Prompt",
            "text": "It is recommended that you clone this shadow palette before editing it"
        },
        "$:/language/ControlPanel/Palette/Editor/Delete/Hint": {
            "title": "$:/language/ControlPanel/Palette/Editor/Delete/Hint",
            "text": "delete this entry from the current palette"
        },
        "$:/language/ControlPanel/Palette/Editor/Names/External/Show": {
            "title": "$:/language/ControlPanel/Palette/Editor/Names/External/Show",
            "text": "Show color names that are not part of the current palette"
        },
        "$:/language/ControlPanel/Palette/Editor/Prompt/Modified": {
            "title": "$:/language/ControlPanel/Palette/Editor/Prompt/Modified",
            "text": "This shadow palette has been modified"
        },
        "$:/language/ControlPanel/Palette/Editor/Prompt": {
            "title": "$:/language/ControlPanel/Palette/Editor/Prompt",
            "text": "Editing"
        },
        "$:/language/ControlPanel/Palette/Editor/Reset/Caption": {
            "title": "$:/language/ControlPanel/Palette/Editor/Reset/Caption",
            "text": "reset"
        },
        "$:/language/ControlPanel/Palette/HideEditor/Caption": {
            "title": "$:/language/ControlPanel/Palette/HideEditor/Caption",
            "text": "hide editor"
        },
        "$:/language/ControlPanel/Palette/Prompt": {
            "title": "$:/language/ControlPanel/Palette/Prompt",
            "text": "Current palette:"
        },
        "$:/language/ControlPanel/Palette/ShowEditor/Caption": {
            "title": "$:/language/ControlPanel/Palette/ShowEditor/Caption",
            "text": "show editor"
        },
        "$:/language/ControlPanel/Parsing/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Caption",
            "text": "Parsing"
        },
        "$:/language/ControlPanel/Parsing/Hint": {
            "title": "$:/language/ControlPanel/Parsing/Hint",
            "text": "Here you can globally disable/enable wiki parser rules. For changes to take effect, save and reload your wiki. Disabling certain parser rules can prevent <$text text=\"TiddlyWiki\"/> from functioning correctly. Use [[safe mode|https://tiddlywiki.com/#SafeMode]] to restore normal operation."
        },
        "$:/language/ControlPanel/Parsing/Block/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Block/Caption",
            "text": "Block Parse Rules"
        },
        "$:/language/ControlPanel/Parsing/Inline/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Inline/Caption",
            "text": "Inline Parse Rules"
        },
        "$:/language/ControlPanel/Parsing/Pragma/Caption": {
            "title": "$:/language/ControlPanel/Parsing/Pragma/Caption",
            "text": "Pragma Parse Rules"
        },
        "$:/language/ControlPanel/Plugins/Add/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Add/Caption",
            "text": "Get more plugins"
        },
        "$:/language/ControlPanel/Plugins/Add/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Add/Hint",
            "text": "Install plugins from the official library"
        },
        "$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint": {
            "title": "$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint",
            "text": "This plugin is already installed at version <$text text=<<installedVersion>>/>"
        },
        "$:/language/ControlPanel/Plugins/AlsoRequires": {
            "title": "$:/language/ControlPanel/Plugins/AlsoRequires",
            "text": "Also requires:"
        },
        "$:/language/ControlPanel/Plugins/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Caption",
            "text": "Plugins"
        },
        "$:/language/ControlPanel/Plugins/Disable/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Disable/Caption",
            "text": "disable"
        },
        "$:/language/ControlPanel/Plugins/Disable/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Disable/Hint",
            "text": "Disable this plugin when reloading page"
        },
        "$:/language/ControlPanel/Plugins/Disabled/Status": {
            "title": "$:/language/ControlPanel/Plugins/Disabled/Status",
            "text": "(disabled)"
        },
        "$:/language/ControlPanel/Plugins/Downgrade/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Downgrade/Caption",
            "text": "downgrade"
        },
        "$:/language/ControlPanel/Plugins/Empty/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Empty/Hint",
            "text": "None"
        },
        "$:/language/ControlPanel/Plugins/Enable/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Enable/Caption",
            "text": "enable"
        },
        "$:/language/ControlPanel/Plugins/Enable/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Enable/Hint",
            "text": "Enable this plugin when reloading page"
        },
        "$:/language/ControlPanel/Plugins/Install/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Install/Caption",
            "text": "install"
        },
        "$:/language/ControlPanel/Plugins/Installed/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Installed/Hint",
            "text": "Currently installed plugins:"
        },
        "$:/language/ControlPanel/Plugins/Languages/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Languages/Caption",
            "text": "Languages"
        },
        "$:/language/ControlPanel/Plugins/Languages/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Languages/Hint",
            "text": "Language pack plugins"
        },
        "$:/language/ControlPanel/Plugins/NoInfoFound/Hint": {
            "title": "$:/language/ControlPanel/Plugins/NoInfoFound/Hint",
            "text": "No ''\"<$text text=<<currentTab>>/>\"'' found"
        },
        "$:/language/ControlPanel/Plugins/NotInstalled/Hint": {
            "title": "$:/language/ControlPanel/Plugins/NotInstalled/Hint",
            "text": "This plugin is not currently installed"
        },
        "$:/language/ControlPanel/Plugins/OpenPluginLibrary": {
            "title": "$:/language/ControlPanel/Plugins/OpenPluginLibrary",
            "text": "open plugin library"
        },
        "$:/language/ControlPanel/Plugins/ClosePluginLibrary": {
            "title": "$:/language/ControlPanel/Plugins/ClosePluginLibrary",
            "text": "close plugin library"
        },
        "$:/language/ControlPanel/Plugins/PluginWillRequireReload": {
            "title": "$:/language/ControlPanel/Plugins/PluginWillRequireReload",
            "text": "(requires reload)"
        },
        "$:/language/ControlPanel/Plugins/Plugins/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Plugins/Caption",
            "text": "Plugins"
        },
        "$:/language/ControlPanel/Plugins/Plugins/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Plugins/Hint",
            "text": "Plugins"
        },
        "$:/language/ControlPanel/Plugins/Reinstall/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Reinstall/Caption",
            "text": "reinstall"
        },
        "$:/language/ControlPanel/Plugins/Themes/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Themes/Caption",
            "text": "Themes"
        },
        "$:/language/ControlPanel/Plugins/Themes/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Themes/Hint",
            "text": "Theme plugins"
        },
        "$:/language/ControlPanel/Plugins/Update/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Update/Caption",
            "text": "update"
        },
        "$:/language/ControlPanel/Plugins/Updates/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Updates/Caption",
            "text": "Updates"
        },
        "$:/language/ControlPanel/Plugins/Updates/Hint": {
            "title": "$:/language/ControlPanel/Plugins/Updates/Hint",
            "text": "Available updates to installed plugins"
        },
        "$:/language/ControlPanel/Plugins/Updates/UpdateAll/Caption": {
            "title": "$:/language/ControlPanel/Plugins/Updates/UpdateAll/Caption",
            "text": "Update <<update-count>> plugins"
        },
        "$:/language/ControlPanel/Plugins/SubPluginPrompt": {
            "title": "$:/language/ControlPanel/Plugins/SubPluginPrompt",
            "text": "With <<count>> sub-plugins available"
        },
        "$:/language/ControlPanel/Saving/Caption": {
            "title": "$:/language/ControlPanel/Saving/Caption",
            "text": "Saving"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Description": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Description",
            "text": "Permit automatic saving for the download saver"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Hint": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Hint",
            "text": "Enable Autosave for Download Saver"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/Caption": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/Caption",
            "text": "Download Saver"
        },
        "$:/language/ControlPanel/Saving/DownloadSaver/Hint": {
            "title": "$:/language/ControlPanel/Saving/DownloadSaver/Hint",
            "text": "These settings apply to the HTML5-compatible download saver"
        },
        "$:/language/ControlPanel/Saving/General/Caption": {
            "title": "$:/language/ControlPanel/Saving/General/Caption",
            "text": "General"
        },
        "$:/language/ControlPanel/Saving/General/Hint": {
            "title": "$:/language/ControlPanel/Saving/General/Hint",
            "text": "These settings apply to all the loaded savers"
        },
        "$:/language/ControlPanel/Saving/Hint": {
            "title": "$:/language/ControlPanel/Saving/Hint",
            "text": "Settings used for saving the entire TiddlyWiki as a single file via a saver module"
        },
        "$:/language/ControlPanel/Saving/GitService/Branch": {
            "title": "$:/language/ControlPanel/Saving/GitService/Branch",
            "text": "Target branch for saving"
        },
        "$:/language/ControlPanel/Saving/GitService/CommitMessage": {
            "title": "$:/language/ControlPanel/Saving/GitService/CommitMessage",
            "text": "Saved by TiddlyWiki"
        },
        "$:/language/ControlPanel/Saving/GitService/Description": {
            "title": "$:/language/ControlPanel/Saving/GitService/Description",
            "text": "These settings are only used when saving to <<service-name>>"
        },
        "$:/language/ControlPanel/Saving/GitService/Filename": {
            "title": "$:/language/ControlPanel/Saving/GitService/Filename",
            "text": "Filename of target file (e.g. `index.html`)"
        },
        "$:/language/ControlPanel/Saving/GitService/Path": {
            "title": "$:/language/ControlPanel/Saving/GitService/Path",
            "text": "Path to target file (e.g. `/wiki/`)"
        },
        "$:/language/ControlPanel/Saving/GitService/Repo": {
            "title": "$:/language/ControlPanel/Saving/GitService/Repo",
            "text": "Target repository (e.g. `Jermolene/TiddlyWiki5`)"
        },
        "$:/language/ControlPanel/Saving/GitService/ServerURL": {
            "title": "$:/language/ControlPanel/Saving/GitService/ServerURL",
            "text": "Server API URL"
        },
        "$:/language/ControlPanel/Saving/GitService/UserName": {
            "title": "$:/language/ControlPanel/Saving/GitService/UserName",
            "text": "Username"
        },
        "$:/language/ControlPanel/Saving/GitService/GitHub/Caption": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitHub/Caption",
            "text": "~GitHub Saver"
        },
        "$:/language/ControlPanel/Saving/GitService/GitHub/Password": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitHub/Password",
            "text": "Password, OAUTH token, or personal access token (see [[GitHub help page|https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line]] for details)"
        },
        "$:/language/ControlPanel/Saving/GitService/GitLab/Caption": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitLab/Caption",
            "text": "~GitLab Saver"
        },
        "$:/language/ControlPanel/Saving/GitService/GitLab/Password": {
            "title": "$:/language/ControlPanel/Saving/GitService/GitLab/Password",
            "text": "Personal access token for API (see [[GitLab help page|https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html]] for details)"
        },
        "$:/language/ControlPanel/Saving/GitService/Gitea/Caption": {
            "title": "$:/language/ControlPanel/Saving/GitService/Gitea/Caption",
            "text": "Gitea Saver"
        },
        "$:/language/ControlPanel/Saving/GitService/Gitea/Password": {
            "title": "$:/language/ControlPanel/Saving/GitService/Gitea/Password",
            "text": "Personal access token for API (via Gitea’s web interface: `Settings | Applications | Generate New Token`)"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading",
            "text": "Advanced Settings"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir",
            "text": "Backup Directory"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Backups": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Backups",
            "text": "Backups"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Caption": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Caption",
            "text": "~TiddlySpot Saver"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Description": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Description",
            "text": "These settings are only used when saving to http://tiddlyspot.com or a compatible remote server"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Filename": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Filename",
            "text": "Upload Filename"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Heading": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Heading",
            "text": "~TiddlySpot"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Hint": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Hint",
            "text": "//The server URL defaults to `http://<wikiname>.tiddlyspot.com/store.cgi` and can be changed to use a custom server address, e.g. `http://example.com/store.php`.//"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/Password": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/Password",
            "text": "Password"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL",
            "text": "Server URL"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir",
            "text": "Upload Directory"
        },
        "$:/language/ControlPanel/Saving/TiddlySpot/UserName": {
            "title": "$:/language/ControlPanel/Saving/TiddlySpot/UserName",
            "text": "Wiki Name"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Caption": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Caption",
            "text": "Autosave"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description",
            "text": "Do not save changes automatically"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description",
            "text": "Save changes automatically"
        },
        "$:/language/ControlPanel/Settings/AutoSave/Hint": {
            "title": "$:/language/ControlPanel/Settings/AutoSave/Hint",
            "text": "Attempt to automatically save changes during editing when using a supporting saver"
        },
        "$:/language/ControlPanel/Settings/CamelCase/Caption": {
            "title": "$:/language/ControlPanel/Settings/CamelCase/Caption",
            "text": "Camel Case Wiki Links"
        },
        "$:/language/ControlPanel/Settings/CamelCase/Hint": {
            "title": "$:/language/ControlPanel/Settings/CamelCase/Hint",
            "text": "You can globally disable automatic linking of ~CamelCase phrases. Requires reload to take effect"
        },
        "$:/language/ControlPanel/Settings/CamelCase/Description": {
            "title": "$:/language/ControlPanel/Settings/CamelCase/Description",
            "text": "Enable automatic ~CamelCase linking"
        },
        "$:/language/ControlPanel/Settings/Caption": {
            "title": "$:/language/ControlPanel/Settings/Caption",
            "text": "Settings"
        },
        "$:/language/ControlPanel/Settings/EditorToolbar/Caption": {
            "title": "$:/language/ControlPanel/Settings/EditorToolbar/Caption",
            "text": "Editor Toolbar"
        },
        "$:/language/ControlPanel/Settings/EditorToolbar/Hint": {
            "title": "$:/language/ControlPanel/Settings/EditorToolbar/Hint",
            "text": "Enable or disable the editor toolbar:"
        },
        "$:/language/ControlPanel/Settings/EditorToolbar/Description": {
            "title": "$:/language/ControlPanel/Settings/EditorToolbar/Description",
            "text": "Show editor toolbar"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Caption": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Caption",
            "text": "Tiddler Info Panel Mode"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Hint": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Hint",
            "text": "Control when the tiddler info panel closes:"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Popup/Description": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Popup/Description",
            "text": "Tiddler info panel closes automatically"
        },
        "$:/language/ControlPanel/Settings/InfoPanelMode/Sticky/Description": {
            "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Sticky/Description",
            "text": "Tiddler info panel stays open until explicitly closed"
        },
        "$:/language/ControlPanel/Settings/Hint": {
            "title": "$:/language/ControlPanel/Settings/Hint",
            "text": "These settings let you customise the behaviour of TiddlyWiki."
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption",
            "text": "Navigation Address Bar"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint",
            "text": "Behaviour of the browser address bar when navigating to a tiddler:"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description",
            "text": "Do not update the address bar"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description",
            "text": "Include the target tiddler"
        },
        "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description",
            "text": "Include the target tiddler and the current story sequence"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/Caption": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/Caption",
            "text": "Navigation History"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/Hint": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/Hint",
            "text": "Update browser history when navigating to a tiddler:"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/No/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/No/Description",
            "text": "Do not update history"
        },
        "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description",
            "text": "Update history"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Caption": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Caption",
            "text": "Permalink/permaview Mode"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Hint": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Hint",
            "text": "Choose how permalink/permaview is handled:"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/CopyToClipboard/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/CopyToClipboard/Description",
            "text": "Copy permalink/permaview URL to clipboard"
        },
        "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/UpdateAddressBar/Description": {
            "title": "$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/UpdateAddressBar/Description",
            "text": "Update address bar with permalink/permaview URL"
        },
        "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption": {
            "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption",
            "text": "Performance Instrumentation"
        },
        "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Hint": {
            "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Hint",
            "text": "Displays performance statistics in the browser developer console. Requires reload to take effect"
        },
        "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Description": {
            "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Description",
            "text": "Enable performance instrumentation"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption",
            "text": "Toolbar Button Style"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint",
            "text": "Choose the style for toolbar buttons:"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless",
            "text": "Borderless"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed",
            "text": "Boxed"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded",
            "text": "Rounded"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Caption": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Caption",
            "text": "Toolbar Buttons"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Hint": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Hint",
            "text": "Default toolbar button appearance:"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description",
            "text": "Include icon"
        },
        "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description": {
            "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description",
            "text": "Include text"
        },
        "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption": {
            "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption",
            "text": "Default Sidebar Tab"
        },
        "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint": {
            "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint",
            "text": "Specify which sidebar tab is displayed by default"
        },
        "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Caption": {
            "title": "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Caption",
            "text": "Default More Sidebar Tab"
        },
        "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Hint": {
            "title": "$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Hint",
            "text": "Specify which More sidebar tab is displayed by default"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption",
            "text": "Tiddler Opening Behaviour"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint",
            "text": "Navigation from //within// the story river"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint",
            "text": "Navigation from //outside// the story river"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove",
            "text": "Open above the current tiddler"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow",
            "text": "Open below the current tiddler"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop",
            "text": "Open at the top of the story river"
        },
        "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom": {
            "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom",
            "text": "Open at the bottom of the story river"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/Caption": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/Caption",
            "text": "Tiddler Titles"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/Hint": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/Hint",
            "text": "Optionally display tiddler titles as links"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/No/Description": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/No/Description",
            "text": "Do not display tiddler titles as links"
        },
        "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description": {
            "title": "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description",
            "text": "Display tiddler titles as links"
        },
        "$:/language/ControlPanel/Settings/MissingLinks/Caption": {
            "title": "$:/language/ControlPanel/Settings/MissingLinks/Caption",
            "text": "Wiki Links"
        },
        "$:/language/ControlPanel/Settings/MissingLinks/Hint": {
            "title": "$:/language/ControlPanel/Settings/MissingLinks/Hint",
            "text": "Choose whether to link to tiddlers that do not exist yet"
        },
        "$:/language/ControlPanel/Settings/MissingLinks/Description": {
            "title": "$:/language/ControlPanel/Settings/MissingLinks/Description",
            "text": "Enable links to missing tiddlers"
        },
        "$:/language/ControlPanel/StoryView/Caption": {
            "title": "$:/language/ControlPanel/StoryView/Caption",
            "text": "Story View"
        },
        "$:/language/ControlPanel/StoryView/Prompt": {
            "title": "$:/language/ControlPanel/StoryView/Prompt",
            "text": "Current view:"
        },
        "$:/language/ControlPanel/Stylesheets/Caption": {
            "title": "$:/language/ControlPanel/Stylesheets/Caption",
            "text": "Stylesheets"
        },
        "$:/language/ControlPanel/Stylesheets/Expand/Caption": {
            "title": "$:/language/ControlPanel/Stylesheets/Expand/Caption",
            "text": "Expand All"
        },
        "$:/language/ControlPanel/Stylesheets/Hint": {
            "title": "$:/language/ControlPanel/Stylesheets/Hint",
            "text": "This is the rendered CSS of the current stylesheet tiddlers tagged with <<tag \"$:/tags/Stylesheet\">>"
        },
        "$:/language/ControlPanel/Stylesheets/Restore/Caption": {
            "title": "$:/language/ControlPanel/Stylesheets/Restore/Caption",
            "text": "Restore"
        },
        "$:/language/ControlPanel/Theme/Caption": {
            "title": "$:/language/ControlPanel/Theme/Caption",
            "text": "Theme"
        },
        "$:/language/ControlPanel/Theme/Prompt": {
            "title": "$:/language/ControlPanel/Theme/Prompt",
            "text": "Current theme:"
        },
        "$:/language/ControlPanel/TiddlerFields/Caption": {
            "title": "$:/language/ControlPanel/TiddlerFields/Caption",
            "text": "Tiddler Fields"
        },
        "$:/language/ControlPanel/TiddlerFields/Hint": {
            "title": "$:/language/ControlPanel/TiddlerFields/Hint",
            "text": "This is the full set of TiddlerFields in use in this wiki (including system tiddlers but excluding shadow tiddlers)."
        },
        "$:/language/ControlPanel/Toolbars/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/Caption",
            "text": "Toolbars"
        },
        "$:/language/ControlPanel/Toolbars/EditToolbar/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Caption",
            "text": "Edit Toolbar"
        },
        "$:/language/ControlPanel/Toolbars/EditToolbar/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Hint",
            "text": "Choose which buttons are displayed for tiddlers in edit mode. Drag and drop to change the ordering"
        },
        "$:/language/ControlPanel/Toolbars/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/Hint",
            "text": "Select which toolbar buttons are displayed"
        },
        "$:/language/ControlPanel/Toolbars/PageControls/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/PageControls/Caption",
            "text": "Page Toolbar"
        },
        "$:/language/ControlPanel/Toolbars/PageControls/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/PageControls/Hint",
            "text": "Choose which buttons are displayed on the main page toolbar. Drag and drop to change the ordering"
        },
        "$:/language/ControlPanel/Toolbars/EditorToolbar/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/EditorToolbar/Caption",
            "text": "Editor Toolbar"
        },
        "$:/language/ControlPanel/Toolbars/EditorToolbar/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/EditorToolbar/Hint",
            "text": "Choose which buttons are displayed in the editor toolbar. Note that some buttons will only appear when editing tiddlers of a certain type. Drag and drop to change the ordering"
        },
        "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption": {
            "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption",
            "text": "View Toolbar"
        },
        "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint": {
            "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint",
            "text": "Choose which buttons are displayed for tiddlers in view mode. Drag and drop to change the ordering"
        },
        "$:/language/ControlPanel/Tools/Download/Full/Caption": {
            "title": "$:/language/ControlPanel/Tools/Download/Full/Caption",
            "text": "Download full wiki"
        },
        "$:/language/Date/DaySuffix/1": {
            "title": "$:/language/Date/DaySuffix/1",
            "text": "st"
        },
        "$:/language/Date/DaySuffix/2": {
            "title": "$:/language/Date/DaySuffix/2",
            "text": "nd"
        },
        "$:/language/Date/DaySuffix/3": {
            "title": "$:/language/Date/DaySuffix/3",
            "text": "rd"
        },
        "$:/language/Date/DaySuffix/4": {
            "title": "$:/language/Date/DaySuffix/4",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/5": {
            "title": "$:/language/Date/DaySuffix/5",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/6": {
            "title": "$:/language/Date/DaySuffix/6",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/7": {
            "title": "$:/language/Date/DaySuffix/7",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/8": {
            "title": "$:/language/Date/DaySuffix/8",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/9": {
            "title": "$:/language/Date/DaySuffix/9",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/10": {
            "title": "$:/language/Date/DaySuffix/10",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/11": {
            "title": "$:/language/Date/DaySuffix/11",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/12": {
            "title": "$:/language/Date/DaySuffix/12",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/13": {
            "title": "$:/language/Date/DaySuffix/13",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/14": {
            "title": "$:/language/Date/DaySuffix/14",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/15": {
            "title": "$:/language/Date/DaySuffix/15",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/16": {
            "title": "$:/language/Date/DaySuffix/16",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/17": {
            "title": "$:/language/Date/DaySuffix/17",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/18": {
            "title": "$:/language/Date/DaySuffix/18",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/19": {
            "title": "$:/language/Date/DaySuffix/19",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/20": {
            "title": "$:/language/Date/DaySuffix/20",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/21": {
            "title": "$:/language/Date/DaySuffix/21",
            "text": "st"
        },
        "$:/language/Date/DaySuffix/22": {
            "title": "$:/language/Date/DaySuffix/22",
            "text": "nd"
        },
        "$:/language/Date/DaySuffix/23": {
            "title": "$:/language/Date/DaySuffix/23",
            "text": "rd"
        },
        "$:/language/Date/DaySuffix/24": {
            "title": "$:/language/Date/DaySuffix/24",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/25": {
            "title": "$:/language/Date/DaySuffix/25",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/26": {
            "title": "$:/language/Date/DaySuffix/26",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/27": {
            "title": "$:/language/Date/DaySuffix/27",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/28": {
            "title": "$:/language/Date/DaySuffix/28",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/29": {
            "title": "$:/language/Date/DaySuffix/29",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/30": {
            "title": "$:/language/Date/DaySuffix/30",
            "text": "th"
        },
        "$:/language/Date/DaySuffix/31": {
            "title": "$:/language/Date/DaySuffix/31",
            "text": "st"
        },
        "$:/language/Date/Long/Day/0": {
            "title": "$:/language/Date/Long/Day/0",
            "text": "Sunday"
        },
        "$:/language/Date/Long/Day/1": {
            "title": "$:/language/Date/Long/Day/1",
            "text": "Monday"
        },
        "$:/language/Date/Long/Day/2": {
            "title": "$:/language/Date/Long/Day/2",
            "text": "Tuesday"
        },
        "$:/language/Date/Long/Day/3": {
            "title": "$:/language/Date/Long/Day/3",
            "text": "Wednesday"
        },
        "$:/language/Date/Long/Day/4": {
            "title": "$:/language/Date/Long/Day/4",
            "text": "Thursday"
        },
        "$:/language/Date/Long/Day/5": {
            "title": "$:/language/Date/Long/Day/5",
            "text": "Friday"
        },
        "$:/language/Date/Long/Day/6": {
            "title": "$:/language/Date/Long/Day/6",
            "text": "Saturday"
        },
        "$:/language/Date/Long/Month/1": {
            "title": "$:/language/Date/Long/Month/1",
            "text": "January"
        },
        "$:/language/Date/Long/Month/2": {
            "title": "$:/language/Date/Long/Month/2",
            "text": "February"
        },
        "$:/language/Date/Long/Month/3": {
            "title": "$:/language/Date/Long/Month/3",
            "text": "March"
        },
        "$:/language/Date/Long/Month/4": {
            "title": "$:/language/Date/Long/Month/4",
            "text": "April"
        },
        "$:/language/Date/Long/Month/5": {
            "title": "$:/language/Date/Long/Month/5",
            "text": "May"
        },
        "$:/language/Date/Long/Month/6": {
            "title": "$:/language/Date/Long/Month/6",
            "text": "June"
        },
        "$:/language/Date/Long/Month/7": {
            "title": "$:/language/Date/Long/Month/7",
            "text": "July"
        },
        "$:/language/Date/Long/Month/8": {
            "title": "$:/language/Date/Long/Month/8",
            "text": "August"
        },
        "$:/language/Date/Long/Month/9": {
            "title": "$:/language/Date/Long/Month/9",
            "text": "September"
        },
        "$:/language/Date/Long/Month/10": {
            "title": "$:/language/Date/Long/Month/10",
            "text": "October"
        },
        "$:/language/Date/Long/Month/11": {
            "title": "$:/language/Date/Long/Month/11",
            "text": "November"
        },
        "$:/language/Date/Long/Month/12": {
            "title": "$:/language/Date/Long/Month/12",
            "text": "December"
        },
        "$:/language/Date/Period/am": {
            "title": "$:/language/Date/Period/am",
            "text": "am"
        },
        "$:/language/Date/Period/pm": {
            "title": "$:/language/Date/Period/pm",
            "text": "pm"
        },
        "$:/language/Date/Short/Day/0": {
            "title": "$:/language/Date/Short/Day/0",
            "text": "Sun"
        },
        "$:/language/Date/Short/Day/1": {
            "title": "$:/language/Date/Short/Day/1",
            "text": "Mon"
        },
        "$:/language/Date/Short/Day/2": {
            "title": "$:/language/Date/Short/Day/2",
            "text": "Tue"
        },
        "$:/language/Date/Short/Day/3": {
            "title": "$:/language/Date/Short/Day/3",
            "text": "Wed"
        },
        "$:/language/Date/Short/Day/4": {
            "title": "$:/language/Date/Short/Day/4",
            "text": "Thu"
        },
        "$:/language/Date/Short/Day/5": {
            "title": "$:/language/Date/Short/Day/5",
            "text": "Fri"
        },
        "$:/language/Date/Short/Day/6": {
            "title": "$:/language/Date/Short/Day/6",
            "text": "Sat"
        },
        "$:/language/Date/Short/Month/1": {
            "title": "$:/language/Date/Short/Month/1",
            "text": "Jan"
        },
        "$:/language/Date/Short/Month/2": {
            "title": "$:/language/Date/Short/Month/2",
            "text": "Feb"
        },
        "$:/language/Date/Short/Month/3": {
            "title": "$:/language/Date/Short/Month/3",
            "text": "Mar"
        },
        "$:/language/Date/Short/Month/4": {
            "title": "$:/language/Date/Short/Month/4",
            "text": "Apr"
        },
        "$:/language/Date/Short/Month/5": {
            "title": "$:/language/Date/Short/Month/5",
            "text": "May"
        },
        "$:/language/Date/Short/Month/6": {
            "title": "$:/language/Date/Short/Month/6",
            "text": "Jun"
        },
        "$:/language/Date/Short/Month/7": {
            "title": "$:/language/Date/Short/Month/7",
            "text": "Jul"
        },
        "$:/language/Date/Short/Month/8": {
            "title": "$:/language/Date/Short/Month/8",
            "text": "Aug"
        },
        "$:/language/Date/Short/Month/9": {
            "title": "$:/language/Date/Short/Month/9",
            "text": "Sep"
        },
        "$:/language/Date/Short/Month/10": {
            "title": "$:/language/Date/Short/Month/10",
            "text": "Oct"
        },
        "$:/language/Date/Short/Month/11": {
            "title": "$:/language/Date/Short/Month/11",
            "text": "Nov"
        },
        "$:/language/Date/Short/Month/12": {
            "title": "$:/language/Date/Short/Month/12",
            "text": "Dec"
        },
        "$:/language/RelativeDate/Future/Days": {
            "title": "$:/language/RelativeDate/Future/Days",
            "text": "<<period>> days from now"
        },
        "$:/language/RelativeDate/Future/Hours": {
            "title": "$:/language/RelativeDate/Future/Hours",
            "text": "<<period>> hours from now"
        },
        "$:/language/RelativeDate/Future/Minutes": {
            "title": "$:/language/RelativeDate/Future/Minutes",
            "text": "<<period>> minutes from now"
        },
        "$:/language/RelativeDate/Future/Months": {
            "title": "$:/language/RelativeDate/Future/Months",
            "text": "<<period>> months from now"
        },
        "$:/language/RelativeDate/Future/Second": {
            "title": "$:/language/RelativeDate/Future/Second",
            "text": "1 second from now"
        },
        "$:/language/RelativeDate/Future/Seconds": {
            "title": "$:/language/RelativeDate/Future/Seconds",
            "text": "<<period>> seconds from now"
        },
        "$:/language/RelativeDate/Future/Years": {
            "title": "$:/language/RelativeDate/Future/Years",
            "text": "<<period>> years from now"
        },
        "$:/language/RelativeDate/Past/Days": {
            "title": "$:/language/RelativeDate/Past/Days",
            "text": "<<period>> days ago"
        },
        "$:/language/RelativeDate/Past/Hours": {
            "title": "$:/language/RelativeDate/Past/Hours",
            "text": "<<period>> hours ago"
        },
        "$:/language/RelativeDate/Past/Minutes": {
            "title": "$:/language/RelativeDate/Past/Minutes",
            "text": "<<period>> minutes ago"
        },
        "$:/language/RelativeDate/Past/Months": {
            "title": "$:/language/RelativeDate/Past/Months",
            "text": "<<period>> months ago"
        },
        "$:/language/RelativeDate/Past/Second": {
            "title": "$:/language/RelativeDate/Past/Second",
            "text": "1 second ago"
        },
        "$:/language/RelativeDate/Past/Seconds": {
            "title": "$:/language/RelativeDate/Past/Seconds",
            "text": "<<period>> seconds ago"
        },
        "$:/language/RelativeDate/Past/Years": {
            "title": "$:/language/RelativeDate/Past/Years",
            "text": "<<period>> years ago"
        },
        "$:/language/Docs/ModuleTypes/allfilteroperator": {
            "title": "$:/language/Docs/ModuleTypes/allfilteroperator",
            "text": "A sub-operator for the ''all'' filter operator."
        },
        "$:/language/Docs/ModuleTypes/animation": {
            "title": "$:/language/Docs/ModuleTypes/animation",
            "text": "Animations that may be used with the RevealWidget."
        },
        "$:/language/Docs/ModuleTypes/authenticator": {
            "title": "$:/language/Docs/ModuleTypes/authenticator",
            "text": "Defines how requests are authenticated by the built-in HTTP server."
        },
        "$:/language/Docs/ModuleTypes/bitmapeditoroperation": {
            "title": "$:/language/Docs/ModuleTypes/bitmapeditoroperation",
            "text": "A bitmap editor toolbar operation."
        },
        "$:/language/Docs/ModuleTypes/command": {
            "title": "$:/language/Docs/ModuleTypes/command",
            "text": "Commands that can be executed under Node.js."
        },
        "$:/language/Docs/ModuleTypes/config": {
            "title": "$:/language/Docs/ModuleTypes/config",
            "text": "Data to be inserted into `$tw.config`."
        },
        "$:/language/Docs/ModuleTypes/filteroperator": {
            "title": "$:/language/Docs/ModuleTypes/filteroperator",
            "text": "Individual filter operator methods."
        },
        "$:/language/Docs/ModuleTypes/global": {
            "title": "$:/language/Docs/ModuleTypes/global",
            "text": "Global data to be inserted into `$tw`."
        },
        "$:/language/Docs/ModuleTypes/info": {
            "title": "$:/language/Docs/ModuleTypes/info",
            "text": "Publishes system information via the [[$:/temp/info-plugin]] pseudo-plugin."
        },
        "$:/language/Docs/ModuleTypes/isfilteroperator": {
            "title": "$:/language/Docs/ModuleTypes/isfilteroperator",
            "text": "Operands for the ''is'' filter operator."
        },
        "$:/language/Docs/ModuleTypes/library": {
            "title": "$:/language/Docs/ModuleTypes/library",
            "text": "Generic module type for general purpose JavaScript modules."
        },
        "$:/language/Docs/ModuleTypes/macro": {
            "title": "$:/language/Docs/ModuleTypes/macro",
            "text": "JavaScript macro definitions."
        },
        "$:/language/Docs/ModuleTypes/parser": {
            "title": "$:/language/Docs/ModuleTypes/parser",
            "text": "Parsers for different content types."
        },
        "$:/language/Docs/ModuleTypes/route": {
            "title": "$:/language/Docs/ModuleTypes/route",
            "text": "Defines how individual URL patterns are handled by the built-in HTTP server."
        },
        "$:/language/Docs/ModuleTypes/saver": {
            "title": "$:/language/Docs/ModuleTypes/saver",
            "text": "Savers handle different methods for saving files from the browser."
        },
        "$:/language/Docs/ModuleTypes/startup": {
            "title": "$:/language/Docs/ModuleTypes/startup",
            "text": "Startup functions."
        },
        "$:/language/Docs/ModuleTypes/storyview": {
            "title": "$:/language/Docs/ModuleTypes/storyview",
            "text": "Story views customise the animation and behaviour of list widgets."
        },
        "$:/language/Docs/ModuleTypes/texteditoroperation": {
            "title": "$:/language/Docs/ModuleTypes/texteditoroperation",
            "text": "A text editor toolbar operation."
        },
        "$:/language/Docs/ModuleTypes/tiddlerdeserializer": {
            "title": "$:/language/Docs/ModuleTypes/tiddlerdeserializer",
            "text": "Converts different content types into tiddlers."
        },
        "$:/language/Docs/ModuleTypes/tiddlerfield": {
            "title": "$:/language/Docs/ModuleTypes/tiddlerfield",
            "text": "Defines the behaviour of an individual tiddler field."
        },
        "$:/language/Docs/ModuleTypes/tiddlermethod": {
            "title": "$:/language/Docs/ModuleTypes/tiddlermethod",
            "text": "Adds methods to the `$tw.Tiddler` prototype."
        },
        "$:/language/Docs/ModuleTypes/upgrader": {
            "title": "$:/language/Docs/ModuleTypes/upgrader",
            "text": "Applies upgrade processing to tiddlers during an upgrade/import."
        },
        "$:/language/Docs/ModuleTypes/utils": {
            "title": "$:/language/Docs/ModuleTypes/utils",
            "text": "Adds methods to `$tw.utils`."
        },
        "$:/language/Docs/ModuleTypes/utils-node": {
            "title": "$:/language/Docs/ModuleTypes/utils-node",
            "text": "Adds Node.js-specific methods to `$tw.utils`."
        },
        "$:/language/Docs/ModuleTypes/widget": {
            "title": "$:/language/Docs/ModuleTypes/widget",
            "text": "Widgets encapsulate DOM rendering and refreshing."
        },
        "$:/language/Docs/ModuleTypes/wikimethod": {
            "title": "$:/language/Docs/ModuleTypes/wikimethod",
            "text": "Adds methods to `$tw.Wiki`."
        },
        "$:/language/Docs/ModuleTypes/wikirule": {
            "title": "$:/language/Docs/ModuleTypes/wikirule",
            "text": "Individual parser rules for the main WikiText parser."
        },
        "$:/language/Docs/PaletteColours/alert-background": {
            "title": "$:/language/Docs/PaletteColours/alert-background",
            "text": "Alert background"
        },
        "$:/language/Docs/PaletteColours/alert-border": {
            "title": "$:/language/Docs/PaletteColours/alert-border",
            "text": "Alert border"
        },
        "$:/language/Docs/PaletteColours/alert-highlight": {
            "title": "$:/language/Docs/PaletteColours/alert-highlight",
            "text": "Alert highlight"
        },
        "$:/language/Docs/PaletteColours/alert-muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/alert-muted-foreground",
            "text": "Alert muted foreground"
        },
        "$:/language/Docs/PaletteColours/background": {
            "title": "$:/language/Docs/PaletteColours/background",
            "text": "General background"
        },
        "$:/language/Docs/PaletteColours/blockquote-bar": {
            "title": "$:/language/Docs/PaletteColours/blockquote-bar",
            "text": "Blockquote bar"
        },
        "$:/language/Docs/PaletteColours/button-background": {
            "title": "$:/language/Docs/PaletteColours/button-background",
            "text": "Default button background"
        },
        "$:/language/Docs/PaletteColours/button-border": {
            "title": "$:/language/Docs/PaletteColours/button-border",
            "text": "Default button border"
        },
        "$:/language/Docs/PaletteColours/button-foreground": {
            "title": "$:/language/Docs/PaletteColours/button-foreground",
            "text": "Default button foreground"
        },
        "$:/language/Docs/PaletteColours/dirty-indicator": {
            "title": "$:/language/Docs/PaletteColours/dirty-indicator",
            "text": "Unsaved changes indicator"
        },
        "$:/language/Docs/PaletteColours/code-background": {
            "title": "$:/language/Docs/PaletteColours/code-background",
            "text": "Code background"
        },
        "$:/language/Docs/PaletteColours/code-border": {
            "title": "$:/language/Docs/PaletteColours/code-border",
            "text": "Code border"
        },
        "$:/language/Docs/PaletteColours/code-foreground": {
            "title": "$:/language/Docs/PaletteColours/code-foreground",
            "text": "Code foreground"
        },
        "$:/language/Docs/PaletteColours/download-background": {
            "title": "$:/language/Docs/PaletteColours/download-background",
            "text": "Download button background"
        },
        "$:/language/Docs/PaletteColours/download-foreground": {
            "title": "$:/language/Docs/PaletteColours/download-foreground",
            "text": "Download button foreground"
        },
        "$:/language/Docs/PaletteColours/dragger-background": {
            "title": "$:/language/Docs/PaletteColours/dragger-background",
            "text": "Dragger background"
        },
        "$:/language/Docs/PaletteColours/dragger-foreground": {
            "title": "$:/language/Docs/PaletteColours/dragger-foreground",
            "text": "Dragger foreground"
        },
        "$:/language/Docs/PaletteColours/dropdown-background": {
            "title": "$:/language/Docs/PaletteColours/dropdown-background",
            "text": "Dropdown background"
        },
        "$:/language/Docs/PaletteColours/dropdown-border": {
            "title": "$:/language/Docs/PaletteColours/dropdown-border",
            "text": "Dropdown border"
        },
        "$:/language/Docs/PaletteColours/dropdown-tab-background-selected": {
            "title": "$:/language/Docs/PaletteColours/dropdown-tab-background-selected",
            "text": "Dropdown tab background for selected tabs"
        },
        "$:/language/Docs/PaletteColours/dropdown-tab-background": {
            "title": "$:/language/Docs/PaletteColours/dropdown-tab-background",
            "text": "Dropdown tab background"
        },
        "$:/language/Docs/PaletteColours/dropzone-background": {
            "title": "$:/language/Docs/PaletteColours/dropzone-background",
            "text": "Dropzone background"
        },
        "$:/language/Docs/PaletteColours/external-link-background-hover": {
            "title": "$:/language/Docs/PaletteColours/external-link-background-hover",
            "text": "External link background hover"
        },
        "$:/language/Docs/PaletteColours/external-link-background-visited": {
            "title": "$:/language/Docs/PaletteColours/external-link-background-visited",
            "text": "External link background visited"
        },
        "$:/language/Docs/PaletteColours/external-link-background": {
            "title": "$:/language/Docs/PaletteColours/external-link-background",
            "text": "External link background"
        },
        "$:/language/Docs/PaletteColours/external-link-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/external-link-foreground-hover",
            "text": "External link foreground hover"
        },
        "$:/language/Docs/PaletteColours/external-link-foreground-visited": {
            "title": "$:/language/Docs/PaletteColours/external-link-foreground-visited",
            "text": "External link foreground visited"
        },
        "$:/language/Docs/PaletteColours/external-link-foreground": {
            "title": "$:/language/Docs/PaletteColours/external-link-foreground",
            "text": "External link foreground"
        },
        "$:/language/Docs/PaletteColours/foreground": {
            "title": "$:/language/Docs/PaletteColours/foreground",
            "text": "General foreground"
        },
        "$:/language/Docs/PaletteColours/menubar-background": {
            "title": "$:/language/Docs/PaletteColours/menubar-background",
            "text": "Menu bar background"
        },
        "$:/language/Docs/PaletteColours/menubar-foreground": {
            "title": "$:/language/Docs/PaletteColours/menubar-foreground",
            "text": "Menu bar foreground"
        },
        "$:/language/Docs/PaletteColours/message-background": {
            "title": "$:/language/Docs/PaletteColours/message-background",
            "text": "Message box background"
        },
        "$:/language/Docs/PaletteColours/message-border": {
            "title": "$:/language/Docs/PaletteColours/message-border",
            "text": "Message box border"
        },
        "$:/language/Docs/PaletteColours/message-foreground": {
            "title": "$:/language/Docs/PaletteColours/message-foreground",
            "text": "Message box foreground"
        },
        "$:/language/Docs/PaletteColours/modal-backdrop": {
            "title": "$:/language/Docs/PaletteColours/modal-backdrop",
            "text": "Modal backdrop"
        },
        "$:/language/Docs/PaletteColours/modal-background": {
            "title": "$:/language/Docs/PaletteColours/modal-background",
            "text": "Modal background"
        },
        "$:/language/Docs/PaletteColours/modal-border": {
            "title": "$:/language/Docs/PaletteColours/modal-border",
            "text": "Modal border"
        },
        "$:/language/Docs/PaletteColours/modal-footer-background": {
            "title": "$:/language/Docs/PaletteColours/modal-footer-background",
            "text": "Modal footer background"
        },
        "$:/language/Docs/PaletteColours/modal-footer-border": {
            "title": "$:/language/Docs/PaletteColours/modal-footer-border",
            "text": "Modal footer border"
        },
        "$:/language/Docs/PaletteColours/modal-header-border": {
            "title": "$:/language/Docs/PaletteColours/modal-header-border",
            "text": "Modal header border"
        },
        "$:/language/Docs/PaletteColours/muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/muted-foreground",
            "text": "General muted foreground"
        },
        "$:/language/Docs/PaletteColours/notification-background": {
            "title": "$:/language/Docs/PaletteColours/notification-background",
            "text": "Notification background"
        },
        "$:/language/Docs/PaletteColours/notification-border": {
            "title": "$:/language/Docs/PaletteColours/notification-border",
            "text": "Notification border"
        },
        "$:/language/Docs/PaletteColours/page-background": {
            "title": "$:/language/Docs/PaletteColours/page-background",
            "text": "Page background"
        },
        "$:/language/Docs/PaletteColours/pre-background": {
            "title": "$:/language/Docs/PaletteColours/pre-background",
            "text": "Preformatted code background"
        },
        "$:/language/Docs/PaletteColours/pre-border": {
            "title": "$:/language/Docs/PaletteColours/pre-border",
            "text": "Preformatted code border"
        },
        "$:/language/Docs/PaletteColours/primary": {
            "title": "$:/language/Docs/PaletteColours/primary",
            "text": "General primary"
        },
        "$:/language/Docs/PaletteColours/select-tag-background": {
            "title": "$:/language/Docs/PaletteColours/select-tag-background",
            "text": "`<select>` element background"
        },
        "$:/language/Docs/PaletteColours/select-tag-foreground": {
            "title": "$:/language/Docs/PaletteColours/select-tag-foreground",
            "text": "`<select>` element text"
        },
        "$:/language/Docs/PaletteColours/sidebar-button-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-button-foreground",
            "text": "Sidebar button foreground"
        },
        "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover",
            "text": "Sidebar controls foreground hover"
        },
        "$:/language/Docs/PaletteColours/sidebar-controls-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground",
            "text": "Sidebar controls foreground"
        },
        "$:/language/Docs/PaletteColours/sidebar-foreground-shadow": {
            "title": "$:/language/Docs/PaletteColours/sidebar-foreground-shadow",
            "text": "Sidebar foreground shadow"
        },
        "$:/language/Docs/PaletteColours/sidebar-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-foreground",
            "text": "Sidebar foreground"
        },
        "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover",
            "text": "Sidebar muted foreground hover"
        },
        "$:/language/Docs/PaletteColours/sidebar-muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground",
            "text": "Sidebar muted foreground"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-background-selected": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-background-selected",
            "text": "Sidebar tab background for selected tabs"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-background": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-background",
            "text": "Sidebar tab background"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-border-selected": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-border-selected",
            "text": "Sidebar tab border for selected tabs"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-border": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-border",
            "text": "Sidebar tab border"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-divider": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-divider",
            "text": "Sidebar tab divider"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected",
            "text": "Sidebar tab foreground for selected tabs"
        },
        "$:/language/Docs/PaletteColours/sidebar-tab-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground",
            "text": "Sidebar tab foreground"
        },
        "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover",
            "text": "Sidebar tiddler link foreground hover"
        },
        "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground": {
            "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground",
            "text": "Sidebar tiddler link foreground"
        },
        "$:/language/Docs/PaletteColours/site-title-foreground": {
            "title": "$:/language/Docs/PaletteColours/site-title-foreground",
            "text": "Site title foreground"
        },
        "$:/language/Docs/PaletteColours/static-alert-foreground": {
            "title": "$:/language/Docs/PaletteColours/static-alert-foreground",
            "text": "Static alert foreground"
        },
        "$:/language/Docs/PaletteColours/tab-background-selected": {
            "title": "$:/language/Docs/PaletteColours/tab-background-selected",
            "text": "Tab background for selected tabs"
        },
        "$:/language/Docs/PaletteColours/tab-background": {
            "title": "$:/language/Docs/PaletteColours/tab-background",
            "text": "Tab background"
        },
        "$:/language/Docs/PaletteColours/tab-border-selected": {
            "title": "$:/language/Docs/PaletteColours/tab-border-selected",
            "text": "Tab border for selected tabs"
        },
        "$:/language/Docs/PaletteColours/tab-border": {
            "title": "$:/language/Docs/PaletteColours/tab-border",
            "text": "Tab border"
        },
        "$:/language/Docs/PaletteColours/tab-divider": {
            "title": "$:/language/Docs/PaletteColours/tab-divider",
            "text": "Tab divider"
        },
        "$:/language/Docs/PaletteColours/tab-foreground-selected": {
            "title": "$:/language/Docs/PaletteColours/tab-foreground-selected",
            "text": "Tab foreground for selected tabs"
        },
        "$:/language/Docs/PaletteColours/tab-foreground": {
            "title": "$:/language/Docs/PaletteColours/tab-foreground",
            "text": "Tab foreground"
        },
        "$:/language/Docs/PaletteColours/table-border": {
            "title": "$:/language/Docs/PaletteColours/table-border",
            "text": "Table border"
        },
        "$:/language/Docs/PaletteColours/table-footer-background": {
            "title": "$:/language/Docs/PaletteColours/table-footer-background",
            "text": "Table footer background"
        },
        "$:/language/Docs/PaletteColours/table-header-background": {
            "title": "$:/language/Docs/PaletteColours/table-header-background",
            "text": "Table header background"
        },
        "$:/language/Docs/PaletteColours/tag-background": {
            "title": "$:/language/Docs/PaletteColours/tag-background",
            "text": "Tag background"
        },
        "$:/language/Docs/PaletteColours/tag-foreground": {
            "title": "$:/language/Docs/PaletteColours/tag-foreground",
            "text": "Tag foreground"
        },
        "$:/language/Docs/PaletteColours/tiddler-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-background",
            "text": "Tiddler background"
        },
        "$:/language/Docs/PaletteColours/tiddler-border": {
            "title": "$:/language/Docs/PaletteColours/tiddler-border",
            "text": "Tiddler border"
        },
        "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover": {
            "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover",
            "text": "Tiddler controls foreground hover"
        },
        "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected": {
            "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected",
            "text": "Tiddler controls foreground for selected controls"
        },
        "$:/language/Docs/PaletteColours/tiddler-controls-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground",
            "text": "Tiddler controls foreground"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-background",
            "text": "Tiddler editor background"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-border-image": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-border-image",
            "text": "Tiddler editor border image"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-border": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-border",
            "text": "Tiddler editor border"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-fields-even": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-even",
            "text": "Tiddler editor background for even fields"
        },
        "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd": {
            "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd",
            "text": "Tiddler editor background for odd fields"
        },
        "$:/language/Docs/PaletteColours/tiddler-info-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-info-background",
            "text": "Tiddler info panel background"
        },
        "$:/language/Docs/PaletteColours/tiddler-info-border": {
            "title": "$:/language/Docs/PaletteColours/tiddler-info-border",
            "text": "Tiddler info panel border"
        },
        "$:/language/Docs/PaletteColours/tiddler-info-tab-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-info-tab-background",
            "text": "Tiddler info panel tab background"
        },
        "$:/language/Docs/PaletteColours/tiddler-link-background": {
            "title": "$:/language/Docs/PaletteColours/tiddler-link-background",
            "text": "Tiddler link background"
        },
        "$:/language/Docs/PaletteColours/tiddler-link-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-link-foreground",
            "text": "Tiddler link foreground"
        },
        "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground",
            "text": "Tiddler subtitle foreground"
        },
        "$:/language/Docs/PaletteColours/tiddler-title-foreground": {
            "title": "$:/language/Docs/PaletteColours/tiddler-title-foreground",
            "text": "Tiddler title foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-new-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-new-button",
            "text": "Toolbar 'new tiddler' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-options-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-options-button",
            "text": "Toolbar 'options' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-save-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-save-button",
            "text": "Toolbar 'save' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-info-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-info-button",
            "text": "Toolbar 'info' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-edit-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-edit-button",
            "text": "Toolbar 'edit' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-close-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-close-button",
            "text": "Toolbar 'close' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-delete-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-delete-button",
            "text": "Toolbar 'delete' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-cancel-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-cancel-button",
            "text": "Toolbar 'cancel' button foreground"
        },
        "$:/language/Docs/PaletteColours/toolbar-done-button": {
            "title": "$:/language/Docs/PaletteColours/toolbar-done-button",
            "text": "Toolbar 'done' button foreground"
        },
        "$:/language/Docs/PaletteColours/untagged-background": {
            "title": "$:/language/Docs/PaletteColours/untagged-background",
            "text": "Untagged pill background"
        },
        "$:/language/Docs/PaletteColours/very-muted-foreground": {
            "title": "$:/language/Docs/PaletteColours/very-muted-foreground",
            "text": "Very muted foreground"
        },
        "$:/language/EditTemplate/Body/External/Hint": {
            "title": "$:/language/EditTemplate/Body/External/Hint",
            "text": "This tiddler shows content stored outside of the main TiddlyWiki file. You can edit the tags and fields but cannot directly edit the content itself"
        },
        "$:/language/EditTemplate/Body/Placeholder": {
            "title": "$:/language/EditTemplate/Body/Placeholder",
            "text": "Type the text for this tiddler"
        },
        "$:/language/EditTemplate/Body/Preview/Type/Output": {
            "title": "$:/language/EditTemplate/Body/Preview/Type/Output",
            "text": "output"
        },
        "$:/language/EditTemplate/Field/Remove/Caption": {
            "title": "$:/language/EditTemplate/Field/Remove/Caption",
            "text": "remove field"
        },
        "$:/language/EditTemplate/Field/Remove/Hint": {
            "title": "$:/language/EditTemplate/Field/Remove/Hint",
            "text": "Remove field"
        },
        "$:/language/EditTemplate/Field/Dropdown/Caption": {
            "title": "$:/language/EditTemplate/Field/Dropdown/Caption",
            "text": "field list"
        },
        "$:/language/EditTemplate/Field/Dropdown/Hint": {
            "title": "$:/language/EditTemplate/Field/Dropdown/Hint",
            "text": "Show field list"
        },
        "$:/language/EditTemplate/Fields/Add/Button": {
            "title": "$:/language/EditTemplate/Fields/Add/Button",
            "text": "add"
        },
        "$:/language/EditTemplate/Fields/Add/Button/Hint": {
            "title": "$:/language/EditTemplate/Fields/Add/Button/Hint",
            "text": "Add the new field to the tiddler"
        },
        "$:/language/EditTemplate/Fields/Add/Name/Placeholder": {
            "title": "$:/language/EditTemplate/Fields/Add/Name/Placeholder",
            "text": "field name"
        },
        "$:/language/EditTemplate/Fields/Add/Prompt": {
            "title": "$:/language/EditTemplate/Fields/Add/Prompt",
            "text": "Add a new field:"
        },
        "$:/language/EditTemplate/Fields/Add/Value/Placeholder": {
            "title": "$:/language/EditTemplate/Fields/Add/Value/Placeholder",
            "text": "field value"
        },
        "$:/language/EditTemplate/Fields/Add/Dropdown/System": {
            "title": "$:/language/EditTemplate/Fields/Add/Dropdown/System",
            "text": "System fields"
        },
        "$:/language/EditTemplate/Fields/Add/Dropdown/User": {
            "title": "$:/language/EditTemplate/Fields/Add/Dropdown/User",
            "text": "User fields"
        },
        "$:/language/EditTemplate/Shadow/Warning": {
            "title": "$:/language/EditTemplate/Shadow/Warning",
            "text": "This is a shadow tiddler. Any changes you make will override the default version from the plugin <<pluginLink>>"
        },
        "$:/language/EditTemplate/Shadow/OverriddenWarning": {
            "title": "$:/language/EditTemplate/Shadow/OverriddenWarning",
            "text": "This is a modified shadow tiddler. You can revert to the default version in the plugin <<pluginLink>> by deleting this tiddler"
        },
        "$:/language/EditTemplate/Tags/Add/Button": {
            "title": "$:/language/EditTemplate/Tags/Add/Button",
            "text": "add"
        },
        "$:/language/EditTemplate/Tags/Add/Button/Hint": {
            "title": "$:/language/EditTemplate/Tags/Add/Button/Hint",
            "text": "add tag"
        },
        "$:/language/EditTemplate/Tags/Add/Placeholder": {
            "title": "$:/language/EditTemplate/Tags/Add/Placeholder",
            "text": "tag name"
        },
        "$:/language/EditTemplate/Tags/Dropdown/Caption": {
            "title": "$:/language/EditTemplate/Tags/Dropdown/Caption",
            "text": "tag list"
        },
        "$:/language/EditTemplate/Tags/Dropdown/Hint": {
            "title": "$:/language/EditTemplate/Tags/Dropdown/Hint",
            "text": "Show tag list"
        },
        "$:/language/EditTemplate/Title/BadCharacterWarning": {
            "title": "$:/language/EditTemplate/Title/BadCharacterWarning",
            "text": "Warning: avoid using any of the characters <<bad-chars>> in tiddler titles"
        },
        "$:/language/EditTemplate/Title/Exists/Prompt": {
            "title": "$:/language/EditTemplate/Title/Exists/Prompt",
            "text": "Target tiddler already exists"
        },
        "$:/language/EditTemplate/Title/Relink/Prompt": {
            "title": "$:/language/EditTemplate/Title/Relink/Prompt",
            "text": "Update ''<$text text=<<fromTitle>>/>'' to ''<$text text=<<toTitle>>/>'' in the //tags// and //list// fields of other tiddlers"
        },
        "$:/language/EditTemplate/Title/References/Prompt": {
            "title": "$:/language/EditTemplate/Title/References/Prompt",
            "text": "The following references to this tiddler will not be automatically updated:"
        },
        "$:/language/EditTemplate/Type/Dropdown/Caption": {
            "title": "$:/language/EditTemplate/Type/Dropdown/Caption",
            "text": "content type list"
        },
        "$:/language/EditTemplate/Type/Dropdown/Hint": {
            "title": "$:/language/EditTemplate/Type/Dropdown/Hint",
            "text": "Show content type list"
        },
        "$:/language/EditTemplate/Type/Delete/Caption": {
            "title": "$:/language/EditTemplate/Type/Delete/Caption",
            "text": "delete content type"
        },
        "$:/language/EditTemplate/Type/Delete/Hint": {
            "title": "$:/language/EditTemplate/Type/Delete/Hint",
            "text": "Delete content type"
        },
        "$:/language/EditTemplate/Type/Placeholder": {
            "title": "$:/language/EditTemplate/Type/Placeholder",
            "text": "content type"
        },
        "$:/language/EditTemplate/Type/Prompt": {
            "title": "$:/language/EditTemplate/Type/Prompt",
            "text": "Type:"
        },
        "$:/language/Exporters/StaticRiver": {
            "title": "$:/language/Exporters/StaticRiver",
            "text": "Static HTML"
        },
        "$:/language/Exporters/JsonFile": {
            "title": "$:/language/Exporters/JsonFile",
            "text": "JSON file"
        },
        "$:/language/Exporters/CsvFile": {
            "title": "$:/language/Exporters/CsvFile",
            "text": "CSV file"
        },
        "$:/language/Exporters/TidFile": {
            "title": "$:/language/Exporters/TidFile",
            "text": "\".tid\" file"
        },
        "$:/language/Docs/Fields/_canonical_uri": {
            "title": "$:/language/Docs/Fields/_canonical_uri",
            "text": "The full URI of an external image tiddler"
        },
        "$:/language/Docs/Fields/bag": {
            "title": "$:/language/Docs/Fields/bag",
            "text": "The name of the bag from which a tiddler came"
        },
        "$:/language/Docs/Fields/caption": {
            "title": "$:/language/Docs/Fields/caption",
            "text": "The text to be displayed on a tab or button"
        },
        "$:/language/Docs/Fields/color": {
            "title": "$:/language/Docs/Fields/color",
            "text": "The CSS color value associated with a tiddler"
        },
        "$:/language/Docs/Fields/component": {
            "title": "$:/language/Docs/Fields/component",
            "text": "The name of the component responsible for an [[alert tiddler|AlertMechanism]]"
        },
        "$:/language/Docs/Fields/current-tiddler": {
            "title": "$:/language/Docs/Fields/current-tiddler",
            "text": "Used to cache the top tiddler in a [[history list|HistoryMechanism]]"
        },
        "$:/language/Docs/Fields/created": {
            "title": "$:/language/Docs/Fields/created",
            "text": "The date a tiddler was created"
        },
        "$:/language/Docs/Fields/creator": {
            "title": "$:/language/Docs/Fields/creator",
            "text": "The name of the person who created a tiddler"
        },
        "$:/language/Docs/Fields/dependents": {
            "title": "$:/language/Docs/Fields/dependents",
            "text": "For a plugin, lists the dependent plugin titles"
        },
        "$:/language/Docs/Fields/description": {
            "title": "$:/language/Docs/Fields/description",
            "text": "The descriptive text for a plugin, or a modal dialogue"
        },
        "$:/language/Docs/Fields/draft.of": {
            "title": "$:/language/Docs/Fields/draft.of",
            "text": "For draft tiddlers, contains the title of the tiddler of which this is a draft"
        },
        "$:/language/Docs/Fields/draft.title": {
            "title": "$:/language/Docs/Fields/draft.title",
            "text": "For draft tiddlers, contains the proposed new title of the tiddler"
        },
        "$:/language/Docs/Fields/footer": {
            "title": "$:/language/Docs/Fields/footer",
            "text": "The footer text for a wizard"
        },
        "$:/language/Docs/Fields/hide-body": {
            "title": "$:/language/Docs/Fields/hide-body",
            "text": "The view template will hide bodies of tiddlers if set to: ''yes''"
        },
        "$:/language/Docs/Fields/icon": {
            "title": "$:/language/Docs/Fields/icon",
            "text": "The title of the tiddler containing the icon associated with a tiddler"
        },
        "$:/language/Docs/Fields/library": {
            "title": "$:/language/Docs/Fields/library",
            "text": "Indicates that a tiddler should be saved as a JavaScript library if set to: ''yes''"
        },
        "$:/language/Docs/Fields/list": {
            "title": "$:/language/Docs/Fields/list",
            "text": "An ordered list of tiddler titles associated with a tiddler"
        },
        "$:/language/Docs/Fields/list-before": {
            "title": "$:/language/Docs/Fields/list-before",
            "text": "If set, the title of a tiddler before which this tiddler should be added to the ordered list of tiddler titles, or at the start of the list if this field is present but empty"
        },
        "$:/language/Docs/Fields/list-after": {
            "title": "$:/language/Docs/Fields/list-after",
            "text": "If set, the title of the tiddler after which this tiddler should be added to the ordered list of tiddler titles, or at the end of the list if this field is present but empty"
        },
        "$:/language/Docs/Fields/modified": {
            "title": "$:/language/Docs/Fields/modified",
            "text": "The date and time at which a tiddler was last modified"
        },
        "$:/language/Docs/Fields/modifier": {
            "title": "$:/language/Docs/Fields/modifier",
            "text": "The tiddler title associated with the person who last modified a tiddler"
        },
        "$:/language/Docs/Fields/name": {
            "title": "$:/language/Docs/Fields/name",
            "text": "The human readable name associated with a plugin tiddler"
        },
        "$:/language/Docs/Fields/plugin-priority": {
            "title": "$:/language/Docs/Fields/plugin-priority",
            "text": "A numerical value indicating the priority of a plugin tiddler"
        },
        "$:/language/Docs/Fields/plugin-type": {
            "title": "$:/language/Docs/Fields/plugin-type",
            "text": "The type of plugin in a plugin tiddler"
        },
        "$:/language/Docs/Fields/revision": {
            "title": "$:/language/Docs/Fields/revision",
            "text": "The revision of the tiddler held at the server"
        },
        "$:/language/Docs/Fields/released": {
            "title": "$:/language/Docs/Fields/released",
            "text": "Date of a TiddlyWiki release"
        },
        "$:/language/Docs/Fields/source": {
            "title": "$:/language/Docs/Fields/source",
            "text": "The source URL associated with a tiddler"
        },
        "$:/language/Docs/Fields/subtitle": {
            "title": "$:/language/Docs/Fields/subtitle",
            "text": "The subtitle text for a wizard"
        },
        "$:/language/Docs/Fields/tags": {
            "title": "$:/language/Docs/Fields/tags",
            "text": "A list of tags associated with a tiddler"
        },
        "$:/language/Docs/Fields/text": {
            "title": "$:/language/Docs/Fields/text",
            "text": "The body text of a tiddler"
        },
        "$:/language/Docs/Fields/throttle.refresh": {
            "title": "$:/language/Docs/Fields/throttle.refresh",
            "text": "If present, throttles refreshes of this tiddler"
        },
        "$:/language/Docs/Fields/title": {
            "title": "$:/language/Docs/Fields/title",
            "text": "The unique name of a tiddler"
        },
        "$:/language/Docs/Fields/toc-link": {
            "title": "$:/language/Docs/Fields/toc-link",
            "text": "Suppresses the tiddler's link in a Table of Contents tree if set to: ''no''"
        },
        "$:/language/Docs/Fields/type": {
            "title": "$:/language/Docs/Fields/type",
            "text": "The content type of a tiddler"
        },
        "$:/language/Docs/Fields/version": {
            "title": "$:/language/Docs/Fields/version",
            "text": "Version information for a plugin"
        },
        "$:/language/Docs/Fields/_is_skinny": {
            "title": "$:/language/Docs/Fields/_is_skinny",
            "text": "If present, indicates that the tiddler text field must be loaded from the server"
        },
        "$:/language/Filters/AllTiddlers": {
            "title": "$:/language/Filters/AllTiddlers",
            "text": "All tiddlers except system tiddlers"
        },
        "$:/language/Filters/RecentSystemTiddlers": {
            "title": "$:/language/Filters/RecentSystemTiddlers",
            "text": "Recently modified tiddlers, including system tiddlers"
        },
        "$:/language/Filters/RecentTiddlers": {
            "title": "$:/language/Filters/RecentTiddlers",
            "text": "Recently modified tiddlers"
        },
        "$:/language/Filters/AllTags": {
            "title": "$:/language/Filters/AllTags",
            "text": "All tags except system tags"
        },
        "$:/language/Filters/Missing": {
            "title": "$:/language/Filters/Missing",
            "text": "Missing tiddlers"
        },
        "$:/language/Filters/Drafts": {
            "title": "$:/language/Filters/Drafts",
            "text": "Draft tiddlers"
        },
        "$:/language/Filters/Orphans": {
            "title": "$:/language/Filters/Orphans",
            "text": "Orphan tiddlers"
        },
        "$:/language/Filters/SystemTiddlers": {
            "title": "$:/language/Filters/SystemTiddlers",
            "text": "System tiddlers"
        },
        "$:/language/Filters/ShadowTiddlers": {
            "title": "$:/language/Filters/ShadowTiddlers",
            "text": "Shadow tiddlers"
        },
        "$:/language/Filters/OverriddenShadowTiddlers": {
            "title": "$:/language/Filters/OverriddenShadowTiddlers",
            "text": "Overridden shadow tiddlers"
        },
        "$:/language/Filters/SessionTiddlers": {
            "title": "$:/language/Filters/SessionTiddlers",
            "text": "Tiddlers modified since the wiki was loaded"
        },
        "$:/language/Filters/SystemTags": {
            "title": "$:/language/Filters/SystemTags",
            "text": "System tags"
        },
        "$:/language/Filters/StoryList": {
            "title": "$:/language/Filters/StoryList",
            "text": "Tiddlers in the story river, excluding <$text text=\"$:/AdvancedSearch\"/>"
        },
        "$:/language/Filters/TypedTiddlers": {
            "title": "$:/language/Filters/TypedTiddlers",
            "text": "Non wiki-text tiddlers"
        },
        "GettingStarted": {
            "title": "GettingStarted",
            "text": "\\define lingo-base() $:/language/ControlPanel/Basics/\nWelcome to ~TiddlyWiki and the ~TiddlyWiki community\n\nBefore you start storing important information in ~TiddlyWiki it is vital to make sure that you can reliably save changes. See https://tiddlywiki.com/#GettingStarted for details\n\n!! Set up this ~TiddlyWiki\n\n<div class=\"tc-control-panel\">\n\n|<$link to=\"$:/SiteTitle\"><<lingo Title/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteTitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/SiteSubtitle\"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteSubtitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/DefaultTiddlers\"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit tag=\"textarea\" tiddler=\"$:/DefaultTiddlers\"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |\n</div>\n\nSee the [[control panel|$:/ControlPanel]] for more options.\n"
        },
        "$:/language/Help/build": {
            "title": "$:/language/Help/build",
            "description": "Automatically run configured commands",
            "text": "Build the specified build targets for the current wiki. If no build targets are specified then all available targets will be built.\n\n```\n--build <target> [<target> ...]\n```\n\nBuild targets are defined in the `tiddlywiki.info` file of a wiki folder.\n\n"
        },
        "$:/language/Help/clearpassword": {
            "title": "$:/language/Help/clearpassword",
            "description": "Clear a password for subsequent crypto operations",
            "text": "Clear the password for subsequent crypto operations\n\n```\n--clearpassword\n```\n"
        },
        "$:/language/Help/default": {
            "title": "$:/language/Help/default",
            "text": "\\define commandTitle()\n$:/language/Help/$(command)$\n\\end\n```\nusage: tiddlywiki [<wikifolder>] [--<command> [<args>...]...]\n```\n\nAvailable commands:\n\n<ul>\n<$list filter=\"[commands[]sort[title]]\" variable=\"command\">\n<li><$link to=<<commandTitle>>><$macrocall $name=\"command\" $type=\"text/plain\" $output=\"text/plain\"/></$link>: <$transclude tiddler=<<commandTitle>> field=\"description\"/></li>\n</$list>\n</ul>\n\nTo get detailed help on a command:\n\n```\ntiddlywiki --help <command>\n```\n"
        },
        "$:/language/Help/deletetiddlers": {
            "title": "$:/language/Help/deletetiddlers",
            "description": "Deletes a group of tiddlers",
            "text": "<<.from-version \"5.1.20\">> Deletes a group of tiddlers identified by a filter.\n\n```\n--deletetiddlers <filter>\n```\n"
        },
        "$:/language/Help/editions": {
            "title": "$:/language/Help/editions",
            "description": "Lists the available editions of TiddlyWiki",
            "text": "Lists the names and descriptions of the available editions. You can create a new wiki of a specified edition with the `--init` command.\n\n```\n--editions\n```\n"
        },
        "$:/language/Help/fetch": {
            "title": "$:/language/Help/fetch",
            "description": "Fetch tiddlers from wiki by URL",
            "text": "Fetch one or more files over HTTP/HTTPS, and import the tiddlers matching a filter, optionally transforming the incoming titles.\n\n```\n--fetch file <url> <import-filter> <transform-filter>\n--fetch files <url-filter> <import-filter> <transform-filter>\n--fetch raw-file <url> <transform-filter>\n--fetch raw-files <url-filter> <transform-filter>\n```\n\nThe \"file\" and \"files\" variants fetch the specified files and attempt to import the tiddlers within them (the same processing as if the files were dragged into the browser window). The \"raw-file\" and \"raw-files\" variants fetch the specified files and then store the raw file data in tiddlers, without applying the import logic.\n\nWith the \"file\" and \"raw-file\" variants only a single file is fetched and the first parameter is the URL of the file to read.\n\nWith the \"files\" and \"raw-files\" variants, multiple files are fetched and the first parameter is a filter yielding a list of URLs of the files to read. For example, given a set of tiddlers tagged \"remote-server\" that have a field \"url\" the filter `[tag[remote-server]get[url]]` will retrieve all the available URLs.\n\nFor the \"file\" and \"files\" variants, the `<import-filter>` parameter specifies a filter determining which tiddlers are imported. It defaults to `[all[tiddlers]]` if not provided.\n\nFor all variants, the `<transform-filter>` parameter specifies an optional filter that transforms the titles of the imported tiddlers. For example, `[addprefix[$:/myimports/]]` would add the prefix `$:/myimports/` to each title.\n\nPreceding the `--fetch` command with `--verbose` will output progress information during the import.\n\nNote that TiddlyWiki will not fetch an older version of an already loaded plugin.\n\nThe following example retrieves all the non-system tiddlers from https://tiddlywiki.com and saves them to a JSON file:\n\n```\ntiddlywiki --verbose --fetch file \"https://tiddlywiki.com/\" \"[!is[system]]\" \"\" --rendertiddler \"$:/core/templates/exporters/JsonFile\" output.json text/plain \"\" exportFilter \"[!is[system]]\"\n```\n\nThe following example retrieves the \"favicon\" file from tiddlywiki.com and saves it in a file called \"output.ico\". Note that the intermediate tiddler \"Icon Tiddler\" is quoted in the \"--fetch\" command because it is being used as a transformation filter to replace the default title, while there are no quotes for the \"--savetiddler\" command because it is being used directly as a title.\n\n```\ntiddlywiki --verbose --fetch raw-file \"https://tiddlywiki.com/favicon.ico\" \"[[Icon Tiddler]]\" --savetiddler \"Icon Tiddler\" output.ico\n```\n\n"
        },
        "$:/language/Help/help": {
            "title": "$:/language/Help/help",
            "description": "Display help for TiddlyWiki commands",
            "text": "Displays help text for a command:\n\n```\n--help [<command>]\n```\n\nIf the command name is omitted then a list of available commands is displayed.\n"
        },
        "$:/language/Help/import": {
            "title": "$:/language/Help/import",
            "description": "Import tiddlers from a file",
            "text": "Import tiddlers from TiddlyWiki (`.html`), `.tiddler`, `.tid`, `.json` or other local files. The deserializer must be explicitly specified, unlike the `load` command which infers the deserializer from the file extension.\n\n```\n--import <filepath> <deserializer> [<title>] [<encoding>]\n```\n\nThe deserializers in the core include:\n\n* application/javascript\n* application/json\n* application/x-tiddler\n* application/x-tiddler-html-div\n* application/x-tiddlers\n* text/html\n* text/plain\n\nThe title of the imported tiddler defaults to the filename.\n\nThe encoding defaults to \"utf8\", but can be \"base64\" for importing binary files.\n\nNote that TiddlyWiki will not import an older version of an already loaded plugin.\n"
        },
        "$:/language/Help/init": {
            "title": "$:/language/Help/init",
            "description": "Initialise a new wiki folder",
            "text": "Initialise an empty [[WikiFolder|WikiFolders]] with a copy of the specified edition.\n\n```\n--init <edition> [<edition> ...]\n```\n\nFor example:\n\n```\ntiddlywiki ./MyWikiFolder --init empty\n```\n\nNote:\n\n* The wiki folder directory will be created if necessary\n* The \"edition\" defaults to ''empty''\n* The init command will fail if the wiki folder is not empty\n* The init command removes any `includeWikis` definitions in the edition's `tiddlywiki.info` file\n* When multiple editions are specified, editions initialised later will overwrite any files shared with earlier editions (so, the final `tiddlywiki.info` file will be copied from the last edition)\n* `--editions` returns a list of available editions\n"
        },
        "$:/language/Help/listen": {
            "title": "$:/language/Help/listen",
            "description": "Provides an HTTP server interface to TiddlyWiki",
            "text": "Serves a wiki over HTTP.\n\nThe listen command uses NamedCommandParameters:\n\n```\n--listen [<name>=<value>]...\n```\n\nAll parameters are optional with safe defaults, and can be specified in any order. The recognised parameters are:\n\n* ''host'' - optional hostname to serve from (defaults to \"127.0.0.1\" aka \"localhost\")\n* ''path-prefix'' - optional prefix for paths\n* ''port'' - port number on which to listen; non-numeric values are interpreted as a system environment variable from which the port number is extracted (defaults to \"8080\")\n* ''credentials'' - pathname of credentials CSV file (relative to wiki folder)\n* ''anon-username'' - the username for signing edits for anonymous users\n* ''username'' - optional username for basic authentication\n* ''password'' - optional password for basic authentication\n* ''authenticated-user-header'' - optional name of header to be used for trusted authentication\n* ''readers'' - comma separated list of principals allowed to read from this wiki\n* ''writers'' - comma separated list of principals allowed to write to this wiki\n* ''csrf-disable'' - set to \"yes\" to disable CSRF checks (defaults to \"no\")\n* ''root-tiddler'' - the tiddler to serve at the root (defaults to \"$:/core/save/all\")\n* ''root-render-type'' - the content type to which the root tiddler should be rendered (defaults to \"text/plain\")\n* ''root-serve-type'' - the content type with which the root tiddler should be served (defaults to \"text/html\")\n* ''tls-cert'' - pathname of TLS certificate file (relative to wiki folder)\n* ''tls-key'' - pathname of TLS key file (relative to wiki folder)\n* ''debug-level'' - optional debug level; set to \"debug\" to view request details (defaults to \"none\")\n* ''gzip'' - set to \"yes\" to enable gzip compression for some http endpoints (defaults to \"no\")\n\nFor information on opening up your instance to the entire local network, and possible security concerns, see the WebServer tiddler at TiddlyWiki.com.\n\n"
        },
        "$:/language/Help/load": {
            "title": "$:/language/Help/load",
            "description": "Load tiddlers from a file",
            "text": "Load tiddlers from TiddlyWiki (`.html`), `.tiddler`, `.tid`, `.json` or other local files. The processing applied to incoming files is determined by the file extension. Use the alternative `import` command if you need to specify the deserializer and encoding explicitly.\n\n```\n--load <filepath> [noerror]\n--load <dirpath> [noerror]\n```\n\nBy default, the load command raises an error if no tiddlers are found. The error can be suppressed by providing the optional \"noerror\" parameter.\n\nTo load tiddlers from an encrypted TiddlyWiki file you should first specify the password with the PasswordCommand. For example:\n\n```\ntiddlywiki ./MyWiki --password pa55w0rd --load my_encrypted_wiki.html\n```\n\nNote that TiddlyWiki will not load an older version of an already loaded plugin.\n"
        },
        "$:/language/Help/makelibrary": {
            "title": "$:/language/Help/makelibrary",
            "description": "Construct library plugin required by upgrade process",
            "text": "Constructs the `$:/UpgradeLibrary` tiddler for the upgrade process.\n\nThe upgrade library is formatted as an ordinary plugin tiddler with the plugin type `library`. It contains a copy of each of the plugins, themes and language packs available within the TiddlyWiki5 repository.\n\nThis command is intended for internal use; it is only relevant to users constructing a custom upgrade procedure.\n\n```\n--makelibrary <title>\n```\n\nThe title argument defaults to `$:/UpgradeLibrary`.\n"
        },
        "$:/language/Help/notfound": {
            "title": "$:/language/Help/notfound",
            "text": "No such help item"
        },
        "$:/language/Help/output": {
            "title": "$:/language/Help/output",
            "description": "Set the base output directory for subsequent commands",
            "text": "Sets the base output directory for subsequent commands. The default output directory is the `output` subdirectory of the edition directory.\n\n```\n--output <pathname>\n```\n\nIf the specified pathname is relative then it is resolved relative to the current working directory. For example `--output .` sets the output directory to the current working directory.\n\n"
        },
        "$:/language/Help/password": {
            "title": "$:/language/Help/password",
            "description": "Set a password for subsequent crypto operations",
            "text": "Set a password for subsequent crypto operations\n\n```\n--password <password>\n```\n\n''Note'': This should not be used for serving TiddlyWiki with password protection. Instead, see the password option under the [[ServerCommand]].\n"
        },
        "$:/language/Help/render": {
            "title": "$:/language/Help/render",
            "description": "Renders individual tiddlers to files",
            "text": "Render individual tiddlers identified by a filter and save the results to the specified files.\n\nOptionally, the title of a template tiddler can be specified. In this case, instead of directly rendering each tiddler, the template tiddler is rendered with the \"currentTiddler\" variable set to the title of the tiddler that is being rendered.\n\nA name and value for an additional variable may optionally also be specified.\n\n```\n--render <tiddler-filter> [<filename-filter>] [<render-type>] [<template>] [<name>] [<value>]\n```\n\n* ''tiddler-filter'': A filter identifying the tiddler(s) to be rendered\n* ''filename-filter'': Optional filter transforming tiddler titles into pathnames. If omitted, defaults to `[is[tiddler]addsuffix[.html]]`, which uses the unchanged tiddler title as the filename\n* ''render-type'': Optional render type: `text/html` (the default) returns the full HTML text and `text/plain` just returns the text content (ie it ignores HTML tags and other unprintable material)\n* ''template'': Optional template through which each tiddler is rendered\n* ''name'': Name of optional variable\n* ''value'': Value of optional variable\n\nBy default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nNotes:\n\n* The output directory is not cleared of any existing files\n* Any missing directories in the path to the filename are automatically created.\n* When referring to a tiddler with spaces in its title, take care to use both the quotes required by your shell and also TiddlyWiki's double square brackets : `--render \"[[Motovun Jack.jpg]]\"`\n* The filename filter is evaluated with the selected items being set to the title of the tiddler currently being rendered, allowing the title to be used as the basis for computing the filename. For example `[encodeuricomponent[]addprefix[static/]]` applies URI encoding to each title, and then adds the prefix `static/`\n* The `--render` command is a more flexible replacement for both the `--rendertiddler` and `--rendertiddlers` commands, which are deprecated\n\nExamples:\n\n* `--render \"[!is[system]]\" \"[encodeuricomponent[]addprefix[tiddlers/]addsuffix[.html]]\"` -- renders all non-system tiddlers as files in the subdirectory \"tiddlers\" with URL-encoded titles and the extension HTML\n\n"
        },
        "$:/language/Help/rendertiddler": {
            "title": "$:/language/Help/rendertiddler",
            "description": "Render an individual tiddler as a specified ContentType",
            "text": "(Note: The `--rendertiddler` command is deprecated in favour of the new, more flexible `--render` command)\n\nRender an individual tiddler as a specified ContentType, defaulting to `text/html` and save it to the specified filename.\n\nOptionally the title of a template tiddler can be specified, in which case the template tiddler is rendered with the \"currentTiddler\" variable set to the tiddler that is being rendered (the first parameter value).\n\nA name and value for an additional variable may optionally also be specified.\n\n```\n--rendertiddler <title> <filename> [<type>] [<template>] [<name>] [<value>]\n```\n\nBy default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nAny missing directories in the path to the filename are automatically created.\n\nFor example, the following command saves all tiddlers matching the filter `[tag[done]]` to a JSON file titled `output.json` by employing the core template `$:/core/templates/exporters/JsonFile`.\n\n```\n--rendertiddler \"$:/core/templates/exporters/JsonFile\" output.json text/plain \"\" exportFilter \"[tag[done]]\"\n```\n"
        },
        "$:/language/Help/rendertiddlers": {
            "title": "$:/language/Help/rendertiddlers",
            "description": "Render tiddlers matching a filter to a specified ContentType",
            "text": "(Note: The `--rendertiddlers` command is deprecated in favour of the new, more flexible `--render` command)\n\nRender a set of tiddlers matching a filter to separate files of a specified ContentType (defaults to `text/html`) and extension (defaults to `.html`).\n\n```\n--rendertiddlers <filter> <template> <pathname> [<type>] [<extension>] [\"noclean\"]\n```\n\nFor example:\n\n```\n--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html ./static text/plain\n```\n\nBy default, the pathname is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nAny files in the target directory are deleted unless the ''noclean'' flag is specified. The target directory is recursively created if it is missing.\n"
        },
        "$:/language/Help/save": {
            "title": "$:/language/Help/save",
            "description": "Saves individual raw tiddlers to files",
            "text": "Saves individual tiddlers identified by a filter in their raw text or binary format to the specified files.\n\n```\n--save <tiddler-filter> <filename-filter>\n```\n\n* ''tiddler-filter'': A filter identifying the tiddler(s) to be saved\n* ''filename-filter'': Optional filter transforming tiddler titles into pathnames. If omitted, defaults to `[is[tiddler]]`, which uses the unchanged tiddler title as the filename\n\nBy default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nNotes:\n\n* The output directory is not cleared of any existing files\n* Any missing directories in the path to the filename are automatically created.\n* When saving a tiddler with spaces in its title, take care to use both the quotes required by your shell and also TiddlyWiki's double square brackets : `--save \"[[Motovun Jack.jpg]]\"`\n* The filename filter is evaluated with the selected items being set to the title of the tiddler currently being saved, allowing the title to be used as the basis for computing the filename. For example `[encodeuricomponent[]addprefix[static/]]` applies URI encoding to each title, and then adds the prefix `static/`\n* The `--save` command is a more flexible replacement for both the `--savetiddler` and `--savetiddlers` commands, which are deprecated\n\nExamples:\n\n* `--save \"[!is[system]is[image]]\" \"[encodeuricomponent[]addprefix[tiddlers/]]\"` -- saves all non-system image tiddlers as files in the subdirectory \"tiddlers\" with URL-encoded titles\n"
        },
        "$:/language/Help/savetiddler": {
            "title": "$:/language/Help/savetiddler",
            "description": "Saves a raw tiddler to a file",
            "text": "(Note: The `--savetiddler` command is deprecated in favour of the new, more flexible `--save` command)\n\nSaves an individual tiddler in its raw text or binary format to the specified filename.\n\n```\n--savetiddler <title> <filename>\n```\n\nBy default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nAny missing directories in the path to the filename are automatically created.\n"
        },
        "$:/language/Help/savetiddlers": {
            "title": "$:/language/Help/savetiddlers",
            "description": "Saves a group of raw tiddlers to a directory",
            "text": "(Note: The `--savetiddlers` command is deprecated in favour of the new, more flexible `--save` command)\n\nSaves a group of tiddlers in their raw text or binary format to the specified directory.\n\n```\n--savetiddlers <filter> <pathname> [\"noclean\"]\n```\n\nBy default, the pathname is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nThe output directory is cleared of existing files before saving the specified files. The deletion can be disabled by specifying the ''noclean'' flag.\n\nAny missing directories in the pathname are automatically created.\n"
        },
        "$:/language/Help/savewikifolder": {
            "title": "$:/language/Help/savewikifolder",
            "description": "Saves a wiki to a new wiki folder",
            "text": "<<.from-version \"5.1.20\">> Saves the current wiki as a wiki folder, including tiddlers, plugins and configuration:\n\n```\n--savewikifolder <wikifolderpath> [<filter>]\n```\n\n* The target wiki folder must be empty or non-existent\n* The filter specifies which tiddlers should be included. It is optional, defaulting to `[all[tiddlers]]`\n* Plugins from the official plugin library are replaced with references to those plugins in the `tiddlywiki.info` file\n* Custom plugins are unpacked into their own folder\n\nA common usage is to convert a TiddlyWiki HTML file into a wiki folder:\n\n```\ntiddlywiki --load ./mywiki.html --savewikifolder ./mywikifolder\n```\n"
        },
        "$:/language/Help/server": {
            "title": "$:/language/Help/server",
            "description": "Provides an HTTP server interface to TiddlyWiki (deprecated in favour of the new listen command)",
            "text": "Legacy command to serve a wiki over HTTP.\n\n```\n--server <port> <root-tiddler> <root-render-type> <root-serve-type> <username> <password> <host> <path-prefix> <debug-level>\n```\n\nThe parameters are:\n\n* ''port'' - port number on which to listen; non-numeric values are interpreted as a system environment variable from which the port number is extracted (defaults to \"8080\")\n* ''root-tiddler'' - the tiddler to serve at the root (defaults to \"$:/core/save/all\")\n* ''root-render-type'' - the content type to which the root tiddler should be rendered (defaults to \"text/plain\")\n* ''root-serve-type'' - the content type with which the root tiddler should be served (defaults to \"text/html\")\n* ''username'' - the default username for signing edits\n* ''password'' - optional password for basic authentication\n* ''host'' - optional hostname to serve from (defaults to \"127.0.0.1\" aka \"localhost\")\n* ''path-prefix'' - optional prefix for paths\n* ''debug-level'' - optional debug level; set to \"debug\" to view request details (defaults to \"none\")\n\nIf the password parameter is specified then the browser will prompt the user for the username and password. Note that the password is transmitted in plain text so this implementation should only be used on a trusted network or over HTTPS.\n\nFor example:\n\n```\n--server 8080 $:/core/save/all text/plain text/html MyUserName passw0rd\n```\n\nThe username and password can be specified as empty strings if you need to set the hostname or pathprefix and don't want to require a password.\n\n\n```\n--server 8080 $:/core/save/all text/plain text/html \"\" \"\" 192.168.0.245\n```\n\nUsing an address like this exposes your system to the local network. For information on opening up your instance to the entire local network, and possible security concerns, see the WebServer tiddler at TiddlyWiki.com.\n\nTo run multiple TiddlyWiki servers at the same time you'll need to put each one on a different port. It can be useful to use an environment variable to pass the port number to the Node.js process. This example references an environment variable called \"MY_PORT_NUMBER\":\n\n```\n--server MY_PORT_NUMBER $:/core/save/all text/plain text/html MyUserName passw0rd\n```\n"
        },
        "$:/language/Help/setfield": {
            "title": "$:/language/Help/setfield",
            "description": "Prepares external tiddlers for use",
            "text": "//Note that this command is experimental and may change or be replaced before being finalised//\n\nSets the specified field of a group of tiddlers to the result of wikifying a template tiddler with the `currentTiddler` variable set to the tiddler.\n\n```\n--setfield <filter> <fieldname> <templatetitle> <rendertype>\n```\n\nThe parameters are:\n\n* ''filter'' - filter identifying the tiddlers to be affected\n* ''fieldname'' - the field to modify (defaults to \"text\")\n* ''templatetitle'' - the tiddler to wikify into the specified field. If blank or missing then the specified field is deleted\n* ''rendertype'' - the text type to render (defaults to \"text/plain\"; \"text/html\" can be used to include HTML tags)\n"
        },
        "$:/language/Help/unpackplugin": {
            "title": "$:/language/Help/unpackplugin",
            "description": "Unpack the payload tiddlers from a plugin",
            "text": "Extract the payload tiddlers from a plugin, creating them as ordinary tiddlers:\n\n```\n--unpackplugin <title>\n```\n"
        },
        "$:/language/Help/verbose": {
            "title": "$:/language/Help/verbose",
            "description": "Triggers verbose output mode",
            "text": "Triggers verbose output, useful for debugging\n\n```\n--verbose\n```\n"
        },
        "$:/language/Help/version": {
            "title": "$:/language/Help/version",
            "description": "Displays the version number of TiddlyWiki",
            "text": "Displays the version number of TiddlyWiki.\n\n```\n--version\n```\n"
        },
        "$:/language/Import/Imported/Hint": {
            "title": "$:/language/Import/Imported/Hint",
            "text": "The following tiddlers were imported:"
        },
        "$:/language/Import/Listing/Cancel/Caption": {
            "title": "$:/language/Import/Listing/Cancel/Caption",
            "text": "Cancel"
        },
        "$:/language/Import/Listing/Hint": {
            "title": "$:/language/Import/Listing/Hint",
            "text": "These tiddlers are ready to import:"
        },
        "$:/language/Import/Listing/Import/Caption": {
            "title": "$:/language/Import/Listing/Import/Caption",
            "text": "Import"
        },
        "$:/language/Import/Listing/Select/Caption": {
            "title": "$:/language/Import/Listing/Select/Caption",
            "text": "Select"
        },
        "$:/language/Import/Listing/Status/Caption": {
            "title": "$:/language/Import/Listing/Status/Caption",
            "text": "Status"
        },
        "$:/language/Import/Listing/Title/Caption": {
            "title": "$:/language/Import/Listing/Title/Caption",
            "text": "Title"
        },
        "$:/language/Import/Listing/Preview": {
            "title": "$:/language/Import/Listing/Preview",
            "text": "Preview:"
        },
        "$:/language/Import/Listing/Preview/Text": {
            "title": "$:/language/Import/Listing/Preview/Text",
            "text": "Text"
        },
        "$:/language/Import/Listing/Preview/TextRaw": {
            "title": "$:/language/Import/Listing/Preview/TextRaw",
            "text": "Text (Raw)"
        },
        "$:/language/Import/Listing/Preview/Fields": {
            "title": "$:/language/Import/Listing/Preview/Fields",
            "text": "Fields"
        },
        "$:/language/Import/Listing/Preview/Diff": {
            "title": "$:/language/Import/Listing/Preview/Diff",
            "text": "Diff"
        },
        "$:/language/Import/Listing/Preview/DiffFields": {
            "title": "$:/language/Import/Listing/Preview/DiffFields",
            "text": "Diff (Fields)"
        },
        "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible": {
            "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible",
            "text": "Blocked incompatible or obsolete plugin"
        },
        "$:/language/Import/Upgrader/Plugins/Suppressed/Version": {
            "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Version",
            "text": "Blocked plugin (due to incoming <<incoming>> being older than existing <<existing>>)"
        },
        "$:/language/Import/Upgrader/Plugins/Upgraded": {
            "title": "$:/language/Import/Upgrader/Plugins/Upgraded",
            "text": "Upgraded plugin from <<incoming>> to <<upgraded>>"
        },
        "$:/language/Import/Upgrader/State/Suppressed": {
            "title": "$:/language/Import/Upgrader/State/Suppressed",
            "text": "Blocked temporary state tiddler"
        },
        "$:/language/Import/Upgrader/System/Suppressed": {
            "title": "$:/language/Import/Upgrader/System/Suppressed",
            "text": "Blocked system tiddler"
        },
        "$:/language/Import/Upgrader/System/Warning": {
            "title": "$:/language/Import/Upgrader/System/Warning",
            "text": "Core module tiddler"
        },
        "$:/language/Import/Upgrader/System/Alert": {
            "title": "$:/language/Import/Upgrader/System/Alert",
            "text": "You are about to import a tiddler that will overwrite a core module tiddler. This is not recommended as it may make the system unstable"
        },
        "$:/language/Import/Upgrader/ThemeTweaks/Created": {
            "title": "$:/language/Import/Upgrader/ThemeTweaks/Created",
            "text": "Migrated theme tweak from <$text text=<<from>>/>"
        },
        "$:/language/AboveStory/ClassicPlugin/Warning": {
            "title": "$:/language/AboveStory/ClassicPlugin/Warning",
            "text": "It looks like you are trying to load a plugin designed for ~TiddlyWiki Classic. Please note that [[these plugins do not work with TiddlyWiki version 5.x.x|https://tiddlywiki.com/#TiddlyWikiClassic]]. ~TiddlyWiki Classic plugins detected:"
        },
        "$:/language/BinaryWarning/Prompt": {
            "title": "$:/language/BinaryWarning/Prompt",
            "text": "This tiddler contains binary data"
        },
        "$:/language/ClassicWarning/Hint": {
            "title": "$:/language/ClassicWarning/Hint",
            "text": "This tiddler is written in TiddlyWiki Classic wiki text format, which is not fully compatible with TiddlyWiki version 5. See https://tiddlywiki.com/static/Upgrading.html for more details."
        },
        "$:/language/ClassicWarning/Upgrade/Caption": {
            "title": "$:/language/ClassicWarning/Upgrade/Caption",
            "text": "upgrade"
        },
        "$:/language/CloseAll/Button": {
            "title": "$:/language/CloseAll/Button",
            "text": "close all"
        },
        "$:/language/ColourPicker/Recent": {
            "title": "$:/language/ColourPicker/Recent",
            "text": "Recent:"
        },
        "$:/language/ConfirmCancelTiddler": {
            "title": "$:/language/ConfirmCancelTiddler",
            "text": "Do you wish to discard changes to the tiddler \"<$text text=<<title>>/>\"?"
        },
        "$:/language/ConfirmDeleteTiddler": {
            "title": "$:/language/ConfirmDeleteTiddler",
            "text": "Do you wish to delete the tiddler \"<$text text=<<title>>/>\"?"
        },
        "$:/language/ConfirmOverwriteTiddler": {
            "title": "$:/language/ConfirmOverwriteTiddler",
            "text": "Do you wish to overwrite the tiddler \"<$text text=<<title>>/>\"?"
        },
        "$:/language/ConfirmEditShadowTiddler": {
            "title": "$:/language/ConfirmEditShadowTiddler",
            "text": "You are about to edit a ShadowTiddler. Any changes will override the default system making future upgrades non-trivial. Are you sure you want to edit \"<$text text=<<title>>/>\"?"
        },
        "$:/language/Count": {
            "title": "$:/language/Count",
            "text": "count"
        },
        "$:/language/DefaultNewTiddlerTitle": {
            "title": "$:/language/DefaultNewTiddlerTitle",
            "text": "New Tiddler"
        },
        "$:/language/Diffs/CountMessage": {
            "title": "$:/language/Diffs/CountMessage",
            "text": "<<diff-count>> differences"
        },
        "$:/language/DropMessage": {
            "title": "$:/language/DropMessage",
            "text": "Drop here (or use the 'Escape' key to cancel)"
        },
        "$:/language/Encryption/Cancel": {
            "title": "$:/language/Encryption/Cancel",
            "text": "Cancel"
        },
        "$:/language/Encryption/ConfirmClearPassword": {
            "title": "$:/language/Encryption/ConfirmClearPassword",
            "text": "Do you wish to clear the password? This will remove the encryption applied when saving this wiki"
        },
        "$:/language/Encryption/PromptSetPassword": {
            "title": "$:/language/Encryption/PromptSetPassword",
            "text": "Set a new password for this TiddlyWiki"
        },
        "$:/language/Encryption/Username": {
            "title": "$:/language/Encryption/Username",
            "text": "Username"
        },
        "$:/language/Encryption/Password": {
            "title": "$:/language/Encryption/Password",
            "text": "Password"
        },
        "$:/language/Encryption/RepeatPassword": {
            "title": "$:/language/Encryption/RepeatPassword",
            "text": "Repeat password"
        },
        "$:/language/Encryption/PasswordNoMatch": {
            "title": "$:/language/Encryption/PasswordNoMatch",
            "text": "Passwords do not match"
        },
        "$:/language/Encryption/SetPassword": {
            "title": "$:/language/Encryption/SetPassword",
            "text": "Set password"
        },
        "$:/language/Error/Caption": {
            "title": "$:/language/Error/Caption",
            "text": "Error"
        },
        "$:/language/Error/EditConflict": {
            "title": "$:/language/Error/EditConflict",
            "text": "File changed on server"
        },
        "$:/language/Error/Filter": {
            "title": "$:/language/Error/Filter",
            "text": "Filter error"
        },
        "$:/language/Error/FilterSyntax": {
            "title": "$:/language/Error/FilterSyntax",
            "text": "Syntax error in filter expression"
        },
        "$:/language/Error/IsFilterOperator": {
            "title": "$:/language/Error/IsFilterOperator",
            "text": "Filter Error: Unknown operand for the 'is' filter operator"
        },
        "$:/language/Error/LoadingPluginLibrary": {
            "title": "$:/language/Error/LoadingPluginLibrary",
            "text": "Error loading plugin library"
        },
        "$:/language/Error/NetworkErrorAlert": {
            "title": "$:/language/Error/NetworkErrorAlert",
            "text": "`<h2>''Network Error''</h2>It looks like the connection to the server has been lost. This may indicate a problem with your network connection. Please attempt to restore network connectivity before continuing.<br><br>''Any unsaved changes will be automatically synchronised when connectivity is restored''.`"
        },
        "$:/language/Error/RecursiveTransclusion": {
            "title": "$:/language/Error/RecursiveTransclusion",
            "text": "Recursive transclusion error in transclude widget"
        },
        "$:/language/Error/RetrievingSkinny": {
            "title": "$:/language/Error/RetrievingSkinny",
            "text": "Error retrieving skinny tiddler list"
        },
        "$:/language/Error/SavingToTWEdit": {
            "title": "$:/language/Error/SavingToTWEdit",
            "text": "Error saving to TWEdit"
        },
        "$:/language/Error/WhileSaving": {
            "title": "$:/language/Error/WhileSaving",
            "text": "Error while saving"
        },
        "$:/language/Error/XMLHttpRequest": {
            "title": "$:/language/Error/XMLHttpRequest",
            "text": "XMLHttpRequest error code"
        },
        "$:/language/InternalJavaScriptError/Title": {
            "title": "$:/language/InternalJavaScriptError/Title",
            "text": "Internal JavaScript Error"
        },
        "$:/language/InternalJavaScriptError/Hint": {
            "title": "$:/language/InternalJavaScriptError/Hint",
            "text": "Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser"
        },
        "$:/language/InvalidFieldName": {
            "title": "$:/language/InvalidFieldName",
            "text": "Illegal characters in field name \"<$text text=<<fieldName>>/>\". Fields can only contain lowercase letters, digits and the characters underscore (`_`), hyphen (`-`) and period (`.`)"
        },
        "$:/language/LazyLoadingWarning": {
            "title": "$:/language/LazyLoadingWarning",
            "text": "<p>Trying to load external content from ''<$text text={{!!_canonical_uri}}/>''</p><p>If this message doesn't disappear, either the tiddler content type doesn't match the type of the external content, or you may be using a browser that doesn't support external content for wikis loaded as standalone files. See https://tiddlywiki.com/#ExternalText</p>"
        },
        "$:/language/LoginToTiddlySpace": {
            "title": "$:/language/LoginToTiddlySpace",
            "text": "Login to TiddlySpace"
        },
        "$:/language/Manager/Controls/FilterByTag/None": {
            "title": "$:/language/Manager/Controls/FilterByTag/None",
            "text": "(none)"
        },
        "$:/language/Manager/Controls/FilterByTag/Prompt": {
            "title": "$:/language/Manager/Controls/FilterByTag/Prompt",
            "text": "Filter by tag:"
        },
        "$:/language/Manager/Controls/Order/Prompt": {
            "title": "$:/language/Manager/Controls/Order/Prompt",
            "text": "Reverse order"
        },
        "$:/language/Manager/Controls/Search/Placeholder": {
            "title": "$:/language/Manager/Controls/Search/Placeholder",
            "text": "Search"
        },
        "$:/language/Manager/Controls/Search/Prompt": {
            "title": "$:/language/Manager/Controls/Search/Prompt",
            "text": "Search:"
        },
        "$:/language/Manager/Controls/Show/Option/Tags": {
            "title": "$:/language/Manager/Controls/Show/Option/Tags",
            "text": "tags"
        },
        "$:/language/Manager/Controls/Show/Option/Tiddlers": {
            "title": "$:/language/Manager/Controls/Show/Option/Tiddlers",
            "text": "tiddlers"
        },
        "$:/language/Manager/Controls/Show/Prompt": {
            "title": "$:/language/Manager/Controls/Show/Prompt",
            "text": "Show:"
        },
        "$:/language/Manager/Controls/Sort/Prompt": {
            "title": "$:/language/Manager/Controls/Sort/Prompt",
            "text": "Sort by:"
        },
        "$:/language/Manager/Item/Colour": {
            "title": "$:/language/Manager/Item/Colour",
            "text": "Colour"
        },
        "$:/language/Manager/Item/Fields": {
            "title": "$:/language/Manager/Item/Fields",
            "text": "Fields"
        },
        "$:/language/Manager/Item/Icon/None": {
            "title": "$:/language/Manager/Item/Icon/None",
            "text": "(none)"
        },
        "$:/language/Manager/Item/Icon": {
            "title": "$:/language/Manager/Item/Icon",
            "text": "Icon"
        },
        "$:/language/Manager/Item/RawText": {
            "title": "$:/language/Manager/Item/RawText",
            "text": "Raw text"
        },
        "$:/language/Manager/Item/Tags": {
            "title": "$:/language/Manager/Item/Tags",
            "text": "Tags"
        },
        "$:/language/Manager/Item/Tools": {
            "title": "$:/language/Manager/Item/Tools",
            "text": "Tools"
        },
        "$:/language/Manager/Item/WikifiedText": {
            "title": "$:/language/Manager/Item/WikifiedText",
            "text": "Wikified text"
        },
        "$:/language/MissingTiddler/Hint": {
            "title": "$:/language/MissingTiddler/Hint",
            "text": "Missing tiddler \"<$text text=<<currentTiddler>>/>\" -- click {{||$:/core/ui/Buttons/edit}} to create"
        },
        "$:/language/No": {
            "title": "$:/language/No",
            "text": "No"
        },
        "$:/language/OfficialPluginLibrary": {
            "title": "$:/language/OfficialPluginLibrary",
            "text": "Official ~TiddlyWiki Plugin Library"
        },
        "$:/language/OfficialPluginLibrary/Hint": {
            "title": "$:/language/OfficialPluginLibrary/Hint",
            "text": "The official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team."
        },
        "$:/language/PluginReloadWarning": {
            "title": "$:/language/PluginReloadWarning",
            "text": "Please save {{$:/core/ui/Buttons/save-wiki}} and reload {{$:/core/ui/Buttons/refresh}} to allow changes to ~JavaScript plugins to take effect"
        },
        "$:/language/RecentChanges/DateFormat": {
            "title": "$:/language/RecentChanges/DateFormat",
            "text": "DDth MMM YYYY"
        },
        "$:/language/SystemTiddler/Tooltip": {
            "title": "$:/language/SystemTiddler/Tooltip",
            "text": "This is a system tiddler"
        },
        "$:/language/SystemTiddlers/Include/Prompt": {
            "title": "$:/language/SystemTiddlers/Include/Prompt",
            "text": "Include system tiddlers"
        },
        "$:/language/TagManager/Colour/Heading": {
            "title": "$:/language/TagManager/Colour/Heading",
            "text": "Colour"
        },
        "$:/language/TagManager/Count/Heading": {
            "title": "$:/language/TagManager/Count/Heading",
            "text": "Count"
        },
        "$:/language/TagManager/Icon/Heading": {
            "title": "$:/language/TagManager/Icon/Heading",
            "text": "Icon"
        },
        "$:/language/TagManager/Icons/None": {
            "title": "$:/language/TagManager/Icons/None",
            "text": "None"
        },
        "$:/language/TagManager/Info/Heading": {
            "title": "$:/language/TagManager/Info/Heading",
            "text": "Info"
        },
        "$:/language/TagManager/Tag/Heading": {
            "title": "$:/language/TagManager/Tag/Heading",
            "text": "Tag"
        },
        "$:/language/Tiddler/DateFormat": {
            "title": "$:/language/Tiddler/DateFormat",
            "text": "DDth MMM YYYY at hh12:0mmam"
        },
        "$:/language/UnsavedChangesWarning": {
            "title": "$:/language/UnsavedChangesWarning",
            "text": "You have unsaved changes in TiddlyWiki"
        },
        "$:/language/Yes": {
            "title": "$:/language/Yes",
            "text": "Yes"
        },
        "$:/language/Modals/Download": {
            "title": "$:/language/Modals/Download",
            "subtitle": "Download changes",
            "footer": "<$button message=\"tm-close-tiddler\">Close</$button>",
            "help": "https://tiddlywiki.com/static/DownloadingChanges.html",
            "text": "Your browser only supports manual saving.\n\nTo save your modified wiki, right click on the download link below and select \"Download file\" or \"Save file\", and then choose the folder and filename.\n\n//You can marginally speed things up by clicking the link with the control key (Windows) or the options/alt key (Mac OS X). You will not be prompted for the folder or filename, but your browser is likely to give it an unrecognisable name -- you may need to rename the file to include an `.html` extension before you can do anything useful with it.//\n\nOn smartphones that do not allow files to be downloaded you can instead bookmark the link, and then sync your bookmarks to a desktop computer from where the wiki can be saved normally.\n"
        },
        "$:/language/Modals/SaveInstructions": {
            "title": "$:/language/Modals/SaveInstructions",
            "subtitle": "Save your work",
            "footer": "<$button message=\"tm-close-tiddler\">Close</$button>",
            "help": "https://tiddlywiki.com/static/SavingChanges.html",
            "text": "Your changes to this wiki need to be saved as a ~TiddlyWiki HTML file.\n\n!!! Desktop browsers\n\n# Select ''Save As'' from the ''File'' menu\n# Choose a filename and location\n#* Some browsers also require you to explicitly specify the file saving format as ''Webpage, HTML only'' or similar\n# Close this tab\n\n!!! Smartphone browsers\n\n# Create a bookmark to this page\n#* If you've got iCloud or Google Sync set up then the bookmark will automatically sync to your desktop where you can open it and save it as above\n# Close this tab\n\n//If you open the bookmark again in Mobile Safari you will see this message again. If you want to go ahead and use the file, just click the ''close'' button below//\n"
        },
        "$:/config/NewJournal/Title": {
            "title": "$:/config/NewJournal/Title",
            "text": "DDth MMM YYYY"
        },
        "$:/config/NewJournal/Text": {
            "title": "$:/config/NewJournal/Text",
            "text": ""
        },
        "$:/config/NewJournal/Tags": {
            "title": "$:/config/NewJournal/Tags",
            "tags": "Journal"
        },
        "$:/language/Notifications/Save/Done": {
            "title": "$:/language/Notifications/Save/Done",
            "text": "Saved wiki"
        },
        "$:/language/Notifications/Save/Starting": {
            "title": "$:/language/Notifications/Save/Starting",
            "text": "Starting to save wiki"
        },
        "$:/language/Notifications/CopiedToClipboard/Succeeded": {
            "title": "$:/language/Notifications/CopiedToClipboard/Succeeded",
            "text": "Copied to clipboard!"
        },
        "$:/language/Notifications/CopiedToClipboard/Failed": {
            "title": "$:/language/Notifications/CopiedToClipboard/Failed",
            "text": "Failed to copy to clipboard!"
        },
        "$:/language/Search/DefaultResults/Caption": {
            "title": "$:/language/Search/DefaultResults/Caption",
            "text": "List"
        },
        "$:/language/Search/Filter/Caption": {
            "title": "$:/language/Search/Filter/Caption",
            "text": "Filter"
        },
        "$:/language/Search/Filter/Hint": {
            "title": "$:/language/Search/Filter/Hint",
            "text": "Search via a [[filter expression|https://tiddlywiki.com/static/Filters.html]]"
        },
        "$:/language/Search/Filter/Matches": {
            "title": "$:/language/Search/Filter/Matches",
            "text": "//<small><<resultCount>> matches</small>//"
        },
        "$:/language/Search/Matches": {
            "title": "$:/language/Search/Matches",
            "text": "//<small><<resultCount>> matches</small>//"
        },
        "$:/language/Search/Matches/All": {
            "title": "$:/language/Search/Matches/All",
            "text": "All matches:"
        },
        "$:/language/Search/Matches/Title": {
            "title": "$:/language/Search/Matches/Title",
            "text": "Title matches:"
        },
        "$:/language/Search/Search": {
            "title": "$:/language/Search/Search",
            "text": "Search"
        },
        "$:/language/Search/Search/TooShort": {
            "title": "$:/language/Search/Search/TooShort",
            "text": "Search text too short"
        },
        "$:/language/Search/Shadows/Caption": {
            "title": "$:/language/Search/Shadows/Caption",
            "text": "Shadows"
        },
        "$:/language/Search/Shadows/Hint": {
            "title": "$:/language/Search/Shadows/Hint",
            "text": "Search for shadow tiddlers"
        },
        "$:/language/Search/Shadows/Matches": {
            "title": "$:/language/Search/Shadows/Matches",
            "text": "//<small><<resultCount>> matches</small>//"
        },
        "$:/language/Search/Standard/Caption": {
            "title": "$:/language/Search/Standard/Caption",
            "text": "Standard"
        },
        "$:/language/Search/Standard/Hint": {
            "title": "$:/language/Search/Standard/Hint",
            "text": "Search for standard tiddlers"
        },
        "$:/language/Search/Standard/Matches": {
            "title": "$:/language/Search/Standard/Matches",
            "text": "//<small><<resultCount>> matches</small>//"
        },
        "$:/language/Search/System/Caption": {
            "title": "$:/language/Search/System/Caption",
            "text": "System"
        },
        "$:/language/Search/System/Hint": {
            "title": "$:/language/Search/System/Hint",
            "text": "Search for system tiddlers"
        },
        "$:/language/Search/System/Matches": {
            "title": "$:/language/Search/System/Matches",
            "text": "//<small><<resultCount>> matches</small>//"
        },
        "$:/language/SideBar/All/Caption": {
            "title": "$:/language/SideBar/All/Caption",
            "text": "All"
        },
        "$:/language/SideBar/Contents/Caption": {
            "title": "$:/language/SideBar/Contents/Caption",
            "text": "Contents"
        },
        "$:/language/SideBar/Drafts/Caption": {
            "title": "$:/language/SideBar/Drafts/Caption",
            "text": "Drafts"
        },
        "$:/language/SideBar/Explorer/Caption": {
            "title": "$:/language/SideBar/Explorer/Caption",
            "text": "Explorer"
        },
        "$:/language/SideBar/Missing/Caption": {
            "title": "$:/language/SideBar/Missing/Caption",
            "text": "Missing"
        },
        "$:/language/SideBar/More/Caption": {
            "title": "$:/language/SideBar/More/Caption",
            "text": "More"
        },
        "$:/language/SideBar/Open/Caption": {
            "title": "$:/language/SideBar/Open/Caption",
            "text": "Open"
        },
        "$:/language/SideBar/Orphans/Caption": {
            "title": "$:/language/SideBar/Orphans/Caption",
            "text": "Orphans"
        },
        "$:/language/SideBar/Recent/Caption": {
            "title": "$:/language/SideBar/Recent/Caption",
            "text": "Recent"
        },
        "$:/language/SideBar/Shadows/Caption": {
            "title": "$:/language/SideBar/Shadows/Caption",
            "text": "Shadows"
        },
        "$:/language/SideBar/System/Caption": {
            "title": "$:/language/SideBar/System/Caption",
            "text": "System"
        },
        "$:/language/SideBar/Tags/Caption": {
            "title": "$:/language/SideBar/Tags/Caption",
            "text": "Tags"
        },
        "$:/language/SideBar/Tags/Untagged/Caption": {
            "title": "$:/language/SideBar/Tags/Untagged/Caption",
            "text": "untagged"
        },
        "$:/language/SideBar/Tools/Caption": {
            "title": "$:/language/SideBar/Tools/Caption",
            "text": "Tools"
        },
        "$:/language/SideBar/Types/Caption": {
            "title": "$:/language/SideBar/Types/Caption",
            "text": "Types"
        },
        "$:/SiteSubtitle": {
            "title": "$:/SiteSubtitle",
            "text": "a non-linear personal web notebook"
        },
        "$:/SiteTitle": {
            "title": "$:/SiteTitle",
            "text": "My ~TiddlyWiki"
        },
        "$:/language/Snippets/ListByTag": {
            "title": "$:/language/Snippets/ListByTag",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "List of tiddlers by tag",
            "text": "<<list-links \"[tag[task]sort[title]]\">>\n"
        },
        "$:/language/Snippets/MacroDefinition": {
            "title": "$:/language/Snippets/MacroDefinition",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "Macro definition",
            "text": "\\define macroName(param1:\"default value\",param2)\nText of the macro\n\\end\n"
        },
        "$:/language/Snippets/Table4x3": {
            "title": "$:/language/Snippets/Table4x3",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "Table with 4 columns by 3 rows",
            "text": "|! |!Alpha |!Beta |!Gamma |!Delta |\n|!One | | | | |\n|!Two | | | | |\n|!Three | | | | |\n"
        },
        "$:/language/Snippets/TableOfContents": {
            "title": "$:/language/Snippets/TableOfContents",
            "tags": "$:/tags/TextEditor/Snippet",
            "caption": "Table of Contents",
            "text": "<div class=\"tc-table-of-contents\">\n\n<<toc-selective-expandable 'TableOfContents'>>\n\n</div>"
        },
        "$:/language/ThemeTweaks/ThemeTweaks": {
            "title": "$:/language/ThemeTweaks/ThemeTweaks",
            "text": "Theme Tweaks"
        },
        "$:/language/ThemeTweaks/ThemeTweaks/Hint": {
            "title": "$:/language/ThemeTweaks/ThemeTweaks/Hint",
            "text": "You can tweak certain aspects of the ''Vanilla'' theme."
        },
        "$:/language/ThemeTweaks/Options": {
            "title": "$:/language/ThemeTweaks/Options",
            "text": "Options"
        },
        "$:/language/ThemeTweaks/Options/SidebarLayout": {
            "title": "$:/language/ThemeTweaks/Options/SidebarLayout",
            "text": "Sidebar layout"
        },
        "$:/language/ThemeTweaks/Options/SidebarLayout/Fixed-Fluid": {
            "title": "$:/language/ThemeTweaks/Options/SidebarLayout/Fixed-Fluid",
            "text": "Fixed story, fluid sidebar"
        },
        "$:/language/ThemeTweaks/Options/SidebarLayout/Fluid-Fixed": {
            "title": "$:/language/ThemeTweaks/Options/SidebarLayout/Fluid-Fixed",
            "text": "Fluid story, fixed sidebar"
        },
        "$:/language/ThemeTweaks/Options/StickyTitles": {
            "title": "$:/language/ThemeTweaks/Options/StickyTitles",
            "text": "Sticky titles"
        },
        "$:/language/ThemeTweaks/Options/StickyTitles/Hint": {
            "title": "$:/language/ThemeTweaks/Options/StickyTitles/Hint",
            "text": "Causes tiddler titles to \"stick\" to the top of the browser window"
        },
        "$:/language/ThemeTweaks/Options/CodeWrapping": {
            "title": "$:/language/ThemeTweaks/Options/CodeWrapping",
            "text": "Wrap long lines in code blocks"
        },
        "$:/language/ThemeTweaks/Settings": {
            "title": "$:/language/ThemeTweaks/Settings",
            "text": "Settings"
        },
        "$:/language/ThemeTweaks/Settings/FontFamily": {
            "title": "$:/language/ThemeTweaks/Settings/FontFamily",
            "text": "Font family"
        },
        "$:/language/ThemeTweaks/Settings/CodeFontFamily": {
            "title": "$:/language/ThemeTweaks/Settings/CodeFontFamily",
            "text": "Code font family"
        },
        "$:/language/ThemeTweaks/Settings/EditorFontFamily": {
            "title": "$:/language/ThemeTweaks/Settings/EditorFontFamily",
            "text": "Editor font family"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImage": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImage",
            "text": "Page background image"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment",
            "text": "Page background image attachment"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Scroll": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Scroll",
            "text": "Scroll with tiddlers"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Fixed": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Fixed",
            "text": "Fixed to window"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize",
            "text": "Page background image size"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Auto": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Auto",
            "text": "Auto"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Cover": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Cover",
            "text": "Cover"
        },
        "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Contain": {
            "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Contain",
            "text": "Contain"
        },
        "$:/language/ThemeTweaks/Metrics": {
            "title": "$:/language/ThemeTweaks/Metrics",
            "text": "Sizes"
        },
        "$:/language/ThemeTweaks/Metrics/FontSize": {
            "title": "$:/language/ThemeTweaks/Metrics/FontSize",
            "text": "Font size"
        },
        "$:/language/ThemeTweaks/Metrics/LineHeight": {
            "title": "$:/language/ThemeTweaks/Metrics/LineHeight",
            "text": "Line height"
        },
        "$:/language/ThemeTweaks/Metrics/BodyFontSize": {
            "title": "$:/language/ThemeTweaks/Metrics/BodyFontSize",
            "text": "Font size for tiddler body"
        },
        "$:/language/ThemeTweaks/Metrics/BodyLineHeight": {
            "title": "$:/language/ThemeTweaks/Metrics/BodyLineHeight",
            "text": "Line height for tiddler body"
        },
        "$:/language/ThemeTweaks/Metrics/StoryLeft": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryLeft",
            "text": "Story left position"
        },
        "$:/language/ThemeTweaks/Metrics/StoryLeft/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryLeft/Hint",
            "text": "how far the left margin of the story river<br>(tiddler area) is from the left of the page"
        },
        "$:/language/ThemeTweaks/Metrics/StoryTop": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryTop",
            "text": "Story top position"
        },
        "$:/language/ThemeTweaks/Metrics/StoryTop/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryTop/Hint",
            "text": "how far the top margin of the story river<br>is from the top of the page"
        },
        "$:/language/ThemeTweaks/Metrics/StoryRight": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryRight",
            "text": "Story right"
        },
        "$:/language/ThemeTweaks/Metrics/StoryRight/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryRight/Hint",
            "text": "how far the left margin of the sidebar <br>is from the left of the page"
        },
        "$:/language/ThemeTweaks/Metrics/StoryWidth": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryWidth",
            "text": "Story width"
        },
        "$:/language/ThemeTweaks/Metrics/StoryWidth/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/StoryWidth/Hint",
            "text": "the overall width of the story river"
        },
        "$:/language/ThemeTweaks/Metrics/TiddlerWidth": {
            "title": "$:/language/ThemeTweaks/Metrics/TiddlerWidth",
            "text": "Tiddler width"
        },
        "$:/language/ThemeTweaks/Metrics/TiddlerWidth/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/TiddlerWidth/Hint",
            "text": "within the story river"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint",
            "text": "Sidebar breakpoint"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint/Hint",
            "text": "the minimum page width at which the story<br>river and sidebar will appear side by side"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarWidth": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarWidth",
            "text": "Sidebar width"
        },
        "$:/language/ThemeTweaks/Metrics/SidebarWidth/Hint": {
            "title": "$:/language/ThemeTweaks/Metrics/SidebarWidth/Hint",
            "text": "the width of the sidebar in fluid-fixed layout"
        },
        "$:/language/TiddlerInfo/Advanced/Caption": {
            "title": "$:/language/TiddlerInfo/Advanced/Caption",
            "text": "Advanced"
        },
        "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint",
            "text": "none"
        },
        "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading": {
            "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading",
            "text": "Plugin Details"
        },
        "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint",
            "text": "This plugin contains the following shadow tiddlers:"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading",
            "text": "Shadow Status"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint",
            "text": "The tiddler <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> is not a shadow tiddler"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint",
            "text": "The tiddler <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> is a shadow tiddler"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source",
            "text": "It is defined in the plugin <$link to=<<pluginTiddler>>><$text text=<<pluginTiddler>>/></$link>"
        },
        "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint": {
            "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint",
            "text": "It is overridden by an ordinary tiddler"
        },
        "$:/language/TiddlerInfo/Fields/Caption": {
            "title": "$:/language/TiddlerInfo/Fields/Caption",
            "text": "Fields"
        },
        "$:/language/TiddlerInfo/List/Caption": {
            "title": "$:/language/TiddlerInfo/List/Caption",
            "text": "List"
        },
        "$:/language/TiddlerInfo/List/Empty": {
            "title": "$:/language/TiddlerInfo/List/Empty",
            "text": "This tiddler does not have a list"
        },
        "$:/language/TiddlerInfo/Listed/Caption": {
            "title": "$:/language/TiddlerInfo/Listed/Caption",
            "text": "Listed"
        },
        "$:/language/TiddlerInfo/Listed/Empty": {
            "title": "$:/language/TiddlerInfo/Listed/Empty",
            "text": "This tiddler is not listed by any others"
        },
        "$:/language/TiddlerInfo/References/Caption": {
            "title": "$:/language/TiddlerInfo/References/Caption",
            "text": "References"
        },
        "$:/language/TiddlerInfo/References/Empty": {
            "title": "$:/language/TiddlerInfo/References/Empty",
            "text": "No tiddlers link to this one"
        },
        "$:/language/TiddlerInfo/Tagging/Caption": {
            "title": "$:/language/TiddlerInfo/Tagging/Caption",
            "text": "Tagging"
        },
        "$:/language/TiddlerInfo/Tagging/Empty": {
            "title": "$:/language/TiddlerInfo/Tagging/Empty",
            "text": "No tiddlers are tagged with this one"
        },
        "$:/language/TiddlerInfo/Tools/Caption": {
            "title": "$:/language/TiddlerInfo/Tools/Caption",
            "text": "Tools"
        },
        "$:/language/Docs/Types/application/javascript": {
            "title": "$:/language/Docs/Types/application/javascript",
            "description": "JavaScript code",
            "name": "application/javascript",
            "group": "Developer",
            "group-sort": "2"
        },
        "$:/language/Docs/Types/application/json": {
            "title": "$:/language/Docs/Types/application/json",
            "description": "JSON data",
            "name": "application/json",
            "group": "Developer",
            "group-sort": "2"
        },
        "$:/language/Docs/Types/application/x-tiddler-dictionary": {
            "title": "$:/language/Docs/Types/application/x-tiddler-dictionary",
            "description": "Data dictionary",
            "name": "application/x-tiddler-dictionary",
            "group": "Developer",
            "group-sort": "2"
        },
        "$:/language/Docs/Types/image/gif": {
            "title": "$:/language/Docs/Types/image/gif",
            "description": "GIF image",
            "name": "image/gif",
            "group": "Image",
            "group-sort": "1"
        },
        "$:/language/Docs/Types/image/jpeg": {
            "title": "$:/language/Docs/Types/image/jpeg",
            "description": "JPEG image",
            "name": "image/jpeg",
            "group": "Image",
            "group-sort": "1"
        },
        "$:/language/Docs/Types/image/png": {
            "title": "$:/language/Docs/Types/image/png",
            "description": "PNG image",
            "name": "image/png",
            "group": "Image",
            "group-sort": "1"
        },
        "$:/language/Docs/Types/image/svg+xml": {
            "title": "$:/language/Docs/Types/image/svg+xml",
            "description": "Structured Vector Graphics image",
            "name": "image/svg+xml",
            "group": "Image",
            "group-sort": "1"
        },
        "$:/language/Docs/Types/image/x-icon": {
            "title": "$:/language/Docs/Types/image/x-icon",
            "description": "ICO format icon file",
            "name": "image/x-icon",
            "group": "Image",
            "group-sort": "1"
        },
        "$:/language/Docs/Types/text/css": {
            "title": "$:/language/Docs/Types/text/css",
            "description": "Static stylesheet",
            "name": "text/css",
            "group": "Developer",
            "group-sort": "2"
        },
        "$:/language/Docs/Types/text/html": {
            "title": "$:/language/Docs/Types/text/html",
            "description": "HTML markup",
            "name": "text/html",
            "group": "Text",
            "group-sort": "0"
        },
        "$:/language/Docs/Types/text/plain": {
            "title": "$:/language/Docs/Types/text/plain",
            "description": "Plain text",
            "name": "text/plain",
            "group": "Text",
            "group-sort": "0"
        },
        "$:/language/Docs/Types/text/vnd.tiddlywiki": {
            "title": "$:/language/Docs/Types/text/vnd.tiddlywiki",
            "description": "TiddlyWiki 5",
            "name": "text/vnd.tiddlywiki",
            "group": "Text",
            "group-sort": "0"
        },
        "$:/language/Docs/Types/text/x-tiddlywiki": {
            "title": "$:/language/Docs/Types/text/x-tiddlywiki",
            "description": "TiddlyWiki Classic",
            "name": "text/x-tiddlywiki",
            "group": "Text",
            "group-sort": "0"
        },
        "$:/languages/en-GB/icon": {
            "title": "$:/languages/en-GB/icon",
            "type": "image/svg+xml",
            "text": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 60 30\" width=\"1200\" height=\"600\">\n<clipPath id=\"t\">\n\t<path d=\"M30,15 h30 v15 z v15 h-30 z h-30 v-15 z v-15 h30 z\"/>\n</clipPath>\n<path d=\"M0,0 v30 h60 v-30 z\" fill=\"#00247d\"/>\n<path d=\"M0,0 L60,30 M60,0 L0,30\" stroke=\"#fff\" stroke-width=\"6\"/>\n<path d=\"M0,0 L60,30 M60,0 L0,30\" clip-path=\"url(#t)\" stroke=\"#cf142b\" stroke-width=\"4\"/>\n<path d=\"M30,0 v30 M0,15 h60\" stroke=\"#fff\" stroke-width=\"10\"/>\n<path d=\"M30,0 v30 M0,15 h60\" stroke=\"#cf142b\" stroke-width=\"6\"/>\n</svg>\n"
        },
        "$:/languages/en-GB": {
            "title": "$:/languages/en-GB",
            "name": "en-GB",
            "description": "English (British)",
            "author": "JeremyRuston",
            "core-version": ">=5.0.0\"",
            "text": "Stub pseudo-plugin for the default language"
        },
        "$:/core/modules/commander.js": {
            "title": "$:/core/modules/commander.js",
            "text": "/*\\\ntitle: $:/core/modules/commander.js\ntype: application/javascript\nmodule-type: global\n\nThe $tw.Commander class is a command interpreter\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nParse a sequence of commands\n\tcommandTokens: an array of command string tokens\n\twiki: reference to the wiki store object\n\tstreams: {output:, error:}, each of which has a write(string) method\n\tcallback: a callback invoked as callback(err) where err is null if there was no error\n*/\nvar Commander = function(commandTokens,callback,wiki,streams) {\n\tvar path = require(\"path\");\n\tthis.commandTokens = commandTokens;\n\tthis.nextToken = 0;\n\tthis.callback = callback;\n\tthis.wiki = wiki;\n\tthis.streams = streams;\n\tthis.outputPath = path.resolve($tw.boot.wikiPath,$tw.config.wikiOutputSubDir);\n};\n\n/*\nLog a string if verbose flag is set\n*/\nCommander.prototype.log = function(str) {\n\tif(this.verbose) {\n\t\tthis.streams.output.write(str + \"\\n\");\n\t}\n};\n\n/*\nWrite a string if verbose flag is set\n*/\nCommander.prototype.write = function(str) {\n\tif(this.verbose) {\n\t\tthis.streams.output.write(str);\n\t}\n};\n\n/*\nAdd a string of tokens to the command queue\n*/\nCommander.prototype.addCommandTokens = function(commandTokens) {\n\tvar params = commandTokens.slice(0);\n\tparams.unshift(0);\n\tparams.unshift(this.nextToken);\n\tArray.prototype.splice.apply(this.commandTokens,params);\n};\n\n/*\nExecute the sequence of commands and invoke a callback on completion\n*/\nCommander.prototype.execute = function() {\n\tthis.executeNextCommand();\n};\n\n/*\nExecute the next command in the sequence\n*/\nCommander.prototype.executeNextCommand = function() {\n\tvar self = this;\n\t// Invoke the callback if there are no more commands\n\tif(this.nextToken >= this.commandTokens.length) {\n\t\tthis.callback(null);\n\t} else {\n\t\t// Get and check the command token\n\t\tvar commandName = this.commandTokens[this.nextToken++];\n\t\tif(commandName.substr(0,2) !== \"--\") {\n\t\t\tthis.callback(\"Missing command: \" + commandName);\n\t\t} else {\n\t\t\tcommandName = commandName.substr(2); // Trim off the --\n\t\t\t// Accumulate the parameters to the command\n\t\t\tvar params = [];\n\t\t\twhile(this.nextToken < this.commandTokens.length && \n\t\t\t\tthis.commandTokens[this.nextToken].substr(0,2) !== \"--\") {\n\t\t\t\tparams.push(this.commandTokens[this.nextToken++]);\n\t\t\t}\n\t\t\t// Get the command info\n\t\t\tvar command = $tw.commands[commandName],\n\t\t\t\tc,err;\n\t\t\tif(!command) {\n\t\t\t\tthis.callback(\"Unknown command: \" + commandName);\n\t\t\t} else {\n\t\t\t\tif(this.verbose) {\n\t\t\t\t\tthis.streams.output.write(\"Executing command: \" + commandName + \" \" + params.join(\" \") + \"\\n\");\n\t\t\t\t}\n\t\t\t\t// Parse named parameters if required\n\t\t\t\tif(command.info.namedParameterMode) {\n\t\t\t\t\tparams = this.extractNamedParameters(params,command.info.mandatoryParameters);\n\t\t\t\t\tif(typeof params === \"string\") {\n\t\t\t\t\t\treturn this.callback(params);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(command.info.synchronous) {\n\t\t\t\t\t// Synchronous command\n\t\t\t\t\tc = new command.Command(params,this);\n\t\t\t\t\terr = c.execute();\n\t\t\t\t\tif(err) {\n\t\t\t\t\t\tthis.callback(err);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.executeNextCommand();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Asynchronous command\n\t\t\t\t\tc = new command.Command(params,this,function(err) {\n\t\t\t\t\t\tif(err) {\n\t\t\t\t\t\t\tself.callback(err);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.executeNextCommand();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\terr = c.execute();\n\t\t\t\t\tif(err) {\n\t\t\t\t\t\tthis.callback(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\n/*\nGiven an array of parameter strings `params` in name:value format, and an array of mandatory parameter names in `mandatoryParameters`, returns a hashmap of values or a string if error\n*/\nCommander.prototype.extractNamedParameters = function(params,mandatoryParameters) {\n\tmandatoryParameters = mandatoryParameters || [];\n\tvar errors = [],\n\t\tparamsByName = Object.create(null);\n\t// Extract the parameters\n\t$tw.utils.each(params,function(param) {\n\t\tvar index = param.indexOf(\"=\");\n\t\tif(index < 1) {\n\t\t\terrors.push(\"malformed named parameter: '\" + param + \"'\");\n\t\t}\n\t\tparamsByName[param.slice(0,index)] = $tw.utils.trim(param.slice(index+1));\n\t});\n\t// Check the mandatory parameters are present\n\t$tw.utils.each(mandatoryParameters,function(mandatoryParameter) {\n\t\tif(!$tw.utils.hop(paramsByName,mandatoryParameter)) {\n\t\t\terrors.push(\"missing mandatory parameter: '\" + mandatoryParameter + \"'\");\n\t\t}\n\t});\n\t// Return any errors\n\tif(errors.length > 0) {\n\t\treturn errors.join(\" and\\n\");\n\t} else {\n\t\treturn paramsByName;\t\t\n\t}\n};\n\nCommander.initCommands = function(moduleType) {\n\tmoduleType = moduleType || \"command\";\n\t$tw.commands = {};\n\t$tw.modules.forEachModuleOfType(moduleType,function(title,module) {\n\t\tvar c = $tw.commands[module.info.name] = {};\n\t\t// Add the methods defined by the module\n\t\tfor(var f in module) {\n\t\t\tif($tw.utils.hop(module,f)) {\n\t\t\t\tc[f] = module[f];\n\t\t\t}\n\t\t}\n\t});\n};\n\nexports.Commander = Commander;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/commands/build.js": {
            "title": "$:/core/modules/commands/build.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/build.js\ntype: application/javascript\nmodule-type: command\n\nCommand to build a build target\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"build\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\t// Get the build targets defined in the wiki\n\tvar buildTargets = $tw.boot.wikiInfo.build;\n\tif(!buildTargets) {\n\t\treturn \"No build targets defined\";\n\t}\n\t// Loop through each of the specified targets\n\tvar targets;\n\tif(this.params.length > 0) {\n\t\ttargets = this.params;\n\t} else {\n\t\ttargets = Object.keys(buildTargets);\n\t}\n\tfor(var targetIndex=0; targetIndex<targets.length; targetIndex++) {\n\t\tvar target = targets[targetIndex],\n\t\t\tcommands = buildTargets[target];\n\t\tif(!commands) {\n\t\t\treturn \"Build target '\" + target + \"' not found\";\n\t\t}\n\t\t// Add the commands to the queue\n\t\tthis.commander.addCommandTokens(commands);\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/clearpassword.js": {
            "title": "$:/core/modules/commands/clearpassword.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/clearpassword.js\ntype: application/javascript\nmodule-type: command\n\nClear password for crypto operations\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"clearpassword\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\t$tw.crypto.setPassword(null);\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/deletetiddlers.js": {
            "title": "$:/core/modules/commands/deletetiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/deletetiddlers.js\ntype: application/javascript\nmodule-type: command\n\nCommand to delete tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"deletetiddlers\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing filter\";\n\t}\n\tvar self = this,\n\t\twiki = this.commander.wiki,\n\t\tfilter = this.params[0],\n\t\ttiddlers = wiki.filterTiddlers(filter);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\twiki.deleteTiddler(title);\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/editions.js": {
            "title": "$:/core/modules/commands/editions.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/editions.js\ntype: application/javascript\nmodule-type: command\n\nCommand to list the available editions\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"editions\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tvar self = this;\n\t// Output the list\n\tthis.commander.streams.output.write(\"Available editions:\\n\\n\");\n\tvar editionInfo = $tw.utils.getEditionInfo();\n\t$tw.utils.each(editionInfo,function(info,name) {\n\t\tself.commander.streams.output.write(\"    \" + name + \": \" + info.description + \"\\n\");\n\t});\n\tthis.commander.streams.output.write(\"\\n\");\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/fetch.js": {
            "title": "$:/core/modules/commands/fetch.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/fetch.js\ntype: application/javascript\nmodule-type: command\n\nCommands to fetch external tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"fetch\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing subcommand and url\";\n\t}\n\tswitch(this.params[0]) {\n\t\tcase \"raw-file\":\n\t\t\treturn this.fetchFiles({\n\t\t\t\traw: true,\n\t\t\t\turl: this.params[1],\n\t\t\t\ttransformFilter: this.params[2] || \"\",\n\t\t\t\tcallback: this.callback\n\t\t\t});\n\t\t\tbreak;\n\t\tcase \"file\":\n\t\t\treturn this.fetchFiles({\n\t\t\t\turl: this.params[1],\n\t\t\t\timportFilter: this.params[2],\n\t\t\t\ttransformFilter: this.params[3] || \"\",\n\t\t\t\tcallback: this.callback\n\t\t\t});\n\t\t\tbreak;\n\t\tcase \"raw-files\":\n\t\t\treturn this.fetchFiles({\n\t\t\t\traw: true,\n\t\t\t\turlFilter: this.params[1],\n\t\t\t\ttransformFilter: this.params[2] || \"\",\n\t\t\t\tcallback: this.callback\n\t\t\t});\n\t\t\tbreak;\n\t\tcase \"files\":\n\t\t\treturn this.fetchFiles({\n\t\t\t\turlFilter: this.params[1],\n\t\t\t\timportFilter: this.params[2],\n\t\t\t\ttransformFilter: this.params[3] || \"\",\n\t\t\t\tcallback: this.callback\n\t\t\t});\n\t\t\tbreak;\n\t}\n\treturn null;\n};\n\nCommand.prototype.fetchFiles = function(options) {\n\tvar self = this;\n\t// Get the list of URLs\n\tvar urls;\n\tif(options.url) {\n\t\turls = [options.url]\n\t} else if(options.urlFilter) {\n\t\turls = $tw.wiki.filterTiddlers(options.urlFilter);\n\t} else {\n\t\treturn \"Missing URL\";\n\t}\n\t// Process each URL in turn\n\tvar next = 0;\n\tvar getNextFile = function(err) {\n\t\tif(err) {\n\t\t\treturn options.callback(err);\n\t\t}\n\t\tif(next < urls.length) {\n\t\t\tself.fetchFile(urls[next++],options,getNextFile);\n\t\t} else {\n\t\t\toptions.callback(null);\n\t\t}\n\t};\n\tgetNextFile(null);\n\t// Success\n\treturn null;\n};\n\nCommand.prototype.fetchFile = function(url,options,callback,redirectCount) {\n\tif(redirectCount > 10) {\n\t\treturn callback(\"Error too many redirects retrieving \" + url);\n\t}\n\tvar self = this,\n\t\tlib = url.substr(0,8) === \"https://\" ? require(\"https\") : require(\"http\");\n\tlib.get(url).on(\"response\",function(response) {\n\t    var type = (response.headers[\"content-type\"] || \"\").split(\";\")[0],\n\t    \tdata = [];\n\t    self.commander.write(\"Reading \" + url + \": \");\n\t    response.on(\"data\",function(chunk) {\n\t        data.push(chunk);\n\t        self.commander.write(\".\");\n\t    });\n\t    response.on(\"end\",function() {\n\t        self.commander.write(\"\\n\");\n\t        if(response.statusCode === 200) {\n\t\t        self.processBody(Buffer.concat(data),type,options,url);\n\t\t        callback(null);\n\t        } else {\n\t        \tif(response.statusCode === 302 || response.statusCode === 303 || response.statusCode === 307) {\n\t        \t\treturn self.fetchFile(response.headers.location,options,callback,redirectCount + 1);\n\t        \t} else {\n\t\t        \treturn callback(\"Error \" + response.statusCode + \" retrieving \" + url)\t        \t\t\n\t        \t}\n\t        }\n\t   \t});\n\t   \tresponse.on(\"error\",function(e) {\n\t\t\tconsole.log(\"Error on GET request: \" + e);\n\t\t\tcallback(e);\n\t   \t});\n\t});\n\treturn null;\n};\n\nCommand.prototype.processBody = function(body,type,options,url) {\n\tvar self = this;\n\t// Collect the tiddlers in a wiki\n\tvar incomingWiki = new $tw.Wiki();\n\tif(options.raw) {\n\t\tvar typeInfo = type ? $tw.config.contentTypeInfo[type] : null,\n\t\t\tencoding = typeInfo ? typeInfo.encoding : \"utf8\";\n\t\tincomingWiki.addTiddler(new $tw.Tiddler({\n\t\t\ttitle: url,\n\t\t\ttype: type,\n\t\t\ttext: body.toString(encoding)\n\t\t}));\n\t} else {\n\t\t// Deserialise the file to extract the tiddlers\n\t\tvar tiddlers = this.commander.wiki.deserializeTiddlers(type || \"text/html\",body.toString(\"utf8\"),{});\n\t\t$tw.utils.each(tiddlers,function(tiddler) {\n\t\t\tincomingWiki.addTiddler(new $tw.Tiddler(tiddler));\n\t\t});\n\t}\n\t// Filter the tiddlers to select the ones we want\n\tvar filteredTitles = incomingWiki.filterTiddlers(options.importFilter || \"[all[tiddlers]]\");\n\t// Import the selected tiddlers\n\tvar count = 0;\n\tincomingWiki.each(function(tiddler,title) {\n\t\tif(filteredTitles.indexOf(title) !== -1) {\n\t\t\tvar newTiddler;\n\t\t\tif(options.transformFilter) {\n\t\t\t\tvar transformedTitle = (incomingWiki.filterTiddlers(options.transformFilter,null,self.commander.wiki.makeTiddlerIterator([title])) || [\"\"])[0];\n\t\t\t\tif(transformedTitle) {\n\t\t\t\t\tself.commander.log(\"Importing \" + title + \" as \" + transformedTitle)\n\t\t\t\t\tnewTiddler = new $tw.Tiddler(tiddler,{title: transformedTitle});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tself.commander.log(\"Importing \" + title)\n\t\t\t\tnewTiddler = tiddler;\n\t\t\t}\n\t\t\tself.commander.wiki.importTiddler(newTiddler);\n\t\t\tcount++;\n\t\t}\n\t});\n\tself.commander.log(\"Imported \" + count + \" tiddlers\")\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/help.js": {
            "title": "$:/core/modules/commands/help.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/help.js\ntype: application/javascript\nmodule-type: command\n\nHelp command\n\n\\*/\n(function(){\n\n/*jshint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"help\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tvar subhelp = this.params[0] || \"default\",\n\t\thelpBase = \"$:/language/Help/\",\n\t\ttext;\n\tif(!this.commander.wiki.getTiddler(helpBase + subhelp)) {\n\t\tsubhelp = \"notfound\";\n\t}\n\t// Wikify the help as formatted text (ie block elements generate newlines)\n\ttext = this.commander.wiki.renderTiddler(\"text/plain-formatted\",helpBase + subhelp);\n\t// Remove any leading linebreaks\n\ttext = text.replace(/^(\\r?\\n)*/g,\"\");\n\tthis.commander.streams.output.write(text);\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/import.js": {
            "title": "$:/core/modules/commands/import.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/import.js\ntype: application/javascript\nmodule-type: command\n\nCommand to import tiddlers from a file\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"import\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\");\n\tif(this.params.length < 2) {\n\t\treturn \"Missing parameters\";\n\t}\n\tvar filename = self.params[0],\n\t\tdeserializer = self.params[1],\n\t\ttitle = self.params[2] || filename,\n\t\tencoding = self.params[3] || \"utf8\",\n\t\ttext = fs.readFileSync(filename,encoding),\n\t\ttiddlers = this.commander.wiki.deserializeTiddlers(null,text,{title: title},{deserializer: deserializer});\n\t$tw.utils.each(tiddlers,function(tiddler) {\n\t\tself.commander.wiki.importTiddler(new $tw.Tiddler(tiddler));\n\t});\n\tthis.commander.log(tiddlers.length + \" tiddler(s) imported\");\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/init.js": {
            "title": "$:/core/modules/commands/init.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/init.js\ntype: application/javascript\nmodule-type: command\n\nCommand to initialise an empty wiki folder\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"init\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tvar fs = require(\"fs\"),\n\t\tpath = require(\"path\");\n\t// Check that we don't already have a valid wiki folder\n\tif($tw.boot.wikiTiddlersPath || ($tw.utils.isDirectory($tw.boot.wikiPath) && !$tw.utils.isDirectoryEmpty($tw.boot.wikiPath))) {\n\t\treturn \"Wiki folder is not empty\";\n\t}\n\t// Loop through each of the specified editions\n\tvar editions = this.params.length > 0 ? this.params : [\"empty\"];\n\tfor(var editionIndex=0; editionIndex<editions.length; editionIndex++) {\n\t\tvar editionName = editions[editionIndex];\n\t\t// Check the edition exists\n\t\tvar editionPath = $tw.findLibraryItem(editionName,$tw.getLibraryItemSearchPaths($tw.config.editionsPath,$tw.config.editionsEnvVar));\n\t\tif(!$tw.utils.isDirectory(editionPath)) {\n\t\t\treturn \"Edition '\" + editionName + \"' not found\";\n\t\t}\n\t\t// Copy the edition content\n\t\tvar err = $tw.utils.copyDirectory(editionPath,$tw.boot.wikiPath);\n\t\tif(!err) {\n\t\t\tthis.commander.streams.output.write(\"Copied edition '\" + editionName + \"' to \" + $tw.boot.wikiPath + \"\\n\");\n\t\t} else {\n\t\t\treturn err;\n\t\t}\n\t}\n\t// Tweak the tiddlywiki.info to remove any included wikis\n\tvar packagePath = $tw.boot.wikiPath + \"/tiddlywiki.info\",\n\t\tpackageJson = JSON.parse(fs.readFileSync(packagePath));\n\tdelete packageJson.includeWikis;\n\tfs.writeFileSync(packagePath,JSON.stringify(packageJson,null,$tw.config.preferences.jsonSpaces));\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/listen.js": {
            "title": "$:/core/modules/commands/listen.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/listen.js\ntype: application/javascript\nmodule-type: command\n\nListen for HTTP requests and serve tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Server = require(\"$:/core/modules/server/server.js\").Server;\n\nexports.info = {\n\tname: \"listen\",\n\tsynchronous: true,\n\tnamedParameterMode: true,\n\tmandatoryParameters: [],\n};\n\nvar Command = function(params,commander,callback) {\n\tvar self = this;\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar self = this;\n\tif(!$tw.boot.wikiTiddlersPath) {\n\t\t$tw.utils.warning(\"Warning: Wiki folder '\" + $tw.boot.wikiPath + \"' does not exist or is missing a tiddlywiki.info file\");\n\t}\n\t// Set up server\n\tthis.server = new Server({\n\t\twiki: this.commander.wiki,\n\t\tvariables: self.params\n\t});\n\tvar nodeServer = this.server.listen();\n\t$tw.hooks.invokeHook(\"th-server-command-post-start\",this.server,nodeServer,\"tiddlywiki\");\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/load.js": {
            "title": "$:/core/modules/commands/load.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/load.js\ntype: application/javascript\nmodule-type: command\n\nCommand to load tiddlers from a file or directory\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"load\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\");\n\tif(this.params.length < 1) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar tiddlers = $tw.loadTiddlersFromPath(self.params[0]),\n\t\tcount = 0;\n\t$tw.utils.each(tiddlers,function(tiddlerInfo) {\n\t\t$tw.utils.each(tiddlerInfo.tiddlers,function(tiddler) {\n\t\t\tself.commander.wiki.importTiddler(new $tw.Tiddler(tiddler));\n\t\t\tcount++;\n\t\t});\n\t});\n\tif(!count && self.params[1] !== \"noerror\") {\n\t\tself.callback(\"No tiddlers found in file \\\"\" + self.params[0] + \"\\\"\");\n\t} else {\n\t\tself.callback(null);\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/makelibrary.js": {
            "title": "$:/core/modules/commands/makelibrary.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/makelibrary.js\ntype: application/javascript\nmodule-type: command\n\nCommand to pack all of the plugins in the library into a plugin tiddler of type \"library\"\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"makelibrary\",\n\tsynchronous: true\n};\n\nvar UPGRADE_LIBRARY_TITLE = \"$:/UpgradeLibrary\";\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar wiki = this.commander.wiki,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\tupgradeLibraryTitle = this.params[0] || UPGRADE_LIBRARY_TITLE,\n\t\ttiddlers = {};\n\t// Collect up the library plugins\n\tvar collectPlugins = function(folder) {\n\t\t\tvar pluginFolders = fs.readdirSync(folder);\n\t\t\tfor(var p=0; p<pluginFolders.length; p++) {\n\t\t\t\tif(!$tw.boot.excludeRegExp.test(pluginFolders[p])) {\n\t\t\t\t\tpluginFields = $tw.loadPluginFolder(path.resolve(folder,\"./\" + pluginFolders[p]));\n\t\t\t\t\tif(pluginFields && pluginFields.title) {\n\t\t\t\t\t\ttiddlers[pluginFields.title] = pluginFields;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcollectPublisherPlugins = function(folder) {\n\t\t\tvar publisherFolders = fs.readdirSync(folder);\n\t\t\tfor(var t=0; t<publisherFolders.length; t++) {\n\t\t\t\tif(!$tw.boot.excludeRegExp.test(publisherFolders[t])) {\n\t\t\t\t\tcollectPlugins(path.resolve(folder,\"./\" + publisherFolders[t]));\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.pluginsPath,$tw.config.pluginsEnvVar),collectPublisherPlugins);\n\t$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.themesPath,$tw.config.themesEnvVar),collectPublisherPlugins);\n\t$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.languagesPath,$tw.config.languagesEnvVar),collectPlugins);\n\t// Save the upgrade library tiddler\n\tvar pluginFields = {\n\t\ttitle: upgradeLibraryTitle,\n\t\ttype: \"application/json\",\n\t\t\"plugin-type\": \"library\",\n\t\t\"text\": JSON.stringify({tiddlers: tiddlers})\n\t};\n\twiki.addTiddler(new $tw.Tiddler(pluginFields));\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/output.js": {
            "title": "$:/core/modules/commands/output.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/output.js\ntype: application/javascript\nmodule-type: command\n\nCommand to set the default output location (defaults to current working directory)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"output\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar fs = require(\"fs\"),\n\t\tpath = require(\"path\");\n\tif(this.params.length < 1) {\n\t\treturn \"Missing output path\";\n\t}\n\tthis.commander.outputPath = path.resolve(process.cwd(),this.params[0]);\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/password.js": {
            "title": "$:/core/modules/commands/password.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/password.js\ntype: application/javascript\nmodule-type: command\n\nSave password for crypto operations\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"password\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing password\";\n\t}\n\t$tw.crypto.setPassword(this.params[0]);\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/render.js": {
            "title": "$:/core/modules/commands/render.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/render.js\ntype: application/javascript\nmodule-type: command\n\nRender individual tiddlers and save the results to the specified files\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.info = {\n\tname: \"render\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing tiddler filter\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\twiki = this.commander.wiki,\n\t\ttiddlerFilter = this.params[0],\n\t\tfilenameFilter = this.params[1] || \"[is[tiddler]addsuffix[.html]]\",\n\t\ttype = this.params[2] || \"text/html\",\n\t\ttemplate = this.params[3],\n\t\tvarName = this.params[4],\n\t\tvarValue = this.params[5],\n\t\ttiddlers = wiki.filterTiddlers(tiddlerFilter);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar parser = wiki.parseTiddler(template || title),\n\t\t\tvariables = {currentTiddler: title};\n\t\tif(varName) {\n\t\t\tvariables[varName] = varValue || \"\";\n\t\t}\n\t\tvar widgetNode = wiki.makeWidget(parser,{variables: variables}),\n\t\t\tcontainer = $tw.fakeDocument.createElement(\"div\");\n\t\twidgetNode.render(container,null);\n\t\tvar text = type === \"text/html\" ? container.innerHTML : container.textContent,\n\t\t\tfilepath = path.resolve(self.commander.outputPath,wiki.filterTiddlers(filenameFilter,$tw.rootWidget,wiki.makeTiddlerIterator([title]))[0]);\n\t\tif(self.commander.verbose) {\n\t\t\tconsole.log(\"Rendering \\\"\" + title + \"\\\" to \\\"\" + filepath + \"\\\"\");\n\t\t}\n\t\t$tw.utils.createFileDirectories(filepath);\n\t\tfs.writeFileSync(filepath,text,\"utf8\");\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/rendertiddler.js": {
            "title": "$:/core/modules/commands/rendertiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/rendertiddler.js\ntype: application/javascript\nmodule-type: command\n\nCommand to render a tiddler and save it to a file\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"rendertiddler\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\ttitle = this.params[0],\n\t\tfilename = path.resolve(this.commander.outputPath,this.params[1]),\n\t\ttype = this.params[2] || \"text/html\",\n\t\ttemplate = this.params[3],\n\t\tname = this.params[4],\n\t\tvalue = this.params[5],\n\t\tvariables = {};\n\t$tw.utils.createFileDirectories(filename);\n\tif(template) {\n\t\tvariables.currentTiddler = title;\n\t\ttitle = template;\n\t}\n\tif(name && value) {\n\t\tvariables[name] = value;\n\t}\n\tfs.writeFile(filename,this.commander.wiki.renderTiddler(type,title,{variables: variables}),\"utf8\",function(err) {\n\t\tself.callback(err);\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/rendertiddlers.js": {
            "title": "$:/core/modules/commands/rendertiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/rendertiddlers.js\ntype: application/javascript\nmodule-type: command\n\nCommand to render several tiddlers to a folder of files\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.info = {\n\tname: \"rendertiddlers\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\twiki = this.commander.wiki,\n\t\tfilter = this.params[0],\n\t\ttemplate = this.params[1],\n\t\toutputPath = this.commander.outputPath,\n\t\tpathname = path.resolve(outputPath,this.params[2]),\t\t\n\t\ttype = this.params[3] || \"text/html\",\n\t\textension = this.params[4] || \".html\",\n\t\tdeleteDirectory = (this.params[5] || \"\").toLowerCase() !== \"noclean\",\n\t\ttiddlers = wiki.filterTiddlers(filter);\n\tif(deleteDirectory) {\n\t\t$tw.utils.deleteDirectory(pathname);\n\t}\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar parser = wiki.parseTiddler(template),\n\t\t\twidgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}}),\n\t\t\tcontainer = $tw.fakeDocument.createElement(\"div\");\n\t\twidgetNode.render(container,null);\n\t\tvar text = type === \"text/html\" ? container.innerHTML : container.textContent,\n\t\t\texportPath = null;\n\t\tif($tw.utils.hop($tw.macros,\"tv-get-export-path\")) {\n\t\t\tvar macroPath = $tw.macros[\"tv-get-export-path\"].run.apply(self,[title]);\n\t\t\tif(macroPath) {\n\t\t\t\texportPath = path.resolve(outputPath,macroPath + extension);\n\t\t\t}\n\t\t}\n\t\tvar finalPath = exportPath || path.resolve(pathname,encodeURIComponent(title) + extension);\n\t\t$tw.utils.createFileDirectories(finalPath);\n\t\tfs.writeFileSync(finalPath,text,\"utf8\");\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/save.js": {
            "title": "$:/core/modules/commands/save.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/save.js\ntype: application/javascript\nmodule-type: command\n\nSaves individual tiddlers in their raw text or binary format to the specified files\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"save\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing filename filter\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\twiki = this.commander.wiki,\n\t\ttiddlerFilter = this.params[0],\n\t\tfilenameFilter = this.params[1] || \"[is[tiddler]]\",\n\t\ttiddlers = wiki.filterTiddlers(tiddlerFilter);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = self.commander.wiki.getTiddler(title),\n\t\t\ttype = tiddler.fields.type || \"text/vnd.tiddlywiki\",\n\t\t\tcontentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: \"utf8\"},\n\t\t\tfilepath = path.resolve(self.commander.outputPath,wiki.filterTiddlers(filenameFilter,$tw.rootWidget,wiki.makeTiddlerIterator([title]))[0]);\n\t\tif(self.commander.verbose) {\n\t\t\tconsole.log(\"Saving \\\"\" + title + \"\\\" to \\\"\" + filepath + \"\\\"\");\n\t\t}\n\t\t$tw.utils.createFileDirectories(filepath);\n\t\tfs.writeFileSync(filepath,tiddler.fields.text,contentTypeInfo.encoding);\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/savelibrarytiddlers.js": {
            "title": "$:/core/modules/commands/savelibrarytiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/savelibrarytiddlers.js\ntype: application/javascript\nmodule-type: command\n\nCommand to save the subtiddlers of a bundle tiddler as a series of JSON files\n\n--savelibrarytiddlers <tiddler> <pathname> <skinnylisting>\n\nThe tiddler identifies the bundle tiddler that contains the subtiddlers.\n\nThe pathname specifies the pathname to the folder in which the JSON files should be saved. The filename is the URL encoded title of the subtiddler.\n\nThe skinnylisting specifies the title of the tiddler to which a JSON catalogue of the subtiddlers will be saved. The JSON file contains the same data as the bundle tiddler but with the `text` field removed.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"savelibrarytiddlers\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\tcontainerTitle = this.params[0],\n\t\tfilter = this.params[1],\n\t\tbasepath = this.params[2],\n\t\tskinnyListTitle = this.params[3];\n\t// Get the container tiddler as data\n\tvar containerData = self.commander.wiki.getTiddlerDataCached(containerTitle,undefined);\n\tif(!containerData) {\n\t\treturn \"'\" + containerTitle + \"' is not a tiddler bundle\";\n\t}\n\t// Filter the list of plugins\n\tvar pluginList = [];\n\t$tw.utils.each(containerData.tiddlers,function(tiddler,title) {\n\t\tpluginList.push(title);\n\t});\n\tvar filteredPluginList;\n\tif(filter) {\n\t\tfilteredPluginList = self.commander.wiki.filterTiddlers(filter,null,self.commander.wiki.makeTiddlerIterator(pluginList));\n\t} else {\n\t\tfilteredPluginList = pluginList;\n\t}\n\t// Iterate through the plugins\n\tvar skinnyList = [];\n\t$tw.utils.each(filteredPluginList,function(title) {\n\t\tvar tiddler = containerData.tiddlers[title];\n\t\t// Save each JSON file and collect the skinny data\n\t\tvar pathname = path.resolve(self.commander.outputPath,basepath + encodeURIComponent(title) + \".json\");\n\t\t$tw.utils.createFileDirectories(pathname);\n\t\tfs.writeFileSync(pathname,JSON.stringify(tiddler),\"utf8\");\n\t\t// Collect the skinny list data\n\t\tvar pluginTiddlers = JSON.parse(tiddler.text),\n\t\t\treadmeContent = (pluginTiddlers.tiddlers[title + \"/readme\"] || {}).text,\n\t\t\tdoesRequireReload = !!$tw.wiki.doesPluginInfoRequireReload(pluginTiddlers),\n\t\t\ticonTiddler = pluginTiddlers.tiddlers[title + \"/icon\"] || {},\n\t\t\ticonType = iconTiddler.type,\n\t\t\ticonText = iconTiddler.text,\n\t\t\ticonContent;\n\t\tif(iconType && iconText) {\n\t\t\ticonContent = $tw.utils.makeDataUri(iconText,iconType);\n\t\t}\n\t\tskinnyList.push($tw.utils.extend({},tiddler,{\n\t\t\ttext: undefined,\n\t\t\treadme: readmeContent,\n\t\t\t\"requires-reload\": doesRequireReload ? \"yes\" : \"no\",\n\t\t\ticon: iconContent\n\t\t}));\n\t});\n\t// Save the catalogue tiddler\n\tif(skinnyListTitle) {\n\t\tself.commander.wiki.setTiddlerData(skinnyListTitle,skinnyList);\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/savetiddler.js": {
            "title": "$:/core/modules/commands/savetiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/savetiddler.js\ntype: application/javascript\nmodule-type: command\n\nCommand to save the content of a tiddler to a file\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"savetiddler\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\ttitle = this.params[0],\n\t\tfilename = path.resolve(this.commander.outputPath,this.params[1]),\n\t\ttiddler = this.commander.wiki.getTiddler(title);\n\tif(tiddler) {\n\t\tvar type = tiddler.fields.type || \"text/vnd.tiddlywiki\",\n\t\t\tcontentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: \"utf8\"};\n\t\t$tw.utils.createFileDirectories(filename);\n\t\tfs.writeFile(filename,tiddler.fields.text,contentTypeInfo.encoding,function(err) {\n\t\t\tself.callback(err);\n\t\t});\n\t} else {\n\t\treturn \"Missing tiddler: \" + title;\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/savetiddlers.js": {
            "title": "$:/core/modules/commands/savetiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/savetiddlers.js\ntype: application/javascript\nmodule-type: command\n\nCommand to save several tiddlers to a folder of files\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.info = {\n\tname: \"savetiddlers\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\twiki = this.commander.wiki,\n\t\tfilter = this.params[0],\n\t\tpathname = path.resolve(this.commander.outputPath,this.params[1]),\n\t\tdeleteDirectory = (this.params[2] || \"\").toLowerCase() !== \"noclean\",\n\t\ttiddlers = wiki.filterTiddlers(filter);\n\tif(deleteDirectory) {\n\t\t$tw.utils.deleteDirectory(pathname);\n\t}\n\t$tw.utils.createDirectory(pathname);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = self.commander.wiki.getTiddler(title),\n\t\t\ttype = tiddler.fields.type || \"text/vnd.tiddlywiki\",\n\t\t\tcontentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: \"utf8\"},\n\t\t\tfilename = path.resolve(pathname,encodeURIComponent(title));\n\t\tfs.writeFileSync(filename,tiddler.fields.text,contentTypeInfo.encoding);\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/savewikifolder.js": {
            "title": "$:/core/modules/commands/savewikifolder.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/savewikifolder.js\ntype: application/javascript\nmodule-type: command\n\nCommand to save the current wiki as a wiki folder\n\n--savewikifolder <wikifolderpath> [<filter>]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"savewikifolder\",\n\tsynchronous: true\n};\n\nvar fs,path;\nif($tw.node) {\n\tfs = require(\"fs\");\n\tpath = require(\"path\");\n}\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing wiki folder path\";\n\t}\n\tvar wikifoldermaker = new WikiFolderMaker(this.params[0],this.params[1],this.commander);\n\treturn wikifoldermaker.save();\n};\n\nfunction WikiFolderMaker(wikiFolderPath,wikiFilter,commander) {\n\tthis.wikiFolderPath = wikiFolderPath;\n\tthis.wikiFilter = wikiFilter || \"[all[tiddlers]]\";\n\tthis.commander = commander;\n\tthis.wiki = commander.wiki;\n\tthis.savedPaths = []; // So that we can detect filename clashes\n}\n\nWikiFolderMaker.prototype.log = function(str) {\n\tif(this.commander.verbose) {\n\t\tconsole.log(str);\n\t}\n};\n\nWikiFolderMaker.prototype.tiddlersToIgnore = [\n\t\"$:/boot/boot.css\",\n\t\"$:/boot/boot.js\",\n\t\"$:/boot/bootprefix.js\",\n\t\"$:/core\",\n\t\"$:/library/sjcl.js\",\n\t\"$:/temp/info-plugin\"\n];\n\n/*\nReturns null if successful, or an error string if there was an error\n*/\nWikiFolderMaker.prototype.save = function() {\n\tvar self = this;\n\t// Check that the output directory doesn't exist\n\tif(fs.existsSync(this.wikiFolderPath) && !$tw.utils.isDirectoryEmpty(this.wikiFolderPath)) {\n\t\treturn \"The unpackwiki command requires that the output wiki folder be empty\";\n\t}\n\t// Get the tiddlers from the source wiki\n\tvar tiddlerTitles = this.wiki.filterTiddlers(this.wikiFilter);\n\t// Initialise a new tiddlwiki.info file\n\tvar newWikiInfo = {};\n\t// Process each incoming tiddler in turn\n\t$tw.utils.each(tiddlerTitles,function(title) {\n\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\tif(tiddler) {\n\t\t\tif(self.tiddlersToIgnore.indexOf(title) !== -1) {\n\t\t\t\t// Ignore the core plugin and the ephemeral info plugin\n\t\t\t\tself.log(\"Ignoring tiddler: \" + title);\n\t\t\t} else {\n\t\t\t\tvar type = tiddler.fields.type,\n\t\t\t\t\tpluginType = tiddler.fields[\"plugin-type\"];\n\t\t\t\tif(type === \"application/json\" && pluginType) {\n\t\t\t\t\t// Plugin tiddler\n\t\t\t\t\tvar libraryDetails = self.findPluginInLibrary(title);\n\t\t\t\t\tif(libraryDetails) {\n\t\t\t\t\t\t// A plugin from the core library\n\t\t\t\t\t\tself.log(\"Adding built-in plugin: \" + libraryDetails.name);\n\t\t\t\t\t\tnewWikiInfo[libraryDetails.type] = newWikiInfo[libraryDetails.type]  || [];\n\t\t\t\t\t\t$tw.utils.pushTop(newWikiInfo[libraryDetails.type],libraryDetails.name);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// A custom plugin\n\t\t\t\t\t\tself.log(\"Processing custom plugin: \" + title);\n\t\t\t\t\t\tself.saveCustomPlugin(tiddler);\n\t\t\t\t\t}\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\t// Ordinary tiddler\n\t\t\t\t\tself.saveTiddler(\"tiddlers\",tiddler);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\t// Save the tiddlywiki.info file\n\tthis.saveJSONFile(\"tiddlywiki.info\",newWikiInfo);\n\tself.log(\"Writing tiddlywiki.info: \" + JSON.stringify(newWikiInfo,null,$tw.config.preferences.jsonSpaces));\n\treturn null;\n};\n\n/*\nTest whether the specified tiddler is a plugin in the plugin library\n*/\nWikiFolderMaker.prototype.findPluginInLibrary = function(title) {\n\tvar parts = title.split(\"/\"),\n\t\tpluginPath, type, name;\n\tif(parts[0] === \"$:\") {\n\t\tif(parts[1] === \"languages\" && parts.length === 3) {\n\t\t\tpluginPath = \"languages\" + path.sep + parts[2];\n\t\t\ttype = parts[1];\n\t\t\tname = parts[2];\n\t\t} else if(parts[1] === \"plugins\" || parts[1] === \"themes\" && parts.length === 4) {\n\t\t\tpluginPath = parts[1] + path.sep + parts[2] + path.sep + parts[3];\n\t\t\ttype = parts[1];\n\t\t\tname = parts[2] + \"/\" + parts[3];\n\t\t}\n\t}\n\tif(pluginPath && type && name) {\n\t\tpluginPath = path.resolve($tw.boot.bootPath,\"..\",pluginPath);\n\t\tif(fs.existsSync(pluginPath)) {\n\t\t\treturn {\n\t\t\t\tpluginPath: pluginPath,\n\t\t\t\ttype: type,\n\t\t\t\tname: name\n\t\t\t};\n\t\t}\n\t}\n\treturn false;\n};\n\nWikiFolderMaker.prototype.saveCustomPlugin = function(pluginTiddler) {\n\tvar self = this,\n\t\tpluginTitle = pluginTiddler.fields.title,\n\t\ttitleParts = pluginTitle.split(\"/\"),\n\t\tdirectory = $tw.utils.generateTiddlerFilepath(titleParts[titleParts.length - 1],{\n\t\t\tdirectory: path.resolve(this.wikiFolderPath,pluginTiddler.fields[\"plugin-type\"] + \"s\")\n\t\t}),\n\t\tpluginInfo = pluginTiddler.getFieldStrings({exclude: [\"text\",\"type\"]});\n\tthis.saveJSONFile(directory + path.sep + \"plugin.info\",pluginInfo);\n\tself.log(\"Writing \" + directory + path.sep + \"plugin.info: \" + JSON.stringify(pluginInfo,null,$tw.config.preferences.jsonSpaces));\n\tvar pluginTiddlers = JSON.parse(pluginTiddler.fields.text).tiddlers; // A hashmap of tiddlers in the plugin\n\t$tw.utils.each(pluginTiddlers,function(tiddler) {\n\t\tself.saveTiddler(directory,new $tw.Tiddler(tiddler));\n\t});\n};\n\nWikiFolderMaker.prototype.saveTiddler = function(directory,tiddler) {\n\tvar fileInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{\n\t\tdirectory: path.resolve(this.wikiFolderPath,directory),\n\t\twiki: this.wiki\n\t});\n\t$tw.utils.saveTiddlerToFileSync(tiddler,fileInfo);\n};\n\nWikiFolderMaker.prototype.saveJSONFile = function(filename,json) {\n\tthis.saveTextFile(filename,JSON.stringify(json,null,$tw.config.preferences.jsonSpaces));\n};\n\nWikiFolderMaker.prototype.saveTextFile = function(filename,data) {\n\tthis.saveFile(filename,\"utf8\",data);\n};\n\nWikiFolderMaker.prototype.saveFile = function(filename,encoding,data) {\n\tvar filepath = path.resolve(this.wikiFolderPath,filename);\n\t$tw.utils.createFileDirectories(filepath);\n\tfs.writeFileSync(filepath,data,encoding);\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/server.js": {
            "title": "$:/core/modules/commands/server.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/server.js\ntype: application/javascript\nmodule-type: command\n\nDeprecated legacy command for serving tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Server = require(\"$:/core/modules/server/server.js\").Server;\n\nexports.info = {\n\tname: \"server\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tvar self = this;\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(!$tw.boot.wikiTiddlersPath) {\n\t\t$tw.utils.warning(\"Warning: Wiki folder '\" + $tw.boot.wikiPath + \"' does not exist or is missing a tiddlywiki.info file\");\n\t}\n\t// Set up server\n\tthis.server = new Server({\n\t\twiki: this.commander.wiki,\n\t\tvariables: {\n\t\t\tport: this.params[0],\n\t\t\thost: this.params[6],\n\t\t\t\"root-tiddler\": this.params[1],\n\t\t\t\"root-render-type\": this.params[2],\n\t\t\t\"root-serve-type\": this.params[3],\n\t\t\tusername: this.params[4],\n\t\t\tpassword: this.params[5],\n\t\t\t\"path-prefix\": this.params[7],\n\t\t\t\"debug-level\": this.params[8]\n\t\t}\n\t});\n\tvar nodeServer = this.server.listen();\n\t$tw.hooks.invokeHook(\"th-server-command-post-start\",this.server,nodeServer,\"tiddlywiki\");\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/setfield.js": {
            "title": "$:/core/modules/commands/setfield.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/setfield.js\ntype: application/javascript\nmodule-type: command\n\nCommand to modify selected tiddlers to set a field to the text of a template tiddler that has been wikified with the selected tiddler as the current tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.info = {\n\tname: \"setfield\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 4) {\n\t\treturn \"Missing parameters\";\n\t}\n\tvar self = this,\n\t\twiki = this.commander.wiki,\n\t\tfilter = this.params[0],\n\t\tfieldname = this.params[1] || \"text\",\n\t\ttemplatetitle = this.params[2],\n\t\trendertype = this.params[3] || \"text/plain\",\n\t\ttiddlers = wiki.filterTiddlers(filter);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar parser = wiki.parseTiddler(templatetitle),\n\t\t\tnewFields = {},\n\t\t\ttiddler = wiki.getTiddler(title);\n\t\tif(parser) {\n\t\t\tvar widgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}});\n\t\t\tvar container = $tw.fakeDocument.createElement(\"div\");\n\t\t\twidgetNode.render(container,null);\n\t\t\tnewFields[fieldname] = rendertype === \"text/html\" ? container.innerHTML : container.textContent;\n\t\t} else {\n\t\t\tnewFields[fieldname] = undefined;\n\t\t}\n\t\twiki.addTiddler(new $tw.Tiddler(tiddler,newFields));\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/unpackplugin.js": {
            "title": "$:/core/modules/commands/unpackplugin.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/unpackplugin.js\ntype: application/javascript\nmodule-type: command\n\nCommand to extract the shadow tiddlers from within a plugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"unpackplugin\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing plugin name\";\n\t}\n\tvar self = this,\n\t\ttitle = this.params[0],\n\t\tpluginData = this.commander.wiki.getTiddlerDataCached(title);\n\tif(!pluginData) {\n\t\treturn \"Plugin '\" + title + \"' not found\";\n\t}\n\t$tw.utils.each(pluginData.tiddlers,function(tiddler) {\n\t\tself.commander.wiki.addTiddler(new $tw.Tiddler(tiddler));\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/verbose.js": {
            "title": "$:/core/modules/commands/verbose.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/verbose.js\ntype: application/javascript\nmodule-type: command\n\nVerbose command\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"verbose\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tthis.commander.verbose = true;\n\t// Output the boot message log\n\tthis.commander.streams.output.write(\"Boot log:\\n  \" + $tw.boot.logMessages.join(\"\\n  \") + \"\\n\");\n\treturn null; // No error\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/commands/version.js": {
            "title": "$:/core/modules/commands/version.js",
            "text": "/*\\\ntitle: $:/core/modules/commands/version.js\ntype: application/javascript\nmodule-type: command\n\nVersion command\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"version\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tthis.commander.streams.output.write($tw.version + \"\\n\");\n\treturn null; // No error\n};\n\nexports.Command = Command;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "command"
        },
        "$:/core/modules/config.js": {
            "title": "$:/core/modules/config.js",
            "text": "/*\\\ntitle: $:/core/modules/config.js\ntype: application/javascript\nmodule-type: config\n\nCore configuration constants\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.preferences = {};\n\nexports.preferences.notificationDuration = 3 * 1000;\nexports.preferences.jsonSpaces = 4;\n\nexports.textPrimitives = {\n\tupperLetter: \"[A-Z\\u00c0-\\u00d6\\u00d8-\\u00de\\u0150\\u0170]\",\n\tlowerLetter: \"[a-z\\u00df-\\u00f6\\u00f8-\\u00ff\\u0151\\u0171]\",\n\tanyLetter:   \"[A-Za-z0-9\\u00c0-\\u00d6\\u00d8-\\u00de\\u00df-\\u00f6\\u00f8-\\u00ff\\u0150\\u0170\\u0151\\u0171]\",\n\tblockPrefixLetters:\t\"[A-Za-z0-9-_\\u00c0-\\u00d6\\u00d8-\\u00de\\u00df-\\u00f6\\u00f8-\\u00ff\\u0150\\u0170\\u0151\\u0171]\"\n};\n\nexports.textPrimitives.unWikiLink = \"~\";\nexports.textPrimitives.wikiLink = exports.textPrimitives.upperLetter + \"+\" +\n\texports.textPrimitives.lowerLetter + \"+\" +\n\texports.textPrimitives.upperLetter +\n\texports.textPrimitives.anyLetter + \"*\";\n\nexports.htmlEntities = {quot:34, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 };\n\nexports.htmlVoidElements = \"area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr\".split(\",\");\n\nexports.htmlBlockElements = \"address,article,aside,audio,blockquote,canvas,dd,div,dl,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,li,noscript,ol,output,p,pre,section,table,tfoot,ul,video\".split(\",\");\n\nexports.htmlUnsafeElements = \"script\".split(\",\");\n\n})();\n",
            "type": "application/javascript",
            "module-type": "config"
        },
        "$:/core/modules/deserializers.js": {
            "title": "$:/core/modules/deserializers.js",
            "text": "/*\\\ntitle: $:/core/modules/deserializers.js\ntype: application/javascript\nmodule-type: tiddlerdeserializer\n\nFunctions to deserialise tiddlers from a block of text\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nUtility function to parse an old-style tiddler DIV in a *.tid file. It looks like this:\n\n<div title=\"Title\" creator=\"JoeBloggs\" modifier=\"JoeBloggs\" created=\"201102111106\" modified=\"201102111310\" tags=\"myTag [[my long tag]]\">\n<pre>The text of the tiddler (without the expected HTML encoding).\n</pre>\n</div>\n\nNote that the field attributes are HTML encoded, but that the body of the <PRE> tag is not encoded.\n\nWhen these tiddler DIVs are encountered within a TiddlyWiki HTML file then the body is encoded in the usual way.\n*/\nvar parseTiddlerDiv = function(text /* [,fields] */) {\n\t// Slot together the default results\n\tvar result = {};\n\tif(arguments.length > 1) {\n\t\tfor(var f=1; f<arguments.length; f++) {\n\t\t\tvar fields = arguments[f];\n\t\t\tfor(var t in fields) {\n\t\t\t\tresult[t] = fields[t];\t\t\n\t\t\t}\n\t\t}\n\t}\n\t// Parse the DIV body\n\tvar startRegExp = /^\\s*<div\\s+([^>]*)>(\\s*<pre>)?/gi,\n\t\tendRegExp,\n\t\tmatch = startRegExp.exec(text);\n\tif(match) {\n\t\t// Old-style DIVs don't have the <pre> tag\n\t\tif(match[2]) {\n\t\t\tendRegExp = /<\\/pre>\\s*<\\/div>\\s*$/gi;\n\t\t} else {\n\t\t\tendRegExp = /<\\/div>\\s*$/gi;\n\t\t}\n\t\tvar endMatch = endRegExp.exec(text);\n\t\tif(endMatch) {\n\t\t\t// Extract the text\n\t\t\tresult.text = text.substring(match.index + match[0].length,endMatch.index);\n\t\t\t// Process the attributes\n\t\t\tvar attrRegExp = /\\s*([^=\\s]+)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)')/gi,\n\t\t\t\tattrMatch;\n\t\t\tdo {\n\t\t\t\tattrMatch = attrRegExp.exec(match[1]);\n\t\t\t\tif(attrMatch) {\n\t\t\t\t\tvar name = attrMatch[1];\n\t\t\t\t\tvar value = attrMatch[2] !== undefined ? attrMatch[2] : attrMatch[3];\n\t\t\t\t\tresult[name] = value;\n\t\t\t\t}\n\t\t\t} while(attrMatch);\n\t\t\treturn result;\n\t\t}\n\t}\n\treturn undefined;\n};\n\nexports[\"application/x-tiddler-html-div\"] = function(text,fields) {\n\treturn [parseTiddlerDiv(text,fields)];\n};\n\nexports[\"application/json\"] = function(text,fields) {\n\tvar incoming,\n\t\tresults = [];\n\ttry {\n\t\tincoming = JSON.parse(text);\n\t} catch(e) {\n\t\tincoming = [{\n\t\t\ttitle: \"JSON error: \" + e,\n\t\t\ttext: \"\"\n\t\t}]\n\t}\n\tif(!$tw.utils.isArray(incoming)) {\n\t\tincoming = [incoming];\n\t}\n\tfor(var t=0; t<incoming.length; t++) {\n\t\tvar incomingFields = incoming[t],\n\t\t\tfields = {};\n\t\tfor(var f in incomingFields) {\n\t\t\tif(typeof incomingFields[f] === \"string\") {\n\t\t\t\tfields[f] = incomingFields[f];\n\t\t\t}\n\t\t}\n\t\tresults.push(fields);\n\t}\n\treturn results;\n};\n\n/*\nParse an HTML file into tiddlers. There are three possibilities:\n# A TiddlyWiki classic HTML file containing `text/x-tiddlywiki` tiddlers\n# A TiddlyWiki5 HTML file containing `text/vnd.tiddlywiki` tiddlers\n# An ordinary HTML file\n*/\nexports[\"text/html\"] = function(text,fields) {\n\t// Check if we've got a store area\n\tvar storeAreaMarkerRegExp = /<div id=[\"']?storeArea['\"]?( style=[\"']?display:none;[\"']?)?>/gi,\n\t\tmatch = storeAreaMarkerRegExp.exec(text);\n\tif(match) {\n\t\t// If so, it's either a classic TiddlyWiki file or an unencrypted TW5 file\n\t\t// First read the normal tiddlers\n\t\tvar results = deserializeTiddlyWikiFile(text,storeAreaMarkerRegExp.lastIndex,!!match[1],fields);\n\t\t// Then any system tiddlers\n\t\tvar systemAreaMarkerRegExp = /<div id=[\"']?systemArea['\"]?( style=[\"']?display:none;[\"']?)?>/gi,\n\t\t\tsysMatch = systemAreaMarkerRegExp.exec(text);\n\t\tif(sysMatch) {\n\t\t\tresults.push.apply(results,deserializeTiddlyWikiFile(text,systemAreaMarkerRegExp.lastIndex,!!sysMatch[1],fields));\n\t\t}\n\t\treturn results;\n\t} else {\n\t\t// Check whether we've got an encrypted file\n\t\tvar encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);\n\t\tif(encryptedStoreArea) {\n\t\t\t// If so, attempt to decrypt it using the current password\n\t\t\treturn $tw.utils.decryptStoreArea(encryptedStoreArea);\n\t\t} else {\n\t\t\t// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler\n\t\t\treturn deserializeHtmlFile(text,fields);\n\t\t}\n\t}\n};\n\nfunction deserializeHtmlFile(text,fields) {\n\tvar result = {};\n\t$tw.utils.each(fields,function(value,name) {\n\t\tresult[name] = value;\n\t});\n\tresult.text = text;\n\tresult.type = \"text/html\";\n\treturn [result];\n}\n\nfunction deserializeTiddlyWikiFile(text,storeAreaEnd,isTiddlyWiki5,fields) {\n\tvar results = [],\n\t\tendOfDivRegExp = /(<\\/div>\\s*)/gi,\n\t\tstartPos = storeAreaEnd,\n\t\tdefaultType = isTiddlyWiki5 ? undefined : \"text/x-tiddlywiki\";\n\tendOfDivRegExp.lastIndex = startPos;\n\tvar match = endOfDivRegExp.exec(text);\n\twhile(match) {\n\t\tvar endPos = endOfDivRegExp.lastIndex,\n\t\t\ttiddlerFields = parseTiddlerDiv(text.substring(startPos,endPos),fields,{type: defaultType});\n\t\tif(!tiddlerFields) {\n\t\t\tbreak;\n\t\t}\n\t\t$tw.utils.each(tiddlerFields,function(value,name) {\n\t\t\tif(typeof value === \"string\") {\n\t\t\t\ttiddlerFields[name] = $tw.utils.htmlDecode(value);\n\t\t\t}\n\t\t});\n\t\tif(tiddlerFields.text !== null) {\n\t\t\tresults.push(tiddlerFields);\n\t\t}\n\t\tstartPos = endPos;\n\t\tmatch = endOfDivRegExp.exec(text);\n\t}\n\treturn results;\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "tiddlerdeserializer"
        },
        "$:/core/modules/editor/engines/framed.js": {
            "title": "$:/core/modules/editor/engines/framed.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/engines/framed.js\ntype: application/javascript\nmodule-type: library\n\nText editor engine based on a simple input or textarea within an iframe. This is done so that the selection is preserved even when clicking away from the textarea\n\n\\*/\n(function(){\n\n/*jslint node: true,browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar HEIGHT_VALUE_TITLE = \"$:/config/TextEditor/EditorHeight/Height\";\n\nfunction FramedEngine(options) {\n\t// Save our options\n\toptions = options || {};\n\tthis.widget = options.widget;\n\tthis.value = options.value;\n\tthis.parentNode = options.parentNode;\n\tthis.nextSibling = options.nextSibling;\n\t// Create our hidden dummy text area for reading styles\n\tthis.dummyTextArea = this.widget.document.createElement(\"textarea\");\n\tif(this.widget.editClass) {\n\t\tthis.dummyTextArea.className = this.widget.editClass;\n\t}\n\tthis.dummyTextArea.setAttribute(\"hidden\",\"true\");\n\tthis.parentNode.insertBefore(this.dummyTextArea,this.nextSibling);\n\tthis.widget.domNodes.push(this.dummyTextArea);\n\t// Create the iframe\n\tthis.iframeNode = this.widget.document.createElement(\"iframe\");\n\tthis.parentNode.insertBefore(this.iframeNode,this.nextSibling);\n\tthis.iframeDoc = this.iframeNode.contentWindow.document;\n\t// (Firefox requires us to put some empty content in the iframe)\n\tthis.iframeDoc.open();\n\tthis.iframeDoc.write(\"\");\n\tthis.iframeDoc.close();\n\t// Style the iframe\n\tthis.iframeNode.className = this.dummyTextArea.className;\n\tthis.iframeNode.style.border = \"none\";\n\tthis.iframeNode.style.padding = \"0\";\n\tthis.iframeNode.style.resize = \"none\";\n\tthis.iframeNode.style[\"background-color\"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText(\"$:/palette\"),\"tiddler-editor-background\");\n\tthis.iframeDoc.body.style.margin = \"0\";\n\tthis.iframeDoc.body.style.padding = \"0\";\n\tthis.widget.domNodes.push(this.iframeNode);\n\t// Construct the textarea or input node\n\tvar tag = this.widget.editTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"input\";\n\t}\n\tthis.domNode = this.iframeDoc.createElement(tag);\n\t// Set the text\n\tif(this.widget.editTag === \"textarea\") {\n\t\tthis.domNode.appendChild(this.iframeDoc.createTextNode(this.value));\n\t} else {\n\t\tthis.domNode.value = this.value;\n\t}\n\t// Set the attributes\n\tif(this.widget.editType) {\n\t\tthis.domNode.setAttribute(\"type\",this.widget.editType);\n\t}\n\tif(this.widget.editPlaceholder) {\n\t\tthis.domNode.setAttribute(\"placeholder\",this.widget.editPlaceholder);\n\t}\n\tif(this.widget.editSize) {\n\t\tthis.domNode.setAttribute(\"size\",this.widget.editSize);\n\t}\n\tif(this.widget.editRows) {\n\t\tthis.domNode.setAttribute(\"rows\",this.widget.editRows);\n\t}\n\tif(this.widget.editTabIndex) {\n\t\tthis.iframeNode.setAttribute(\"tabindex\",this.widget.editTabIndex);\n\t}\n\t// Copy the styles from the dummy textarea\n\tthis.copyStyles();\n\t// Add event listeners\n\t$tw.utils.addEventListeners(this.domNode,[\n\t\t{name: \"click\",handlerObject: this,handlerMethod: \"handleClickEvent\"},\n\t\t{name: \"input\",handlerObject: this,handlerMethod: \"handleInputEvent\"},\n\t\t{name: \"keydown\",handlerObject: this.widget,handlerMethod: \"handleKeydownEvent\"}\n\t]);\n\t// Insert the element into the DOM\n\tthis.iframeDoc.body.appendChild(this.domNode);\n}\n\n/*\nCopy styles from the dummy text area to the textarea in the iframe\n*/\nFramedEngine.prototype.copyStyles = function() {\n\t// Copy all styles\n\t$tw.utils.copyStyles(this.dummyTextArea,this.domNode);\n\t// Override the ones that should not be set the same as the dummy textarea\n\tthis.domNode.style.display = \"block\";\n\tthis.domNode.style.width = \"100%\";\n\tthis.domNode.style.margin = \"0\";\n\tthis.domNode.style[\"background-color\"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText(\"$:/palette\"),\"tiddler-editor-background\");\n\t// In Chrome setting -webkit-text-fill-color overrides the placeholder text colour\n\tthis.domNode.style[\"-webkit-text-fill-color\"] = \"currentcolor\";\n};\n\n/*\nSet the text of the engine if it doesn't currently have focus\n*/\nFramedEngine.prototype.setText = function(text,type) {\n\tif(!this.domNode.isTiddlyWikiFakeDom) {\n\t\tif(this.domNode.ownerDocument.activeElement !== this.domNode) {\n\t\t\tthis.domNode.value = text;\n\t\t}\n\t\t// Fix the height if needed\n\t\tthis.fixHeight();\n\t}\n};\n\n/*\nGet the text of the engine\n*/\nFramedEngine.prototype.getText = function() {\n\treturn this.domNode.value;\n};\n\n/*\nFix the height of textarea to fit content\n*/\nFramedEngine.prototype.fixHeight = function() {\n\t// Make sure styles are updated\n\tthis.copyStyles();\n\t// Adjust height\n\tif(this.widget.editTag === \"textarea\") {\n\t\tif(this.widget.editAutoHeight) {\n\t\t\tif(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {\n\t\t\t\tvar newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);\n\t\t\t\tthis.iframeNode.style.height = (newHeight + 14) + \"px\"; // +14 for the border on the textarea\n\t\t\t}\n\t\t} else {\n\t\t\tvar fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,\"400px\"),10);\n\t\t\tfixedHeight = Math.max(fixedHeight,20);\n\t\t\tthis.domNode.style.height = fixedHeight + \"px\";\n\t\t\tthis.iframeNode.style.height = (fixedHeight + 14) + \"px\";\n\t\t}\n\t}\n};\n\n/*\nFocus the engine node\n*/\nFramedEngine.prototype.focus  = function() {\n\tif(this.domNode.focus && this.domNode.select) {\n\t\tthis.domNode.focus();\n\t\tthis.domNode.select();\n\t}\n};\n\n/*\nHandle a click\n*/\nFramedEngine.prototype.handleClickEvent = function(event) {\n\tthis.fixHeight();\n\treturn true;\n};\n\n/*\nHandle a dom \"input\" event which occurs when the text has changed\n*/\nFramedEngine.prototype.handleInputEvent = function(event) {\n\tthis.widget.saveChanges(this.getText());\n\tthis.fixHeight();\n\treturn true;\n};\n\n/*\nCreate a blank structure representing a text operation\n*/\nFramedEngine.prototype.createTextOperation = function() {\n\tvar operation = {\n\t\ttext: this.domNode.value,\n\t\tselStart: this.domNode.selectionStart,\n\t\tselEnd: this.domNode.selectionEnd,\n\t\tcutStart: null,\n\t\tcutEnd: null,\n\t\treplacement: null,\n\t\tnewSelStart: null,\n\t\tnewSelEnd: null\n\t};\n\toperation.selection = operation.text.substring(operation.selStart,operation.selEnd);\n\treturn operation;\n};\n\n/*\nExecute a text operation\n*/\nFramedEngine.prototype.executeTextOperation = function(operation) {\n\t// Perform the required changes to the text area and the underlying tiddler\n\tvar newText = operation.text;\n\tif(operation.replacement !== null) {\n\t\tnewText = operation.text.substring(0,operation.cutStart) + operation.replacement + operation.text.substring(operation.cutEnd);\n\t\t// Attempt to use a execCommand to modify the value of the control\n\t\tif(this.iframeDoc.queryCommandSupported(\"insertText\") && this.iframeDoc.queryCommandSupported(\"delete\") && !$tw.browser.isFirefox) {\n\t\t\tthis.domNode.focus();\n\t\t\tthis.domNode.setSelectionRange(operation.cutStart,operation.cutEnd);\n\t\t\tif(operation.replacement === \"\") {\n\t\t\t\tthis.iframeDoc.execCommand(\"delete\",false,\"\");\n\t\t\t} else {\n\t\t\t\tthis.iframeDoc.execCommand(\"insertText\",false,operation.replacement);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.domNode.value = newText;\n\t\t}\n\t\tthis.domNode.focus();\n\t\tthis.domNode.setSelectionRange(operation.newSelStart,operation.newSelEnd);\n\t}\n\tthis.domNode.focus();\n\treturn newText;\n};\n\nexports.FramedEngine = FramedEngine;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "library"
        },
        "$:/core/modules/editor/engines/simple.js": {
            "title": "$:/core/modules/editor/engines/simple.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/engines/simple.js\ntype: application/javascript\nmodule-type: library\n\nText editor engine based on a simple input or textarea tag\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar HEIGHT_VALUE_TITLE = \"$:/config/TextEditor/EditorHeight/Height\";\n\nfunction SimpleEngine(options) {\n\t// Save our options\n\toptions = options || {};\n\tthis.widget = options.widget;\n\tthis.value = options.value;\n\tthis.parentNode = options.parentNode;\n\tthis.nextSibling = options.nextSibling;\n\t// Construct the textarea or input node\n\tvar tag = this.widget.editTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"input\";\n\t}\n\tthis.domNode = this.widget.document.createElement(tag);\n\t// Set the text\n\tif(this.widget.editTag === \"textarea\") {\n\t\tthis.domNode.appendChild(this.widget.document.createTextNode(this.value));\n\t} else {\n\t\tthis.domNode.value = this.value;\n\t}\n\t// Set the attributes\n\tif(this.widget.editType) {\n\t\tthis.domNode.setAttribute(\"type\",this.widget.editType);\n\t}\n\tif(this.widget.editPlaceholder) {\n\t\tthis.domNode.setAttribute(\"placeholder\",this.widget.editPlaceholder);\n\t}\n\tif(this.widget.editSize) {\n\t\tthis.domNode.setAttribute(\"size\",this.widget.editSize);\n\t}\n\tif(this.widget.editRows) {\n\t\tthis.domNode.setAttribute(\"rows\",this.widget.editRows);\n\t}\n\tif(this.widget.editClass) {\n\t\tthis.domNode.className = this.widget.editClass;\n\t}\n\tif(this.widget.editTabIndex) {\n\t\tthis.domNode.setAttribute(\"tabindex\",this.widget.editTabIndex);\n\t}\n\t// Add an input event handler\n\t$tw.utils.addEventListeners(this.domNode,[\n\t\t{name: \"focus\", handlerObject: this, handlerMethod: \"handleFocusEvent\"},\n\t\t{name: \"input\", handlerObject: this, handlerMethod: \"handleInputEvent\"}\n\t]);\n\t// Insert the element into the DOM\n\tthis.parentNode.insertBefore(this.domNode,this.nextSibling);\n\tthis.widget.domNodes.push(this.domNode);\n}\n\n/*\nSet the text of the engine if it doesn't currently have focus\n*/\nSimpleEngine.prototype.setText = function(text,type) {\n\tif(!this.domNode.isTiddlyWikiFakeDom) {\n\t\tif(this.domNode.ownerDocument.activeElement !== this.domNode || text === \"\") {\n\t\t\tthis.domNode.value = text;\n\t\t}\n\t\t// Fix the height if needed\n\t\tthis.fixHeight();\n\t}\n};\n\n/*\nGet the text of the engine\n*/\nSimpleEngine.prototype.getText = function() {\n\treturn this.domNode.value;\n};\n\n/*\nFix the height of textarea to fit content\n*/\nSimpleEngine.prototype.fixHeight = function() {\n\tif(this.widget.editTag === \"textarea\") {\n\t\tif(this.widget.editAutoHeight) {\n\t\t\tif(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {\n\t\t\t\t$tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);\n\t\t\t}\n\t\t} else {\n\t\t\tvar fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,\"400px\"),10);\n\t\t\tfixedHeight = Math.max(fixedHeight,20);\n\t\t\tthis.domNode.style.height = fixedHeight + \"px\";\n\t\t}\n\t}\n};\n\n/*\nFocus the engine node\n*/\nSimpleEngine.prototype.focus  = function() {\n\tif(this.domNode.focus && this.domNode.select) {\n\t\tthis.domNode.focus();\n\t\tthis.domNode.select();\n\t}\n};\n\n/*\nHandle a dom \"input\" event which occurs when the text has changed\n*/\nSimpleEngine.prototype.handleInputEvent = function(event) {\n\tthis.widget.saveChanges(this.getText());\n\tthis.fixHeight();\n\treturn true;\n};\n\n/*\nHandle a dom \"focus\" event\n*/\nSimpleEngine.prototype.handleFocusEvent = function(event) {\n\tif(this.widget.editFocusPopup) {\n\t\t$tw.popup.triggerPopup({\n\t\t\tdomNode: this.domNode,\n\t\t\ttitle: this.widget.editFocusPopup,\n\t\t\twiki: this.widget.wiki,\n\t\t\tforce: true\n\t\t});\n\t}\n\treturn true;\n};\n\n/*\nCreate a blank structure representing a text operation\n*/\nSimpleEngine.prototype.createTextOperation = function() {\n\treturn null;\n};\n\n/*\nExecute a text operation\n*/\nSimpleEngine.prototype.executeTextOperation = function(operation) {\n};\n\nexports.SimpleEngine = SimpleEngine;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "library"
        },
        "$:/core/modules/editor/factory.js": {
            "title": "$:/core/modules/editor/factory.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/factory.js\ntype: application/javascript\nmodule-type: library\n\nFactory for constructing text editor widgets with specified engines for the toolbar and non-toolbar cases\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar DEFAULT_MIN_TEXT_AREA_HEIGHT = \"100px\"; // Minimum height of textareas in pixels\n\n// Configuration tiddlers\nvar HEIGHT_MODE_TITLE = \"$:/config/TextEditor/EditorHeight/Mode\";\nvar ENABLE_TOOLBAR_TITLE = \"$:/config/TextEditor/EnableToolbar\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nfunction editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {\n\n\tvar EditTextWidget = function(parseTreeNode,options) {\n\t\t// Initialise the editor operations if they've not been done already\n\t\tif(!this.editorOperations) {\n\t\t\tEditTextWidget.prototype.editorOperations = {};\n\t\t\t$tw.modules.applyMethods(\"texteditoroperation\",this.editorOperations);\n\t\t}\n\t\tthis.initialise(parseTreeNode,options);\n\t};\n\n\t/*\n\tInherit from the base widget class\n\t*/\n\tEditTextWidget.prototype = new Widget();\n\n\t/*\n\tRender this widget into the DOM\n\t*/\n\tEditTextWidget.prototype.render = function(parent,nextSibling) {\n\t\t// Save the parent dom node\n\t\tthis.parentDomNode = parent;\n\t\t// Compute our attributes\n\t\tthis.computeAttributes();\n\t\t// Execute our logic\n\t\tthis.execute();\n\t\t// Create the wrapper for the toolbar and render its content\n\t\tif(this.editShowToolbar) {\n\t\t\tthis.toolbarNode = this.document.createElement(\"div\");\n\t\t\tthis.toolbarNode.className = \"tc-editor-toolbar\";\n\t\t\tparent.insertBefore(this.toolbarNode,nextSibling);\n\t\t\tthis.renderChildren(this.toolbarNode,null);\n\t\t\tthis.domNodes.push(this.toolbarNode);\n\t\t}\n\t\t// Create our element\n\t\tvar editInfo = this.getEditInfo(),\n\t\t\tEngine = this.editShowToolbar ? toolbarEngine : nonToolbarEngine;\n\t\tthis.engine = new Engine({\n\t\t\t\twidget: this,\n\t\t\t\tvalue: editInfo.value,\n\t\t\t\ttype: editInfo.type,\n\t\t\t\tparentNode: parent,\n\t\t\t\tnextSibling: nextSibling\n\t\t\t});\n\t\t// Call the postRender hook\n\t\tif(this.postRender) {\n\t\t\tthis.postRender();\n\t\t}\n\t\t// Fix height\n\t\tthis.engine.fixHeight();\n\t\t// Focus if required\n\t\tif(this.editFocus === \"true\" || this.editFocus === \"yes\") {\n\t\t\tthis.engine.focus();\n\t\t}\n\t\t// Add widget message listeners\n\t\tthis.addEventListeners([\n\t\t\t{type: \"tm-edit-text-operation\", handler: \"handleEditTextOperationMessage\"}\n\t\t]);\n\t};\n\n\t/*\n\tGet the tiddler being edited and current value\n\t*/\n\tEditTextWidget.prototype.getEditInfo = function() {\n\t\t// Get the edit value\n\t\tvar self = this,\n\t\t\tvalue,\n\t\t\ttype = \"text/plain\",\n\t\t\tupdate;\n\t\tif(this.editIndex) {\n\t\t\tvalue = this.wiki.extractTiddlerDataItem(this.editTitle,this.editIndex,this.editDefault);\n\t\t\tupdate = function(value) {\n\t\t\t\tvar data = self.wiki.getTiddlerData(self.editTitle,{});\n\t\t\t\tif(data[self.editIndex] !== value) {\n\t\t\t\t\tdata[self.editIndex] = value;\n\t\t\t\t\tself.wiki.setTiddlerData(self.editTitle,data);\n\t\t\t\t}\n\t\t\t};\n\t\t} else {\n\t\t\t// Get the current tiddler and the field name\n\t\t\tvar tiddler = this.wiki.getTiddler(this.editTitle);\n\t\t\tif(tiddler) {\n\t\t\t\t// If we've got a tiddler, the value to display is the field string value\n\t\t\t\tvalue = tiddler.getFieldString(this.editField);\n\t\t\t\tif(this.editField === \"text\") {\n\t\t\t\t\ttype = tiddler.fields.type || \"text/vnd.tiddlywiki\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Otherwise, we need to construct a default value for the editor\n\t\t\t\tswitch(this.editField) {\n\t\t\t\t\tcase \"text\":\n\t\t\t\t\t\tvalue = \"Type the text for the tiddler '\" + this.editTitle + \"'\";\n\t\t\t\t\t\ttype = \"text/vnd.tiddlywiki\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"title\":\n\t\t\t\t\t\tvalue = this.editTitle;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tvalue = \"\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif(this.editDefault !== undefined) {\n\t\t\t\t\tvalue = this.editDefault;\n\t\t\t\t}\n\t\t\t}\n\t\t\tupdate = function(value) {\n\t\t\t\tvar tiddler = self.wiki.getTiddler(self.editTitle),\n\t\t\t\t\tupdateFields = {\n\t\t\t\t\t\ttitle: self.editTitle\n\t\t\t\t\t};\n\t\t\t\tupdateFields[self.editField] = value;\n\t\t\t\tself.wiki.addTiddler(new $tw.Tiddler(self.wiki.getCreationFields(),tiddler,updateFields,self.wiki.getModificationFields()));\n\t\t\t};\n\t\t}\n\t\tif(this.editType) {\n\t\t\ttype = this.editType;\n\t\t}\n\t\treturn {value: value || \"\", type: type, update: update};\n\t};\n\n\t/*\n\tHandle an edit text operation message from the toolbar\n\t*/\n\tEditTextWidget.prototype.handleEditTextOperationMessage = function(event) {\n\t\t// Prepare information about the operation\n\t\tvar operation = this.engine.createTextOperation();\n\t\t// Invoke the handler for the selected operation\n\t\tvar handler = this.editorOperations[event.param];\n\t\tif(handler) {\n\t\t\thandler.call(this,event,operation);\n\t\t}\n\t\t// Execute the operation via the engine\n\t\tvar newText = this.engine.executeTextOperation(operation);\n\t\t// Fix the tiddler height and save changes\n\t\tthis.engine.fixHeight();\n\t\tthis.saveChanges(newText);\n\t};\n\n\t/*\n\tCompute the internal state of the widget\n\t*/\n\tEditTextWidget.prototype.execute = function() {\n\t\t// Get our parameters\n\t\tthis.editTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t\tthis.editField = this.getAttribute(\"field\",\"text\");\n\t\tthis.editIndex = this.getAttribute(\"index\");\n\t\tthis.editDefault = this.getAttribute(\"default\");\n\t\tthis.editClass = this.getAttribute(\"class\");\n\t\tthis.editPlaceholder = this.getAttribute(\"placeholder\");\n\t\tthis.editSize = this.getAttribute(\"size\");\n\t\tthis.editRows = this.getAttribute(\"rows\");\n\t\tthis.editAutoHeight = this.wiki.getTiddlerText(HEIGHT_MODE_TITLE,\"auto\");\n\t\tthis.editAutoHeight = this.getAttribute(\"autoHeight\",this.editAutoHeight === \"auto\" ? \"yes\" : \"no\") === \"yes\";\n\t\tthis.editMinHeight = this.getAttribute(\"minHeight\",DEFAULT_MIN_TEXT_AREA_HEIGHT);\n\t\tthis.editFocusPopup = this.getAttribute(\"focusPopup\");\n\t\tthis.editFocus = this.getAttribute(\"focus\");\n\t\tthis.editTabIndex = this.getAttribute(\"tabindex\");\n\t\t// Get the default editor element tag and type\n\t\tvar tag,type;\n\t\tif(this.editField === \"text\") {\n\t\t\ttag = \"textarea\";\n\t\t} else {\n\t\t\ttag = \"input\";\n\t\t\tvar fieldModule = $tw.Tiddler.fieldModules[this.editField];\n\t\t\tif(fieldModule && fieldModule.editTag) {\n\t\t\t\ttag = fieldModule.editTag;\n\t\t\t}\n\t\t\tif(fieldModule && fieldModule.editType) {\n\t\t\t\ttype = fieldModule.editType;\n\t\t\t}\n\t\t\ttype = type || \"text\";\n\t\t}\n\t\t// Get the rest of our parameters\n\t\tthis.editTag = this.getAttribute(\"tag\",tag) || \"input\";\n\t\tthis.editType = this.getAttribute(\"type\",type);\n\t\t// Make the child widgets\n\t\tthis.makeChildWidgets();\n\t\t// Determine whether to show the toolbar\n\t\tthis.editShowToolbar = this.wiki.getTiddlerText(ENABLE_TOOLBAR_TITLE,\"yes\");\n\t\tthis.editShowToolbar = (this.editShowToolbar === \"yes\") && !!(this.children && this.children.length > 0) && (!this.document.isTiddlyWikiFakeDom);\n\t};\n\n\t/*\n\tSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n\t*/\n\tEditTextWidget.prototype.refresh = function(changedTiddlers) {\n\t\tvar changedAttributes = this.computeAttributes();\n\t\t// Completely rerender if any of our attributes have changed\n\t\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes[\"default\"] || changedAttributes[\"class\"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup ||  changedAttributes.rows || changedAttributes.tabindex || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE]) {\n\t\t\tthis.refreshSelf();\n\t\t\treturn true;\n\t\t} else if(changedTiddlers[this.editTitle]) {\n\t\t\tvar editInfo = this.getEditInfo();\n\t\t\tthis.updateEditor(editInfo.value,editInfo.type);\n\t\t}\n\t\tthis.engine.fixHeight();\n\t\tif(this.editShowToolbar) {\n\t\t\treturn this.refreshChildren(changedTiddlers);\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/*\n\tUpdate the editor with new text. This method is separate from updateEditorDomNode()\n\tso that subclasses can override updateEditor() and still use updateEditorDomNode()\n\t*/\n\tEditTextWidget.prototype.updateEditor = function(text,type) {\n\t\tthis.updateEditorDomNode(text,type);\n\t};\n\n\t/*\n\tUpdate the editor dom node with new text\n\t*/\n\tEditTextWidget.prototype.updateEditorDomNode = function(text,type) {\n\t\tthis.engine.setText(text,type);\n\t};\n\n\t/*\n\tSave changes back to the tiddler store\n\t*/\n\tEditTextWidget.prototype.saveChanges = function(text) {\n\t\tvar editInfo = this.getEditInfo();\n\t\tif(text !== editInfo.value) {\n\t\t\teditInfo.update(text);\n\t\t}\n\t};\n\n\t/*\n\tHandle a dom \"keydown\" event, which we'll bubble up to our container for the keyboard widgets benefit\n\t*/\n\tEditTextWidget.prototype.handleKeydownEvent = function(event) {\n\t\t// Check for a keyboard shortcut\n\t\tif(this.toolbarNode) {\n\t\t\tvar shortcutElements = this.toolbarNode.querySelectorAll(\"[data-tw-keyboard-shortcut]\");\n\t\t\tfor(var index=0; index<shortcutElements.length; index++) {\n\t\t\t\tvar el = shortcutElements[index],\n\t\t\t\t\tshortcutData = el.getAttribute(\"data-tw-keyboard-shortcut\"),\n\t\t\t\t\tkeyInfoArray = $tw.keyboardManager.parseKeyDescriptors(shortcutData,{\n\t\t\t\t\t\twiki: this.wiki\n\t\t\t\t\t});\n\t\t\t\tif($tw.keyboardManager.checkKeyDescriptors(event,keyInfoArray)) {\n\t\t\t\t\tvar clickEvent = this.document.createEvent(\"Events\");\n\t\t\t\t    clickEvent.initEvent(\"click\",true,false);\n\t\t\t\t    el.dispatchEvent(clickEvent);\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Propogate the event to the container\n\t\tif(this.propogateKeydownEvent(event)) {\n\t\t\t// Ignore the keydown if it was already handled\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\treturn true;\n\t\t}\n\t\t// Otherwise, process the keydown normally\n\t\treturn false;\n\t};\n\n\t/*\n\tPropogate keydown events to our container for the keyboard widgets benefit\n\t*/\n\tEditTextWidget.prototype.propogateKeydownEvent = function(event) {\n\t\tvar newEvent = this.document.createEventObject ? this.document.createEventObject() : this.document.createEvent(\"Events\");\n\t\tif(newEvent.initEvent) {\n\t\t\tnewEvent.initEvent(\"keydown\", true, true);\n\t\t}\n\t\tnewEvent.keyCode = event.keyCode;\n\t\tnewEvent.which = event.which;\n\t\tnewEvent.metaKey = event.metaKey;\n\t\tnewEvent.ctrlKey = event.ctrlKey;\n\t\tnewEvent.altKey = event.altKey;\n\t\tnewEvent.shiftKey = event.shiftKey;\n\t\treturn !this.parentDomNode.dispatchEvent(newEvent);\n\t};\n\n\treturn EditTextWidget;\n\n}\n\nexports.editTextWidgetFactory = editTextWidgetFactory;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "library"
        },
        "$:/core/modules/editor/operations/bitmap/clear.js": {
            "title": "$:/core/modules/editor/operations/bitmap/clear.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/bitmap/clear.js\ntype: application/javascript\nmodule-type: bitmapeditoroperation\n\nBitmap editor operation to clear the image\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"clear\"] = function(event) {\n\tvar ctx = this.canvasDomNode.getContext(\"2d\");\n\tctx.globalAlpha = 1;\n\tctx.fillStyle = event.paramObject.colour || \"white\";\n\tctx.fillRect(0,0,this.canvasDomNode.width,this.canvasDomNode.height);\n\t// Save changes\n\tthis.strokeEnd();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "bitmapeditoroperation"
        },
        "$:/core/modules/editor/operations/bitmap/resize.js": {
            "title": "$:/core/modules/editor/operations/bitmap/resize.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/bitmap/resize.js\ntype: application/javascript\nmodule-type: bitmapeditoroperation\n\nBitmap editor operation to resize the image\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"resize\"] = function(event) {\n\t// Get the new width\n\tvar newWidth = parseInt(event.paramObject.width || this.canvasDomNode.width,10),\n\t\tnewHeight = parseInt(event.paramObject.height || this.canvasDomNode.height,10);\n\t// Update if necessary\n\tif(newWidth > 0 && newHeight > 0 && !(newWidth === this.currCanvas.width && newHeight === this.currCanvas.height)) {\n\t\tthis.changeCanvasSize(newWidth,newHeight);\n\t}\n\t// Update the input controls\n\tthis.refreshToolbar();\n\t// Save the image into the tiddler\n\tthis.saveChanges();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "bitmapeditoroperation"
        },
        "$:/core/modules/editor/operations/bitmap/rotate-left.js": {
            "title": "$:/core/modules/editor/operations/bitmap/rotate-left.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/bitmap/rotate-left.js\ntype: application/javascript\nmodule-type: bitmapeditoroperation\n\nBitmap editor operation to rotate the image left by 90 degrees\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"rotate-left\"] = function(event) {\n\t// Rotate the canvas left by 90 degrees\n\tthis.rotateCanvasLeft();\n\t// Update the input controls\n\tthis.refreshToolbar();\n\t// Save the image into the tiddler\n\tthis.saveChanges();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "bitmapeditoroperation"
        },
        "$:/core/modules/editor/operations/text/excise.js": {
            "title": "$:/core/modules/editor/operations/text/excise.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/excise.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to excise the selection to a new tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"excise\"] = function(event,operation) {\n\tvar editTiddler = this.wiki.getTiddler(this.editTitle),\n\t\teditTiddlerTitle = this.editTitle;\n\tif(editTiddler && editTiddler.fields[\"draft.of\"]) {\n\t\teditTiddlerTitle = editTiddler.fields[\"draft.of\"];\n\t}\n\tvar excisionTitle = event.paramObject.title || this.wiki.generateNewTitle(\"New Excision\");\n\tthis.wiki.addTiddler(new $tw.Tiddler(\n\t\tthis.wiki.getCreationFields(),\n\t\tthis.wiki.getModificationFields(),\n\t\t{\n\t\t\ttitle: excisionTitle,\n\t\t\ttext: operation.selection,\n\t\t\ttags: event.paramObject.tagnew === \"yes\" ?  [editTiddlerTitle] : []\n\t\t}\n\t));\n\toperation.replacement = excisionTitle;\n\tswitch(event.paramObject.type || \"transclude\") {\n\t\tcase \"transclude\":\n\t\t\toperation.replacement = \"{{\" + operation.replacement+ \"}}\";\n\t\t\tbreak;\n\t\tcase \"link\":\n\t\t\toperation.replacement = \"[[\" + operation.replacement+ \"]]\";\n\t\t\tbreak;\n\t\tcase \"macro\":\n\t\t\toperation.replacement = \"<<\" + (event.paramObject.macro || \"translink\") + \" \\\"\\\"\\\"\" + operation.replacement + \"\\\"\\\"\\\">>\";\n\t\t\tbreak;\n\t}\n\toperation.cutStart = operation.selStart;\n\toperation.cutEnd = operation.selEnd;\n\toperation.newSelStart = operation.selStart;\n\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/make-link.js": {
            "title": "$:/core/modules/editor/operations/text/make-link.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/make-link.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to make a link\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"make-link\"] = function(event,operation) {\n\tif(operation.selection) {\n\t\toperation.replacement = \"[[\" + operation.selection + \"|\" + event.paramObject.text + \"]]\";\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t} else {\n\t\toperation.replacement = \"[[\" + event.paramObject.text + \"]]\";\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t}\n\toperation.newSelStart = operation.selStart + operation.replacement.length;\n\toperation.newSelEnd = operation.newSelStart;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/prefix-lines.js": {
            "title": "$:/core/modules/editor/operations/text/prefix-lines.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/prefix-lines.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to add a prefix to the selected lines\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"prefix-lines\"] = function(event,operation) {\n\tvar targetCount = parseInt(event.paramObject.count + \"\",10);\n\t// Cut just past the preceding line break, or the start of the text\n\toperation.cutStart = $tw.utils.findPrecedingLineBreak(operation.text,operation.selStart);\n\t// Cut to just past the following line break, or to the end of the text\n\toperation.cutEnd = $tw.utils.findFollowingLineBreak(operation.text,operation.selEnd);\n\t// Compose the required prefix\n\tvar prefix = $tw.utils.repeat(event.paramObject.character,targetCount);\n\t// Process each line\n\tvar lines = operation.text.substring(operation.cutStart,operation.cutEnd).split(/\\r?\\n/mg);\n\t$tw.utils.each(lines,function(line,index) {\n\t\t// Remove and count any existing prefix characters\n\t\tvar count = 0;\n\t\twhile(line.charAt(0) === event.paramObject.character) {\n\t\t\tline = line.substring(1);\n\t\t\tcount++;\n\t\t}\n\t\t// Remove any whitespace\n\t\twhile(line.charAt(0) === \" \") {\n\t\t\tline = line.substring(1);\n\t\t}\n\t\t// We're done if we removed the exact required prefix, otherwise add it\n\t\tif(count !== targetCount) {\n\t\t\t// Apply the prefix\n\t\t\tline =  prefix + \" \" + line;\n\t\t}\n\t\t// Save the modified line\n\t\tlines[index] = line;\n\t});\n\t// Stitch the replacement text together and set the selection\n\toperation.replacement = lines.join(\"\\n\");\n\tif(lines.length === 1) {\n\t\toperation.newSelStart = operation.cutStart + operation.replacement.length;\n\t\toperation.newSelEnd = operation.newSelStart;\n\t} else {\n\t\toperation.newSelStart = operation.cutStart;\n\t\toperation.newSelEnd = operation.newSelStart + operation.replacement.length;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/replace-all.js": {
            "title": "$:/core/modules/editor/operations/text/replace-all.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/replace-all.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to replace the entire text\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"replace-all\"] = function(event,operation) {\n\toperation.cutStart = 0;\n\toperation.cutEnd = operation.text.length;\n\toperation.replacement = event.paramObject.text;\n\toperation.newSelStart = 0;\n\toperation.newSelEnd = operation.replacement.length;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/replace-selection.js": {
            "title": "$:/core/modules/editor/operations/text/replace-selection.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/replace-selection.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to replace the selection\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"replace-selection\"] = function(event,operation) {\n\toperation.replacement = event.paramObject.text;\n\toperation.cutStart = operation.selStart;\n\toperation.cutEnd = operation.selEnd;\n\toperation.newSelStart = operation.selStart;\n\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/save-selection.js": {
            "title": "$:/core/modules/editor/operations/text/save-selection.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/save-selection.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to save the current selection in a specified tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"save-selection\"] = function(event,operation) {\n\tvar tiddler = event.paramObject.tiddler,\n\t\tfield = event.paramObject.field || \"text\";\n\tif(tiddler && field) {\n\t\tthis.wiki.setText(tiddler,field,null,operation.text.substring(operation.selStart,operation.selEnd));\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/wrap-lines.js": {
            "title": "$:/core/modules/editor/operations/text/wrap-lines.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/wrap-lines.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to wrap the selected lines with a prefix and suffix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"wrap-lines\"] = function(event,operation) {\n\t// Cut just past the preceding line break, or the start of the text\n\toperation.cutStart = $tw.utils.findPrecedingLineBreak(operation.text,operation.selStart);\n\t// Cut to just past the following line break, or to the end of the text\n\toperation.cutEnd = $tw.utils.findFollowingLineBreak(operation.text,operation.selEnd);\n\t// Add the prefix and suffix\n\toperation.replacement = event.paramObject.prefix + \"\\n\" +\n\t\t\t\toperation.text.substring(operation.cutStart,operation.cutEnd) + \"\\n\" +\n\t\t\t\tevent.paramObject.suffix + \"\\n\";\n\toperation.newSelStart = operation.cutStart + event.paramObject.prefix.length + 1;\n\toperation.newSelEnd = operation.newSelStart + (operation.cutEnd - operation.cutStart);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/editor/operations/text/wrap-selection.js": {
            "title": "$:/core/modules/editor/operations/text/wrap-selection.js",
            "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/wrap-selection.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to wrap the selection with the specified prefix and suffix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"wrap-selection\"] = function(event,operation) {\n\tif(operation.selStart === operation.selEnd) {\n\t\t// No selection; check if we're within the prefix/suffix\n\t\tif(operation.text.substring(operation.selStart - event.paramObject.prefix.length,operation.selStart + event.paramObject.suffix.length) === event.paramObject.prefix + event.paramObject.suffix) {\n\t\t\t// Remove the prefix and suffix\n\t\t\toperation.cutStart = operation.selStart - event.paramObject.prefix.length;\n\t\t\toperation.cutEnd = operation.selEnd + event.paramObject.suffix.length;\n\t\t\toperation.replacement = \"\";\n\t\t\toperation.newSelStart = operation.cutStart;\n\t\t\toperation.newSelEnd = operation.newSelStart;\n\t\t} else {\n\t\t\t// Wrap the cursor instead\n\t\t\toperation.cutStart = operation.selStart;\n\t\t\toperation.cutEnd = operation.selEnd;\n\t\t\toperation.replacement = event.paramObject.prefix + event.paramObject.suffix;\n\t\t\toperation.newSelStart = operation.selStart + event.paramObject.prefix.length;\n\t\t\toperation.newSelEnd = operation.newSelStart;\n\t\t}\n\t} else if(operation.text.substring(operation.selStart,operation.selStart + event.paramObject.prefix.length) === event.paramObject.prefix && operation.text.substring(operation.selEnd - event.paramObject.suffix.length,operation.selEnd) === event.paramObject.suffix) {\n\t\t// Prefix and suffix are already present, so remove them\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t\toperation.replacement = operation.selection.substring(event.paramObject.prefix.length,operation.selection.length - event.paramObject.suffix.length);\n\t\toperation.newSelStart = operation.selStart;\n\t\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n\t} else {\n\t\t// Add the prefix and suffix\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t\toperation.replacement = event.paramObject.prefix + operation.selection + event.paramObject.suffix;\n\t\toperation.newSelStart = operation.selStart;\n\t\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "texteditoroperation"
        },
        "$:/core/modules/filters/addprefix.js": {
            "title": "$:/core/modules/filters/addprefix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/addprefix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for adding a prefix to each title in the list. This is\nespecially useful in contexts where only a filter expression is allowed\nand macro substitution isn't available.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.addprefix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(operator.operand + title);\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/addsuffix.js": {
            "title": "$:/core/modules/filters/addsuffix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/addsuffix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for adding a suffix to each title in the list. This is\nespecially useful in contexts where only a filter expression is allowed\nand macro substitution isn't available.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.addsuffix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title + operator.operand);\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/after.js": {
            "title": "$:/core/modules/filters/after.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/after.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler from the current list that is after the tiddler named in the operand.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.after = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\tvar index = results.indexOf(operator.operand);\n\tif(index === -1 || index > (results.length - 2)) {\n\t\treturn [];\n\t} else {\n\t\treturn [results[index + 1]];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/all/current.js": {
            "title": "$:/core/modules/filters/all/current.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/current.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[current]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.current = function(source,prefix,options) {\n\tvar currTiddlerTitle = options.widget && options.widget.getVariable(\"currentTiddler\");\n\tif(currTiddlerTitle) {\n\t\treturn [currTiddlerTitle];\n\t} else {\n\t\treturn [];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all/missing.js": {
            "title": "$:/core/modules/filters/all/missing.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/missing.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[missing]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.missing = function(source,prefix,options) {\n\treturn options.wiki.getMissingTitles();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all/orphans.js": {
            "title": "$:/core/modules/filters/all/orphans.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/orphans.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[orphans]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.orphans = function(source,prefix,options) {\n\treturn options.wiki.getOrphanTitles();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all/shadows.js": {
            "title": "$:/core/modules/filters/all/shadows.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/shadows.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[shadows]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.shadows = function(source,prefix,options) {\n\treturn options.wiki.allShadowTitles();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all/tags.js": {
            "title": "$:/core/modules/filters/all/tags.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/tags.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[tags]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tags = function(source,prefix,options) {\n\treturn Object.keys(options.wiki.getTagMap());\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all/tiddlers.js": {
            "title": "$:/core/modules/filters/all/tiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all/tiddlers.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[tiddlers]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tiddlers = function(source,prefix,options) {\n\treturn options.wiki.allTitles();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "allfilteroperator"
        },
        "$:/core/modules/filters/all.js": {
            "title": "$:/core/modules/filters/all.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/all.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for selecting tiddlers\n\n[all[shadows+tiddlers]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar allFilterOperators;\n\nfunction getAllFilterOperators() {\n\tif(!allFilterOperators) {\n\t\tallFilterOperators = {};\n\t\t$tw.modules.applyMethods(\"allfilteroperator\",allFilterOperators);\n\t}\n\treturn allFilterOperators;\n}\n\n/*\nExport our filter function\n*/\nexports.all = function(source,operator,options) {\n\t// Get our suboperators\n\tvar allFilterOperators = getAllFilterOperators();\n\t// Cycle through the suboperators accumulating their results\n\tvar results = [],\n\t\tsubops = operator.operand.split(\"+\");\n\t// Check for common optimisations\n\tif(subops.length === 1 && subops[0] === \"\") {\n\t\treturn source;\n\t} else if(subops.length === 1 && subops[0] === \"tiddlers\") {\n\t\treturn options.wiki.each;\n\t} else if(subops.length === 1 && subops[0] === \"shadows\") {\n\t\treturn options.wiki.eachShadow;\n\t} else if(subops.length === 2 && subops[0] === \"tiddlers\" && subops[1] === \"shadows\") {\n\t\treturn options.wiki.eachTiddlerPlusShadows;\n\t} else if(subops.length === 2 && subops[0] === \"shadows\" && subops[1] === \"tiddlers\") {\n\t\treturn options.wiki.eachShadowPlusTiddlers;\n\t}\n\t// Do it the hard way\n\tfor(var t=0; t<subops.length; t++) {\n\t\tvar subop = allFilterOperators[subops[t]];\n\t\tif(subop) {\n\t\t\t$tw.utils.pushTop(results,subop(source,operator.prefix,options));\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/backlinks.js": {
            "title": "$:/core/modules/filters/backlinks.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/backlinks.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning all the backlinks from a tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.backlinks = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.getTiddlerBacklinks(title));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/before.js": {
            "title": "$:/core/modules/filters/before.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/before.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler from the current list that is before the tiddler named in the operand.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.before = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\tvar index = results.indexOf(operator.operand);\n\tif(index <= 0) {\n\t\treturn [];\n\t} else {\n\t\treturn [results[index - 1]];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/commands.js": {
            "title": "$:/core/modules/filters/commands.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/commands.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the commands available in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.commands = function(source,operator,options) {\n\tvar results = [];\n\t$tw.utils.each($tw.commands,function(commandInfo,name) {\n\t\tresults.push(name);\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/compare.js": {
            "title": "$:/core/modules/filters/compare.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/compare.js\ntype: application/javascript\nmodule-type: filteroperator\n\nGeneral purpose comparison operator\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.compare = function(source,operator,options) {\n\tvar suffixes = operator.suffixes || [],\n\t\ttype = (suffixes[0] || [])[0],\n\t\tmode = (suffixes[1] || [])[0],\n\t\ttypeFn = types[type] || types.number,\n\t\tmodeFn = modes[mode] || modes.eq,\n\t\tinvert = operator.prefix === \"!\",\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tif(modeFn(typeFn(title,operator.operand)) !== invert) {\n\t\t\tresults.push(title);\n\t\t}\n\t});\n\treturn results;\n};\n\nvar types = {\n\t\"number\": function(a,b) {\n\t\treturn compare($tw.utils.parseNumber(a),$tw.utils.parseNumber(b));\n\t},\n\t\"integer\": function(a,b) {\n\t\treturn compare($tw.utils.parseInt(a),$tw.utils.parseInt(b));\n\t},\n\t\"string\": function(a,b) {\n\t\treturn compare(\"\" + a,\"\" +b);\n\t},\n\t\"date\": function(a,b) {\n\t\tvar dateA = $tw.utils.parseDate(a),\n\t\t\tdateB = $tw.utils.parseDate(b);\n\t\tif(!isFinite(dateA)) {\n\t\t\tdateA = new Date(0);\n\t\t}\n\t\tif(!isFinite(dateB)) {\n\t\t\tdateB = new Date(0);\n\t\t}\n\t\treturn compare(dateA,dateB);\n\t},\n\t\"version\": function(a,b) {\n\t\treturn $tw.utils.compareVersions(a,b);\n\t}\n};\n\nfunction compare(a,b) {\n\tif(a > b) {\n\t\treturn +1;\n\t} else if(a < b) {\n\t\treturn -1;\n\t} else {\n\t\treturn 0;\n\t}\n};\n\nvar modes = {\n\t\"eq\": function(value) {return value === 0;},\n\t\"ne\": function(value) {return value !== 0;},\n\t\"gteq\": function(value) {return value >= 0;},\n\t\"gt\": function(value) {return value > 0;},\n\t\"lteq\": function(value) {return value <= 0;},\n\t\"lt\": function(value) {return value < 0;}\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/contains.js": {
            "title": "$:/core/modules/filters/contains.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/contains.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for finding values in array fields\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.contains = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldname = (operator.suffix || \"list\").toLowerCase();\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler) {\n\t\t\t\tvar list = tiddler.getFieldList(fieldname);\n\t\t\t\tif(list.indexOf(operator.operand) === -1) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler) {\n\t\t\t\tvar list = tiddler.getFieldList(fieldname);\n\t\t\t\tif(list.indexOf(operator.operand) !== -1) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/count.js": {
            "title": "$:/core/modules/filters/count.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/count.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the number of entries in the current list.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.count = function(source,operator,options) {\n\tvar count = 0;\n\tsource(function(tiddler,title) {\n\t\tcount++;\n\t});\n\treturn [count + \"\"];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/days.js": {
            "title": "$:/core/modules/filters/days.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/days.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects tiddlers with a specified date field within a specified date interval.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.days = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldName = operator.suffix || \"modified\",\n\t\tdayInterval = (parseInt(operator.operand,10)||0),\n\t\tdayIntervalSign = $tw.utils.sign(dayInterval),\n\t\ttargetTimeStamp = (new Date()).setHours(0,0,0,0) + 1000*60*60*24*dayInterval,\n\t\tisWithinDays = function(dateField) {\n\t\t\tvar sign = $tw.utils.sign(targetTimeStamp - (new Date(dateField)).setHours(0,0,0,0));\n\t\t\treturn sign === 0 || sign === dayIntervalSign;\n\t\t};\n\n\tif(operator.prefix === \"!\") {\n\t\ttargetTimeStamp = targetTimeStamp - 1000*60*60*24*dayIntervalSign;\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && tiddler.fields[fieldName]) {\n\t\t\t\tif(!isWithinDays($tw.utils.parseDate(tiddler.fields[fieldName]))) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && tiddler.fields[fieldName]) {\n\t\t\t\tif(isWithinDays($tw.utils.parseDate(tiddler.fields[fieldName]))) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/each.js": {
            "title": "$:/core/modules/filters/each.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/each.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects one tiddler for each unique value of the specified field.\nWith suffix \"list\", selects all tiddlers that are values in a specified list field.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.each = function(source,operator,options) {\n\tvar results =[] ,\n\tvalue,values = {},\n\tfield = operator.operand || \"title\";\n\tif(operator.suffix === \"value\" && field === \"title\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!$tw.utils.hop(values,title)) {\n\t\t\t\tvalues[title] = true;\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else if(operator.suffix !== \"list-item\") {\n\t\tif(field === \"title\") {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && !$tw.utils.hop(values,title)) {\n\t\t\t\t\tvalues[title] = true;\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvalue = tiddler.getFieldString(field);\n\t\t\t\t\tif(!$tw.utils.hop(values,value)) {\n\t\t\t\t\t\tvalues[value] = true;\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler) {\n\t\t\t\t$tw.utils.each(\n\t\t\t\t\toptions.wiki.getTiddlerList(title,field),\n\t\t\t\t\tfunction(value) {\n\t\t\t\t\t\tif(!$tw.utils.hop(values,value)) {\n\t\t\t\t\t\t\tvalues[value] = true;\n\t\t\t\t\t\t\tresults.push(value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/eachday.js": {
            "title": "$:/core/modules/filters/eachday.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/eachday.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects one tiddler for each unique day covered by the specified date field\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.eachday = function(source,operator,options) {\n\tvar results = [],\n\t\tvalues = [],\n\t\tfieldName = operator.operand || \"modified\";\n\t// Function to convert a date/time to a date integer\n\tvar toDate = function(value) {\n\t\tvalue = (new Date(value)).setHours(0,0,0,0);\n\t\treturn value+0;\n\t};\n\tsource(function(tiddler,title) {\n\t\tif(tiddler && tiddler.fields[fieldName]) {\n\t\t\tvar value = toDate($tw.utils.parseDate(tiddler.fields[fieldName]));\n\t\t\tif(values.indexOf(value) === -1) {\n\t\t\t\tvalues.push(value);\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/editiondescription.js": {
            "title": "$:/core/modules/filters/editiondescription.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/editiondescription.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the descriptions of the specified edition names\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.editiondescription = function(source,operator,options) {\n\tvar results = [],\n\t\teditionInfo = $tw.utils.getEditionInfo();\n\tif(editionInfo) {\n\t\tsource(function(tiddler,title) {\n\t\t\tif($tw.utils.hop(editionInfo,title)) {\n\t\t\t\tresults.push(editionInfo[title].description || \"\");\t\t\t\t\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/editions.js": {
            "title": "$:/core/modules/filters/editions.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/editions.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the available editions in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.editions = function(source,operator,options) {\n\tvar results = [],\n\t\teditionInfo = $tw.utils.getEditionInfo();\n\tif(editionInfo) {\n\t\t$tw.utils.each(editionInfo,function(info,name) {\n\t\t\tresults.push(name);\n\t\t});\n\t}\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/else.js": {
            "title": "$:/core/modules/filters/else.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/else.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for replacing an empty input list with a constant, passing a non-empty input list straight through\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.else = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\tif(results.length === 0) {\n\t\treturn [operator.operand];\n\t} else {\n\t\treturn results;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/decodeuricomponent.js": {
            "title": "$:/core/modules/filters/decodeuricomponent.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/decodeuricomponent.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for applying decodeURIComponent() to each item.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter functions\n*/\n\nexports.decodeuricomponent = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar value = title;\n\t\ttry {\n\t\t\tvalue = decodeURIComponent(title);\n\t\t} catch(e) {\n\t\t}\n\t\tresults.push(value);\n\t});\n\treturn results;\n};\n\nexports.encodeuricomponent = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(encodeURIComponent(title));\n\t});\n\treturn results;\n};\n\nexports.decodeuri = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar value = title;\n\t\ttry {\n\t\t\tvalue = decodeURI(title);\n\t\t} catch(e) {\n\t\t}\n\t\tresults.push(value);\n\t});\n\treturn results;\n};\n\nexports.encodeuri = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(encodeURI(title));\n\t});\n\treturn results;\n};\n\nexports.decodehtml = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.htmlDecode(title));\n\t});\n\treturn results;\n};\n\nexports.encodehtml = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.htmlEncode(title));\n\t});\n\treturn results;\n};\n\nexports.stringify = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.stringify(title));\n\t});\n\treturn results;\n};\n\nexports.jsonstringify = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.jsonStringify(title));\n\t});\n\treturn results;\n};\n\nexports.escaperegexp = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.escapeRegExp(title));\n\t});\n\treturn results;\n};\n\nexports.escapecss = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t// escape any character with a special meaning in CSS using CSS.escape()\n\t\tresults.push(CSS.escape(title));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/enlist.js": {
            "title": "$:/core/modules/filters/enlist.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/enlist.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning its operand parsed as a list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.enlist = function(source,operator,options) {\n\tvar allowDuplicates = false;\n\tswitch(operator.suffix) {\n\t\tcase \"raw\":\n\t\t\tallowDuplicates = true;\n\t\t\tbreak;\n\t\tcase \"dedupe\":\n\t\t\tallowDuplicates = false;\n\t\t\tbreak;\n\t}\n\tvar list = $tw.utils.parseStringArray(operator.operand,allowDuplicates);\n\tif(operator.prefix === \"!\") {\n\t\tvar results = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tif(list.indexOf(title) === -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t\treturn results;\n\t} else {\n\t\treturn list;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/field.js": {
            "title": "$:/core/modules/filters/field.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/field.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for comparing fields for equality\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.field = function(source,operator,options) {\n\tvar results = [],indexedResults,\n\t\tfieldname = (operator.suffix || operator.operator || \"title\").toLowerCase();\n\tif(operator.prefix === \"!\") {\n\t\tif(operator.regexp) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && !operator.regexp.exec(text)) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && text !== operator.operand) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t} else {\n\t\tif(operator.regexp) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && !!operator.regexp.exec(text)) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tif(source.byField && operator.operand) {\n\t\t\t\tindexedResults = source.byField(fieldname,operator.operand);\n\t\t\t\tif(indexedResults) {\n\t\t\t\t\treturn indexedResults\n\t\t\t\t}\n\t\t\t}\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && text === operator.operand) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/fields.js": {
            "title": "$:/core/modules/filters/fields.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/fields.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the fields on the selected tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.fields = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldName,\n\t\tsuffixes = (operator.suffixes || [])[0] || [],\n\t\toperand = $tw.utils.parseStringArray(operator.operand);\n\t\n\tsource(function(tiddler,title) {\n\t\tif(tiddler) {\n\t\t\tif(suffixes.indexOf(\"include\") !== -1) {\n\t\t\t\tfor(fieldName in tiddler.fields) {\n\t\t\t\t\t(operand.indexOf(fieldName) !== -1) ? $tw.utils.pushTop(results,fieldName) : \"\";\n\t\t\t\t}\n\t\t\t} else if (suffixes.indexOf(\"exclude\") !== -1) {\n\t\t\t\tfor(fieldName in tiddler.fields) {\n\t\t\t\t\t(operand.indexOf(fieldName) !== -1) ? \"\" : $tw.utils.pushTop(results,fieldName);\n\t\t\t\t}\n\t\t\t} // else if\n\t\t\telse {\n\t\t\t\tfor(fieldName in tiddler.fields) {\n\t\t\t\t\t$tw.utils.pushTop(results,fieldName);\n\t\t\t\t}\n\t\t\t} // else\n\t\t} // if (tiddler)\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/get.js": {
            "title": "$:/core/modules/filters/get.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/get.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for replacing tiddler titles by the value of the field specified in the operand.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.get = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tif(tiddler) {\n\t\t\tvar value = tiddler.getFieldString(operator.operand);\n\t\t\tif(value) {\n\t\t\t\tresults.push(value);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/getindex.js": {
            "title": "$:/core/modules/filters/getindex.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/getindex.js\ntype: application/javascript\nmodule-type: filteroperator\n\nreturns the value at a given index of datatiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.getindex = function(source,operator,options) {\n\tvar data,title,results = [];\n\tif(operator.operand){\n\t\tsource(function(tiddler,title) {\n\t\t\ttitle = tiddler ? tiddler.fields.title : title;\n\t\t\tdata = options.wiki.extractTiddlerDataItem(tiddler,operator.operand);\n\t\t\tif(data) {\n\t\t\t\tresults.push(data);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/getvariable.js": {
            "title": "$:/core/modules/filters/getvariable.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/getvariable.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for replacing input values by the value of the variable with the same name, or blank if the variable is missing\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.getvariable = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(options.widget.getVariable(title) || \"\");\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/has.js": {
            "title": "$:/core/modules/filters/has.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/has.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking if a tiddler has the specified field or index\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.has = function(source,operator,options) {\n\tvar results = [],\n\t\tinvert = operator.prefix === \"!\";\n\n\tif(operator.suffix === \"field\") {\n\t\tif(invert) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(!tiddler || (tiddler && (!$tw.utils.hop(tiddler.fields,operator.operand)))) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && $tw.utils.hop(tiddler.fields,operator.operand)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\telse if(operator.suffix === \"index\") {\n\t\tif(invert) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(!tiddler || (tiddler && (!$tw.utils.hop($tw.wiki.getTiddlerDataCached(tiddler,Object.create(null)),operator.operand)))) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && $tw.utils.hop($tw.wiki.getTiddlerDataCached(tiddler,Object.create(null)),operator.operand)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\telse {\n\t\tif(invert) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(!tiddler || !$tw.utils.hop(tiddler.fields,operator.operand) || (tiddler.fields[operator.operand] === \"\")) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && $tw.utils.hop(tiddler.fields,operator.operand) && !(tiddler.fields[operator.operand] === \"\" || tiddler.fields[operator.operand].length === 0)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\t\t\t\t\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/haschanged.js": {
            "title": "$:/core/modules/filters/haschanged.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/haschanged.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returns tiddlers from the list that have a non-zero changecount.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.haschanged = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.getChangeCount(title) === 0) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.getChangeCount(title) > 0) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/indexes.js": {
            "title": "$:/core/modules/filters/indexes.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/indexes.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the indexes of a data tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.indexes = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar data = options.wiki.getTiddlerDataCached(title);\n\t\tif(data) {\n\t\t\t$tw.utils.pushTop(results,Object.keys(data));\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/insertbefore.js": {
            "title": "$:/core/modules/filters/insertbefore.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/insertbefore.js\ntype: application/javascript\nmodule-type: filteroperator\n\nInsert an item before another item in a list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nOrder a list\n*/\nexports.insertbefore = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\tvar target = options.widget && options.widget.getVariable(operator.suffix || \"currentTiddler\");\n\tif(target !== operator.operand) {\n\t\t// Remove the entry from the list if it is present\n\t\tvar pos = results.indexOf(operator.operand);\n\t\tif(pos !== -1) {\n\t\t\tresults.splice(pos,1);\n\t\t}\n\t\t// Insert the entry before the target marker\n\t\tpos = results.indexOf(target);\n\t\tif(pos !== -1) {\n\t\t\tresults.splice(pos,0,operator.operand);\n\t\t} else {\n\t\t\tresults.push(operator.operand);\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/is/binary.js": {
            "title": "$:/core/modules/filters/is/binary.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/binary.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[binary]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.binary = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.isBinaryTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.isBinaryTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/blank.js": {
            "title": "$:/core/modules/filters/is/blank.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/blank.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[blank]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.blank = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!title) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/current.js": {
            "title": "$:/core/modules/filters/is/current.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/current.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[current]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.current = function(source,prefix,options) {\n\tvar results = [],\n\t\tcurrTiddlerTitle = options.widget && options.widget.getVariable(\"currentTiddler\");\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title !== currTiddlerTitle) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title === currTiddlerTitle) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/image.js": {
            "title": "$:/core/modules/filters/is/image.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/image.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[image]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.image = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.isImageTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.isImageTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/missing.js": {
            "title": "$:/core/modules/filters/is/missing.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/missing.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[missing]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.missing = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/orphan.js": {
            "title": "$:/core/modules/filters/is/orphan.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/orphan.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[orphan]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.orphan = function(source,prefix,options) {\n\tvar results = [],\n\t\torphanTitles = options.wiki.getOrphanTitles();\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(orphanTitles.indexOf(title) === -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(orphanTitles.indexOf(title) !== -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/shadow.js": {
            "title": "$:/core/modules/filters/is/shadow.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/shadow.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[shadow]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.shadow = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.isShadowTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.isShadowTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/system.js": {
            "title": "$:/core/modules/filters/is/system.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/system.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[system]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.system = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.isSystemTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.isSystemTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/tag.js": {
            "title": "$:/core/modules/filters/is/tag.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/tag.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[tag]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tag = function(source,prefix,options) {\n\tvar results = [],\n\t\ttagMap = options.wiki.getTagMap();\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!$tw.utils.hop(tagMap,title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif($tw.utils.hop(tagMap,title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/tiddler.js": {
            "title": "$:/core/modules/filters/is/tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/tiddler.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[tiddler]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tiddler = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is/variable.js": {
            "title": "$:/core/modules/filters/is/variable.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is/variable.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[variable]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.variable = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!(title in options.widget.variables)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title in options.widget.variables) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "isfilteroperator"
        },
        "$:/core/modules/filters/is.js": {
            "title": "$:/core/modules/filters/is.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/is.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking tiddler properties\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar isFilterOperators;\n\nfunction getIsFilterOperators() {\n\tif(!isFilterOperators) {\n\t\tisFilterOperators = {};\n\t\t$tw.modules.applyMethods(\"isfilteroperator\",isFilterOperators);\n\t}\n\treturn isFilterOperators;\n}\n\n/*\nExport our filter function\n*/\nexports.is = function(source,operator,options) {\n\t// Dispatch to the correct isfilteroperator\n\tvar isFilterOperators = getIsFilterOperators();\n\tif(operator.operand) {\n\t\tvar isFilterOperator = isFilterOperators[operator.operand];\n\t\tif(isFilterOperator) {\n\t\t\treturn isFilterOperator(source,operator.prefix,options);\n\t\t} else {\n\t\t\treturn [$tw.language.getString(\"Error/IsFilterOperator\")];\n\t\t}\n\t} else {\n\t\t// Return all tiddlers if the operand is missing\n\t\tvar results = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.push(title);\n\t\t});\n\t\treturn results;\n\t}\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/limit.js": {
            "title": "$:/core/modules/filters/limit.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/limit.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for chopping the results to a specified maximum number of entries\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.limit = function(source,operator,options) {\n\tvar results = [];\n\t// Convert to an array\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\t// Slice the array if necessary\n\tvar limit = Math.min(results.length,parseInt(operator.operand,10));\n\tif(operator.prefix === \"!\") {\n\t\tresults = results.slice(-limit);\n\t} else {\n\t\tresults = results.slice(0,limit);\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/links.js": {
            "title": "$:/core/modules/filters/links.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/links.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning all the links from a tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.links = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.getTiddlerLinks(title));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/list.js": {
            "title": "$:/core/modules/filters/list.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/list.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddlers whose title is listed in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.list = function(source,operator,options) {\n\tvar results = [],\n\t\ttr = $tw.utils.parseTextReference(operator.operand),\n\t\tcurrTiddlerTitle = options.widget && options.widget.getVariable(\"currentTiddler\"),\n\t\tlist = options.wiki.getTiddlerList(tr.title || currTiddlerTitle,tr.field,tr.index);\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(list.indexOf(title) === -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tresults = list;\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/listed.js": {
            "title": "$:/core/modules/filters/listed.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/listed.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all tiddlers that have the selected tiddlers in a list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.listed = function(source,operator,options) {\n\tvar field = operator.operand || \"list\",\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.findListingsOfTiddler(title,field));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/listops.js": {
            "title": "$:/core/modules/filters/listops.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/listops.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operators for manipulating the current selection list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nOrder a list\n*/\nexports.order = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.operand.toLowerCase() === \"reverse\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.unshift(title);\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.push(title);\n\t\t});\n\t}\n\treturn results;\n};\n\n/*\nReverse list\n*/\nexports.reverse = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.unshift(title);\n\t});\n\treturn results;\n};\n\n/*\nFirst entry/entries in list\n*/\nexports.first = function(source,operator,options) {\n\tvar count = $tw.utils.getInt(operator.operand,1),\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(0,count);\n};\n\n/*\nLast entry/entries in list\n*/\nexports.last = function(source,operator,options) {\n\tvar count = $tw.utils.getInt(operator.operand,1),\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(-count);\n};\n\n/*\nAll but the first entry/entries of the list\n*/\nexports.rest = function(source,operator,options) {\n\tvar count = $tw.utils.getInt(operator.operand,1),\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(count);\n};\nexports.butfirst = exports.rest;\nexports.bf = exports.rest;\n\n/*\nAll but the last entry/entries of the list\n*/\nexports.butlast = function(source,operator,options) {\n\tvar count = $tw.utils.getInt(operator.operand,1),\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(0,-count);\n};\nexports.bl = exports.butlast;\n\n/*\nThe nth member of the list\n*/\nexports.nth = function(source,operator,options) {\n\tvar count = $tw.utils.getInt(operator.operand,1),\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(count - 1,count);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/lookup.js": {
            "title": "$:/core/modules/filters/lookup.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/lookup.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that looks up values via a title prefix\n\n[lookup:<field>[<prefix>]]\n\nPrepends the prefix to the selected items and returns the specified field value\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.lookup = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(options.wiki.getTiddlerText(operator.operand + title) || options.wiki.getTiddlerText(operator.operand + operator.suffix));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/match.js": {
            "title": "$:/core/modules/filters/match.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/match.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking if a title matches a string\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.match = function(source,operator,options) {\n\tvar results = [],\n\t\tsuffixes = (operator.suffixes || [])[0] || [];\n\tif(suffixes.indexOf(\"caseinsensitive\") !== -1) {\n\t\tif(operator.prefix === \"!\") {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(title.toLowerCase() !== (operator.operand || \"\").toLowerCase()) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(title.toLowerCase() === (operator.operand || \"\").toLowerCase()) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t} else {\n\t\tif(operator.prefix === \"!\") {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(title !== operator.operand) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(title === operator.operand) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/math.js": {
            "title": "$:/core/modules/filters/math.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/math.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operators for math. Unary/binary operators work on each item in turn, and return a new item list.\n\nSum/product/maxall/minall operate on the entire list, returning a single item.\n\nNote that strings are converted to numbers automatically. Trailing non-digits are ignored.\n\n* \"\" converts to 0\n* \"12kk\" converts to 12\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.negate = makeNumericBinaryOperator(\n\tfunction(a) {return -a}\n);\n\nexports.abs = makeNumericBinaryOperator(\n\tfunction(a) {return Math.abs(a)}\n);\n\nexports.ceil = makeNumericBinaryOperator(\n\tfunction(a) {return Math.ceil(a)}\n);\n\nexports.floor = makeNumericBinaryOperator(\n\tfunction(a) {return Math.floor(a)}\n);\n\nexports.round = makeNumericBinaryOperator(\n\tfunction(a) {return Math.round(a)}\n);\n\nexports.trunc = makeNumericBinaryOperator(\n\tfunction(a) {return Math.trunc(a)}\n);\n\nexports.untrunc = makeNumericBinaryOperator(\n\tfunction(a) {return Math.ceil(Math.abs(a)) * Math.sign(a)}\n);\n\nexports.sign = makeNumericBinaryOperator(\n\tfunction(a) {return Math.sign(a)}\n);\n\nexports.add = makeNumericBinaryOperator(\n\tfunction(a,b) {return a + b;}\n);\n\nexports.subtract = makeNumericBinaryOperator(\n\tfunction(a,b) {return a - b;}\n);\n\nexports.multiply = makeNumericBinaryOperator(\n\tfunction(a,b) {return a * b;}\n);\n\nexports.divide = makeNumericBinaryOperator(\n\tfunction(a,b) {return a / b;}\n);\n\nexports.remainder = makeNumericBinaryOperator(\n\tfunction(a,b) {return a % b;}\n);\n\nexports.max = makeNumericBinaryOperator(\n\tfunction(a,b) {return Math.max(a,b);}\n);\n\nexports.min = makeNumericBinaryOperator(\n\tfunction(a,b) {return Math.min(a,b);}\n);\n\nexports.fixed = makeNumericBinaryOperator(\n\tfunction(a,b) {return Number.prototype.toFixed.call(a,Math.min(Math.max(b,0),100));}\n);\n\nexports.precision = makeNumericBinaryOperator(\n\tfunction(a,b) {return Number.prototype.toPrecision.call(a,Math.min(Math.max(b,1),100));}\n);\n\nexports.exponential = makeNumericBinaryOperator(\n\tfunction(a,b) {return Number.prototype.toExponential.call(a,Math.min(Math.max(b,0),100));}\n);\n\nexports.sum = makeNumericReducingOperator(\n\tfunction(accumulator,value) {return accumulator + value},\n\t0 // Initial value\n);\n\nexports.product = makeNumericReducingOperator(\n\tfunction(accumulator,value) {return accumulator * value},\n\t1 // Initial value\n);\n\nexports.maxall = makeNumericReducingOperator(\n\tfunction(accumulator,value) {return Math.max(accumulator,value)},\n\t-Infinity // Initial value\n);\n\nexports.minall = makeNumericReducingOperator(\n\tfunction(accumulator,value) {return Math.min(accumulator,value)},\n\tInfinity // Initial value\n);\n\nfunction makeNumericBinaryOperator(fnCalc) {\n\treturn function(source,operator,options) {\n\t\tvar result = [],\n\t\t\tnumOperand = $tw.utils.parseNumber(operator.operand);\n\t\tsource(function(tiddler,title) {\n\t\t\tresult.push($tw.utils.stringifyNumber(fnCalc($tw.utils.parseNumber(title),numOperand)));\n\t\t});\n\t\treturn result;\n\t};\n}\n\nfunction makeNumericReducingOperator(fnCalc,initialValue) {\n\tinitialValue = initialValue || 0;\n\treturn function(source,operator,options) {\n\t\tvar result = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tresult.push(title);\n\t\t});\n\t\treturn [$tw.utils.stringifyNumber(result.reduce(function(accumulator,currentValue) {\n\t\t\treturn fnCalc(accumulator,$tw.utils.parseNumber(currentValue));\n\t\t},initialValue))];\n\t};\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/minlength.js": {
            "title": "$:/core/modules/filters/minlength.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/minlength.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for filtering out titles that don't meet the minimum length in the operand\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.minlength = function(source,operator,options) {\n\tvar results = [],\n\t\tminLength = parseInt(operator.operand || \"\",10) || 0;\n\tsource(function(tiddler,title) {\n\t\tif(title.length >= minLength) {\n\t\t\tresults.push(title);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/modules.js": {
            "title": "$:/core/modules/filters/modules.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/modules.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the titles of the modules of a given type in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.modules = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {\n\t\t\tresults.push(moduleName);\n\t\t});\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/moduletypes.js": {
            "title": "$:/core/modules/filters/moduletypes.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/moduletypes.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the module types in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.moduletypes = function(source,operator,options) {\n\tvar results = [];\n\t$tw.utils.each($tw.modules.types,function(moduleInfo,type) {\n\t\tresults.push(type);\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/next.js": {
            "title": "$:/core/modules/filters/next.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/next.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler whose title occurs next in the list supplied in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.next = function(source,operator,options) {\n\tvar results = [],\n\t\tlist = options.wiki.getTiddlerList(operator.operand);\n\tsource(function(tiddler,title) {\n\t\tvar match = list.indexOf(title);\n\t\t// increment match and then test if result is in range\n\t\tmatch++;\n\t\tif(match > 0 && match < list.length) {\n\t\t\tresults.push(list[match]);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/plugintiddlers.js": {
            "title": "$:/core/modules/filters/plugintiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/plugintiddlers.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the titles of the shadow tiddlers within a plugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.plugintiddlers = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar pluginInfo = options.wiki.getPluginInfo(title) || options.wiki.getTiddlerDataCached(title,{tiddlers:[]});\n\t\tif(pluginInfo && pluginInfo.tiddlers) {\n\t\t\t$tw.utils.each(pluginInfo.tiddlers,function(fields,title) {\n\t\t\t\tresults.push(title);\n\t\t\t});\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/prefix.js": {
            "title": "$:/core/modules/filters/prefix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/prefix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking if a title starts with a prefix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.prefix = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(0,operator.operand.length) !== operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(0,operator.operand.length) === operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/previous.js": {
            "title": "$:/core/modules/filters/previous.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/previous.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler whose title occurs immediately prior in the list supplied in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.previous = function(source,operator,options) {\n\tvar results = [],\n\t\tlist = options.wiki.getTiddlerList(operator.operand);\n\tsource(function(tiddler,title) {\n\t\tvar match = list.indexOf(title);\n\t\t// increment match and then test if result is in range\n\t\tmatch--;\n\t\tif(match >= 0) {\n\t\t\tresults.push(list[match]);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/range.js": {
            "title": "$:/core/modules/filters/range.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/range.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for generating a numeric range.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.range = function(source,operator,options) {\n\tvar results = [];\n\t// Split the operand into numbers delimited by these symbols\n\tvar parts = operator.operand.split(/[,:;]/g),\n\t\tbeg, end, inc, i, fixed = 0;\n\tfor (i=0; i<parts.length; i++) {\n\t\t// Validate real number\n\t\tif(!/^\\s*[+-]?((\\d+(\\.\\d*)?)|(\\.\\d+))\\s*$/.test(parts[i])) {\n\t\t\treturn [\"range: bad number \\\"\" + parts[i] + \"\\\"\"];\n\t\t}\n\t\t// Count digits; the most precise number determines decimal places in output.\n\t\tvar frac = /\\.\\d+/.exec(parts[i]);\n\t\tif(frac) {\n\t\t\tfixed = Math.max(fixed,frac[0].length-1);\n\t\t}\n\t\tparts[i] = parseFloat(parts[i]);\n\t}\n\tswitch(parts.length) {\n\t\tcase 1:\n\t\t\tend = parts[0];\n\t\t\tif (end >= 1) {\n\t\t\t\tbeg = 1;\n\t\t\t}\n\t\t\telse if (end <= -1) {\n\t\t\t\tbeg = -1;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\tinc = 1;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tbeg = parts[0];\n\t\t\tend = parts[1];\n\t\t\tinc = 1;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tbeg = parts[0];\n\t\t\tend = parts[1];\n\t\t\tinc = Math.abs(parts[2]);\n\t\t\tbreak;\n\t}\n\tif(inc === 0) {\n\t\treturn [\"range: increment 0 causes infinite loop\"];\n\t}\n\t// May need to count backwards\n\tvar direction = ((end < beg) ? -1 : 1);\n\tinc *= direction;\n\t// Estimate number of resulting elements\n\tif((end - beg) / inc > 10000) {\n\t\treturn [\"range: too many steps (over 10K)\"];\n\t}\n\t// Avoid rounding error on last step\n\tend += direction * 0.5 * Math.pow(0.1,fixed);\n\tvar safety = 10010;\n\t// Enumerate the range\n\tif (end<beg) {\n\t\tfor(i=beg; i>end; i+=inc) {\n\t\t\tresults.push(i.toFixed(fixed));\n\t\t\tif(--safety<0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor(i=beg; i<end; i+=inc) {\n\t\t\tresults.push(i.toFixed(fixed));\n\t\t\tif(--safety<0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif(safety<0) {\n\t\treturn [\"range: unexpectedly large output\"];\n\t}\n\t// Reverse?\n\tif(operator.prefix === \"!\") {\n\t\tresults.reverse();\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/regexp.js": {
            "title": "$:/core/modules/filters/regexp.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/regexp.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for regexp matching\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.regexp = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldname = (operator.suffix || \"title\").toLowerCase(),\n\t\tregexpString, regexp, flags = \"\", match,\n\t\tgetFieldString = function(tiddler,title) {\n\t\t\tif(tiddler) {\n\t\t\t\treturn tiddler.getFieldString(fieldname);\n\t\t\t} else if(fieldname === \"title\") {\n\t\t\t\treturn title;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t};\n\t// Process flags and construct regexp\n\tregexpString = operator.operand;\n\tmatch = /^\\(\\?([gim]+)\\)/.exec(regexpString);\n\tif(match) {\n\t\tflags = match[1];\n\t\tregexpString = regexpString.substr(match[0].length);\n\t} else {\n\t\tmatch = /\\(\\?([gim]+)\\)$/.exec(regexpString);\n\t\tif(match) {\n\t\t\tflags = match[1];\n\t\t\tregexpString = regexpString.substr(0,regexpString.length - match[0].length);\n\t\t}\n\t}\n\ttry {\n\t\tregexp = new RegExp(regexpString,flags);\n\t} catch(e) {\n\t\treturn [\"\" + e];\n\t}\n\t// Process the incoming tiddlers\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tvar text = getFieldString(tiddler,title);\n\t\t\tif(text !== null) {\n\t\t\t\tif(!regexp.exec(text)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tvar text = getFieldString(tiddler,title);\n\t\t\tif(text !== null) {\n\t\t\t\tif(!!regexp.exec(text)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/removeprefix.js": {
            "title": "$:/core/modules/filters/removeprefix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/removeprefix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for removing a prefix from each title in the list. Titles that do not start with the prefix are removed.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.removeprefix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tif(title.substr(0,operator.operand.length) === operator.operand) {\n\t\t\tresults.push(title.substr(operator.operand.length));\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/removesuffix.js": {
            "title": "$:/core/modules/filters/removesuffix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/removesuffix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for removing a suffix from each title in the list. Titles that do not end with the suffix are removed.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.removesuffix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tif(title && title.substr(-operator.operand.length) === operator.operand) {\n\t\t\tresults.push(title.substr(0,title.length - operator.operand.length));\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/sameday.js": {
            "title": "$:/core/modules/filters/sameday.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/sameday.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects tiddlers with a modified date field on the same day as the provided value.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.sameday = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldName = operator.suffix || \"modified\",\n\t\ttargetDate = (new Date($tw.utils.parseDate(operator.operand))).setHours(0,0,0,0);\n\t// Function to convert a date/time to a date integer\n\tsource(function(tiddler,title) {\n\t\tif(tiddler) {\n\t\t\tif(tiddler.getFieldDay(fieldName) === targetDate) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/search.js": {
            "title": "$:/core/modules/filters/search.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/search.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for searching for the text in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.search = function(source,operator,options) {\n\tvar invert = operator.prefix === \"!\";\n\tif(operator.suffixes) {\n\t\tvar hasFlag = function(flag) {\n\t\t\t\treturn (operator.suffixes[1] || []).indexOf(flag) !== -1;\n\t\t\t},\n\t\t\texcludeFields = false,\n\t\t\tfieldList = operator.suffixes[0] || [],\n\t\t\tfirstField = fieldList[0] || \"\", \n\t\t\tfirstChar = firstField.charAt(0),\n\t\t\tfields;\n\t\tif(firstChar === \"-\") {\n\t\t\tfields = [firstField.slice(1)].concat(fieldList.slice(1));\n\t\t\texcludeFields = true;\n\t\t} else if(fieldList[0] === \"*\"){\n\t\t\tfields = [];\n\t\t\texcludeFields = true;\n\t\t} else {\n\t\t\tfields = fieldList.slice(0);\n\t\t}\n\t\treturn options.wiki.search(operator.operand,{\n\t\t\tsource: source,\n\t\t\tinvert: invert,\n\t\t\tfield: fields,\n\t\t\texcludeField: excludeFields,\n\t\t\tcaseSensitive: hasFlag(\"casesensitive\"),\n\t\t\tliteral: hasFlag(\"literal\"),\n\t\t\twhitespace: hasFlag(\"whitespace\"),\n\t\t\tanchored: hasFlag(\"anchored\"),\n\t\t\tregexp: hasFlag(\"regexp\"),\n\t\t\twords: hasFlag(\"words\")\n\t\t});\n\t} else {\n\t\treturn options.wiki.search(operator.operand,{\n\t\t\tsource: source,\n\t\t\tinvert: invert\n\t\t});\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/shadowsource.js": {
            "title": "$:/core/modules/filters/shadowsource.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/shadowsource.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the source plugins for shadow tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.shadowsource = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar source = options.wiki.getShadowSource(title);\n\t\tif(source) {\n\t\t\t$tw.utils.pushTop(results,source);\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/sort.js": {
            "title": "$:/core/modules/filters/sort.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/sort.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for sorting\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.sort = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",false,false);\n\treturn results;\n};\n\nexports.nsort = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",false,true);\n\treturn results;\n};\n\nexports.sortan = function(source, operator, options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results, operator.operand || \"title\", operator.prefix === \"!\",false,false,true);\n\treturn results;\n};\n\nexports.sortcs = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",true,false);\n\treturn results;\n};\n\nexports.nsortcs = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",true,true);\n\treturn results;\n};\n\nvar prepare_results = function (source) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/splitbefore.js": {
            "title": "$:/core/modules/filters/splitbefore.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/splitbefore.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that splits each result on the first occurance of the specified separator and returns the unique values.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.splitbefore = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar parts = title.split(operator.operand);\n\t\tif(parts.length === 1) {\n\t\t\t$tw.utils.pushTop(results,parts[0]);\n\t\t} else {\n\t\t\t$tw.utils.pushTop(results,parts[0] + operator.operand);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/storyviews.js": {
            "title": "$:/core/modules/filters/storyviews.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/storyviews.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the story views in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.storyviews = function(source,operator,options) {\n\tvar results = [],\n\t\tstoryviews = {};\n\t$tw.modules.applyMethods(\"storyview\",storyviews);\n\t$tw.utils.each(storyviews,function(info,name) {\n\t\tresults.push(name);\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/strings.js": {
            "title": "$:/core/modules/filters/strings.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/strings.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operators for strings. Unary/binary operators work on each item in turn, and return a new item list.\n\nSum/product/maxall/minall operate on the entire list, returning a single item.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.length = makeStringBinaryOperator(\n\tfunction(a) {return [\"\" + (\"\" + a).length];}\n);\n\nexports.uppercase = makeStringBinaryOperator(\n\tfunction(a) {return [(\"\" + a).toUpperCase()];}\n);\n\nexports.lowercase = makeStringBinaryOperator(\n\tfunction(a) {return [(\"\" + a).toLowerCase()];}\n);\n\nexports.sentencecase = makeStringBinaryOperator(\n\tfunction(a) {return [$tw.utils.toSentenceCase(a)];}\n);\n\nexports.titlecase = makeStringBinaryOperator(\n\tfunction(a) {return [$tw.utils.toTitleCase(a)];}\n);\n\nexports.trim = makeStringBinaryOperator(\n\tfunction(a) {return [$tw.utils.trim(a)];}\n);\n\nexports.split = makeStringBinaryOperator(\n\tfunction(a,b) {return (\"\" + a).split(b);}\n);\n\nexports.join = makeStringReducingOperator(\n\tfunction(accumulator,value,operand) {\n\t\tif(accumulator === null) {\n\t\t\treturn value;\n\t\t} else {\n\t\t\treturn accumulator + operand + value;\n\t\t}\n\t},null\n);\n\nfunction makeStringBinaryOperator(fnCalc) {\n\treturn function(source,operator,options) {\n\t\tvar result = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tArray.prototype.push.apply(result,fnCalc(title,operator.operand || \"\"));\n\t\t});\n\t\treturn result;\n\t};\n}\n\nfunction makeStringReducingOperator(fnCalc,initialValue) {\n\treturn function(source,operator,options) {\n\t\tvar result = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tresult.push(title);\n\t\t});\n\t\treturn [result.reduce(function(accumulator,currentValue) {\n\t\t\treturn fnCalc(accumulator,currentValue,operator.operand || \"\");\n\t\t},initialValue) || \"\"];\n\t};\n}\n\nexports.splitregexp = function(source,operator,options) {\n\tvar result = [],\n\t\tsuffix = operator.suffix || \"\",\n\t\tflags = (suffix.indexOf(\"m\") !== -1 ? \"m\" : \"\") + (suffix.indexOf(\"i\") !== -1 ? \"i\" : \"\"),\n\t\tregExp;\n\ttry {\n\t\tregExp = new RegExp(operator.operand || \"\",flags);\t\t\n\t} catch(ex) {\n\t\treturn [\"RegExp error: \" + ex];\n\t}\n\tsource(function(tiddler,title) {\n\t\tArray.prototype.push.apply(result,title.split(regExp));\n\t});\t\t\n\treturn result;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/subfilter.js": {
            "title": "$:/core/modules/filters/subfilter.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/subfilter.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning its operand evaluated as a filter\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.subfilter = function(source,operator,options) {\n\tvar list = options.wiki.filterTiddlers(operator.operand,options.widget,source);\n\tif(operator.prefix === \"!\") {\n\t\tvar results = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tif(list.indexOf(title) === -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t\treturn results;\n\t} else {\n\t\treturn list;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/subtiddlerfields.js": {
            "title": "$:/core/modules/filters/subtiddlerfields.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/subtiddlerfields.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the fields on the selected subtiddlers of the plugin named in the operand\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.subtiddlerfields = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar subtiddler = options.wiki.getSubTiddler(operator.operand,title);\n\t\tif(subtiddler) {\n\t\t\tfor(var fieldName in subtiddler.fields) {\n\t\t\t\t$tw.utils.pushTop(results,fieldName);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/suffix.js": {
            "title": "$:/core/modules/filters/suffix.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/suffix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking if a title ends with a suffix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.suffix = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(-operator.operand.length) !== operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(-operator.operand.length) === operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/tag.js": {
            "title": "$:/core/modules/filters/tag.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/tag.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking for the presence of a tag\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tag = function(source,operator,options) {\n\tvar results = [],indexedResults;\n\tif((operator.suffix || \"\").toLowerCase() === \"strict\" && !operator.operand) {\n\t\t// New semantics:\n\t\t// Always return copy of input if operator.operand is missing\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.push(title);\n\t\t});\n\t} else {\n\t\t// Old semantics:\n\t\tvar tiddlers;\n\t\tif(operator.prefix === \"!\") {\n\t\t\t// Returns a copy of the input if operator.operand is missing\n\t\t\ttiddlers = options.wiki.getTiddlersWithTag(operator.operand);\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddlers.indexOf(title) === -1) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\t// Returns empty results if operator.operand is missing\n\t\t\tif(source.byTag) {\n\t\t\t\tindexedResults = source.byTag(operator.operand);\n\t\t\t\tif(indexedResults) {\n\t\t\t\t\treturn indexedResults;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttiddlers = options.wiki.getTiddlersWithTag(operator.operand);\n\t\t\t\tsource(function(tiddler,title) {\n\t\t\t\t\tif(tiddlers.indexOf(title) !== -1) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tresults = options.wiki.sortByList(results,operator.operand);\n\t\t\t}\n\t\t}\t\t\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/tagging.js": {
            "title": "$:/core/modules/filters/tagging.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/tagging.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all tiddlers that are tagged with the selected tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tagging = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.getTiddlersWithTag(title));\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/tags.js": {
            "title": "$:/core/modules/filters/tags.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/tags.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all the tags of the selected tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tags = function(source,operator,options) {\n\tvar tags = {};\n\tsource(function(tiddler,title) {\n\t\tvar t, length;\n\t\tif(tiddler && tiddler.fields.tags) {\n\t\t\tfor(t=0, length=tiddler.fields.tags.length; t<length; t++) {\n\t\t\t\ttags[tiddler.fields.tags[t]] = true;\n\t\t\t}\n\t\t}\n\t});\n\treturn Object.keys(tags);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/then.js": {
            "title": "$:/core/modules/filters/then.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/then.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for replacing any titles with a constant\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.then = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(operator.operand);\n\t});\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/title.js": {
            "title": "$:/core/modules/filters/title.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/title.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for comparing title fields for equality\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.title = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && tiddler.fields.title !== operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tresults.push(operator.operand);\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/untagged.js": {
            "title": "$:/core/modules/filters/untagged.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/untagged.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all the selected tiddlers that are untagged\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.untagged = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && $tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length > 0) {\n\t\t\t\t$tw.utils.pushTop(results,title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!tiddler || !tiddler.hasField(\"tags\") || ($tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length === 0)) {\n\t\t\t\t$tw.utils.pushTop(results,title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/variables.js": {
            "title": "$:/core/modules/filters/variables.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/variables.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the active variables\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.variables = function(source,operator,options) {\n\tvar names = [];\n\tfor(var variable in options.widget.variables) {\n\t\tnames.push(variable);\n\t}\n\treturn names.sort();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/wikiparserrules.js": {
            "title": "$:/core/modules/filters/wikiparserrules.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/wikiparserrules.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the wiki parser rules in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.wikiparserrules = function(source,operator,options) {\n\tvar results = [],\n\t\toperand = operator.operand;\n\t$tw.utils.each($tw.modules.types.wikirule,function(mod) {\n\t\tvar exp = mod.exports;\n\t\tif(!operand || exp.types[operand]) {\n\t\t\tresults.push(exp.name);\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters/x-listops.js": {
            "title": "$:/core/modules/filters/x-listops.js",
            "text": "/*\\\ntitle: $:/core/modules/filters/x-listops.js\ntype: application/javascript\nmodule-type: filteroperator\n\nExtended filter operators to manipulate the current list.\n\n\\*/\n(function () {\n\n    /*jslint node: true, browser: true */\n    /*global $tw: false */\n    \"use strict\";\n\n    /*\n    Fetch titles from the current list\n    */\n    var prepare_results = function (source) {\n    var results = [];\n        source(function (tiddler, title) {\n            results.push(title);\n        });\n        return results;\n    };\n\n    /*\n    Moves a number of items from the tail of the current list before the item named in the operand\n    */\n    exports.putbefore = function (source, operator) {\n        var results = prepare_results(source),\n            index = results.indexOf(operator.operand),\n            count = $tw.utils.getInt(operator.suffix,1);\n        return (index === -1) ?\n            results.slice(0, -1) :\n            results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index, -count));\n    };\n\n    /*\n    Moves a number of items from the tail of the current list after the item named in the operand\n    */\n    exports.putafter = function (source, operator) {\n        var results = prepare_results(source),\n            index = results.indexOf(operator.operand),\n            count = $tw.utils.getInt(operator.suffix,1);\n        return (index === -1) ?\n            results.slice(0, -1) :\n            results.slice(0, index + 1).concat(results.slice(-count)).concat(results.slice(index + 1, -count));\n    };\n\n    /*\n    Replaces the item named in the operand with a number of items from the tail of the current list\n    */\n    exports.replace = function (source, operator) {\n        var results = prepare_results(source),\n            index = results.indexOf(operator.operand),\n            count = $tw.utils.getInt(operator.suffix,1);\n        return (index === -1) ?\n            results.slice(0, -count) :\n            results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index + 1, -count));\n    };\n\n    /*\n    Moves a number of items from the tail of the current list to the head of the list\n    */\n    exports.putfirst = function (source, operator) {\n        var results = prepare_results(source),\n            count = $tw.utils.getInt(operator.suffix,1);\n        return results.slice(-count).concat(results.slice(0, -count));\n    };\n\n    /*\n    Moves a number of items from the head of the current list to the tail of the list\n    */\n    exports.putlast = function (source, operator) {\n        var results = prepare_results(source),\n            count = $tw.utils.getInt(operator.suffix,1);\n        return results.slice(count).concat(results.slice(0, count));\n    };\n\n    /*\n    Moves the item named in the operand a number of places forward or backward in the list\n    */\n    exports.move = function (source, operator) {\n        var results = prepare_results(source),\n            index = results.indexOf(operator.operand),\n            count = $tw.utils.getInt(operator.suffix,1),\n            marker = results.splice(index, 1),\n            offset =  (index + count) > 0 ? index + count : 0;\n        return results.slice(0, offset).concat(marker).concat(results.slice(offset));\n    };\n\n    /*\n    Returns the items from the current list that are after the item named in the operand\n    */\n    exports.allafter = function (source, operator) {\n        var results = prepare_results(source),\n            index = results.indexOf(operator.operand);\n        return (index === -1) ? [] :\n            (operator.suffix) ? results.slice(index) :\n            results.slice(index + 1);\n    };\n\n    /*\n    Returns the items from the current list that are before the item named in the operand\n    */\n    exports.allbefore = function (source, operator) {\n        var results = prepare_results(source),\n            index = results.indexOf(operator.operand);\n        return (index === -1) ? [] :\n            (operator.suffix) ? results.slice(0, index + 1) :\n            results.slice(0, index);\n    };\n\n    /*\n    Appends the items listed in the operand array to the tail of the current list\n    */\n    exports.append = function (source, operator) {\n        var append = $tw.utils.parseStringArray(operator.operand, \"true\"),\n            results = prepare_results(source),\n            count = parseInt(operator.suffix) || append.length;\n        return (append.length === 0) ? results :\n            (operator.prefix) ? results.concat(append.slice(-count)) :\n            results.concat(append.slice(0, count));\n    };\n\n    /*\n    Prepends the items listed in the operand array to the head of the current list\n    */\n    exports.prepend = function (source, operator) {\n        var prepend = $tw.utils.parseStringArray(operator.operand, \"true\"),\n            results = prepare_results(source),\n            count = $tw.utils.getInt(operator.suffix,prepend.length);\n        return (prepend.length === 0) ? results :\n            (operator.prefix) ? prepend.slice(-count).concat(results) :\n            prepend.slice(0, count).concat(results);\n    };\n\n    /*\n    Returns all items from the current list except the items listed in the operand array\n    */\n    exports.remove = function (source, operator) {\n        var array = $tw.utils.parseStringArray(operator.operand, \"true\"),\n            results = prepare_results(source),\n            count = parseInt(operator.suffix) || array.length,\n            p,\n            len,\n            index;\n        len = array.length - 1;\n        for (p = 0; p < count; ++p) {\n            if (operator.prefix) {\n                index = results.indexOf(array[len - p]);\n            } else {\n                index = results.indexOf(array[p]);\n            }\n            if (index !== -1) {\n                results.splice(index, 1);\n            }\n        }\n        return results;\n    };\n\n    /*\n    Returns all items from the current list sorted in the order of the items in the operand array\n    */\n    exports.sortby = function (source, operator) {\n        var results = prepare_results(source);\n        if (!results || results.length < 2) {\n            return results;\n        }\n        var lookup = $tw.utils.parseStringArray(operator.operand, \"true\");\n        results.sort(function (a, b) {\n            return lookup.indexOf(a) - lookup.indexOf(b);\n        });\n        return results;\n    };\n\n    /*\n    Removes all duplicate items from the current list\n    */\n    exports.unique = function (source, operator) {\n        var results = prepare_results(source);\n        var set = results.reduce(function (a, b) {\n            if (a.indexOf(b) < 0) {\n                a.push(b);\n            }\n            return a;\n        }, []);\n        return set;\n    };\n})();\n",
            "type": "application/javascript",
            "module-type": "filteroperator"
        },
        "$:/core/modules/filters.js": {
            "title": "$:/core/modules/filters.js",
            "text": "/*\\\ntitle: $:/core/modules/filters.js\ntype: application/javascript\nmodule-type: wikimethod\n\nAdds tiddler filtering methods to the $tw.Wiki object.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nParses an operation (i.e. a run) within a filter string\n\toperators: Array of array of operator nodes into which results should be inserted\n\tfilterString: filter string\n\tp: start position within the string\nReturns the new start position, after the parsed operation\n*/\nfunction parseFilterOperation(operators,filterString,p) {\n\tvar nextBracketPos, operator;\n\t// Skip the starting square bracket\n\tif(filterString.charAt(p++) !== \"[\") {\n\t\tthrow \"Missing [ in filter expression\";\n\t}\n\t// Process each operator in turn\n\tdo {\n\t\toperator = {};\n\t\t// Check for an operator prefix\n\t\tif(filterString.charAt(p) === \"!\") {\n\t\t\toperator.prefix = filterString.charAt(p++);\n\t\t}\n\t\t// Get the operator name\n\t\tnextBracketPos = filterString.substring(p).search(/[\\[\\{<\\/]/);\n\t\tif(nextBracketPos === -1) {\n\t\t\tthrow \"Missing [ in filter expression\";\n\t\t}\n\t\tnextBracketPos += p;\n\t\tvar bracket = filterString.charAt(nextBracketPos);\n\t\toperator.operator = filterString.substring(p,nextBracketPos);\n\t\t// Any suffix?\n\t\tvar colon = operator.operator.indexOf(':');\n\t\tif(colon > -1) {\n\t\t\t// The raw suffix for older filters\n\t\t\toperator.suffix = operator.operator.substring(colon + 1);\n\t\t\toperator.operator = operator.operator.substring(0,colon) || \"field\";\n\t\t\t// The processed suffix for newer filters\n\t\t\toperator.suffixes = [];\n\t\t\t$tw.utils.each(operator.suffix.split(\":\"),function(subsuffix) {\n\t\t\t\toperator.suffixes.push([]);\n\t\t\t\t$tw.utils.each(subsuffix.split(\",\"),function(entry) {\n\t\t\t\t\tentry = $tw.utils.trim(entry);\n\t\t\t\t\tif(entry) {\n\t\t\t\t\t\toperator.suffixes[operator.suffixes.length - 1].push(entry); \n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\t// Empty operator means: title\n\t\telse if(operator.operator === \"\") {\n\t\t\toperator.operator = \"title\";\n\t\t}\n\n\t\tp = nextBracketPos + 1;\n\t\tswitch (bracket) {\n\t\t\tcase \"{\": // Curly brackets\n\t\t\t\toperator.indirect = true;\n\t\t\t\tnextBracketPos = filterString.indexOf(\"}\",p);\n\t\t\t\tbreak;\n\t\t\tcase \"[\": // Square brackets\n\t\t\t\tnextBracketPos = filterString.indexOf(\"]\",p);\n\t\t\t\tbreak;\n\t\t\tcase \"<\": // Angle brackets\n\t\t\t\toperator.variable = true;\n\t\t\t\tnextBracketPos = filterString.indexOf(\">\",p);\n\t\t\t\tbreak;\n\t\t\tcase \"/\": // regexp brackets\n\t\t\t\tvar rex = /^((?:[^\\\\\\/]*|\\\\.)*)\\/(?:\\(([mygi]+)\\))?/g,\n\t\t\t\t\trexMatch = rex.exec(filterString.substring(p));\n\t\t\t\tif(rexMatch) {\n\t\t\t\t\toperator.regexp = new RegExp(rexMatch[1], rexMatch[2]);\n// DEPRECATION WARNING\nconsole.log(\"WARNING: Filter\",operator.operator,\"has a deprecated regexp operand\",operator.regexp);\n\t\t\t\t\tnextBracketPos = p + rex.lastIndex - 1;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthrow \"Unterminated regular expression in filter expression\";\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif(nextBracketPos === -1) {\n\t\t\tthrow \"Missing closing bracket in filter expression\";\n\t\t}\n\t\tif(!operator.regexp) {\n\t\t\toperator.operand = filterString.substring(p,nextBracketPos);\n\t\t}\n\t\tp = nextBracketPos + 1;\n\n\t\t// Push this operator\n\t\toperators.push(operator);\n\t} while(filterString.charAt(p) !== \"]\");\n\t// Skip the ending square bracket\n\tif(filterString.charAt(p++) !== \"]\") {\n\t\tthrow \"Missing ] in filter expression\";\n\t}\n\t// Return the parsing position\n\treturn p;\n}\n\n/*\nParse a filter string\n*/\nexports.parseFilter = function(filterString) {\n\tfilterString = filterString || \"\";\n\tvar results = [], // Array of arrays of operator nodes {operator:,operand:}\n\t\tp = 0, // Current position in the filter string\n\t\tmatch;\n\tvar whitespaceRegExp = /(\\s+)/mg,\n\t\toperandRegExp = /((?:\\+|\\-|~|=)?)(?:(\\[)|(?:\"([^\"]*)\")|(?:'([^']*)')|([^\\s\\[\\]]+))/mg;\n\twhile(p < filterString.length) {\n\t\t// Skip any whitespace\n\t\twhitespaceRegExp.lastIndex = p;\n\t\tmatch = whitespaceRegExp.exec(filterString);\n\t\tif(match && match.index === p) {\n\t\t\tp = p + match[0].length;\n\t\t}\n\t\t// Match the start of the operation\n\t\tif(p < filterString.length) {\n\t\t\toperandRegExp.lastIndex = p;\n\t\t\tmatch = operandRegExp.exec(filterString);\n\t\t\tif(!match || match.index !== p) {\n\t\t\t\tthrow $tw.language.getString(\"Error/FilterSyntax\");\n\t\t\t}\n\t\t\tvar operation = {\n\t\t\t\tprefix: \"\",\n\t\t\t\toperators: []\n\t\t\t};\n\t\t\tif(match[1]) {\n\t\t\t\toperation.prefix = match[1];\n\t\t\t\tp++;\n\t\t\t}\n\t\t\tif(match[2]) { // Opening square bracket\n\t\t\t\tp = parseFilterOperation(operation.operators,filterString,p);\n\t\t\t} else {\n\t\t\t\tp = match.index + match[0].length;\n\t\t\t}\n\t\t\tif(match[3] || match[4] || match[5]) { // Double quoted string, single quoted string or unquoted title\n\t\t\t\toperation.operators.push(\n\t\t\t\t\t{operator: \"title\", operand: match[3] || match[4] || match[5]}\n\t\t\t\t);\n\t\t\t}\n\t\t\tresults.push(operation);\n\t\t}\n\t}\n\treturn results;\n};\n\nexports.getFilterOperators = function() {\n\tif(!this.filterOperators) {\n\t\t$tw.Wiki.prototype.filterOperators = {};\n\t\t$tw.modules.applyMethods(\"filteroperator\",this.filterOperators);\n\t}\n\treturn this.filterOperators;\n};\n\nexports.filterTiddlers = function(filterString,widget,source) {\n\tvar fn = this.compileFilter(filterString);\n\treturn fn.call(this,source,widget);\n};\n\n/*\nCompile a filter into a function with the signature fn(source,widget) where:\nsource: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title)\nwidget: an optional widget node for retrieving the current tiddler etc.\n*/\nexports.compileFilter = function(filterString) {\n\tvar filterParseTree;\n\ttry {\n\t\tfilterParseTree = this.parseFilter(filterString);\n\t} catch(e) {\n\t\treturn function(source,widget) {\n\t\t\treturn [$tw.language.getString(\"Error/Filter\") + \": \" + e];\n\t\t};\n\t}\n\t// Get the hashmap of filter operator functions\n\tvar filterOperators = this.getFilterOperators();\n\t// Assemble array of functions, one for each operation\n\tvar operationFunctions = [];\n\t// Step through the operations\n\tvar self = this;\n\t$tw.utils.each(filterParseTree,function(operation) {\n\t\t// Create a function for the chain of operators in the operation\n\t\tvar operationSubFunction = function(source,widget) {\n\t\t\tvar accumulator = source,\n\t\t\t\tresults = [],\n\t\t\t\tcurrTiddlerTitle = widget && widget.getVariable(\"currentTiddler\");\n\t\t\t$tw.utils.each(operation.operators,function(operator) {\n\t\t\t\tvar operand = operator.operand,\n\t\t\t\t\toperatorFunction;\n\t\t\t\tif(!operator.operator) {\n\t\t\t\t\toperatorFunction = filterOperators.title;\n\t\t\t\t} else if(!filterOperators[operator.operator]) {\n\t\t\t\t\toperatorFunction = filterOperators.field;\n\t\t\t\t} else {\n\t\t\t\t\toperatorFunction = filterOperators[operator.operator];\n\t\t\t\t}\n\t\t\t\tif(operator.indirect) {\n\t\t\t\t\toperand = self.getTextReference(operator.operand,\"\",currTiddlerTitle);\n\t\t\t\t}\n\t\t\t\tif(operator.variable) {\n\t\t\t\t\toperand = widget.getVariable(operator.operand,{defaultValue: \"\"});\n\t\t\t\t}\n\t\t\t\t// Invoke the appropriate filteroperator module\n\t\t\t\tresults = operatorFunction(accumulator,{\n\t\t\t\t\t\t\toperator: operator.operator,\n\t\t\t\t\t\t\toperand: operand,\n\t\t\t\t\t\t\tprefix: operator.prefix,\n\t\t\t\t\t\t\tsuffix: operator.suffix,\n\t\t\t\t\t\t\tsuffixes: operator.suffixes,\n\t\t\t\t\t\t\tregexp: operator.regexp\n\t\t\t\t\t\t},{\n\t\t\t\t\t\t\twiki: self,\n\t\t\t\t\t\t\twidget: widget\n\t\t\t\t\t\t});\n\t\t\t\tif($tw.utils.isArray(results)) {\n\t\t\t\t\taccumulator = self.makeTiddlerIterator(results);\n\t\t\t\t} else {\n\t\t\t\t\taccumulator = results;\n\t\t\t\t}\n\t\t\t});\n\t\t\tif($tw.utils.isArray(results)) {\n\t\t\t\treturn results;\n\t\t\t} else {\n\t\t\t\tvar resultArray = [];\n\t\t\t\tresults(function(tiddler,title) {\n\t\t\t\t\tresultArray.push(title);\n\t\t\t\t});\n\t\t\t\treturn resultArray;\n\t\t\t}\n\t\t};\n\t\t// Wrap the operator functions in a wrapper function that depends on the prefix\n\t\toperationFunctions.push((function() {\n\t\t\tswitch(operation.prefix || \"\") {\n\t\t\t\tcase \"\": // No prefix means that the operation is unioned into the result\n\t\t\t\t\treturn function(results,source,widget) {\n\t\t\t\t\t\t$tw.utils.pushTop(results,operationSubFunction(source,widget));\n\t\t\t\t\t};\n\t\t\t\tcase \"=\": // The results of the operation are pushed into the result without deduplication\n\t\t\t\t\treturn function(results,source,widget) {\n\t\t\t\t\t\tArray.prototype.push.apply(results,operationSubFunction(source,widget));\n\t\t\t\t\t};\n\t\t\t\tcase \"-\": // The results of this operation are removed from the main result\n\t\t\t\t\treturn function(results,source,widget) {\n\t\t\t\t\t\t$tw.utils.removeArrayEntries(results,operationSubFunction(source,widget));\n\t\t\t\t\t};\n\t\t\t\tcase \"+\": // This operation is applied to the main results so far\n\t\t\t\t\treturn function(results,source,widget) {\n\t\t\t\t\t\t// This replaces all the elements of the array, but keeps the actual array so that references to it are preserved\n\t\t\t\t\t\tsource = self.makeTiddlerIterator(results);\n\t\t\t\t\t\tresults.splice(0,results.length);\n\t\t\t\t\t\t$tw.utils.pushTop(results,operationSubFunction(source,widget));\n\t\t\t\t\t};\n\t\t\t\tcase \"~\": // This operation is unioned into the result only if the main result so far is empty\n\t\t\t\t\treturn function(results,source,widget) {\n\t\t\t\t\t\tif(results.length === 0) {\n\t\t\t\t\t\t\t// Main result so far is empty\n\t\t\t\t\t\t\t$tw.utils.pushTop(results,operationSubFunction(source,widget));\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t}\n\t\t})());\n\t});\n\t// Return a function that applies the operations to a source iterator of tiddler titles\n\treturn $tw.perf.measure(\"filter: \" + filterString,function filterFunction(source,widget) {\n\t\tif(!source) {\n\t\t\tsource = self.each;\n\t\t} else if(typeof source === \"object\") { // Array or hashmap\n\t\t\tsource = self.makeTiddlerIterator(source);\n\t\t}\n\t\tvar results = [];\n\t\t$tw.utils.each(operationFunctions,function(operationFunction) {\n\t\t\toperationFunction(results,source,widget);\n\t\t});\n\t\treturn results;\n\t});\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikimethod"
        },
        "$:/core/modules/indexers/backlinks-indexer.js": {
            "title": "$:/core/modules/indexers/backlinks-indexer.js",
            "text": "/*\\\ntitle: $:/core/modules/indexers/backlinks-indexer.js\ntype: application/javascript\nmodule-type: indexer\n\nIndexes the tiddlers' backlinks\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global modules: false */\n\"use strict\";\n\n\nfunction BacklinksIndexer(wiki) {\n\tthis.wiki = wiki;\n}\n\nBacklinksIndexer.prototype.init = function() {\n\tthis.index = null;\n}\n\nBacklinksIndexer.prototype.rebuild = function() {\n\tthis.index = null;\n}\n\nBacklinksIndexer.prototype._getLinks = function(tiddler) {\n\tvar parser =  this.wiki.parseText(tiddler.fields.type, tiddler.fields.text, {});\n\tif(parser) {\n\t\treturn this.wiki.extractLinks(parser.tree);\n\t}\n\treturn [];\n}\n\nBacklinksIndexer.prototype.update = function(updateDescriptor) {\n\tif(!this.index) {\n\t\treturn;\n\t}\n\tvar newLinks = [],\n\t    oldLinks = [],\n\t    self = this;\n\tif(updateDescriptor.old.exists) {\n\t\toldLinks = this._getLinks(updateDescriptor.old.tiddler);\n\t}\n\tif(updateDescriptor.new.exists) {\n\t\tnewLinks = this._getLinks(updateDescriptor.new.tiddler);\n\t}\n\n\t$tw.utils.each(oldLinks,function(link) {\n\t\tif(self.index[link]) {\n\t\t\tdelete self.index[link][updateDescriptor.old.tiddler.fields.title];\n\t\t}\n\t});\n\t$tw.utils.each(newLinks,function(link) {\n\t\tif(!self.index[link]) {\n\t\t\tself.index[link] = Object.create(null);\n\t\t}\n\t\tself.index[link][updateDescriptor.new.tiddler.fields.title] = true;\n\t});\n}\n\nBacklinksIndexer.prototype.lookup = function(title) {\n\tif(!this.index) {\n\t\tthis.index = Object.create(null);\n\t\tvar self = this;\n\t\tthis.wiki.forEachTiddler(function(title,tiddler) {\n\t\t\tvar links = self._getLinks(tiddler);\n\t\t\t$tw.utils.each(links, function(link) {\n\t\t\t\tif(!self.index[link]) {\n\t\t\t\t\tself.index[link] = Object.create(null);\n\t\t\t\t}\n\t\t\t\tself.index[link][title] = true;\n\t\t\t});\n\t\t});\n\t}\n\tif(this.index[title]) {\n\t\treturn Object.keys(this.index[title]);\n\t} else {\n\t\treturn [];\n\t}\n}\n\nexports.BacklinksIndexer = BacklinksIndexer;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "indexer"
        },
        "$:/core/modules/indexers/field-indexer.js": {
            "title": "$:/core/modules/indexers/field-indexer.js",
            "text": "/*\\\ntitle: $:/core/modules/indexers/field-indexer.js\ntype: application/javascript\nmodule-type: indexer\n\nIndexes the tiddlers with each field value\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global modules: false */\n\"use strict\";\n\nvar DEFAULT_MAXIMUM_INDEXED_VALUE_LENGTH = 128;\n\nfunction FieldIndexer(wiki) {\n\tthis.wiki = wiki;\n}\n\nFieldIndexer.prototype.init = function() {\n\tthis.index = null;\n\tthis.maxIndexedValueLength = DEFAULT_MAXIMUM_INDEXED_VALUE_LENGTH;\n\tthis.addIndexMethods();\n}\n\n// Provided for testing\nFieldIndexer.prototype.setMaxIndexedValueLength = function(length) {\n\tthis.index = null;\n\tthis.maxIndexedValueLength = length;\n};\n\nFieldIndexer.prototype.addIndexMethods = function() {\n\tvar self = this;\n\tthis.wiki.each.byField = function(name,value) {\n\t\tvar titles = self.wiki.allTitles(),\n\t\t\tlookup = self.lookup(name,value);\n\t\treturn lookup && lookup.filter(function(title) {\n\t\t\treturn titles.indexOf(title) !== -1;\n\t\t});\n\t};\n\tthis.wiki.eachShadow.byField = function(name,value) {\n\t\tvar titles = self.wiki.allShadowTitles(),\n\t\t\tlookup = self.lookup(name,value);\n\t\treturn lookup && lookup.filter(function(title) {\n\t\t\treturn titles.indexOf(title) !== -1;\n\t\t});\n\t};\n\tthis.wiki.eachTiddlerPlusShadows.byField = function(name,value) {\n\t\tvar lookup = self.lookup(name,value);\n\t\treturn lookup ? lookup.slice(0) : null;\n\t};\n\tthis.wiki.eachShadowPlusTiddlers.byField = function(name,value) {\n\t\tvar lookup = self.lookup(name,value);\n\t\treturn lookup ? lookup.slice(0) : null;\n\t};\n};\n\n/*\nTear down and then rebuild the index as if all tiddlers have changed\n*/\nFieldIndexer.prototype.rebuild = function() {\n\t// Invalidate the index so that it will be rebuilt when it is next used\n\tthis.index = null;\n};\n\n/*\nBuild the index for a particular field\n*/\nFieldIndexer.prototype.buildIndexForField = function(name) {\n\tvar self = this;\n\t// Hashmap by field name of hashmap by field value of array of tiddler titles\n\tthis.index = this.index || Object.create(null);\n\tthis.index[name] = Object.create(null);\n\tvar baseIndex = this.index[name];\n\t// Update the index for each tiddler\n\tthis.wiki.eachTiddlerPlusShadows(function(tiddler,title) {\n\t\tif(name in tiddler.fields) {\n\t\t\tvar value = tiddler.getFieldString(name);\n\t\t\t// Skip any values above the maximum length\n\t\t\tif(value.length < self.maxIndexedValueLength) {\n\t\t\t\tbaseIndex[value] = baseIndex[value] || [];\n\t\t\t\tbaseIndex[value].push(title);\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\nUpdate the index in the light of a tiddler value changing; note that the title must be identical. (Renames are handled as a separate delete and create)\nupdateDescriptor: {old: {tiddler: <tiddler>, shadow: <boolean>, exists: <boolean>},new: {tiddler: <tiddler>, shadow: <boolean>, exists: <boolean>}}\n*/\nFieldIndexer.prototype.update = function(updateDescriptor) {\n\tvar self = this;\n\t// Don't do anything if the index hasn't been built yet\n\tif(this.index === null) {\n\t\treturn;\n\t}\n\t// Remove the old tiddler from the index\n\tif(updateDescriptor.old.tiddler) {\n\t\t$tw.utils.each(this.index,function(indexEntry,name) {\n\t\t\tif(name in updateDescriptor.old.tiddler.fields) {\n\t\t\t\tvar value = updateDescriptor.old.tiddler.getFieldString(name),\n\t\t\t\t\ttiddlerList = indexEntry[value];\n\t\t\t\tif(tiddlerList) {\n\t\t\t\t\tvar index = tiddlerList.indexOf(updateDescriptor.old.tiddler.fields.title);\n\t\t\t\t\tif(index !== -1) {\n\t\t\t\t\t\ttiddlerList.splice(index,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\t// Add the new tiddler to the index\n\tif(updateDescriptor[\"new\"].tiddler) {\n\t\t$tw.utils.each(this.index,function(indexEntry,name) {\n\t\t\tif(name in updateDescriptor[\"new\"].tiddler.fields) {\n\t\t\t\tvar value = updateDescriptor[\"new\"].tiddler.getFieldString(name);\n\t\t\t\tif(value.length < self.maxIndexedValueLength) {\n\t\t\t\t\tindexEntry[value] = indexEntry[value] || [];\n\t\t\t\t\tindexEntry[value].push(updateDescriptor[\"new\"].tiddler.fields.title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\t\t\n\t}\n};\n\n// Lookup the given field returning a list of tiddler titles\nFieldIndexer.prototype.lookup = function(name,value) {\n\t// Fail the lookup if the value is too long\n\tif(value.length >= this.maxIndexedValueLength) {\n\t\treturn null;\n\t}\n\t// Update the index if it has yet to be built\n\tif(this.index === null || !this.index[name]) {\n\t\tthis.buildIndexForField(name);\n\t}\n\treturn this.index[name][value] || [];\n};\n\nexports.FieldIndexer = FieldIndexer;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "indexer"
        },
        "$:/core/modules/indexers/tag-indexer.js": {
            "title": "$:/core/modules/indexers/tag-indexer.js",
            "text": "/*\\\ntitle: $:/core/modules/indexers/tag-indexer.js\ntype: application/javascript\nmodule-type: indexer\n\nIndexes the tiddlers with each tag\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global modules: false */\n\"use strict\";\n\nfunction TagIndexer(wiki) {\n\tthis.wiki = wiki;\n}\n\nTagIndexer.prototype.init = function() {\n\tthis.subIndexers = [\n\t\tnew TagSubIndexer(this,\"each\"),\n\t\tnew TagSubIndexer(this,\"eachShadow\"),\n\t\tnew TagSubIndexer(this,\"eachTiddlerPlusShadows\"),\n\t\tnew TagSubIndexer(this,\"eachShadowPlusTiddlers\")\n\t];\n\t$tw.utils.each(this.subIndexers,function(subIndexer) {\n\t\tsubIndexer.addIndexMethod();\n\t});\n};\n\nTagIndexer.prototype.rebuild = function() {\n\t$tw.utils.each(this.subIndexers,function(subIndexer) {\n\t\tsubIndexer.rebuild();\n\t});\n};\n\nTagIndexer.prototype.update = function(updateDescriptor) {\n\t$tw.utils.each(this.subIndexers,function(subIndexer) {\n\t\tsubIndexer.update(updateDescriptor);\n\t});\n};\n\nfunction TagSubIndexer(indexer,iteratorMethod) {\n\tthis.indexer = indexer;\n\tthis.iteratorMethod = iteratorMethod;\n\tthis.index = null; // Hashmap of tag title to {isSorted: bool, titles: [array]} or null if not yet initialised\n}\n\nTagSubIndexer.prototype.addIndexMethod = function() {\n\tvar self = this;\n\tthis.indexer.wiki[this.iteratorMethod].byTag = function(tag) {\n\t\treturn self.lookup(tag).slice(0);\n\t};\n};\n\nTagSubIndexer.prototype.rebuild = function() {\n\tvar self = this;\n\t// Hashmap by tag of array of {isSorted:, titles:[]}\n\tthis.index = Object.create(null);\n\t// Add all the tags\n\tthis.indexer.wiki[this.iteratorMethod](function(tiddler,title) {\n\t\t$tw.utils.each(tiddler.fields.tags,function(tag) {\n\t\t\tif(!self.index[tag]) {\n\t\t\t\tself.index[tag] = {isSorted: false, titles: [title]};\n\t\t\t} else {\n\t\t\t\tself.index[tag].titles.push(title);\n\t\t\t}\n\t\t});\t\t\n\t});\n};\n\nTagSubIndexer.prototype.update = function(updateDescriptor) {\n\tthis.index = null;\n};\n\nTagSubIndexer.prototype.lookup = function(tag) {\n\t// Update the index if it has yet to be built\n\tif(this.index === null) {\n\t\tthis.rebuild();\n\t}\n\tvar indexRecord = this.index[tag];\n\tif(indexRecord) {\n\t\tif(!indexRecord.isSorted) {\n\t\t\tif(this.indexer.wiki.sortByList) {\n\t\t\t\tindexRecord.titles = this.indexer.wiki.sortByList(indexRecord.titles,tag);\n\t\t\t}\t\t\t\n\t\t\tindexRecord.isSorted = true;\n\t\t}\n\t\treturn indexRecord.titles;\n\t} else {\n\t\treturn [];\n\t}\n};\n\n\nexports.TagIndexer = TagIndexer;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "indexer"
        },
        "$:/core/modules/info/platform.js": {
            "title": "$:/core/modules/info/platform.js",
            "text": "/*\\\ntitle: $:/core/modules/info/platform.js\ntype: application/javascript\nmodule-type: info\n\nInitialise basic platform $:/info/ tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.getInfoTiddlerFields = function() {\n\tvar mapBoolean = function(value) {return value ? \"yes\" : \"no\";},\n\t\tinfoTiddlerFields = [];\n\t// Basics\n\tinfoTiddlerFields.push({title: \"$:/info/browser\", text: mapBoolean(!!$tw.browser)});\n\tinfoTiddlerFields.push({title: \"$:/info/node\", text: mapBoolean(!!$tw.node)});\n\tif($tw.browser) {\n\t\t// Document location\n\t\tvar setLocationProperty = function(name,value) {\n\t\t\t\tinfoTiddlerFields.push({title: \"$:/info/url/\" + name, text: value});\t\t\t\n\t\t\t},\n\t\t\tlocation = document.location;\n\t\tsetLocationProperty(\"full\", (location.toString()).split(\"#\")[0]);\n\t\tsetLocationProperty(\"host\", location.host);\n\t\tsetLocationProperty(\"hostname\", location.hostname);\n\t\tsetLocationProperty(\"protocol\", location.protocol);\n\t\tsetLocationProperty(\"port\", location.port);\n\t\tsetLocationProperty(\"pathname\", location.pathname);\n\t\tsetLocationProperty(\"search\", location.search);\n\t\tsetLocationProperty(\"origin\", location.origin);\n\t\t// Screen size\n\t\tinfoTiddlerFields.push({title: \"$:/info/browser/screen/width\", text: window.screen.width.toString()});\n\t\tinfoTiddlerFields.push({title: \"$:/info/browser/screen/height\", text: window.screen.height.toString()});\n\t\t// Language\n\t\tinfoTiddlerFields.push({title: \"$:/info/browser/language\", text: navigator.language || \"\"});\n\t}\n\treturn infoTiddlerFields;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "info"
        },
        "$:/core/modules/keyboard.js": {
            "title": "$:/core/modules/keyboard.js",
            "text": "/*\\\ntitle: $:/core/modules/keyboard.js\ntype: application/javascript\nmodule-type: global\n\nKeyboard handling utilities\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar namedKeys = {\n\t\"cancel\": 3,\n\t\"help\": 6,\n\t\"backspace\": 8,\n\t\"tab\": 9,\n\t\"clear\": 12,\n\t\"return\": 13,\n\t\"enter\": 13,\n\t\"pause\": 19,\n\t\"escape\": 27,\n\t\"space\": 32,\n\t\"page_up\": 33,\n\t\"page_down\": 34,\n\t\"end\": 35,\n\t\"home\": 36,\n\t\"left\": 37,\n\t\"up\": 38,\n\t\"right\": 39,\n\t\"down\": 40,\n\t\"printscreen\": 44,\n\t\"insert\": 45,\n\t\"delete\": 46,\n\t\"0\": 48,\n\t\"1\": 49,\n\t\"2\": 50,\n\t\"3\": 51,\n\t\"4\": 52,\n\t\"5\": 53,\n\t\"6\": 54,\n\t\"7\": 55,\n\t\"8\": 56,\n\t\"9\": 57,\n\t\"firefoxsemicolon\": 59,\n\t\"firefoxequals\": 61,\n\t\"a\": 65,\n\t\"b\": 66,\n\t\"c\": 67,\n\t\"d\": 68,\n\t\"e\": 69,\n\t\"f\": 70,\n\t\"g\": 71,\n\t\"h\": 72,\n\t\"i\": 73,\n\t\"j\": 74,\n\t\"k\": 75,\n\t\"l\": 76,\n\t\"m\": 77,\n\t\"n\": 78,\n\t\"o\": 79,\n\t\"p\": 80,\n\t\"q\": 81,\n\t\"r\": 82,\n\t\"s\": 83,\n\t\"t\": 84,\n\t\"u\": 85,\n\t\"v\": 86,\n\t\"w\": 87,\n\t\"x\": 88,\n\t\"y\": 89,\n\t\"z\": 90,\n\t\"numpad0\": 96,\n\t\"numpad1\": 97,\n\t\"numpad2\": 98,\n\t\"numpad3\": 99,\n\t\"numpad4\": 100,\n\t\"numpad5\": 101,\n\t\"numpad6\": 102,\n\t\"numpad7\": 103,\n\t\"numpad8\": 104,\n\t\"numpad9\": 105,\n\t\"multiply\": 106,\n\t\"add\": 107,\n\t\"separator\": 108,\n\t\"subtract\": 109,\n\t\"decimal\": 110,\n\t\"divide\": 111,\n\t\"f1\": 112,\n\t\"f2\": 113,\n\t\"f3\": 114,\n\t\"f4\": 115,\n\t\"f5\": 116,\n\t\"f6\": 117,\n\t\"f7\": 118,\n\t\"f8\": 119,\n\t\"f9\": 120,\n\t\"f10\": 121,\n\t\"f11\": 122,\n\t\"f12\": 123,\n\t\"f13\": 124,\n\t\"f14\": 125,\n\t\"f15\": 126,\n\t\"f16\": 127,\n\t\"f17\": 128,\n\t\"f18\": 129,\n\t\"f19\": 130,\n\t\"f20\": 131,\n\t\"f21\": 132,\n\t\"f22\": 133,\n\t\"f23\": 134,\n\t\"f24\": 135,\n\t\"firefoxminus\": 173,\n\t\"semicolon\": 186,\n\t\"equals\": 187,\n\t\"comma\": 188,\n\t\"dash\": 189,\n\t\"period\": 190,\n\t\"slash\": 191,\n\t\"backquote\": 192,\n\t\"openbracket\": 219,\n\t\"backslash\": 220,\n\t\"closebracket\": 221,\n\t\"quote\": 222\n};\n\nfunction KeyboardManager(options) {\n\tvar self = this;\n\toptions = options || \"\";\n\t// Save the named key hashmap\n\tthis.namedKeys = namedKeys;\n\t// Create a reverse mapping of code to keyname\n\tthis.keyNames = [];\n\t$tw.utils.each(namedKeys,function(keyCode,name) {\n\t\tself.keyNames[keyCode] = name.substr(0,1).toUpperCase() + name.substr(1);\n\t});\n\t// Save the platform-specific name of the \"meta\" key\n\tthis.metaKeyName = $tw.platform.isMac ? \"cmd-\" : \"win-\";\n\tthis.shortcutKeysList = [], // Stores the shortcut-key descriptors\n\tthis.shortcutActionList = [], // Stores the corresponding action strings\n\tthis.shortcutParsedList = []; // Stores the parsed key descriptors\n\tthis.lookupNames = [\"shortcuts\"];\n\tthis.lookupNames.push($tw.platform.isMac ? \"shortcuts-mac\" : \"shortcuts-not-mac\")\n\tthis.lookupNames.push($tw.platform.isWindows ? \"shortcuts-windows\" : \"shortcuts-not-windows\");\n\tthis.lookupNames.push($tw.platform.isLinux ? \"shortcuts-linux\" : \"shortcuts-not-linux\");\n\tthis.updateShortcutLists(this.getShortcutTiddlerList());\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tself.handleShortcutChanges(changes);\n\t});\n}\n\n/*\nReturn an array of keycodes for the modifier keys ctrl, shift, alt, meta\n*/\nKeyboardManager.prototype.getModifierKeys = function() {\n\treturn [\n\t\t16, // Shift\n\t\t17, // Ctrl\n\t\t18, // Alt\n\t\t20, // CAPS LOCK\n\t\t91, // Meta (left)\n\t\t93, // Meta (right)\n\t\t224 // Meta (Firefox)\n\t]\n};\n\n/*\nParses a key descriptor into the structure:\n{\n\tkeyCode: numeric keycode\n\tshiftKey: boolean\n\taltKey: boolean\n\tctrlKey: boolean\n\tmetaKey: boolean\n}\nKey descriptors have the following format:\n\tctrl+enter\n\tctrl+shift+alt+A\n*/\nKeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor) {\n\tvar components = keyDescriptor.split(/\\+|\\-/),\n\t\tinfo = {\n\t\t\tkeyCode: 0,\n\t\t\tshiftKey: false,\n\t\t\taltKey: false,\n\t\t\tctrlKey: false,\n\t\t\tmetaKey: false\n\t\t};\n\tfor(var t=0; t<components.length; t++) {\n\t\tvar s = components[t].toLowerCase(),\n\t\t\tc = s.charCodeAt(0);\n\t\t// Look for modifier keys\n\t\tif(s === \"ctrl\") {\n\t\t\tinfo.ctrlKey = true;\n\t\t} else if(s === \"shift\") {\n\t\t\tinfo.shiftKey = true;\n\t\t} else if(s === \"alt\") {\n\t\t\tinfo.altKey = true;\n\t\t} else if(s === \"meta\" || s === \"cmd\" || s === \"win\") {\n\t\t\tinfo.metaKey = true;\n\t\t}\n\t\t// Replace named keys with their code\n\t\tif(this.namedKeys[s]) {\n\t\t\tinfo.keyCode = this.namedKeys[s];\n\t\t}\n\t}\n\tif(info.keyCode) {\n\t\treturn info;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nParse a list of key descriptors into an array of keyInfo objects. The key descriptors can be passed as an array of strings or a space separated string\n*/\nKeyboardManager.prototype.parseKeyDescriptors = function(keyDescriptors,options) {\n\tvar self = this;\n\toptions = options || {};\n\toptions.stack = options.stack || [];\n\tvar wiki = options.wiki || $tw.wiki;\n\tif(typeof keyDescriptors === \"string\" && keyDescriptors === \"\") {\n\t\treturn [];\n\t}\n\tif(!$tw.utils.isArray(keyDescriptors)) {\n\t\tkeyDescriptors = keyDescriptors.split(\" \");\n\t}\n\tvar result = [];\n\t$tw.utils.each(keyDescriptors,function(keyDescriptor) {\n\t\t// Look for a named shortcut\n\t\tif(keyDescriptor.substr(0,2) === \"((\" && keyDescriptor.substr(-2,2) === \"))\") {\n\t\t\tif(options.stack.indexOf(keyDescriptor) === -1) {\n\t\t\t\toptions.stack.push(keyDescriptor);\n\t\t\t\tvar name = keyDescriptor.substring(2,keyDescriptor.length - 2),\n\t\t\t\t\tlookupName = function(configName) {\n\t\t\t\t\t\tvar keyDescriptors = wiki.getTiddlerText(\"$:/config/\" + configName + \"/\" + name);\n\t\t\t\t\t\tif(keyDescriptors) {\n\t\t\t\t\t\t\tresult.push.apply(result,self.parseKeyDescriptors(keyDescriptors,options));\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t$tw.utils.each(self.lookupNames,function(platformDescriptor) {\n\t\t\t\t\tlookupName(platformDescriptor);\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tresult.push(self.parseKeyDescriptor(keyDescriptor));\n\t\t}\n\t});\n\treturn result;\n};\n\nKeyboardManager.prototype.getPrintableShortcuts = function(keyInfoArray) {\n\tvar self = this,\n\t\tresult = [];\n\t$tw.utils.each(keyInfoArray,function(keyInfo) {\n\t\tif(keyInfo) {\n\t\t\tresult.push((keyInfo.ctrlKey ? \"ctrl-\" : \"\") + \n\t\t\t\t   (keyInfo.shiftKey ? \"shift-\" : \"\") + \n\t\t\t\t   (keyInfo.altKey ? \"alt-\" : \"\") + \n\t\t\t\t   (keyInfo.metaKey ? self.metaKeyName : \"\") + \n\t\t\t\t   (self.keyNames[keyInfo.keyCode]));\n\t\t}\n\t});\n\treturn result;\n}\n\nKeyboardManager.prototype.checkKeyDescriptor = function(event,keyInfo) {\n\treturn keyInfo &&\n\t\t\tevent.keyCode === keyInfo.keyCode && \n\t\t\tevent.shiftKey === keyInfo.shiftKey && \n\t\t\tevent.altKey === keyInfo.altKey && \n\t\t\tevent.ctrlKey === keyInfo.ctrlKey && \n\t\t\tevent.metaKey === keyInfo.metaKey;\n};\n\nKeyboardManager.prototype.checkKeyDescriptors = function(event,keyInfoArray) {\n\tfor(var t=0; t<keyInfoArray.length; t++) {\n\t\tif(this.checkKeyDescriptor(event,keyInfoArray[t])) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\nKeyboardManager.prototype.getShortcutTiddlerList = function() {\n\treturn $tw.wiki.getTiddlersWithTag(\"$:/tags/KeyboardShortcut\");\n};\n\nKeyboardManager.prototype.updateShortcutLists = function(tiddlerList) {\n\tthis.shortcutTiddlers = tiddlerList;\n\tfor(var i=0; i<tiddlerList.length; i++) {\n\t\tvar title = tiddlerList[i],\n\t\t\ttiddlerFields = $tw.wiki.getTiddler(title).fields;\n\t\tthis.shortcutKeysList[i] = tiddlerFields.key !== undefined ? tiddlerFields.key : undefined;\n\t\tthis.shortcutActionList[i] = tiddlerFields.text;\n\t\tthis.shortcutParsedList[i] = this.shortcutKeysList[i] !== undefined ? this.parseKeyDescriptors(this.shortcutKeysList[i]) : undefined;\n\t}\n};\n\nKeyboardManager.prototype.handleKeydownEvent = function(event) {\n\tvar key, action;\n\tfor(var i=0; i<this.shortcutTiddlers.length; i++) {\n\t\tif(this.shortcutParsedList[i] !== undefined && this.checkKeyDescriptors(event,this.shortcutParsedList[i])) {\n\t\t\tkey = this.shortcutParsedList[i];\n\t\t\taction = this.shortcutActionList[i];\n\t\t}\n\t}\n\tif(key !== undefined) {\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\t$tw.rootWidget.invokeActionString(action,$tw.rootWidget);\n\t\treturn true;\n\t}\n\treturn false;\n};\n\nKeyboardManager.prototype.detectNewShortcuts = function(changedTiddlers) {\n\tvar shortcutConfigTiddlers = [],\n\t\thandled = false;\n\t$tw.utils.each(this.lookupNames,function(platformDescriptor) {\n\t\tvar descriptorString = \"$:/config/\" + platformDescriptor + \"/\";\n\t\tObject.keys(changedTiddlers).forEach(function(configTiddler) {\n\t\t\tvar configString = configTiddler.substr(0, configTiddler.lastIndexOf(\"/\") + 1);\n\t\t\tif(configString === descriptorString) {\n\t\t\t\tshortcutConfigTiddlers.push(configTiddler);\n\t\t\t\thandled = true;\n\t\t\t}\n\t\t});\n\t});\n\tif(handled) {\n\t\treturn $tw.utils.hopArray(changedTiddlers,shortcutConfigTiddlers);\n\t} else {\n\t\treturn false;\n\t}\n};\n\nKeyboardManager.prototype.handleShortcutChanges = function(changedTiddlers) {\n\tvar newList = this.getShortcutTiddlerList();\n\tvar hasChanged = $tw.utils.hopArray(changedTiddlers,this.shortcutTiddlers) ? true :\n\t\t($tw.utils.hopArray(changedTiddlers,newList) ? true :\n\t\t(this.detectNewShortcuts(changedTiddlers))\n\t);\n\t// Re-cache shortcuts if something changed\n\tif(hasChanged) {\n\t\tthis.updateShortcutLists(newList);\n\t}\n};\n\nexports.KeyboardManager = KeyboardManager;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/language.js": {
            "title": "$:/core/modules/language.js",
            "text": "/*\\\ntitle: $:/core/modules/language.js\ntype: application/javascript\nmodule-type: global\n\nThe $tw.Language() manages translateable strings\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nCreate an instance of the language manager. Options include:\nwiki: wiki from which to retrieve translation tiddlers\n*/\nfunction Language(options) {\n\toptions = options || \"\";\n\tthis.wiki = options.wiki || $tw.wiki;\n}\n\n/*\nReturn a wikified translateable string. The title is automatically prefixed with \"$:/language/\"\nOptions include:\nvariables: optional hashmap of variables to supply to the language wikification\n*/\nLanguage.prototype.getString = function(title,options) {\n\toptions = options || {};\n\ttitle = \"$:/language/\" + title;\n\treturn this.wiki.renderTiddler(\"text/plain\",title,{variables: options.variables});\n};\n\n/*\nReturn a raw, unwikified translateable string. The title is automatically prefixed with \"$:/language/\"\n*/\nLanguage.prototype.getRawString = function(title) {\n\ttitle = \"$:/language/\" + title;\n\treturn this.wiki.getTiddlerText(title);\n};\n\nexports.Language = Language;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/macros/changecount.js": {
            "title": "$:/core/modules/macros/changecount.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/changecount.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to return the changecount for the current tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"changecount\";\n\nexports.params = [];\n\n/*\nRun the macro\n*/\nexports.run = function() {\n\treturn this.wiki.getChangeCount(this.getVariable(\"currentTiddler\")) + \"\";\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/contrastcolour.js": {
            "title": "$:/core/modules/macros/contrastcolour.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/contrastcolour.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to choose which of two colours has the highest contrast with a base colour\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"contrastcolour\";\n\nexports.params = [\n\t{name: \"target\"},\n\t{name: \"fallbackTarget\"},\n\t{name: \"colourA\"},\n\t{name: \"colourB\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(target,fallbackTarget,colourA,colourB) {\n\tvar rgbTarget = $tw.utils.parseCSSColor(target) || $tw.utils.parseCSSColor(fallbackTarget);\n\tif(!rgbTarget) {\n\t\treturn colourA;\n\t}\n\tvar rgbColourA = $tw.utils.parseCSSColor(colourA),\n\t\trgbColourB = $tw.utils.parseCSSColor(colourB);\n\tif(rgbColourA && !rgbColourB) {\n\t\treturn rgbColourA;\n\t}\n\tif(rgbColourB && !rgbColourA) {\n\t\treturn rgbColourB;\n\t}\n\tif(!rgbColourA && !rgbColourB) {\n\t\t// If neither colour is readable, return a crude inverse of the target\n\t\treturn [255 - rgbTarget[0],255 - rgbTarget[1],255 - rgbTarget[2],rgbTarget[3]];\n\t}\n\t// Colour brightness formula derived from http://www.w3.org/WAI/ER/WD-AERT/#color-contrast\n\tvar brightnessTarget = rgbTarget[0] * 0.299 + rgbTarget[1] * 0.587 + rgbTarget[2] * 0.114,\n\t\tbrightnessA = rgbColourA[0] * 0.299 + rgbColourA[1] * 0.587 + rgbColourA[2] * 0.114,\n\t\tbrightnessB = rgbColourB[0] * 0.299 + rgbColourB[1] * 0.587 + rgbColourB[2] * 0.114;\n\treturn Math.abs(brightnessTarget - brightnessA) > Math.abs(brightnessTarget - brightnessB) ? colourA : colourB;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/csvtiddlers.js": {
            "title": "$:/core/modules/macros/csvtiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/csvtiddlers.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to output tiddlers matching a filter to CSV\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"csvtiddlers\";\n\nexports.params = [\n\t{name: \"filter\"},\n\t{name: \"format\"},\n];\n\n/*\nRun the macro\n*/\nexports.run = function(filter,format) {\n\tvar self = this,\n\t\ttiddlers = this.wiki.filterTiddlers(filter),\n\t\ttiddler,\n\t\tfields = [],\n\t\tt,f;\n\t// Collect all the fields\n\tfor(t=0;t<tiddlers.length; t++) {\n\t\ttiddler = this.wiki.getTiddler(tiddlers[t]);\n\t\tfor(f in tiddler.fields) {\n\t\t\tif(fields.indexOf(f) === -1) {\n\t\t\t\tfields.push(f);\n\t\t\t}\n\t\t}\n\t}\n\t// Sort the fields and bring the standard ones to the front\n\tfields.sort();\n\t\"title text modified modifier created creator\".split(\" \").reverse().forEach(function(value,index) {\n\t\tvar p = fields.indexOf(value);\n\t\tif(p !== -1) {\n\t\t\tfields.splice(p,1);\n\t\t\tfields.unshift(value)\n\t\t}\n\t});\n\t// Output the column headings\n\tvar output = [], row = [];\n\tfields.forEach(function(value) {\n\t\trow.push(quoteAndEscape(value))\n\t});\n\toutput.push(row.join(\",\"));\n\t// Output each tiddler\n\tfor(var t=0;t<tiddlers.length; t++) {\n\t\trow = [];\n\t\ttiddler = this.wiki.getTiddler(tiddlers[t]);\n\t\t\tfor(f=0; f<fields.length; f++) {\n\t\t\t\trow.push(quoteAndEscape(tiddler ? tiddler.getFieldString(fields[f]) || \"\" : \"\"));\n\t\t\t}\n\t\toutput.push(row.join(\",\"));\n\t}\n\treturn output.join(\"\\n\");\n};\n\nfunction quoteAndEscape(value) {\n\treturn \"\\\"\" + value.replace(/\"/mg,\"\\\"\\\"\") + \"\\\"\";\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/displayshortcuts.js": {
            "title": "$:/core/modules/macros/displayshortcuts.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/displayshortcuts.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to display a list of keyboard shortcuts in human readable form. Notably, it resolves named shortcuts like `((bold))` to the underlying keystrokes.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"displayshortcuts\";\n\nexports.params = [\n\t{name: \"shortcuts\"},\n\t{name: \"prefix\"},\n\t{name: \"separator\"},\n\t{name: \"suffix\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(shortcuts,prefix,separator,suffix) {\n\tvar shortcutArray = $tw.keyboardManager.getPrintableShortcuts($tw.keyboardManager.parseKeyDescriptors(shortcuts,{\n\t\twiki: this.wiki\n\t}));\n\tif(shortcutArray.length > 0) {\n\t\tshortcutArray.sort(function(a,b) {\n\t\t    return a.toLowerCase().localeCompare(b.toLowerCase());\n\t\t})\n\t\treturn prefix + shortcutArray.join(separator) + suffix;\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/jsontiddler.js": {
            "title": "$:/core/modules/macros/jsontiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/jsontiddler.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to output a single tiddler to JSON\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"jsontiddler\";\n\nexports.params = [\n\t{name: \"title\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(title) {\n\ttitle = title || this.getVariable(\"currentTiddler\");\n\tvar tiddler = !!title && this.wiki.getTiddler(title),\n\t\tfields = new Object();\n\tif(tiddler) {\n\t\tfor(var field in tiddler.fields) {\n\t\t\tfields[field] = tiddler.getFieldString(field);\n\t\t}\n\t}\n\treturn JSON.stringify(fields,null,$tw.config.preferences.jsonSpaces);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/jsontiddlers.js": {
            "title": "$:/core/modules/macros/jsontiddlers.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/jsontiddlers.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to output tiddlers matching a filter to JSON\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"jsontiddlers\";\n\nexports.params = [\n\t{name: \"filter\"},\n\t{name: \"spaces\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(filter,spaces) {\n\treturn this.wiki.getTiddlersAsJson(filter,$tw.utils.parseInt(spaces));\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/makedatauri.js": {
            "title": "$:/core/modules/macros/makedatauri.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/makedatauri.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to convert a string of text to a data URI\n\n<<makedatauri text:\"Text to be converted\" type:\"text/vnd.tiddlywiki\">>\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"makedatauri\";\n\nexports.params = [\n\t{name: \"text\"},\n\t{name: \"type\"},\n\t{name: \"_canonical_uri\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(text,type,_canonical_uri) {\n\treturn $tw.utils.makeDataUri(text,type,_canonical_uri);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/now.js": {
            "title": "$:/core/modules/macros/now.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/now.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to return a formatted version of the current time\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"now\";\n\nexports.params = [\n\t{name: \"format\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(format) {\n\treturn $tw.utils.formatDateString(new Date(),format || \"0hh:0mm, DDth MMM YYYY\");\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/qualify.js": {
            "title": "$:/core/modules/macros/qualify.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/qualify.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to qualify a state tiddler title according\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"qualify\";\n\nexports.params = [\n\t{name: \"title\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(title) {\n\treturn title + \"-\" + this.getStateQualifier();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/resolvepath.js": {
            "title": "$:/core/modules/macros/resolvepath.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/resolvepath.js\ntype: application/javascript\nmodule-type: macro\n\nResolves a relative path for an absolute rootpath.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"resolvepath\";\n\nexports.params = [\n\t{name: \"source\"},\n\t{name: \"root\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(source, root) {\n\treturn $tw.utils.resolvePath(source, root);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/unusedtitle.js": {
            "title": "$:/core/modules/macros/unusedtitle.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/unusedtitle.js\ntype: application/javascript\nmodule-type: macro\nMacro to return a new title that is unused in the wiki. It can be given a name as a base.\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"unusedtitle\";\n\nexports.params = [\n\t{name: \"baseName\"},\n\t{name: \"options\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(baseName, options) {\n\tif(!baseName) {\n\t\tbaseName = $tw.language.getString(\"DefaultNewTiddlerTitle\");\n\t}\n\treturn this.wiki.generateNewTitle(baseName, options);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/macros/version.js": {
            "title": "$:/core/modules/macros/version.js",
            "text": "/*\\\ntitle: $:/core/modules/macros/version.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to return the TiddlyWiki core version number\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"version\";\n\nexports.params = [];\n\n/*\nRun the macro\n*/\nexports.run = function() {\n\treturn $tw.version;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "macro"
        },
        "$:/core/modules/parsers/audioparser.js": {
            "title": "$:/core/modules/parsers/audioparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/audioparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe audio parser parses an audio tiddler into an embeddable HTML element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar AudioParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"audio\",\n\t\t\tattributes: {\n\t\t\t\tcontrols: {type: \"string\", value: \"controls\"},\n\t\t\t\tstyle: {type: \"string\", value: \"width: 100%; object-fit: contain\"}\n\t\t\t}\n\t\t},\n\t\tsrc;\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\telement.attributes.src = {type: \"string\", value: \"data:\" + type + \";base64,\" + text};\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"audio/ogg\"] = AudioParser;\nexports[\"audio/mpeg\"] = AudioParser;\nexports[\"audio/mp3\"] = AudioParser;\nexports[\"audio/mp4\"] = AudioParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/binaryparser.js": {
            "title": "$:/core/modules/parsers/binaryparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/binaryparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe binary parser parses a binary tiddler into a warning message and download link\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar BINARY_WARNING_MESSAGE = \"$:/core/ui/BinaryWarning\";\nvar EXPORT_BUTTON_IMAGE = \"$:/core/images/export-button\";\n\nvar BinaryParser = function(type,text,options) {\n\t// Transclude the binary data tiddler warning message\n\tvar warn = {\n\t\ttype: \"element\",\n\t\ttag: \"p\",\n\t\tchildren: [{\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: BINARY_WARNING_MESSAGE}\n\t\t\t}\n\t\t}]\n\t};\n\t// Create download link based on binary tiddler title\n\tvar link = {\n\t\ttype: \"element\",\n\t\ttag: \"a\",\n\t\tattributes: {\n\t\t\ttitle: {type: \"indirect\", textReference: \"!!title\"},\n\t\t\tdownload: {type: \"indirect\", textReference: \"!!title\"}\n\t\t},\n\t\tchildren: [{\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: EXPORT_BUTTON_IMAGE}\n\t\t\t}\n\t\t}]\n\t};\n\t// Set the link href to external or internal data URI\n\tif(options._canonical_uri) {\n\t\tlink.attributes.href = {\n\t\t\ttype: \"string\", \n\t\t\tvalue: options._canonical_uri\n\t\t};\n\t} else if(text) {\n\t\tlink.attributes.href = {\n\t\t\ttype: \"string\", \n\t\t\tvalue: \"data:\" + type + \";base64,\" + text\n\t\t};\n\t}\n\t// Combine warning message and download link in a div\n\tvar element = {\n\t\ttype: \"element\",\n\t\ttag: \"div\",\n\t\tattributes: {\n\t\t\tclass: {type: \"string\", value: \"tc-binary-warning\"}\n\t\t},\n\t\tchildren: [warn, link]\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"application/octet-stream\"] = BinaryParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/csvparser.js": {
            "title": "$:/core/modules/parsers/csvparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/csvparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe CSV text parser processes CSV files into a table wrapped in a scrollable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar CsvParser = function(type,text,options) {\n\t// Table framework\n\tthis.tree = [{\n\t\t\"type\": \"scrollable\", \"children\": [{\n\t\t\t\"type\": \"element\", \"tag\": \"table\", \"children\": [{\n\t\t\t\t\"type\": \"element\", \"tag\": \"tbody\", \"children\": []\n\t\t\t}], \"attributes\": {\n\t\t\t\t\"class\": {\"type\": \"string\", \"value\": \"tc-csv-table\"}\n\t\t\t}\n\t\t}]\n\t}];\n\t// Split the text into lines\n\tvar lines = text.split(/\\r?\\n/mg),\n\t\ttag = \"th\";\n\tfor(var line=0; line<lines.length; line++) {\n\t\tvar lineText = lines[line];\n\t\tif(lineText) {\n\t\t\tvar row = {\n\t\t\t\t\t\"type\": \"element\", \"tag\": \"tr\", \"children\": []\n\t\t\t\t};\n\t\t\tvar columns = lineText.split(\",\");\n\t\t\tfor(var column=0; column<columns.length; column++) {\n\t\t\t\trow.children.push({\n\t\t\t\t\t\t\"type\": \"element\", \"tag\": tag, \"children\": [{\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": columns[column]\n\t\t\t\t\t\t}]\n\t\t\t\t\t});\n\t\t\t}\n\t\t\ttag = \"td\";\n\t\t\tthis.tree[0].children[0].children[0].children.push(row);\n\t\t}\n\t}\n};\n\nexports[\"text/csv\"] = CsvParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/htmlparser.js": {
            "title": "$:/core/modules/parsers/htmlparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/htmlparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe HTML parser displays text as raw HTML\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar HtmlParser = function(type,text,options) {\n\tvar src;\n\tif(options._canonical_uri) {\n\t\tsrc = options._canonical_uri;\n\t} else if(text) {\n\t\tsrc = \"data:text/html;charset=utf-8,\" + encodeURIComponent(text);\n\t}\n\tthis.tree = [{\n\t\ttype: \"element\",\n\t\ttag: \"iframe\",\n\t\tattributes: {\n\t\t\tsrc: {type: \"string\", value: src},\n\t\t\tsandbox: {type: \"string\", value: \"\"}\n\t\t}\n\t}];\n};\n\nexports[\"text/html\"] = HtmlParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/imageparser.js": {
            "title": "$:/core/modules/parsers/imageparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/imageparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe image parser parses an image into an embeddable HTML element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar ImageParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"img\",\n\t\t\tattributes: {}\n\t\t};\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\tif(type === \"image/svg+xml\" || type === \".svg\") {\n\t\t\telement.attributes.src = {type: \"string\", value: \"data:image/svg+xml,\" + encodeURIComponent(text)};\n\t\t} else {\n\t\t\telement.attributes.src = {type: \"string\", value: \"data:\" + type + \";base64,\" + text};\n\t\t}\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"image/svg+xml\"] = ImageParser;\nexports[\"image/jpg\"] = ImageParser;\nexports[\"image/jpeg\"] = ImageParser;\nexports[\"image/png\"] = ImageParser;\nexports[\"image/gif\"] = ImageParser;\nexports[\"image/webp\"] = ImageParser;\nexports[\"image/heic\"] = ImageParser;\nexports[\"image/heif\"] = ImageParser;\nexports[\"image/x-icon\"] = ImageParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/utils/parseutils.js": {
            "title": "$:/core/modules/utils/parseutils.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/parseutils.js\ntype: application/javascript\nmodule-type: utils\n\nUtility functions concerned with parsing text into tokens.\n\nMost functions have the following pattern:\n\n* The parameters are:\n** `source`: the source string being parsed\n** `pos`: the current parse position within the string\n** Any further parameters are used to identify the token that is being parsed\n* The return value is:\n** null if the token was not found at the specified position\n** an object representing the token with the following standard fields:\n*** `type`: string indicating the type of the token\n*** `start`: start position of the token in the source string\n*** `end`: end position of the token in the source string\n*** Any further fields required to describe the token\n\nThe exception is `skipWhiteSpace`, which just returns the position after the whitespace.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nLook for a whitespace token. Returns null if not found, otherwise returns {type: \"whitespace\", start:, end:,}\n*/\nexports.parseWhiteSpace = function(source,pos) {\n\tvar p = pos,c;\n\twhile(true) {\n\t\tc = source.charAt(p);\n\t\tif((c === \" \") || (c === \"\\f\") || (c === \"\\n\") || (c === \"\\r\") || (c === \"\\t\") || (c === \"\\v\") || (c === \"\\u00a0\")) { // Ignores some obscure unicode spaces\n\t\t\tp++;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\tif(p === pos) {\n\t\treturn null;\n\t} else {\n\t\treturn {\n\t\t\ttype: \"whitespace\",\n\t\t\tstart: pos,\n\t\t\tend: p\n\t\t}\n\t}\n};\n\n/*\nConvenience wrapper for parseWhiteSpace. Returns the position after the whitespace\n*/\nexports.skipWhiteSpace = function(source,pos) {\n\tvar c;\n\twhile(true) {\n\t\tc = source.charAt(pos);\n\t\tif((c === \" \") || (c === \"\\f\") || (c === \"\\n\") || (c === \"\\r\") || (c === \"\\t\") || (c === \"\\v\") || (c === \"\\u00a0\")) { // Ignores some obscure unicode spaces\n\t\t\tpos++;\n\t\t} else {\n\t\t\treturn pos;\n\t\t}\n\t}\n};\n\n/*\nLook for a given string token. Returns null if not found, otherwise returns {type: \"token\", value:, start:, end:,}\n*/\nexports.parseTokenString = function(source,pos,token) {\n\tvar match = source.indexOf(token,pos) === pos;\n\tif(match) {\n\t\treturn {\n\t\t\ttype: \"token\",\n\t\t\tvalue: token,\n\t\t\tstart: pos,\n\t\t\tend: pos + token.length\n\t\t};\n\t}\n\treturn null;\n};\n\n/*\nLook for a token matching a regex. Returns null if not found, otherwise returns {type: \"regexp\", match:, start:, end:,}\n*/\nexports.parseTokenRegExp = function(source,pos,reToken) {\n\tvar node = {\n\t\ttype: \"regexp\",\n\t\tstart: pos\n\t};\n\treToken.lastIndex = pos;\n\tnode.match = reToken.exec(source);\n\tif(node.match && node.match.index === pos) {\n\t\tnode.end = pos + node.match[0].length;\n\t\treturn node;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nLook for a string literal. Returns null if not found, otherwise returns {type: \"string\", value:, start:, end:,}\n*/\nexports.parseStringLiteral = function(source,pos) {\n\tvar node = {\n\t\ttype: \"string\",\n\t\tstart: pos\n\t};\n\tvar reString = /(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\")|(?:'([^']*)')/g;\n\treString.lastIndex = pos;\n\tvar match = reString.exec(source);\n\tif(match && match.index === pos) {\n\t\tnode.value = match[1] !== undefined ? match[1] :(\n\t\t\tmatch[2] !== undefined ? match[2] : match[3] \n\t\t\t\t\t);\n\t\tnode.end = pos + match[0].length;\n\t\treturn node;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nLook for a macro invocation parameter. Returns null if not found, or {type: \"macro-parameter\", name:, value:, start:, end:}\n*/\nexports.parseMacroParameter = function(source,pos) {\n\tvar node = {\n\t\ttype: \"macro-parameter\",\n\t\tstart: pos\n\t};\n\t// Define our regexp\n\tvar reMacroParameter = /(?:([A-Za-z0-9\\-_]+)\\s*:)?(?:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\\s>\"'=]+)))/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the parameter\n\tvar token = $tw.utils.parseTokenRegExp(source,pos,reMacroParameter);\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Get the parameter details\n\tnode.value = token.match[2] !== undefined ? token.match[2] : (\n\t\t\t\t\ttoken.match[3] !== undefined ? token.match[3] : (\n\t\t\t\t\t\ttoken.match[4] !== undefined ? token.match[4] : (\n\t\t\t\t\t\t\ttoken.match[5] !== undefined ? token.match[5] : (\n\t\t\t\t\t\t\t\ttoken.match[6] !== undefined ? token.match[6] : (\n\t\t\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t);\n\tif(token.match[1]) {\n\t\tnode.name = token.match[1];\n\t}\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n/*\nLook for a macro invocation. Returns null if not found, or {type: \"macrocall\", name:, parameters:, start:, end:}\n*/\nexports.parseMacroInvocation = function(source,pos) {\n\tvar node = {\n\t\ttype: \"macrocall\",\n\t\tstart: pos,\n\t\tparams: []\n\t};\n\t// Define our regexps\n\tvar reMacroName = /([^\\s>\"'=]+)/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a double less than sign\n\tvar token = $tw.utils.parseTokenString(source,pos,\"<<\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Get the macro name\n\tvar name = $tw.utils.parseTokenRegExp(source,pos,reMacroName);\n\tif(!name) {\n\t\treturn null;\n\t}\n\tnode.name = name.match[1];\n\tpos = name.end;\n\t// Process parameters\n\tvar parameter = $tw.utils.parseMacroParameter(source,pos);\n\twhile(parameter) {\n\t\tnode.params.push(parameter);\n\t\tpos = parameter.end;\n\t\t// Get the next parameter\n\t\tparameter = $tw.utils.parseMacroParameter(source,pos);\n\t}\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a double greater than sign\n\ttoken = $tw.utils.parseTokenString(source,pos,\">>\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n/*\nLook for an HTML attribute definition. Returns null if not found, otherwise returns {type: \"attribute\", name:, valueType: \"string|indirect|macro\", value:, start:, end:,}\n*/\nexports.parseAttribute = function(source,pos) {\n\tvar node = {\n\t\tstart: pos\n\t};\n\t// Define our regexps\n\tvar reAttributeName = /([^\\/\\s>\"'=]+)/g,\n\t\treUnquotedAttribute = /([^\\/\\s<>\"'=]+)/g,\n\t\treFilteredValue = /\\{\\{\\{(.+?)\\}\\}\\}/g,\n\t\treIndirectValue = /\\{\\{([^\\}]+)\\}\\}/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Get the attribute name\n\tvar name = $tw.utils.parseTokenRegExp(source,pos,reAttributeName);\n\tif(!name) {\n\t\treturn null;\n\t}\n\tnode.name = name.match[1];\n\tpos = name.end;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for an equals sign\n\tvar token = $tw.utils.parseTokenString(source,pos,\"=\");\n\tif(token) {\n\t\tpos = token.end;\n\t\t// Skip whitespace\n\t\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t\t// Look for a string literal\n\t\tvar stringLiteral = $tw.utils.parseStringLiteral(source,pos);\n\t\tif(stringLiteral) {\n\t\t\tpos = stringLiteral.end;\n\t\t\tnode.type = \"string\";\n\t\t\tnode.value = stringLiteral.value;\n\t\t} else {\n\t\t\t// Look for a filtered value\n\t\t\tvar filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);\n\t\t\tif(filteredValue) {\n\t\t\t\tpos = filteredValue.end;\n\t\t\t\tnode.type = \"filtered\";\n\t\t\t\tnode.filter = filteredValue.match[1];\n\t\t\t} else {\n\t\t\t\t// Look for an indirect value\n\t\t\t\tvar indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);\n\t\t\t\tif(indirectValue) {\n\t\t\t\t\tpos = indirectValue.end;\n\t\t\t\t\tnode.type = \"indirect\";\n\t\t\t\t\tnode.textReference = indirectValue.match[1];\n\t\t\t\t} else {\n\t\t\t\t\t// Look for a unquoted value\n\t\t\t\t\tvar unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);\n\t\t\t\t\tif(unquotedValue) {\n\t\t\t\t\t\tpos = unquotedValue.end;\n\t\t\t\t\t\tnode.type = \"string\";\n\t\t\t\t\t\tnode.value = unquotedValue.match[1];\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Look for a macro invocation value\n\t\t\t\t\t\tvar macroInvocation = $tw.utils.parseMacroInvocation(source,pos);\n\t\t\t\t\t\tif(macroInvocation) {\n\t\t\t\t\t\t\tpos = macroInvocation.end;\n\t\t\t\t\t\t\tnode.type = \"macro\";\n\t\t\t\t\t\t\tnode.value = macroInvocation;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnode.type = \"string\";\n\t\t\t\t\t\t\tnode.value = \"true\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tnode.type = \"string\";\n\t\tnode.value = \"true\";\n\t}\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/parsers/pdfparser.js": {
            "title": "$:/core/modules/parsers/pdfparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/pdfparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe PDF parser embeds a PDF viewer\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar ImageParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"embed\",\n\t\t\tattributes: {}\n\t\t},\n\t\tsrc;\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\telement.attributes.src = {type: \"string\", value: \"data:application/pdf;base64,\" + text};\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"application/pdf\"] = ImageParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/textparser.js": {
            "title": "$:/core/modules/parsers/textparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/textparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe plain text parser processes blocks of source text into a degenerate parse tree consisting of a single text node\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar TextParser = function(type,text,options) {\n\tthis.tree = [{\n\t\ttype: \"codeblock\",\n\t\tattributes: {\n\t\t\tcode: {type: \"string\", value: text},\n\t\t\tlanguage: {type: \"string\", value: type}\n\t\t}\n\t}];\n};\n\nexports[\"text/plain\"] = TextParser;\nexports[\"text/x-tiddlywiki\"] = TextParser;\nexports[\"application/javascript\"] = TextParser;\nexports[\"application/json\"] = TextParser;\nexports[\"text/css\"] = TextParser;\nexports[\"application/x-tiddler-dictionary\"] = TextParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/videoparser.js": {
            "title": "$:/core/modules/parsers/videoparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/videoparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe video parser parses a video tiddler into an embeddable HTML element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar VideoParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"video\",\n\t\t\tattributes: {\n\t\t\t\tcontrols: {type: \"string\", value: \"controls\"},\n\t\t\t\tstyle: {type: \"string\", value: \"width: 100%; object-fit: contain\"}\n\t\t\t}\n\t\t},\n\t\tsrc;\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\telement.attributes.src = {type: \"string\", value: \"data:\" + type + \";base64,\" + text};\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"video/ogg\"] = VideoParser;\nexports[\"video/webm\"] = VideoParser;\nexports[\"video/mp4\"] = VideoParser;\nexports[\"video/quicktime\"] = VideoParser;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/wikiparser/rules/codeblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/codeblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/codeblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for code blocks. For example:\n\n```\n\t```\n\tThis text will not be //wikified//\n\t```\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"codeblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match and get language if defined\n\tthis.matchRegExp = /```([\\w-]*)\\r?\\n/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /(\\r?\\n```$)/mg;\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Look for the end of the block\n\treEnd.lastIndex = this.parser.pos;\n\tvar match = reEnd.exec(this.parser.source),\n\t\ttext;\n\t// Process the block\n\tif(match) {\n\t\ttext = this.parser.source.substring(this.parser.pos,match.index);\n\t\tthis.parser.pos = match.index + match[0].length;\n\t} else {\n\t\ttext = this.parser.source.substr(this.parser.pos);\n\t\tthis.parser.pos = this.parser.sourceLength;\n\t}\n\t// Return the $codeblock widget\n\treturn [{\n\t\t\ttype: \"codeblock\",\n\t\t\tattributes: {\n\t\t\t\t\tcode: {type: \"string\", value: text},\n\t\t\t\t\tlanguage: {type: \"string\", value: this.match[1]}\n\t\t\t}\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/codeinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/codeinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/codeinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for code runs. For example:\n\n```\n\tThis is a `code run`.\n\tThis is another ``code run``\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"codeinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(``?)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar reEnd = new RegExp(this.match[1], \"mg\");\n\t// Look for the end marker\n\treEnd.lastIndex = this.parser.pos;\n\tvar match = reEnd.exec(this.parser.source),\n\t\ttext;\n\t// Process the text\n\tif(match) {\n\t\ttext = this.parser.source.substring(this.parser.pos,match.index);\n\t\tthis.parser.pos = match.index + match[0].length;\n\t} else {\n\t\ttext = this.parser.source.substr(this.parser.pos);\n\t\tthis.parser.pos = this.parser.sourceLength;\n\t}\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"code\",\n\t\tchildren: [{\n\t\t\ttype: \"text\",\n\t\t\ttext: text\n\t\t}]\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/commentblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/commentblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/commentblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for HTML comments. For example:\n\n```\n<!-- This is a comment -->\n```\n\nNote that the syntax for comments is simplified to an opening \"<!--\" sequence and a closing \"-->\" sequence -- HTML itself implements a more complex format (see http://ostermiller.org/findhtmlcomment.html)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"commentblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\tthis.matchRegExp = /<!--/mg;\n\tthis.endMatchRegExp = /-->/mg;\n};\n\nexports.findNextMatch = function(startPos) {\n\tthis.matchRegExp.lastIndex = startPos;\n\tthis.match = this.matchRegExp.exec(this.parser.source);\n\tif(this.match) {\n\t\tthis.endMatchRegExp.lastIndex = startPos + this.match[0].length;\n\t\tthis.endMatch = this.endMatchRegExp.exec(this.parser.source);\n\t\tif(this.endMatch) {\n\t\t\treturn this.match.index;\n\t\t}\n\t}\n\treturn undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.endMatchRegExp.lastIndex;\n\t// Don't return any elements\n\treturn [];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/commentinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/commentinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/commentinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for HTML comments. For example:\n\n```\n<!-- This is a comment -->\n```\n\nNote that the syntax for comments is simplified to an opening \"<!--\" sequence and a closing \"-->\" sequence -- HTML itself implements a more complex format (see http://ostermiller.org/findhtmlcomment.html)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"commentinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\tthis.matchRegExp = /<!--/mg;\n\tthis.endMatchRegExp = /-->/mg;\n};\n\nexports.findNextMatch = function(startPos) {\n\tthis.matchRegExp.lastIndex = startPos;\n\tthis.match = this.matchRegExp.exec(this.parser.source);\n\tif(this.match) {\n\t\tthis.endMatchRegExp.lastIndex = startPos + this.match[0].length;\n\t\tthis.endMatch = this.endMatchRegExp.exec(this.parser.source);\n\t\tif(this.endMatch) {\n\t\t\treturn this.match.index;\n\t\t}\n\t}\n\treturn undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.endMatchRegExp.lastIndex;\n\t// Don't return any elements\n\treturn [];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/dash.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/dash.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/dash.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for dashes. For example:\n\n```\nThis is an en-dash: --\n\nThis is an em-dash: ---\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"dash\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /-{2,3}(?!-)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar dash = this.match[0].length === 2 ? \"&ndash;\" : \"&mdash;\";\n\treturn [{\n\t\ttype: \"entity\",\n\t\tentity: dash\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/bold.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/bold.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/bold.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - bold. For example:\n\n```\n\tThis is ''bold'' text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except bold \n\\rules only bold \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"bold\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /''/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/''/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"strong\",\n\t\tchildren: tree\n\t}];\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/italic.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/italic.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/italic.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - italic. For example:\n\n```\n\tThis is //italic// text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except italic\n\\rules only italic\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"italic\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\/\\//mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/\\/\\//mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"em\",\n\t\tchildren: tree\n\t}];\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - strikethrough. For example:\n\n```\n\tThis is ~~strikethrough~~ text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except strikethrough \n\\rules only strikethrough \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"strikethrough\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /~~/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/~~/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"strike\",\n\t\tchildren: tree\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/subscript.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/subscript.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/subscript.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - subscript. For example:\n\n```\n\tThis is ,,subscript,, text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except subscript \n\\rules only subscript \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"subscript\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /,,/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/,,/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"sub\",\n\t\tchildren: tree\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/superscript.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/superscript.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/superscript.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - superscript. For example:\n\n```\n\tThis is ^^superscript^^ text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except superscript \n\\rules only superscript \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"superscript\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\^\\^/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/\\^\\^/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"sup\",\n\t\tchildren: tree\n\t}];\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/emphasis/underscore.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/underscore.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/underscore.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - underscore. For example:\n\n```\n\tThis is __underscore__ text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except underscore \n\\rules only underscore\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"underscore\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /__/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/__/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"u\",\n\t\tchildren: tree\n\t}];\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/entity.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/entity.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/entity.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for HTML entities. For example:\n\n```\n\tThis is a copyright symbol: &copy;\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"entity\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(&#?[a-zA-Z0-9]{2,8};)/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar entityString = this.match[1];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Return the entity\n\treturn [{type: \"entity\", entity: this.match[0]}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/extlink.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/extlink.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/extlink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for external links. For example:\n\n```\nAn external link: https://www.tiddlywiki.com/\n\nA suppressed external link: ~http://www.tiddlyspace.com/\n```\n\nExternal links can be suppressed by preceding them with `~`.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"extlink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /~?(?:file|http|https|mailto|ftp|irc|news|data|skype):[^\\s<>{}\\[\\]`|\"\\\\^]+(?:\\/|\\b)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Create the link unless it is suppressed\n\tif(this.match[0].substr(0,1) === \"~\") {\n\t\treturn [{type: \"text\", text: this.match[0].substr(1)}];\n\t} else {\n\t\treturn [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"a\",\n\t\t\tattributes: {\n\t\t\t\thref: {type: \"string\", value: this.match[0]},\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-tiddlylink-external\"},\n\t\t\t\ttarget: {type: \"string\", value: \"_blank\"},\n\t\t\t\trel: {type: \"string\", value: \"noopener noreferrer\"}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\", text: this.match[0]\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for block-level filtered transclusion. For example:\n\n```\n{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"filteredtranscludeblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{\\{([^\\|]+?)(?:\\|([^\\|\\{\\}]+))?(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}([^\\}]*)\\}(?:\\.(\\S+))?(?:\\r?\\n|$)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar filter = this.match[1],\n\t\ttooltip = this.match[2],\n\t\ttemplate = $tw.utils.trim(this.match[3]),\n\t\tstyle = this.match[4],\n\t\tclasses = this.match[5];\n\t// Return the list widget\n\tvar node = {\n\t\ttype: \"list\",\n\t\tattributes: {\n\t\t\tfilter: {type: \"string\", value: filter}\n\t\t},\n\t\tisBlock: true\n\t};\n\tif(tooltip) {\n\t\tnode.attributes.tooltip = {type: \"string\", value: tooltip};\n\t}\n\tif(template) {\n\t\tnode.attributes.template = {type: \"string\", value: template};\n\t}\n\tif(style) {\n\t\tnode.attributes.style = {type: \"string\", value: style};\n\t}\n\tif(classes) {\n\t\tnode.attributes.itemClass = {type: \"string\", value: classes.split(\".\").join(\" \")};\n\t}\n\treturn [node];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for inline filtered transclusion. For example:\n\n```\n{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"filteredtranscludeinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{\\{([^\\|]+?)(?:\\|([^\\|\\{\\}]+))?(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}([^\\}]*)\\}(?:\\.(\\S+))?/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar filter = this.match[1],\n\t\ttooltip = this.match[2],\n\t\ttemplate = $tw.utils.trim(this.match[3]),\n\t\tstyle = this.match[4],\n\t\tclasses = this.match[5];\n\t// Return the list widget\n\tvar node = {\n\t\ttype: \"list\",\n\t\tattributes: {\n\t\t\tfilter: {type: \"string\", value: filter}\n\t\t}\n\t};\n\tif(tooltip) {\n\t\tnode.attributes.tooltip = {type: \"string\", value: tooltip};\n\t}\n\tif(template) {\n\t\tnode.attributes.template = {type: \"string\", value: template};\n\t}\n\tif(style) {\n\t\tnode.attributes.style = {type: \"string\", value: style};\n\t}\n\tif(classes) {\n\t\tnode.attributes.itemClass = {type: \"string\", value: classes.split(\".\").join(\" \")};\n\t}\n\treturn [node];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/hardlinebreaks.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/hardlinebreaks.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/hardlinebreaks.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for marking areas with hard line breaks. For example:\n\n```\n\"\"\"\nThis is some text\nThat is set like\nIt is a Poem\nWhen it is\nClearly\nNot\n\"\"\"\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"hardlinebreaks\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\"\"\"(?:\\r?\\n)?/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /(\"\"\")|(\\r?\\n)/mg,\n\t\ttree = [],\n\t\tmatch;\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tdo {\n\t\t// Parse the run up to the terminator\n\t\ttree.push.apply(tree,this.parser.parseInlineRun(reEnd,{eatTerminator: false}));\n\t\t// Redo the terminator match\n\t\treEnd.lastIndex = this.parser.pos;\n\t\tmatch = reEnd.exec(this.parser.source);\n\t\tif(match) {\n\t\t\tthis.parser.pos = reEnd.lastIndex;\n\t\t\t// Add a line break if the terminator was a line break\n\t\t\tif(match[2]) {\n\t\t\t\ttree.push({type: \"element\", tag: \"br\"});\n\t\t\t}\n\t\t}\n\t} while(match && !match[1]);\n\t// Return the nodes\n\treturn tree;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/heading.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/heading.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/heading.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for headings\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"heading\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(!{1,6})/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar headingLevel = this.match[1].length;\n\t// Move past the !s\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse any classes, whitespace and then the heading itself\n\tvar classes = this.parser.parseClasses();\n\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\tvar tree = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t// Return the heading\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"h\" + headingLevel, \n\t\tattributes: {\n\t\t\t\"class\": {type: \"string\", value: classes.join(\" \")}\n\t\t},\n\t\tchildren: tree\n\t}];\n};\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/horizrule.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/horizrule.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/horizrule.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for rules. For example:\n\n```\n---\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"horizrule\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /-{3,}\\r?(?:\\n|$)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\treturn [{type: \"element\", tag: \"hr\"}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/html.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/html.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/html.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki rule for HTML elements and widgets. For example:\n\n{{{\n<aside>\nThis is an HTML5 aside element\n</aside>\n\n<$slider target=\"MyTiddler\">\nThis is a widget invocation\n</$slider>\n\n}}}\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"html\";\nexports.types = {inline: true, block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n};\n\nexports.findNextMatch = function(startPos) {\n\t// Find the next tag\n\tthis.nextTag = this.findNextTag(this.parser.source,startPos,{\n\t\trequireLineBreak: this.is.block\n\t});\n\treturn this.nextTag ? this.nextTag.start : undefined;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Retrieve the most recent match so that recursive calls don't overwrite it\n\tvar tag = this.nextTag;\n\tthis.nextTag = null;\n\t// Advance the parser position to past the tag\n\tthis.parser.pos = tag.end;\n\t// Check for an immediately following double linebreak\n\tvar hasLineBreak = !tag.isSelfClosing && !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\\S\\n\\r]*\\r?\\n(?:[^\\S\\n\\r]*\\r?\\n|$))/g);\n\t// Set whether we're in block mode\n\ttag.isBlock = this.is.block || hasLineBreak;\n\t// Parse the body if we need to\n\tif(!tag.isSelfClosing && $tw.config.htmlVoidElements.indexOf(tag.tag) === -1) {\n\t\t\tvar reEndString = \"</\" + $tw.utils.escapeRegExp(tag.tag) + \">\",\n\t\t\t\treEnd = new RegExp(\"(\" + reEndString + \")\",\"mg\");\n\t\tif(hasLineBreak) {\n\t\t\ttag.children = this.parser.parseBlocks(reEndString);\n\t\t} else {\n\t\t\ttag.children = this.parser.parseInlineRun(reEnd);\n\t\t}\n\t\treEnd.lastIndex = this.parser.pos;\n\t\tvar endMatch = reEnd.exec(this.parser.source);\n\t\tif(endMatch && endMatch.index === this.parser.pos) {\n\t\t\tthis.parser.pos = endMatch.index + endMatch[0].length;\n\t\t}\n\t}\n\t// Return the tag\n\treturn [tag];\n};\n\n/*\nLook for an HTML tag. Returns null if not found, otherwise returns {type: \"element\", name:, attributes: [], isSelfClosing:, start:, end:,}\n*/\nexports.parseTag = function(source,pos,options) {\n\toptions = options || {};\n\tvar token,\n\t\tnode = {\n\t\t\ttype: \"element\",\n\t\t\tstart: pos,\n\t\t\tattributes: {}\n\t\t};\n\t// Define our regexps\n\tvar reTagName = /([a-zA-Z0-9\\-\\$]+)/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a less than sign\n\ttoken = $tw.utils.parseTokenString(source,pos,\"<\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Get the tag name\n\ttoken = $tw.utils.parseTokenRegExp(source,pos,reTagName);\n\tif(!token) {\n\t\treturn null;\n\t}\n\tnode.tag = token.match[1];\n\tif(node.tag.slice(1).indexOf(\"$\") !== -1) {\n\t\treturn null;\n\t}\n\tif(node.tag.charAt(0) === \"$\") {\n\t\tnode.type = node.tag.substr(1);\n\t}\n\tpos = token.end;\n\t// Check that the tag is terminated by a space, / or >\n\tif(!$tw.utils.parseWhiteSpace(source,pos) && !(source.charAt(pos) === \"/\") && !(source.charAt(pos) === \">\") ) {\n\t\treturn null;\n\t}\n\t// Process attributes\n\tvar attribute = $tw.utils.parseAttribute(source,pos);\n\twhile(attribute) {\n\t\tnode.attributes[attribute.name] = attribute;\n\t\tpos = attribute.end;\n\t\t// Get the next attribute\n\t\tattribute = $tw.utils.parseAttribute(source,pos);\n\t}\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a closing slash\n\ttoken = $tw.utils.parseTokenString(source,pos,\"/\");\n\tif(token) {\n\t\tpos = token.end;\n\t\tnode.isSelfClosing = true;\n\t}\n\t// Look for a greater than sign\n\ttoken = $tw.utils.parseTokenString(source,pos,\">\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Check for a required line break\n\tif(options.requireLineBreak) {\n\t\ttoken = $tw.utils.parseTokenRegExp(source,pos,/([^\\S\\n\\r]*\\r?\\n(?:[^\\S\\n\\r]*\\r?\\n|$))/g);\n\t\tif(!token) {\n\t\t\treturn null;\n\t\t}\n\t}\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\nexports.findNextTag = function(source,pos,options) {\n\t// A regexp for finding candidate HTML tags\n\tvar reLookahead = /<([a-zA-Z\\-\\$]+)/g;\n\t// Find the next candidate\n\treLookahead.lastIndex = pos;\n\tvar match = reLookahead.exec(source);\n\twhile(match) {\n\t\t// Try to parse the candidate as a tag\n\t\tvar tag = this.parseTag(source,match.index,options);\n\t\t// Return success\n\t\tif(tag && this.isLegalTag(tag)) {\n\t\t\treturn tag;\n\t\t}\n\t\t// Look for the next match\n\t\treLookahead.lastIndex = match.index + 1;\n\t\tmatch = reLookahead.exec(source);\n\t}\n\t// Failed\n\treturn null;\n};\n\nexports.isLegalTag = function(tag) {\n\t// Widgets are always OK\n\tif(tag.type !== \"element\") {\n\t\treturn true;\n\t// If it's an HTML tag that starts with a dash then it's not legal\n\t} else if(tag.tag.charAt(0) === \"-\") {\n\t\treturn false;\n\t} else {\n\t\t// Otherwise it's OK\n\t\treturn true;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/image.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/image.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/image.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for embedding images. For example:\n\n```\n[img[https://tiddlywiki.com/fractalveg.jpg]]\n[img width=23 height=24 [https://tiddlywiki.com/fractalveg.jpg]]\n[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]\n[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]\n[img[TiddlerTitle]]\n[img[Description of image|TiddlerTitle]]\n```\n\nGenerates the `<$image>` widget.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"image\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n};\n\nexports.findNextMatch = function(startPos) {\n\t// Find the next tag\n\tthis.nextImage = this.findNextImage(this.parser.source,startPos);\n\treturn this.nextImage ? this.nextImage.start : undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.nextImage.end;\n\tvar node = {\n\t\ttype: \"image\",\n\t\tattributes: this.nextImage.attributes\n\t};\n\treturn [node];\n};\n\n/*\nFind the next image from the current position\n*/\nexports.findNextImage = function(source,pos) {\n\t// A regexp for finding candidate HTML tags\n\tvar reLookahead = /(\\[img)/g;\n\t// Find the next candidate\n\treLookahead.lastIndex = pos;\n\tvar match = reLookahead.exec(source);\n\twhile(match) {\n\t\t// Try to parse the candidate as a tag\n\t\tvar tag = this.parseImage(source,match.index);\n\t\t// Return success\n\t\tif(tag) {\n\t\t\treturn tag;\n\t\t}\n\t\t// Look for the next match\n\t\treLookahead.lastIndex = match.index + 1;\n\t\tmatch = reLookahead.exec(source);\n\t}\n\t// Failed\n\treturn null;\n};\n\n/*\nLook for an image at the specified position. Returns null if not found, otherwise returns {type: \"image\", attributes: [], isSelfClosing:, start:, end:,}\n*/\nexports.parseImage = function(source,pos) {\n\tvar token,\n\t\tnode = {\n\t\t\ttype: \"image\",\n\t\t\tstart: pos,\n\t\t\tattributes: {}\n\t\t};\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the `[img`\n\ttoken = $tw.utils.parseTokenString(source,pos,\"[img\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Process attributes\n\tif(source.charAt(pos) !== \"[\") {\n\t\tvar attribute = $tw.utils.parseAttribute(source,pos);\n\t\twhile(attribute) {\n\t\t\tnode.attributes[attribute.name] = attribute;\n\t\t\tpos = attribute.end;\n\t\t\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t\t\tif(source.charAt(pos) !== \"[\") {\n\t\t\t\t// Get the next attribute\n\t\t\t\tattribute = $tw.utils.parseAttribute(source,pos);\n\t\t\t} else {\n\t\t\t\tattribute = null;\n\t\t\t}\n\t\t}\n\t}\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the `[` after the attributes\n\ttoken = $tw.utils.parseTokenString(source,pos,\"[\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Get the source up to the terminating `]]`\n\ttoken = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\\]]*?)\\|)?([^\\]]+?)\\]\\]/g);\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\tif(token.match[1]) {\n\t\tnode.attributes.tooltip = {type: \"string\", value: token.match[1].trim()};\n\t}\n\tnode.attributes.source = {type: \"string\", value: (token.match[2] || \"\").trim()};\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/import.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/import.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/import.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki pragma rule for importing variable definitions\n\n```\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"import\";\nexports.types = {pragma: true};\n\n/*\nInstantiate parse rule\n*/\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\\\import[^\\S\\n]/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\tvar self = this;\n\t// Move past the pragma invocation\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse the filter terminated by a line break\n\tvar reMatch = /(.*)(\\r?\\n)|$/mg;\n\treMatch.lastIndex = this.parser.pos;\n\tvar match = reMatch.exec(this.parser.source);\n\tthis.parser.pos = reMatch.lastIndex;\n\t// Parse tree nodes to return\n\treturn [{\n\t\ttype: \"importvariables\",\n\t\tattributes: {\n\t\t\tfilter: {type: \"string\", value: match[1]}\n\t\t},\n\t\tchildren: []\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/list.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/list.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/list.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for lists. For example:\n\n```\n* This is an unordered list\n* It has two items\n\n# This is a numbered list\n## With a subitem\n# And a third item\n\n; This is a term that is being defined\n: This is the definition of that term\n```\n\nNote that lists can be nested arbitrarily:\n\n```\n#** One\n#* Two\n#** Three\n#**** Four\n#**# Five\n#**## Six\n## Seven\n### Eight\n## Nine\n```\n\nA CSS class can be applied to a list item as follows:\n\n```\n* List item one\n*.active List item two has the class `active`\n* List item three\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"list\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /([\\*#;:>]+)/mg;\n};\n\nvar listTypes = {\n\t\"*\": {listTag: \"ul\", itemTag: \"li\"},\n\t\"#\": {listTag: \"ol\", itemTag: \"li\"},\n\t\";\": {listTag: \"dl\", itemTag: \"dt\"},\n\t\":\": {listTag: \"dl\", itemTag: \"dd\"},\n\t\">\": {listTag: \"blockquote\", itemTag: \"div\"}\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Array of parse tree nodes for the previous row of the list\n\tvar listStack = [];\n\t// Cycle through the items in the list\n\twhile(true) {\n\t\t// Match the list marker\n\t\tvar reMatch = /([\\*#;:>]+)/mg;\n\t\treMatch.lastIndex = this.parser.pos;\n\t\tvar match = reMatch.exec(this.parser.source);\n\t\tif(!match || match.index !== this.parser.pos) {\n\t\t\tbreak;\n\t\t}\n\t\t// Check whether the list type of the top level matches\n\t\tvar listInfo = listTypes[match[0].charAt(0)];\n\t\tif(listStack.length > 0 && listStack[0].tag !== listInfo.listTag) {\n\t\t\tbreak;\n\t\t}\n\t\t// Move past the list marker\n\t\tthis.parser.pos = match.index + match[0].length;\n\t\t// Walk through the list markers for the current row\n\t\tfor(var t=0; t<match[0].length; t++) {\n\t\t\tlistInfo = listTypes[match[0].charAt(t)];\n\t\t\t// Remove any stacked up element if we can't re-use it because the list type doesn't match\n\t\t\tif(listStack.length > t && listStack[t].tag !== listInfo.listTag) {\n\t\t\t\tlistStack.splice(t,listStack.length - t);\n\t\t\t}\n\t\t\t// Construct the list element or reuse the previous one at this level\n\t\t\tif(listStack.length <= t) {\n\t\t\t\tvar listElement = {type: \"element\", tag: listInfo.listTag, children: [\n\t\t\t\t\t{type: \"element\", tag: listInfo.itemTag, children: []}\n\t\t\t\t]};\n\t\t\t\t// Link this list element into the last child item of the parent list item\n\t\t\t\tif(t) {\n\t\t\t\t\tvar prevListItem = listStack[t-1].children[listStack[t-1].children.length-1];\n\t\t\t\t\tprevListItem.children.push(listElement);\n\t\t\t\t}\n\t\t\t\t// Save this element in the stack\n\t\t\t\tlistStack[t] = listElement;\n\t\t\t} else if(t === (match[0].length - 1)) {\n\t\t\t\tlistStack[t].children.push({type: \"element\", tag: listInfo.itemTag, children: []});\n\t\t\t}\n\t\t}\n\t\tif(listStack.length > match[0].length) {\n\t\t\tlistStack.splice(match[0].length,listStack.length - match[0].length);\n\t\t}\n\t\t// Process the body of the list item into the last list item\n\t\tvar lastListChildren = listStack[listStack.length-1].children,\n\t\t\tlastListItem = lastListChildren[lastListChildren.length-1],\n\t\t\tclasses = this.parser.parseClasses();\n\t\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\t\tvar tree = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t\tlastListItem.children.push.apply(lastListItem.children,tree);\n\t\tif(classes.length > 0) {\n\t\t\t$tw.utils.addClassToParseTreeNode(lastListItem,classes.join(\" \"));\n\t\t}\n\t\t// Consume any whitespace following the list item\n\t\tthis.parser.skipWhitespace();\n\t}\n\t// Return the root element of the list\n\treturn [listStack[0]];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/macrocallblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/macrocallblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/macrocallblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki rule for block macro calls\n\n```\n<<name value value2>>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"macrocallblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /<<([^>\\s]+)(?:\\s*)((?:[^>]|(?:>(?!>)))*?)>>(?:\\r?\\n|$)/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar macroName = this.match[1],\n\t\tparamString = this.match[2];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar params = [],\n\t\treParam = /\\s*(?:([A-Za-z0-9\\-_]+)\\s*:)?(?:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\"'\\s]+)))/mg,\n\t\tparamMatch = reParam.exec(paramString);\n\twhile(paramMatch) {\n\t\t// Process this parameter\n\t\tvar paramInfo = {\n\t\t\tvalue: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5] || paramMatch[6]\n\t\t};\n\t\tif(paramMatch[1]) {\n\t\t\tparamInfo.name = paramMatch[1];\n\t\t}\n\t\tparams.push(paramInfo);\n\t\t// Find the next match\n\t\tparamMatch = reParam.exec(paramString);\n\t}\n\treturn [{\n\t\ttype: \"macrocall\",\n\t\tname: macroName,\n\t\tparams: params,\n\t\tisBlock: true\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/macrocallinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/macrocallinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/macrocallinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki rule for macro calls\n\n```\n<<name value value2>>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"macrocallinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /<<([^\\s>]+)\\s*([\\s\\S]*?)>>/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar macroName = this.match[1],\n\t\tparamString = this.match[2];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar params = [],\n\t\treParam = /\\s*(?:([A-Za-z0-9\\-_]+)\\s*:)?(?:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\"'\\s]+)))/mg,\n\t\tparamMatch = reParam.exec(paramString);\n\twhile(paramMatch) {\n\t\t// Process this parameter\n\t\tvar paramInfo = {\n\t\t\tvalue: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5]|| paramMatch[6]\n\t\t};\n\t\tif(paramMatch[1]) {\n\t\t\tparamInfo.name = paramMatch[1];\n\t\t}\n\t\tparams.push(paramInfo);\n\t\t// Find the next match\n\t\tparamMatch = reParam.exec(paramString);\n\t}\n\treturn [{\n\t\ttype: \"macrocall\",\n\t\tname: macroName,\n\t\tparams: params\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/macrodef.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/macrodef.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/macrodef.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki pragma rule for macro definitions\n\n```\n\\define name(param:defaultvalue,param2:defaultvalue)\ndefinition text, including $param$ markers\n\\end\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"macrodef\";\nexports.types = {pragma: true};\n\n/*\nInstantiate parse rule\n*/\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\\\define\\s+([^(\\s]+)\\(\\s*([^)]*)\\)(\\s*\\r?\\n)?/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Move past the macro name and parameters\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse the parameters\n\tvar paramString = this.match[2],\n\t\tparams = [];\n\tif(paramString !== \"\") {\n\t\tvar reParam = /\\s*([A-Za-z0-9\\-_]+)(?:\\s*:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\"'\\s]+)))?/mg,\n\t\t\tparamMatch = reParam.exec(paramString);\n\t\twhile(paramMatch) {\n\t\t\t// Save the parameter details\n\t\t\tvar paramInfo = {name: paramMatch[1]},\n\t\t\t\tdefaultValue = paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5] || paramMatch[6];\n\t\t\tif(defaultValue) {\n\t\t\t\tparamInfo[\"default\"] = defaultValue;\n\t\t\t}\n\t\t\tparams.push(paramInfo);\n\t\t\t// Look for the next parameter\n\t\t\tparamMatch = reParam.exec(paramString);\n\t\t}\n\t}\n\t// Is this a multiline definition?\n\tvar reEnd;\n\tif(this.match[3]) {\n\t\t// If so, the end of the body is marked with \\end\n\t\treEnd = /(\\r?\\n\\\\end[^\\S\\n\\r]*(?:$|\\r?\\n))/mg;\n\t} else {\n\t\t// Otherwise, the end of the definition is marked by the end of the line\n\t\treEnd = /($|\\r?\\n)/mg;\n\t\t// Move past any whitespace\n\t\tthis.parser.pos = $tw.utils.skipWhiteSpace(this.parser.source,this.parser.pos);\n\t}\n\t// Find the end of the definition\n\treEnd.lastIndex = this.parser.pos;\n\tvar text,\n\t\tendMatch = reEnd.exec(this.parser.source);\n\tif(endMatch) {\n\t\ttext = this.parser.source.substring(this.parser.pos,endMatch.index);\n\t\tthis.parser.pos = endMatch.index + endMatch[0].length;\n\t} else {\n\t\t// We didn't find the end of the definition, so we'll make it blank\n\t\ttext = \"\";\n\t}\n\t// Save the macro definition\n\treturn [{\n\t\ttype: \"set\",\n\t\tattributes: {\n\t\t\tname: {type: \"string\", value: this.match[1]},\n\t\t\tvalue: {type: \"string\", value: text}\n\t\t},\n\t\tchildren: [],\n\t\tparams: params,\n\t\tisMacroDefinition: true\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/prettyextlink.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/prettyextlink.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/prettyextlink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for external links. For example:\n\n```\n[ext[https://tiddlywiki.com/fractalveg.jpg]]\n[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"prettyextlink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n};\n\nexports.findNextMatch = function(startPos) {\n\t// Find the next tag\n\tthis.nextLink = this.findNextLink(this.parser.source,startPos);\n\treturn this.nextLink ? this.nextLink.start : undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.nextLink.end;\n\treturn [this.nextLink];\n};\n\n/*\nFind the next link from the current position\n*/\nexports.findNextLink = function(source,pos) {\n\t// A regexp for finding candidate links\n\tvar reLookahead = /(\\[ext\\[)/g;\n\t// Find the next candidate\n\treLookahead.lastIndex = pos;\n\tvar match = reLookahead.exec(source);\n\twhile(match) {\n\t\t// Try to parse the candidate as a link\n\t\tvar link = this.parseLink(source,match.index);\n\t\t// Return success\n\t\tif(link) {\n\t\t\treturn link;\n\t\t}\n\t\t// Look for the next match\n\t\treLookahead.lastIndex = match.index + 1;\n\t\tmatch = reLookahead.exec(source);\n\t}\n\t// Failed\n\treturn null;\n};\n\n/*\nLook for an link at the specified position. Returns null if not found, otherwise returns {type: \"element\", tag: \"a\", attributes: [], isSelfClosing:, start:, end:,}\n*/\nexports.parseLink = function(source,pos) {\n\tvar token,\n\t\ttextNode = {\n\t\t\ttype: \"text\"\n\t\t},\n\t\tnode = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"a\",\n\t\t\tstart: pos,\n\t\t\tattributes: {\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-tiddlylink-external\"},\n\t\t\t},\n\t\t\tchildren: [textNode]\n\t\t};\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the `[ext[`\n\ttoken = $tw.utils.parseTokenString(source,pos,\"[ext[\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Look ahead for the terminating `]]`\n\tvar closePos = source.indexOf(\"]]\",pos);\n\tif(closePos === -1) {\n\t\treturn null;\n\t}\n\t// Look for a `|` separating the tooltip\n\tvar splitPos = source.indexOf(\"|\",pos);\n\tif(splitPos === -1 || splitPos > closePos) {\n\t\tsplitPos = null;\n\t}\n\t// Pull out the tooltip and URL\n\tvar tooltip, URL;\n\tif(splitPos) {\n\t\tURL = source.substring(splitPos + 1,closePos).trim();\n\t\ttextNode.text = source.substring(pos,splitPos).trim();\n\t} else {\n\t\tURL = source.substring(pos,closePos).trim();\n\t\ttextNode.text = URL;\n\t}\n\tnode.attributes.href = {type: \"string\", value: URL};\n\tnode.attributes.target = {type: \"string\", value: \"_blank\"};\n\tnode.attributes.rel = {type: \"string\", value: \"noopener noreferrer\"};\n\t// Update the end position\n\tnode.end = closePos + 2;\n\treturn node;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/prettylink.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/prettylink.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/prettylink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for pretty links. For example:\n\n```\n[[Introduction]]\n\n[[Link description|TiddlerTitle]]\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"prettylink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\[\\[(.*?)(?:\\|(.*?))?\\]\\]/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Process the link\n\tvar text = this.match[1],\n\t\tlink = this.match[2] || text;\n\tif($tw.utils.isLinkExternal(link)) {\n\t\treturn [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"a\",\n\t\t\tattributes: {\n\t\t\t\thref: {type: \"string\", value: link},\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-tiddlylink-external\"},\n\t\t\t\ttarget: {type: \"string\", value: \"_blank\"},\n\t\t\t\trel: {type: \"string\", value: \"noopener noreferrer\"}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\", text: text\n\t\t\t}]\n\t\t}];\n\t} else {\n\t\treturn [{\n\t\t\ttype: \"link\",\n\t\t\tattributes: {\n\t\t\t\tto: {type: \"string\", value: link}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\", text: text\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/quoteblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/quoteblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/quoteblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for quote blocks. For example:\n\n```\n\t<<<.optionalClass(es) optional cited from\n\ta quote\n\t<<<\n\t\n\t<<<.optionalClass(es)\n\ta quote\n\t<<< optional cited from\n```\n\nQuotes can be quoted by putting more <s\n\n```\n\t<<<\n\tQuote Level 1\n\t\n\t<<<<\n\tQuoteLevel 2\n\t<<<<\n\t\n\t<<<\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"quoteblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(<<<+)/mg;\n};\n\nexports.parse = function() {\n\tvar classes = [\"tc-quote\"];\n\t// Get all the details of the match\n\tvar reEndString = \"^\" + this.match[1] + \"(?!<)\";\n\t// Move past the <s\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t\n\t// Parse any classes, whitespace and then the optional cite itself\n\tclasses.push.apply(classes, this.parser.parseClasses());\n\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\tvar cite = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t// before handling the cite, parse the body of the quote\n\tvar tree= this.parser.parseBlocks(reEndString);\n\t// If we got a cite, put it before the text\n\tif(cite.length > 0) {\n\t\ttree.unshift({\n\t\t\ttype: \"element\",\n\t\t\ttag: \"cite\",\n\t\t\tchildren: cite\n\t\t});\n\t}\n\t// Parse any optional cite\n\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\tcite = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t// If we got a cite, push it\n\tif(cite.length > 0) {\n\t\ttree.push({\n\t\t\ttype: \"element\",\n\t\t\ttag: \"cite\",\n\t\t\tchildren: cite\n\t\t});\n\t}\n\t// Return the blockquote element\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"blockquote\",\n\t\tattributes: {\n\t\t\tclass: { type: \"string\", value: classes.join(\" \") },\n\t\t},\n\t\tchildren: tree\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/rules.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/rules.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/rules.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki pragma rule for rules specifications\n\n```\n\\rules except ruleone ruletwo rulethree\n\\rules only ruleone ruletwo rulethree\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"rules\";\nexports.types = {pragma: true};\n\n/*\nInstantiate parse rule\n*/\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\\\rules[^\\S\\n]/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Move past the pragma invocation\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse whitespace delimited tokens terminated by a line break\n\tvar reMatch = /[^\\S\\n]*(\\S+)|(\\r?\\n)/mg,\n\t\ttokens = [];\n\treMatch.lastIndex = this.parser.pos;\n\tvar match = reMatch.exec(this.parser.source);\n\twhile(match && match.index === this.parser.pos) {\n\t\tthis.parser.pos = reMatch.lastIndex;\n\t\t// Exit if we've got the line break\n\t\tif(match[2]) {\n\t\t\tbreak;\n\t\t}\n\t\t// Process the token\n\t\tif(match[1]) {\n\t\t\ttokens.push(match[1]);\n\t\t}\n\t\t// Match the next token\n\t\tmatch = reMatch.exec(this.parser.source);\n\t}\n\t// Process the tokens\n\tif(tokens.length > 0) {\n\t\tthis.parser.amendRules(tokens[0],tokens.slice(1));\n\t}\n\t// No parse tree nodes to return\n\treturn [];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/styleblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/styleblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/styleblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for assigning styles and classes to paragraphs and other blocks. For example:\n\n```\n@@.myClass\n@@background-color:red;\nThis paragraph will have the CSS class `myClass`.\n\n* The `<ul>` around this list will also have the class `myClass`\n* List item 2\n\n@@\n```\n\nNote that classes and styles can be mixed subject to the rule that styles must precede classes. For example\n\n```\n@@.myFirstClass.mySecondClass\n@@width:100px;.myThirdClass\nThis is a paragraph\n@@\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"styleblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /@@((?:[^\\.\\r\\n\\s:]+:[^\\r\\n;]+;)+)?(?:\\.([^\\r\\n\\s]+))?\\r?\\n/mg;\n};\n\nexports.parse = function() {\n\tvar reEndString = \"^@@(?:\\\\r?\\\\n)?\";\n\tvar classes = [], styles = [];\n\tdo {\n\t\t// Get the class and style\n\t\tif(this.match[1]) {\n\t\t\tstyles.push(this.match[1]);\n\t\t}\n\t\tif(this.match[2]) {\n\t\t\tclasses.push(this.match[2].split(\".\").join(\" \"));\n\t\t}\n\t\t// Move past the match\n\t\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t\t// Look for another line of classes and styles\n\t\tthis.match = this.matchRegExp.exec(this.parser.source);\n\t} while(this.match && this.match.index === this.parser.pos);\n\t// Parse the body\n\tvar tree = this.parser.parseBlocks(reEndString);\n\tfor(var t=0; t<tree.length; t++) {\n\t\tif(classes.length > 0) {\n\t\t\t$tw.utils.addClassToParseTreeNode(tree[t],classes.join(\" \"));\n\t\t}\n\t\tif(styles.length > 0) {\n\t\t\t$tw.utils.addAttributeToParseTreeNode(tree[t],\"style\",styles.join(\"\"));\n\t\t}\n\t}\n\treturn tree;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/styleinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/styleinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/styleinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for assigning styles and classes to inline runs. For example:\n\n```\n@@.myClass This is some text with a class@@\n@@background-color:red;This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@\n```\n\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"styleinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /@@((?:[^\\.\\r\\n\\s:]+:[^\\r\\n;]+;)+)?(\\.(?:[^\\r\\n\\s]+)\\s+)?/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /@@/g;\n\t// Get the styles and class\n\tvar stylesString = this.match[1],\n\t\tclassString = this.match[2] ? this.match[2].split(\".\").join(\" \") : undefined;\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse the run up to the terminator\n\tvar tree = this.parser.parseInlineRun(reEnd,{eatTerminator: true});\n\t// Return the classed span\n\tvar node = {\n\t\ttype: \"element\",\n\t\ttag: \"span\",\n\t\tattributes: {\n\t\t\t\"class\": {type: \"string\", value: \"tc-inline-style\"}\n\t\t},\n\t\tchildren: tree\n\t};\n\tif(classString) {\n\t\t$tw.utils.addClassToParseTreeNode(node,classString);\n\t}\n\tif(stylesString) {\n\t\t$tw.utils.addAttributeToParseTreeNode(node,\"style\",stylesString);\n\t}\n\treturn [node];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/syslink.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/syslink.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/syslink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for system tiddler links.\nCan be suppressed preceding them with `~`.\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"syslink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = new RegExp(\n\t\t\"~?\\\\$:\\\\/[\" +\n\t\t$tw.config.textPrimitives.anyLetter.substr(1,$tw.config.textPrimitives.anyLetter.length - 2) +\n\t\t\"\\/._-]+\",\n\t\t\"mg\"\n\t);\n};\n\nexports.parse = function() {\n\tvar match = this.match[0];\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Create the link unless it is suppressed\n\tif(match.substr(0,1) === \"~\") {\n\t\treturn [{type: \"text\", text: match.substr(1)}];\n\t} else {\n\t\treturn [{\n\t\t\ttype: \"link\",\n\t\t\tattributes: {\n\t\t\t\tto: {type: \"string\", value: match}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: match\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/table.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/table.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/table.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for tables.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"table\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\|(?:[^\\n]*)\\|(?:[fhck]?)\\r?(?:\\n|$)/mg;\n};\n\nvar processRow = function(prevColumns) {\n\tvar cellRegExp = /(?:\\|([^\\n\\|]*)\\|)|(\\|[fhck]?\\r?(?:\\n|$))/mg,\n\t\tcellTermRegExp = /((?:\\x20*)\\|)/mg,\n\t\ttree = [],\n\t\tcol = 0,\n\t\tcolSpanCount = 1,\n\t\tprevCell,\n\t\tvAlign;\n\t// Match a single cell\n\tcellRegExp.lastIndex = this.parser.pos;\n\tvar cellMatch = cellRegExp.exec(this.parser.source);\n\twhile(cellMatch && cellMatch.index === this.parser.pos) {\n\t\tif(cellMatch[1] === \"~\") {\n\t\t\t// Rowspan\n\t\t\tvar last = prevColumns[col];\n\t\t\tif(last) {\n\t\t\t\tlast.rowSpanCount++;\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(last.element,\"rowspan\",last.rowSpanCount);\n\t\t\t\tvAlign = $tw.utils.getAttributeValueFromParseTreeNode(last.element,\"valign\",\"center\");\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(last.element,\"valign\",vAlign);\n\t\t\t\tif(colSpanCount > 1) {\n\t\t\t\t\t$tw.utils.addAttributeToParseTreeNode(last.element,\"colspan\",colSpanCount);\n\t\t\t\t\tcolSpanCount = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Move to just before the `|` terminating the cell\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t} else if(cellMatch[1] === \">\") {\n\t\t\t// Colspan\n\t\t\tcolSpanCount++;\n\t\t\t// Move to just before the `|` terminating the cell\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t} else if(cellMatch[1] === \"<\" && prevCell) {\n\t\t\tcolSpanCount = 1 + $tw.utils.getAttributeValueFromParseTreeNode(prevCell,\"colspan\",1);\n\t\t\t$tw.utils.addAttributeToParseTreeNode(prevCell,\"colspan\",colSpanCount);\n\t\t\tcolSpanCount = 1;\n\t\t\t// Move to just before the `|` terminating the cell\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t} else if(cellMatch[2]) {\n\t\t\t// End of row\n\t\t\tif(prevCell && colSpanCount > 1) {\n\t\t\t\tif(prevCell.attributes && prevCell.attributes && prevCell.attributes.colspan) {\n\t\t\t\t\t\tcolSpanCount += prevCell.attributes.colspan.value;\n\t\t\t\t} else {\n\t\t\t\t\tcolSpanCount -= 1;\n\t\t\t\t}\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(prevCell,\"colspan\",colSpanCount);\n\t\t\t}\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t\tbreak;\n\t\t} else {\n\t\t\t// For ordinary cells, step beyond the opening `|`\n\t\t\tthis.parser.pos++;\n\t\t\t// Look for a space at the start of the cell\n\t\t\tvar spaceLeft = false;\n\t\t\tvAlign = null;\n\t\t\tif(this.parser.source.substr(this.parser.pos).search(/^\\^([^\\^]|\\^\\^)/) === 0) {\n\t\t\t\tvAlign = \"top\";\n\t\t\t} else if(this.parser.source.substr(this.parser.pos).search(/^,([^,]|,,)/) === 0) {\n\t\t\t\tvAlign = \"bottom\";\n\t\t\t}\n\t\t\tif(vAlign) {\n\t\t\t\tthis.parser.pos++;\n\t\t\t}\n\t\t\tvar chr = this.parser.source.substr(this.parser.pos,1);\n\t\t\twhile(chr === \" \") {\n\t\t\t\tspaceLeft = true;\n\t\t\t\tthis.parser.pos++;\n\t\t\t\tchr = this.parser.source.substr(this.parser.pos,1);\n\t\t\t}\n\t\t\t// Check whether this is a heading cell\n\t\t\tvar cell;\n\t\t\tif(chr === \"!\") {\n\t\t\t\tthis.parser.pos++;\n\t\t\t\tcell = {type: \"element\", tag: \"th\", children: []};\n\t\t\t} else {\n\t\t\t\tcell = {type: \"element\", tag: \"td\", children: []};\n\t\t\t}\n\t\t\ttree.push(cell);\n\t\t\t// Record information about this cell\n\t\t\tprevCell = cell;\n\t\t\tprevColumns[col] = {rowSpanCount:1,element:cell};\n\t\t\t// Check for a colspan\n\t\t\tif(colSpanCount > 1) {\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"colspan\",colSpanCount);\n\t\t\t\tcolSpanCount = 1;\n\t\t\t}\n\t\t\t// Parse the cell\n\t\t\tcell.children = this.parser.parseInlineRun(cellTermRegExp,{eatTerminator: true});\n\t\t\t// Set the alignment for the cell\n\t\t\tif(vAlign) {\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"valign\",vAlign);\n\t\t\t}\n\t\t\tif(this.parser.source.substr(this.parser.pos - 2,1) === \" \") { // spaceRight\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"align\",spaceLeft ? \"center\" : \"left\");\n\t\t\t} else if(spaceLeft) {\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"align\",\"right\");\n\t\t\t}\n\t\t\t// Move back to the closing `|`\n\t\t\tthis.parser.pos--;\n\t\t}\n\t\tcol++;\n\t\tcellRegExp.lastIndex = this.parser.pos;\n\t\tcellMatch = cellRegExp.exec(this.parser.source);\n\t}\n\treturn tree;\n};\n\nexports.parse = function() {\n\tvar rowContainerTypes = {\"c\":\"caption\", \"h\":\"thead\", \"\":\"tbody\", \"f\":\"tfoot\"},\n\t\ttable = {type: \"element\", tag: \"table\", children: []},\n\t\trowRegExp = /^\\|([^\\n]*)\\|([fhck]?)\\r?(?:\\n|$)/mg,\n\t\trowTermRegExp = /(\\|(?:[fhck]?)\\r?(?:\\n|$))/mg,\n\t\tprevColumns = [],\n\t\tcurrRowType,\n\t\trowContainer,\n\t\trowCount = 0;\n\t// Match the row\n\trowRegExp.lastIndex = this.parser.pos;\n\tvar rowMatch = rowRegExp.exec(this.parser.source);\n\twhile(rowMatch && rowMatch.index === this.parser.pos) {\n\t\tvar rowType = rowMatch[2];\n\t\t// Check if it is a class assignment\n\t\tif(rowType === \"k\") {\n\t\t\t$tw.utils.addClassToParseTreeNode(table,rowMatch[1]);\n\t\t\tthis.parser.pos = rowMatch.index + rowMatch[0].length;\n\t\t} else {\n\t\t\t// Otherwise, create a new row if this one is of a different type\n\t\t\tif(rowType !== currRowType) {\n\t\t\t\trowContainer = {type: \"element\", tag: rowContainerTypes[rowType], children: []};\n\t\t\t\ttable.children.push(rowContainer);\n\t\t\t\tcurrRowType = rowType;\n\t\t\t}\n\t\t\t// Is this a caption row?\n\t\t\tif(currRowType === \"c\") {\n\t\t\t\t// If so, move past the opening `|` of the row\n\t\t\t\tthis.parser.pos++;\n\t\t\t\t// Move the caption to the first row if it isn't already\n\t\t\t\tif(table.children.length !== 1) {\n\t\t\t\t\ttable.children.pop(); // Take rowContainer out of the children array\n\t\t\t\t\ttable.children.splice(0,0,rowContainer); // Insert it at the bottom\t\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t// Set the alignment - TODO: figure out why TW did this\n//\t\t\t\trowContainer.attributes.align = rowCount === 0 ? \"top\" : \"bottom\";\n\t\t\t\t// Parse the caption\n\t\t\t\trowContainer.children = this.parser.parseInlineRun(rowTermRegExp,{eatTerminator: true});\n\t\t\t} else {\n\t\t\t\t// Create the row\n\t\t\t\tvar theRow = {type: \"element\", tag: \"tr\", children: []};\n\t\t\t\t$tw.utils.addClassToParseTreeNode(theRow,rowCount%2 ? \"oddRow\" : \"evenRow\");\n\t\t\t\trowContainer.children.push(theRow);\n\t\t\t\t// Process the row\n\t\t\t\ttheRow.children = processRow.call(this,prevColumns);\n\t\t\t\tthis.parser.pos = rowMatch.index + rowMatch[0].length;\n\t\t\t\t// Increment the row count\n\t\t\t\trowCount++;\n\t\t\t}\n\t\t}\n\t\trowMatch = rowRegExp.exec(this.parser.source);\n\t}\n\treturn [table];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/transcludeblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/transcludeblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/transcludeblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for block-level transclusion. For example:\n\n```\n{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"transcludeblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{([^\\{\\}\\|]*)(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}(?:\\r?\\n|$)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar template = $tw.utils.trim(this.match[2]),\n\t\ttextRef = $tw.utils.trim(this.match[1]);\n\t// Prepare the transclude widget\n\tvar transcludeNode = {\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {},\n\t\t\tisBlock: true\n\t\t};\n\t// Prepare the tiddler widget\n\tvar tr, targetTitle, targetField, targetIndex, tiddlerNode;\n\tif(textRef) {\n\t\ttr = $tw.utils.parseTextReference(textRef);\n\t\ttargetTitle = tr.title;\n\t\ttargetField = tr.field;\n\t\ttargetIndex = tr.index;\n\t\ttiddlerNode = {\n\t\t\ttype: \"tiddler\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: targetTitle}\n\t\t\t},\n\t\t\tisBlock: true,\n\t\t\tchildren: [transcludeNode]\n\t\t};\n\t}\n\tif(template) {\n\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: template};\n\t\tif(textRef) {\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t} else {\n\t\tif(textRef) {\n\t\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: targetTitle};\n\t\t\tif(targetField) {\n\t\t\t\ttranscludeNode.attributes.field = {type: \"string\", value: targetField};\n\t\t\t}\n\t\t\tif(targetIndex) {\n\t\t\t\ttranscludeNode.attributes.index = {type: \"string\", value: targetIndex};\n\t\t\t}\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/transcludeinline.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/transcludeinline.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/transcludeinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for inline-level transclusion. For example:\n\n```\n{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"transcludeinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{([^\\{\\}\\|]*)(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar template = $tw.utils.trim(this.match[2]),\n\t\ttextRef = $tw.utils.trim(this.match[1]);\n\t// Prepare the transclude widget\n\tvar transcludeNode = {\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {}\n\t\t};\n\t// Prepare the tiddler widget\n\tvar tr, targetTitle, targetField, targetIndex, tiddlerNode;\n\tif(textRef) {\n\t\ttr = $tw.utils.parseTextReference(textRef);\n\t\ttargetTitle = tr.title;\n\t\ttargetField = tr.field;\n\t\ttargetIndex = tr.index;\n\t\ttiddlerNode = {\n\t\t\ttype: \"tiddler\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: targetTitle}\n\t\t\t},\n\t\t\tchildren: [transcludeNode]\n\t\t};\n\t}\n\tif(template) {\n\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: template};\n\t\tif(textRef) {\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t} else {\n\t\tif(textRef) {\n\t\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: targetTitle};\n\t\t\tif(targetField) {\n\t\t\t\ttranscludeNode.attributes.field = {type: \"string\", value: targetField};\n\t\t\t}\n\t\t\tif(targetIndex) {\n\t\t\t\ttranscludeNode.attributes.index = {type: \"string\", value: targetIndex};\n\t\t\t}\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/typedblock.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/typedblock.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/typedblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for typed blocks. For example:\n\n```\n$$$.js\nThis will be rendered as JavaScript\n$$$\n\n$$$.svg\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"150\" height=\"100\">\n  <circle cx=\"100\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"2\" fill=\"red\" />\n</svg>\n$$$\n\n$$$text/vnd.tiddlywiki>text/html\nThis will be rendered as an //HTML representation// of WikiText\n$$$\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.name = \"typedblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\$\\$\\$([^ >\\r\\n]*)(?: *> *([^ \\r\\n]+))?\\r?\\n/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /\\r?\\n\\$\\$\\$\\r?(?:\\n|$)/mg;\n\t// Save the type\n\tvar parseType = this.match[1],\n\t\trenderType = this.match[2];\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Look for the end of the block\n\treEnd.lastIndex = this.parser.pos;\n\tvar match = reEnd.exec(this.parser.source),\n\t\ttext;\n\t// Process the block\n\tif(match) {\n\t\ttext = this.parser.source.substring(this.parser.pos,match.index);\n\t\tthis.parser.pos = match.index + match[0].length;\n\t} else {\n\t\ttext = this.parser.source.substr(this.parser.pos);\n\t\tthis.parser.pos = this.parser.sourceLength;\n\t}\n\t// Parse the block according to the specified type\n\tvar parser = this.parser.wiki.parseText(parseType,text,{defaultType: \"text/plain\"});\n\t// If there's no render type, just return the parse tree\n\tif(!renderType) {\n\t\treturn parser.tree;\n\t} else {\n\t\t// Otherwise, render to the rendertype and return in a <PRE> tag\n\t\tvar widgetNode = this.parser.wiki.makeWidget(parser),\n\t\t\tcontainer = $tw.fakeDocument.createElement(\"div\");\n\t\twidgetNode.render(container,null);\n\t\ttext = renderType === \"text/html\" ? container.innerHTML : container.textContent;\n\t\treturn [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"pre\",\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: text\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/whitespace.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/whitespace.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/whitespace.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki pragma rule for whitespace specifications\n\n```\n\\whitespace trim\n\\whitespace notrim\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"whitespace\";\nexports.types = {pragma: true};\n\n/*\nInstantiate parse rule\n*/\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\\\whitespace[^\\S\\n]/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\tvar self = this;\n\t// Move past the pragma invocation\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse whitespace delimited tokens terminated by a line break\n\tvar reMatch = /[^\\S\\n]*(\\S+)|(\\r?\\n)/mg,\n\t\ttokens = [];\n\treMatch.lastIndex = this.parser.pos;\n\tvar match = reMatch.exec(this.parser.source);\n\twhile(match && match.index === this.parser.pos) {\n\t\tthis.parser.pos = reMatch.lastIndex;\n\t\t// Exit if we've got the line break\n\t\tif(match[2]) {\n\t\t\tbreak;\n\t\t}\n\t\t// Process the token\n\t\tif(match[1]) {\n\t\t\ttokens.push(match[1]);\n\t\t}\n\t\t// Match the next token\n\t\tmatch = reMatch.exec(this.parser.source);\n\t}\n\t// Process the tokens\n\t$tw.utils.each(tokens,function(token) {\n\t\tswitch(token) {\n\t\t\tcase \"trim\":\n\t\t\t\tself.parser.configTrimWhiteSpace = true;\n\t\t\t\tbreak;\n\t\t\tcase \"notrim\":\n\t\t\t\tself.parser.configTrimWhiteSpace = false;\n\t\t\t\tbreak;\n\t\t}\n\t});\n\t// No parse tree nodes to return\n\treturn [];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/rules/wikilink.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/wikilink.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/wikilink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for wiki links. For example:\n\n```\nAWikiLink\nAnotherLink\n~SuppressedLink\n```\n\nPrecede a camel case word with `~` to prevent it from being recognised as a link.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"wikilink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = new RegExp($tw.config.textPrimitives.unWikiLink + \"?\" + $tw.config.textPrimitives.wikiLink,\"mg\");\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get the details of the match\n\tvar linkText = this.match[0];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// If the link starts with the unwikilink character then just output it as plain text\n\tif(linkText.substr(0,1) === $tw.config.textPrimitives.unWikiLink) {\n\t\treturn [{type: \"text\", text: linkText.substr(1)}];\n\t}\n\t// If the link has been preceded with a blocked letter then don't treat it as a link\n\tif(this.match.index > 0) {\n\t\tvar preRegExp = new RegExp($tw.config.textPrimitives.blockPrefixLetters,\"mg\");\n\t\tpreRegExp.lastIndex = this.match.index-1;\n\t\tvar preMatch = preRegExp.exec(this.parser.source);\n\t\tif(preMatch && preMatch.index === this.match.index-1) {\n\t\t\treturn [{type: \"text\", text: linkText}];\n\t\t}\n\t}\n\treturn [{\n\t\ttype: \"link\",\n\t\tattributes: {\n\t\t\tto: {type: \"string\", value: linkText}\n\t\t},\n\t\tchildren: [{\n\t\t\ttype: \"text\",\n\t\t\ttext: linkText\n\t\t}]\n\t}];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikirule"
        },
        "$:/core/modules/parsers/wikiparser/wikiparser.js": {
            "title": "$:/core/modules/parsers/wikiparser/wikiparser.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/wikiparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe wiki text parser processes blocks of source text into a parse tree.\n\nThe parse tree is made up of nested arrays of these JavaScript objects:\n\n\t{type: \"element\", tag: <string>, attributes: {}, children: []} - an HTML element\n\t{type: \"text\", text: <string>} - a text node\n\t{type: \"entity\", value: <string>} - an entity\n\t{type: \"raw\", html: <string>} - raw HTML\n\nAttributes are stored as hashmaps of the following objects:\n\n\t{type: \"string\", value: <string>} - literal string\n\t{type: \"indirect\", textReference: <textReference>} - indirect through a text reference\n\t{type: \"macro\", macro: <TBD>} - indirect through a macro invocation\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar WikiParser = function(type,text,options) {\n\tthis.wiki = options.wiki;\n\tvar self = this;\n\t// Check for an externally linked tiddler\n\tif($tw.browser && (text || \"\") === \"\" && options._canonical_uri) {\n\t\tthis.loadRemoteTiddler(options._canonical_uri);\n\t\ttext = $tw.language.getRawString(\"LazyLoadingWarning\");\n\t}\n\t// Initialise the classes if we don't have them already\n\tif(!this.pragmaRuleClasses) {\n\t\tWikiParser.prototype.pragmaRuleClasses = $tw.modules.createClassesFromModules(\"wikirule\",\"pragma\",$tw.WikiRuleBase);\n\t\tthis.setupRules(WikiParser.prototype.pragmaRuleClasses,\"$:/config/WikiParserRules/Pragmas/\");\n\t}\n\tif(!this.blockRuleClasses) {\n\t\tWikiParser.prototype.blockRuleClasses = $tw.modules.createClassesFromModules(\"wikirule\",\"block\",$tw.WikiRuleBase);\n\t\tthis.setupRules(WikiParser.prototype.blockRuleClasses,\"$:/config/WikiParserRules/Block/\");\n\t}\n\tif(!this.inlineRuleClasses) {\n\t\tWikiParser.prototype.inlineRuleClasses = $tw.modules.createClassesFromModules(\"wikirule\",\"inline\",$tw.WikiRuleBase);\n\t\tthis.setupRules(WikiParser.prototype.inlineRuleClasses,\"$:/config/WikiParserRules/Inline/\");\n\t}\n\t// Save the parse text\n\tthis.type = type || \"text/vnd.tiddlywiki\";\n\tthis.source = text || \"\";\n\tthis.sourceLength = this.source.length;\n\t// Flag for ignoring whitespace\n\tthis.configTrimWhiteSpace = false;\n\t// Set current parse position\n\tthis.pos = 0;\n\t// Instantiate the pragma parse rules\n\tthis.pragmaRules = this.instantiateRules(this.pragmaRuleClasses,\"pragma\",0);\n\t// Instantiate the parser block and inline rules\n\tthis.blockRules = this.instantiateRules(this.blockRuleClasses,\"block\",0);\n\tthis.inlineRules = this.instantiateRules(this.inlineRuleClasses,\"inline\",0);\n\t// Parse any pragmas\n\tthis.tree = [];\n\tvar topBranch = this.parsePragmas();\n\t// Parse the text into inline runs or blocks\n\tif(options.parseAsInline) {\n\t\ttopBranch.push.apply(topBranch,this.parseInlineRun());\n\t} else {\n\t\ttopBranch.push.apply(topBranch,this.parseBlocks());\n\t}\n\t// Return the parse tree\n};\n\n/*\n*/\nWikiParser.prototype.loadRemoteTiddler = function(url) {\n\tvar self = this;\n\t$tw.utils.httpRequest({\n\t\turl: url,\n\t\ttype: \"GET\",\n\t\tcallback: function(err,data) {\n\t\t\tif(!err) {\n\t\t\t\tvar tiddlers = self.wiki.deserializeTiddlers(\".tid\",data,self.wiki.getCreationFields());\n\t\t\t\t$tw.utils.each(tiddlers,function(tiddler) {\n\t\t\t\t\ttiddler[\"_canonical_uri\"] = url;\n\t\t\t\t});\n\t\t\t\tif(tiddlers) {\n\t\t\t\t\tself.wiki.addTiddlers(tiddlers);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\n*/\nWikiParser.prototype.setupRules = function(proto,configPrefix) {\n\tvar self = this;\n\tif(!$tw.safemode) {\n\t\t$tw.utils.each(proto,function(object,name) {\n\t\t\tif(self.wiki.getTiddlerText(configPrefix + name,\"enable\") !== \"enable\") {\n\t\t\t\tdelete proto[name];\n\t\t\t}\n\t\t});\n\t}\n};\n\n/*\nInstantiate an array of parse rules\n*/\nWikiParser.prototype.instantiateRules = function(classes,type,startPos) {\n\tvar rulesInfo = [],\n\t\tself = this;\n\t$tw.utils.each(classes,function(RuleClass) {\n\t\t// Instantiate the rule\n\t\tvar rule = new RuleClass(self);\n\t\trule.is = {};\n\t\trule.is[type] = true;\n\t\trule.init(self);\n\t\tvar matchIndex = rule.findNextMatch(startPos);\n\t\tif(matchIndex !== undefined) {\n\t\t\trulesInfo.push({\n\t\t\t\trule: rule,\n\t\t\t\tmatchIndex: matchIndex\n\t\t\t});\n\t\t}\n\t});\n\treturn rulesInfo;\n};\n\n/*\nSkip any whitespace at the current position. Options are:\n\ttreatNewlinesAsNonWhitespace: true if newlines are NOT to be treated as whitespace\n*/\nWikiParser.prototype.skipWhitespace = function(options) {\n\toptions = options || {};\n\tvar whitespaceRegExp = options.treatNewlinesAsNonWhitespace ? /([^\\S\\n]+)/mg : /(\\s+)/mg;\n\twhitespaceRegExp.lastIndex = this.pos;\n\tvar whitespaceMatch = whitespaceRegExp.exec(this.source);\n\tif(whitespaceMatch && whitespaceMatch.index === this.pos) {\n\t\tthis.pos = whitespaceRegExp.lastIndex;\n\t}\n};\n\n/*\nGet the next match out of an array of parse rule instances\n*/\nWikiParser.prototype.findNextMatch = function(rules,startPos) {\n\t// Find the best matching rule by finding the closest match position\n\tvar matchingRule,\n\t\tmatchingRulePos = this.sourceLength;\n\t// Step through each rule\n\tfor(var t=0; t<rules.length; t++) {\n\t\tvar ruleInfo = rules[t];\n\t\t// Ask the rule to get the next match if we've moved past the current one\n\t\tif(ruleInfo.matchIndex !== undefined  && ruleInfo.matchIndex < startPos) {\n\t\t\truleInfo.matchIndex = ruleInfo.rule.findNextMatch(startPos);\n\t\t}\n\t\t// Adopt this match if it's closer than the current best match\n\t\tif(ruleInfo.matchIndex !== undefined && ruleInfo.matchIndex <= matchingRulePos) {\n\t\t\tmatchingRule = ruleInfo;\n\t\t\tmatchingRulePos = ruleInfo.matchIndex;\n\t\t}\n\t}\n\treturn matchingRule;\n};\n\n/*\nParse any pragmas at the beginning of a block of parse text\n*/\nWikiParser.prototype.parsePragmas = function() {\n\tvar currentTreeBranch = this.tree;\n\twhile(true) {\n\t\t// Skip whitespace\n\t\tthis.skipWhitespace();\n\t\t// Check for the end of the text\n\t\tif(this.pos >= this.sourceLength) {\n\t\t\tbreak;\n\t\t}\n\t\t// Check if we've arrived at a pragma rule match\n\t\tvar nextMatch = this.findNextMatch(this.pragmaRules,this.pos);\n\t\t// If not, just exit\n\t\tif(!nextMatch || nextMatch.matchIndex !== this.pos) {\n\t\t\tbreak;\n\t\t}\n\t\t// Process the pragma rule\n\t\tvar subTree = nextMatch.rule.parse();\n\t\tif(subTree.length > 0) {\n\t\t\t// Quick hack; we only cope with a single parse tree node being returned, which is true at the moment\n\t\t\tcurrentTreeBranch.push.apply(currentTreeBranch,subTree);\n\t\t\tsubTree[0].children = [];\n\t\t\tcurrentTreeBranch = subTree[0].children;\n\t\t}\n\t}\n\treturn currentTreeBranch;\n};\n\n/*\nParse a block from the current position\n\tterminatorRegExpString: optional regular expression string that identifies the end of plain paragraphs. Must not include capturing parenthesis\n*/\nWikiParser.prototype.parseBlock = function(terminatorRegExpString) {\n\tvar terminatorRegExp = terminatorRegExpString ? new RegExp(\"(\" + terminatorRegExpString + \"|\\\\r?\\\\n\\\\r?\\\\n)\",\"mg\") : /(\\r?\\n\\r?\\n)/mg;\n\tthis.skipWhitespace();\n\tif(this.pos >= this.sourceLength) {\n\t\treturn [];\n\t}\n\t// Look for a block rule that applies at the current position\n\tvar nextMatch = this.findNextMatch(this.blockRules,this.pos);\n\tif(nextMatch && nextMatch.matchIndex === this.pos) {\n\t\treturn nextMatch.rule.parse();\n\t}\n\t// Treat it as a paragraph if we didn't find a block rule\n\treturn [{type: \"element\", tag: \"p\", children: this.parseInlineRun(terminatorRegExp)}];\n};\n\n/*\nParse a series of blocks of text until a terminating regexp is encountered or the end of the text\n\tterminatorRegExpString: terminating regular expression\n*/\nWikiParser.prototype.parseBlocks = function(terminatorRegExpString) {\n\tif(terminatorRegExpString) {\n\t\treturn this.parseBlocksTerminated(terminatorRegExpString);\n\t} else {\n\t\treturn this.parseBlocksUnterminated();\n\t}\n};\n\n/*\nParse a block from the current position to the end of the text\n*/\nWikiParser.prototype.parseBlocksUnterminated = function() {\n\tvar tree = [];\n\twhile(this.pos < this.sourceLength) {\n\t\ttree.push.apply(tree,this.parseBlock());\n\t}\n\treturn tree;\n};\n\n/*\nParse blocks of text until a terminating regexp is encountered\n*/\nWikiParser.prototype.parseBlocksTerminated = function(terminatorRegExpString) {\n\tvar terminatorRegExp = new RegExp(\"(\" + terminatorRegExpString + \")\",\"mg\"),\n\t\ttree = [];\n\t// Skip any whitespace\n\tthis.skipWhitespace();\n\t//  Check if we've got the end marker\n\tterminatorRegExp.lastIndex = this.pos;\n\tvar match = terminatorRegExp.exec(this.source);\n\t// Parse the text into blocks\n\twhile(this.pos < this.sourceLength && !(match && match.index === this.pos)) {\n\t\tvar blocks = this.parseBlock(terminatorRegExpString);\n\t\ttree.push.apply(tree,blocks);\n\t\t// Skip any whitespace\n\t\tthis.skipWhitespace();\n\t\t//  Check if we've got the end marker\n\t\tterminatorRegExp.lastIndex = this.pos;\n\t\tmatch = terminatorRegExp.exec(this.source);\n\t}\n\tif(match && match.index === this.pos) {\n\t\tthis.pos = match.index + match[0].length;\n\t}\n\treturn tree;\n};\n\n/*\nParse a run of text at the current position\n\tterminatorRegExp: a regexp at which to stop the run\n\toptions: see below\nOptions available:\n\teatTerminator: move the parse position past any encountered terminator (default false)\n*/\nWikiParser.prototype.parseInlineRun = function(terminatorRegExp,options) {\n\tif(terminatorRegExp) {\n\t\treturn this.parseInlineRunTerminated(terminatorRegExp,options);\n\t} else {\n\t\treturn this.parseInlineRunUnterminated(options);\n\t}\n};\n\nWikiParser.prototype.parseInlineRunUnterminated = function(options) {\n\tvar tree = [];\n\t// Find the next occurrence of an inline rule\n\tvar nextMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t// Loop around the matches until we've reached the end of the text\n\twhile(this.pos < this.sourceLength && nextMatch) {\n\t\t// Process the text preceding the run rule\n\t\tif(nextMatch.matchIndex > this.pos) {\n\t\t\tthis.pushTextWidget(tree,this.source.substring(this.pos,nextMatch.matchIndex));\n\t\t\tthis.pos = nextMatch.matchIndex;\n\t\t}\n\t\t// Process the run rule\n\t\ttree.push.apply(tree,nextMatch.rule.parse());\n\t\t// Look for the next run rule\n\t\tnextMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t}\n\t// Process the remaining text\n\tif(this.pos < this.sourceLength) {\n\t\tthis.pushTextWidget(tree,this.source.substr(this.pos));\n\t}\n\tthis.pos = this.sourceLength;\n\treturn tree;\n};\n\nWikiParser.prototype.parseInlineRunTerminated = function(terminatorRegExp,options) {\n\toptions = options || {};\n\tvar tree = [];\n\t// Find the next occurrence of the terminator\n\tterminatorRegExp.lastIndex = this.pos;\n\tvar terminatorMatch = terminatorRegExp.exec(this.source);\n\t// Find the next occurrence of a inlinerule\n\tvar inlineRuleMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t// Loop around until we've reached the end of the text\n\twhile(this.pos < this.sourceLength && (terminatorMatch || inlineRuleMatch)) {\n\t\t// Return if we've found the terminator, and it precedes any inline rule match\n\t\tif(terminatorMatch) {\n\t\t\tif(!inlineRuleMatch || inlineRuleMatch.matchIndex >= terminatorMatch.index) {\n\t\t\t\tif(terminatorMatch.index > this.pos) {\n\t\t\t\t\tthis.pushTextWidget(tree,this.source.substring(this.pos,terminatorMatch.index));\n\t\t\t\t}\n\t\t\t\tthis.pos = terminatorMatch.index;\n\t\t\t\tif(options.eatTerminator) {\n\t\t\t\t\tthis.pos += terminatorMatch[0].length;\n\t\t\t\t}\n\t\t\t\treturn tree;\n\t\t\t}\n\t\t}\n\t\t// Process any inline rule, along with the text preceding it\n\t\tif(inlineRuleMatch) {\n\t\t\t// Preceding text\n\t\t\tif(inlineRuleMatch.matchIndex > this.pos) {\n\t\t\t\tthis.pushTextWidget(tree,this.source.substring(this.pos,inlineRuleMatch.matchIndex));\n\t\t\t\tthis.pos = inlineRuleMatch.matchIndex;\n\t\t\t}\n\t\t\t// Process the inline rule\n\t\t\ttree.push.apply(tree,inlineRuleMatch.rule.parse());\n\t\t\t// Look for the next inline rule\n\t\t\tinlineRuleMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t\t\t// Look for the next terminator match\n\t\t\tterminatorRegExp.lastIndex = this.pos;\n\t\t\tterminatorMatch = terminatorRegExp.exec(this.source);\n\t\t}\n\t}\n\t// Process the remaining text\n\tif(this.pos < this.sourceLength) {\n\t\tthis.pushTextWidget(tree,this.source.substr(this.pos));\n\t}\n\tthis.pos = this.sourceLength;\n\treturn tree;\n};\n\n/*\nPush a text widget onto an array, respecting the configTrimWhiteSpace setting\n*/\nWikiParser.prototype.pushTextWidget = function(array,text) {\n\tif(this.configTrimWhiteSpace) {\n\t\ttext = $tw.utils.trim(text);\n\t}\n\tif(text) {\n\t\tarray.push({type: \"text\", text: text});\t\t\n\t}\n};\n\n/*\nParse zero or more class specifiers `.classname`\n*/\nWikiParser.prototype.parseClasses = function() {\n\tvar classRegExp = /\\.([^\\s\\.]+)/mg,\n\t\tclassNames = [];\n\tclassRegExp.lastIndex = this.pos;\n\tvar match = classRegExp.exec(this.source);\n\twhile(match && match.index === this.pos) {\n\t\tthis.pos = match.index + match[0].length;\n\t\tclassNames.push(match[1]);\n\t\tmatch = classRegExp.exec(this.source);\n\t}\n\treturn classNames;\n};\n\n/*\nAmend the rules used by this instance of the parser\n\ttype: `only` keeps just the named rules, `except` keeps all but the named rules\n\tnames: array of rule names\n*/\nWikiParser.prototype.amendRules = function(type,names) {\n\tnames = names || [];\n\t// Define the filter function\n\tvar keepFilter;\n\tif(type === \"only\") {\n\t\tkeepFilter = function(name) {\n\t\t\treturn names.indexOf(name) !== -1;\n\t\t};\n\t} else if(type === \"except\") {\n\t\tkeepFilter = function(name) {\n\t\t\treturn names.indexOf(name) === -1;\n\t\t};\n\t} else {\n\t\treturn;\n\t}\n\t// Define a function to process each of our rule arrays\n\tvar processRuleArray = function(ruleArray) {\n\t\tfor(var t=ruleArray.length-1; t>=0; t--) {\n\t\t\tif(!keepFilter(ruleArray[t].rule.name)) {\n\t\t\t\truleArray.splice(t,1);\n\t\t\t}\n\t\t}\n\t};\n\t// Process each rule array\n\tprocessRuleArray(this.pragmaRules);\n\tprocessRuleArray(this.blockRules);\n\tprocessRuleArray(this.inlineRules);\n};\n\nexports[\"text/vnd.tiddlywiki\"] = WikiParser;\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "parser"
        },
        "$:/core/modules/parsers/wikiparser/rules/wikirulebase.js": {
            "title": "$:/core/modules/parsers/wikiparser/rules/wikirulebase.js",
            "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/wikirulebase.js\ntype: application/javascript\nmodule-type: global\n\nBase class for wiki parser rules\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nThis constructor is always overridden with a blank constructor, and so shouldn't be used\n*/\nvar WikiRuleBase = function() {\n};\n\n/*\nTo be overridden by individual rules\n*/\nWikiRuleBase.prototype.init = function(parser) {\n\tthis.parser = parser;\n};\n\n/*\nDefault implementation of findNextMatch uses RegExp matching\n*/\nWikiRuleBase.prototype.findNextMatch = function(startPos) {\n\tthis.matchRegExp.lastIndex = startPos;\n\tthis.match = this.matchRegExp.exec(this.parser.source);\n\treturn this.match ? this.match.index : undefined;\n};\n\nexports.WikiRuleBase = WikiRuleBase;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/pluginswitcher.js": {
            "title": "$:/core/modules/pluginswitcher.js",
            "text": "/*\\\ntitle: $:/core/modules/pluginswitcher.js\ntype: application/javascript\nmodule-type: global\n\nManages switching plugins for themes and languages.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\noptions:\nwiki: wiki store to be used\npluginType: type of plugin to be switched\ncontrollerTitle: title of tiddler used to control switching of this resource\ndefaultPlugins: array of default plugins to be used if nominated plugin isn't found\nonSwitch: callback when plugin is switched (single parameter is array of plugin titles)\n*/\nfunction PluginSwitcher(options) {\n\tthis.wiki = options.wiki;\n\tthis.pluginType = options.pluginType;\n\tthis.controllerTitle = options.controllerTitle;\n\tthis.defaultPlugins = options.defaultPlugins || [];\n\tthis.onSwitch = options.onSwitch;\n\t// Switch to the current plugin\n\tthis.switchPlugins();\n\t// Listen for changes to the selected plugin\n\tvar self = this;\n\tthis.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.utils.hop(changes,self.controllerTitle)) {\n\t\t\tself.switchPlugins();\n\t\t}\n\t});\n}\n\nPluginSwitcher.prototype.switchPlugins = function() {\n\t// Get the name of the current theme\n\tvar selectedPluginTitle = this.wiki.getTiddlerText(this.controllerTitle);\n\t// If it doesn't exist, then fallback to one of the default themes\n\tvar index = 0;\n\twhile(!this.wiki.getTiddler(selectedPluginTitle) && index < this.defaultPlugins.length) {\n\t\tselectedPluginTitle = this.defaultPlugins[index++];\n\t}\n\t// Accumulate the titles of the plugins that we need to load\n\tvar plugins = [],\n\t\tself = this,\n\t\taccumulatePlugin = function(title) {\n\t\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\t\tif(tiddler && tiddler.isPlugin() && plugins.indexOf(title) === -1) {\n\t\t\t\tplugins.push(title);\n\t\t\t\tvar pluginInfo = JSON.parse(self.wiki.getTiddlerText(title)),\n\t\t\t\t\tdependents = $tw.utils.parseStringArray(tiddler.fields.dependents || \"\");\n\t\t\t\t$tw.utils.each(dependents,function(title) {\n\t\t\t\t\taccumulatePlugin(title);\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\taccumulatePlugin(selectedPluginTitle);\n\t// Read the plugin info for the incoming plugins\n\tvar changes = $tw.wiki.readPluginInfo(plugins);\n\t// Unregister any existing theme tiddlers\n\tvar unregisteredTiddlers = $tw.wiki.unregisterPluginTiddlers(this.pluginType);\n\t// Register any new theme tiddlers\n\tvar registeredTiddlers = $tw.wiki.registerPluginTiddlers(this.pluginType,plugins);\n\t// Unpack the current theme tiddlers\n\t$tw.wiki.unpackPluginTiddlers();\n\t// Call the switch handler\n\tif(this.onSwitch) {\n\t\tthis.onSwitch(plugins);\n\t}\n};\n\nexports.PluginSwitcher = PluginSwitcher;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/saver-handler.js": {
            "title": "$:/core/modules/saver-handler.js",
            "text": "/*\\\ntitle: $:/core/modules/saver-handler.js\ntype: application/javascript\nmodule-type: global\n\nThe saver handler tracks changes to the store and handles saving the entire wiki via saver modules.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInstantiate the saver handler with the following options:\nwiki: wiki to be synced\ndirtyTracking: true if dirty tracking should be performed\n*/\nfunction SaverHandler(options) {\n\tvar self = this;\n\tthis.wiki = options.wiki;\n\tthis.dirtyTracking = options.dirtyTracking;\n\tthis.preloadDirty = options.preloadDirty || [];\n\tthis.pendingAutoSave = false;\n\t// Make a logger\n\tthis.logger = new $tw.utils.Logger(\"saver-handler\");\n\t// Initialise our savers\n\tif($tw.browser) {\n\t\tthis.initSavers();\n\t}\n\t// Only do dirty tracking if required\n\tif($tw.browser && this.dirtyTracking) {\n\t\t// Compile the dirty tiddler filter\n\t\tthis.filterFn = this.wiki.compileFilter(this.wiki.getTiddlerText(this.titleSyncFilter));\n\t\t// Count of changes that have not yet been saved\n\t\tvar filteredChanges = self.filterFn.call(self.wiki,function(iterator) {\n\t\t\t\t$tw.utils.each(self.preloadDirty,function(title) {\n\t\t\t\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\t\t\t\titerator(tiddler,title);\n\t\t\t\t});\n\t\t});\n\t\tthis.numChanges = filteredChanges.length;\n\t\t// Listen out for changes to tiddlers\n\t\tthis.wiki.addEventListener(\"change\",function(changes) {\n\t\t\t// Filter the changes so that we only count changes to tiddlers that we care about\n\t\t\tvar filteredChanges = self.filterFn.call(self.wiki,function(iterator) {\n\t\t\t\t$tw.utils.each(changes,function(change,title) {\n\t\t\t\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\t\t\t\titerator(tiddler,title);\n\t\t\t\t});\n\t\t\t});\n\t\t\t// Adjust the number of changes\n\t\t\tself.numChanges += filteredChanges.length;\n\t\t\tself.updateDirtyStatus();\n\t\t\t// Do any autosave if one is pending and there's no more change events\n\t\t\tif(self.pendingAutoSave && self.wiki.getSizeOfTiddlerEventQueue() === 0) {\n\t\t\t\t// Check if we're dirty\n\t\t\t\tif(self.numChanges > 0) {\n\t\t\t\t\tself.saveWiki({\n\t\t\t\t\t\tmethod: \"autosave\",\n\t\t\t\t\t\tdownloadType: \"text/plain\"\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tself.pendingAutoSave = false;\n\t\t\t}\n\t\t});\n\t\t// Listen for the autosave event\n\t\t$tw.rootWidget.addEventListener(\"tm-auto-save-wiki\",function(event) {\n\t\t\t// Do the autosave unless there are outstanding tiddler change events\n\t\t\tif(self.wiki.getSizeOfTiddlerEventQueue() === 0) {\n\t\t\t\t// Check if we're dirty\n\t\t\t\tif(self.numChanges > 0) {\n\t\t\t\t\tself.saveWiki({\n\t\t\t\t\t\tmethod: \"autosave\",\n\t\t\t\t\t\tdownloadType: \"text/plain\"\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Otherwise put ourselves in the \"pending autosave\" state and wait for the change event before we do the autosave\n\t\t\t\tself.pendingAutoSave = true;\n\t\t\t}\n\t\t});\n\t\t// Set up our beforeunload handler\n\t\t$tw.addUnloadTask(function(event) {\n\t\t\tvar confirmationMessage;\n\t\t\tif(self.isDirty()) {\n\t\t\t\tconfirmationMessage = $tw.language.getString(\"UnsavedChangesWarning\");\n\t\t\t\tevent.returnValue = confirmationMessage; // Gecko\n\t\t\t}\n\t\t\treturn confirmationMessage;\n\t\t});\n\t}\n\t// Install the save action handlers\n\tif($tw.browser) {\n\t\t$tw.rootWidget.addEventListener(\"tm-save-wiki\",function(event) {\n\t\t\tself.saveWiki({\n\t\t\t\ttemplate: event.param,\n\t\t\t\tdownloadType: \"text/plain\",\n\t\t\t\tvariables: event.paramObject\n\t\t\t});\n\t\t});\n\t\t$tw.rootWidget.addEventListener(\"tm-download-file\",function(event) {\n\t\t\tself.saveWiki({\n\t\t\t\tmethod: \"download\",\n\t\t\t\ttemplate: event.param,\n\t\t\t\tdownloadType: \"text/plain\",\n\t\t\t\tvariables: event.paramObject\n\t\t\t});\n\t\t});\n\t}\n}\n\nSaverHandler.prototype.titleSyncFilter = \"$:/config/SaverFilter\";\nSaverHandler.prototype.titleAutoSave = \"$:/config/AutoSave\";\nSaverHandler.prototype.titleSavedNotification = \"$:/language/Notifications/Save/Done\";\n\n/*\nSelect the appropriate saver modules and set them up\n*/\nSaverHandler.prototype.initSavers = function(moduleType) {\n\tmoduleType = moduleType || \"saver\";\n\t// Instantiate the available savers\n\tthis.savers = [];\n\tvar self = this;\n\t$tw.modules.forEachModuleOfType(moduleType,function(title,module) {\n\t\tif(module.canSave(self)) {\n\t\t\tself.savers.push(module.create(self.wiki));\n\t\t}\n\t});\n\t// Sort the savers into priority order\n\tthis.savers.sort(function(a,b) {\n\t\tif(a.info.priority < b.info.priority) {\n\t\t\treturn -1;\n\t\t} else {\n\t\t\tif(a.info.priority > b.info.priority) {\n\t\t\t\treturn +1;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\nSave the wiki contents. Options are:\n\tmethod: \"save\", \"autosave\" or \"download\"\n\ttemplate: the tiddler containing the template to save\n\tdownloadType: the content type for the saved file\n*/\nSaverHandler.prototype.saveWiki = function(options) {\n\toptions = options || {};\n\tvar self = this,\n\t\tmethod = options.method || \"save\";\n\t// Ignore autosave if disabled\n\tif(method === \"autosave\" && this.wiki.getTiddlerText(this.titleAutoSave,\"yes\") !== \"yes\") {\n\t\treturn false;\n\t}\n\tvar\tvariables = options.variables || {},\n\t\ttemplate = options.template || \"$:/core/save/all\",\n\t\tdownloadType = options.downloadType || \"text/plain\",\n\t\ttext = this.wiki.renderTiddler(downloadType,template,options),\n\t\tcallback = function(err) {\n\t\t\tif(err) {\n\t\t\t\talert($tw.language.getString(\"Error/WhileSaving\") + \":\\n\\n\" + err);\n\t\t\t} else {\n\t\t\t\t// Clear the task queue if we're saving (rather than downloading)\n\t\t\t\tif(method !== \"download\") {\n\t\t\t\t\tself.numChanges = 0;\n\t\t\t\t\tself.updateDirtyStatus();\n\t\t\t\t}\n\t\t\t\t$tw.notifier.display(self.titleSavedNotification);\n\t\t\t\tif(options.callback) {\n\t\t\t\t\toptions.callback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t// Call the highest priority saver that supports this method\n\tfor(var t=this.savers.length-1; t>=0; t--) {\n\t\tvar saver = this.savers[t];\n\t\tif(saver.info.capabilities.indexOf(method) !== -1 && saver.save(text,method,callback,{variables: {filename: variables.filename}})) {\n\t\t\tthis.logger.log(\"Saving wiki with method\",method,\"through saver\",saver.info.name);\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\n/*\nChecks whether the wiki is dirty (ie the window shouldn't be closed)\n*/\nSaverHandler.prototype.isDirty = function() {\n\treturn this.numChanges > 0;\n};\n\n/*\nUpdate the document body with the class \"tc-dirty\" if the wiki has unsaved/unsynced changes\n*/\nSaverHandler.prototype.updateDirtyStatus = function() {\n\tif($tw.browser) {\n\t\t$tw.utils.toggleClass(document.body,\"tc-dirty\",this.isDirty());\n\t}\n};\n\nexports.SaverHandler = SaverHandler;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/savers/andtidwiki.js": {
            "title": "$:/core/modules/savers/andtidwiki.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/andtidwiki.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via the AndTidWiki Android app\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false, netscape: false, Components: false */\n\"use strict\";\n\nvar AndTidWiki = function(wiki) {\n};\n\nAndTidWiki.prototype.save = function(text,method,callback,options) {\n\tvar filename = options && options.variables ? options.variables.filename : null;\n\tif (method === \"download\") {\n\t\t// Support download\n\t\tif (window.twi.saveDownload) {\n\t\t\ttry {\n\t\t\t\twindow.twi.saveDownload(text,filename);\n\t\t\t} catch(err) {\n\t\t\t\tif (err.message === \"Method not found\") {\n\t\t\t\t\twindow.twi.saveDownload(text);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tvar link = document.createElement(\"a\");\n\t\t\tlink.setAttribute(\"href\",\"data:text/plain,\" + encodeURIComponent(text));\n\t\t\tif (filename) {\n\t\t\t    link.setAttribute(\"download\",filename);\n\t\t\t}\n\t\t\tdocument.body.appendChild(link);\n\t\t\tlink.click();\n\t\t\tdocument.body.removeChild(link);\n\t\t}\n\t} else if (window.twi.saveWiki) {\n\t\t// Direct save in Tiddloid\n\t\twindow.twi.saveWiki(text);\n\t} else {\n\t\t// Get the pathname of this document\n\t\tvar pathname = decodeURIComponent(document.location.toString().split(\"#\")[0]);\n\t\t// Strip the file://\n\t\tif(pathname.indexOf(\"file://\") === 0) {\n\t\t\tpathname = pathname.substr(7);\n\t\t}\n\t\t// Strip any query or location part\n\t\tvar p = pathname.indexOf(\"?\");\n\t\tif(p !== -1) {\n\t\t\tpathname = pathname.substr(0,p);\n\t\t}\n\t\tp = pathname.indexOf(\"#\");\n\t\tif(p !== -1) {\n\t\t\tpathname = pathname.substr(0,p);\n\t\t}\n\t\t// Save the file\n\t\twindow.twi.saveFile(pathname,text);\n\t}\n\t// Call the callback\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nAndTidWiki.prototype.info = {\n\tname: \"andtidwiki\",\n\tpriority: 1600,\n\tcapabilities: [\"save\", \"autosave\", \"download\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn !!window.twi && !!window.twi.saveFile;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new AndTidWiki(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/beaker.js": {
            "title": "$:/core/modules/savers/beaker.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/beaker.js\ntype: application/javascript\nmodule-type: saver\n\nSaves files using the Beaker browser's (https://beakerbrowser.com) Dat protocol (https://datproject.org/)\nCompatible with beaker >= V0.7.2\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSet up the saver\n*/\nvar BeakerSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nBeakerSaver.prototype.save = function(text,method,callback) {\n\tvar dat = new DatArchive(\"\" + window.location),\n\t\tpathname = (\"\" + window.location.pathname).split(\"#\")[0];\n\tdat.stat(pathname).then(function(value) {\n\t\tif(value.isDirectory()) {\n\t\t\tpathname = pathname + \"/index.html\";\n\t\t}\n\t\tdat.writeFile(pathname,text,\"utf8\").then(function(value) {\n\t\t\tcallback(null);\n\t\t},function(reason) {\n\t\t\tcallback(\"Beaker Saver Write Error: \" + reason);\n\t\t});\n\t},function(reason) {\n\t\tcallback(\"Beaker Saver Stat Error: \" + reason);\n\t});\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nBeakerSaver.prototype.info = {\n\tname: \"beaker\",\n\tpriority: 3000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn !!window.DatArchive && location.protocol===\"dat:\";\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new BeakerSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/download.js": {
            "title": "$:/core/modules/savers/download.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/download.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via HTML5's download APIs\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar DownloadSaver = function(wiki) {\n};\n\nDownloadSaver.prototype.save = function(text,method,callback,options) {\n\toptions = options || {};\n\t// Get the current filename\n\tvar filename = options.variables.filename;\n\tif(!filename) {\n\t\tvar p = document.location.pathname.lastIndexOf(\"/\");\n\t\tif(p !== -1) {\n\t\t\t// We decode the pathname because document.location is URL encoded by the browser\n\t\t\tfilename = decodeURIComponent(document.location.pathname.substr(p+1));\n\t\t}\n\t}\n\tif(!filename) {\n\t\tfilename = \"tiddlywiki.html\";\n\t}\n\t// Set up the link\n\tvar link = document.createElement(\"a\");\n\tif(Blob !== undefined) {\n\t\tvar blob = new Blob([text], {type: \"text/html\"});\n\t\tlink.setAttribute(\"href\", URL.createObjectURL(blob));\n\t} else {\n\t\tlink.setAttribute(\"href\",\"data:text/html,\" + encodeURIComponent(text));\n\t}\n\tlink.setAttribute(\"download\",filename);\n\tdocument.body.appendChild(link);\n\tlink.click();\n\tdocument.body.removeChild(link);\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nDownloadSaver.prototype.info = {\n\tname: \"download\",\n\tpriority: 100\n};\n\nObject.defineProperty(DownloadSaver.prototype.info, \"capabilities\", {\n\tget: function() {\n\t\tvar capabilities = [\"save\", \"download\"];\n\t\tif(($tw.wiki.getTextReference(\"$:/config/DownloadSaver/AutoSave\") || \"\").toLowerCase() === \"yes\") {\n\t\t\tcapabilities.push(\"autosave\");\n\t\t}\n\t\treturn capabilities;\n\t}\n});\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn document.createElement(\"a\").download !== undefined;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new DownloadSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/fsosaver.js": {
            "title": "$:/core/modules/savers/fsosaver.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/fsosaver.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via MS FileSystemObject ActiveXObject\n\nNote: Since TiddlyWiki's markup contains the MOTW, the FileSystemObject normally won't be available. \nHowever, if the wiki is loaded as an .HTA file (Windows HTML Applications) then the FSO can be used.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar FSOSaver = function(wiki) {\n};\n\nFSOSaver.prototype.save = function(text,method,callback) {\n\t// Get the pathname of this document\n\tvar pathname = unescape(document.location.pathname);\n\t// Test for a Windows path of the form /x:\\blah...\n\tif(/^\\/[A-Z]\\:\\\\[^\\\\]+/i.test(pathname)) {\t// ie: ^/[a-z]:/[^/]+\n\t\t// Remove the leading slash\n\t\tpathname = pathname.substr(1);\n\t} else if(document.location.hostname !== \"\" && /^\\/\\\\[^\\\\]+\\\\[^\\\\]+/i.test(pathname)) {\t// test for \\\\server\\share\\blah... - ^/[^/]+/[^/]+\n\t\t// Remove the leading slash\n\t\tpathname = pathname.substr(1);\n\t\t// reconstruct UNC path\n\t\tpathname = \"\\\\\\\\\" + document.location.hostname + pathname;\n\t} else {\n\t\treturn false;\n\t}\n\t// Save the file (as UTF-16)\n\tvar fso = new ActiveXObject(\"Scripting.FileSystemObject\");\n\tvar file = fso.OpenTextFile(pathname,2,-1,-1);\n\tfile.Write(text);\n\tfile.Close();\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nFSOSaver.prototype.info = {\n\tname: \"FSOSaver\",\n\tpriority: 120,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\ttry {\n\t\treturn (window.location.protocol === \"file:\") && !!(new ActiveXObject(\"Scripting.FileSystemObject\"));\n\t} catch(e) { return false; }\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new FSOSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/gitea.js": {
            "title": "$:/core/modules/savers/gitea.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/gitea.js\ntype: application/javascript\nmodule-type: saver\n\nSaves wiki by pushing a commit to the gitea\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar GiteaSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nGiteaSaver.prototype.save = function(text,method,callback) {\n\tvar self = this,\n\t\tusername = this.wiki.getTiddlerText(\"$:/Gitea/Username\"),\n\t\tpassword = $tw.utils.getPassword(\"Gitea\"),\n\t\trepo = this.wiki.getTiddlerText(\"$:/Gitea/Repo\"),\n\t\tpath = this.wiki.getTiddlerText(\"$:/Gitea/Path\",\"\"),\n\t\tfilename = this.wiki.getTiddlerText(\"$:/Gitea/Filename\"),\n\t\tbranch = this.wiki.getTiddlerText(\"$:/Gitea/Branch\") || \"master\",\n\t\tendpoint = this.wiki.getTiddlerText(\"$:/Gitea/ServerURL\") || \"https://gitea\",\n\t\theaders = {\n\t\t\t\"Accept\": \"application/json\",\n\t\t\t\"Content-Type\": \"application/json;charset=UTF-8\",\n\t\t\t\"Authorization\": \"Basic \" + window.btoa(username + \":\" + password)\n\t\t};\n\t// Bail if we don't have everything we need\n\tif(!username || !password || !repo || !path || !filename) {\n\t\treturn false;\n\t}\n\t// Make sure the path start and ends with a slash\n\tif(path.substring(0,1) !== \"/\") {\n\t\tpath = \"/\" + path;\n\t}\n\tif(path.substring(path.length - 1) !== \"/\") {\n\t\tpath = path + \"/\";\n\t}\n\t// Compose the base URI\n\tvar uri = endpoint + \"/repos/\" + repo + \"/contents\" + path;\n\t// Perform a get request to get the details (inc shas) of files in the same path as our file\n\t$tw.utils.httpRequest({\n\t\turl: uri,\n\t\ttype: \"GET\",\n\t\theaders: headers,\n\t\tdata: {\n\t\t\tref: branch\n\t\t},\n\t\tcallback: function(err,getResponseDataJson,xhr) {\n\t\t\tvar getResponseData,sha = \"\";\n\t\t\tif(err && xhr.status !== 404) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tvar use_put = true;\n\t\t\tif(xhr.status !== 404) {\n\t\t\t\tgetResponseData = JSON.parse(getResponseDataJson);\n\t\t\t\t$tw.utils.each(getResponseData,function(details) {\n\t\t\t\t\tif(details.name === filename) {\n\t\t\t\t\t\tsha = details.sha;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif(sha === \"\"){\n\t\t\t\t\tuse_put = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar data = {\n\t\t\t\tmessage: $tw.language.getRawString(\"ControlPanel/Saving/GitService/CommitMessage\"),\n\t\t\t\tcontent: $tw.utils.base64Encode(text),\n\t\t\t\tsha: sha\n\t\t\t};\n\t\t\t$tw.utils.httpRequest({\n\t\t\t\turl: endpoint + \"/repos/\" + repo + \"/branches/\" + branch,\n\t\t\t\ttype: \"GET\",\n\t\t\t\theaders: headers,\n\t\t\t\tcallback: function(err,getResponseDataJson,xhr) {\n\t\t\t\t\tif(xhr.status === 404) {\n\t\t\t\t\t\tcallback(\"Please ensure the branch in the Gitea repo exists\");\n\t\t\t\t\t}else{\n\t\t\t\t\t\tdata[\"branch\"] = branch;\n\t\t\t\t\t\tself.upload(uri + filename, use_put?\"PUT\":\"POST\", headers, data, callback);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\treturn true;\n};\n\nGiteaSaver.prototype.upload = function(uri,method,headers,data,callback) {\n\t$tw.utils.httpRequest({\n\t\turl: uri,\n\t\ttype: method,\n\t\theaders: headers,\n\t\tdata: JSON.stringify(data),\n\t\tcallback: function(err,putResponseDataJson,xhr) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tvar putResponseData = JSON.parse(putResponseDataJson);\n\t\t\tcallback(null);\n\t\t}\n\t});\n};\n\n/*\nInformation about this saver\n*/\nGiteaSaver.prototype.info = {\n\tname: \"Gitea\",\n\tpriority: 2000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new GiteaSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/github.js": {
            "title": "$:/core/modules/savers/github.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/github.js\ntype: application/javascript\nmodule-type: saver\n\nSaves wiki by pushing a commit to the GitHub v3 REST API\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar GitHubSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nGitHubSaver.prototype.save = function(text,method,callback) {\n\tvar self = this,\n\t\tusername = this.wiki.getTiddlerText(\"$:/GitHub/Username\"),\n\t\tpassword = $tw.utils.getPassword(\"github\"),\n\t\trepo = this.wiki.getTiddlerText(\"$:/GitHub/Repo\"),\n\t\tpath = this.wiki.getTiddlerText(\"$:/GitHub/Path\",\"\"),\n\t\tfilename = this.wiki.getTiddlerText(\"$:/GitHub/Filename\"),\n\t\tbranch = this.wiki.getTiddlerText(\"$:/GitHub/Branch\") || \"master\",\n\t\tendpoint = this.wiki.getTiddlerText(\"$:/GitHub/ServerURL\") || \"https://api.github.com\",\n\t\theaders = {\n\t\t\t\"Accept\": \"application/vnd.github.v3+json\",\n\t\t\t\"Content-Type\": \"application/json;charset=UTF-8\",\n\t\t\t\"Authorization\": \"Basic \" + window.btoa(username + \":\" + password)\n\t\t};\n\t// Bail if we don't have everything we need\n\tif(!username || !password || !repo || !path || !filename) {\n\t\treturn false;\n\t}\n\t// Make sure the path start and ends with a slash\n\tif(path.substring(0,1) !== \"/\") {\n\t\tpath = \"/\" + path;\n\t}\n\tif(path.substring(path.length - 1) !== \"/\") {\n\t\tpath = path + \"/\";\n\t}\n\t// Compose the base URI\n\tvar uri = endpoint + \"/repos/\" + repo + \"/contents\" + path;\n\t// Perform a get request to get the details (inc shas) of files in the same path as our file\n\t$tw.utils.httpRequest({\n\t\turl: uri,\n\t\ttype: \"GET\",\n\t\theaders: headers,\n\t\tdata: {\n\t\t\tref: branch\n\t\t},\n\t\tcallback: function(err,getResponseDataJson,xhr) {\n\t\t\tvar getResponseData,sha = \"\";\n\t\t\tif(err && xhr.status !== 404) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tif(xhr.status !== 404) {\n\t\t\t\tgetResponseData = JSON.parse(getResponseDataJson);\n\t\t\t\t$tw.utils.each(getResponseData,function(details) {\n\t\t\t\t\tif(details.name === filename) {\n\t\t\t\t\t\tsha = details.sha;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tvar data = {\n\t\t\t\tmessage: $tw.language.getRawString(\"ControlPanel/Saving/GitService/CommitMessage\"),\n\t\t\t\tcontent: $tw.utils.base64Encode(text),\n\t\t\t\tbranch: branch,\n\t\t\t\tsha: sha\n\t\t\t};\n\t\t\t// Perform a PUT request to save the file\n\t\t\t$tw.utils.httpRequest({\n\t\t\t\turl: uri + filename,\n\t\t\t\ttype: \"PUT\",\n\t\t\t\theaders: headers,\n\t\t\t\tdata: JSON.stringify(data),\n\t\t\t\tcallback: function(err,putResponseDataJson,xhr) {\n\t\t\t\t\tif(err) {\n\t\t\t\t\t\treturn callback(err);\n\t\t\t\t\t}\n\t\t\t\t\tvar putResponseData = JSON.parse(putResponseDataJson);\n\t\t\t\t\tcallback(null);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nGitHubSaver.prototype.info = {\n\tname: \"github\",\n\tpriority: 2000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new GitHubSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/gitlab.js": {
            "title": "$:/core/modules/savers/gitlab.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/gitlab.js\ntype: application/javascript\nmodule-type: saver\n\nSaves wiki by pushing a commit to the GitLab REST API\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: true */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar GitLabSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nGitLabSaver.prototype.save = function(text,method,callback) {\n\t/* See https://docs.gitlab.com/ee/api/repository_files.html */\n\tvar self = this,\n\t\tusername = this.wiki.getTiddlerText(\"$:/GitLab/Username\"),\n\t\tpassword = $tw.utils.getPassword(\"gitlab\"),\n\t\trepo = this.wiki.getTiddlerText(\"$:/GitLab/Repo\"),\n\t\tpath = this.wiki.getTiddlerText(\"$:/GitLab/Path\",\"\"),\n\t\tfilename = this.wiki.getTiddlerText(\"$:/GitLab/Filename\"),\n\t\tbranch = this.wiki.getTiddlerText(\"$:/GitLab/Branch\") || \"master\",\n\t\tendpoint = this.wiki.getTiddlerText(\"$:/GitLab/ServerURL\") || \"https://gitlab.com/api/v4\",\n\t\theaders = {\n\t\t\t\"Content-Type\": \"application/json;charset=UTF-8\",\n\t\t\t\"Private-Token\": password\n\t\t};\n\t// Bail if we don't have everything we need\n\tif(!username || !password || !repo || !path || !filename) {\n\t\treturn false;\n\t}\n\t// Make sure the path start and ends with a slash\n\tif(path.substring(0,1) !== \"/\") {\n\t\tpath = \"/\" + path;\n\t}\n\tif(path.substring(path.length - 1) !== \"/\") {\n\t\tpath = path + \"/\";\n\t}\n\t// Compose the base URI\n\tvar uri = endpoint + \"/projects/\" + encodeURIComponent(repo) + \"/repository/\";\n\t// Perform a get request to get the details (inc shas) of files in the same path as our file\n\t$tw.utils.httpRequest({\n\t\turl: uri + \"tree/?path=\" + encodeURIComponent(path.replace(/^\\/+|\\/$/g, '')) + \"&branch=\" + encodeURIComponent(branch.replace(/^\\/+|\\/$/g, '')),\n\t\ttype: \"GET\",\n\t\theaders: headers,\n\t\tcallback: function(err,getResponseDataJson,xhr) {\n\t\t\tvar getResponseData,sha = \"\";\n\t\t\tif(err && xhr.status !== 404) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tvar requestType = \"POST\";\n\t\t\tif(xhr.status !== 404) {\n\t\t\t\tgetResponseData = JSON.parse(getResponseDataJson);\n\t\t\t\t$tw.utils.each(getResponseData,function(details) {\n\t\t\t\t\tif(details.name === filename) {\n\t\t\t\t\t\trequestType = \"PUT\";\n\t\t\t\t\t\tsha = details.sha;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tvar data = {\n\t\t\t\tcommit_message: $tw.language.getRawString(\"ControlPanel/Saving/GitService/CommitMessage\"),\n\t\t\t\tcontent: text,\n\t\t\t\tbranch: branch,\n\t\t\t\tsha: sha\n\t\t\t};\n\t\t\t// Perform a request to save the file\n\t\t\t$tw.utils.httpRequest({\n\t\t\t\turl: uri + \"files/\" + encodeURIComponent(path.replace(/^\\/+/, '') + filename),\n\t\t\t\ttype: requestType,\n\t\t\t\theaders: headers,\n\t\t\t\tdata: JSON.stringify(data),\n\t\t\t\tcallback: function(err,putResponseDataJson,xhr) {\n\t\t\t\t\tif(err) {\n\t\t\t\t\t\treturn callback(err);\n\t\t\t\t\t}\n\t\t\t\t\tvar putResponseData = JSON.parse(putResponseDataJson);\n\t\t\t\t\tcallback(null);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nGitLabSaver.prototype.info = {\n\tname: \"gitlab\",\n\tpriority: 2000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new GitLabSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/manualdownload.js": {
            "title": "$:/core/modules/savers/manualdownload.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/manualdownload.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via HTML5's download APIs\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Title of the tiddler containing the download message\nvar downloadInstructionsTitle = \"$:/language/Modals/Download\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar ManualDownloadSaver = function(wiki) {\n};\n\nManualDownloadSaver.prototype.save = function(text,method,callback) {\n\t$tw.modal.display(downloadInstructionsTitle,{\n\t\tdownloadLink: \"data:text/html,\" + encodeURIComponent(text)\n\t});\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nManualDownloadSaver.prototype.info = {\n\tname: \"manualdownload\",\n\tpriority: 0,\n\tcapabilities: [\"save\", \"download\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new ManualDownloadSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/msdownload.js": {
            "title": "$:/core/modules/savers/msdownload.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/msdownload.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via window.navigator.msSaveBlob()\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar MsDownloadSaver = function(wiki) {\n};\n\nMsDownloadSaver.prototype.save = function(text,method,callback) {\n\t// Get the current filename\n\tvar filename = \"tiddlywiki.html\",\n\t\tp = document.location.pathname.lastIndexOf(\"/\");\n\tif(p !== -1) {\n\t\tfilename = document.location.pathname.substr(p+1);\n\t}\n\t// Set up the link\n\tvar blob = new Blob([text], {type: \"text/html\"});\n\twindow.navigator.msSaveBlob(blob,filename);\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nMsDownloadSaver.prototype.info = {\n\tname: \"msdownload\",\n\tpriority: 110,\n\tcapabilities: [\"save\", \"download\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn !!window.navigator.msSaveBlob;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new MsDownloadSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/put.js": {
            "title": "$:/core/modules/savers/put.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/put.js\ntype: application/javascript\nmodule-type: saver\n\nSaves wiki by performing a PUT request to the server\n\nWorks with any server which accepts a PUT request\nto the current URL, such as a WebDAV server.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nRetrieve ETag if available\n*/\nvar retrieveETag = function(self) {\n\tvar headers = {\n\t\tAccept: \"*/*;charset=UTF-8\"\n\t};\n\t$tw.utils.httpRequest({\n\t\turl: self.uri(),\n\t\ttype: \"HEAD\",\n\t\theaders: headers,\n\t\tcallback: function(err,data,xhr) {\n\t\t\tif(err) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar etag = xhr.getResponseHeader(\"ETag\");\n\t\t\tif(!etag) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tself.etag = etag.replace(/^W\\//,\"\");\n\t\t}\n\t});\n};\n\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar PutSaver = function(wiki) {\n\tthis.wiki = wiki;\n\tvar self = this;\n\tvar uri = this.uri();\n\t// Async server probe. Until probe finishes, save will fail fast\n\t// See also https://github.com/Jermolene/TiddlyWiki5/issues/2276\n\t$tw.utils.httpRequest({\n\t\turl: uri,\n\t\ttype: \"OPTIONS\",\n\t\tcallback: function(err,data,xhr) {\n\t\t\t// Check DAV header http://www.webdav.org/specs/rfc2518.html#rfc.section.9.1\n\t\t\tif(!err) {\n\t\t\t\tself.serverAcceptsPuts = xhr.status === 200 && !!xhr.getResponseHeader(\"dav\");\n\t\t\t}\n\t\t}\n\t});\n\tretrieveETag(this);\n};\n\nPutSaver.prototype.uri = function() {\n\treturn document.location.toString().split(\"#\")[0];\n};\n\n// TODO: in case of edit conflict\n// Prompt: Do you want to save over this? Y/N\n// Merging would be ideal, and may be possible using future generic merge flow\nPutSaver.prototype.save = function(text,method,callback) {\n\tif(!this.serverAcceptsPuts) {\n\t\treturn false;\n\t}\n\tvar self = this;\n\tvar headers = {\n\t\t\"Content-Type\": \"text/html;charset=UTF-8\"\n\t};\n\tif(this.etag) {\n\t\theaders[\"If-Match\"] = this.etag;\n\t}\n\t$tw.utils.httpRequest({\n\t\turl: this.uri(),\n\t\ttype: \"PUT\",\n\t\theaders: headers,\n\t\tdata: text,\n\t\tcallback: function(err,data,xhr) {\n\t\t\tif(err) {\n\t\t\t\t// response is textual: \"XMLHttpRequest error code: 412\"\n\t\t\t\tvar status = Number(err.substring(err.indexOf(':') + 2, err.length))\n\t\t\t\tif(status === 412) { // edit conflict\n\t\t\t\t\tvar message = $tw.language.getString(\"Error/EditConflict\");\n\t\t\t\t\tcallback(message);\n\t\t\t\t} else {\n\t\t\t\t\tcallback(err); // fail\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tself.etag = xhr.getResponseHeader(\"ETag\");\n\t\t\t\tif(self.etag == null) {\n\t\t\t\t\tretrieveETag(self);\n\t\t\t\t}\n\t\t\t\tcallback(null); // success\n\t\t\t}\n\t\t}\n\t});\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nPutSaver.prototype.info = {\n\tname: \"put\",\n\tpriority: 2000,\n\tcapabilities: [\"save\",\"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn /^https?:/.test(location.protocol);\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new PutSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/tiddlyfox.js": {
            "title": "$:/core/modules/savers/tiddlyfox.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/tiddlyfox.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via the TiddlyFox file extension\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false, netscape: false, Components: false */\n\"use strict\";\n\nvar TiddlyFoxSaver = function(wiki) {\n};\n\nTiddlyFoxSaver.prototype.save = function(text,method,callback) {\n\tvar messageBox = document.getElementById(\"tiddlyfox-message-box\");\n\tif(messageBox) {\n\t\t// Get the pathname of this document\n\t\tvar pathname = document.location.toString().split(\"#\")[0];\n\t\t// Replace file://localhost/ with file:///\n\t\tif(pathname.indexOf(\"file://localhost/\") === 0) {\n\t\t\tpathname = \"file://\" + pathname.substr(16);\n\t\t}\n\t\t// Windows path file:///x:/blah/blah --> x:\\blah\\blah\n\t\tif(/^file\\:\\/\\/\\/[A-Z]\\:\\//i.test(pathname)) {\n\t\t\t// Remove the leading slash and convert slashes to backslashes\n\t\t\tpathname = pathname.substr(8).replace(/\\//g,\"\\\\\");\n\t\t// Firefox Windows network path file://///server/share/blah/blah --> //server/share/blah/blah\n\t\t} else if(pathname.indexOf(\"file://///\") === 0) {\n\t\t\tpathname = \"\\\\\\\\\" + unescape(pathname.substr(10)).replace(/\\//g,\"\\\\\");\n\t\t// Mac/Unix local path file:///path/path --> /path/path\n\t\t} else if(pathname.indexOf(\"file:///\") === 0) {\n\t\t\tpathname = unescape(pathname.substr(7));\n\t\t// Mac/Unix local path file:/path/path --> /path/path\n\t\t} else if(pathname.indexOf(\"file:/\") === 0) {\n\t\t\tpathname = unescape(pathname.substr(5));\n\t\t// Otherwise Windows networth path file://server/share/path/path --> \\\\server\\share\\path\\path\n\t\t} else {\n\t\t\tpathname = \"\\\\\\\\\" + unescape(pathname.substr(7)).replace(new RegExp(\"/\",\"g\"),\"\\\\\");\n\t\t}\n\t\t// Create the message element and put it in the message box\n\t\tvar message = document.createElement(\"div\");\n\t\tmessage.setAttribute(\"data-tiddlyfox-path\",decodeURIComponent(pathname));\n\t\tmessage.setAttribute(\"data-tiddlyfox-content\",text);\n\t\tmessageBox.appendChild(message);\n\t\t// Add an event handler for when the file has been saved\n\t\tmessage.addEventListener(\"tiddlyfox-have-saved-file\",function(event) {\n\t\t\tcallback(null);\n\t\t}, false);\n\t\t// Create and dispatch the custom event to the extension\n\t\tvar event = document.createEvent(\"Events\");\n\t\tevent.initEvent(\"tiddlyfox-save-file\",true,false);\n\t\tmessage.dispatchEvent(event);\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\nInformation about this saver\n*/\nTiddlyFoxSaver.prototype.info = {\n\tname: \"tiddlyfox\",\n\tpriority: 1500,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new TiddlyFoxSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/tiddlyie.js": {
            "title": "$:/core/modules/savers/tiddlyie.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/tiddlyie.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via Internet Explorer BHO extenion (TiddlyIE)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar TiddlyIESaver = function(wiki) {\n};\n\nTiddlyIESaver.prototype.save = function(text,method,callback) {\n\t// Check existence of TiddlyIE BHO extension (note: only works after document is complete)\n\tif(typeof(window.TiddlyIE) != \"undefined\") {\n\t\t// Get the pathname of this document\n\t\tvar pathname = unescape(document.location.pathname);\n\t\t// Test for a Windows path of the form /x:/blah...\n\t\tif(/^\\/[A-Z]\\:\\/[^\\/]+/i.test(pathname)) {\t// ie: ^/[a-z]:/[^/]+ (is this better?: ^/[a-z]:/[^/]+(/[^/]+)*\\.[^/]+ )\n\t\t\t// Remove the leading slash\n\t\t\tpathname = pathname.substr(1);\n\t\t\t// Convert slashes to backslashes\n\t\t\tpathname = pathname.replace(/\\//g,\"\\\\\");\n\t\t} else if(document.hostname !== \"\" && /^\\/[^\\/]+\\/[^\\/]+/i.test(pathname)) {\t// test for \\\\server\\share\\blah... - ^/[^/]+/[^/]+\n\t\t\t// Convert slashes to backslashes\n\t\t\tpathname = pathname.replace(/\\//g,\"\\\\\");\n\t\t\t// reconstruct UNC path\n\t\t\tpathname = \"\\\\\\\\\" + document.location.hostname + pathname;\n\t\t} else return false;\n\t\t// Prompt the user to save the file\n\t\twindow.TiddlyIE.save(pathname, text);\n\t\t// Callback that we succeeded\n\t\tcallback(null);\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\nInformation about this saver\n*/\nTiddlyIESaver.prototype.info = {\n\tname: \"tiddlyiesaver\",\n\tpriority: 1500,\n\tcapabilities: [\"save\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn (window.location.protocol === \"file:\");\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new TiddlyIESaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/twedit.js": {
            "title": "$:/core/modules/savers/twedit.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/twedit.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via the TWEdit iOS app\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false, netscape: false, Components: false */\n\"use strict\";\n\nvar TWEditSaver = function(wiki) {\n};\n\nTWEditSaver.prototype.save = function(text,method,callback) {\n\t// Bail if we're not running under TWEdit\n\tif(typeof DeviceInfo !== \"object\") {\n\t\treturn false;\n\t}\n\t// Get the pathname of this document\n\tvar pathname = decodeURIComponent(document.location.pathname);\n\t// Strip any query or location part\n\tvar p = pathname.indexOf(\"?\");\n\tif(p !== -1) {\n\t\tpathname = pathname.substr(0,p);\n\t}\n\tp = pathname.indexOf(\"#\");\n\tif(p !== -1) {\n\t\tpathname = pathname.substr(0,p);\n\t}\n\t// Remove the leading \"/Documents\" from path\n\tvar prefix = \"/Documents\";\n\tif(pathname.indexOf(prefix) === 0) {\n\t\tpathname = pathname.substr(prefix.length);\n\t}\n\t// Error handler\n\tvar errorHandler = function(event) {\n\t\t// Error\n\t\tcallback($tw.language.getString(\"Error/SavingToTWEdit\") + \": \" + event.target.error.code);\n\t};\n\t// Get the file system\n\twindow.requestFileSystem(LocalFileSystem.PERSISTENT,0,function(fileSystem) {\n\t\t// Now we've got the filesystem, get the fileEntry\n\t\tfileSystem.root.getFile(pathname, {create: true}, function(fileEntry) {\n\t\t\t// Now we've got the fileEntry, create the writer\n\t\t\tfileEntry.createWriter(function(writer) {\n\t\t\t\twriter.onerror = errorHandler;\n\t\t\t\twriter.onwrite = function() {\n\t\t\t\t\tcallback(null);\n\t\t\t\t};\n\t\t\t\twriter.position = 0;\n\t\t\t\twriter.write(text);\n\t\t\t},errorHandler);\n\t\t}, errorHandler);\n\t}, errorHandler);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nTWEditSaver.prototype.info = {\n\tname: \"twedit\",\n\tpriority: 1600,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new TWEditSaver(wiki);\n};\n\n/////////////////////////// Hack\n// HACK: This ensures that TWEdit recognises us as a TiddlyWiki document\nif($tw.browser) {\n\twindow.version = {title: \"TiddlyWiki\"};\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/savers/upload.js": {
            "title": "$:/core/modules/savers/upload.js",
            "text": "/*\\\ntitle: $:/core/modules/savers/upload.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via upload to a server.\n\nDesigned to be compatible with BidiX's UploadPlugin at http://tiddlywiki.bidix.info/#UploadPlugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar UploadSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nUploadSaver.prototype.save = function(text,method,callback) {\n\t// Get the various parameters we need\n\tvar backupDir = this.wiki.getTextReference(\"$:/UploadBackupDir\") || \".\",\n\t\tusername = this.wiki.getTextReference(\"$:/UploadName\"),\n\t\tpassword = $tw.utils.getPassword(\"upload\"),\n\t\tuploadDir = this.wiki.getTextReference(\"$:/UploadDir\") || \".\",\n\t\tuploadFilename = this.wiki.getTextReference(\"$:/UploadFilename\") || \"index.html\",\n\t\turl = this.wiki.getTextReference(\"$:/UploadURL\");\n\t// Bail out if we don't have the bits we need\n\tif(!username || username.toString().trim() === \"\" || !password || password.toString().trim() === \"\") {\n\t\treturn false;\n\t}\n\t// Construct the url if not provided\n\tif(!url) {\n\t\turl = \"http://\" + username + \".tiddlyspot.com/store.cgi\";\n\t}\n\t// Assemble the header\n\tvar boundary = \"---------------------------\" + \"AaB03x\";\t\n\tvar uploadFormName = \"UploadPlugin\";\n\tvar head = [];\n\thead.push(\"--\" + boundary + \"\\r\\nContent-disposition: form-data; name=\\\"UploadPlugin\\\"\\r\\n\");\n\thead.push(\"backupDir=\" + backupDir + \";user=\" + username + \";password=\" + password + \";uploaddir=\" + uploadDir + \";;\"); \n\thead.push(\"\\r\\n\" + \"--\" + boundary);\n\thead.push(\"Content-disposition: form-data; name=\\\"userfile\\\"; filename=\\\"\" + uploadFilename + \"\\\"\");\n\thead.push(\"Content-Type: text/html;charset=UTF-8\");\n\thead.push(\"Content-Length: \" + text.length + \"\\r\\n\");\n\thead.push(\"\");\n\t// Assemble the tail and the data itself\n\tvar tail = \"\\r\\n--\" + boundary + \"--\\r\\n\",\n\t\tdata = head.join(\"\\r\\n\") + text + tail;\n\t// Do the HTTP post\n\tvar http = new XMLHttpRequest();\n\thttp.open(\"POST\",url,true,username,password);\n\thttp.setRequestHeader(\"Content-Type\",\"multipart/form-data; charset=UTF-8; boundary=\" + boundary);\n\thttp.onreadystatechange = function() {\n\t\tif(http.readyState == 4 && http.status == 200) {\n\t\t\tif(http.responseText.substr(0,4) === \"0 - \") {\n\t\t\t\tcallback(null);\n\t\t\t} else {\n\t\t\t\tcallback(http.responseText);\n\t\t\t}\n\t\t}\n\t};\n\ttry {\n\t\thttp.send(data);\n\t} catch(ex) {\n\t\treturn callback($tw.language.getString(\"Error/Caption\") + \":\" + ex);\n\t}\n\t$tw.notifier.display(\"$:/language/Notifications/Save/Starting\");\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nUploadSaver.prototype.info = {\n\tname: \"upload\",\n\tpriority: 2000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new UploadSaver(wiki);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "saver"
        },
        "$:/core/modules/server/authenticators/basic.js": {
            "title": "$:/core/modules/server/authenticators/basic.js",
            "text": "/*\\\ntitle: $:/core/modules/server/authenticators/basic.js\ntype: application/javascript\nmodule-type: authenticator\n\nAuthenticator for WWW basic authentication\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nif($tw.node) {\n\tvar util = require(\"util\"),\n\t\tfs = require(\"fs\"),\n\t\turl = require(\"url\"),\n\t\tpath = require(\"path\");\n}\n\nfunction BasicAuthenticator(server) {\n\tthis.server = server;\n\tthis.credentialsData = [];\n}\n\n/*\nReturns true if the authenticator is active, false if it is inactive, or a string if there is an error\n*/\nBasicAuthenticator.prototype.init = function() {\n\t// Read the credentials data\n\tthis.credentialsFilepath = this.server.get(\"credentials\");\n\tif(this.credentialsFilepath) {\n\t\tvar resolveCredentialsFilepath = path.resolve($tw.boot.wikiPath,this.credentialsFilepath);\n\t\tif(fs.existsSync(resolveCredentialsFilepath) && !fs.statSync(resolveCredentialsFilepath).isDirectory()) {\n\t\t\tvar credentialsText = fs.readFileSync(resolveCredentialsFilepath,\"utf8\"),\n\t\t\t\tcredentialsData = $tw.utils.parseCsvStringWithHeader(credentialsText);\n\t\t\tif(typeof credentialsData === \"string\") {\n\t\t\t\treturn \"Error: \" + credentialsData + \" reading credentials from '\" + resolveCredentialsFilepath + \"'\";\n\t\t\t} else {\n\t\t\t\tthis.credentialsData = credentialsData;\n\t\t\t}\n\t\t} else {\n\t\t\treturn \"Error: Unable to load user credentials from '\" + resolveCredentialsFilepath + \"'\";\n\t\t}\n\t}\n\t// Add the hardcoded username and password if specified\n\tif(this.server.get(\"username\") && this.server.get(\"password\")) {\n\t\tthis.credentialsData = this.credentialsData || [];\n\t\tthis.credentialsData.push({\n\t\t\tusername: this.server.get(\"username\"),\n\t\t\tpassword: this.server.get(\"password\")\n\t\t});\n\t}\n\treturn this.credentialsData.length > 0;\n};\n\n/*\nReturns true if the request is authenticated and assigns the \"authenticatedUsername\" state variable.\nReturns false if the request couldn't be authenticated having sent an appropriate response to the browser\n*/\nBasicAuthenticator.prototype.authenticateRequest = function(request,response,state) {\n\t// Extract the incoming username and password from the request\n\tvar header = request.headers.authorization || \"\";\n\tif(!header && state.allowAnon) {\n\t\t// If there's no header and anonymous access is allowed then we don't set authenticatedUsername\n\t\treturn true;\n\t}\n\tvar token = header.split(/\\s+/).pop() || \"\",\n\t\tauth = $tw.utils.base64Decode(token),\n\t\tparts = auth.split(/:/),\n\t\tincomingUsername = parts[0],\n\t\tincomingPassword = parts[1];\n\t// Check that at least one of the credentials matches\n\tvar matchingCredentials = this.credentialsData.find(function(credential) {\n\t\treturn credential.username === incomingUsername && credential.password === incomingPassword;\n\t});\n\tif(matchingCredentials) {\n\t\t// If so, add the authenticated username to the request state\n\t\tstate.authenticatedUsername = incomingUsername;\n\t\treturn true;\n\t} else {\n\t\t// If not, return an authentication challenge\n\t\tresponse.writeHead(401,\"Authentication required\",{\n\t\t\t\"WWW-Authenticate\": 'Basic realm=\"Please provide your username and password to login to ' + state.server.servername + '\"'\n\t\t});\n\t\tresponse.end();\n\t\treturn false;\n\t}\n};\n\nexports.AuthenticatorClass = BasicAuthenticator;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "authenticator"
        },
        "$:/core/modules/server/authenticators/header.js": {
            "title": "$:/core/modules/server/authenticators/header.js",
            "text": "/*\\\ntitle: $:/core/modules/server/authenticators/header.js\ntype: application/javascript\nmodule-type: authenticator\n\nAuthenticator for trusted header authentication\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nfunction HeaderAuthenticator(server) {\n\tthis.server = server;\n\tthis.header = server.get(\"authenticated-user-header\");\n}\n\n/*\nReturns true if the authenticator is active, false if it is inactive, or a string if there is an error\n*/\nHeaderAuthenticator.prototype.init = function() {\n\treturn !!this.header;\n};\n\n/*\nReturns true if the request is authenticated and assigns the \"authenticatedUsername\" state variable.\nReturns false if the request couldn't be authenticated having sent an appropriate response to the browser\n*/\nHeaderAuthenticator.prototype.authenticateRequest = function(request,response,state) {\n\t// Otherwise, authenticate as the username in the specified header\n\tvar username = request.headers[this.header];\n\tif(!username && !state.allowAnon) {\n\t\tresponse.writeHead(401,\"Authorization header required to login to '\" + state.server.servername + \"'\");\n\t\tresponse.end();\n\t\treturn false;\n\t} else {\n\t\t// authenticatedUsername will be undefined for anonymous users\n\t\tstate.authenticatedUsername = username;\n\t\treturn true;\n\t}\n};\n\nexports.AuthenticatorClass = HeaderAuthenticator;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "authenticator"
        },
        "$:/core/modules/server/routes/delete-tiddler.js": {
            "title": "$:/core/modules/server/routes/delete-tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/delete-tiddler.js\ntype: application/javascript\nmodule-type: route\n\nDELETE /recipes/default/tiddlers/:title\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"DELETE\";\n\nexports.path = /^\\/bags\\/default\\/tiddlers\\/(.+)$/;\n\nexports.handler = function(request,response,state) {\n\tvar title = decodeURIComponent(state.params[0]);\n\tstate.wiki.deleteTiddler(title);\n\tresponse.writeHead(204, \"OK\", {\n\t\t\"Content-Type\": \"text/plain\"\n\t});\n\tresponse.end();\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-favicon.js": {
            "title": "$:/core/modules/server/routes/get-favicon.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-favicon.js\ntype: application/javascript\nmodule-type: route\n\nGET /favicon.ico\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/favicon.ico$/;\n\nexports.handler = function(request,response,state) {\n\tresponse.writeHead(200, {\"Content-Type\": \"image/x-icon\"});\n\tvar buffer = state.wiki.getTiddlerText(\"$:/favicon.ico\",\"\");\n\tresponse.end(buffer,\"base64\");\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-file.js": {
            "title": "$:/core/modules/server/routes/get-file.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-file.js\ntype: application/javascript\nmodule-type: route\n\nGET /files/:filepath\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/files\\/(.+)$/;\n\nexports.handler = function(request,response,state) {\n\tvar path = require(\"path\"),\n\t\tfs = require(\"fs\"),\n\t\tutil = require(\"util\"),\n\t\tsuppliedFilename = decodeURIComponent(state.params[0]),\n\t\tfilename = path.resolve($tw.boot.wikiPath,\"files\",suppliedFilename),\n\t\textension = path.extname(filename);\n\tfs.readFile(filename,function(err,content) {\n\t\tvar status,content,type = \"text/plain\";\n\t\tif(err) {\n\t\t\tconsole.log(\"Error accessing file \" + filename + \": \" + err.toString());\n\t\t\tstatus = 404;\n\t\t\tcontent = \"File '\" + suppliedFilename + \"' not found\";\n\t\t} else {\n\t\t\tstatus = 200;\n\t\t\tcontent = content;\n\t\t\ttype = ($tw.config.fileExtensionInfo[extension] ? $tw.config.fileExtensionInfo[extension].type : \"application/octet-stream\");\n\t\t}\n\t\tresponse.writeHead(status,{\n\t\t\t\"Content-Type\": type\n\t\t});\n\t\tresponse.end(content);\n\t});\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-index.js": {
            "title": "$:/core/modules/server/routes/get-index.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-index.js\ntype: application/javascript\nmodule-type: route\n\nGET /\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar zlib = require(\"zlib\");\n\nexports.method = \"GET\";\n\nexports.path = /^\\/$/;\n\nexports.handler = function(request,response,state) {\n\tvar acceptEncoding = request.headers[\"accept-encoding\"];\n\tif(!acceptEncoding) {\n\t\tacceptEncoding = \"\";\n\t}\n\tvar text = state.wiki.renderTiddler(state.server.get(\"root-render-type\"),state.server.get(\"root-tiddler\")),\n\t\tresponseHeaders = {\n\t\t\"Content-Type\": state.server.get(\"root-serve-type\")\n\t};\n\t/*\n\tIf the gzip=yes flag for `listen` is set, check if the user agent permits\n\tcompression. If so, compress our response. Note that we use the synchronous\n\tfunctions from zlib to stay in the imperative style. The current `Server`\n\tdoesn't depend on this, and we may just as well use the async versions.\n\t*/\n\tif(state.server.enableGzip) {\n\t\tif (/\\bdeflate\\b/.test(acceptEncoding)) {\n\t\t\tresponseHeaders[\"Content-Encoding\"] = \"deflate\";\n\t\t\ttext = zlib.deflateSync(text);\n\t\t} else if (/\\bgzip\\b/.test(acceptEncoding)) {\n\t\t\tresponseHeaders[\"Content-Encoding\"] = \"gzip\";\n\t\t\ttext = zlib.gzipSync(text);\n\t\t}\n\t}\n\tresponse.writeHead(200,responseHeaders);\n\tresponse.end(text);\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-login-basic.js": {
            "title": "$:/core/modules/server/routes/get-login-basic.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-login-basic.js\ntype: application/javascript\nmodule-type: route\n\nGET /login-basic -- force a Basic Authentication challenge\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/login-basic$/;\n\nexports.handler = function(request,response,state) {\n\tif(!state.authenticatedUsername) {\n\t\t// Challenge if there's no username\n\t\tresponse.writeHead(401,{\n\t\t\t\"WWW-Authenticate\": 'Basic realm=\"Please provide your username and password to login to ' + state.server.servername + '\"'\n\t\t});\n\t\tresponse.end();\t\t\n\t} else {\n\t\t// Redirect to the root wiki if login worked\n\t\tresponse.writeHead(302,{\n\t\t\tLocation: \"/\"\n\t\t});\n\t\tresponse.end();\n\t}\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-status.js": {
            "title": "$:/core/modules/server/routes/get-status.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-status.js\ntype: application/javascript\nmodule-type: route\n\nGET /status\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/status$/;\n\nexports.handler = function(request,response,state) {\n\tresponse.writeHead(200, {\"Content-Type\": \"application/json\"});\n\tvar text = JSON.stringify({\n\t\tusername: state.authenticatedUsername || state.server.get(\"anon-username\") || \"\",\n\t\tanonymous: !state.authenticatedUsername,\n\t\tread_only: !state.server.isAuthorized(\"writers\",state.authenticatedUsername),\n\t\tspace: {\n\t\t\trecipe: \"default\"\n\t\t},\n\t\ttiddlywiki_version: $tw.version\n\t});\n\tresponse.end(text,\"utf8\");\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-tiddler-html.js": {
            "title": "$:/core/modules/server/routes/get-tiddler-html.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-tiddler-html.js\ntype: application/javascript\nmodule-type: route\n\nGET /:title\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/([^\\/]+)$/;\n\nexports.handler = function(request,response,state) {\n\tvar title = decodeURIComponent(state.params[0]),\n\t\ttiddler = state.wiki.getTiddler(title);\n\tif(tiddler) {\n\t\tvar renderType = tiddler.getFieldString(\"_render_type\"),\n\t\t\trenderTemplate = tiddler.getFieldString(\"_render_template\");\n\t\t// Tiddler fields '_render_type' and '_render_template' overwrite\n\t\t// system wide settings for render type and template\n\t\tif(state.wiki.isSystemTiddler(title)) {\n\t\t\trenderType = renderType || state.server.get(\"system-tiddler-render-type\");\n\t\t\trenderTemplate = renderTemplate || state.server.get(\"system-tiddler-render-template\");\n\t\t} else {\n\t\t\trenderType = renderType || state.server.get(\"tiddler-render-type\");\n\t\t\trenderTemplate = renderTemplate || state.server.get(\"tiddler-render-template\");\n\t\t}\n\t\tvar text = state.wiki.renderTiddler(renderType,renderTemplate,{parseAsInline: true, variables: {currentTiddler: title}});\n\t\t// Naughty not to set a content-type, but it's the easiest way to ensure the browser will see HTML pages as HTML, and accept plain text tiddlers as CSS or JS\n\t\tresponse.writeHead(200);\n\t\tresponse.end(text,\"utf8\");\n\t} else {\n\t\tresponse.writeHead(404);\n\t\tresponse.end();\n\t}\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-tiddler.js": {
            "title": "$:/core/modules/server/routes/get-tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-tiddler.js\ntype: application/javascript\nmodule-type: route\n\nGET /recipes/default/tiddlers/:title\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/recipes\\/default\\/tiddlers\\/(.+)$/;\n\nexports.handler = function(request,response,state) {\n\tvar title = decodeURIComponent(state.params[0]),\n\t\ttiddler = state.wiki.getTiddler(title),\n\t\ttiddlerFields = {},\n\t\tknownFields = [\n\t\t\t\"bag\", \"created\", \"creator\", \"modified\", \"modifier\", \"permissions\", \"recipe\", \"revision\", \"tags\", \"text\", \"title\", \"type\", \"uri\"\n\t\t];\n\tif(tiddler) {\n\t\t$tw.utils.each(tiddler.fields,function(field,name) {\n\t\t\tvar value = tiddler.getFieldString(name);\n\t\t\tif(knownFields.indexOf(name) !== -1) {\n\t\t\t\ttiddlerFields[name] = value;\n\t\t\t} else {\n\t\t\t\ttiddlerFields.fields = tiddlerFields.fields || {};\n\t\t\t\ttiddlerFields.fields[name] = value;\n\t\t\t}\n\t\t});\n\t\ttiddlerFields.revision = state.wiki.getChangeCount(title);\n\t\ttiddlerFields.bag = \"default\";\n\t\ttiddlerFields.type = tiddlerFields.type || \"text/vnd.tiddlywiki\";\n\t\tresponse.writeHead(200, {\"Content-Type\": \"application/json\"});\n\t\tresponse.end(JSON.stringify(tiddlerFields),\"utf8\");\n\t} else {\n\t\tresponse.writeHead(404);\n\t\tresponse.end();\n\t}\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/get-tiddlers-json.js": {
            "title": "$:/core/modules/server/routes/get-tiddlers-json.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/get-tiddlers-json.js\ntype: application/javascript\nmodule-type: route\n\nGET /recipes/default/tiddlers/tiddlers.json?filter=<filter>\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar DEFAULT_FILTER = \"[all[tiddlers]!is[system]sort[title]]\";\n\nexports.method = \"GET\";\n\nexports.path = /^\\/recipes\\/default\\/tiddlers.json$/;\n\nexports.handler = function(request,response,state) {\n\tvar filter = state.queryParameters.filter || DEFAULT_FILTER;\n\tif($tw.wiki.getTiddlerText(\"$:/config/Server/AllowAllExternalFilters\") !== \"yes\") {\n\t\tif($tw.wiki.getTiddlerText(\"$:/config/Server/ExternalFilters/\" + filter) !== \"yes\") {\n\t\t\tconsole.log(\"Blocked attempt to GET /recipes/default/tiddlers/tiddlers.json with filter: \" + filter);\n\t\t\tresponse.writeHead(403);\n\t\t\tresponse.end();\n\t\t\treturn;\n\t\t}\n\t}\n\tvar excludeFields = (state.queryParameters.exclude || \"text\").split(\",\"),\n\t\ttitles = state.wiki.filterTiddlers(filter);\n\tresponse.writeHead(200, {\"Content-Type\": \"application/json\"});\n\tvar tiddlers = [];\n\t$tw.utils.each(titles,function(title) {\n\t\tvar tiddler = state.wiki.getTiddler(title);\n\t\tif(tiddler) {\n\t\t\tvar tiddlerFields = tiddler.getFieldStrings({exclude: excludeFields});\n\t\t\ttiddlerFields.revision = state.wiki.getChangeCount(title);\n\t\t\ttiddlerFields.type = tiddlerFields.type || \"text/vnd.tiddlywiki\";\n\t\t\ttiddlers.push(tiddlerFields);\n\t\t}\n\t});\n\tvar text = JSON.stringify(tiddlers);\n\tresponse.end(text,\"utf8\");\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/routes/put-tiddler.js": {
            "title": "$:/core/modules/server/routes/put-tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/server/routes/put-tiddler.js\ntype: application/javascript\nmodule-type: route\n\nPUT /recipes/default/tiddlers/:title\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.method = \"PUT\";\n\nexports.path = /^\\/recipes\\/default\\/tiddlers\\/(.+)$/;\n\nexports.handler = function(request,response,state) {\n\tvar title = decodeURIComponent(state.params[0]),\n\tfields = JSON.parse(state.data);\n\t// Pull up any subfields in the `fields` object\n\tif(fields.fields) {\n\t\t$tw.utils.each(fields.fields,function(field,name) {\n\t\t\tfields[name] = field;\n\t\t});\n\t\tdelete fields.fields;\n\t}\n\t// Remove any revision field\n\tif(fields.revision) {\n\t\tdelete fields.revision;\n\t}\n\tstate.wiki.addTiddler(new $tw.Tiddler(state.wiki.getCreationFields(),fields,{title: title},state.wiki.getModificationFields()));\n\tvar changeCount = state.wiki.getChangeCount(title).toString();\n\tresponse.writeHead(204, \"OK\",{\n\t\tEtag: \"\\\"default/\" + encodeURIComponent(title) + \"/\" + changeCount + \":\\\"\",\n\t\t\"Content-Type\": \"text/plain\"\n\t});\n\tresponse.end();\n};\n\n}());\n",
            "type": "application/javascript",
            "module-type": "route"
        },
        "$:/core/modules/server/server.js": {
            "title": "$:/core/modules/server/server.js",
            "text": "/*\\\ntitle: $:/core/modules/server/server.js\ntype: application/javascript\nmodule-type: library\n\nServe tiddlers over http\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nif($tw.node) {\n\tvar util = require(\"util\"),\n\t\tfs = require(\"fs\"),\n\t\turl = require(\"url\"),\n\t\tpath = require(\"path\"),\n\t\tquerystring = require(\"querystring\");\n}\n\n/*\nA simple HTTP server with regexp-based routes\noptions: variables - optional hashmap of variables to set (a misnomer - they are really constant parameters)\n\t\t routes - optional array of routes to use\n\t\t wiki - reference to wiki object\n*/\nfunction Server(options) {\n\tvar self = this;\n\tthis.routes = options.routes || [];\n\tthis.authenticators = options.authenticators || [];\n\tthis.wiki = options.wiki;\n\tthis.servername = $tw.utils.transliterateToSafeASCII(this.wiki.getTiddlerText(\"$:/SiteTitle\") || \"TiddlyWiki5\");\n\t// Initialise the variables\n\tthis.variables = $tw.utils.extend({},this.defaultVariables);\n\tif(options.variables) {\n\t\tfor(var variable in options.variables) {\n\t\t\tif(options.variables[variable]) {\n\t\t\t\tthis.variables[variable] = options.variables[variable];\n\t\t\t}\n\t\t}\t\t\n\t}\n\t$tw.utils.extend({},this.defaultVariables,options.variables);\n\t// Initialise CSRF\n\tthis.csrfDisable = this.get(\"csrf-disable\") === \"yes\";\n\t// Initialize Gzip compression\n\tthis.enableGzip = this.get(\"gzip\") === \"yes\";\n\t// Initialise authorization\n\tvar authorizedUserName = (this.get(\"username\") && this.get(\"password\")) ? this.get(\"username\") : \"(anon)\";\n\tthis.authorizationPrincipals = {\n\t\treaders: (this.get(\"readers\") || authorizedUserName).split(\",\").map($tw.utils.trim),\n\t\twriters: (this.get(\"writers\") || authorizedUserName).split(\",\").map($tw.utils.trim)\n\t}\n\t// Load and initialise authenticators\n\t$tw.modules.forEachModuleOfType(\"authenticator\", function(title,authenticatorDefinition) {\n\t\t// console.log(\"Loading server route \" + title);\n\t\tself.addAuthenticator(authenticatorDefinition.AuthenticatorClass);\n\t});\n\t// Load route handlers\n\t$tw.modules.forEachModuleOfType(\"route\", function(title,routeDefinition) {\n\t\t// console.log(\"Loading server route \" + title);\n\t\tself.addRoute(routeDefinition);\n\t});\n\t// Initialise the http vs https\n\tthis.listenOptions = null;\n\tthis.protocol = \"http\";\n\tvar tlsKeyFilepath = this.get(\"tls-key\"),\n\t\ttlsCertFilepath = this.get(\"tls-cert\");\n\tif(tlsCertFilepath && tlsKeyFilepath) {\n\t\tthis.listenOptions = {\n\t\t\tkey: fs.readFileSync(path.resolve($tw.boot.wikiPath,tlsKeyFilepath),\"utf8\"),\n\t\t\tcert: fs.readFileSync(path.resolve($tw.boot.wikiPath,tlsCertFilepath),\"utf8\")\n\t\t};\n\t\tthis.protocol = \"https\";\n\t}\n\tthis.transport = require(this.protocol);\n}\n\nServer.prototype.defaultVariables = {\n\tport: \"8080\",\n\thost: \"127.0.0.1\",\n\t\"root-tiddler\": \"$:/core/save/all\",\n\t\"root-render-type\": \"text/plain\",\n\t\"root-serve-type\": \"text/html\",\n\t\"tiddler-render-type\": \"text/html\",\n\t\"tiddler-render-template\": \"$:/core/templates/server/static.tiddler.html\",\n\t\"system-tiddler-render-type\": \"text/plain\",\n\t\"system-tiddler-render-template\": \"$:/core/templates/wikified-tiddler\",\n\t\"debug-level\": \"none\",\n\t\"gzip\": \"no\"\n};\n\nServer.prototype.get = function(name) {\n\treturn this.variables[name];\n};\n\nServer.prototype.addRoute = function(route) {\n\tthis.routes.push(route);\n};\n\nServer.prototype.addAuthenticator = function(AuthenticatorClass) {\n\t// Instantiate and initialise the authenticator\n\tvar authenticator = new AuthenticatorClass(this),\n\t\tresult = authenticator.init();\n\tif(typeof result === \"string\") {\n\t\t$tw.utils.error(\"Error: \" + result);\n\t} else if(result) {\n\t\t// Only use the authenticator if it initialised successfully\n\t\tthis.authenticators.push(authenticator);\n\t}\n};\n\nServer.prototype.findMatchingRoute = function(request,state) {\n\tvar pathprefix = this.get(\"path-prefix\") || \"\";\n\tfor(var t=0; t<this.routes.length; t++) {\n\t\tvar potentialRoute = this.routes[t],\n\t\t\tpathRegExp = potentialRoute.path,\n\t\t\tpathname = state.urlInfo.pathname,\n\t\t\tmatch;\n\t\tif(pathprefix) {\n\t\t\tif(pathname.substr(0,pathprefix.length) === pathprefix) {\n\t\t\t\tpathname = pathname.substr(pathprefix.length) || \"/\";\n\t\t\t\tmatch = potentialRoute.path.exec(pathname);\n\t\t\t} else {\n\t\t\t\tmatch = false;\n\t\t\t}\n\t\t} else {\n\t\t\tmatch = potentialRoute.path.exec(pathname);\n\t\t}\n\t\tif(match && request.method === potentialRoute.method) {\n\t\t\tstate.params = [];\n\t\t\tfor(var p=1; p<match.length; p++) {\n\t\t\t\tstate.params.push(match[p]);\n\t\t\t}\n\t\t\treturn potentialRoute;\n\t\t}\n\t}\n\treturn null;\n};\n\nServer.prototype.methodMappings = {\n\t\"GET\": \"readers\",\n\t\"OPTIONS\": \"readers\",\n\t\"HEAD\": \"readers\",\n\t\"PUT\": \"writers\",\n\t\"POST\": \"writers\",\n\t\"DELETE\": \"writers\"\n};\n\n/*\nCheck whether a given user is authorized for the specified authorizationType (\"readers\" or \"writers\"). Pass null or undefined as the username to check for anonymous access\n*/\nServer.prototype.isAuthorized = function(authorizationType,username) {\n\tvar principals = this.authorizationPrincipals[authorizationType] || [];\n\treturn principals.indexOf(\"(anon)\") !== -1 || (username && (principals.indexOf(\"(authenticated)\") !== -1 || principals.indexOf(username) !== -1));\n}\n\nServer.prototype.requestHandler = function(request,response) {\n\t// Compose the state object\n\tvar self = this;\n\tvar state = {};\n\tstate.wiki = self.wiki;\n\tstate.server = self;\n\tstate.urlInfo = url.parse(request.url);\n\tstate.queryParameters = querystring.parse(state.urlInfo.query);\n\t// Get the principals authorized to access this resource\n\tvar authorizationType = this.methodMappings[request.method] || \"readers\";\n\t// Check for the CSRF header if this is a write\n\tif(!this.csrfDisable && authorizationType === \"writers\" && request.headers[\"x-requested-with\"] !== \"TiddlyWiki\") {\n\t\tresponse.writeHead(403,\"'X-Requested-With' header required to login to '\" + this.servername + \"'\");\n\t\tresponse.end();\n\t\treturn;\t\t\n\t}\n\t// Check whether anonymous access is granted\n\tstate.allowAnon = this.isAuthorized(authorizationType,null);\n\t// Authenticate with the first active authenticator\n\tif(this.authenticators.length > 0) {\n\t\tif(!this.authenticators[0].authenticateRequest(request,response,state)) {\n\t\t\t// Bail if we failed (the authenticator will have sent the response)\n\t\t\treturn;\n\t\t}\t\t\n\t}\n\t// Authorize with the authenticated username\n\tif(!this.isAuthorized(authorizationType,state.authenticatedUsername)) {\n\t\tresponse.writeHead(401,\"'\" + state.authenticatedUsername + \"' is not authorized to access '\" + this.servername + \"'\");\n\t\tresponse.end();\n\t\treturn;\n\t}\n\t// Find the route that matches this path\n\tvar route = self.findMatchingRoute(request,state);\n\t// Optionally output debug info\n\tif(self.get(\"debug-level\") !== \"none\") {\n\t\tconsole.log(\"Request path:\",JSON.stringify(state.urlInfo));\n\t\tconsole.log(\"Request headers:\",JSON.stringify(request.headers));\n\t\tconsole.log(\"authenticatedUsername:\",state.authenticatedUsername);\n\t}\n\t// Return a 404 if we didn't find a route\n\tif(!route) {\n\t\tresponse.writeHead(404);\n\t\tresponse.end();\n\t\treturn;\n\t}\n\t// Receive the request body if necessary and hand off to the route handler\n\tif(route.bodyFormat === \"stream\" || request.method === \"GET\" || request.method === \"HEAD\") {\n\t\t// Let the route handle the request stream itself\n\t\troute.handler(request,response,state);\n\t} else if(route.bodyFormat === \"string\" || !route.bodyFormat) {\n\t\t// Set the encoding for the incoming request\n\t\trequest.setEncoding(\"utf8\");\n\t\tvar data = \"\";\n\t\trequest.on(\"data\",function(chunk) {\n\t\t\tdata += chunk.toString();\n\t\t});\n\t\trequest.on(\"end\",function() {\n\t\t\tstate.data = data;\n\t\t\troute.handler(request,response,state);\n\t\t});\n\t} else if(route.bodyFormat === \"buffer\") {\n\t\tvar data = [];\n\t\trequest.on(\"data\",function(chunk) {\n\t\t\tdata.push(chunk);\n\t\t});\n\t\trequest.on(\"end\",function() {\n\t\t\tstate.data = Buffer.concat(data);\n\t\t\troute.handler(request,response,state);\n\t\t})\n\t} else {\n\t\tresponse.writeHead(400,\"Invalid bodyFormat \" + route.bodyFormat + \" in route \" + route.method + \" \" + route.path.source);\n\t\tresponse.end();\n\t}\n};\n\n/*\nListen for requests\nport: optional port number (falls back to value of \"port\" variable)\nhost: optional host address (falls back to value of \"host\" variable)\nprefix: optional prefix (falls back to value of \"path-prefix\" variable)\n*/\nServer.prototype.listen = function(port,host,prefix) {\n\tvar self = this;\n\t// Handle defaults for port and host\n\tport = port || this.get(\"port\");\n\thost = host || this.get(\"host\");\n\tprefix = prefix || this.get(\"path-prefix\") || \"\";\n\t// Check for the port being a string and look it up as an environment variable\n\tif(parseInt(port,10).toString() !== port) {\n\t\tport = process.env[port] || 8080;\n\t}\n\t// Warn if required plugins are missing\n\tif(!$tw.wiki.getTiddler(\"$:/plugins/tiddlywiki/tiddlyweb\") || !$tw.wiki.getTiddler(\"$:/plugins/tiddlywiki/filesystem\")) {\n\t\t$tw.utils.warning(\"Warning: Plugins required for client-server operation (\\\"tiddlywiki/filesystem\\\" and \\\"tiddlywiki/tiddlyweb\\\") are missing from tiddlywiki.info file\");\n\t}\n\t// Create the server\n\tvar server;\n\tif(this.listenOptions) {\n\t\tserver = this.transport.createServer(this.listenOptions,this.requestHandler.bind(this));\n\t} else {\n\t\tserver = this.transport.createServer(this.requestHandler.bind(this));\n\t}\n\t// Display the port number after we've started listening (the port number might have been specified as zero, in which case we will get an assigned port)\n\tserver.on(\"listening\",function() {\n\t\tvar address = server.address();\n\t\t$tw.utils.log(\"Serving on \" + self.protocol + \"://\" + address.address + \":\" + address.port + prefix,\"brown/orange\");\n\t\t$tw.utils.log(\"(press ctrl-C to exit)\",\"red\");\n\t});\n\t// Listen\n\treturn server.listen(port,host);\n};\n\nexports.Server = Server;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "library"
        },
        "$:/core/modules/browser-messaging.js": {
            "title": "$:/core/modules/browser-messaging.js",
            "text": "/*\\\ntitle: $:/core/modules/browser-messaging.js\ntype: application/javascript\nmodule-type: startup\n\nBrowser message handling\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"browser-messaging\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\n/*\nLoad a specified url as an iframe and call the callback when it is loaded. If the url is already loaded then the existing iframe instance is used\n*/\nfunction loadIFrame(url,callback) {\n\t// Check if iframe already exists\n\tvar iframeInfo = $tw.browserMessaging.iframeInfoMap[url];\n\tif(iframeInfo) {\n\t\t// We've already got the iframe\n\t\tcallback(null,iframeInfo);\n\t} else {\n\t\t// Create the iframe and save it in the list\n\t\tvar iframe = document.createElement(\"iframe\");\n\t\tiframeInfo = {\n\t\t\turl: url,\n\t\t\tstatus: \"loading\",\n\t\t\tdomNode: iframe\n\t\t};\n\t\t$tw.browserMessaging.iframeInfoMap[url] = iframeInfo;\n\t\tsaveIFrameInfoTiddler(iframeInfo);\n\t\t// Add the iframe to the DOM and hide it\n\t\tiframe.style.display = \"none\";\n\t\tiframe.setAttribute(\"library\",\"true\");\n\t\tdocument.body.appendChild(iframe);\n\t\t// Set up onload\n\t\tiframe.onload = function() {\n\t\t\tiframeInfo.status = \"loaded\";\n\t\t\tsaveIFrameInfoTiddler(iframeInfo);\n\t\t\tcallback(null,iframeInfo);\n\t\t};\n\t\tiframe.onerror = function() {\n\t\t\tcallback(\"Cannot load iframe\");\n\t\t};\n\t\ttry {\n\t\t\tiframe.src = url;\n\t\t} catch(ex) {\n\t\t\tcallback(ex);\n\t\t}\n\t}\n}\n\n/*\nUnload library iframe for given url\n*/\nfunction unloadIFrame(url){\n\t$tw.utils.each(document.getElementsByTagName('iframe'), function(iframe) {\n\t\tif(iframe.getAttribute(\"library\") === \"true\" &&\n\t\t  iframe.getAttribute(\"src\") === url) {\n\t\t\tiframe.parentNode.removeChild(iframe);\n\t\t}\n\t});\n}\n\nfunction saveIFrameInfoTiddler(iframeInfo) {\n\t$tw.wiki.addTiddler(new $tw.Tiddler($tw.wiki.getCreationFields(),{\n\t\ttitle: \"$:/temp/ServerConnection/\" + iframeInfo.url,\n\t\ttext: iframeInfo.status,\n\t\ttags: [\"$:/tags/ServerConnection\"],\n\t\turl: iframeInfo.url\n\t},$tw.wiki.getModificationFields()));\n}\n\nexports.startup = function() {\n\t// Initialise the store of iframes we've created\n\t$tw.browserMessaging = {\n\t\tiframeInfoMap: {} // Hashmap by URL of {url:,status:\"loading/loaded\",domNode:}\n\t};\n\t// Listen for widget messages to control loading the plugin library\n\t$tw.rootWidget.addEventListener(\"tm-load-plugin-library\",function(event) {\n\t\tvar paramObject = event.paramObject || {},\n\t\t\turl = paramObject.url;\n\t\tif(url) {\n\t\t\tloadIFrame(url,function(err,iframeInfo) {\n\t\t\t\tif(err) {\n\t\t\t\t\talert($tw.language.getString(\"Error/LoadingPluginLibrary\") + \": \" + url);\n\t\t\t\t} else {\n\t\t\t\t\tiframeInfo.domNode.contentWindow.postMessage({\n\t\t\t\t\t\tverb: \"GET\",\n\t\t\t\t\t\turl: \"recipes/library/tiddlers.json\",\n\t\t\t\t\t\tcookies: {\n\t\t\t\t\t\t\ttype: \"save-info\",\n\t\t\t\t\t\t\tinfoTitlePrefix: paramObject.infoTitlePrefix || \"$:/temp/RemoteAssetInfo/\",\n\t\t\t\t\t\t\turl: url\n\t\t\t\t\t\t}\n\t\t\t\t\t},\"*\");\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t// Listen for widget messages to control unloading the plugin library\n\t$tw.rootWidget.addEventListener(\"tm-unload-plugin-library\",function(event) {\n\t\tvar paramObject = event.paramObject || {},\n\t\t\turl = paramObject.url;\n\t\t$tw.browserMessaging.iframeInfoMap[url] = undefined;\n\t\tif(url) {\n\t\t\tunloadIFrame(url);\n\t\t\t$tw.utils.each(\n\t\t\t\t$tw.wiki.filterTiddlers(\"[[$:/temp/ServerConnection/\" + url + \"]] [prefix[$:/temp/RemoteAssetInfo/\" + url + \"/]]\"),\n\t\t\t\tfunction(title) {\n\t\t\t\t\t$tw.wiki.deleteTiddler(title);\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t});\n\t$tw.rootWidget.addEventListener(\"tm-load-plugin-from-library\",function(event) {\n\t\tvar paramObject = event.paramObject || {},\n\t\t\turl = paramObject.url,\n\t\t\ttitle = paramObject.title;\n\t\tif(url && title) {\n\t\t\tloadIFrame(url,function(err,iframeInfo) {\n\t\t\t\tif(err) {\n\t\t\t\t\talert($tw.language.getString(\"Error/LoadingPluginLibrary\") + \": \" + url);\n\t\t\t\t} else {\n\t\t\t\t\tiframeInfo.domNode.contentWindow.postMessage({\n\t\t\t\t\t\tverb: \"GET\",\n\t\t\t\t\t\turl: \"recipes/library/tiddlers/\" + encodeURIComponent(title) + \".json\",\n\t\t\t\t\t\tcookies: {\n\t\t\t\t\t\t\ttype: \"save-tiddler\",\n\t\t\t\t\t\t\turl: url\n\t\t\t\t\t\t}\n\t\t\t\t\t},\"*\");\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t// Listen for window messages from other windows\n\twindow.addEventListener(\"message\",function listener(event){\n\t\t// console.log(\"browser-messaging: \",document.location.toString())\n\t\t// console.log(\"browser-messaging: Received message from\",event.origin);\n\t\t// console.log(\"browser-messaging: Message content\",event.data);\n\t\tswitch(event.data.verb) {\n\t\t\tcase \"GET-RESPONSE\":\n\t\t\t\tif(event.data.status.charAt(0) === \"2\") {\n\t\t\t\t\tif(event.data.cookies) {\n\t\t\t\t\t\tif(event.data.cookies.type === \"save-info\") {\n\t\t\t\t\t\t\tvar tiddlers = JSON.parse(event.data.body);\n\t\t\t\t\t\t\t$tw.utils.each(tiddlers,function(tiddler) {\n\t\t\t\t\t\t\t\t$tw.wiki.addTiddler(new $tw.Tiddler($tw.wiki.getCreationFields(),tiddler,{\n\t\t\t\t\t\t\t\t\ttitle: event.data.cookies.infoTitlePrefix + event.data.cookies.url + \"/\" + tiddler.title,\n\t\t\t\t\t\t\t\t\t\"original-title\": tiddler.title,\n\t\t\t\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\t\t\t\ttype: \"text/vnd.tiddlywiki\",\n\t\t\t\t\t\t\t\t\t\"original-type\": tiddler.type,\n\t\t\t\t\t\t\t\t\t\"plugin-type\": undefined,\n\t\t\t\t\t\t\t\t\t\"original-plugin-type\": tiddler[\"plugin-type\"],\n\t\t\t\t\t\t\t\t\t\"module-type\": undefined,\n\t\t\t\t\t\t\t\t\t\"original-module-type\": tiddler[\"module-type\"],\n\t\t\t\t\t\t\t\t\ttags: [\"$:/tags/RemoteAssetInfo\"],\n\t\t\t\t\t\t\t\t\t\"original-tags\": $tw.utils.stringifyList(tiddler.tags || []),\n\t\t\t\t\t\t\t\t\t\"server-url\": event.data.cookies.url\n\t\t\t\t\t\t\t\t},$tw.wiki.getModificationFields()));\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if(event.data.cookies.type === \"save-tiddler\") {\n\t\t\t\t\t\t\tvar tiddler = JSON.parse(event.data.body);\n\t\t\t\t\t\t\t$tw.wiki.addTiddler(new $tw.Tiddler(tiddler));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t},false);\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/commands.js": {
            "title": "$:/core/modules/startup/commands.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/commands.js\ntype: application/javascript\nmodule-type: startup\n\nCommand processing\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"commands\";\nexports.platforms = [\"node\"];\nexports.after = [\"story\"];\nexports.synchronous = false;\n\nexports.startup = function(callback) {\n\t// On the server, start a commander with the command line arguments\n\tvar commander = new $tw.Commander(\n\t\t$tw.boot.argv,\n\t\tfunction(err) {\n\t\t\tif(err) {\n\t\t\t\treturn $tw.utils.error(\"Error: \" + err);\n\t\t\t}\n\t\t\tcallback();\n\t\t},\n\t\t$tw.wiki,\n\t\t{output: process.stdout, error: process.stderr}\n\t);\n\tcommander.execute();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/CSSescape.js": {
            "title": "$:/core/modules/startup/CSSescape.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/CSSescape.js\ntype: application/javascript\nmodule-type: startup\n\nPolyfill for CSS.escape()\n\n\\*/\n(function(root,factory){\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"css-escape\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\n/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */\n// https://github.com/umdjs/umd/blob/master/returnExports.js\nexports.startup = factory(root);\n}(typeof global != 'undefined' ? global : this, function(root) {\n\n\tif (root.CSS && root.CSS.escape) {\n\t\treturn;\n\t}\n\n\t// https://drafts.csswg.org/cssom/#serialize-an-identifier\n\tvar cssEscape = function(value) {\n\t\tif (arguments.length == 0) {\n\t\t\tthrow new TypeError('`CSS.escape` requires an argument.');\n\t\t}\n\t\tvar string = String(value);\n\t\tvar length = string.length;\n\t\tvar index = -1;\n\t\tvar codeUnit;\n\t\tvar result = '';\n\t\tvar firstCodeUnit = string.charCodeAt(0);\n\t\twhile (++index < length) {\n\t\t\tcodeUnit = string.charCodeAt(index);\n\t\t\t// Note: there’s no need to special-case astral symbols, surrogate\n\t\t\t// pairs, or lone surrogates.\n\n\t\t\t// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER\n\t\t\t// (U+FFFD).\n\t\t\tif (codeUnit == 0x0000) {\n\t\t\t\tresult += '\\uFFFD';\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t// If the character is in the range [\\1-\\1F] (U+0001 to U+001F) or is\n\t\t\t\t// U+007F, […]\n\t\t\t\t(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||\n\t\t\t\t// If the character is the first character and is in the range [0-9]\n\t\t\t\t// (U+0030 to U+0039), […]\n\t\t\t\t(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||\n\t\t\t\t// If the character is the second character and is in the range [0-9]\n\t\t\t\t// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]\n\t\t\t\t(\n\t\t\t\t\tindex == 1 &&\n\t\t\t\t\tcodeUnit >= 0x0030 && codeUnit <= 0x0039 &&\n\t\t\t\t\tfirstCodeUnit == 0x002D\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\t// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point\n\t\t\t\tresult += '\\\\' + codeUnit.toString(16) + ' ';\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t// If the character is the first character and is a `-` (U+002D), and\n\t\t\t\t// there is no second character, […]\n\t\t\t\tindex == 0 &&\n\t\t\t\tlength == 1 &&\n\t\t\t\tcodeUnit == 0x002D\n\t\t\t) {\n\t\t\t\tresult += '\\\\' + string.charAt(index);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If the character is not handled by one of the above rules and is\n\t\t\t// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or\n\t\t\t// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to\n\t\t\t// U+005A), or [a-z] (U+0061 to U+007A), […]\n\t\t\tif (\n\t\t\t\tcodeUnit >= 0x0080 ||\n\t\t\t\tcodeUnit == 0x002D ||\n\t\t\t\tcodeUnit == 0x005F ||\n\t\t\t\tcodeUnit >= 0x0030 && codeUnit <= 0x0039 ||\n\t\t\t\tcodeUnit >= 0x0041 && codeUnit <= 0x005A ||\n\t\t\t\tcodeUnit >= 0x0061 && codeUnit <= 0x007A\n\t\t\t) {\n\t\t\t\t// the character itself\n\t\t\t\tresult += string.charAt(index);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Otherwise, the escaped character.\n\t\t\t// https://drafts.csswg.org/cssom/#escape-a-character\n\t\t\tresult += '\\\\' + string.charAt(index);\n\n\t\t}\n\t\treturn result;\n\t};\n\n\tif (!root.CSS) {\n\t\troot.CSS = {};\n\t}\n\n\troot.CSS.escape = cssEscape;\n\n}));\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/favicon.js": {
            "title": "$:/core/modules/startup/favicon.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/favicon.js\ntype: application/javascript\nmodule-type: startup\n\nFavicon handling\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"favicon\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\t\t\n// Favicon tiddler\nvar FAVICON_TITLE = \"$:/favicon.ico\";\n\nexports.startup = function() {\n\t// Set up the favicon\n\tsetFavicon();\n\t// Reset the favicon when the tiddler changes\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.utils.hop(changes,FAVICON_TITLE)) {\n\t\t\tsetFavicon();\n\t\t}\n\t});\n};\n\nfunction setFavicon() {\n\tvar tiddler = $tw.wiki.getTiddler(FAVICON_TITLE);\n\tif(tiddler) {\n\t\tvar faviconLink = document.getElementById(\"faviconLink\");\n\t\tfaviconLink.setAttribute(\"href\",\"data:\" + tiddler.fields.type + \";base64,\" + tiddler.fields.text);\n\t}\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/info.js": {
            "title": "$:/core/modules/startup/info.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/info.js\ntype: application/javascript\nmodule-type: startup\n\nInitialise $:/info tiddlers via $:/temp/info-plugin pseudo-plugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"info\";\nexports.before = [\"startup\"];\nexports.after = [\"load-modules\"];\nexports.synchronous = true;\n\nvar TITLE_INFO_PLUGIN = \"$:/temp/info-plugin\";\n\nexports.startup = function() {\n\t// Collect up the info tiddlers\n\tvar infoTiddlerFields = {};\n\t// Give each info module a chance to fill in as many info tiddlers as they want\n\t$tw.modules.forEachModuleOfType(\"info\",function(title,moduleExports) {\n\t\tif(moduleExports && moduleExports.getInfoTiddlerFields) {\n\t\t\tvar tiddlerFieldsArray = moduleExports.getInfoTiddlerFields(infoTiddlerFields);\n\t\t\t$tw.utils.each(tiddlerFieldsArray,function(fields) {\n\t\t\t\tif(fields) {\n\t\t\t\t\tinfoTiddlerFields[fields.title] = fields;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t// Bake the info tiddlers into a plugin. We use the non-standard plugin-type \"info\" because ordinary plugins are only registered asynchronously after being loaded dynamically\n\tvar fields = {\n\t\ttitle: TITLE_INFO_PLUGIN,\n\t\ttype: \"application/json\",\n\t\t\"plugin-type\": \"info\",\n\t\ttext: JSON.stringify({tiddlers: infoTiddlerFields},null,$tw.config.preferences.jsonSpaces)\n\t};\n\t$tw.wiki.addTiddler(new $tw.Tiddler(fields));\n\t$tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);\n\t$tw.wiki.registerPluginTiddlers(\"info\");\n\t$tw.wiki.unpackPluginTiddlers();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/load-modules.js": {
            "title": "$:/core/modules/startup/load-modules.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/load-modules.js\ntype: application/javascript\nmodule-type: startup\n\nLoad core modules\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"load-modules\";\nexports.synchronous = true;\n\nexports.startup = function() {\n\t// Load modules\n\t$tw.modules.applyMethods(\"utils\",$tw.utils);\n\tif($tw.node) {\n\t\t$tw.modules.applyMethods(\"utils-node\",$tw.utils);\n\t}\n\t$tw.modules.applyMethods(\"global\",$tw);\n\t$tw.modules.applyMethods(\"config\",$tw.config);\n\t$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap(\"tiddlerfield\");\n\t$tw.modules.applyMethods(\"tiddlermethod\",$tw.Tiddler.prototype);\n\t$tw.modules.applyMethods(\"wikimethod\",$tw.Wiki.prototype);\n\t$tw.wiki.addIndexersToWiki();\n\t$tw.modules.applyMethods(\"tiddlerdeserializer\",$tw.Wiki.tiddlerDeserializerModules);\n\t$tw.macros = $tw.modules.getModulesByTypeAsHashmap(\"macro\");\n\t$tw.wiki.initParsers();\n\t$tw.Commander.initCommands();\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/password.js": {
            "title": "$:/core/modules/startup/password.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/password.js\ntype: application/javascript\nmodule-type: startup\n\nPassword handling\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"password\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\nexports.startup = function() {\n\t$tw.rootWidget.addEventListener(\"tm-set-password\",function(event) {\n\t\t$tw.passwordPrompt.createPrompt({\n\t\t\tserviceName: $tw.language.getString(\"Encryption/PromptSetPassword\"),\n\t\t\tnoUserName: true,\n\t\t\tsubmitText: $tw.language.getString(\"Encryption/SetPassword\"),\n\t\t\tcanCancel: true,\n\t\t\trepeatPassword: true,\n\t\t\tcallback: function(data) {\n\t\t\t\tif(data) {\n\t\t\t\t\t$tw.crypto.setPassword(data.password);\n\t\t\t\t}\n\t\t\t\treturn true; // Get rid of the password prompt\n\t\t\t}\n\t\t});\n\t});\n\t$tw.rootWidget.addEventListener(\"tm-clear-password\",function(event) {\n\t\tif($tw.browser) {\n\t\t\tif(!confirm($tw.language.getString(\"Encryption/ConfirmClearPassword\"))) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t$tw.crypto.setPassword(null);\n\t});\n\t// Ensure that $:/isEncrypted is maintained properly\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.utils.hop(changes,\"$:/isEncrypted\")) {\n\t\t\t$tw.crypto.updateCryptoStateTiddler();\n\t\t}\n\t});\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/plugins.js": {
            "title": "$:/core/modules/startup/plugins.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/plugins.js\ntype: application/javascript\nmodule-type: startup\n\nStartup logic concerned with managing plugins\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"plugins\";\nexports.after = [\"load-modules\"];\nexports.synchronous = true;\n\nvar TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE = \"$:/status/RequireReloadDueToPluginChange\";\n\nvar PREFIX_CONFIG_REGISTER_PLUGIN_TYPE = \"$:/config/RegisterPluginType/\";\n\nexports.startup = function() {\n\t$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: \"no\"});\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tvar changesToProcess = [],\n\t\t\trequireReloadDueToPluginChange = false;\n\t\t$tw.utils.each(Object.keys(changes),function(title) {\n\t\t\tvar tiddler = $tw.wiki.getTiddler(title),\n\t\t\t\trequiresReload = $tw.wiki.doesPluginRequireReload(title);\n\t\t\tif(requiresReload) {\n\t\t\t\trequireReloadDueToPluginChange = true;\n\t\t\t} else if(tiddler) {\n\t\t\t\tvar pluginType = tiddler.fields[\"plugin-type\"];\n\t\t\t\tif($tw.wiki.getTiddlerText(PREFIX_CONFIG_REGISTER_PLUGIN_TYPE + (tiddler.fields[\"plugin-type\"] || \"\"),\"no\") === \"yes\") {\n\t\t\t\t\tchangesToProcess.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tif(requireReloadDueToPluginChange) {\n\t\t\t$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: \"yes\"});\n\t\t}\n\t\t// Read or delete the plugin info of the changed tiddlers\n\t\tif(changesToProcess.length > 0) {\n\t\t\tvar changes = $tw.wiki.readPluginInfo(changesToProcess);\n\t\t\tif(changes.modifiedPlugins.length > 0 || changes.deletedPlugins.length > 0) {\n\t\t\t\t// (Re-)register any modified plugins\n\t\t\t\t$tw.wiki.registerPluginTiddlers(null,changes.modifiedPlugins);\n\t\t\t\t// Unregister any deleted plugins\n\t\t\t\t$tw.wiki.unregisterPluginTiddlers(null,changes.deletedPlugins);\n\t\t\t\t// Unpack the shadow tiddlers\n\t\t\t\t$tw.wiki.unpackPluginTiddlers();\n\t\t\t}\n\t\t}\n\t});\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/render.js": {
            "title": "$:/core/modules/startup/render.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/render.js\ntype: application/javascript\nmodule-type: startup\n\nTitle, stylesheet and page rendering\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"render\";\nexports.platforms = [\"browser\"];\nexports.after = [\"story\"];\nexports.synchronous = true;\n\n// Default story and history lists\nvar PAGE_TITLE_TITLE = \"$:/core/wiki/title\";\nvar PAGE_STYLESHEET_TITLE = \"$:/core/ui/PageStylesheet\";\nvar PAGE_TEMPLATE_TITLE = \"$:/core/ui/PageTemplate\";\n\n// Time (in ms) that we defer refreshing changes to draft tiddlers\nvar DRAFT_TIDDLER_TIMEOUT_TITLE = \"$:/config/Drafts/TypingTimeout\";\nvar THROTTLE_REFRESH_TIMEOUT = 400;\n\nexports.startup = function() {\n\t// Set up the title\n\t$tw.titleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TITLE_TITLE,{document: $tw.fakeDocument, parseAsInline: true});\n\t$tw.titleContainer = $tw.fakeDocument.createElement(\"div\");\n\t$tw.titleWidgetNode.render($tw.titleContainer,null);\n\tdocument.title = $tw.titleContainer.textContent;\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.titleWidgetNode.refresh(changes,$tw.titleContainer,null)) {\n\t\t\tdocument.title = $tw.titleContainer.textContent;\n\t\t}\n\t});\n\t// Set up the styles\n\t$tw.styleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_STYLESHEET_TITLE,{document: $tw.fakeDocument});\n\t$tw.styleContainer = $tw.fakeDocument.createElement(\"style\");\n\t$tw.styleWidgetNode.render($tw.styleContainer,null);\n\t$tw.styleElement = document.createElement(\"style\");\n\t$tw.styleElement.innerHTML = $tw.styleContainer.textContent;\n\tdocument.head.insertBefore($tw.styleElement,document.head.firstChild);\n\t$tw.wiki.addEventListener(\"change\",$tw.perf.report(\"styleRefresh\",function(changes) {\n\t\tif($tw.styleWidgetNode.refresh(changes,$tw.styleContainer,null)) {\n\t\t\t$tw.styleElement.innerHTML = $tw.styleContainer.textContent;\n\t\t}\n\t}));\n\t// Display the $:/core/ui/PageTemplate tiddler to kick off the display\n\t$tw.perf.report(\"mainRender\",function() {\n\t\t$tw.pageWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TEMPLATE_TITLE,{document: document, parentWidget: $tw.rootWidget});\n\t\t$tw.pageContainer = document.createElement(\"div\");\n\t\t$tw.utils.addClass($tw.pageContainer,\"tc-page-container-wrapper\");\n\t\tdocument.body.insertBefore($tw.pageContainer,document.body.firstChild);\n\t\t$tw.pageWidgetNode.render($tw.pageContainer,null);\n   \t\t$tw.hooks.invokeHook(\"th-page-refreshed\");\n\t})();\n\t// Remove any splash screen elements\n\tvar removeList = document.querySelectorAll(\".tc-remove-when-wiki-loaded\");\n\t$tw.utils.each(removeList,function(removeItem) {\n\t\tif(removeItem.parentNode) {\n\t\t\tremoveItem.parentNode.removeChild(removeItem);\n\t\t}\n\t});\n\t// Prepare refresh mechanism\n\tvar deferredChanges = Object.create(null),\n\t\ttimerId;\n\tfunction refresh() {\n\t\t// Process the refresh\n\t\t$tw.hooks.invokeHook(\"th-page-refreshing\");\n\t\t$tw.pageWidgetNode.refresh(deferredChanges);\n\t\tdeferredChanges = Object.create(null);\n\t\t$tw.hooks.invokeHook(\"th-page-refreshed\");\n\t}\n\t// Add the change event handler\n\t$tw.wiki.addEventListener(\"change\",$tw.perf.report(\"mainRefresh\",function(changes) {\n\t\t// Check if only tiddlers that are throttled have changed\n\t\tvar onlyThrottledTiddlersHaveChanged = true;\n\t\tfor(var title in changes) {\n\t\t\tvar tiddler = $tw.wiki.getTiddler(title);\n\t\t\tif(!tiddler || !(tiddler.hasField(\"draft.of\") || tiddler.hasField(\"throttle.refresh\"))) {\n\t\t\t\tonlyThrottledTiddlersHaveChanged = false;\n\t\t\t}\n\t\t}\n\t\t// Defer the change if only drafts have changed\n\t\tif(timerId) {\n\t\t\tclearTimeout(timerId);\n\t\t}\n\t\ttimerId = null;\n\t\tif(onlyThrottledTiddlersHaveChanged) {\n\t\t\tvar timeout = parseInt($tw.wiki.getTiddlerText(DRAFT_TIDDLER_TIMEOUT_TITLE,\"\"),10);\n\t\t\tif(isNaN(timeout)) {\n\t\t\t\ttimeout = THROTTLE_REFRESH_TIMEOUT;\n\t\t\t}\n\t\t\ttimerId = setTimeout(refresh,timeout);\n\t\t\t$tw.utils.extend(deferredChanges,changes);\n\t\t} else {\n\t\t\t$tw.utils.extend(deferredChanges,changes);\n\t\t\trefresh();\n\t\t}\n\t}));\n\t// Fix up the link between the root widget and the page container\n\t$tw.rootWidget.domNodes = [$tw.pageContainer];\n\t$tw.rootWidget.children = [$tw.pageWidgetNode];\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/rootwidget.js": {
            "title": "$:/core/modules/startup/rootwidget.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/rootwidget.js\ntype: application/javascript\nmodule-type: startup\n\nSetup the root widget and the core root widget handlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"rootwidget\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.before = [\"story\"];\nexports.synchronous = true;\n\nexports.startup = function() {\n\t// Install the modal message mechanism\n\t$tw.modal = new $tw.utils.Modal($tw.wiki);\n\t$tw.rootWidget.addEventListener(\"tm-modal\",function(event) {\n\t\t$tw.modal.display(event.param,{variables: event.paramObject, event: event});\n\t});\n\t// Install the notification  mechanism\n\t$tw.notifier = new $tw.utils.Notifier($tw.wiki);\n\t$tw.rootWidget.addEventListener(\"tm-notify\",function(event) {\n\t\t$tw.notifier.display(event.param,{variables: event.paramObject});\n\t});\n\t// Install the copy-to-clipboard  mechanism\n\t$tw.rootWidget.addEventListener(\"tm-copy-to-clipboard\",function(event) {\n\t\t$tw.utils.copyToClipboard(event.param);\n\t});\n\t// Install the tm-focus-selector message\n\t$tw.rootWidget.addEventListener(\"tm-focus-selector\",function(event) {\n\t\tvar selector = event.param || \"\",\n\t\t\telement;\n\t\ttry {\n\t\t\telement = document.querySelector(selector);\n\t\t} catch(e) {\n\t\t\tconsole.log(\"Error in selector: \",selector)\n\t\t}\n\t\tif(element && element.focus) {\n\t\t\telement.focus(event.paramObject);\n\t\t}\n\t});\n\t// Install the scroller\n\t$tw.pageScroller = new $tw.utils.PageScroller();\n\t$tw.rootWidget.addEventListener(\"tm-scroll\",function(event) {\n\t\t$tw.pageScroller.handleEvent(event);\n\t});\n\tvar fullscreen = $tw.utils.getFullScreenApis();\n\tif(fullscreen) {\n\t\t$tw.rootWidget.addEventListener(\"tm-full-screen\",function(event) {\n\t\t\tvar fullScreenDocument = event.event ? event.event.target.ownerDocument : document;\n\t\t\tif(event.param === \"enter\") {\n\t\t\t\tfullScreenDocument.documentElement[fullscreen._requestFullscreen](Element.ALLOW_KEYBOARD_INPUT);\n\t\t\t} else if(event.param === \"exit\") {\n\t\t\t\tfullScreenDocument[fullscreen._exitFullscreen]();\n\t\t\t} else {\n\t\t\t\tif(fullScreenDocument[fullscreen._fullscreenElement]) {\n\t\t\t\t\tfullScreenDocument[fullscreen._exitFullscreen]();\n\t\t\t\t} else {\n\t\t\t\t\tfullScreenDocument.documentElement[fullscreen._requestFullscreen](Element.ALLOW_KEYBOARD_INPUT);\n\t\t\t\t}\t\t\t\t\n\t\t\t}\n\t\t});\n\t}\n\t// If we're being viewed on a data: URI then give instructions for how to save\n\tif(document.location.protocol === \"data:\") {\n\t\t$tw.rootWidget.dispatchEvent({\n\t\t\ttype: \"tm-modal\",\n\t\t\tparam: \"$:/language/Modals/SaveInstructions\"\n\t\t});\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup.js": {
            "title": "$:/core/modules/startup.js",
            "text": "/*\\\ntitle: $:/core/modules/startup.js\ntype: application/javascript\nmodule-type: startup\n\nMiscellaneous startup logic for both the client and server.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"startup\";\nexports.after = [\"load-modules\"];\nexports.synchronous = true;\n\n// Set to `true` to enable performance instrumentation\nvar PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE = \"$:/config/Performance/Instrumentation\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.startup = function() {\n\tvar modules,n,m,f;\n\t// Minimal browser detection\n\tif($tw.browser) {\n\t\t$tw.browser.isIE = (/msie|trident/i.test(navigator.userAgent));\n\t\t$tw.browser.isFirefox = !!document.mozFullScreenEnabled;\n\t}\n\t// Platform detection\n\t$tw.platform = {};\n\tif($tw.browser) {\n\t\t$tw.platform.isMac = /Mac/.test(navigator.platform);\n\t\t$tw.platform.isWindows = /win/i.test(navigator.platform);\n\t\t$tw.platform.isLinux = /Linux/i.test(navigator.platform);\n\t} else {\n\t\tswitch(require(\"os\").platform()) {\n\t\t\tcase \"darwin\":\n\t\t\t\t$tw.platform.isMac = true;\n\t\t\t\tbreak;\n\t\t\tcase \"win32\":\n\t\t\t\t$tw.platform.isWindows = true;\n\t\t\t\tbreak;\n\t\t\tcase \"freebsd\":\n\t\t\t\t$tw.platform.isLinux = true;\n\t\t\t\tbreak;\n\t\t\tcase \"linux\":\n\t\t\t\t$tw.platform.isLinux = true;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\t// Initialise version\n\t$tw.version = $tw.utils.extractVersionInfo();\n\t// Set up the performance framework\n\t$tw.perf = new $tw.Performance($tw.wiki.getTiddlerText(PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE,\"no\") === \"yes\");\n\t// Create a root widget for attaching event handlers. By using it as the parentWidget for another widget tree, one can reuse the event handlers\n\t$tw.rootWidget = new widget.widget({\n\t\ttype: \"widget\",\n\t\tchildren: []\n\t},{\n\t\twiki: $tw.wiki,\n\t\tdocument: $tw.browser ? document : $tw.fakeDocument\n\t});\n\t// Execute any startup actions\n\tvar executeStartupTiddlers = function(tag) {\n\t\t$tw.utils.each($tw.wiki.filterTiddlers(\"[all[shadows+tiddlers]tag[\" + tag + \"]!has[draft.of]]\"),function(title) {\n\t\t\t$tw.rootWidget.invokeActionString($tw.wiki.getTiddlerText(title),$tw.rootWidget);\n\t\t});\n\t};\n\texecuteStartupTiddlers(\"$:/tags/StartupAction\");\n\tif($tw.browser) {\n\t\texecuteStartupTiddlers(\"$:/tags/StartupAction/Browser\");\t\t\n\t}\n\tif($tw.node) {\n\t\texecuteStartupTiddlers(\"$:/tags/StartupAction/Node\");\t\t\n\t}\n\t// Kick off the language manager and switcher\n\t$tw.language = new $tw.Language();\n\t$tw.languageSwitcher = new $tw.PluginSwitcher({\n\t\twiki: $tw.wiki,\n\t\tpluginType: \"language\",\n\t\tcontrollerTitle: \"$:/language\",\n\t\tdefaultPlugins: [\n\t\t\t\"$:/languages/en-GB\"\n\t\t],\n\t\tonSwitch: function(plugins) {\n\t\t\tif($tw.browser) {\n\t\t\t\tvar pluginTiddler = $tw.wiki.getTiddler(plugins[0]);\n\t\t\t\tif(pluginTiddler) {\n\t\t\t\t\tdocument.documentElement.setAttribute(\"dir\",pluginTiddler.getFieldString(\"text-direction\") || \"auto\");\n\t\t\t\t} else {\n\t\t\t\t\tdocument.documentElement.removeAttribute(\"dir\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\t// Kick off the theme manager\n\t$tw.themeManager = new $tw.PluginSwitcher({\n\t\twiki: $tw.wiki,\n\t\tpluginType: \"theme\",\n\t\tcontrollerTitle: \"$:/theme\",\n\t\tdefaultPlugins: [\n\t\t\t\"$:/themes/tiddlywiki/snowwhite\",\n\t\t\t\"$:/themes/tiddlywiki/vanilla\"\n\t\t]\n\t});\n\t// Kick off the keyboard manager\n\t$tw.keyboardManager = new $tw.KeyboardManager();\n\t// Listen for shortcuts\n\tif($tw.browser) {\n\t\t$tw.utils.addEventListeners(document,[{\n\t\t\tname: \"keydown\",\n\t\t\thandlerObject: $tw.keyboardManager,\n\t\t\thandlerMethod: \"handleKeydownEvent\"\n\t\t}]);\n\t}\n\t// Clear outstanding tiddler store change events to avoid an unnecessary refresh cycle at startup\n\t$tw.wiki.clearTiddlerEventQueue();\n\t// Find a working syncadaptor\n\t$tw.syncadaptor = undefined;\n\t$tw.modules.forEachModuleOfType(\"syncadaptor\",function(title,module) {\n\t\tif(!$tw.syncadaptor && module.adaptorClass) {\n\t\t\t$tw.syncadaptor = new module.adaptorClass({wiki: $tw.wiki});\n\t\t}\n\t});\n\t// Set up the syncer object if we've got a syncadaptor\n\tif($tw.syncadaptor) {\n\t\t$tw.syncer = new $tw.Syncer({wiki: $tw.wiki, syncadaptor: $tw.syncadaptor});\n\t}\n\t// Setup the saver handler\n\t$tw.saverHandler = new $tw.SaverHandler({\n\t\twiki: $tw.wiki,\n\t\tdirtyTracking: !$tw.syncadaptor,\n\t\tpreloadDirty: $tw.boot.preloadDirty || []\n\t});\n\t// Host-specific startup\n\tif($tw.browser) {\n\t\t// Install the popup manager\n\t\t$tw.popup = new $tw.utils.Popup();\n\t\t// Install the animator\n\t\t$tw.anim = new $tw.utils.Animator();\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/story.js": {
            "title": "$:/core/modules/startup/story.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/story.js\ntype: application/javascript\nmodule-type: startup\n\nLoad core modules\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"story\";\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\n// Default story and history lists\nvar DEFAULT_STORY_TITLE = \"$:/StoryList\";\nvar DEFAULT_HISTORY_TITLE = \"$:/HistoryList\";\n\n// Default tiddlers\nvar DEFAULT_TIDDLERS_TITLE = \"$:/DefaultTiddlers\";\n\n// Config\nvar CONFIG_UPDATE_ADDRESS_BAR = \"$:/config/Navigation/UpdateAddressBar\"; // Can be \"no\", \"permalink\", \"permaview\"\nvar CONFIG_UPDATE_HISTORY = \"$:/config/Navigation/UpdateHistory\"; // Can be \"yes\" or \"no\"\nvar CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD = \"$:/config/Navigation/Permalinkview/CopyToClipboard\"; // Can be \"yes\" (default) or \"no\"\nvar CONFIG_PERMALINKVIEW_UPDATE_ADDRESS_BAR = \"$:/config/Navigation/Permalinkview/UpdateAddressBar\"; // Can be \"yes\" (default) or \"no\"\n\n\n// Links to help, if there is no param\nvar HELP_OPEN_EXTERNAL_WINDOW = \"http://tiddlywiki.com/#WidgetMessage%3A%20tm-open-external-window\";\n\nexports.startup = function() {\n\t// Open startup tiddlers\n\topenStartupTiddlers({\n\t\tdisableHistory: $tw.boot.disableStartupNavigation\n\t});\n\tif($tw.browser) {\n\t\t// Set up location hash update\n\t\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\t\tif($tw.utils.hop(changes,DEFAULT_STORY_TITLE) || $tw.utils.hop(changes,DEFAULT_HISTORY_TITLE)) {\n\t\t\t\tupdateLocationHash({\n\t\t\t\t\tupdateAddressBar: $tw.wiki.getTiddlerText(CONFIG_UPDATE_ADDRESS_BAR,\"permaview\").trim(),\n\t\t\t\t\tupdateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,\"no\").trim()\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\t// Listen for changes to the browser location hash\n\t\twindow.addEventListener(\"hashchange\",function() {\n\t\t\tvar hash = $tw.utils.getLocationHash();\n\t\t\tif(hash !== $tw.locationHash) {\n\t\t\t\t$tw.locationHash = hash;\n\t\t\t\topenStartupTiddlers({defaultToCurrentStory: true});\n\t\t\t}\n\t\t},false);\n\t\t// Listen for the tm-browser-refresh message\n\t\t$tw.rootWidget.addEventListener(\"tm-browser-refresh\",function(event) {\n\t\t\twindow.location.reload(true);\n\t\t});\n\t\t// Listen for tm-open-external-window message\n\t\t$tw.rootWidget.addEventListener(\"tm-open-external-window\",function(event) {\n\t\t\tvar paramObject = event.paramObject || {},\n\t\t\t\tstrUrl = event.param || HELP_OPEN_EXTERNAL_WINDOW,\n\t\t\t\tstrWindowName = paramObject.windowName,\n\t\t\t\tstrWindowFeatures = paramObject.windowFeatures;\n\t\t\twindow.open(strUrl, strWindowName, strWindowFeatures);\n\t\t});\n\t\t// Listen for the tm-print message\n\t\t$tw.rootWidget.addEventListener(\"tm-print\",function(event) {\n\t\t\t(event.event.view || window).print();\n\t\t});\n\t\t// Listen for the tm-home message\n\t\t$tw.rootWidget.addEventListener(\"tm-home\",function(event) {\n\t\t\twindow.location.hash = \"\";\n\t\t\tvar storyFilter = $tw.wiki.getTiddlerText(DEFAULT_TIDDLERS_TITLE),\n\t\t\t\tstoryList = $tw.wiki.filterTiddlers(storyFilter);\n\t\t\t//invoke any hooks that might change the default story list\n\t\t\tstoryList = $tw.hooks.invokeHook(\"th-opening-default-tiddlers-list\",storyList);\n\t\t\t$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: \"\", list: storyList},$tw.wiki.getModificationFields());\n\t\t\tif(storyList[0]) {\n\t\t\t\t$tw.wiki.addToHistory(storyList[0]);\n\t\t\t}\n\t\t});\n\t\t// Listen for the tm-permalink message\n\t\t$tw.rootWidget.addEventListener(\"tm-permalink\",function(event) {\n\t\t\tupdateLocationHash({\n\t\t\t\tupdateAddressBar: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_UPDATE_ADDRESS_BAR,\"yes\").trim() === \"yes\" ? \"permalink\" : \"none\",\n\t\t\t\tupdateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,\"no\").trim(),\n\t\t\t\ttargetTiddler: event.param || event.tiddlerTitle,\n\t\t\t\tcopyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,\"yes\").trim() === \"yes\" ? \"permalink\" : \"none\"\n\t\t\t});\n\t\t});\n\t\t// Listen for the tm-permaview message\n\t\t$tw.rootWidget.addEventListener(\"tm-permaview\",function(event) {\n\t\t\tupdateLocationHash({\n\t\t\t\tupdateAddressBar: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_UPDATE_ADDRESS_BAR,\"yes\").trim() === \"yes\" ? \"permaview\" : \"none\",\n\t\t\t\tupdateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,\"no\").trim(),\n\t\t\t\ttargetTiddler: event.param || event.tiddlerTitle,\n\t\t\t\tcopyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,\"yes\").trim() === \"yes\" ? \"permaview\" : \"none\"\n\t\t\t});\t\t\t\t\n\t\t});\n\t}\n};\n\n/*\nProcess the location hash to open the specified tiddlers. Options:\ndisableHistory: if true $:/History is NOT updated\ndefaultToCurrentStory: If true, the current story is retained as the default, instead of opening the default tiddlers\n*/\nfunction openStartupTiddlers(options) {\n\toptions = options || {};\n\t// Work out the target tiddler and the story filter. \"null\" means \"unspecified\"\n\tvar target = null,\n\t\tstoryFilter = null;\n\tif($tw.locationHash.length > 1) {\n\t\tvar hash = $tw.locationHash.substr(1),\n\t\t\tsplit = hash.indexOf(\":\");\n\t\tif(split === -1) {\n\t\t\ttarget = decodeURIComponent(hash.trim());\n\t\t} else {\n\t\t\ttarget = decodeURIComponent(hash.substr(0,split).trim());\n\t\t\tstoryFilter = decodeURIComponent(hash.substr(split + 1).trim());\n\t\t}\n\t}\n\t// If the story wasn't specified use the current tiddlers or a blank story\n\tif(storyFilter === null) {\n\t\tif(options.defaultToCurrentStory) {\n\t\t\tvar currStoryList = $tw.wiki.getTiddlerList(DEFAULT_STORY_TITLE);\n\t\t\tstoryFilter = $tw.utils.stringifyList(currStoryList);\n\t\t} else {\n\t\t\tif(target && target !== \"\") {\n\t\t\t\tstoryFilter = \"\";\n\t\t\t} else {\n\t\t\t\tstoryFilter = $tw.wiki.getTiddlerText(DEFAULT_TIDDLERS_TITLE);\n\t\t\t}\n\t\t}\n\t}\n\t// Process the story filter to get the story list\n\tvar storyList = $tw.wiki.filterTiddlers(storyFilter);\n\t// Invoke any hooks that want to change the default story list\n\tstoryList = $tw.hooks.invokeHook(\"th-opening-default-tiddlers-list\",storyList);\n\t// If the target tiddler isn't included then splice it in at the top\n\tif(target && storyList.indexOf(target) === -1) {\n\t\tstoryList.unshift(target);\n\t}\n\t// Save the story list\n\t$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: \"\", list: storyList},$tw.wiki.getModificationFields());\n\t// Update history\n\tif(!options.disableHistory) {\n\t\t// If a target tiddler was specified add it to the history stack\n\t\tif(target && target !== \"\") {\n\t\t\t// The target tiddler doesn't need double square brackets, but we'll silently remove them if they're present\n\t\t\tif(target.indexOf(\"[[\") === 0 && target.substr(-2) === \"]]\") {\n\t\t\t\ttarget = target.substr(2,target.length - 4);\n\t\t\t}\n\t\t\t$tw.wiki.addToHistory(target);\n\t\t} else if(storyList.length > 0) {\n\t\t\t$tw.wiki.addToHistory(storyList[0]);\n\t\t}\t\t\n\t}\n}\n\n/*\noptions: See below\noptions.updateAddressBar: \"permalink\", \"permaview\" or \"no\" (defaults to \"permaview\")\noptions.updateHistory: \"yes\" or \"no\" (defaults to \"no\")\noptions.copyToClipboard: \"permalink\", \"permaview\" or \"no\" (defaults to \"no\")\noptions.targetTiddler: optional title of target tiddler for permalink\n*/\nfunction updateLocationHash(options) {\n\t// Get the story and the history stack\n\tvar storyList = $tw.wiki.getTiddlerList(DEFAULT_STORY_TITLE),\n\t\thistoryList = $tw.wiki.getTiddlerData(DEFAULT_HISTORY_TITLE,[]),\n\t\ttargetTiddler = \"\";\n\tif(options.targetTiddler) {\n\t\ttargetTiddler = options.targetTiddler;\n\t} else {\n\t\t// The target tiddler is the one at the top of the stack\n\t\tif(historyList.length > 0) {\n\t\t\ttargetTiddler = historyList[historyList.length-1].title;\n\t\t}\n\t\t// Blank the target tiddler if it isn't present in the story\n\t\tif(storyList.indexOf(targetTiddler) === -1) {\n\t\t\ttargetTiddler = \"\";\n\t\t}\n\t}\n\t// Assemble the location hash\n\tswitch(options.updateAddressBar) {\n\t\tcase \"permalink\":\n\t\t\t$tw.locationHash = \"#\" + encodeURIComponent(targetTiddler);\n\t\t\tbreak;\n\t\tcase \"permaview\":\n\t\t\t$tw.locationHash = \"#\" + encodeURIComponent(targetTiddler) + \":\" + encodeURIComponent($tw.utils.stringifyList(storyList));\n\t\t\tbreak;\n\t}\n\t// Copy URL to the clipboard\n\tswitch(options.copyToClipboard) {\n\t\tcase \"permalink\":\n\t\t\t$tw.utils.copyToClipboard($tw.utils.getLocationPath() + \"#\" + encodeURIComponent(targetTiddler));\n\t\t\tbreak;\n\t\tcase \"permaview\":\n\t\t\t$tw.utils.copyToClipboard($tw.utils.getLocationPath() + \"#\" + encodeURIComponent(targetTiddler) + \":\" + encodeURIComponent($tw.utils.stringifyList(storyList)));\n\t\t\tbreak;\n\t}\n\t// Only change the location hash if we must, thus avoiding unnecessary onhashchange events\n\tif($tw.utils.getLocationHash() !== $tw.locationHash) {\n\t\tif(options.updateHistory === \"yes\") {\n\t\t\t// Assign the location hash so that history is updated\n\t\t\twindow.location.hash = $tw.locationHash;\n\t\t} else {\n\t\t\t// We use replace so that browser history isn't affected\n\t\t\twindow.location.replace(window.location.toString().split(\"#\")[0] + $tw.locationHash);\n\t\t}\n\t}\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/startup/windows.js": {
            "title": "$:/core/modules/startup/windows.js",
            "text": "/*\\\ntitle: $:/core/modules/startup/windows.js\ntype: application/javascript\nmodule-type: startup\n\nSetup root widget handlers for the messages concerned with opening external browser windows\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"windows\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\n// Global to keep track of open windows (hashmap by title)\nvar windows = {};\n\nexports.startup = function() {\n\t// Handle open window message\n\t$tw.rootWidget.addEventListener(\"tm-open-window\",function(event) {\n\t\t// Get the parameters\n\t\tvar refreshHandler,\n\t\t\ttitle = event.param || event.tiddlerTitle,\n\t\t\tparamObject = event.paramObject || {},\n\t\t\twindowTitle = paramObject.windowTitle || title,\n\t\t\ttemplate = paramObject.template || \"$:/core/templates/single.tiddler.window\",\n\t\t\twidth = paramObject.width || \"700\",\n\t\t\theight = paramObject.height || \"600\",\n\t\t\tvariables = $tw.utils.extend({},paramObject,{currentTiddler: title});\n\t\t// Open the window\n\t\tvar srcWindow,\n\t\t    srcDocument;\n\t\t// In case that popup blockers deny opening a new window\n\t\ttry {\n\t\t\tsrcWindow = window.open(\"\",\"external-\" + title,\"scrollbars,width=\" + width + \",height=\" + height),\n\t\t\tsrcDocument = srcWindow.document;\n\t\t}\n\t\tcatch(e) {\n\t\t\treturn;\n\t\t}\n\t\twindows[title] = srcWindow;\n\t\t// Check for reopening the same window\n\t\tif(srcWindow.haveInitialisedWindow) {\n\t\t\treturn;\n\t\t}\n\t\t// Initialise the document\n\t\tsrcDocument.write(\"<html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>\");\n\t\tsrcDocument.close();\n\t\tsrcDocument.title = windowTitle;\n\t\tsrcWindow.addEventListener(\"beforeunload\",function(event) {\n\t\t\tdelete windows[title];\n\t\t\t$tw.wiki.removeEventListener(\"change\",refreshHandler);\n\t\t},false);\n\t\t// Set up the styles\n\t\tvar styleWidgetNode = $tw.wiki.makeTranscludeWidget(\"$:/core/ui/PageStylesheet\",{\n\t\t\t\tdocument: $tw.fakeDocument,\n\t\t\t\tvariables: variables,\n\t\t\t\timportPageMacros: true}),\n\t\t\tstyleContainer = $tw.fakeDocument.createElement(\"style\");\n\t\tstyleWidgetNode.render(styleContainer,null);\n\t\tvar styleElement = srcDocument.createElement(\"style\");\n\t\tstyleElement.innerHTML = styleContainer.textContent;\n\t\tsrcDocument.head.insertBefore(styleElement,srcDocument.head.firstChild);\n\t\t// Render the text of the tiddler\n\t\tvar parser = $tw.wiki.parseTiddler(template),\n\t\t\twidgetNode = $tw.wiki.makeWidget(parser,{document: srcDocument, parentWidget: $tw.rootWidget, variables: variables});\n\t\twidgetNode.render(srcDocument.body,srcDocument.body.firstChild);\n\t\t// Function to handle refreshes\n\t\trefreshHandler = function(changes) {\n\t\t\tif(styleWidgetNode.refresh(changes,styleContainer,null)) {\n\t\t\t\tstyleElement.innerHTML = styleContainer.textContent;\n\t\t\t}\n\t\t\twidgetNode.refresh(changes);\n\t\t};\n\t\t$tw.wiki.addEventListener(\"change\",refreshHandler);\n\t\t// Listen for keyboard shortcuts\n\t\t$tw.utils.addEventListeners(srcDocument,[{\n\t\t\tname: \"keydown\",\n\t\t\thandlerObject: $tw.keyboardManager,\n\t\t\thandlerMethod: \"handleKeydownEvent\"\n\t\t},{\n\t\t\tname: \"click\",\n\t\t\thandlerObject: $tw.popup,\n\t\t\thandlerMethod: \"handleEvent\"\n\t\t}]);\n\t\tsrcWindow.haveInitialisedWindow = true;\n\t});\n\t// Close open windows when unloading main window\n\t$tw.addUnloadTask(function() {\n\t\t$tw.utils.each(windows,function(win) {\n\t\t\twin.close();\n\t\t});\n\t});\n\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "startup"
        },
        "$:/core/modules/story.js": {
            "title": "$:/core/modules/story.js",
            "text": "/*\\\ntitle: $:/core/modules/story.js\ntype: application/javascript\nmodule-type: global\n\nLightweight object for managing interactions with the story and history lists.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nConstruct Story object with options:\nwiki: reference to wiki object to use to resolve tiddler titles\nstoryTitle: title of story list tiddler\nhistoryTitle: title of history list tiddler\n*/\nfunction Story(options) {\n\toptions = options || {};\n\tthis.wiki = options.wiki || $tw.wiki;\n\tthis.storyTitle = options.storyTitle || \"$:/StoryList\";\n\tthis.historyTitle = options.historyTitle || \"$:/HistoryList\";\n};\n\nStory.prototype.navigateTiddler = function(navigateTo,navigateFromTitle,navigateFromClientRect) {\n\tthis.addToStory(navigateTo,navigateFromTitle);\n\tthis.addToHistory(navigateTo,navigateFromClientRect);\n};\n\nStory.prototype.getStoryList = function() {\n\treturn this.wiki.getTiddlerList(this.storyTitle) || [];\n};\n\nStory.prototype.addToStory = function(navigateTo,navigateFromTitle,options) {\n\toptions = options || {};\n\tvar storyList = this.getStoryList();\n\t// See if the tiddler is already there\n\tvar slot = storyList.indexOf(navigateTo);\n\t// Quit if it already exists in the story river\n\tif(slot >= 0) {\n\t\treturn;\n\t}\n\t// First we try to find the position of the story element we navigated from\n\tvar fromIndex = storyList.indexOf(navigateFromTitle);\n\tif(fromIndex >= 0) {\n\t\t// The tiddler is added from inside the river\n\t\t// Determine where to insert the tiddler; Fallback is \"below\"\n\t\tswitch(options.openLinkFromInsideRiver) {\n\t\t\tcase \"top\":\n\t\t\t\tslot = 0;\n\t\t\t\tbreak;\n\t\t\tcase \"bottom\":\n\t\t\t\tslot = storyList.length;\n\t\t\t\tbreak;\n\t\t\tcase \"above\":\n\t\t\t\tslot = fromIndex;\n\t\t\t\tbreak;\n\t\t\tcase \"below\": // Intentional fall-through\n\t\t\tdefault:\n\t\t\t\tslot = fromIndex + 1;\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\t// The tiddler is opened from outside the river. Determine where to insert the tiddler; default is \"top\"\n\t\tif(options.openLinkFromOutsideRiver === \"bottom\") {\n\t\t\t// Insert at bottom\n\t\t\tslot = storyList.length;\n\t\t} else {\n\t\t\t// Insert at top\n\t\t\tslot = 0;\n\t\t}\n\t}\n\t// Add the tiddler\n\tstoryList.splice(slot,0,navigateTo);\n\t// Save the story\n\tthis.saveStoryList(storyList);\n};\n\nStory.prototype.saveStoryList = function(storyList) {\n\tvar storyTiddler = this.wiki.getTiddler(this.storyTitle);\n\tthis.wiki.addTiddler(new $tw.Tiddler(\n\t\tthis.wiki.getCreationFields(),\n\t\t{title: this.storyTitle},\n\t\tstoryTiddler,\n\t\t{list: storyList},\n\t\tthis.wiki.getModificationFields()\n\t));\n};\n\nStory.prototype.addToHistory = function(navigateTo,navigateFromClientRect) {\n\tvar titles = $tw.utils.isArray(navigateTo) ? navigateTo : [navigateTo];\n\t// Add a new record to the top of the history stack\n\tvar historyList = this.wiki.getTiddlerData(this.historyTitle,[]);\n\t$tw.utils.each(titles,function(title) {\n\t\thistoryList.push({title: title, fromPageRect: navigateFromClientRect});\n\t});\n\tthis.wiki.setTiddlerData(this.historyTitle,historyList,{\"current-tiddler\": titles[titles.length-1]});\n};\n\nStory.prototype.storyCloseTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyCloseAllTiddlers = function() {\n// TBD\n};\n\nStory.prototype.storyCloseOtherTiddlers = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyEditTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyDeleteTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storySaveTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyCancelTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyNewTiddler = function(targetTitle) {\n// TBD\n};\n\nexports.Story = Story;\n\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/storyviews/classic.js": {
            "title": "$:/core/modules/storyviews/classic.js",
            "text": "/*\\\ntitle: $:/core/modules/storyviews/classic.js\ntype: application/javascript\nmodule-type: storyview\n\nViews the story as a linear sequence\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar easing = \"cubic-bezier(0.645, 0.045, 0.355, 1)\"; // From http://easings.net/#easeInOutCubic\n\nvar ClassicStoryView = function(listWidget) {\n\tthis.listWidget = listWidget;\n};\n\nClassicStoryView.prototype.navigateTo = function(historyInfo) {\n\tvar duration = $tw.utils.getAnimationDuration()\n\tvar listElementIndex = this.listWidget.findListItem(0,historyInfo.title);\n\tif(listElementIndex === undefined) {\n\t\treturn;\n\t}\n\tvar listItemWidget = this.listWidget.children[listElementIndex],\n\t\ttargetElement = listItemWidget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\tif(duration) {\n\t\t// Scroll the node into view\n\t\tthis.listWidget.dispatchEvent({type: \"tm-scroll\", target: targetElement});\t\n\t} else {\n\t\ttargetElement.scrollIntoView();\n\t}\n};\n\nClassicStoryView.prototype.insert = function(widget) {\n\tvar duration = $tw.utils.getAnimationDuration();\n\tif(duration) {\n\t\tvar targetElement = widget.findFirstDomNode();\n\t\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\t\tif(!(targetElement instanceof Element)) {\n\t\t\treturn;\n\t\t}\n\t\t// Get the current height of the tiddler\n\t\tvar computedStyle = window.getComputedStyle(targetElement),\n\t\t\tcurrMarginBottom = parseInt(computedStyle.marginBottom,10),\n\t\t\tcurrMarginTop = parseInt(computedStyle.marginTop,10),\n\t\t\tcurrHeight = targetElement.offsetHeight + currMarginTop;\n\t\t// Reset the margin once the transition is over\n\t\tsetTimeout(function() {\n\t\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t\t{transition: \"none\"},\n\t\t\t\t{marginBottom: \"\"}\n\t\t\t]);\n\t\t},duration);\n\t\t// Set up the initial position of the element\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: \"none\"},\n\t\t\t{marginBottom: (-currHeight) + \"px\"},\n\t\t\t{opacity: \"0.0\"}\n\t\t]);\n\t\t$tw.utils.forceLayout(targetElement);\n\t\t// Transition to the final position\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: \"opacity \" + duration + \"ms \" + easing + \", \" +\n\t\t\t\t\t\t\"margin-bottom \" + duration + \"ms \" + easing},\n\t\t\t{marginBottom: currMarginBottom + \"px\"},\n\t\t\t{opacity: \"1.0\"}\n\t]);\n\t}\n};\n\nClassicStoryView.prototype.remove = function(widget) {\n\tvar duration = $tw.utils.getAnimationDuration();\n\tif(duration) {\n\t\tvar targetElement = widget.findFirstDomNode(),\n\t\t\tremoveElement = function() {\n\t\t\t\twidget.removeChildDomNodes();\n\t\t\t};\n\t\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\t\tif(!(targetElement instanceof Element)) {\n\t\t\tremoveElement();\n\t\t\treturn;\n\t\t}\n\t\t// Get the current height of the tiddler\n\t\tvar currWidth = targetElement.offsetWidth,\n\t\t\tcomputedStyle = window.getComputedStyle(targetElement),\n\t\t\tcurrMarginBottom = parseInt(computedStyle.marginBottom,10),\n\t\t\tcurrMarginTop = parseInt(computedStyle.marginTop,10),\n\t\t\tcurrHeight = targetElement.offsetHeight + currMarginTop;\n\t\t// Remove the dom nodes of the widget at the end of the transition\n\t\tsetTimeout(removeElement,duration);\n\t\t// Animate the closure\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: \"none\"},\n\t\t\t{transform: \"translateX(0px)\"},\n\t\t\t{marginBottom:  currMarginBottom + \"px\"},\n\t\t\t{opacity: \"1.0\"}\n\t\t]);\n\t\t$tw.utils.forceLayout(targetElement);\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", \" +\n\t\t\t\t\t\t\"opacity \" + duration + \"ms \" + easing + \", \" +\n\t\t\t\t\t\t\"margin-bottom \" + duration + \"ms \" + easing},\n\t\t\t{transform: \"translateX(-\" + currWidth + \"px)\"},\n\t\t\t{marginBottom: (-currHeight) + \"px\"},\n\t\t\t{opacity: \"0.0\"}\n\t\t]);\n\t} else {\n\t\twidget.removeChildDomNodes();\n\t}\n};\n\nexports.classic = ClassicStoryView;\n\n})();",
            "type": "application/javascript",
            "module-type": "storyview"
        },
        "$:/core/modules/storyviews/pop.js": {
            "title": "$:/core/modules/storyviews/pop.js",
            "text": "/*\\\ntitle: $:/core/modules/storyviews/pop.js\ntype: application/javascript\nmodule-type: storyview\n\nAnimates list insertions and removals\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar PopStoryView = function(listWidget) {\n\tthis.listWidget = listWidget;\n};\n\nPopStoryView.prototype.navigateTo = function(historyInfo) {\n\tvar listElementIndex = this.listWidget.findListItem(0,historyInfo.title);\n\tif(listElementIndex === undefined) {\n\t\treturn;\n\t}\n\tvar listItemWidget = this.listWidget.children[listElementIndex],\n\t\ttargetElement = listItemWidget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Scroll the node into view\n\tthis.listWidget.dispatchEvent({type: \"tm-scroll\", target: targetElement});\n};\n\nPopStoryView.prototype.insert = function(widget) {\n\tvar targetElement = widget.findFirstDomNode(),\n\t\tduration = $tw.utils.getAnimationDuration();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Reset once the transition is over\n\tsetTimeout(function() {\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: \"none\"},\n\t\t\t{transform: \"none\"}\n\t\t]);\n\t\t$tw.utils.setStyle(widget.document.body,[\n\t\t\t{\"overflow-x\": \"\"}\n\t\t]);\n\t},duration);\n\t// Prevent the page from overscrolling due to the zoom factor\n\t$tw.utils.setStyle(widget.document.body,[\n\t\t{\"overflow-x\": \"hidden\"}\n\t]);\n\t// Set up the initial position of the element\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: \"none\"},\n\t\t{transform: \"scale(2)\"},\n\t\t{opacity: \"0.0\"}\n\t]);\n\t$tw.utils.forceLayout(targetElement);\n\t// Transition to the final position\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{transform: \"scale(1)\"},\n\t\t{opacity: \"1.0\"}\n\t]);\n};\n\nPopStoryView.prototype.remove = function(widget) {\n\tvar targetElement = widget.findFirstDomNode(),\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\tremoveElement = function() {\n\t\t\tif(targetElement && targetElement.parentNode) {\n\t\t\t\twidget.removeChildDomNodes();\n\t\t\t}\n\t\t};\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\tremoveElement();\n\t\treturn;\n\t}\n\t// Remove the element at the end of the transition\n\tsetTimeout(removeElement,duration);\n\t// Animate the closure\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: \"none\"},\n\t\t{transform: \"scale(1)\"},\n\t\t{opacity: \"1.0\"}\n\t]);\n\t$tw.utils.forceLayout(targetElement);\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{transform: \"scale(0.1)\"},\n\t\t{opacity: \"0.0\"}\n\t]);\n};\n\nexports.pop = PopStoryView;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "storyview"
        },
        "$:/core/modules/storyviews/zoomin.js": {
            "title": "$:/core/modules/storyviews/zoomin.js",
            "text": "/*\\\ntitle: $:/core/modules/storyviews/zoomin.js\ntype: application/javascript\nmodule-type: storyview\n\nZooms between individual tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar easing = \"cubic-bezier(0.645, 0.045, 0.355, 1)\"; // From http://easings.net/#easeInOutCubic\n\nvar ZoominListView = function(listWidget) {\n\tvar self = this;\n\tthis.listWidget = listWidget;\n\t// Get the index of the tiddler that is at the top of the history\n\tvar history = this.listWidget.wiki.getTiddlerDataCached(this.listWidget.historyTitle,[]),\n\t\ttargetTiddler;\n\tif(history.length > 0) {\n\t\ttargetTiddler = history[history.length-1].title;\n\t}\n\t// Make all the tiddlers position absolute, and hide all but the top (or first) one\n\t$tw.utils.each(this.listWidget.children,function(itemWidget,index) {\n\t\tvar domNode = itemWidget.findFirstDomNode();\n\t\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\t\tif(!(domNode instanceof Element)) {\n\t\t\treturn;\n\t\t}\n\t\tif((targetTiddler && targetTiddler !== itemWidget.parseTreeNode.itemTitle) || (!targetTiddler && index)) {\n\t\t\tdomNode.style.display = \"none\";\n\t\t} else {\n\t\t\tself.currentTiddlerDomNode = domNode;\n\t\t}\n\t\t$tw.utils.addClass(domNode,\"tc-storyview-zoomin-tiddler\");\n\t});\n};\n\nZoominListView.prototype.navigateTo = function(historyInfo) {\n\tvar duration = $tw.utils.getAnimationDuration(),\n\t\tlistElementIndex = this.listWidget.findListItem(0,historyInfo.title);\n\tif(listElementIndex === undefined) {\n\t\treturn;\n\t}\n\tvar listItemWidget = this.listWidget.children[listElementIndex],\n\t\ttargetElement = listItemWidget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Make the new tiddler be position absolute and visible so that we can measure it\n\t$tw.utils.addClass(targetElement,\"tc-storyview-zoomin-tiddler\");\n\t$tw.utils.setStyle(targetElement,[\n\t\t{display: \"block\"},\n\t\t{transformOrigin: \"0 0\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t{transition: \"none\"},\n\t\t{opacity: \"0.0\"}\n\t]);\n\t// Get the position of the source node, or use the centre of the window as the source position\n\tvar sourceBounds = historyInfo.fromPageRect || {\n\t\t\tleft: window.innerWidth/2 - 2,\n\t\t\ttop: window.innerHeight/2 - 2,\n\t\t\twidth: window.innerWidth/8,\n\t\t\theight: window.innerHeight/8\n\t\t};\n\t// Try to find the title node in the target tiddler\n\tvar titleDomNode = findTitleDomNode(listItemWidget) || listItemWidget.findFirstDomNode(),\n\t\tzoomBounds = titleDomNode.getBoundingClientRect();\n\t// Compute the transform for the target tiddler to make the title lie over the source rectange\n\tvar targetBounds = targetElement.getBoundingClientRect(),\n\t\tscale = sourceBounds.width / zoomBounds.width,\n\t\tx = sourceBounds.left - targetBounds.left - (zoomBounds.left - targetBounds.left) * scale,\n\t\ty = sourceBounds.top - targetBounds.top - (zoomBounds.top - targetBounds.top) * scale;\n\t// Transform the target tiddler to its starting position\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transform: \"translateX(\" + x + \"px) translateY(\" + y + \"px) scale(\" + scale + \")\"}\n\t]);\n\t// Force layout\n\t$tw.utils.forceLayout(targetElement);\n\t// Apply the ending transitions with a timeout to ensure that the previously applied transformations are applied first\n\tvar self = this,\n\t\tprevCurrentTiddler = this.currentTiddlerDomNode;\n\tthis.currentTiddlerDomNode = targetElement;\n\t// Transform the target tiddler to its natural size\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t{opacity: \"1.0\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t{zIndex: \"500\"},\n\t]);\n\t// Transform the previous tiddler out of the way and then hide it\n\tif(prevCurrentTiddler && prevCurrentTiddler !== targetElement) {\n\t\tscale = zoomBounds.width / sourceBounds.width;\n\t\tx =  zoomBounds.left - targetBounds.left - (sourceBounds.left - targetBounds.left) * scale;\n\t\ty =  zoomBounds.top - targetBounds.top - (sourceBounds.top - targetBounds.top) * scale;\n\t\t$tw.utils.setStyle(prevCurrentTiddler,[\n\t\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t\t{opacity: \"0.0\"},\n\t\t\t{transformOrigin: \"0 0\"},\n\t\t\t{transform: \"translateX(\" + x + \"px) translateY(\" + y + \"px) scale(\" + scale + \")\"},\n\t\t\t{zIndex: \"0\"}\n\t\t]);\n\t\t// Hide the tiddler when the transition has finished\n\t\tsetTimeout(function() {\n\t\t\tif(self.currentTiddlerDomNode !== prevCurrentTiddler) {\n\t\t\t\tprevCurrentTiddler.style.display = \"none\";\n\t\t\t}\n\t\t},duration);\n\t}\n\t// Scroll the target into view\n//\t$tw.pageScroller.scrollIntoView(targetElement);\n};\n\n/*\nFind the first child DOM node of a widget that has the class \"tc-title\"\n*/\nfunction findTitleDomNode(widget,targetClass) {\n\ttargetClass = targetClass || \"tc-title\";\n\tvar domNode = widget.findFirstDomNode();\n\tif(domNode && domNode.querySelector) {\n\t\treturn domNode.querySelector(\".\" + targetClass);\n\t}\n\treturn null;\n}\n\nZoominListView.prototype.insert = function(widget) {\n\tvar targetElement = widget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Make the newly inserted node position absolute and hidden\n\t$tw.utils.addClass(targetElement,\"tc-storyview-zoomin-tiddler\");\n\t$tw.utils.setStyle(targetElement,[\n\t\t{display: \"none\"}\n\t]);\n};\n\nZoominListView.prototype.remove = function(widget) {\n\tvar targetElement = widget.findFirstDomNode(),\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\tremoveElement = function() {\n\t\t\twidget.removeChildDomNodes();\n\t\t};\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\tremoveElement();\n\t\treturn;\n\t}\n\t// Abandon if hidden\n\tif(targetElement.style.display != \"block\" ) {\n\t\tremoveElement();\n\t\treturn;\n\t}\n\t// Set up the tiddler that is being closed\n\t$tw.utils.addClass(targetElement,\"tc-storyview-zoomin-tiddler\");\n\t$tw.utils.setStyle(targetElement,[\n\t\t{display: \"block\"},\n\t\t{transformOrigin: \"50% 50%\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t{transition: \"none\"},\n\t\t{zIndex: \"0\"}\n\t]);\n\t// We'll move back to the previous or next element in the story\n\tvar toWidget = widget.previousSibling();\n\tif(!toWidget) {\n\t\ttoWidget = widget.nextSibling();\n\t}\n\tvar toWidgetDomNode = toWidget && toWidget.findFirstDomNode();\n\t// Set up the tiddler we're moving back in\n\tif(toWidgetDomNode) {\n\t\t$tw.utils.addClass(toWidgetDomNode,\"tc-storyview-zoomin-tiddler\");\n\t\t$tw.utils.setStyle(toWidgetDomNode,[\n\t\t\t{display: \"block\"},\n\t\t\t{transformOrigin: \"50% 50%\"},\n\t\t\t{transform: \"translateX(0px) translateY(0px) scale(10)\"},\n\t\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t\t{opacity: \"0\"},\n\t\t\t{zIndex: \"500\"}\n\t\t]);\n\t\tthis.currentTiddlerDomNode = toWidgetDomNode;\n\t}\n\t// Animate them both\n\t// Force layout\n\t$tw.utils.forceLayout(this.listWidget.parentDomNode);\n\t// First, the tiddler we're closing\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transformOrigin: \"50% 50%\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(0.1)\"},\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t{opacity: \"0\"},\n\t\t{zIndex: \"0\"}\n\t]);\n\tsetTimeout(removeElement,duration);\n\t// Now the tiddler we're going back to\n\tif(toWidgetDomNode) {\n\t\t$tw.utils.setStyle(toWidgetDomNode,[\n\t\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t\t{opacity: \"1\"}\n\t\t]);\n\t}\n\treturn true; // Indicate that we'll delete the DOM node\n};\n\nexports.zoomin = ZoominListView;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "storyview"
        },
        "$:/core/modules/syncer.js": {
            "title": "$:/core/modules/syncer.js",
            "text": "/*\\\ntitle: $:/core/modules/syncer.js\ntype: application/javascript\nmodule-type: global\n\nThe syncer tracks changes to the store and synchronises them to a remote data store represented as a \"sync adaptor\"\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nDefaults\n*/\nSyncer.prototype.titleIsLoggedIn = \"$:/status/IsLoggedIn\";\nSyncer.prototype.titleIsAnonymous = \"$:/status/IsAnonymous\";\nSyncer.prototype.titleIsReadOnly = \"$:/status/IsReadOnly\";\nSyncer.prototype.titleUserName = \"$:/status/UserName\";\nSyncer.prototype.titleSyncFilter = \"$:/config/SyncFilter\";\nSyncer.prototype.titleSyncPollingInterval = \"$:/config/SyncPollingInterval\";\nSyncer.prototype.titleSyncDisableLazyLoading = \"$:/config/SyncDisableLazyLoading\";\nSyncer.prototype.titleSavedNotification = \"$:/language/Notifications/Save/Done\";\nSyncer.prototype.titleSyncThrottleInterval = \"$:/config/SyncThrottleInterval\";\nSyncer.prototype.taskTimerInterval = 1 * 1000; // Interval for sync timer\nSyncer.prototype.throttleInterval = 1 * 1000; // Defer saving tiddlers if they've changed in the last 1s...\nSyncer.prototype.errorRetryInterval = 5 * 1000; // Interval to retry after an error\nSyncer.prototype.fallbackInterval = 10 * 1000; // Unless the task is older than 10s\nSyncer.prototype.pollTimerInterval = 60 * 1000; // Interval for polling for changes from the adaptor\n\n/*\nInstantiate the syncer with the following options:\nsyncadaptor: reference to syncadaptor to be used\nwiki: wiki to be synced\n*/\nfunction Syncer(options) {\n\tvar self = this;\n\tthis.wiki = options.wiki;\n\t// Save parameters\n\tthis.syncadaptor = options.syncadaptor;\n\tthis.disableUI = !!options.disableUI;\n\tthis.titleIsLoggedIn = options.titleIsLoggedIn || this.titleIsLoggedIn;\n\tthis.titleUserName = options.titleUserName || this.titleUserName;\n\tthis.titleSyncFilter = options.titleSyncFilter || this.titleSyncFilter;\n\tthis.titleSavedNotification = options.titleSavedNotification || this.titleSavedNotification;\n\tthis.taskTimerInterval = options.taskTimerInterval || this.taskTimerInterval;\n\tthis.throttleInterval = options.throttleInterval || parseInt(this.wiki.getTiddlerText(this.titleSyncThrottleInterval,\"\"),10) || this.throttleInterval;\n\tthis.errorRetryInterval = options.errorRetryInterval || this.errorRetryInterval;\n\tthis.fallbackInterval = options.fallbackInterval || this.fallbackInterval;\n\tthis.pollTimerInterval = options.pollTimerInterval || parseInt(this.wiki.getTiddlerText(this.titleSyncPollingInterval,\"\"),10) || this.pollTimerInterval;\n\tthis.logging = \"logging\" in options ? options.logging : true;\n\t// Make a logger\n\tthis.logger = new $tw.utils.Logger(\"syncer\" + ($tw.browser ? \"-browser\" : \"\") + ($tw.node ? \"-server\" : \"\")  + (this.syncadaptor.name ? (\"-\" + this.syncadaptor.name) : \"\"),{\n\t\tcolour: \"cyan\",\n\t\tenable: this.logging,\n\t\tsaveHistory: true\n\t});\n\t// Make another logger for connection errors\n\tthis.loggerConnection = new $tw.utils.Logger(\"syncer\" + ($tw.browser ? \"-browser\" : \"\") + ($tw.node ? \"-server\" : \"\")  + (this.syncadaptor.name ? (\"-\" + this.syncadaptor.name) : \"\") + \"-connection\",{\n\t\tcolour: \"cyan\",\n\t\tenable: this.logging\n\t});\n\t// Ask the syncadaptor to use the main logger\n\tif(this.syncadaptor.setLoggerSaveBuffer) {\n\t\tthis.syncadaptor.setLoggerSaveBuffer(this.logger);\n\t}\n\t// Compile the dirty tiddler filter\n\tthis.filterFn = this.wiki.compileFilter(this.wiki.getTiddlerText(this.titleSyncFilter));\n\t// Record information for known tiddlers\n\tthis.readTiddlerInfo();\n\tthis.titlesToBeLoaded = {}; // Hashmap of titles of tiddlers that need loading from the server\n\tthis.titlesHaveBeenLazyLoaded = {}; // Hashmap of titles of tiddlers that have already been lazily loaded from the server\n\t// Timers\n\tthis.taskTimerId = null; // Timer for task dispatch\n\tthis.pollTimerId = null; // Timer for polling server\n\t// Number of outstanding requests\n\tthis.numTasksInProgress = 0;\n\t// Listen out for changes to tiddlers\n\tthis.wiki.addEventListener(\"change\",function(changes) {\n\t\t// Filter the changes to just include ones that are being synced\n\t\tvar filteredChanges = self.getSyncedTiddlers(function(callback) {\n\t\t\t$tw.utils.each(changes,function(change,title) {\n\t\t\t\tvar tiddler = self.wiki.tiddlerExists(title) && self.wiki.getTiddler(title);\n\t\t\t\tcallback(tiddler,title);\n\t\t\t});\n\t\t});\n\t\tif(filteredChanges.length > 0) {\n\t\t\tself.processTaskQueue();\n\t\t} else {\n\t\t\t// Look for deletions of tiddlers we're already syncing\t\n\t\t\tvar outstandingDeletion = false\n\t\t\t$tw.utils.each(changes,function(change,title,object) {\n\t\t\t\tif(change.deleted && $tw.utils.hop(self.tiddlerInfo,title)) {\n\t\t\t\t\toutstandingDeletion = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\tif(outstandingDeletion) {\n\t\t\t\tself.processTaskQueue();\n\t\t\t}\n\t\t}\n\t});\n\t// Browser event handlers\n\tif($tw.browser && !this.disableUI) {\n\t\t// Set up our beforeunload handler\n\t\t$tw.addUnloadTask(function(event) {\n\t\t\tvar confirmationMessage;\n\t\t\tif(self.isDirty()) {\n\t\t\t\tconfirmationMessage = $tw.language.getString(\"UnsavedChangesWarning\");\n\t\t\t\tevent.returnValue = confirmationMessage; // Gecko\n\t\t\t}\n\t\t\treturn confirmationMessage;\n\t\t});\n\t\t// Listen out for login/logout/refresh events in the browser\n\t\t$tw.rootWidget.addEventListener(\"tm-login\",function() {\n\t\t\tself.handleLoginEvent();\n\t\t});\n\t\t$tw.rootWidget.addEventListener(\"tm-logout\",function() {\n\t\t\tself.handleLogoutEvent();\n\t\t});\n\t\t$tw.rootWidget.addEventListener(\"tm-server-refresh\",function() {\n\t\t\tself.handleRefreshEvent();\n\t\t});\n\t\t$tw.rootWidget.addEventListener(\"tm-copy-syncer-logs-to-clipboard\",function() {\n\t\t\t$tw.utils.copyToClipboard($tw.utils.getSystemInfo() + \"\\n\\nLog:\\n\" + self.logger.getBuffer());\n\t\t});\n\t}\n\t// Listen out for lazyLoad events\n\tif(!this.disableUI && $tw.wiki.getTiddlerText(this.titleSyncDisableLazyLoading) !== \"yes\") {\n\t\tthis.wiki.addEventListener(\"lazyLoad\",function(title) {\n\t\t\tself.handleLazyLoadEvent(title);\n\t\t});\t\t\n\t}\n\t// Get the login status\n\tthis.getStatus(function(err,isLoggedIn) {\n\t\t// Do a sync from the server\n\t\tself.syncFromServer();\n\t});\n}\n\n/*\nShow a generic network error alert\n*/\nSyncer.prototype.displayError = function(msg,err) {\n\tif(err === ($tw.language.getString(\"Error/XMLHttpRequest\") + \": 0\")) {\n\t\tthis.loggerConnection.alert($tw.language.getString(\"Error/NetworkErrorAlert\"));\n\t\tthis.logger.log(msg + \":\",err);\n\t} else {\n\t\tthis.logger.alert(msg + \":\",err);\n\t}\n};\n\n/*\nReturn an array of the tiddler titles that are subjected to syncing\n*/\nSyncer.prototype.getSyncedTiddlers = function(source) {\n\treturn this.filterFn.call(this.wiki,source);\n};\n\n/*\nReturn an array of the tiddler titles that are subjected to syncing\n*/\nSyncer.prototype.getTiddlerRevision = function(title) {\n\tif(this.syncadaptor && this.syncadaptor.getTiddlerRevision) {\n\t\treturn this.syncadaptor.getTiddlerRevision(title);\n\t} else {\n\t\treturn this.wiki.getTiddler(title).fields.revision;\t\n\t} \n};\n\n/*\nRead (or re-read) the latest tiddler info from the store\n*/\nSyncer.prototype.readTiddlerInfo = function() {\n\t// Hashmap by title of {revision:,changeCount:,adaptorInfo:}\n\t// \"revision\" is the revision of the tiddler last seen on the server, and \"changecount\" is the corresponding local changecount\n\tthis.tiddlerInfo = {};\n\t// Record information for known tiddlers\n\tvar self = this,\n\t\ttiddlers = this.getSyncedTiddlers();\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = self.wiki.tiddlerExists(title) && self.wiki.getTiddler(title);\n\t\tself.tiddlerInfo[title] = {\n\t\t\trevision: self.getTiddlerRevision(title),\n\t\t\tadaptorInfo: self.syncadaptor && self.syncadaptor.getTiddlerInfo(tiddler),\n\t\t\tchangeCount: self.wiki.getChangeCount(title)\n\t\t};\n\t});\n};\n\n/*\nChecks whether the wiki is dirty (ie the window shouldn't be closed)\n*/\nSyncer.prototype.isDirty = function() {\n\tthis.logger.log(\"Checking dirty status\");\n\t// Check tiddlers that are in the store and included in the filter function\n\tvar titles = this.getSyncedTiddlers();\n\tfor(var index=0; index<titles.length; index++) {\n\t\tvar title = titles[index],\n\t\t\ttiddlerInfo = this.tiddlerInfo[title];\n\t\tif(this.wiki.tiddlerExists(title)) {\n\t\t\tif(tiddlerInfo) {\n\t\t\t\t// If the tiddler is known on the server and has been modified locally then it needs to be saved to the server\n\t\t\t\tif($tw.wiki.getChangeCount(title) > tiddlerInfo.changeCount) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If the tiddler isn't known on the server then it needs to be saved to the server\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\t// Check tiddlers that are known from the server but not currently in the store\n\ttitles = Object.keys(this.tiddlerInfo);\n\tfor(index=0; index<titles.length; index++) {\n\t\tif(!this.wiki.tiddlerExists(titles[index])) {\n\t\t\t// There must be a pending delete\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\n/*\nUpdate the document body with the class \"tc-dirty\" if the wiki has unsaved/unsynced changes\n*/\nSyncer.prototype.updateDirtyStatus = function() {\n\tif($tw.browser && !this.disableUI) {\n\t\tvar dirty = this.isDirty();\n\t\t$tw.utils.toggleClass(document.body,\"tc-dirty\",dirty);\n\t\tif(!dirty) {\n\t\t\tthis.loggerConnection.clearAlerts();\n\t\t}\n\t}\n};\n\n/*\nSave an incoming tiddler in the store, and updates the associated tiddlerInfo\n*/\nSyncer.prototype.storeTiddler = function(tiddlerFields) {\n\t// Save the tiddler\n\tvar tiddler = new $tw.Tiddler(tiddlerFields);\n\tthis.wiki.addTiddler(tiddler);\n\t// Save the tiddler revision and changeCount details\n\tthis.tiddlerInfo[tiddlerFields.title] = {\n\t\trevision: this.getTiddlerRevision(tiddlerFields.title),\n\t\tadaptorInfo: this.syncadaptor.getTiddlerInfo(tiddler),\n\t\tchangeCount: this.wiki.getChangeCount(tiddlerFields.title)\n\t};\n};\n\nSyncer.prototype.getStatus = function(callback) {\n\tvar self = this;\n\t// Check if the adaptor supports getStatus()\n\tif(this.syncadaptor && this.syncadaptor.getStatus) {\n\t\t// Mark us as not logged in\n\t\tthis.wiki.addTiddler({title: this.titleIsLoggedIn,text: \"no\"});\n\t\t// Get login status\n\t\tthis.syncadaptor.getStatus(function(err,isLoggedIn,username,isReadOnly,isAnonymous) {\n\t\t\tif(err) {\n\t\t\t\tself.logger.alert(err);\n\t\t\t} else {\n\t\t\t\t// Set the various status tiddlers\n\t\t\t\tself.wiki.addTiddler({title: self.titleIsReadOnly,text: isReadOnly ? \"yes\" : \"no\"});\n\t\t\t\tself.wiki.addTiddler({title: self.titleIsAnonymous,text: isAnonymous ? \"yes\" : \"no\"});\n\t\t\t\tself.wiki.addTiddler({title: self.titleIsLoggedIn,text: isLoggedIn ? \"yes\" : \"no\"});\n\t\t\t\tif(isLoggedIn) {\n\t\t\t\t\tself.wiki.addTiddler({title: self.titleUserName,text: username || \"\"});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Invoke the callback\n\t\t\tif(callback) {\n\t\t\t\tcallback(err,isLoggedIn,username);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tcallback(null,true,\"UNAUTHENTICATED\");\n\t}\n};\n\n/*\nSynchronise from the server by reading the skinny tiddler list and queuing up loads for any tiddlers that we don't already have up to date\n*/\nSyncer.prototype.syncFromServer = function() {\n\tvar self = this,\n\t\tcancelNextSync = function() {\n\t\t\tif(self.pollTimerId) {\n\t\t\t\tclearTimeout(self.pollTimerId);\n\t\t\t\tself.pollTimerId = null;\n\t\t\t}\n\t\t},\n\t\ttriggerNextSync = function() {\n\t\t\tself.pollTimerId = setTimeout(function() {\n\t\t\t\tself.pollTimerId = null;\n\t\t\t\tself.syncFromServer.call(self);\n\t\t\t},self.pollTimerInterval);\n\t\t};\n\tif(this.syncadaptor && this.syncadaptor.getUpdatedTiddlers) {\n\t\tthis.logger.log(\"Retrieving updated tiddler list\");\n\t\tcancelNextSync();\n\t\tthis.syncadaptor.getUpdatedTiddlers(self,function(err,updates) {\n\t\t\ttriggerNextSync();\n\t\t\tif(err) {\n\t\t\t\tself.displayError($tw.language.getString(\"Error/RetrievingSkinny\"),err);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif(updates) {\n\t\t\t\t$tw.utils.each(updates.modifications,function(title) {\n\t\t\t\t\tself.titlesToBeLoaded[title] = true;\n\t\t\t\t});\n\t\t\t\t$tw.utils.each(updates.deletions,function(title) {\n\t\t\t\t\tdelete self.tiddlerInfo[title];\n\t\t\t\t\tself.logger.log(\"Deleting tiddler missing from server:\",title);\n\t\t\t\t\tself.wiki.deleteTiddler(title);\n\t\t\t\t});\n\t\t\t\tif(updates.modifications.length > 0 || updates.deletions.length > 0) {\n\t\t\t\t\tself.processTaskQueue();\n\t\t\t\t}\t\t\t\t\n\t\t\t}\n\t\t});\n\t} else if(this.syncadaptor && this.syncadaptor.getSkinnyTiddlers) {\n\t\tthis.logger.log(\"Retrieving skinny tiddler list\");\n\t\tcancelNextSync();\n\t\tthis.syncadaptor.getSkinnyTiddlers(function(err,tiddlers) {\n\t\t\ttriggerNextSync();\n\t\t\t// Check for errors\n\t\t\tif(err) {\n\t\t\t\tself.displayError($tw.language.getString(\"Error/RetrievingSkinny\"),err);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Keep track of which tiddlers we already know about have been reported this time\n\t\t\tvar previousTitles = Object.keys(self.tiddlerInfo);\n\t\t\t// Process each incoming tiddler\n\t\t\tfor(var t=0; t<tiddlers.length; t++) {\n\t\t\t\t// Get the incoming tiddler fields, and the existing tiddler\n\t\t\t\tvar tiddlerFields = tiddlers[t],\n\t\t\t\t\tincomingRevision = tiddlerFields.revision + \"\",\n\t\t\t\t\ttiddler = self.wiki.tiddlerExists(tiddlerFields.title) && self.wiki.getTiddler(tiddlerFields.title),\n\t\t\t\t\ttiddlerInfo = self.tiddlerInfo[tiddlerFields.title],\n\t\t\t\t\tcurrRevision = tiddlerInfo ? tiddlerInfo.revision : null,\n\t\t\t\t\tindexInPreviousTitles = previousTitles.indexOf(tiddlerFields.title);\n\t\t\t\tif(indexInPreviousTitles !== -1) {\n\t\t\t\t\tpreviousTitles.splice(indexInPreviousTitles,1);\n\t\t\t\t}\n\t\t\t\t// Ignore the incoming tiddler if it's the same as the revision we've already got\n\t\t\t\tif(currRevision !== incomingRevision) {\n\t\t\t\t\t// Only load the skinny version if we don't already have a fat version of the tiddler\n\t\t\t\t\tif(!tiddler || tiddler.fields.text === undefined) {\n\t\t\t\t\t\tself.storeTiddler(tiddlerFields);\n\t\t\t\t\t}\n\t\t\t\t\t// Do a full load of this tiddler\n\t\t\t\t\tself.titlesToBeLoaded[tiddlerFields.title] = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Delete any tiddlers that were previously reported but missing this time\n\t\t\t$tw.utils.each(previousTitles,function(title) {\n\t\t\t\tdelete self.tiddlerInfo[title];\n\t\t\t\tself.logger.log(\"Deleting tiddler missing from server:\",title);\n\t\t\t\tself.wiki.deleteTiddler(title);\n\t\t\t});\n\t\t\tself.processTaskQueue();\n\t\t});\n\t}\n};\n\n/*\nForce load a tiddler from the server\n*/\nSyncer.prototype.enqueueLoadTiddler = function(title) {\n\tthis.titlesToBeLoaded[title] = true;\n\tthis.processTaskQueue();\n};\n\n/*\nLazily load a skinny tiddler if we can\n*/\nSyncer.prototype.handleLazyLoadEvent = function(title) {\n\t// Ignore if the syncadaptor doesn't handle it\n\tif(!this.syncadaptor.supportsLazyLoading) {\n\t\treturn;\n\t}\n\t// Don't lazy load the same tiddler twice\n\tif(!this.titlesHaveBeenLazyLoaded[title]) {\n\t\t// Don't lazy load if the tiddler isn't included in the sync filter\n\t\tif(this.getSyncedTiddlers().indexOf(title) !== -1) {\n\t\t\t// Mark the tiddler as needing loading, and having already been lazily loaded\n\t\t\tthis.titlesToBeLoaded[title] = true;\n\t\t\tthis.titlesHaveBeenLazyLoaded[title] = true;\n\t\t}\n\t}\n};\n\n/*\nDispay a password prompt and allow the user to login\n*/\nSyncer.prototype.handleLoginEvent = function() {\n\tvar self = this;\n\tthis.getStatus(function(err,isLoggedIn,username) {\n\t\tif(!err && !isLoggedIn) {\n\t\t\t$tw.passwordPrompt.createPrompt({\n\t\t\t\tserviceName: $tw.language.getString(\"LoginToTiddlySpace\"),\n\t\t\t\tcallback: function(data) {\n\t\t\t\t\tself.login(data.username,data.password,function(err,isLoggedIn) {\n\t\t\t\t\t\tself.syncFromServer();\n\t\t\t\t\t});\n\t\t\t\t\treturn true; // Get rid of the password prompt\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n};\n\n/*\nAttempt to login to TiddlyWeb.\n\tusername: username\n\tpassword: password\n\tcallback: invoked with arguments (err,isLoggedIn)\n*/\nSyncer.prototype.login = function(username,password,callback) {\n\tthis.logger.log(\"Attempting to login as\",username);\n\tvar self = this;\n\tif(this.syncadaptor.login) {\n\t\tthis.syncadaptor.login(username,password,function(err) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tself.getStatus(function(err,isLoggedIn,username) {\n\t\t\t\tif(callback) {\n\t\t\t\t\tcallback(err,isLoggedIn);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t} else {\n\t\tcallback(null,true);\n\t}\n};\n\n/*\nAttempt to log out of TiddlyWeb\n*/\nSyncer.prototype.handleLogoutEvent = function() {\n\tthis.logger.log(\"Attempting to logout\");\n\tvar self = this;\n\tif(this.syncadaptor.logout) {\n\t\tthis.syncadaptor.logout(function(err) {\n\t\t\tif(err) {\n\t\t\t\tself.logger.alert(err);\n\t\t\t} else {\n\t\t\t\tself.getStatus();\n\t\t\t}\n\t\t});\n\t}\n};\n\n/*\nImmediately refresh from the server\n*/\nSyncer.prototype.handleRefreshEvent = function() {\n\tthis.syncFromServer();\n};\n\n/*\nProcess the next task\n*/\nSyncer.prototype.processTaskQueue = function() {\n\tvar self = this;\n\t// Only process a task if the sync adaptor is fully initialised and we're not already performing\n\t// a task. If we are already performing a task then we'll dispatch the next one when it completes\n\tif((!this.syncadaptor.isReady || this.syncadaptor.isReady()) && this.numTasksInProgress === 0) {\n\t\t// Choose the next task to perform\n\t\tvar task = this.chooseNextTask();\n\t\t// Perform the task if we had one\n\t\tif(typeof task === \"object\" && task !== null) {\n\t\t\tthis.numTasksInProgress += 1;\n\t\t\ttask.run(function(err) {\n\t\t\t\tself.numTasksInProgress -= 1;\n\t\t\t\tif(err) {\n\t\t\t\t\tself.displayError(\"Sync error while processing \" + task.type + \" of '\" + task.title + \"'\",err);\n\t\t\t\t\tself.updateDirtyStatus();\n\t\t\t\t\tself.triggerTimeout(self.errorRetryInterval);\n\t\t\t\t} else {\n\t\t\t\t\tself.updateDirtyStatus();\n\t\t\t\t\t// Process the next task\n\t\t\t\t\tself.processTaskQueue.call(self);\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\t// No task is ready so update the status\n\t\t\tthis.updateDirtyStatus();\n\t\t\t// And trigger a timeout if there is a pending task\n\t\t\tif(task === true) {\n\t\t\t\tthis.triggerTimeout();\t\t\t\t\n\t\t\t}\n\t\t}\n\t} else {\n\t\tthis.updateDirtyStatus();\t\t\n\t}\n};\n\nSyncer.prototype.triggerTimeout = function(interval) {\n\tvar self = this;\n\tif(!this.taskTimerId) {\n\t\tthis.taskTimerId = setTimeout(function() {\n\t\t\tself.taskTimerId = null;\n\t\t\tself.processTaskQueue.call(self);\n\t\t},interval || self.taskTimerInterval);\n\t}\n};\n\n/*\nChoose the next sync task. We prioritise saves, then deletes, then loads from the server\n\nReturns either a task object, null if there's no upcoming tasks, or the boolean true if there are pending tasks that aren't yet due\n*/\nSyncer.prototype.chooseNextTask = function() {\n\tvar thresholdLastSaved = (new Date()) - this.throttleInterval,\n\t\thavePending = null;\n\t// First we look for tiddlers that have been modified locally and need saving back to the server\n\tvar titles = this.getSyncedTiddlers();\n\tfor(var index=0; index<titles.length; index++) {\n\t\tvar title = titles[index],\n\t\t\ttiddler = this.wiki.tiddlerExists(title) && this.wiki.getTiddler(title),\n\t\t\ttiddlerInfo = this.tiddlerInfo[title];\n\t\tif(tiddler) {\n\t\t\t// If the tiddler is not known on the server, or has been modified locally no more recently than the threshold then it needs to be saved to the server\n\t\t\tvar hasChanged = !tiddlerInfo || $tw.wiki.getChangeCount(title) > tiddlerInfo.changeCount,\n\t\t\t\tisReadyToSave = !tiddlerInfo || !tiddlerInfo.timestampLastSaved || tiddlerInfo.timestampLastSaved < thresholdLastSaved;\n\t\t\tif(hasChanged) {\n\t\t\t\tif(isReadyToSave) {\n\t\t\t\t\treturn new SaveTiddlerTask(this,title); \t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\thavePending = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Second, we check tiddlers that are known from the server but not currently in the store, and so need deleting on the server\n\ttitles = Object.keys(this.tiddlerInfo);\n\tfor(index=0; index<titles.length; index++) {\n\t\ttitle = titles[index];\n\t\ttiddlerInfo = this.tiddlerInfo[title];\n\t\ttiddler = this.wiki.tiddlerExists(title) && this.wiki.getTiddler(title);\n\t\tif(!tiddler) {\n\t\t\treturn new DeleteTiddlerTask(this,title);\n\t\t}\n\t}\n\t// Check for tiddlers that need loading\n\ttitle = Object.keys(this.titlesToBeLoaded)[0];\n\tif(title) {\n\t\tdelete this.titlesToBeLoaded[title];\n\t\treturn new LoadTiddlerTask(this,title);\n\t}\n\t// No tasks are ready\n\treturn havePending;\n};\n\nfunction SaveTiddlerTask(syncer,title) {\n\tthis.syncer = syncer;\n\tthis.title = title;\n\tthis.type = \"save\";\n}\n\nSaveTiddlerTask.prototype.run = function(callback) {\n\tvar self = this,\n\t\tchangeCount = this.syncer.wiki.getChangeCount(this.title),\n\t\ttiddler = this.syncer.wiki.tiddlerExists(this.title) && this.syncer.wiki.getTiddler(this.title);\n\tthis.syncer.logger.log(\"Dispatching 'save' task:\",this.title);\n\tif(tiddler) {\n\t\tthis.syncer.syncadaptor.saveTiddler(tiddler,function(err,adaptorInfo,revision) {\n\t\t\t// If there's an error, exit without changing any internal state\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\t// Adjust the info stored about this tiddler\n\t\t\tself.syncer.tiddlerInfo[self.title] = {\n\t\t\t\tchangeCount: changeCount,\n\t\t\t\tadaptorInfo: adaptorInfo,\n\t\t\t\trevision: revision,\n\t\t\t\ttimestampLastSaved: new Date()\n\t\t\t};\n\t\t\t// Invoke the callback\n\t\t\tcallback(null);\n\t\t});\n\t} else {\n\t\tthis.syncer.logger.log(\" Not Dispatching 'save' task:\",this.title,\"tiddler does not exist\");\n\t\t$tw.utils.nextTick(callback(null));\n\t}\n};\n\nfunction DeleteTiddlerTask(syncer,title) {\n\tthis.syncer = syncer;\n\tthis.title = title;\n\tthis.type = \"delete\";\n}\n\nDeleteTiddlerTask.prototype.run = function(callback) {\n\tvar self = this;\n\tthis.syncer.logger.log(\"Dispatching 'delete' task:\",this.title);\n\tthis.syncer.syncadaptor.deleteTiddler(this.title,function(err) {\n\t\t// If there's an error, exit without changing any internal state\n\t\tif(err) {\n\t\t\treturn callback(err);\n\t\t}\n\t\t// Remove the info stored about this tiddler\n\t\tdelete self.syncer.tiddlerInfo[self.title];\n\t\t// Invoke the callback\n\t\tcallback(null);\n\t},{\n\t\ttiddlerInfo: self.syncer.tiddlerInfo[this.title]\n\t});\n};\n\nfunction LoadTiddlerTask(syncer,title) {\n\tthis.syncer = syncer;\n\tthis.title = title;\n\tthis.type = \"load\";\n}\n\nLoadTiddlerTask.prototype.run = function(callback) {\n\tvar self = this;\n\tthis.syncer.logger.log(\"Dispatching 'load' task:\",this.title);\n\tthis.syncer.syncadaptor.loadTiddler(this.title,function(err,tiddlerFields) {\n\t\t// If there's an error, exit without changing any internal state\n\t\tif(err) {\n\t\t\treturn callback(err);\n\t\t}\n\t\t// Update the info stored about this tiddler\n\t\tif(tiddlerFields) {\n\t\t\tself.syncer.storeTiddler(tiddlerFields);\n\t\t}\n\t\t// Invoke the callback\n\t\tcallback(null);\n\t});\n};\n\nexports.Syncer = Syncer;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/tiddler.js": {
            "title": "$:/core/modules/tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/tiddler.js\ntype: application/javascript\nmodule-type: tiddlermethod\n\nExtension methods for the $tw.Tiddler object (constructor and methods required at boot time are in boot/boot.js)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.hasTag = function(tag) {\n\treturn this.fields.tags && this.fields.tags.indexOf(tag) !== -1;\n};\n\nexports.isPlugin = function() {\n\treturn this.fields.type === \"application/json\" && this.hasField(\"plugin-type\");\n};\n\nexports.isDraft = function() {\n\treturn this.hasField(\"draft.of\");\n};\n\nexports.getFieldString = function(field) {\n\tvar value = this.fields[field];\n\t// Check for a missing field\n\tif(value === undefined || value === null) {\n\t\treturn \"\";\n\t}\n\t// Parse the field with the associated module (if any)\n\tvar fieldModule = $tw.Tiddler.fieldModules[field];\n\tif(fieldModule && fieldModule.stringify) {\n\t\treturn fieldModule.stringify.call(this,value);\n\t} else {\n\t\treturn value.toString();\n\t}\n};\n\n/*\nGet the value of a field as a list\n*/\nexports.getFieldList = function(field) {\n\tvar value = this.fields[field];\n\t// Check for a missing field\n\tif(value === undefined || value === null) {\n\t\treturn [];\n\t}\n\treturn $tw.utils.parseStringArray(value);\n};\n\n/*\nGet all the fields as a hashmap of strings. Options:\n\texclude: an array of field names to exclude\n*/\nexports.getFieldStrings = function(options) {\n\toptions = options || {};\n\tvar exclude = options.exclude || [];\n\tvar fields = {};\n\tfor(var field in this.fields) {\n\t\tif($tw.utils.hop(this.fields,field)) {\n\t\t\tif(exclude.indexOf(field) === -1) {\n\t\t\t\tfields[field] = this.getFieldString(field);\n\t\t\t}\n\t\t}\n\t}\n\treturn fields;\n};\n\n/*\nGet all the fields as a name:value block. Options:\n\texclude: an array of field names to exclude\n*/\nexports.getFieldStringBlock = function(options) {\n\toptions = options || {};\n\tvar exclude = options.exclude || [],\n\t\tfields = Object.keys(this.fields).sort(),\n\t\tresult = [];\n\tfor(var t=0; t<fields.length; t++) {\n\t\tvar field = fields[t];\n\t\tif(exclude.indexOf(field) === -1) {\n\t\t\tresult.push(field + \": \" + this.getFieldString(field));\n\t\t}\n\t}\n\treturn result.join(\"\\n\");\n};\n\nexports.getFieldDay = function(field) {\n\tif(this.cache && this.cache.day && $tw.utils.hop(this.cache.day,field) ) {\n\t\treturn this.cache.day[field];\n\t}\n\tvar day = \"\";\n\tif(this.fields[field]) {\n\t\tday = (new Date($tw.utils.parseDate(this.fields[field]))).setHours(0,0,0,0);\n\t}\n\tthis.cache.day = this.cache.day || {};\n\tthis.cache.day[field] = day;\n\treturn day;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "tiddlermethod"
        },
        "$:/core/modules/upgraders/plugins.js": {
            "title": "$:/core/modules/upgraders/plugins.js",
            "text": "/*\\\ntitle: $:/core/modules/upgraders/plugins.js\ntype: application/javascript\nmodule-type: upgrader\n\nUpgrader module that checks that plugins are newer than any already installed version\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar UPGRADE_LIBRARY_TITLE = \"$:/UpgradeLibrary\";\n\nvar BLOCKED_PLUGINS = {\n\t\"$:/themes/tiddlywiki/stickytitles\": {\n\t\tversions: [\"*\"]\n\t},\n\t\"$:/plugins/tiddlywiki/fullscreen\": {\n\t\tversions: [\"*\"]\n\t}\n};\n\nexports.upgrade = function(wiki,titles,tiddlers) {\n\tvar self = this,\n\t\tmessages = {},\n\t\tupgradeLibrary,\n\t\tgetLibraryTiddler = function(title) {\n\t\t\tif(!upgradeLibrary) {\n\t\t\t\tupgradeLibrary = wiki.getTiddlerData(UPGRADE_LIBRARY_TITLE,{});\n\t\t\t\tupgradeLibrary.tiddlers = upgradeLibrary.tiddlers || {};\n\t\t\t}\n\t\t\treturn upgradeLibrary.tiddlers[title];\n\t\t};\n\n\t// Go through all the incoming tiddlers\n\t$tw.utils.each(titles,function(title) {\n\t\tvar incomingTiddler = tiddlers[title];\n\t\t// Check if we're dealing with a plugin\n\t\tif(incomingTiddler && incomingTiddler[\"plugin-type\"]) {\n\t\t\t// Check whether the plugin contains JS modules\n\t\t\tvar requiresReload = $tw.wiki.doesPluginInfoRequireReload(JSON.parse(incomingTiddler.text)) ? ($tw.wiki.getTiddlerText(\"$:/language/ControlPanel/Plugins/PluginWillRequireReload\") + \" \") : \"\";\n\t\t\tmessages[title] = requiresReload;\n\t\t\tif(incomingTiddler.version) {\n\t\t\t\t// Upgrade the incoming plugin if it is in the upgrade library\n\t\t\t\tvar libraryTiddler = getLibraryTiddler(title);\n\t\t\t\tif(libraryTiddler && libraryTiddler[\"plugin-type\"] && libraryTiddler.version) {\n\t\t\t\t\ttiddlers[title] = libraryTiddler;\n\t\t\t\t\tmessages[title] = requiresReload + $tw.language.getString(\"Import/Upgrader/Plugins/Upgraded\",{variables: {incoming: incomingTiddler.version, upgraded: libraryTiddler.version}});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Suppress the incoming plugin if it is older than the currently installed one\n\t\t\t\tvar existingTiddler = wiki.getTiddler(title);\n\t\t\t\tif(existingTiddler && existingTiddler.hasField(\"plugin-type\") && existingTiddler.hasField(\"version\")) {\n\t\t\t\t\t// Reject the incoming plugin by blanking all its fields\n\t\t\t\t\tif($tw.utils.checkVersions(existingTiddler.fields.version,incomingTiddler.version)) {\n\t\t\t\t\t\ttiddlers[title] = Object.create(null);\n\t\t\t\t\t\tmessages[title] = requiresReload + $tw.language.getString(\"Import/Upgrader/Plugins/Suppressed/Version\",{variables: {incoming: incomingTiddler.version, existing: existingTiddler.fields.version}});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Check whether the plugin is on the blocked list\n\t\t\tvar blockInfo = BLOCKED_PLUGINS[title];\n\t\t\tif(blockInfo) {\n\t\t\t\tif(blockInfo.versions.indexOf(\"*\") !== -1 || (incomingTiddler.version && blockInfo.versions.indexOf(incomingTiddler.version) !== -1)) {\n\t\t\t\t\ttiddlers[title] = Object.create(null);\n\t\t\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/Plugins/Suppressed/Incompatible\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\treturn messages;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "upgrader"
        },
        "$:/core/modules/upgraders/system.js": {
            "title": "$:/core/modules/upgraders/system.js",
            "text": "/*\\\ntitle: $:/core/modules/upgraders/system.js\ntype: application/javascript\nmodule-type: upgrader\n\nUpgrader module that suppresses certain system tiddlers that shouldn't be imported\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar DONT_IMPORT_LIST = [\"$:/StoryList\",\"$:/HistoryList\"],\n\tDONT_IMPORT_PREFIX_LIST = [\"$:/temp/\",\"$:/state/\",\"$:/Import\"],\n\tWARN_IMPORT_PREFIX_LIST = [\"$:/core/modules/\"];\n\nexports.upgrade = function(wiki,titles,tiddlers) {\n\tvar self = this,\n\t\tmessages = {},\n\t\tshowAlert = false;\n\t// Check for tiddlers on our list\n\t$tw.utils.each(titles,function(title) {\n\t\tif(DONT_IMPORT_LIST.indexOf(title) !== -1) {\n\t\t\ttiddlers[title] = Object.create(null);\n\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/System/Suppressed\");\n\t\t} else {\n\t\t\tfor(var t=0; t<DONT_IMPORT_PREFIX_LIST.length; t++) {\n\t\t\t\tvar prefix = DONT_IMPORT_PREFIX_LIST[t];\n\t\t\t\tif(title.substr(0,prefix.length) === prefix) {\n\t\t\t\t\ttiddlers[title] = Object.create(null);\n\t\t\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/State/Suppressed\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor(var t=0; t<WARN_IMPORT_PREFIX_LIST.length; t++) {\n\t\t\t\tvar prefix = WARN_IMPORT_PREFIX_LIST[t];\n\t\t\t\tif(title.substr(0,prefix.length) === prefix && wiki.isShadowTiddler(title)) {\n\t\t\t\t\tshowAlert = true;\n\t\t\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/System/Warning\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\tif(showAlert) {\n\t\tvar logger = new $tw.utils.Logger(\"import\");\n\t\tlogger.alert($tw.language.getString(\"Import/Upgrader/System/Alert\"));\n\t}\n\treturn messages;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "upgrader"
        },
        "$:/core/modules/upgraders/themetweaks.js": {
            "title": "$:/core/modules/upgraders/themetweaks.js",
            "text": "/*\\\ntitle: $:/core/modules/upgraders/themetweaks.js\ntype: application/javascript\nmodule-type: upgrader\n\nUpgrader module that handles the change in theme tweak storage introduced in 5.0.14-beta.\n\nPreviously, theme tweaks were stored in two data tiddlers:\n\n* $:/themes/tiddlywiki/vanilla/metrics\n* $:/themes/tiddlywiki/vanilla/settings\n\nNow, each tweak is stored in its own separate tiddler.\n\nThis upgrader copies any values from the old format to the new. The old data tiddlers are not deleted in case they have been used to store additional indexes.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar MAPPINGS = {\n\t\"$:/themes/tiddlywiki/vanilla/metrics\": {\n\t\t\"fontsize\": \"$:/themes/tiddlywiki/vanilla/metrics/fontsize\",\n\t\t\"lineheight\": \"$:/themes/tiddlywiki/vanilla/metrics/lineheight\",\n\t\t\"storyleft\": \"$:/themes/tiddlywiki/vanilla/metrics/storyleft\",\n\t\t\"storytop\": \"$:/themes/tiddlywiki/vanilla/metrics/storytop\",\n\t\t\"storyright\": \"$:/themes/tiddlywiki/vanilla/metrics/storyright\",\n\t\t\"storywidth\": \"$:/themes/tiddlywiki/vanilla/metrics/storywidth\",\n\t\t\"tiddlerwidth\": \"$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth\"\n\t},\n\t\"$:/themes/tiddlywiki/vanilla/settings\": {\n\t\t\"fontfamily\": \"$:/themes/tiddlywiki/vanilla/settings/fontfamily\"\n\t}\n};\n\nexports.upgrade = function(wiki,titles,tiddlers) {\n\tvar self = this,\n\t\tmessages = {};\n\t// Check for tiddlers on our list\n\t$tw.utils.each(titles,function(title) {\n\t\tvar mapping = MAPPINGS[title];\n\t\tif(mapping) {\n\t\t\tvar tiddler = new $tw.Tiddler(tiddlers[title]),\n\t\t\t\ttiddlerData = wiki.getTiddlerDataCached(tiddler,{});\n\t\t\tfor(var index in mapping) {\n\t\t\t\tvar mappedTitle = mapping[index];\n\t\t\t\tif(!tiddlers[mappedTitle] || tiddlers[mappedTitle].title !== mappedTitle) {\n\t\t\t\t\ttiddlers[mappedTitle] = {\n\t\t\t\t\t\ttitle: mappedTitle,\n\t\t\t\t\t\ttext: tiddlerData[index]\n\t\t\t\t\t};\n\t\t\t\t\tmessages[mappedTitle] = $tw.language.getString(\"Import/Upgrader/ThemeTweaks/Created\",{variables: {\n\t\t\t\t\t\tfrom: title + \"##\" + index\n\t\t\t\t\t}});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\treturn messages;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "upgrader"
        },
        "$:/core/modules/utils/base64-utf8/base64-utf8.module.js": {
            "text": "(function(){// From https://gist.github.com/Nijikokun/5192472\n//\n// UTF8 Module\n//\n// Cleaner and modularized utf-8 encoding and decoding library for javascript.\n//\n// copyright: MIT\n// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com\n!function(r,e,o,t){void 0!==o.module&&o.module.exports?o.module.exports=e.apply(o):void 0!==o.define&&\"function\"===o.define&&o.define.amd?define(\"utf8\",[],e):o.utf8=e.apply(o)}(0,function(){return{encode:function(r){if(\"string\"!=typeof r)return r;r=r.replace(/\\r\\n/g,\"\\n\");for(var e,o=\"\",t=0;t<r.length;t++)(e=r.charCodeAt(t))<128?o+=String.fromCharCode(e):e>127&&e<2048?(o+=String.fromCharCode(e>>6|192),o+=String.fromCharCode(63&e|128)):(o+=String.fromCharCode(e>>12|224),o+=String.fromCharCode(e>>6&63|128),o+=String.fromCharCode(63&e|128));return o},decode:function(r){if(\"string\"!=typeof r)return r;for(var e=\"\",o=0,t=0;o<r.length;)(t=r.charCodeAt(o))<128?(e+=String.fromCharCode(t),o++):t>191&&t<224?(e+=String.fromCharCode((31&t)<<6|63&r.charCodeAt(o+1)),o+=2):(e+=String.fromCharCode((15&t)<<12|(63&r.charCodeAt(o+1))<<6|63&r.charCodeAt(o+2)),o+=3);return e}}},this),function(r,e,o,t){if(void 0!==o.module&&o.module.exports){if(t&&o.require)for(var n=0;n<t.length;n++)o[t[n]]=o.require(t[n]);o.module.exports=e.apply(o)}else void 0!==o.define&&\"function\"===o.define&&o.define.amd?define(\"base64\",t||[],e):o.base64=e.apply(o)}(0,function(r){var e=r||this.utf8,o=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";return{encode:function(r){if(void 0===e)throw{error:\"MissingMethod\",message:\"UTF8 Module is missing.\"};if(\"string\"!=typeof r)return r;r=e.encode(r);for(var t,n,i,d,f,a,h,c=\"\",u=0;u<r.length;)d=(t=r.charCodeAt(u++))>>2,f=(3&t)<<4|(n=r.charCodeAt(u++))>>4,a=(15&n)<<2|(i=r.charCodeAt(u++))>>6,h=63&i,isNaN(n)?a=h=64:isNaN(i)&&(h=64),c+=o.charAt(d)+o.charAt(f)+o.charAt(a)+o.charAt(h);return c},decode:function(r){if(void 0===e)throw{error:\"MissingMethod\",message:\"UTF8 Module is missing.\"};if(\"string\"!=typeof r)return r;r=r.replace(/[^A-Za-z0-9\\+\\/\\=]/g,\"\");for(var t,n,i,d,f,a,h=\"\",c=0;c<r.length;)t=o.indexOf(r.charAt(c++))<<2|(d=o.indexOf(r.charAt(c++)))>>4,n=(15&d)<<4|(f=o.indexOf(r.charAt(c++)))>>2,i=(3&f)<<6|(a=o.indexOf(r.charAt(c++))),h+=String.fromCharCode(t),64!=f&&(h+=String.fromCharCode(n)),64!=a&&(h+=String.fromCharCode(i));return e.decode(h)}}},this,[\"utf8\"]);}).call(exports);",
            "type": "application/javascript",
            "title": "$:/core/modules/utils/base64-utf8/base64-utf8.module.js",
            "module-type": "library"
        },
        "$:/core/modules/utils/crypto.js": {
            "title": "$:/core/modules/utils/crypto.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/crypto.js\ntype: application/javascript\nmodule-type: utils\n\nUtility functions related to crypto.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nLook for an encrypted store area in the text of a TiddlyWiki file\n*/\nexports.extractEncryptedStoreArea = function(text) {\n\tvar encryptedStoreAreaStartMarker = \"<pre id=\\\"encryptedStoreArea\\\" type=\\\"text/plain\\\" style=\\\"display:none;\\\">\",\n\t\tencryptedStoreAreaStart = text.indexOf(encryptedStoreAreaStartMarker);\n\tif(encryptedStoreAreaStart !== -1) {\n\t\tvar encryptedStoreAreaEnd = text.indexOf(\"</pre>\",encryptedStoreAreaStart);\n\t\tif(encryptedStoreAreaEnd !== -1) {\n\t\t\treturn $tw.utils.htmlDecode(text.substring(encryptedStoreAreaStart + encryptedStoreAreaStartMarker.length,encryptedStoreAreaEnd-1));\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nAttempt to extract the tiddlers from an encrypted store area using the current password. If the password is not provided then the password in the password store will be used\n*/\nexports.decryptStoreArea = function(encryptedStoreArea,password) {\n\tvar decryptedText = $tw.crypto.decrypt(encryptedStoreArea,password);\n\tif(decryptedText) {\n\t\tvar json = JSON.parse(decryptedText),\n\t\t\ttiddlers = [];\n\t\tfor(var title in json) {\n\t\t\tif(title !== \"$:/isEncrypted\") {\n\t\t\t\ttiddlers.push(json[title]);\n\t\t\t}\n\t\t}\n\t\treturn tiddlers;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n\n/*\nAttempt to extract the tiddlers from an encrypted store area using the current password. If that fails, the user is prompted for a password.\nencryptedStoreArea: text of the TiddlyWiki encrypted store area\ncallback: function(tiddlers) called with the array of decrypted tiddlers\n\nThe following configuration settings are supported:\n\n$tw.config.usePasswordVault: causes any password entered by the user to also be put into the system password vault\n*/\nexports.decryptStoreAreaInteractive = function(encryptedStoreArea,callback,options) {\n\t// Try to decrypt with the current password\n\tvar tiddlers = $tw.utils.decryptStoreArea(encryptedStoreArea);\n\tif(tiddlers) {\n\t\tcallback(tiddlers);\n\t} else {\n\t\t// Prompt for a new password and keep trying\n\t\t$tw.passwordPrompt.createPrompt({\n\t\t\tserviceName: \"Enter a password to decrypt the imported TiddlyWiki\",\n\t\t\tnoUserName: true,\n\t\t\tcanCancel: true,\n\t\t\tsubmitText: \"Decrypt\",\n\t\t\tcallback: function(data) {\n\t\t\t\t// Exit if the user cancelled\n\t\t\t\tif(!data) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t// Attempt to decrypt the tiddlers\n\t\t\t\tvar tiddlers = $tw.utils.decryptStoreArea(encryptedStoreArea,data.password);\n\t\t\t\tif(tiddlers) {\n\t\t\t\t\tif($tw.config.usePasswordVault) {\n\t\t\t\t\t\t$tw.crypto.setPassword(data.password);\n\t\t\t\t\t}\n\t\t\t\t\tcallback(tiddlers);\n\t\t\t\t\t// Exit and remove the password prompt\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\t// We didn't decrypt everything, so continue to prompt for password\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/csv.js": {
            "title": "$:/core/modules/utils/csv.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/csv.js\ntype: application/javascript\nmodule-type: utils\n\nA barebones CSV parser\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nParse a CSV string with a header row and return an array of hashmaps.\n*/\nexports.parseCsvStringWithHeader = function(text,options) {\n\toptions = options || {};\n\tvar separator = options.separator || \",\",\n\t\trows = text.split(/\\r?\\n/mg).map(function(row) {\n\t\t\treturn $tw.utils.trim(row);\n\t\t}).filter(function(row) {\n\t\t\treturn row !== \"\";\n\t\t});\n\tif(rows.length < 1) {\n\t\treturn \"Missing header row\";\n\t}\n\tvar headings = rows[0].split(separator),\n\t\tresults = [];\n\tfor(var row=1; row<rows.length; row++) {\n\t\tvar columns = rows[row].split(separator),\n\t\t\tcolumnResult = Object.create(null);\n\t\tif(columns.length !== headings.length) {\n\t\t\treturn \"Malformed CSV row '\" + rows[row] + \"'\";\n\t\t}\n\t\tfor(var column=0; column<columns.length; column++) {\n\t\t\tvar columnName = headings[column];\n\t\t\tcolumnResult[columnName] = $tw.utils.trim(columns[column] || \"\");\n\t\t}\n\t\tresults.push(columnResult);\t\t\t\n\t}\n\treturn results;\n}\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/diff-match-patch/diff_match_patch.js": {
            "text": "(function(){function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=.5;this.Patch_Margin=4;this.Match_MaxBits=32}var DIFF_DELETE=-1,DIFF_INSERT=1,DIFF_EQUAL=0;\ndiff_match_patch.prototype.diff_main=function(a,b,c,d){\"undefined\"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error(\"Null input. (diff_main)\");if(a==b)return a?[[DIFF_EQUAL,a]]:[];\"undefined\"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);f=this.diff_commonSuffix(a,b);var g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,b.length-f);a=this.diff_compute_(a,\nb,e,d);c&&a.unshift([DIFF_EQUAL,c]);g&&a.push([DIFF_EQUAL,g]);this.diff_cleanupMerge(a);return a};\ndiff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[DIFF_INSERT,b]];if(!b)return[[DIFF_DELETE,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[[DIFF_INSERT,e.substring(0,g)],[DIFF_EQUAL,f],[DIFF_INSERT,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=DIFF_DELETE),c):1==f.length?[[DIFF_DELETE,a],[DIFF_INSERT,b]]:(e=this.diff_halfMatch_(a,b))?(b=e[1],f=e[3],a=e[4],e=this.diff_main(e[0],e[2],c,d),c=this.diff_main(b,f,c,d),e.concat([[DIFF_EQUAL,\na]],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,b,d):this.diff_bisect_(a,b,d)};\ndiff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b);a=d.chars1;b=d.chars2;d=d.lineArray;a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push([DIFF_EQUAL,\"\"]);for(var e=d=b=0,f=\"\",g=\"\";b<a.length;){switch(a[b][0]){case DIFF_INSERT:e++;g+=a[b][1];break;case DIFF_DELETE:d++;f+=a[b][1];break;case DIFF_EQUAL:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,0,d[e]);b+=\nd.length}d=e=0;g=f=\"\"}b++}a.pop();return a};\ndiff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=2*f,h=Array(g),l=Array(g),k=0;k<g;k++)h[k]=-1,l[k]=-1;h[f+1]=0;l[f+1]=0;k=d-e;for(var m=0!=k%2,p=0,x=0,w=0,q=0,t=0;t<f&&!((new Date).getTime()>c);t++){for(var v=-t+p;v<=t-x;v+=2){var n=f+v;var r=v==-t||v!=t&&h[n-1]<h[n+1]?h[n+1]:h[n-1]+1;for(var y=r-v;r<d&&y<e&&a.charAt(r)==b.charAt(y);)r++,y++;h[n]=r;if(r>d)x+=2;else if(y>e)p+=2;else if(m&&(n=f+k-v,0<=n&&n<g&&-1!=l[n])){var u=d-l[n];if(r>=\nu)return this.diff_bisectSplit_(a,b,r,y,c)}}for(v=-t+w;v<=t-q;v+=2){n=f+v;u=v==-t||v!=t&&l[n-1]<l[n+1]?l[n+1]:l[n-1]+1;for(r=u-v;u<d&&r<e&&a.charAt(d-u-1)==b.charAt(e-r-1);)u++,r++;l[n]=u;if(u>d)q+=2;else if(r>e)w+=2;else if(!m&&(n=f+k-v,0<=n&&n<g&&-1!=h[n]&&(r=h[n],y=f+r-n,u=d-u,r>=u)))return this.diff_bisectSplit_(a,b,r,y,c)}}return[[DIFF_DELETE,a],[DIFF_INSERT,b]]};\ndiff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)};\ndiff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b=\"\",c=0,f=-1,g=d.length;f<a.length-1;){f=a.indexOf(\"\\n\",c);-1==f&&(f=a.length-1);var h=a.substring(c,f+1);c=f+1;(e.hasOwnProperty?e.hasOwnProperty(h):void 0!==e[h])?b+=String.fromCharCode(e[h]):(b+=String.fromCharCode(g),e[h]=g,d[g++]=h)}return b}var d=[],e={};d[0]=\"\";var f=c(a),g=c(b);return{chars1:f,chars2:g,lineArray:d}};\ndiff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join(\"\")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\ndiff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\ndiff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;d=0;for(var e=1;;){var f=a.substring(c-e);f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};\ndiff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g=\"\",h,k,l,m;-1!=(e=b.indexOf(d,e+1));){var p=f.diff_commonPrefix(a.substring(c),b.substring(e)),u=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<u+p&&(g=b.substring(e-u,e)+b.substring(e,e+p),h=a.substring(0,c-u),k=a.substring(c+p),l=b.substring(0,e-u),m=b.substring(e+p))}return 2*g.length>=a.length?[h,k,l,m,g]:null}if(0>=this.Diff_Timeout)return null;\nvar d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4));d=c(d,e,Math.ceil(d.length/2));if(g||d)g=d?g?g[4].length>d[4].length?g:d:d:g;else return null;if(a.length>b.length){d=g[0];e=g[1];var h=g[2];var l=g[3]}else h=g[0],l=g[1],d=g[2],e=g[3];return[d,e,h,l,g[4]]};\ndiff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,l=0,k=0;f<a.length;)a[f][0]==DIFF_EQUAL?(c[d++]=f,g=l,h=k,k=l=0,e=a[f][1]):(a[f][0]==DIFF_INSERT?l+=a[f][1].length:k+=a[f][1].length,e&&e.length<=Math.max(g,h)&&e.length<=Math.max(l,k)&&(a.splice(c[d-1],0,[DIFF_DELETE,e]),a[c[d-1]+1][0]=DIFF_INSERT,d--,d--,f=0<d?c[d-1]:-1,k=l=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<a.length;){if(a[f-1][0]==\nDIFF_DELETE&&a[f][0]==DIFF_INSERT){b=a[f-1][1];c=a[f][1];d=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[DIFF_EQUAL,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[DIFF_EQUAL,b.substring(0,e)]),a[f-1][0]=DIFF_INSERT,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=DIFF_DELETE,a[f+1][1]=b.substring(e),f++;f++}f++}};\ndiff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_);c=g&&c.match(diff_match_patch.linebreakRegex_);d=h&&d.match(diff_match_patch.linebreakRegex_);var k=c&&a.match(diff_match_patch.blanklineEndRegex_),l=d&&b.match(diff_match_patch.blanklineStartRegex_);\nreturn k||l?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(a[c-1][0]==DIFF_EQUAL&&a[c+1][0]==DIFF_EQUAL){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g){var h=e.substring(e.length-g);d=d.substring(0,d.length-g);e=h+e.substring(0,e.length-g);f=h+f}g=d;h=e;for(var l=f,k=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){d+=e.charAt(0);e=e.substring(1)+f.charAt(0);f=f.substring(1);var m=b(d,e)+b(e,f);m>=k&&(k=m,g=d,h=e,l=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-\n1,1),c--),a[c][1]=h,l?a[c+1][1]=l:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\\s/;diff_match_patch.linebreakRegex_=/[\\r\\n]/;diff_match_patch.blanklineEndRegex_=/\\n\\r?\\n$/;diff_match_patch.blanklineStartRegex_=/^\\r?\\n\\r?\\n/;\ndiff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,l=!1,k=!1;f<a.length;)a[f][0]==DIFF_EQUAL?(a[f][1].length<this.Diff_EditCost&&(l||k)?(c[d++]=f,g=l,h=k,e=a[f][1]):(d=0,e=null),l=k=!1):(a[f][0]==DIFF_DELETE?k=!0:l=!0,e&&(g&&h&&l&&k||e.length<this.Diff_EditCost/2&&3==g+h+l+k)&&(a.splice(c[d-1],0,[DIFF_DELETE,e]),a[c[d-1]+1][0]=DIFF_INSERT,d--,e=null,g&&h?(l=k=!0,d=0):(d--,f=0<d?c[d-1]:-1,l=k=!1),b=!0)),f++;b&&this.diff_cleanupMerge(a)};\ndiff_match_patch.prototype.diff_cleanupMerge=function(a){a.push([DIFF_EQUAL,\"\"]);for(var b=0,c=0,d=0,e=\"\",f=\"\",g;b<a.length;)switch(a[b][0]){case DIFF_INSERT:d++;f+=a[b][1];b++;break;case DIFF_DELETE:c++;e+=a[b][1];b++;break;case DIFF_EQUAL:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&a[b-c-d-1][0]==DIFF_EQUAL?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,[DIFF_EQUAL,f.substring(0,g)]),b++),f=f.substring(g),e=e.substring(g)),g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-\ng)+a[b][1],f=f.substring(0,f.length-g),e=e.substring(0,e.length-g))),0===c?a.splice(b-d,c+d,[DIFF_INSERT,f]):0===d?a.splice(b-c,c+d,[DIFF_DELETE,e]):a.splice(b-c-d,c+d,[DIFF_DELETE,e],[DIFF_INSERT,f]),b=b-c-d+(c?1:0)+(d?1:0)+1):0!==b&&a[b-1][0]==DIFF_EQUAL?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=\"\"}\"\"===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)a[b-1][0]==DIFF_EQUAL&&a[b+1][0]==DIFF_EQUAL&&(a[b][1].substring(a[b][1].length-a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,\na[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,a[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};\ndiff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){a[g][0]!==DIFF_INSERT&&(c+=a[g][1].length);a[g][0]!==DIFF_DELETE&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&a[g][0]===DIFF_DELETE?f:f+(b-e)};\ndiff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\\n/g,g=0;g<a.length;g++){var h=a[g][0],l=a[g][1].replace(c,\"&amp;\").replace(d,\"&lt;\").replace(e,\"&gt;\").replace(f,\"&para;<br>\");switch(h){case DIFF_INSERT:b[g]='<ins style=\"background:#e6ffe6;\">'+l+\"</ins>\";break;case DIFF_DELETE:b[g]='<del style=\"background:#ffe6e6;\">'+l+\"</del>\";break;case DIFF_EQUAL:b[g]=\"<span>\"+l+\"</span>\"}}return b.join(\"\")};\ndiff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==DIFF_INSERT&&(b[c]=a[c][1]);return b.join(\"\")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==DIFF_DELETE&&(b[c]=a[c][1]);return b.join(\"\")};\ndiff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][1];switch(a[e][0]){case DIFF_INSERT:c+=f.length;break;case DIFF_DELETE:d+=f.length;break;case DIFF_EQUAL:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};\ndiff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case DIFF_INSERT:b[c]=\"+\"+encodeURI(a[c][1]);break;case DIFF_DELETE:b[c]=\"-\"+a[c][1].length;break;case DIFF_EQUAL:b[c]=\"=\"+a[c][1].length}return b.join(\"\\t\").replace(/%20/g,\" \")};\ndiff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case \"+\":try{c[d++]=[DIFF_INSERT,decodeURI(h)]}catch(k){throw Error(\"Illegal escape in diff_fromDelta: \"+h);}break;case \"-\":case \"=\":var l=parseInt(h,10);if(isNaN(l)||0>l)throw Error(\"Invalid number in diff_fromDelta: \"+h);h=a.substring(e,e+=l);\"=\"==f[g].charAt(0)?c[d++]=[DIFF_EQUAL,h]:c[d++]=[DIFF_DELETE,h];break;default:if(f[g])throw Error(\"Invalid diff operation in diff_fromDelta: \"+\nf[g]);}}if(e!=a.length)throw Error(\"Delta length (\"+e+\") does not equal source text length (\"+a.length+\").\");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error(\"Null input. (match_main)\");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};\ndiff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return f.Match_Distance?e+g/f.Match_Distance:g?1:e}if(b.length>this.Match_MaxBits)throw Error(\"Pattern too long for this browser.\");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));var l=1<<b.length-1;h=-1;for(var k,m,p=b.length+a.length,x,w=0;w<b.length;w++){k=0;for(m=p;k<m;)d(w,\nc+m)<=g?k=m:p=m,m=Math.floor((p-k)/2+k);p=m;k=Math.max(1,c-m+1);var q=Math.min(c+m,a.length)+b.length;m=Array(q+2);for(m[q+1]=(1<<w)-1;q>=k;q--){var t=e[a.charAt(q-1)];m[q]=0===w?(m[q+1]<<1|1)&t:(m[q+1]<<1|1)&t|(x[q+1]|x[q])<<1|1|x[q+1];if(m[q]&l&&(t=d(w,q-1),t<=g))if(g=t,h=q-1,h>c)k=Math.max(1,2*c-h);else break}if(d(w+1,c)>g)break;x=m}return h};\ndiff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};\ndiff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift([DIFF_EQUAL,c]);(d=b.substring(a.start2+a.length1,a.start2+a.length1+d))&&a.diffs.push([DIFF_EQUAL,d]);a.start1-=c.length;a.start2-=\nc.length;a.length1+=c.length+d.length;a.length2+=c.length+d.length}};\ndiff_match_patch.prototype.patch_make=function(a,b,c){if(\"string\"==typeof a&&\"string\"==typeof b&&\"undefined\"==typeof c){var d=a;b=this.diff_main(d,b,!0);2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b))}else if(a&&\"object\"==typeof a&&\"undefined\"==typeof b&&\"undefined\"==typeof c)b=a,d=this.diff_text1(b);else if(\"string\"==typeof a&&b&&\"object\"==typeof b&&\"undefined\"==typeof c)d=a;else if(\"string\"==typeof a&&\"string\"==typeof b&&c&&\"object\"==typeof c)d=a,b=c;else throw Error(\"Unknown call format to patch_make.\");\nif(0===b.length)return[];c=[];a=new diff_match_patch.patch_obj;for(var e=0,f=0,g=0,h=d,l=0;l<b.length;l++){var k=b[l][0],m=b[l][1];e||k===DIFF_EQUAL||(a.start1=f,a.start2=g);switch(k){case DIFF_INSERT:a.diffs[e++]=b[l];a.length2+=m.length;d=d.substring(0,g)+m+d.substring(g);break;case DIFF_DELETE:a.length1+=m.length;a.diffs[e++]=b[l];d=d.substring(0,g)+d.substring(g+m.length);break;case DIFF_EQUAL:m.length<=2*this.Patch_Margin&&e&&b.length!=l+1?(a.diffs[e++]=b[l],a.length1+=m.length,a.length2+=m.length):\nm.length>=2*this.Patch_Margin&&e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}k!==DIFF_INSERT&&(f+=m.length);k!==DIFF_DELETE&&(g+=m.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};\ndiff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=d.diffs[f].slice();e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};\ndiff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];a=this.patch_deepCopy(a);var c=this.patch_addPadding(a);b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),l=-1;if(h.length>this.Match_MaxBits){var k=this.match_main(b,h.substring(0,this.Match_MaxBits),g);-1!=k&&(l=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==l||k>=l)&&(k=-1)}else k=this.match_main(b,h,\ng);if(-1==k)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=k-g,g=-1==l?b.substring(k,k+h.length):b.substring(k,l+this.Match_MaxBits),h==g)b=b.substring(0,k)+this.diff_text2(a[f].diffs)+b.substring(k+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);h=0;var m;for(l=0;l<a[f].diffs.length;l++){var p=a[f].diffs[l];p[0]!==DIFF_EQUAL&&(m=this.diff_xIndex(g,h));p[0]===\nDIFF_INSERT?b=b.substring(0,k+m)+p[1]+b.substring(k+m):p[0]===DIFF_DELETE&&(b=b.substring(0,k+m)+b.substring(k+this.diff_xIndex(g,h+p[1].length)));p[0]!==DIFF_DELETE&&(h+=p[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};\ndiff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c=\"\",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;d=a[0];var e=d.diffs;if(0==e.length||e[0][0]!=DIFF_EQUAL)e.unshift([DIFF_EQUAL,c]),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||e[e.length-\n1][0]!=DIFF_EQUAL?(e.push([DIFF_EQUAL,c]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};\ndiff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g=\"\";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,l=!0;h.start1=e-g.length;h.start2=f-g.length;\"\"!==g&&(h.length1=h.length2=g.length,h.diffs.push([DIFF_EQUAL,g]));for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){g=d.diffs[0][0];var k=d.diffs[0][1];g===DIFF_INSERT?(h.length2+=k.length,f+=k.length,h.diffs.push(d.diffs.shift()),\nl=!1):g===DIFF_DELETE&&1==h.diffs.length&&h.diffs[0][0]==DIFF_EQUAL&&k.length>2*b?(h.length1+=k.length,e+=k.length,l=!1,h.diffs.push([g,k]),d.diffs.shift()):(k=k.substring(0,b-h.length1-this.Patch_Margin),h.length1+=k.length,e+=k.length,g===DIFF_EQUAL?(h.length2+=k.length,f+=k.length):l=!1,h.diffs.push([g,k]),k==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(k.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);k=this.diff_text1(d.diffs).substring(0,\nthis.Patch_Margin);\"\"!==k&&(h.length1+=k.length,h.length2+=k.length,0!==h.diffs.length&&h.diffs[h.diffs.length-1][0]===DIFF_EQUAL?h.diffs[h.diffs.length-1][1]+=k:h.diffs.push([DIFF_EQUAL,k]));l||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join(\"\")};\ndiff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;a=a.split(\"\\n\");for(var c=0,d=/^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error(\"Invalid patch string: \"+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);\"\"===e[2]?(f.start1--,f.length1=1):\"0\"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);\"\"===e[4]?(f.start2--,f.length2=1):\"0\"==e[4]?f.length2=0:(f.start2--,f.length2=\nparseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error(\"Illegal escape in patch_fromText: \"+g);}if(\"-\"==e)f.diffs.push([DIFF_DELETE,g]);else if(\"+\"==e)f.diffs.push([DIFF_INSERT,g]);else if(\" \"==e)f.diffs.push([DIFF_EQUAL,g]);else if(\"@\"==e)break;else if(\"\"!==e)throw Error('Invalid patch mode \"'+e+'\" in: '+g);c++}}return b};diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};\ndiff_match_patch.patch_obj.prototype.toString=function(){for(var a=[\"@@ -\"+(0===this.length1?this.start1+\",0\":1==this.length1?this.start1+1:this.start1+1+\",\"+this.length1)+\" +\"+(0===this.length2?this.start2+\",0\":1==this.length2?this.start2+1:this.start2+1+\",\"+this.length2)+\" @@\\n\"],b,c=0;c<this.diffs.length;c++){switch(this.diffs[c][0]){case DIFF_INSERT:b=\"+\";break;case DIFF_DELETE:b=\"-\";break;case DIFF_EQUAL:b=\" \"}a[c+1]=b+encodeURI(this.diffs[c][1])+\"\\n\"}return a.join(\"\").replace(/%20/g,\" \")};\nthis.diff_match_patch=diff_match_patch;this.DIFF_DELETE=DIFF_DELETE;this.DIFF_INSERT=DIFF_INSERT;this.DIFF_EQUAL=DIFF_EQUAL;\n}).call(exports);",
            "type": "application/javascript",
            "title": "$:/core/modules/utils/diff-match-patch/diff_match_patch.js",
            "module-type": "library"
        },
        "$:/core/modules/utils/dom/animations/slide.js": {
            "title": "$:/core/modules/utils/dom/animations/slide.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/animations/slide.js\ntype: application/javascript\nmodule-type: animation\n\nA simple slide animation that varies the height of the element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nfunction slideOpen(domNode,options) {\n\toptions = options || {};\n\tvar duration = options.duration || $tw.utils.getAnimationDuration();\n\t// Get the current height of the domNode\n\tvar computedStyle = window.getComputedStyle(domNode),\n\t\tcurrMarginBottom = parseInt(computedStyle.marginBottom,10),\n\t\tcurrMarginTop = parseInt(computedStyle.marginTop,10),\n\t\tcurrPaddingBottom = parseInt(computedStyle.paddingBottom,10),\n\t\tcurrPaddingTop = parseInt(computedStyle.paddingTop,10),\n\t\tcurrHeight = domNode.offsetHeight;\n\t// Reset the margin once the transition is over\n\tsetTimeout(function() {\n\t\t$tw.utils.setStyle(domNode,[\n\t\t\t{transition: \"none\"},\n\t\t\t{marginBottom: \"\"},\n\t\t\t{marginTop: \"\"},\n\t\t\t{paddingBottom: \"\"},\n\t\t\t{paddingTop: \"\"},\n\t\t\t{height: \"auto\"},\n\t\t\t{opacity: \"\"}\n\t\t]);\n\t\tif(options.callback) {\n\t\t\toptions.callback();\n\t\t}\n\t},duration);\n\t// Set up the initial position of the element\n\t$tw.utils.setStyle(domNode,[\n\t\t{transition: \"none\"},\n\t\t{marginTop: \"0px\"},\n\t\t{marginBottom: \"0px\"},\n\t\t{paddingTop: \"0px\"},\n\t\t{paddingBottom: \"0px\"},\n\t\t{height: \"0px\"},\n\t\t{opacity: \"0\"}\n\t]);\n\t$tw.utils.forceLayout(domNode);\n\t// Transition to the final position\n\t$tw.utils.setStyle(domNode,[\n\t\t{transition: \"margin-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"margin-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"height \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{marginBottom: currMarginBottom + \"px\"},\n\t\t{marginTop: currMarginTop + \"px\"},\n\t\t{paddingBottom: currPaddingBottom + \"px\"},\n\t\t{paddingTop: currPaddingTop + \"px\"},\n\t\t{height: currHeight + \"px\"},\n\t\t{opacity: \"1\"}\n\t]);\n}\n\nfunction slideClosed(domNode,options) {\n\toptions = options || {};\n\tvar duration = options.duration || $tw.utils.getAnimationDuration(),\n\t\tcurrHeight = domNode.offsetHeight;\n\t// Clear the properties we've set when the animation is over\n\tsetTimeout(function() {\n\t\t$tw.utils.setStyle(domNode,[\n\t\t\t{transition: \"none\"},\n\t\t\t{marginBottom: \"\"},\n\t\t\t{marginTop: \"\"},\n\t\t\t{paddingBottom: \"\"},\n\t\t\t{paddingTop: \"\"},\n\t\t\t{height: \"auto\"},\n\t\t\t{opacity: \"\"}\n\t\t]);\n\t\tif(options.callback) {\n\t\t\toptions.callback();\n\t\t}\n\t},duration);\n\t// Set up the initial position of the element\n\t$tw.utils.setStyle(domNode,[\n\t\t{height: currHeight + \"px\"},\n\t\t{opacity: \"1\"}\n\t]);\n\t$tw.utils.forceLayout(domNode);\n\t// Transition to the final position\n\t$tw.utils.setStyle(domNode,[\n\t\t{transition: \"margin-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"margin-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"height \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{marginTop: \"0px\"},\n\t\t{marginBottom: \"0px\"},\n\t\t{paddingTop: \"0px\"},\n\t\t{paddingBottom: \"0px\"},\n\t\t{height: \"0px\"},\n\t\t{opacity: \"0\"}\n\t]);\n}\n\nexports.slide = {\n\topen: slideOpen,\n\tclose: slideClosed\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "animation"
        },
        "$:/core/modules/utils/dom/animator.js": {
            "title": "$:/core/modules/utils/dom/animator.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/animator.js\ntype: application/javascript\nmodule-type: utils\n\nOrchestrates animations and transitions\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nfunction Animator() {\n\t// Get the registered animation modules\n\tthis.animations = {};\n\t$tw.modules.applyMethods(\"animation\",this.animations);\n}\n\nAnimator.prototype.perform = function(type,domNode,options) {\n\toptions = options || {};\n\t// Find an animation that can handle this type\n\tvar chosenAnimation;\n\t$tw.utils.each(this.animations,function(animation,name) {\n\t\tif($tw.utils.hop(animation,type)) {\n\t\t\tchosenAnimation = animation[type];\n\t\t}\n\t});\n\tif(!chosenAnimation) {\n\t\tchosenAnimation = function(domNode,options) {\n\t\t\tif(options.callback) {\n\t\t\t\toptions.callback();\n\t\t\t}\n\t\t};\n\t}\n\t// Call the animation\n\tchosenAnimation(domNode,options);\n};\n\nexports.Animator = Animator;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/browser.js": {
            "title": "$:/core/modules/utils/dom/browser.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/browser.js\ntype: application/javascript\nmodule-type: utils\n\nBrowser feature detection\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSet style properties of an element\n\telement: dom node\n\tstyles: ordered array of {name: value} pairs\n*/\nexports.setStyle = function(element,styles) {\n\tif(element.nodeType === 1) { // Element.ELEMENT_NODE\n\t\tfor(var t=0; t<styles.length; t++) {\n\t\t\tfor(var styleName in styles[t]) {\n\t\t\t\telement.style[$tw.utils.convertStyleNameToPropertyName(styleName)] = styles[t][styleName];\n\t\t\t}\n\t\t}\n\t}\n};\n\n/*\nConverts a standard CSS property name into the local browser-specific equivalent. For example:\n\t\"background-color\" --> \"backgroundColor\"\n\t\"transition\" --> \"webkitTransition\"\n*/\n\nvar styleNameCache = {}; // We'll cache the style name conversions\n\nexports.convertStyleNameToPropertyName = function(styleName) {\n\t// Return from the cache if we can\n\tif(styleNameCache[styleName]) {\n\t\treturn styleNameCache[styleName];\n\t}\n\t// Convert it by first removing any hyphens\n\tvar propertyName = $tw.utils.unHyphenateCss(styleName);\n\t// Then check if it needs a prefix\n\tif($tw.browser && document.body.style[propertyName] === undefined) {\n\t\tvar prefixes = [\"O\",\"MS\",\"Moz\",\"webkit\"];\n\t\tfor(var t=0; t<prefixes.length; t++) {\n\t\t\tvar prefixedName = prefixes[t] + propertyName.substr(0,1).toUpperCase() + propertyName.substr(1);\n\t\t\tif(document.body.style[prefixedName] !== undefined) {\n\t\t\t\tpropertyName = prefixedName;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t// Put it in the cache too\n\tstyleNameCache[styleName] = propertyName;\n\treturn propertyName;\n};\n\n/*\nConverts a JS format CSS property name back into the dashed form used in CSS declarations. For example:\n\t\"backgroundColor\" --> \"background-color\"\n\t\"webkitTransform\" --> \"-webkit-transform\"\n*/\nexports.convertPropertyNameToStyleName = function(propertyName) {\n\t// Rehyphenate the name\n\tvar styleName = $tw.utils.hyphenateCss(propertyName);\n\t// If there's a webkit prefix, add a dash (other browsers have uppercase prefixes, and so get the dash automatically)\n\tif(styleName.indexOf(\"webkit\") === 0) {\n\t\tstyleName = \"-\" + styleName;\n\t} else if(styleName.indexOf(\"-m-s\") === 0) {\n\t\tstyleName = \"-ms\" + styleName.substr(4);\n\t}\n\treturn styleName;\n};\n\n/*\nRound trip a stylename to a property name and back again. For example:\n\t\"transform\" --> \"webkitTransform\" --> \"-webkit-transform\"\n*/\nexports.roundTripPropertyName = function(propertyName) {\n\treturn $tw.utils.convertPropertyNameToStyleName($tw.utils.convertStyleNameToPropertyName(propertyName));\n};\n\n/*\nConverts a standard event name into the local browser specific equivalent. For example:\n\t\"animationEnd\" --> \"webkitAnimationEnd\"\n*/\n\nvar eventNameCache = {}; // We'll cache the conversions\n\nvar eventNameMappings = {\n\t\"transitionEnd\": {\n\t\tcorrespondingCssProperty: \"transition\",\n\t\tmappings: {\n\t\t\ttransition: \"transitionend\",\n\t\t\tOTransition: \"oTransitionEnd\",\n\t\t\tMSTransition: \"msTransitionEnd\",\n\t\t\tMozTransition: \"transitionend\",\n\t\t\twebkitTransition: \"webkitTransitionEnd\"\n\t\t}\n\t},\n\t\"animationEnd\": {\n\t\tcorrespondingCssProperty: \"animation\",\n\t\tmappings: {\n\t\t\tanimation: \"animationend\",\n\t\t\tOAnimation: \"oAnimationEnd\",\n\t\t\tMSAnimation: \"msAnimationEnd\",\n\t\t\tMozAnimation: \"animationend\",\n\t\t\twebkitAnimation: \"webkitAnimationEnd\"\n\t\t}\n\t}\n};\n\nexports.convertEventName = function(eventName) {\n\tif(eventNameCache[eventName]) {\n\t\treturn eventNameCache[eventName];\n\t}\n\tvar newEventName = eventName,\n\t\tmappings = eventNameMappings[eventName];\n\tif(mappings) {\n\t\tvar convertedProperty = $tw.utils.convertStyleNameToPropertyName(mappings.correspondingCssProperty);\n\t\tif(mappings.mappings[convertedProperty]) {\n\t\t\tnewEventName = mappings.mappings[convertedProperty];\n\t\t}\n\t}\n\t// Put it in the cache too\n\teventNameCache[eventName] = newEventName;\n\treturn newEventName;\n};\n\n/*\nReturn the names of the fullscreen APIs\n*/\nexports.getFullScreenApis = function() {\n\tvar d = document,\n\t\tdb = d.body,\n\t\tresult = {\n\t\t\"_requestFullscreen\": db.webkitRequestFullscreen !== undefined ? \"webkitRequestFullscreen\" :\n\t\t\t\t\t\t\tdb.mozRequestFullScreen !== undefined ? \"mozRequestFullScreen\" :\n\t\t\t\t\t\t\tdb.msRequestFullscreen !== undefined ? \"msRequestFullscreen\" :\n\t\t\t\t\t\t\tdb.requestFullscreen !== undefined ? \"requestFullscreen\" : \"\",\n\t\t\"_exitFullscreen\": d.webkitExitFullscreen !== undefined ? \"webkitExitFullscreen\" :\n\t\t\t\t\t\t\td.mozCancelFullScreen !== undefined ? \"mozCancelFullScreen\" :\n\t\t\t\t\t\t\td.msExitFullscreen !== undefined ? \"msExitFullscreen\" :\n\t\t\t\t\t\t\td.exitFullscreen !== undefined ? \"exitFullscreen\" : \"\",\n\t\t\"_fullscreenElement\": d.webkitFullscreenElement !== undefined ? \"webkitFullscreenElement\" :\n\t\t\t\t\t\t\td.mozFullScreenElement !== undefined ? \"mozFullScreenElement\" :\n\t\t\t\t\t\t\td.msFullscreenElement !== undefined ? \"msFullscreenElement\" :\n\t\t\t\t\t\t\td.fullscreenElement !== undefined ? \"fullscreenElement\" : \"\",\n\t\t\"_fullscreenChange\": d.webkitFullscreenElement !== undefined ? \"webkitfullscreenchange\" :\n\t\t\t\t\t\t\td.mozFullScreenElement !== undefined ? \"mozfullscreenchange\" :\n\t\t\t\t\t\t\td.msFullscreenElement !== undefined ? \"MSFullscreenChange\" :\n\t\t\t\t\t\t\td.fullscreenElement !== undefined ? \"fullscreenchange\" : \"\"\n\t};\n\tif(!result._requestFullscreen || !result._exitFullscreen || !result._fullscreenElement || !result._fullscreenChange) {\n\t\treturn null;\n\t} else {\n\t\treturn result;\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/csscolorparser.js": {
            "title": "$:/core/modules/utils/dom/csscolorparser.js",
            "text": "// (c) Dean McNamee <dean@gmail.com>, 2012.\n//\n// https://github.com/deanm/css-color-parser-js\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n// IN THE SOFTWARE.\n\n// http://www.w3.org/TR/css3-color/\nvar kCSSColorTable = {\n  \"transparent\": [0,0,0,0], \"aliceblue\": [240,248,255,1],\n  \"antiquewhite\": [250,235,215,1], \"aqua\": [0,255,255,1],\n  \"aquamarine\": [127,255,212,1], \"azure\": [240,255,255,1],\n  \"beige\": [245,245,220,1], \"bisque\": [255,228,196,1],\n  \"black\": [0,0,0,1], \"blanchedalmond\": [255,235,205,1],\n  \"blue\": [0,0,255,1], \"blueviolet\": [138,43,226,1],\n  \"brown\": [165,42,42,1], \"burlywood\": [222,184,135,1],\n  \"cadetblue\": [95,158,160,1], \"chartreuse\": [127,255,0,1],\n  \"chocolate\": [210,105,30,1], \"coral\": [255,127,80,1],\n  \"cornflowerblue\": [100,149,237,1], \"cornsilk\": [255,248,220,1],\n  \"crimson\": [220,20,60,1], \"cyan\": [0,255,255,1],\n  \"darkblue\": [0,0,139,1], \"darkcyan\": [0,139,139,1],\n  \"darkgoldenrod\": [184,134,11,1], \"darkgray\": [169,169,169,1],\n  \"darkgreen\": [0,100,0,1], \"darkgrey\": [169,169,169,1],\n  \"darkkhaki\": [189,183,107,1], \"darkmagenta\": [139,0,139,1],\n  \"darkolivegreen\": [85,107,47,1], \"darkorange\": [255,140,0,1],\n  \"darkorchid\": [153,50,204,1], \"darkred\": [139,0,0,1],\n  \"darksalmon\": [233,150,122,1], \"darkseagreen\": [143,188,143,1],\n  \"darkslateblue\": [72,61,139,1], \"darkslategray\": [47,79,79,1],\n  \"darkslategrey\": [47,79,79,1], \"darkturquoise\": [0,206,209,1],\n  \"darkviolet\": [148,0,211,1], \"deeppink\": [255,20,147,1],\n  \"deepskyblue\": [0,191,255,1], \"dimgray\": [105,105,105,1],\n  \"dimgrey\": [105,105,105,1], \"dodgerblue\": [30,144,255,1],\n  \"firebrick\": [178,34,34,1], \"floralwhite\": [255,250,240,1],\n  \"forestgreen\": [34,139,34,1], \"fuchsia\": [255,0,255,1],\n  \"gainsboro\": [220,220,220,1], \"ghostwhite\": [248,248,255,1],\n  \"gold\": [255,215,0,1], \"goldenrod\": [218,165,32,1],\n  \"gray\": [128,128,128,1], \"green\": [0,128,0,1],\n  \"greenyellow\": [173,255,47,1], \"grey\": [128,128,128,1],\n  \"honeydew\": [240,255,240,1], \"hotpink\": [255,105,180,1],\n  \"indianred\": [205,92,92,1], \"indigo\": [75,0,130,1],\n  \"ivory\": [255,255,240,1], \"khaki\": [240,230,140,1],\n  \"lavender\": [230,230,250,1], \"lavenderblush\": [255,240,245,1],\n  \"lawngreen\": [124,252,0,1], \"lemonchiffon\": [255,250,205,1],\n  \"lightblue\": [173,216,230,1], \"lightcoral\": [240,128,128,1],\n  \"lightcyan\": [224,255,255,1], \"lightgoldenrodyellow\": [250,250,210,1],\n  \"lightgray\": [211,211,211,1], \"lightgreen\": [144,238,144,1],\n  \"lightgrey\": [211,211,211,1], \"lightpink\": [255,182,193,1],\n  \"lightsalmon\": [255,160,122,1], \"lightseagreen\": [32,178,170,1],\n  \"lightskyblue\": [135,206,250,1], \"lightslategray\": [119,136,153,1],\n  \"lightslategrey\": [119,136,153,1], \"lightsteelblue\": [176,196,222,1],\n  \"lightyellow\": [255,255,224,1], \"lime\": [0,255,0,1],\n  \"limegreen\": [50,205,50,1], \"linen\": [250,240,230,1],\n  \"magenta\": [255,0,255,1], \"maroon\": [128,0,0,1],\n  \"mediumaquamarine\": [102,205,170,1], \"mediumblue\": [0,0,205,1],\n  \"mediumorchid\": [186,85,211,1], \"mediumpurple\": [147,112,219,1],\n  \"mediumseagreen\": [60,179,113,1], \"mediumslateblue\": [123,104,238,1],\n  \"mediumspringgreen\": [0,250,154,1], \"mediumturquoise\": [72,209,204,1],\n  \"mediumvioletred\": [199,21,133,1], \"midnightblue\": [25,25,112,1],\n  \"mintcream\": [245,255,250,1], \"mistyrose\": [255,228,225,1],\n  \"moccasin\": [255,228,181,1], \"navajowhite\": [255,222,173,1],\n  \"navy\": [0,0,128,1], \"oldlace\": [253,245,230,1],\n  \"olive\": [128,128,0,1], \"olivedrab\": [107,142,35,1],\n  \"orange\": [255,165,0,1], \"orangered\": [255,69,0,1],\n  \"orchid\": [218,112,214,1], \"palegoldenrod\": [238,232,170,1],\n  \"palegreen\": [152,251,152,1], \"paleturquoise\": [175,238,238,1],\n  \"palevioletred\": [219,112,147,1], \"papayawhip\": [255,239,213,1],\n  \"peachpuff\": [255,218,185,1], \"peru\": [205,133,63,1],\n  \"pink\": [255,192,203,1], \"plum\": [221,160,221,1],\n  \"powderblue\": [176,224,230,1], \"purple\": [128,0,128,1],\n  \"red\": [255,0,0,1], \"rosybrown\": [188,143,143,1],\n  \"royalblue\": [65,105,225,1], \"saddlebrown\": [139,69,19,1],\n  \"salmon\": [250,128,114,1], \"sandybrown\": [244,164,96,1],\n  \"seagreen\": [46,139,87,1], \"seashell\": [255,245,238,1],\n  \"sienna\": [160,82,45,1], \"silver\": [192,192,192,1],\n  \"skyblue\": [135,206,235,1], \"slateblue\": [106,90,205,1],\n  \"slategray\": [112,128,144,1], \"slategrey\": [112,128,144,1],\n  \"snow\": [255,250,250,1], \"springgreen\": [0,255,127,1],\n  \"steelblue\": [70,130,180,1], \"tan\": [210,180,140,1],\n  \"teal\": [0,128,128,1], \"thistle\": [216,191,216,1],\n  \"tomato\": [255,99,71,1], \"turquoise\": [64,224,208,1],\n  \"violet\": [238,130,238,1], \"wheat\": [245,222,179,1],\n  \"white\": [255,255,255,1], \"whitesmoke\": [245,245,245,1],\n  \"yellow\": [255,255,0,1], \"yellowgreen\": [154,205,50,1]}\n\nfunction clamp_css_byte(i) {  // Clamp to integer 0 .. 255.\n  i = Math.round(i);  // Seems to be what Chrome does (vs truncation).\n  return i < 0 ? 0 : i > 255 ? 255 : i;\n}\n\nfunction clamp_css_float(f) {  // Clamp to float 0.0 .. 1.0.\n  return f < 0 ? 0 : f > 1 ? 1 : f;\n}\n\nfunction parse_css_int(str) {  // int or percentage.\n  if (str[str.length - 1] === '%')\n    return clamp_css_byte(parseFloat(str) / 100 * 255);\n  return clamp_css_byte(parseInt(str));\n}\n\nfunction parse_css_float(str) {  // float or percentage.\n  if (str[str.length - 1] === '%')\n    return clamp_css_float(parseFloat(str) / 100);\n  return clamp_css_float(parseFloat(str));\n}\n\nfunction css_hue_to_rgb(m1, m2, h) {\n  if (h < 0) h += 1;\n  else if (h > 1) h -= 1;\n\n  if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;\n  if (h * 2 < 1) return m2;\n  if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6;\n  return m1;\n}\n\nfunction parseCSSColor(css_str) {\n  // Remove all whitespace, not compliant, but should just be more accepting.\n  var str = css_str.replace(/ /g, '').toLowerCase();\n\n  // Color keywords (and transparent) lookup.\n  if (str in kCSSColorTable) return kCSSColorTable[str].slice();  // dup.\n\n  // #abc and #abc123 syntax.\n  if (str[0] === '#') {\n    if (str.length === 4) {\n      var iv = parseInt(str.substr(1), 16);  // TODO(deanm): Stricter parsing.\n      if (!(iv >= 0 && iv <= 0xfff)) return null;  // Covers NaN.\n      return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),\n              (iv & 0xf0) | ((iv & 0xf0) >> 4),\n              (iv & 0xf) | ((iv & 0xf) << 4),\n              1];\n    } else if (str.length === 7) {\n      var iv = parseInt(str.substr(1), 16);  // TODO(deanm): Stricter parsing.\n      if (!(iv >= 0 && iv <= 0xffffff)) return null;  // Covers NaN.\n      return [(iv & 0xff0000) >> 16,\n              (iv & 0xff00) >> 8,\n              iv & 0xff,\n              1];\n    }\n\n    return null;\n  }\n\n  var op = str.indexOf('('), ep = str.indexOf(')');\n  if (op !== -1 && ep + 1 === str.length) {\n    var fname = str.substr(0, op);\n    var params = str.substr(op+1, ep-(op+1)).split(',');\n    var alpha = 1;  // To allow case fallthrough.\n    switch (fname) {\n      case 'rgba':\n        if (params.length !== 4) return null;\n        alpha = parse_css_float(params.pop());\n        // Fall through.\n      case 'rgb':\n        if (params.length !== 3) return null;\n        return [parse_css_int(params[0]),\n                parse_css_int(params[1]),\n                parse_css_int(params[2]),\n                alpha];\n      case 'hsla':\n        if (params.length !== 4) return null;\n        alpha = parse_css_float(params.pop());\n        // Fall through.\n      case 'hsl':\n        if (params.length !== 3) return null;\n        var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360;  // 0 .. 1\n        // NOTE(deanm): According to the CSS spec s/l should only be\n        // percentages, but we don't bother and let float or percentage.\n        var s = parse_css_float(params[1]);\n        var l = parse_css_float(params[2]);\n        var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;\n        var m1 = l * 2 - m2;\n        return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255),\n                clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255),\n                clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255),\n                alpha];\n      default:\n        return null;\n    }\n  }\n\n  return null;\n}\n\ntry { exports.parseCSSColor = parseCSSColor } catch(e) { }\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom.js": {
            "title": "$:/core/modules/utils/dom.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom.js\ntype: application/javascript\nmodule-type: utils\n\nVarious static DOM-related utility functions.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nDetermines whether element 'a' contains element 'b'\nCode thanks to John Resig, http://ejohn.org/blog/comparing-document-position/\n*/\nexports.domContains = function(a,b) {\n\treturn a.contains ?\n\t\ta !== b && a.contains(b) :\n\t\t!!(a.compareDocumentPosition(b) & 16);\n};\n\nexports.removeChildren = function(node) {\n\twhile(node.hasChildNodes()) {\n\t\tnode.removeChild(node.firstChild);\n\t}\n};\n\nexports.hasClass = function(el,className) {\n\treturn el && el.className && el.className.toString().split(\" \").indexOf(className) !== -1;\n};\n\nexports.addClass = function(el,className) {\n\tvar c = el.className.split(\" \");\n\tif(c.indexOf(className) === -1) {\n\t\tc.push(className);\n\t\tel.className = c.join(\" \");\n\t}\n};\n\nexports.removeClass = function(el,className) {\n\tvar c = el.className.split(\" \"),\n\t\tp = c.indexOf(className);\n\tif(p !== -1) {\n\t\tc.splice(p,1);\n\t\tel.className = c.join(\" \");\n\t}\n};\n\nexports.toggleClass = function(el,className,status) {\n\tif(status === undefined) {\n\t\tstatus = !exports.hasClass(el,className);\n\t}\n\tif(status) {\n\t\texports.addClass(el,className);\n\t} else {\n\t\texports.removeClass(el,className);\n\t}\n};\n\n/*\nGet the first parent element that has scrollbars or use the body as fallback.\n*/\nexports.getScrollContainer = function(el) {\n\tvar doc = el.ownerDocument;\n\twhile(el.parentNode) {\t\n\t\tel = el.parentNode;\n\t\tif(el.scrollTop) {\n\t\t\treturn el;\n\t\t}\n\t}\n\treturn doc.body;\n};\n\n/*\nGet the scroll position of the viewport\nReturns:\n\t{\n\t\tx: horizontal scroll position in pixels,\n\t\ty: vertical scroll position in pixels\n\t}\n*/\nexports.getScrollPosition = function(srcWindow) {\n\tvar scrollWindow = srcWindow || window;\n\tif(\"scrollX\" in scrollWindow) {\n\t\treturn {x: scrollWindow.scrollX, y: scrollWindow.scrollY};\n\t} else {\n\t\treturn {x: scrollWindow.document.documentElement.scrollLeft, y: scrollWindow.document.documentElement.scrollTop};\n\t}\n};\n\n/*\nAdjust the height of a textarea to fit its content, preserving scroll position, and return the height\n*/\nexports.resizeTextAreaToFit = function(domNode,minHeight) {\n\t// Get the scroll container and register the current scroll position\n\tvar container = $tw.utils.getScrollContainer(domNode),\n\t\tscrollTop = container.scrollTop;\n    // Measure the specified minimum height\n\tdomNode.style.height = minHeight;\n\tvar measuredHeight = domNode.offsetHeight || parseInt(minHeight,10);\n\t// Set its height to auto so that it snaps to the correct height\n\tdomNode.style.height = \"auto\";\n\t// Calculate the revised height\n\tvar newHeight = Math.max(domNode.scrollHeight + domNode.offsetHeight - domNode.clientHeight,measuredHeight);\n\t// Only try to change the height if it has changed\n\tif(newHeight !== domNode.offsetHeight) {\n\t\tdomNode.style.height = newHeight + \"px\";\n\t\t// Make sure that the dimensions of the textarea are recalculated\n\t\t$tw.utils.forceLayout(domNode);\n\t\t// Set the container to the position we registered at the beginning\n\t\tcontainer.scrollTop = scrollTop;\n\t}\n\treturn newHeight;\n};\n\n/*\nGets the bounding rectangle of an element in absolute page coordinates\n*/\nexports.getBoundingPageRect = function(element) {\n\tvar scrollPos = $tw.utils.getScrollPosition(element.ownerDocument.defaultView),\n\t\tclientRect = element.getBoundingClientRect();\n\treturn {\n\t\tleft: clientRect.left + scrollPos.x,\n\t\twidth: clientRect.width,\n\t\tright: clientRect.right + scrollPos.x,\n\t\ttop: clientRect.top + scrollPos.y,\n\t\theight: clientRect.height,\n\t\tbottom: clientRect.bottom + scrollPos.y\n\t};\n};\n\n/*\nSaves a named password in the browser\n*/\nexports.savePassword = function(name,password) {\n\tvar done = false;\n\ttry {\n\t\twindow.localStorage.setItem(\"tw5-password-\" + name,password);\n\t\tdone = true;\n\t} catch(e) {\n\t}\n\tif(!done) {\n\t\t$tw.savedPasswords = $tw.savedPasswords || Object.create(null);\n\t\t$tw.savedPasswords[name] = password;\n\t}\n};\n\n/*\nRetrieve a named password from the browser\n*/\nexports.getPassword = function(name) {\n\tvar value;\n\ttry {\n\t\tvalue = window.localStorage.getItem(\"tw5-password-\" + name);\n\t} catch(e) {\n\t}\n\tif(value !== undefined) {\n\t\treturn value;\n\t} else {\n\t\treturn ($tw.savedPasswords || Object.create(null))[name] || \"\";\n\t}\n};\n\n/*\nForce layout of a dom node and its descendents\n*/\nexports.forceLayout = function(element) {\n\tvar dummy = element.offsetWidth;\n};\n\n/*\nPulse an element for debugging purposes\n*/\nexports.pulseElement = function(element) {\n\t// Event handler to remove the class at the end\n\telement.addEventListener($tw.browser.animationEnd,function handler(event) {\n\t\telement.removeEventListener($tw.browser.animationEnd,handler,false);\n\t\t$tw.utils.removeClass(element,\"pulse\");\n\t},false);\n\t// Apply the pulse class\n\t$tw.utils.removeClass(element,\"pulse\");\n\t$tw.utils.forceLayout(element);\n\t$tw.utils.addClass(element,\"pulse\");\n};\n\n/*\nAttach specified event handlers to a DOM node\ndomNode: where to attach the event handlers\nevents: array of event handlers to be added (see below)\nEach entry in the events array is an object with these properties:\nhandlerFunction: optional event handler function\nhandlerObject: optional event handler object\nhandlerMethod: optionally specifies object handler method name (defaults to `handleEvent`)\n*/\nexports.addEventListeners = function(domNode,events) {\n\t$tw.utils.each(events,function(eventInfo) {\n\t\tvar handler;\n\t\tif(eventInfo.handlerFunction) {\n\t\t\thandler = eventInfo.handlerFunction;\n\t\t} else if(eventInfo.handlerObject) {\n\t\t\tif(eventInfo.handlerMethod) {\n\t\t\t\thandler = function(event) {\n\t\t\t\t\teventInfo.handlerObject[eventInfo.handlerMethod].call(eventInfo.handlerObject,event);\n\t\t\t\t};\t\n\t\t\t} else {\n\t\t\t\thandler = eventInfo.handlerObject;\n\t\t\t}\n\t\t}\n\t\tdomNode.addEventListener(eventInfo.name,handler,false);\n\t});\n};\n\n/*\nGet the computed styles applied to an element as an array of strings of individual CSS properties\n*/\nexports.getComputedStyles = function(domNode) {\n\tvar textAreaStyles = window.getComputedStyle(domNode,null),\n\t\tstyleDefs = [],\n\t\tname;\n\tfor(var t=0; t<textAreaStyles.length; t++) {\n\t\tname = textAreaStyles[t];\n\t\tstyleDefs.push(name + \": \" + textAreaStyles.getPropertyValue(name) + \";\");\n\t}\n\treturn styleDefs;\n};\n\n/*\nApply a set of styles passed as an array of strings of individual CSS properties\n*/\nexports.setStyles = function(domNode,styleDefs) {\n\tdomNode.style.cssText = styleDefs.join(\"\");\n};\n\n/*\nCopy the computed styles from a source element to a destination element\n*/\nexports.copyStyles = function(srcDomNode,dstDomNode) {\n\t$tw.utils.setStyles(dstDomNode,$tw.utils.getComputedStyles(srcDomNode));\n};\n\n/*\nCopy plain text to the clipboard on browsers that support it\n*/\nexports.copyToClipboard = function(text,options) {\n\toptions = options || {};\n\tvar textArea = document.createElement(\"textarea\");\n\ttextArea.style.position = \"fixed\";\n\ttextArea.style.top = 0;\n\ttextArea.style.left = 0;\n\ttextArea.style.fontSize = \"12pt\";\n\ttextArea.style.width = \"2em\";\n\ttextArea.style.height = \"2em\";\n\ttextArea.style.padding = 0;\n\ttextArea.style.border = \"none\";\n\ttextArea.style.outline = \"none\";\n\ttextArea.style.boxShadow = \"none\";\n\ttextArea.style.background = \"transparent\";\n\ttextArea.value = text;\n\tdocument.body.appendChild(textArea);\n\ttextArea.select();\n\ttextArea.setSelectionRange(0,text.length);\n\tvar succeeded = false;\n\ttry {\n\t\tsucceeded = document.execCommand(\"copy\");\n\t} catch (err) {\n\t}\n\tif(!options.doNotNotify) {\n\t\t$tw.notifier.display(succeeded ? \"$:/language/Notifications/CopiedToClipboard/Succeeded\" : \"$:/language/Notifications/CopiedToClipboard/Failed\");\n\t}\n\tdocument.body.removeChild(textArea);\n};\n\nexports.getLocationPath = function() {\n\treturn window.location.toString().split(\"#\")[0];\n};\n\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/dragndrop.js": {
            "title": "$:/core/modules/utils/dom/dragndrop.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/dragndrop.js\ntype: application/javascript\nmodule-type: utils\n\nBrowser data transfer utilities, used with the clipboard and drag and drop\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nOptions:\n\ndomNode: dom node to make draggable\ndragImageType: \"pill\" or \"dom\"\ndragTiddlerFn: optional function to retrieve the title of tiddler to drag\ndragFilterFn: optional function to retreive the filter defining a list of tiddlers to drag\nwidget: widget to use as the contect for the filter\n*/\nexports.makeDraggable = function(options) {\n\tvar dragImageType = options.dragImageType || \"dom\",\n\t\tdragImage,\n\t\tdomNode = options.domNode;\n\t// Make the dom node draggable (not necessary for anchor tags)\n\tif((domNode.tagName || \"\").toLowerCase() !== \"a\") {\n\t\tdomNode.setAttribute(\"draggable\",\"true\");\t\t\n\t}\n\t// Add event handlers\n\t$tw.utils.addEventListeners(domNode,[\n\t\t{name: \"dragstart\", handlerFunction: function(event) {\n\t\t\tif(event.dataTransfer === undefined) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Collect the tiddlers being dragged\n\t\t\tvar dragTiddler = options.dragTiddlerFn && options.dragTiddlerFn(),\n\t\t\t\tdragFilter = options.dragFilterFn && options.dragFilterFn(),\n\t\t\t\ttitles = dragTiddler ? [dragTiddler] : [],\n\t\t\t    \tstartActions = options.startActions;\n\t\t\tif(dragFilter) {\n\t\t\t\ttitles.push.apply(titles,options.widget.wiki.filterTiddlers(dragFilter,options.widget));\n\t\t\t}\n\t\t\tvar titleString = $tw.utils.stringifyList(titles);\n\t\t\t// Check that we've something to drag\n\t\t\tif(titles.length > 0 && event.target === domNode) {\n\t\t\t\t// Mark the drag in progress\n\t\t\t\t$tw.dragInProgress = domNode;\n\t\t\t\t// Set the dragging class on the element being dragged\n\t\t\t\t$tw.utils.addClass(event.target,\"tc-dragging\");\n\t\t\t\t// Invoke drag-start actions if given\n\t\t\t\tif(startActions !== undefined) {\n\t\t\t\t\toptions.widget.invokeActionString(startActions,options.widget,event,{actionTiddler: titleString});\n\t\t\t\t}\n\t\t\t\t// Create the drag image elements\n\t\t\t\tdragImage = options.widget.document.createElement(\"div\");\n\t\t\t\tdragImage.className = \"tc-tiddler-dragger\";\n\t\t\t\tvar inner = options.widget.document.createElement(\"div\");\n\t\t\t\tinner.className = \"tc-tiddler-dragger-inner\";\n\t\t\t\tinner.appendChild(options.widget.document.createTextNode(\n\t\t\t\t\ttitles.length === 1 ? \n\t\t\t\t\t\ttitles[0] :\n\t\t\t\t\t\ttitles.length + \" tiddlers\"\n\t\t\t\t));\n\t\t\t\tdragImage.appendChild(inner);\n\t\t\t\toptions.widget.document.body.appendChild(dragImage);\n\t\t\t\t// Set the data transfer properties\n\t\t\t\tvar dataTransfer = event.dataTransfer;\n\t\t\t\t// Set up the image\n\t\t\t\tdataTransfer.effectAllowed = \"all\";\n\t\t\t\tif(dataTransfer.setDragImage) {\n\t\t\t\t\tif(dragImageType === \"pill\") {\n\t\t\t\t\t\tdataTransfer.setDragImage(dragImage.firstChild,-16,-16);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar r = domNode.getBoundingClientRect();\n\t\t\t\t\t\tdataTransfer.setDragImage(domNode,event.clientX-r.left,event.clientY-r.top);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Set up the data transfer\n\t\t\t\tif(dataTransfer.clearData) {\n\t\t\t\t\tdataTransfer.clearData();\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\tvar jsonData = [];\n\t\t\t\tif(titles.length > 1) {\n\t\t\t\t\ttitles.forEach(function(title) {\n\t\t\t\t\t\tjsonData.push(options.widget.wiki.getTiddlerAsJson(title));\n\t\t\t\t\t});\n\t\t\t\t\tjsonData = \"[\" + jsonData.join(\",\") + \"]\";\n\t\t\t\t} else {\n\t\t\t\t\tjsonData = options.widget.wiki.getTiddlerAsJson(titles[0]);\n\t\t\t\t}\n\t\t\t\t// IE doesn't like these content types\n\t\t\t\tif(!$tw.browser.isIE) {\n\t\t\t\t\tdataTransfer.setData(\"text/vnd.tiddler\",jsonData);\n\t\t\t\t\tdataTransfer.setData(\"text/plain\",titleString);\n\t\t\t\t\tdataTransfer.setData(\"text/x-moz-url\",\"data:text/vnd.tiddler,\" + encodeURIComponent(jsonData));\n\t\t\t\t}\n\t\t\t\tdataTransfer.setData(\"URL\",\"data:text/vnd.tiddler,\" + encodeURIComponent(jsonData));\n\t\t\t\tdataTransfer.setData(\"Text\",titleString);\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\t\t\treturn false;\n\t\t}},\n\t\t{name: \"dragend\", handlerFunction: function(event) {\n\t\t\tif(event.target === domNode) {\n\t\t\t\t// Collect the tiddlers being dragged\n\t\t\t\tvar dragTiddler = options.dragTiddlerFn && options.dragTiddlerFn(),\n\t\t\t\t\tdragFilter = options.dragFilterFn && options.dragFilterFn(),\n\t\t\t\t\ttitles = dragTiddler ? [dragTiddler] : [],\n\t\t\t    \t\tendActions = options.endActions;\n\t\t\t\tif(dragFilter) {\n\t\t\t\t\ttitles.push.apply(titles,options.widget.wiki.filterTiddlers(dragFilter,options.widget));\n\t\t\t\t}\n\t\t\t\tvar titleString = $tw.utils.stringifyList(titles);\n\t\t\t\t$tw.dragInProgress = null;\n\t\t\t\t// Invoke drag-end actions if given\n\t\t\t\tif(endActions !== undefined) {\n\t\t\t\t\toptions.widget.invokeActionString(endActions,options.widget,event,{actionTiddler: titleString});\n\t\t\t\t}\n\t\t\t\t// Remove the dragging class on the element being dragged\n\t\t\t\t$tw.utils.removeClass(event.target,\"tc-dragging\");\n\t\t\t\t// Delete the drag image element\n\t\t\t\tif(dragImage) {\n\t\t\t\t\tdragImage.parentNode.removeChild(dragImage);\n\t\t\t\t\tdragImage = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}}\n\t]);\n};\n\nexports.importDataTransfer = function(dataTransfer,fallbackTitle,callback) {\n\t// Try each provided data type in turn\n\tif($tw.log.IMPORT) {\n\t\tconsole.log(\"Available data types:\");\n\t\tfor(var type=0; type<dataTransfer.types.length; type++) {\n\t\t\tconsole.log(\"type\",dataTransfer.types[type],dataTransfer.getData(dataTransfer.types[type]))\n\t\t}\n\t}\n\tfor(var t=0; t<importDataTypes.length; t++) {\n\t\tif(!$tw.browser.isIE || importDataTypes[t].IECompatible) {\n\t\t\t// Get the data\n\t\t\tvar dataType = importDataTypes[t];\n\t\t\t\tvar data = dataTransfer.getData(dataType.type);\n\t\t\t// Import the tiddlers in the data\n\t\t\tif(data !== \"\" && data !== null) {\n\t\t\t\tif($tw.log.IMPORT) {\n\t\t\t\t\tconsole.log(\"Importing data type '\" + dataType.type + \"', data: '\" + data + \"'\")\n\t\t\t\t}\n\t\t\t\tvar tiddlerFields = dataType.toTiddlerFieldsArray(data,fallbackTitle);\n\t\t\t\tcallback(tiddlerFields);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar importDataTypes = [\n\t{type: \"text/vnd.tiddler\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn parseJSONTiddlers(data,fallbackTitle);\n\t}},\n\t{type: \"URL\", IECompatible: true, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\t// Check for tiddler data URI\n\t\tvar match = decodeURIComponent(data).match(/^data\\:text\\/vnd\\.tiddler,(.*)/i);\n\t\tif(match) {\n\t\t\treturn parseJSONTiddlers(match[1],fallbackTitle);\n\t\t} else {\n\t\t\treturn [{title: fallbackTitle, text: data}]; // As URL string\n\t\t}\n\t}},\n\t{type: \"text/x-moz-url\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\t// Check for tiddler data URI\n\t\tvar match = decodeURIComponent(data).match(/^data\\:text\\/vnd\\.tiddler,(.*)/i);\n\t\tif(match) {\n\t\t\treturn parseJSONTiddlers(match[1],fallbackTitle);\n\t\t} else {\n\t\t\treturn [{title: fallbackTitle, text: data}]; // As URL string\n\t\t}\n\t}},\n\t{type: \"text/html\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}},\n\t{type: \"text/plain\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}},\n\t{type: \"Text\", IECompatible: true, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}},\n\t{type: \"text/uri-list\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}}\n];\n\nfunction parseJSONTiddlers(json,fallbackTitle) {\n\tvar data = JSON.parse(json);\n\tif(!$tw.utils.isArray(data)) {\n\t\tdata = [data];\n\t}\n\tdata.forEach(function(fields) {\n\t\tfields.title = fields.title || fallbackTitle;\n\t});\n\treturn data;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/http.js": {
            "title": "$:/core/modules/utils/dom/http.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/http.js\ntype: application/javascript\nmodule-type: utils\n\nBrowser HTTP support\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nA quick and dirty HTTP function; to be refactored later. Options are:\n\turl: URL to retrieve\n\theaders: hashmap of headers to send\n\ttype: GET, PUT, POST etc\n\tcallback: function invoked with (err,data,xhr)\n\treturnProp: string name of the property to return as first argument of callback\n*/\nexports.httpRequest = function(options) {\n\tvar type = options.type || \"GET\",\n\t\turl = options.url,\n\t\theaders = options.headers || {accept: \"application/json\"},\n\t\treturnProp = options.returnProp || \"responseText\",\n\t\trequest = new XMLHttpRequest(),\n\t\tdata = \"\",\n\t\tf,results;\n\t// Massage the data hashmap into a string\n\tif(options.data) {\n\t\tif(typeof options.data === \"string\") { // Already a string\n\t\t\tdata = options.data;\n\t\t} else { // A hashmap of strings\n\t\t\tresults = [];\n\t\t\t$tw.utils.each(options.data,function(dataItem,dataItemTitle) {\n\t\t\t\tresults.push(dataItemTitle + \"=\" + encodeURIComponent(dataItem));\n\t\t\t});\n\t\t\tif(type === \"GET\" || type === \"HEAD\") {\n\t\t\t\turl += \"?\" + results.join(\"&\");\n\t\t\t} else {\n\t\t\t\tdata = results.join(\"&\");\n\t\t\t}\n\t\t}\n\t}\n\t// Set up the state change handler\n\trequest.onreadystatechange = function() {\n\t\tif(this.readyState === 4) {\n\t\t\tif(this.status === 200 || this.status === 201 || this.status === 204) {\n\t\t\t\t// Success!\n\t\t\t\toptions.callback(null,this[returnProp],this);\n\t\t\t\treturn;\n\t\t\t}\n\t\t// Something went wrong\n\t\toptions.callback($tw.language.getString(\"Error/XMLHttpRequest\") + \": \" + this.status,null,this);\n\t\t}\n\t};\n\t// Make the request\n\trequest.open(type,url,true);\n\tif(headers) {\n\t\t$tw.utils.each(headers,function(header,headerTitle,object) {\n\t\t\trequest.setRequestHeader(headerTitle,header);\n\t\t});\n\t}\n\tif(data && !$tw.utils.hop(headers,\"Content-type\")) {\n\t\trequest.setRequestHeader(\"Content-type\",\"application/x-www-form-urlencoded; charset=UTF-8\");\n\t}\n\tif(!$tw.utils.hop(headers,\"X-Requested-With\")) {\n\t\trequest.setRequestHeader(\"X-Requested-With\",\"TiddlyWiki\");\n\t}\n\ttry {\n\t\trequest.send(data);\n\t} catch(e) {\n\t\toptions.callback(e,null,this);\n\t}\n\treturn request;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/keyboard.js": {
            "title": "$:/core/modules/utils/dom/keyboard.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/keyboard.js\ntype: application/javascript\nmodule-type: utils\n\nKeyboard utilities; now deprecated. Instead, use $tw.keyboardManager\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n[\"parseKeyDescriptor\",\"checkKeyDescriptor\"].forEach(function(method) {\n\texports[method] = function() {\n\t\tif($tw.keyboardManager) {\n\t\t\treturn $tw.keyboardManager[method].apply($tw.keyboardManager,Array.prototype.slice.call(arguments,0));\n\t\t} else {\n\t\t\treturn null\n\t\t}\n\t};\n});\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/modal.js": {
            "title": "$:/core/modules/utils/dom/modal.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/modal.js\ntype: application/javascript\nmodule-type: utils\n\nModal message mechanism\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nvar Modal = function(wiki) {\n\tthis.wiki = wiki;\n\tthis.modalCount = 0;\n};\n\n/*\nDisplay a modal dialogue\n\ttitle: Title of tiddler to display\n\toptions: see below\nOptions include:\n\tdownloadLink: Text of a big download link to include\n*/\nModal.prototype.display = function(title,options) {\n\toptions = options || {};\n\tthis.srcDocument = options.variables && (options.variables.rootwindow === \"true\" ||\n\t\t\t\toptions.variables.rootwindow === \"yes\") ? document :\n\t\t\t\t(options.event.event && options.event.event.target ? options.event.event.target.ownerDocument : document);\n\tthis.srcWindow = this.srcDocument.defaultView;\n\tvar self = this,\n\t\trefreshHandler,\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\ttiddler = this.wiki.getTiddler(title);\n\t// Don't do anything if the tiddler doesn't exist\n\tif(!tiddler) {\n\t\treturn;\n\t}\n\t// Create the variables\n\tvar variables = $tw.utils.extend({currentTiddler: title},options.variables);\n\t// Create the wrapper divs\n\tvar wrapper = this.srcDocument.createElement(\"div\"),\n\t\tmodalBackdrop = this.srcDocument.createElement(\"div\"),\n\t\tmodalWrapper = this.srcDocument.createElement(\"div\"),\n\t\tmodalHeader = this.srcDocument.createElement(\"div\"),\n\t\theaderTitle = this.srcDocument.createElement(\"h3\"),\n\t\tmodalBody = this.srcDocument.createElement(\"div\"),\n\t\tmodalLink = this.srcDocument.createElement(\"a\"),\n\t\tmodalFooter = this.srcDocument.createElement(\"div\"),\n\t\tmodalFooterHelp = this.srcDocument.createElement(\"span\"),\n\t\tmodalFooterButtons = this.srcDocument.createElement(\"span\");\n\t// Up the modal count and adjust the body class\n\tthis.modalCount++;\n\tthis.adjustPageClass();\n\t// Add classes\n\t$tw.utils.addClass(wrapper,\"tc-modal-wrapper\");\n\tif(tiddler.fields && tiddler.fields.class) {\n\t\t$tw.utils.addClass(wrapper,tiddler.fields.class);\n\t}\n\t$tw.utils.addClass(modalBackdrop,\"tc-modal-backdrop\");\n\t$tw.utils.addClass(modalWrapper,\"tc-modal\");\n\t$tw.utils.addClass(modalHeader,\"tc-modal-header\");\n\t$tw.utils.addClass(modalBody,\"tc-modal-body\");\n\t$tw.utils.addClass(modalFooter,\"tc-modal-footer\");\n\t// Join them together\n\twrapper.appendChild(modalBackdrop);\n\twrapper.appendChild(modalWrapper);\n\tmodalHeader.appendChild(headerTitle);\n\tmodalWrapper.appendChild(modalHeader);\n\tmodalWrapper.appendChild(modalBody);\n\tmodalFooter.appendChild(modalFooterHelp);\n\tmodalFooter.appendChild(modalFooterButtons);\n\tmodalWrapper.appendChild(modalFooter);\n\t// Render the title of the message\n\tvar headerWidgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tfield: \"subtitle\",\n\t\tmode: \"inline\",\n\t\tchildren: [{\n\t\t\ttype: \"text\",\n\t\t\tattributes: {\n\t\t\t\ttext: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalue: title\n\t\t}}}],\n\t\tparentWidget: $tw.rootWidget,\n\t\tdocument: this.srcDocument,\n\t\tvariables: variables,\n\t\timportPageMacros: true\n\t});\n\theaderWidgetNode.render(headerTitle,null);\n\t// Render the body of the message\n\tvar bodyWidgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tparentWidget: $tw.rootWidget,\n\t\tdocument: this.srcDocument,\n\t\tvariables: variables,\n\t\timportPageMacros: true\n\t});\n\tbodyWidgetNode.render(modalBody,null);\n\t// Setup the link if present\n\tif(options.downloadLink) {\n\t\tmodalLink.href = options.downloadLink;\n\t\tmodalLink.appendChild(this.srcDocument.createTextNode(\"Right-click to save changes\"));\n\t\tmodalBody.appendChild(modalLink);\n\t}\n\t// Render the footer of the message\n\tif(tiddler.fields && tiddler.fields.help) {\n\t\tvar link = this.srcDocument.createElement(\"a\");\n\t\tlink.setAttribute(\"href\",tiddler.fields.help);\n\t\tlink.setAttribute(\"target\",\"_blank\");\n\t\tlink.setAttribute(\"rel\",\"noopener noreferrer\");\n\t\tlink.appendChild(this.srcDocument.createTextNode(\"Help\"));\n\t\tmodalFooterHelp.appendChild(link);\n\t\tmodalFooterHelp.style.float = \"left\";\n\t}\n\tvar footerWidgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tfield: \"footer\",\n\t\tmode: \"inline\",\n\t\tchildren: [{\n\t\t\ttype: \"button\",\n\t\t\tattributes: {\n\t\t\t\tmessage: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalue: \"tm-close-tiddler\"\n\t\t\t\t}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\",\n\t\t\t\tattributes: {\n\t\t\t\t\ttext: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tvalue: $tw.language.getString(\"Buttons/Close/Caption\")\n\t\t\t}}}\n\t\t]}],\n\t\tparentWidget: $tw.rootWidget,\n\t\tdocument: this.srcDocument,\n\t\tvariables: variables,\n\t\timportPageMacros: true\n\t});\n\tfooterWidgetNode.render(modalFooterButtons,null);\n\t// Set up the refresh handler\n\trefreshHandler = function(changes) {\n\t\theaderWidgetNode.refresh(changes,modalHeader,null);\n\t\tbodyWidgetNode.refresh(changes,modalBody,null);\n\t\tfooterWidgetNode.refresh(changes,modalFooterButtons,null);\n\t};\n\tthis.wiki.addEventListener(\"change\",refreshHandler);\n\t// Add the close event handler\n\tvar closeHandler = function(event) {\n\t\t// Remove our refresh handler\n\t\tself.wiki.removeEventListener(\"change\",refreshHandler);\n\t\t// Decrease the modal count and adjust the body class\n\t\tself.modalCount--;\n\t\tself.adjustPageClass();\n\t\t// Force layout and animate the modal message away\n\t\t$tw.utils.forceLayout(modalBackdrop);\n\t\t$tw.utils.forceLayout(modalWrapper);\n\t\t$tw.utils.setStyle(modalBackdrop,[\n\t\t\t{opacity: \"0\"}\n\t\t]);\n\t\t$tw.utils.setStyle(modalWrapper,[\n\t\t\t{transform: \"translateY(\" + self.srcWindow.innerHeight + \"px)\"}\n\t\t]);\n\t\t// Set up an event for the transition end\n\t\tself.srcWindow.setTimeout(function() {\n\t\t\tif(wrapper.parentNode) {\n\t\t\t\t// Remove the modal message from the DOM\n\t\t\t\tself.srcDocument.body.removeChild(wrapper);\n\t\t\t}\n\t\t},duration);\n\t\t// Don't let anyone else handle the tm-close-tiddler message\n\t\treturn false;\n\t};\n\theaderWidgetNode.addEventListener(\"tm-close-tiddler\",closeHandler,false);\n\tbodyWidgetNode.addEventListener(\"tm-close-tiddler\",closeHandler,false);\n\tfooterWidgetNode.addEventListener(\"tm-close-tiddler\",closeHandler,false);\n\t// Set the initial styles for the message\n\t$tw.utils.setStyle(modalBackdrop,[\n\t\t{opacity: \"0\"}\n\t]);\n\t$tw.utils.setStyle(modalWrapper,[\n\t\t{transformOrigin: \"0% 0%\"},\n\t\t{transform: \"translateY(\" + (-this.srcWindow.innerHeight) + \"px)\"}\n\t]);\n\t// Put the message into the document\n\tthis.srcDocument.body.appendChild(wrapper);\n\t// Set up animation for the styles\n\t$tw.utils.setStyle(modalBackdrop,[\n\t\t{transition: \"opacity \" + duration + \"ms ease-out\"}\n\t]);\n\t$tw.utils.setStyle(modalWrapper,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out\"}\n\t]);\n\t// Force layout\n\t$tw.utils.forceLayout(modalBackdrop);\n\t$tw.utils.forceLayout(modalWrapper);\n\t// Set final animated styles\n\t$tw.utils.setStyle(modalBackdrop,[\n\t\t{opacity: \"0.7\"}\n\t]);\n\t$tw.utils.setStyle(modalWrapper,[\n\t\t{transform: \"translateY(0px)\"}\n\t]);\n};\n\nModal.prototype.adjustPageClass = function() {\n\tvar windowContainer = $tw.pageContainer ? ($tw.pageContainer === this.srcDocument.body.firstChild ? $tw.pageContainer : this.srcDocument.body.firstChild) : null;\n\tif(windowContainer) {\n\t\t$tw.utils.toggleClass(windowContainer,\"tc-modal-displayed\",this.modalCount > 0);\n\t}\n};\n\nexports.Modal = Modal;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/notifier.js": {
            "title": "$:/core/modules/utils/dom/notifier.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/notifier.js\ntype: application/javascript\nmodule-type: utils\n\nNotifier mechanism\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nvar Notifier = function(wiki) {\n\tthis.wiki = wiki;\n};\n\n/*\nDisplay a notification\n\ttitle: Title of tiddler containing the notification text\n\toptions: see below\nOptions include:\n*/\nNotifier.prototype.display = function(title,options) {\n\toptions = options || {};\n\t// Create the wrapper divs\n\tvar self = this,\n\t\tnotification = document.createElement(\"div\"),\n\t\ttiddler = this.wiki.getTiddler(title),\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\trefreshHandler;\n\t// Don't do anything if the tiddler doesn't exist\n\tif(!tiddler) {\n\t\treturn;\n\t}\n\t// Add classes\n\t$tw.utils.addClass(notification,\"tc-notification\");\n\t// Create the variables\n\tvar variables = $tw.utils.extend({currentTiddler: title},options.variables);\n\t// Render the body of the notification\n\tvar widgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tparentWidget: $tw.rootWidget,\n\t\tdocument: document,\n\t\tvariables: variables,\n\t\timportPageMacros: true});\n\twidgetNode.render(notification,null);\n\trefreshHandler = function(changes) {\n\t\twidgetNode.refresh(changes,notification,null);\n\t};\n\tthis.wiki.addEventListener(\"change\",refreshHandler);\n\t// Set the initial styles for the notification\n\t$tw.utils.setStyle(notification,[\n\t\t{opacity: \"0\"},\n\t\t{transformOrigin: \"0% 0%\"},\n\t\t{transform: \"translateY(\" + (-window.innerHeight) + \"px)\"},\n\t\t{transition: \"opacity \" + duration + \"ms ease-out, \" + $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out\"}\n\t]);\n\t// Add the notification to the DOM\n\tdocument.body.appendChild(notification);\n\t// Force layout\n\t$tw.utils.forceLayout(notification);\n\t// Set final animated styles\n\t$tw.utils.setStyle(notification,[\n\t\t{opacity: \"1.0\"},\n\t\t{transform: \"translateY(0px)\"}\n\t]);\n\t// Set a timer to remove the notification\n\twindow.setTimeout(function() {\n\t\t// Remove our change event handler\n\t\tself.wiki.removeEventListener(\"change\",refreshHandler);\n\t\t// Force layout and animate the notification away\n\t\t$tw.utils.forceLayout(notification);\n\t\t$tw.utils.setStyle(notification,[\n\t\t\t{opacity: \"0.0\"},\n\t\t\t{transform: \"translateX(\" + (notification.offsetWidth) + \"px)\"}\n\t\t]);\n\t\t// Remove the modal message from the DOM once the transition ends\n\t\tsetTimeout(function() {\n\t\t\tif(notification.parentNode) {\n\t\t\t\tdocument.body.removeChild(notification);\n\t\t\t}\n\t\t},duration);\n\t},$tw.config.preferences.notificationDuration);\n};\n\nexports.Notifier = Notifier;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/popup.js": {
            "title": "$:/core/modules/utils/dom/popup.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/popup.js\ntype: application/javascript\nmodule-type: utils\n\nModule that creates a $tw.utils.Popup object prototype that manages popups in the browser\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nCreates a Popup object with these options:\n\trootElement: the DOM element to which the popup zapper should be attached\n*/\nvar Popup = function(options) {\n\toptions = options || {};\n\tthis.rootElement = options.rootElement || document.documentElement;\n\tthis.popups = []; // Array of {title:,wiki:,domNode:} objects\n};\n\n/*\nTrigger a popup open or closed. Parameters are in a hashmap:\n\ttitle: title of the tiddler where the popup details are stored\n\tdomNode: dom node to which the popup will be positioned (one of domNode or domNodeRect is required)\n\tdomNodeRect: rectangle to which the popup will be positioned\n\twiki: wiki\n\tforce: if specified, forces the popup state to true or false (instead of toggling it)\n\tfloating: if true, skips registering the popup, meaning that it will need manually clearing\n*/\nPopup.prototype.triggerPopup = function(options) {\n\t// Check if this popup is already active\n\tvar index = this.findPopup(options.title);\n\t// Compute the new state\n\tvar state = index === -1;\n\tif(options.force !== undefined) {\n\t\tstate = options.force;\n\t}\n\t// Show or cancel the popup according to the new state\n\tif(state) {\n\t\tthis.show(options);\n\t} else {\n\t\tthis.cancel(index);\n\t}\n};\n\nPopup.prototype.findPopup = function(title) {\n\tvar index = -1;\n\tfor(var t=0; t<this.popups.length; t++) {\n\t\tif(this.popups[t].title === title) {\n\t\t\tindex = t;\n\t\t}\n\t}\n\treturn index;\n};\n\nPopup.prototype.handleEvent = function(event) {\n\tif(event.type === \"click\") {\n\t\t// Find out what was clicked on\n\t\tvar info = this.popupInfo(event.target),\n\t\t\tcancelLevel = info.popupLevel - 1;\n\t\t// Don't remove the level that was clicked on if we clicked on a handle\n\t\tif(info.isHandle) {\n\t\t\tcancelLevel++;\n\t\t}\n\t\t// Cancel\n\t\tthis.cancel(cancelLevel);\n\t}\n};\n\n/*\nFind the popup level containing a DOM node. Returns:\npopupLevel: count of the number of nested popups containing the specified element\nisHandle: true if the specified element is within a popup handle\n*/\nPopup.prototype.popupInfo = function(domNode) {\n\tvar isHandle = false,\n\t\tpopupCount = 0,\n\t\tnode = domNode;\n\t// First check ancestors to see if we're within a popup handle\n\twhile(node) {\n\t\tif($tw.utils.hasClass(node,\"tc-popup-handle\")) {\n\t\t\tisHandle = true;\n\t\t\tpopupCount++;\n\t\t}\n\t\tif($tw.utils.hasClass(node,\"tc-popup-keep\")) {\n\t\t\tisHandle = true;\n\t\t}\n\t\tnode = node.parentNode;\n\t}\n\t// Then count the number of ancestor popups\n\tnode = domNode;\n\twhile(node) {\n\t\tif($tw.utils.hasClass(node,\"tc-popup\")) {\n\t\t\tpopupCount++;\n\t\t}\n\t\tnode = node.parentNode;\n\t}\n\tvar info = {\n\t\tpopupLevel: popupCount,\n\t\tisHandle: isHandle\n\t};\n\treturn info;\n};\n\n/*\nDisplay a popup by adding it to the stack\n*/\nPopup.prototype.show = function(options) {\n\t// Find out what was clicked on\n\tvar info = this.popupInfo(options.domNode);\n\t// Cancel any higher level popups\n\tthis.cancel(info.popupLevel);\n\n\t// Store the popup details if not already there\n\tif(!options.floating && this.findPopup(options.title) === -1) {\n\t\tthis.popups.push({\n\t\t\ttitle: options.title,\n\t\t\twiki: options.wiki,\n\t\t\tdomNode: options.domNode,\n\t\t\tnoStateReference: options.noStateReference\n\t\t});\n\t}\n\t// Set the state tiddler\n\tvar rect;\n\tif(options.domNodeRect) {\n\t\trect = options.domNodeRect;\n\t} else {\n\t\trect = {\n\t\t\tleft: options.domNode.offsetLeft,\n\t\t\ttop: options.domNode.offsetTop,\n\t\t\twidth: options.domNode.offsetWidth,\n\t\t\theight: options.domNode.offsetHeight\n\t\t};\n\t}\n\tvar popupRect = \"(\" + rect.left + \",\" + rect.top + \",\" + \n\t\t\t\trect.width + \",\" + rect.height + \")\";\n\tif(options.noStateReference) {\n\t\toptions.wiki.setText(options.title,\"text\",undefined,popupRect);\n\t} else {\n\t\toptions.wiki.setTextReference(options.title,popupRect);\n\t}\n\t// Add the click handler if we have any popups\n\tif(this.popups.length > 0) {\n\t\tthis.rootElement.addEventListener(\"click\",this,true);\t\t\n\t}\n};\n\n/*\nCancel all popups at or above a specified level or DOM node\nlevel: popup level to cancel (0 cancels all popups)\n*/\nPopup.prototype.cancel = function(level) {\n\tvar numPopups = this.popups.length;\n\tlevel = Math.max(0,Math.min(level,numPopups));\n\tfor(var t=level; t<numPopups; t++) {\n\t\tvar popup = this.popups.pop();\n\t\tif(popup.title) {\n\t\t\tif(popup.noStateReference) {\n\t\t\t\tpopup.wiki.deleteTiddler(popup.title);\n\t\t\t} else {\n\t\t\t\tpopup.wiki.deleteTiddler($tw.utils.parseTextReference(popup.title).title);\n        \t\t}\n\t\t}\n\t}\n\tif(this.popups.length === 0) {\n\t\tthis.rootElement.removeEventListener(\"click\",this,false);\n\t}\n};\n\n/*\nReturns true if the specified title and text identifies an active popup\n*/\nPopup.prototype.readPopupState = function(text) {\n\tvar popupLocationRegExp = /^\\((-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+)\\)$/;\n\treturn popupLocationRegExp.test(text);\n};\n\nexports.Popup = Popup;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/dom/scroller.js": {
            "title": "$:/core/modules/utils/dom/scroller.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/dom/scroller.js\ntype: application/javascript\nmodule-type: utils\n\nModule that creates a $tw.utils.Scroller object prototype that manages scrolling in the browser\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nEvent handler for when the `tm-scroll` event hits the document body\n*/\nvar PageScroller = function() {\n\tthis.idRequestFrame = null;\n\tthis.requestAnimationFrame = window.requestAnimationFrame ||\n\t\twindow.webkitRequestAnimationFrame ||\n\t\twindow.mozRequestAnimationFrame ||\n\t\tfunction(callback) {\n\t\t\treturn window.setTimeout(callback, 1000/60);\n\t\t};\n\tthis.cancelAnimationFrame = window.cancelAnimationFrame ||\n\t\twindow.webkitCancelAnimationFrame ||\n\t\twindow.webkitCancelRequestAnimationFrame ||\n\t\twindow.mozCancelAnimationFrame ||\n\t\twindow.mozCancelRequestAnimationFrame ||\n\t\tfunction(id) {\n\t\t\twindow.clearTimeout(id);\n\t\t};\n};\n\nPageScroller.prototype.isScrolling = function() {\n\treturn this.idRequestFrame !== null;\n}\n\nPageScroller.prototype.cancelScroll = function(srcWindow) {\n\tif(this.idRequestFrame) {\n\t\tthis.cancelAnimationFrame.call(srcWindow,this.idRequestFrame);\n\t\tthis.idRequestFrame = null;\n\t}\n};\n\n/*\nHandle an event\n*/\nPageScroller.prototype.handleEvent = function(event) {\n\tif(event.type === \"tm-scroll\") {\n\t\treturn this.scrollIntoView(event.target);\n\t}\n\treturn true;\n};\n\n/*\nHandle a scroll event hitting the page document\n*/\nPageScroller.prototype.scrollIntoView = function(element,callback) {\n\tvar self = this,\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t    srcWindow = element ? element.ownerDocument.defaultView : window;\n\t// Now get ready to scroll the body\n\tthis.cancelScroll(srcWindow);\n\tthis.startTime = Date.now();\n\t// Get the height of any position:fixed toolbars\n\tvar toolbar = srcWindow.document.querySelector(\".tc-adjust-top-of-scroll\"),\n\t\toffset = 0;\n\tif(toolbar) {\n\t\toffset = toolbar.offsetHeight;\n\t}\n\t// Get the client bounds of the element and adjust by the scroll position\n\tvar getBounds = function() {\n\t\t\tvar clientBounds = typeof callback === 'function' ? callback() : element.getBoundingClientRect(),\n\t\t\t\tscrollPosition = $tw.utils.getScrollPosition(srcWindow);\n\t\t\treturn {\n\t\t\t\tleft: clientBounds.left + scrollPosition.x,\n\t\t\t\ttop: clientBounds.top + scrollPosition.y - offset,\n\t\t\t\twidth: clientBounds.width,\n\t\t\t\theight: clientBounds.height\n\t\t\t};\n\t\t},\n\t\t// We'll consider the horizontal and vertical scroll directions separately via this function\n\t\t// targetPos/targetSize - position and size of the target element\n\t\t// currentPos/currentSize - position and size of the current scroll viewport\n\t\t// returns: new position of the scroll viewport\n\t\tgetEndPos = function(targetPos,targetSize,currentPos,currentSize) {\n\t\t\tvar newPos = targetPos;\n\t\t\t// If we are scrolling within 50 pixels of the top/left then snap to zero\n\t\t\tif(newPos < 50) {\n\t\t\t\tnewPos = 0;\n\t\t\t}\n\t\t\treturn newPos;\n\t\t},\n\t\tdrawFrame = function drawFrame() {\n\t\t\tvar t;\n\t\t\tif(duration <= 0) {\n\t\t\t\tt = 1;\n\t\t\t} else {\n\t\t\t\tt = ((Date.now()) - self.startTime) / duration;\t\n\t\t\t}\n\t\t\tif(t >= 1) {\n\t\t\t\tself.cancelScroll(srcWindow);\n\t\t\t\tt = 1;\n\t\t\t}\n\t\t\tt = $tw.utils.slowInSlowOut(t);\n\t\t\tvar scrollPosition = $tw.utils.getScrollPosition(srcWindow),\n\t\t\t\tbounds = getBounds(),\n\t\t\t\tendX = getEndPos(bounds.left,bounds.width,scrollPosition.x,srcWindow.innerWidth),\n\t\t\t\tendY = getEndPos(bounds.top,bounds.height,scrollPosition.y,srcWindow.innerHeight);\n\t\t\tsrcWindow.scrollTo(scrollPosition.x + (endX - scrollPosition.x) * t,scrollPosition.y + (endY - scrollPosition.y) * t);\n\t\t\tif(t < 1) {\n\t\t\t\tself.idRequestFrame = self.requestAnimationFrame.call(srcWindow,drawFrame);\n\t\t\t}\n\t\t};\n\tdrawFrame();\n};\n\nexports.PageScroller = PageScroller;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/edition-info.js": {
            "title": "$:/core/modules/utils/edition-info.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/edition-info.js\ntype: application/javascript\nmodule-type: utils-node\n\nInformation about the available editions\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar fs = require(\"fs\"),\n\tpath = require(\"path\");\n\nvar editionInfo;\n\nexports.getEditionInfo = function() {\n\tif(!editionInfo) {\n\t\t// Enumerate the edition paths\n\t\tvar editionPaths = $tw.getLibraryItemSearchPaths($tw.config.editionsPath,$tw.config.editionsEnvVar);\n\t\teditionInfo = {};\n\t\tfor(var editionIndex=0; editionIndex<editionPaths.length; editionIndex++) {\n\t\t\tvar editionPath = editionPaths[editionIndex];\n\t\t\t// Enumerate the folders\n\t\t\tvar entries = fs.readdirSync(editionPath);\n\t\t\tfor(var entryIndex=0; entryIndex<entries.length; entryIndex++) {\n\t\t\t\tvar entry = entries[entryIndex];\n\t\t\t\t// Check if directories have a valid tiddlywiki.info\n\t\t\t\tif(!editionInfo[entry] && $tw.utils.isDirectory(path.resolve(editionPath,entry))) {\n\t\t\t\t\tvar info;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tinfo = JSON.parse(fs.readFileSync(path.resolve(editionPath,entry,\"tiddlywiki.info\"),\"utf8\"));\n\t\t\t\t\t} catch(ex) {\n\t\t\t\t\t}\n\t\t\t\t\tif(info) {\n\t\t\t\t\t\teditionInfo[entry] = info;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn editionInfo;\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils-node"
        },
        "$:/core/modules/utils/fakedom.js": {
            "title": "$:/core/modules/utils/fakedom.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/fakedom.js\ntype: application/javascript\nmodule-type: global\n\nA barebones implementation of DOM interfaces needed by the rendering mechanism.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Sequence number used to enable us to track objects for testing\nvar sequenceNumber = null;\n\nvar bumpSequenceNumber = function(object) {\n\tif(sequenceNumber !== null) {\n\t\tobject.sequenceNumber = sequenceNumber++;\n\t}\n};\n\nvar TW_TextNode = function(text) {\n\tbumpSequenceNumber(this);\n\tthis.textContent = text + \"\";\n};\n\nObject.defineProperty(TW_TextNode.prototype, \"nodeType\", {\n\tget: function() {\n\t\treturn 3;\n\t}\n});\n\nObject.defineProperty(TW_TextNode.prototype, \"formattedTextContent\", {\n\tget: function() {\n\t\treturn this.textContent.replace(/(\\r?\\n)/g,\"\");\n\t}\n});\n\nvar TW_Element = function(tag,namespace) {\n\tbumpSequenceNumber(this);\n\tthis.isTiddlyWikiFakeDom = true;\n\tthis.tag = tag;\n\tthis.attributes = {};\n\tthis.isRaw = false;\n\tthis.children = [];\n\tthis._style = {};\n\tthis.namespaceURI = namespace || \"http://www.w3.org/1999/xhtml\";\n};\n\nObject.defineProperty(TW_Element.prototype, \"style\", {\n\tget: function() {\n\t\treturn this._style;\n\t},\n\tset: function(str) {\n\t\tvar self = this;\n\t\tstr = str || \"\";\n\t\t$tw.utils.each(str.split(\";\"),function(declaration) {\n\t\t\tvar parts = declaration.split(\":\"),\n\t\t\t\tname = $tw.utils.trim(parts[0]),\n\t\t\t\tvalue = $tw.utils.trim(parts[1]);\n\t\t\tif(name && value) {\n\t\t\t\tself._style[$tw.utils.convertStyleNameToPropertyName(name)] = value;\n\t\t\t}\n\t\t});\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"nodeType\", {\n\tget: function() {\n\t\treturn 1;\n\t}\n});\n\nTW_Element.prototype.getAttribute = function(name) {\n\tif(this.isRaw) {\n\t\tthrow \"Cannot getAttribute on a raw TW_Element\";\n\t}\n\treturn this.attributes[name];\n};\n\nTW_Element.prototype.setAttribute = function(name,value) {\n\tif(this.isRaw) {\n\t\tthrow \"Cannot setAttribute on a raw TW_Element\";\n\t}\n\tthis.attributes[name] = value + \"\";\n};\n\nTW_Element.prototype.setAttributeNS = function(namespace,name,value) {\n\tthis.setAttribute(name,value);\n};\n\nTW_Element.prototype.removeAttribute = function(name) {\n\tif(this.isRaw) {\n\t\tthrow \"Cannot removeAttribute on a raw TW_Element\";\n\t}\n\tif($tw.utils.hop(this.attributes,name)) {\n\t\tdelete this.attributes[name];\n\t}\n};\n\nTW_Element.prototype.appendChild = function(node) {\n\tthis.children.push(node);\n\tnode.parentNode = this;\n};\n\nTW_Element.prototype.insertBefore = function(node,nextSibling) {\n\tif(nextSibling) {\n\t\tvar p = this.children.indexOf(nextSibling);\n\t\tif(p !== -1) {\n\t\t\tthis.children.splice(p,0,node);\n\t\t\tnode.parentNode = this;\n\t\t} else {\n\t\t\tthis.appendChild(node);\n\t\t}\n\t} else {\n\t\tthis.appendChild(node);\n\t}\n};\n\nTW_Element.prototype.removeChild = function(node) {\n\tvar p = this.children.indexOf(node);\n\tif(p !== -1) {\n\t\tthis.children.splice(p,1);\n\t}\n};\n\nTW_Element.prototype.hasChildNodes = function() {\n\treturn !!this.children.length;\n};\n\nObject.defineProperty(TW_Element.prototype, \"childNodes\", {\n\tget: function() {\n\t\treturn this.children;\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"firstChild\", {\n\tget: function() {\n\t\treturn this.children[0];\n\t}\n});\n\nTW_Element.prototype.addEventListener = function(type,listener,useCapture) {\n\t// Do nothing\n};\n\nObject.defineProperty(TW_Element.prototype, \"tagName\", {\n\tget: function() {\n\t\treturn this.tag || \"\";\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"className\", {\n\tget: function() {\n\t\treturn this.attributes[\"class\"] || \"\";\n\t},\n\tset: function(value) {\n\t\tthis.attributes[\"class\"] = value + \"\";\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"value\", {\n\tget: function() {\n\t\treturn this.attributes.value || \"\";\n\t},\n\tset: function(value) {\n\t\tthis.attributes.value = value + \"\";\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"outerHTML\", {\n\tget: function() {\n\t\tvar output = [],attr,a,v;\n\t\toutput.push(\"<\",this.tag);\n\t\tif(this.attributes) {\n\t\t\tattr = [];\n\t\t\tfor(a in this.attributes) {\n\t\t\t\tattr.push(a);\n\t\t\t}\n\t\t\tattr.sort();\n\t\t\tfor(a=0; a<attr.length; a++) {\n\t\t\t\tv = this.attributes[attr[a]];\n\t\t\t\tif(v !== undefined) {\n\t\t\t\t\toutput.push(\" \",attr[a],\"=\\\"\",$tw.utils.htmlEncode(v),\"\\\"\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(this._style) {\n\t\t\tvar style = [];\n\t\t\tfor(var s in this._style) {\n\t\t\t\tstyle.push($tw.utils.convertPropertyNameToStyleName(s) + \":\" + this._style[s] + \";\");\n\t\t\t}\n\t\t\tif(style.length > 0) {\n\t\t\t\toutput.push(\" style=\\\"\",style.join(\"\"),\"\\\"\");\n\t\t\t}\n\t\t}\n\t\toutput.push(\">\");\n\t\tif($tw.config.htmlVoidElements.indexOf(this.tag) === -1) {\n\t\t\toutput.push(this.innerHTML);\n\t\t\toutput.push(\"</\",this.tag,\">\");\n\t\t}\n\t\treturn output.join(\"\");\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"innerHTML\", {\n\tget: function() {\n\t\tif(this.isRaw) {\n\t\t\treturn this.rawHTML;\n\t\t} else {\n\t\t\tvar b = [];\n\t\t\t$tw.utils.each(this.children,function(node) {\n\t\t\t\tif(node instanceof TW_Element) {\n\t\t\t\t\tb.push(node.outerHTML);\n\t\t\t\t} else if(node instanceof TW_TextNode) {\n\t\t\t\t\tb.push($tw.utils.htmlEncode(node.textContent));\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn b.join(\"\");\n\t\t}\n\t},\n\tset: function(value) {\n\t\tthis.isRaw = true;\n\t\tthis.rawHTML = value;\n\t\tthis.rawTextContent = null;\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"textInnerHTML\", {\n\tset: function(value) {\n\t\tif(this.isRaw) {\n\t\t\tthis.rawTextContent = value;\n\t\t} else {\n\t\t\tthrow \"Cannot set textInnerHTML of a non-raw TW_Element\";\n\t\t}\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"textContent\", {\n\tget: function() {\n\t\tif(this.isRaw) {\n\t\t\tif(this.rawTextContent === null) {\n\t\t\t\treturn \"\";\n\t\t\t} else {\n\t\t\t\treturn this.rawTextContent;\n\t\t\t}\n\t\t} else {\n\t\t\tvar b = [];\n\t\t\t$tw.utils.each(this.children,function(node) {\n\t\t\t\tb.push(node.textContent);\n\t\t\t});\n\t\t\treturn b.join(\"\");\n\t\t}\n\t},\n\tset: function(value) {\n\t\tthis.children = [new TW_TextNode(value)];\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"formattedTextContent\", {\n\tget: function() {\n\t\tif(this.isRaw) {\n\t\t\treturn \"\";\n\t\t} else {\n\t\t\tvar b = [],\n\t\t\t\tisBlock = $tw.config.htmlBlockElements.indexOf(this.tag) !== -1;\n\t\t\tif(isBlock) {\n\t\t\t\tb.push(\"\\n\");\n\t\t\t}\n\t\t\tif(this.tag === \"li\") {\n\t\t\t\tb.push(\"* \");\n\t\t\t}\n\t\t\t$tw.utils.each(this.children,function(node) {\n\t\t\t\tb.push(node.formattedTextContent);\n\t\t\t});\n\t\t\tif(isBlock) {\n\t\t\t\tb.push(\"\\n\");\n\t\t\t}\n\t\t\treturn b.join(\"\");\n\t\t}\n\t}\n});\n\nvar document = {\n\tsetSequenceNumber: function(value) {\n\t\tsequenceNumber = value;\n\t},\n\tcreateElementNS: function(namespace,tag) {\n\t\treturn new TW_Element(tag,namespace);\n\t},\n\tcreateElement: function(tag) {\n\t\treturn new TW_Element(tag);\n\t},\n\tcreateTextNode: function(text) {\n\t\treturn new TW_TextNode(text);\n\t},\n\tcompatMode: \"CSS1Compat\", // For KaTeX to know that we're not a browser in quirks mode\n\tisTiddlyWikiFakeDom: true\n};\n\nexports.fakeDocument = document;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/utils/filesystem.js": {
            "title": "$:/core/modules/utils/filesystem.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/filesystem.js\ntype: application/javascript\nmodule-type: utils-node\n\nFile system utilities\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar fs = require(\"fs\"),\n\tpath = require(\"path\");\n\n/*\nRecursively (and synchronously) copy a directory and all its content\n*/\nexports.copyDirectory = function(srcPath,dstPath) {\n\t// Remove any trailing path separators\n\tsrcPath = $tw.utils.removeTrailingSeparator(srcPath);\n\tdstPath = $tw.utils.removeTrailingSeparator(dstPath);\n\t// Create the destination directory\n\tvar err = $tw.utils.createDirectory(dstPath);\n\tif(err) {\n\t\treturn err;\n\t}\n\t// Function to copy a folder full of files\n\tvar copy = function(srcPath,dstPath) {\n\t\tvar srcStats = fs.lstatSync(srcPath),\n\t\t\tdstExists = fs.existsSync(dstPath);\n\t\tif(srcStats.isFile()) {\n\t\t\t$tw.utils.copyFile(srcPath,dstPath);\n\t\t} else if(srcStats.isDirectory()) {\n\t\t\tvar items = fs.readdirSync(srcPath);\n\t\t\tfor(var t=0; t<items.length; t++) {\n\t\t\t\tvar item = items[t],\n\t\t\t\t\terr = copy(srcPath + path.sep + item,dstPath + path.sep + item);\n\t\t\t\tif(err) {\n\t\t\t\t\treturn err;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\tcopy(srcPath,dstPath);\n\treturn null;\n};\n\n/*\nCopy a file\n*/\nvar FILE_BUFFER_LENGTH = 64 * 1024,\n\tfileBuffer;\n\nexports.copyFile = function(srcPath,dstPath) {\n\t// Create buffer if required\n\tif(!fileBuffer) {\n\t\tfileBuffer = Buffer.alloc(FILE_BUFFER_LENGTH);\n\t}\n\t// Create any directories in the destination\n\t$tw.utils.createDirectory(path.dirname(dstPath));\n\t// Copy the file\n\tvar srcFile = fs.openSync(srcPath,\"r\"),\n\t\tdstFile = fs.openSync(dstPath,\"w\"),\n\t\tbytesRead = 1,\n\t\tpos = 0;\n\twhile (bytesRead > 0) {\n\t\tbytesRead = fs.readSync(srcFile,fileBuffer,0,FILE_BUFFER_LENGTH,pos);\n\t\tfs.writeSync(dstFile,fileBuffer,0,bytesRead);\n\t\tpos += bytesRead;\n\t}\n\tfs.closeSync(srcFile);\n\tfs.closeSync(dstFile);\n\treturn null;\n};\n\n/*\nRemove trailing path separator\n*/\nexports.removeTrailingSeparator = function(dirPath) {\n\tvar len = dirPath.length;\n\tif(dirPath.charAt(len-1) === path.sep) {\n\t\tdirPath = dirPath.substr(0,len-1);\n\t}\n\treturn dirPath;\n};\n\n/*\nRecursively create a directory\n*/\nexports.createDirectory = function(dirPath) {\n\tif(dirPath.substr(dirPath.length-1,1) !== path.sep) {\n\t\tdirPath = dirPath + path.sep;\n\t}\n\tvar pos = 1;\n\tpos = dirPath.indexOf(path.sep,pos);\n\twhile(pos !== -1) {\n\t\tvar subDirPath = dirPath.substr(0,pos);\n\t\tif(!$tw.utils.isDirectory(subDirPath)) {\n\t\t\ttry {\n\t\t\t\tfs.mkdirSync(subDirPath);\n\t\t\t} catch(e) {\n\t\t\t\treturn \"Error creating directory '\" + subDirPath + \"'\";\n\t\t\t}\n\t\t}\n\t\tpos = dirPath.indexOf(path.sep,pos + 1);\n\t}\n\treturn null;\n};\n\n/*\nRecursively create directories needed to contain a specified file\n*/\nexports.createFileDirectories = function(filePath) {\n\treturn $tw.utils.createDirectory(path.dirname(filePath));\n};\n\n/*\nRecursively delete a directory\n*/\nexports.deleteDirectory = function(dirPath) {\n\tif(fs.existsSync(dirPath)) {\n\t\tvar entries = fs.readdirSync(dirPath);\n\t\tfor(var entryIndex=0; entryIndex<entries.length; entryIndex++) {\n\t\t\tvar currPath = dirPath + path.sep + entries[entryIndex];\n\t\t\tif(fs.lstatSync(currPath).isDirectory()) {\n\t\t\t\t$tw.utils.deleteDirectory(currPath);\n\t\t\t} else {\n\t\t\t\tfs.unlinkSync(currPath);\n\t\t\t}\n\t\t}\n\tfs.rmdirSync(dirPath);\n\t}\n\treturn null;\n};\n\n/*\nCheck if a path identifies a directory\n*/\nexports.isDirectory = function(dirPath) {\n\treturn fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory();\n};\n\n/*\nCheck if a path identifies a directory that is empty\n*/\nexports.isDirectoryEmpty = function(dirPath) {\n\tif(!$tw.utils.isDirectory(dirPath)) {\n\t\treturn false;\n\t}\n\tvar files = fs.readdirSync(dirPath),\n\t\tempty = true;\n\t$tw.utils.each(files,function(file,index) {\n\t\tif(file.charAt(0) !== \".\") {\n\t\t\tempty = false;\n\t\t}\n\t});\n\treturn empty;\n};\n\n/*\nRecursively delete a tree of empty directories\n*/\nexports.deleteEmptyDirs = function(dirpath,callback) {\n\tvar self = this;\n\tfs.readdir(dirpath,function(err,files) {\n\t\tif(err) {\n\t\t\treturn callback(err);\n\t\t}\n\t\tif(files.length > 0) {\n\t\t\treturn callback(null);\n\t\t}\n\t\tfs.rmdir(dirpath,function(err) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tself.deleteEmptyDirs(path.dirname(dirpath),callback);\n\t\t});\n\t});\n};\n\n/*\nCreate a fileInfo object for saving a tiddler:\n\tfilepath: the absolute path to the file containing the tiddler\n\ttype: the type of the tiddler file (NOT the type of the tiddler)\n\thasMetaFile: true if the file also has a companion .meta file\nOptions include:\n\tdirectory: absolute path of root directory to which we are saving\n\tpathFilters: optional array of filters to be used to generate the base path\n\twiki: optional wiki for evaluating the pathFilters\n*/\nexports.generateTiddlerFileInfo = function(tiddler,options) {\n\tvar fileInfo = {};\n\t// Check if the tiddler has any unsafe fields that can't be expressed in a .tid or .meta file: containing control characters, or leading/trailing whitespace\n\tvar hasUnsafeFields = false;\n\t$tw.utils.each(tiddler.getFieldStrings(),function(value,fieldName) {\n\t\tif(fieldName !== \"text\") {\n\t\t\thasUnsafeFields = hasUnsafeFields || /[\\x00-\\x1F]/mg.test(value);\n\t\t\thasUnsafeFields = hasUnsafeFields || ($tw.utils.trim(value) !== value);\n\t\t}\n\t});\n\t// Check for field values \n\tif(hasUnsafeFields) {\n\t\t// Save as a JSON file\n\t\tfileInfo.type = \"application/json\";\n\t\tfileInfo.hasMetaFile = false;\n\t} else {\n\t\t// Save as a .tid or a text/binary file plus a .meta file\n\t\tvar tiddlerType = tiddler.fields.type || \"text/vnd.tiddlywiki\";\n\t\tif(tiddlerType === \"text/vnd.tiddlywiki\") {\n\t\t\t// Save as a .tid file\n\t\t\tfileInfo.type = \"application/x-tiddler\";\n\t\t\tfileInfo.hasMetaFile = false;\n\t\t} else {\n\t\t\t// Save as a text/binary file and a .meta file\n\t\t\tfileInfo.type = tiddlerType;\n\t\t\tfileInfo.hasMetaFile = true;\n\t\t}\n\t}\n\t// Take the file extension from the tiddler content type\n\tvar contentTypeInfo = $tw.config.contentTypeInfo[fileInfo.type] || {extension: \"\"};\n\t// Generate the filepath\n\tfileInfo.filepath = $tw.utils.generateTiddlerFilepath(tiddler.fields.title,{\n\t\textension: contentTypeInfo.extension,\n\t\tdirectory: options.directory,\n\t\tpathFilters: options.pathFilters,\n\t\twiki: options.wiki\n\t});\n\treturn fileInfo;\n};\n\n/*\nGenerate the filepath for saving a tiddler\nOptions include:\n\textension: file extension to be added the finished filepath\n\tdirectory: absolute path of root directory to which we are saving\n\tpathFilters: optional array of filters to be used to generate the base path\n\twiki: optional wiki for evaluating the pathFilters\n*/\nexports.generateTiddlerFilepath = function(title,options) {\n\tvar self = this,\n\t\tdirectory = options.directory || \"\",\n\t\textension = options.extension || \"\",\n\t\tfilepath;\n\t// Check if any of the pathFilters applies\n\tif(options.pathFilters && options.wiki) {\n\t\t$tw.utils.each(options.pathFilters,function(filter) {\n\t\t\tif(!filepath) {\n\t\t\t\tvar source = options.wiki.makeTiddlerIterator([title]),\n\t\t\t\t\tresult = options.wiki.filterTiddlers(filter,null,source);\n\t\t\t\tif(result.length > 0) {\n\t\t\t\t\tfilepath = result[0];\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\t// If not, generate a base pathname\n\tif(!filepath) {\n\t\tfilepath = title;\n\t\t// If the filepath already ends in the extension then remove it\n\t\tif(filepath.substring(filepath.length - extension.length) === extension) {\n\t\t\tfilepath = filepath.substring(0,filepath.length - extension.length);\n\t\t}\n\t\t// Remove any forward or backward slashes so we don't create directories\n\t\tfilepath = filepath.replace(/\\/|\\\\/g,\"_\");\n\t}\n\t// Don't let the filename start with a dot because such files are invisible on *nix\n\tfilepath = filepath.replace(/^\\./g,\"_\");\n\t// Remove any characters that can't be used in cross-platform filenames\n\tfilepath = $tw.utils.transliterate(filepath.replace(/<|>|\\:|\\\"|\\||\\?|\\*|\\^/g,\"_\"));\n\t// Truncate the filename if it is too long\n\tif(filepath.length > 200) {\n\t\tfilepath = filepath.substr(0,200);\n\t}\n\t// If the resulting filename is blank (eg because the title is just punctuation characters)\n\tif(!filepath) {\n\t\t// ...then just use the character codes of the title\n\t\tfilepath = \"\";\t\n\t\t$tw.utils.each(title.split(\"\"),function(char) {\n\t\t\tif(filepath) {\n\t\t\t\tfilepath += \"-\";\n\t\t\t}\n\t\t\tfilepath += char.charCodeAt(0).toString();\n\t\t});\n\t}\n\t// Add a uniquifier if the file already exists\n\tvar fullPath,\n\t\tcount = 0;\n\tdo {\n\t\tfullPath = path.resolve(directory,filepath + (count ? \"_\" + count : \"\") + extension);\n\t\tcount++;\n\t} while(fs.existsSync(fullPath));\n\t// Return the full path to the file\n\treturn fullPath;\n};\n\n/*\nSave a tiddler to a file described by the fileInfo:\n\tfilepath: the absolute path to the file containing the tiddler\n\ttype: the type of the tiddler file (NOT the type of the tiddler)\n\thasMetaFile: true if the file also has a companion .meta file\n*/\nexports.saveTiddlerToFile = function(tiddler,fileInfo,callback) {\n\t$tw.utils.createDirectory(path.dirname(fileInfo.filepath));\n\tif(fileInfo.hasMetaFile) {\n\t\t// Save the tiddler as a separate body and meta file\n\t\tvar typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || \"text/plain\"] || {encoding: \"utf8\"};\n\t\tfs.writeFile(fileInfo.filepath,tiddler.fields.text,typeInfo.encoding,function(err) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tfs.writeFile(fileInfo.filepath + \".meta\",tiddler.getFieldStringBlock({exclude: [\"text\",\"bag\"]}),\"utf8\",callback);\n\t\t});\n\t} else {\n\t\t// Save the tiddler as a self contained templated file\n\t\tif(fileInfo.type === \"application/x-tiddler\") {\n\t\t\tfs.writeFile(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: [\"text\",\"bag\"]}) + (!!tiddler.fields.text ? \"\\n\\n\" + tiddler.fields.text : \"\"),\"utf8\",callback);\n\t\t} else {\n\t\t\tfs.writeFile(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: [\"bag\"]})],null,$tw.config.preferences.jsonSpaces),\"utf8\",callback);\n\t\t}\n\t}\n};\n\n/*\nSave a tiddler to a file described by the fileInfo:\n\tfilepath: the absolute path to the file containing the tiddler\n\ttype: the type of the tiddler file (NOT the type of the tiddler)\n\thasMetaFile: true if the file also has a companion .meta file\n*/\nexports.saveTiddlerToFileSync = function(tiddler,fileInfo) {\n\t$tw.utils.createDirectory(path.dirname(fileInfo.filepath));\n\tif(fileInfo.hasMetaFile) {\n\t\t// Save the tiddler as a separate body and meta file\n\t\tvar typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || \"text/plain\"] || {encoding: \"utf8\"};\n\t\tfs.writeFileSync(fileInfo.filepath,tiddler.fields.text,typeInfo.encoding);\n\t\tfs.writeFileSync(fileInfo.filepath + \".meta\",tiddler.getFieldStringBlock({exclude: [\"text\",\"bag\"]}),\"utf8\");\n\t} else {\n\t\t// Save the tiddler as a self contained templated file\n\t\tif(fileInfo.type === \"application/x-tiddler\") {\n\t\t\tfs.writeFileSync(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: [\"text\",\"bag\"]}) + (!!tiddler.fields.text ? \"\\n\\n\" + tiddler.fields.text : \"\"),\"utf8\");\n\t\t} else {\n\t\t\tfs.writeFileSync(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: [\"bag\"]})],null,$tw.config.preferences.jsonSpaces),\"utf8\");\n\t\t}\n\t}\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils-node"
        },
        "$:/core/modules/utils/logger.js": {
            "title": "$:/core/modules/utils/logger.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/logger.js\ntype: application/javascript\nmodule-type: utils\n\nA basic logging implementation\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar ALERT_TAG = \"$:/tags/Alert\";\n\n/*\nMake a new logger\n*/\nfunction Logger(componentName,options) {\n\toptions = options || {};\n\tthis.componentName = componentName || \"\";\n\tthis.colour = options.colour || \"white\";\n\tthis.enable = \"enable\" in options ? options.enable : true;\n\tthis.save = \"save\" in options ? options.save : true;\n\tthis.saveLimit = options.saveLimit || 100 * 1024;\n\tthis.saveBufferLogger = this;\n\tthis.buffer = \"\";\n\tthis.alertCount = 0;\n}\n\nLogger.prototype.setSaveBuffer = function(logger) {\n\tthis.saveBufferLogger = logger;\n};\n\n/*\nLog a message\n*/\nLogger.prototype.log = function(/* args */) {\n\tvar self = this;\n\tif(this.enable) {\n\t\tif(this.saveBufferLogger.save) {\n\t\t\tthis.saveBufferLogger.buffer += $tw.utils.formatDateString(new Date(),\"YYYY MM DD 0hh:0mm:0ss.0XXX\") + \":\";\n\t\t\t$tw.utils.each(Array.prototype.slice.call(arguments,0),function(arg,index) {\n\t\t\t\tself.saveBufferLogger.buffer += \" \" + arg;\n\t\t\t});\n\t\t\tthis.saveBufferLogger.buffer += \"\\n\";\n\t\t\tthis.saveBufferLogger.buffer = this.saveBufferLogger.buffer.slice(-this.saveBufferLogger.saveLimit);\t\t\t\n\t\t}\n\t\tif(console !== undefined && console.log !== undefined) {\n\t\t\treturn Function.apply.call(console.log, console, [$tw.utils.terminalColour(this.colour),this.componentName + \":\"].concat(Array.prototype.slice.call(arguments,0)).concat($tw.utils.terminalColour()));\n\t\t}\n\t} \n};\n\n/*\nRead the message buffer\n*/\nLogger.prototype.getBuffer = function() {\n\treturn this.saveBufferLogger.buffer;\n};\n\n/*\nLog a structure as a table\n*/\nLogger.prototype.table = function(value) {\n\t(console.table || console.log)(value);\n};\n\n/*\nAlert a message\n*/\nLogger.prototype.alert = function(/* args */) {\n\tif(this.enable) {\n\t\t// Prepare the text of the alert\n\t\tvar text = Array.prototype.join.call(arguments,\" \");\n\t\t// Create alert tiddlers in the browser\n\t\tif($tw.browser) {\n\t\t\t// Check if there is an existing alert with the same text and the same component\n\t\t\tvar existingAlerts = $tw.wiki.getTiddlersWithTag(ALERT_TAG),\n\t\t\t\talertFields,\n\t\t\t\texistingCount,\n\t\t\t\tself = this;\n\t\t\t$tw.utils.each(existingAlerts,function(title) {\n\t\t\t\tvar tiddler = $tw.wiki.getTiddler(title);\n\t\t\t\tif(tiddler.fields.text === text && tiddler.fields.component === self.componentName && tiddler.fields.modified && (!alertFields || tiddler.fields.modified < alertFields.modified)) {\n\t\t\t\t\t\talertFields = $tw.utils.extend({},tiddler.fields);\n\t\t\t\t}\n\t\t\t});\n\t\t\tif(alertFields) {\n\t\t\t\texistingCount = alertFields.count || 1;\n\t\t\t} else {\n\t\t\t\talertFields = {\n\t\t\t\t\ttitle: $tw.wiki.generateNewTitle(\"$:/temp/alerts/alert\",{prefix: \"\"}),\n\t\t\t\t\ttext: text,\n\t\t\t\t\ttags: [ALERT_TAG],\n\t\t\t\t\tcomponent: this.componentName\n\t\t\t\t};\n\t\t\t\texistingCount = 0;\n\t\t\t\tthis.alertCount += 1;\n\t\t\t}\n\t\t\talertFields.modified = new Date();\n\t\t\tif(++existingCount > 1) {\n\t\t\t\talertFields.count = existingCount;\n\t\t\t} else {\n\t\t\t\talertFields.count = undefined;\n\t\t\t}\n\t\t\t$tw.wiki.addTiddler(new $tw.Tiddler(alertFields));\n\t\t\t// Log the alert as well\n\t\t\tthis.log.apply(this,Array.prototype.slice.call(arguments,0));\n\t\t} else {\n\t\t\t// Print an orange message to the console if not in the browser\n\t\t\tconsole.error(\"\\x1b[1;33m\" + text + \"\\x1b[0m\");\n\t\t}\t\t\n\t}\n};\n\n/*\nClear outstanding alerts\n*/\nLogger.prototype.clearAlerts = function() {\n\tvar self = this;\n\tif($tw.browser && this.alertCount > 0) {\n\t\t$tw.utils.each($tw.wiki.getTiddlersWithTag(ALERT_TAG),function(title) {\n\t\t\tvar tiddler = $tw.wiki.getTiddler(title);\n\t\t\tif(tiddler.fields.component === self.componentName) {\n\t\t\t\t$tw.wiki.deleteTiddler(title);\n\t\t\t}\n\t\t});\n\t\tthis.alertCount = 0;\n\t}\n};\n\nexports.Logger = Logger;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/parsetree.js": {
            "title": "$:/core/modules/utils/parsetree.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/parsetree.js\ntype: application/javascript\nmodule-type: utils\n\nParse tree utility functions.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.addAttributeToParseTreeNode = function(node,name,value) {\n\tnode.attributes = node.attributes || {};\n\tnode.attributes[name] = {type: \"string\", value: value};\n};\n\nexports.getAttributeValueFromParseTreeNode = function(node,name,defaultValue) {\n\tif(node.attributes && node.attributes[name] && node.attributes[name].value !== undefined) {\n\t\treturn node.attributes[name].value;\n\t}\n\treturn defaultValue;\n};\n\nexports.addClassToParseTreeNode = function(node,classString) {\n\tvar classes = [];\n\tnode.attributes = node.attributes || {};\n\tnode.attributes[\"class\"] = node.attributes[\"class\"] || {type: \"string\", value: \"\"};\n\tif(node.attributes[\"class\"].type === \"string\") {\n\t\tif(node.attributes[\"class\"].value !== \"\") {\n\t\t\tclasses = node.attributes[\"class\"].value.split(\" \");\n\t\t}\n\t\tif(classString !== \"\") {\n\t\t\t$tw.utils.pushTop(classes,classString.split(\" \"));\n\t\t}\n\t\tnode.attributes[\"class\"].value = classes.join(\" \");\n\t}\n};\n\nexports.addStyleToParseTreeNode = function(node,name,value) {\n\t\tnode.attributes = node.attributes || {};\n\t\tnode.attributes.style = node.attributes.style || {type: \"string\", value: \"\"};\n\t\tif(node.attributes.style.type === \"string\") {\n\t\t\tnode.attributes.style.value += name + \":\" + value + \";\";\n\t\t}\n};\n\nexports.findParseTreeNode = function(nodeArray,search) {\n\tfor(var t=0; t<nodeArray.length; t++) {\n\t\tif(nodeArray[t].type === search.type && nodeArray[t].tag === search.tag) {\n\t\t\treturn nodeArray[t];\n\t\t}\n\t}\n\treturn undefined;\n};\n\n/*\nHelper to get the text of a parse tree node or array of nodes\n*/\nexports.getParseTreeText = function getParseTreeText(tree) {\n\tvar output = [];\n\tif($tw.utils.isArray(tree)) {\n\t\t$tw.utils.each(tree,function(node) {\n\t\t\toutput.push(getParseTreeText(node));\n\t\t});\n\t} else {\n\t\tif(tree.type === \"text\") {\n\t\t\toutput.push(tree.text);\n\t\t}\n\t\tif(tree.children) {\n\t\t\treturn getParseTreeText(tree.children);\n\t\t}\n\t}\n\treturn output.join(\"\");\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/performance.js": {
            "title": "$:/core/modules/utils/performance.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/performance.js\ntype: application/javascript\nmodule-type: global\n\nPerformance measurement.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nfunction Performance(enabled) {\n\tthis.enabled = !!enabled;\n\tthis.measures = {}; // Hashmap by measurement name of {time:, invocations:}\n\tthis.logger = new $tw.utils.Logger(\"performance\");\n\tthis.showGreeting();\n}\n\nPerformance.prototype.showGreeting = function() {\n\tif($tw.browser) {\n\t\tthis.logger.log(\"Execute $tw.perf.log(); to see filter execution timings\");\t\t\n\t}\n};\n\n/*\nWrap performance reporting around a top level function\n*/\nPerformance.prototype.report = function(name,fn) {\n\tvar self = this;\n\tif(this.enabled) {\n\t\treturn function() {\n\t\t\tvar startTime = $tw.utils.timer(),\n\t\t\t\tresult = fn.apply(this,arguments);\n\t\t\tself.logger.log(name + \": \" + $tw.utils.timer(startTime).toFixed(2) + \"ms\");\n\t\t\treturn result;\n\t\t};\n\t} else {\n\t\treturn fn;\n\t}\n};\n\nPerformance.prototype.log = function() {\n\tvar self = this,\n\t\ttotalTime = 0,\n\t\torderedMeasures = Object.keys(this.measures).sort(function(a,b) {\n\t\t\tif(self.measures[a].time > self.measures[b].time) {\n\t\t\t\treturn -1;\n\t\t\t} else if (self.measures[a].time < self.measures[b].time) {\n\t\t\t\treturn + 1;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t});\n\t$tw.utils.each(orderedMeasures,function(name) {\n\t\ttotalTime += self.measures[name].time;\n\t});\n\tvar results = []\n\t$tw.utils.each(orderedMeasures,function(name) {\n\t\tvar measure = self.measures[name];\n\t\tresults.push({name: name,invocations: measure.invocations, avgTime: measure.time / measure.invocations, totalTime: measure.time, percentTime: (measure.time / totalTime) * 100})\n\t});\n\tself.logger.table(results);\n};\n\n/*\nWrap performance measurements around a subfunction\n*/\nPerformance.prototype.measure = function(name,fn) {\n\tvar self = this;\n\tif(this.enabled) {\n\t\treturn function() {\n\t\t\tvar startTime = $tw.utils.timer(),\n\t\t\t\tresult = fn.apply(this,arguments);\n\t\t\tif(!(name in self.measures)) {\n\t\t\t\tself.measures[name] = {time: 0, invocations: 0};\n\t\t\t}\n\t\t\tself.measures[name].time += $tw.utils.timer(startTime);\n\t\t\tself.measures[name].invocations++;\n\t\t\treturn result;\n\t\t};\n\t} else {\n\t\treturn fn;\n\t}\n};\n\nexports.Performance = Performance;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "global"
        },
        "$:/core/modules/utils/pluginmaker.js": {
            "title": "$:/core/modules/utils/pluginmaker.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/pluginmaker.js\ntype: application/javascript\nmodule-type: utils\n\nA quick and dirty way to pack up plugins within the browser.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nRepack a plugin, and then delete any non-shadow payload tiddlers\n*/\nexports.repackPlugin = function(title,additionalTiddlers,excludeTiddlers) {\n\tadditionalTiddlers = additionalTiddlers || [];\n\texcludeTiddlers = excludeTiddlers || [];\n\t// Get the plugin tiddler\n\tvar pluginTiddler = $tw.wiki.getTiddler(title);\n\tif(!pluginTiddler) {\n\t\tthrow \"No such tiddler as \" + title;\n\t}\n\t// Extract the JSON\n\tvar jsonPluginTiddler;\n\ttry {\n\t\tjsonPluginTiddler = JSON.parse(pluginTiddler.fields.text);\n\t} catch(e) {\n\t\tthrow \"Cannot parse plugin tiddler \" + title + \"\\n\" + $tw.language.getString(\"Error/Caption\") + \": \" + e;\n\t}\n\t// Get the list of tiddlers\n\tvar tiddlers = Object.keys(jsonPluginTiddler.tiddlers);\n\t// Add the additional tiddlers\n\t$tw.utils.pushTop(tiddlers,additionalTiddlers);\n\t// Remove any excluded tiddlers\n\tfor(var t=tiddlers.length-1; t>=0; t--) {\n\t\tif(excludeTiddlers.indexOf(tiddlers[t]) !== -1) {\n\t\t\ttiddlers.splice(t,1);\n\t\t}\n\t}\n\t// Pack up the tiddlers into a block of JSON\n\tvar plugins = {};\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = $tw.wiki.getTiddler(title),\n\t\t\tfields = {};\n\t\t$tw.utils.each(tiddler.fields,function (value,name) {\n\t\t\tfields[name] = tiddler.getFieldString(name);\n\t\t});\n\t\tplugins[title] = fields;\n\t});\n\t// Retrieve and bump the version number\n\tvar pluginVersion = $tw.utils.parseVersion(pluginTiddler.getFieldString(\"version\") || \"0.0.0\") || {\n\t\t\tmajor: \"0\",\n\t\t\tminor: \"0\",\n\t\t\tpatch: \"0\"\n\t\t};\n\tpluginVersion.patch++;\n\tvar version = pluginVersion.major + \".\" + pluginVersion.minor + \".\" + pluginVersion.patch;\n\tif(pluginVersion.prerelease) {\n\t\tversion += \"-\" + pluginVersion.prerelease;\n\t}\n\tif(pluginVersion.build) {\n\t\tversion += \"+\" + pluginVersion.build;\n\t}\n\t// Save the tiddler\n\t$tw.wiki.addTiddler(new $tw.Tiddler(pluginTiddler,{text: JSON.stringify({tiddlers: plugins},null,4), version: version}));\n\t// Delete any non-shadow constituent tiddlers\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tif($tw.wiki.tiddlerExists(title)) {\n\t\t\t$tw.wiki.deleteTiddler(title);\n\t\t}\n\t});\n\t// Trigger an autosave\n\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n\t// Return a heartwarming confirmation\n\treturn \"Plugin \" + title + \" successfully saved\";\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/transliterate.js": {
            "title": "$:/core/modules/utils/transliterate.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/transliterate.js\ntype: application/javascript\nmodule-type: utils\n\nTransliteration static utility functions.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nTransliterate string to ASCII\n\n(Some pairs taken from http://semplicewebsites.com/removing-accents-javascript)\n*/\nexports.transliterationPairs = {\n\t\"Á\":\"A\",\n\t\"Ă\":\"A\",\n\t\"Ắ\":\"A\",\n\t\"Ặ\":\"A\",\n\t\"Ằ\":\"A\",\n\t\"Ẳ\":\"A\",\n\t\"Ẵ\":\"A\",\n\t\"Ǎ\":\"A\",\n\t\"Â\":\"A\",\n\t\"Ấ\":\"A\",\n\t\"Ậ\":\"A\",\n\t\"Ầ\":\"A\",\n\t\"Ẩ\":\"A\",\n\t\"Ẫ\":\"A\",\n\t\"Ä\":\"A\",\n\t\"Ǟ\":\"A\",\n\t\"Ȧ\":\"A\",\n\t\"Ǡ\":\"A\",\n\t\"Ạ\":\"A\",\n\t\"Ȁ\":\"A\",\n\t\"À\":\"A\",\n\t\"Ả\":\"A\",\n\t\"Ȃ\":\"A\",\n\t\"Ā\":\"A\",\n\t\"Ą\":\"A\",\n\t\"Å\":\"A\",\n\t\"Ǻ\":\"A\",\n\t\"Ḁ\":\"A\",\n\t\"Ⱥ\":\"A\",\n\t\"Ã\":\"A\",\n\t\"Ꜳ\":\"AA\",\n\t\"Æ\":\"AE\",\n\t\"Ǽ\":\"AE\",\n\t\"Ǣ\":\"AE\",\n\t\"Ꜵ\":\"AO\",\n\t\"Ꜷ\":\"AU\",\n\t\"Ꜹ\":\"AV\",\n\t\"Ꜻ\":\"AV\",\n\t\"Ꜽ\":\"AY\",\n\t\"Ḃ\":\"B\",\n\t\"Ḅ\":\"B\",\n\t\"Ɓ\":\"B\",\n\t\"Ḇ\":\"B\",\n\t\"Ƀ\":\"B\",\n\t\"Ƃ\":\"B\",\n\t\"Ć\":\"C\",\n\t\"Č\":\"C\",\n\t\"Ç\":\"C\",\n\t\"Ḉ\":\"C\",\n\t\"Ĉ\":\"C\",\n\t\"Ċ\":\"C\",\n\t\"Ƈ\":\"C\",\n\t\"Ȼ\":\"C\",\n\t\"Ď\":\"D\",\n\t\"Ḑ\":\"D\",\n\t\"Ḓ\":\"D\",\n\t\"Ḋ\":\"D\",\n\t\"Ḍ\":\"D\",\n\t\"Ɗ\":\"D\",\n\t\"Ḏ\":\"D\",\n\t\"Dz\":\"D\",\n\t\"Dž\":\"D\",\n\t\"Đ\":\"D\",\n\t\"Ƌ\":\"D\",\n\t\"DZ\":\"DZ\",\n\t\"DŽ\":\"DZ\",\n\t\"É\":\"E\",\n\t\"Ĕ\":\"E\",\n\t\"Ě\":\"E\",\n\t\"Ȩ\":\"E\",\n\t\"Ḝ\":\"E\",\n\t\"Ê\":\"E\",\n\t\"Ế\":\"E\",\n\t\"Ệ\":\"E\",\n\t\"Ề\":\"E\",\n\t\"Ể\":\"E\",\n\t\"Ễ\":\"E\",\n\t\"Ḙ\":\"E\",\n\t\"Ë\":\"E\",\n\t\"Ė\":\"E\",\n\t\"Ẹ\":\"E\",\n\t\"Ȅ\":\"E\",\n\t\"È\":\"E\",\n\t\"Ẻ\":\"E\",\n\t\"Ȇ\":\"E\",\n\t\"Ē\":\"E\",\n\t\"Ḗ\":\"E\",\n\t\"Ḕ\":\"E\",\n\t\"Ę\":\"E\",\n\t\"Ɇ\":\"E\",\n\t\"Ẽ\":\"E\",\n\t\"Ḛ\":\"E\",\n\t\"Ꝫ\":\"ET\",\n\t\"Ḟ\":\"F\",\n\t\"Ƒ\":\"F\",\n\t\"Ǵ\":\"G\",\n\t\"Ğ\":\"G\",\n\t\"Ǧ\":\"G\",\n\t\"Ģ\":\"G\",\n\t\"Ĝ\":\"G\",\n\t\"Ġ\":\"G\",\n\t\"Ɠ\":\"G\",\n\t\"Ḡ\":\"G\",\n\t\"Ǥ\":\"G\",\n\t\"Ḫ\":\"H\",\n\t\"Ȟ\":\"H\",\n\t\"Ḩ\":\"H\",\n\t\"Ĥ\":\"H\",\n\t\"Ⱨ\":\"H\",\n\t\"Ḧ\":\"H\",\n\t\"Ḣ\":\"H\",\n\t\"Ḥ\":\"H\",\n\t\"Ħ\":\"H\",\n\t\"Í\":\"I\",\n\t\"Ĭ\":\"I\",\n\t\"Ǐ\":\"I\",\n\t\"Î\":\"I\",\n\t\"Ï\":\"I\",\n\t\"Ḯ\":\"I\",\n\t\"İ\":\"I\",\n\t\"Ị\":\"I\",\n\t\"Ȉ\":\"I\",\n\t\"Ì\":\"I\",\n\t\"Ỉ\":\"I\",\n\t\"Ȋ\":\"I\",\n\t\"Ī\":\"I\",\n\t\"Į\":\"I\",\n\t\"Ɨ\":\"I\",\n\t\"Ĩ\":\"I\",\n\t\"Ḭ\":\"I\",\n\t\"Ꝺ\":\"D\",\n\t\"Ꝼ\":\"F\",\n\t\"Ᵹ\":\"G\",\n\t\"Ꞃ\":\"R\",\n\t\"Ꞅ\":\"S\",\n\t\"Ꞇ\":\"T\",\n\t\"Ꝭ\":\"IS\",\n\t\"Ĵ\":\"J\",\n\t\"Ɉ\":\"J\",\n\t\"Ḱ\":\"K\",\n\t\"Ǩ\":\"K\",\n\t\"Ķ\":\"K\",\n\t\"Ⱪ\":\"K\",\n\t\"Ꝃ\":\"K\",\n\t\"Ḳ\":\"K\",\n\t\"Ƙ\":\"K\",\n\t\"Ḵ\":\"K\",\n\t\"Ꝁ\":\"K\",\n\t\"Ꝅ\":\"K\",\n\t\"Ĺ\":\"L\",\n\t\"Ƚ\":\"L\",\n\t\"Ľ\":\"L\",\n\t\"Ļ\":\"L\",\n\t\"Ḽ\":\"L\",\n\t\"Ḷ\":\"L\",\n\t\"Ḹ\":\"L\",\n\t\"Ⱡ\":\"L\",\n\t\"Ꝉ\":\"L\",\n\t\"Ḻ\":\"L\",\n\t\"Ŀ\":\"L\",\n\t\"Ɫ\":\"L\",\n\t\"Lj\":\"L\",\n\t\"Ł\":\"L\",\n\t\"LJ\":\"LJ\",\n\t\"Ḿ\":\"M\",\n\t\"Ṁ\":\"M\",\n\t\"Ṃ\":\"M\",\n\t\"Ɱ\":\"M\",\n\t\"Ń\":\"N\",\n\t\"Ň\":\"N\",\n\t\"Ņ\":\"N\",\n\t\"Ṋ\":\"N\",\n\t\"Ṅ\":\"N\",\n\t\"Ṇ\":\"N\",\n\t\"Ǹ\":\"N\",\n\t\"Ɲ\":\"N\",\n\t\"Ṉ\":\"N\",\n\t\"Ƞ\":\"N\",\n\t\"Nj\":\"N\",\n\t\"Ñ\":\"N\",\n\t\"NJ\":\"NJ\",\n\t\"Ó\":\"O\",\n\t\"Ŏ\":\"O\",\n\t\"Ǒ\":\"O\",\n\t\"Ô\":\"O\",\n\t\"Ố\":\"O\",\n\t\"Ộ\":\"O\",\n\t\"Ồ\":\"O\",\n\t\"Ổ\":\"O\",\n\t\"Ỗ\":\"O\",\n\t\"Ö\":\"O\",\n\t\"Ȫ\":\"O\",\n\t\"Ȯ\":\"O\",\n\t\"Ȱ\":\"O\",\n\t\"Ọ\":\"O\",\n\t\"Ő\":\"O\",\n\t\"Ȍ\":\"O\",\n\t\"Ò\":\"O\",\n\t\"Ỏ\":\"O\",\n\t\"Ơ\":\"O\",\n\t\"Ớ\":\"O\",\n\t\"Ợ\":\"O\",\n\t\"Ờ\":\"O\",\n\t\"Ở\":\"O\",\n\t\"Ỡ\":\"O\",\n\t\"Ȏ\":\"O\",\n\t\"Ꝋ\":\"O\",\n\t\"Ꝍ\":\"O\",\n\t\"Ō\":\"O\",\n\t\"Ṓ\":\"O\",\n\t\"Ṑ\":\"O\",\n\t\"Ɵ\":\"O\",\n\t\"Ǫ\":\"O\",\n\t\"Ǭ\":\"O\",\n\t\"Ø\":\"O\",\n\t\"Ǿ\":\"O\",\n\t\"Õ\":\"O\",\n\t\"Ṍ\":\"O\",\n\t\"Ṏ\":\"O\",\n\t\"Ȭ\":\"O\",\n\t\"Ƣ\":\"OI\",\n\t\"Ꝏ\":\"OO\",\n\t\"Ɛ\":\"E\",\n\t\"Ɔ\":\"O\",\n\t\"Ȣ\":\"OU\",\n\t\"Ṕ\":\"P\",\n\t\"Ṗ\":\"P\",\n\t\"Ꝓ\":\"P\",\n\t\"Ƥ\":\"P\",\n\t\"Ꝕ\":\"P\",\n\t\"Ᵽ\":\"P\",\n\t\"Ꝑ\":\"P\",\n\t\"Ꝙ\":\"Q\",\n\t\"Ꝗ\":\"Q\",\n\t\"Ŕ\":\"R\",\n\t\"Ř\":\"R\",\n\t\"Ŗ\":\"R\",\n\t\"Ṙ\":\"R\",\n\t\"Ṛ\":\"R\",\n\t\"Ṝ\":\"R\",\n\t\"Ȑ\":\"R\",\n\t\"Ȓ\":\"R\",\n\t\"Ṟ\":\"R\",\n\t\"Ɍ\":\"R\",\n\t\"Ɽ\":\"R\",\n\t\"Ꜿ\":\"C\",\n\t\"Ǝ\":\"E\",\n\t\"Ś\":\"S\",\n\t\"Ṥ\":\"S\",\n\t\"Š\":\"S\",\n\t\"Ṧ\":\"S\",\n\t\"Ş\":\"S\",\n\t\"Ŝ\":\"S\",\n\t\"Ș\":\"S\",\n\t\"Ṡ\":\"S\",\n\t\"Ṣ\":\"S\",\n\t\"Ṩ\":\"S\",\n\t\"Ť\":\"T\",\n\t\"Ţ\":\"T\",\n\t\"Ṱ\":\"T\",\n\t\"Ț\":\"T\",\n\t\"Ⱦ\":\"T\",\n\t\"Ṫ\":\"T\",\n\t\"Ṭ\":\"T\",\n\t\"Ƭ\":\"T\",\n\t\"Ṯ\":\"T\",\n\t\"Ʈ\":\"T\",\n\t\"Ŧ\":\"T\",\n\t\"Ɐ\":\"A\",\n\t\"Ꞁ\":\"L\",\n\t\"Ɯ\":\"M\",\n\t\"Ʌ\":\"V\",\n\t\"Ꜩ\":\"TZ\",\n\t\"Ú\":\"U\",\n\t\"Ŭ\":\"U\",\n\t\"Ǔ\":\"U\",\n\t\"Û\":\"U\",\n\t\"Ṷ\":\"U\",\n\t\"Ü\":\"U\",\n\t\"Ǘ\":\"U\",\n\t\"Ǚ\":\"U\",\n\t\"Ǜ\":\"U\",\n\t\"Ǖ\":\"U\",\n\t\"Ṳ\":\"U\",\n\t\"Ụ\":\"U\",\n\t\"Ű\":\"U\",\n\t\"Ȕ\":\"U\",\n\t\"Ù\":\"U\",\n\t\"Ủ\":\"U\",\n\t\"Ư\":\"U\",\n\t\"Ứ\":\"U\",\n\t\"Ự\":\"U\",\n\t\"Ừ\":\"U\",\n\t\"Ử\":\"U\",\n\t\"Ữ\":\"U\",\n\t\"Ȗ\":\"U\",\n\t\"Ū\":\"U\",\n\t\"Ṻ\":\"U\",\n\t\"Ų\":\"U\",\n\t\"Ů\":\"U\",\n\t\"Ũ\":\"U\",\n\t\"Ṹ\":\"U\",\n\t\"Ṵ\":\"U\",\n\t\"Ꝟ\":\"V\",\n\t\"Ṿ\":\"V\",\n\t\"Ʋ\":\"V\",\n\t\"Ṽ\":\"V\",\n\t\"Ꝡ\":\"VY\",\n\t\"Ẃ\":\"W\",\n\t\"Ŵ\":\"W\",\n\t\"Ẅ\":\"W\",\n\t\"Ẇ\":\"W\",\n\t\"Ẉ\":\"W\",\n\t\"Ẁ\":\"W\",\n\t\"Ⱳ\":\"W\",\n\t\"Ẍ\":\"X\",\n\t\"Ẋ\":\"X\",\n\t\"Ý\":\"Y\",\n\t\"Ŷ\":\"Y\",\n\t\"Ÿ\":\"Y\",\n\t\"Ẏ\":\"Y\",\n\t\"Ỵ\":\"Y\",\n\t\"Ỳ\":\"Y\",\n\t\"Ƴ\":\"Y\",\n\t\"Ỷ\":\"Y\",\n\t\"Ỿ\":\"Y\",\n\t\"Ȳ\":\"Y\",\n\t\"Ɏ\":\"Y\",\n\t\"Ỹ\":\"Y\",\n\t\"Ź\":\"Z\",\n\t\"Ž\":\"Z\",\n\t\"Ẑ\":\"Z\",\n\t\"Ⱬ\":\"Z\",\n\t\"Ż\":\"Z\",\n\t\"Ẓ\":\"Z\",\n\t\"Ȥ\":\"Z\",\n\t\"Ẕ\":\"Z\",\n\t\"Ƶ\":\"Z\",\n\t\"IJ\":\"IJ\",\n\t\"Œ\":\"OE\",\n\t\"ᴀ\":\"A\",\n\t\"ᴁ\":\"AE\",\n\t\"ʙ\":\"B\",\n\t\"ᴃ\":\"B\",\n\t\"ᴄ\":\"C\",\n\t\"ᴅ\":\"D\",\n\t\"ᴇ\":\"E\",\n\t\"ꜰ\":\"F\",\n\t\"ɢ\":\"G\",\n\t\"ʛ\":\"G\",\n\t\"ʜ\":\"H\",\n\t\"ɪ\":\"I\",\n\t\"ʁ\":\"R\",\n\t\"ᴊ\":\"J\",\n\t\"ᴋ\":\"K\",\n\t\"ʟ\":\"L\",\n\t\"ᴌ\":\"L\",\n\t\"ᴍ\":\"M\",\n\t\"ɴ\":\"N\",\n\t\"ᴏ\":\"O\",\n\t\"ɶ\":\"OE\",\n\t\"ᴐ\":\"O\",\n\t\"ᴕ\":\"OU\",\n\t\"ᴘ\":\"P\",\n\t\"ʀ\":\"R\",\n\t\"ᴎ\":\"N\",\n\t\"ᴙ\":\"R\",\n\t\"ꜱ\":\"S\",\n\t\"ᴛ\":\"T\",\n\t\"ⱻ\":\"E\",\n\t\"ᴚ\":\"R\",\n\t\"ᴜ\":\"U\",\n\t\"ᴠ\":\"V\",\n\t\"ᴡ\":\"W\",\n\t\"ʏ\":\"Y\",\n\t\"ᴢ\":\"Z\",\n\t\"á\":\"a\",\n\t\"ă\":\"a\",\n\t\"ắ\":\"a\",\n\t\"ặ\":\"a\",\n\t\"ằ\":\"a\",\n\t\"ẳ\":\"a\",\n\t\"ẵ\":\"a\",\n\t\"ǎ\":\"a\",\n\t\"â\":\"a\",\n\t\"ấ\":\"a\",\n\t\"ậ\":\"a\",\n\t\"ầ\":\"a\",\n\t\"ẩ\":\"a\",\n\t\"ẫ\":\"a\",\n\t\"ä\":\"a\",\n\t\"ǟ\":\"a\",\n\t\"ȧ\":\"a\",\n\t\"ǡ\":\"a\",\n\t\"ạ\":\"a\",\n\t\"ȁ\":\"a\",\n\t\"à\":\"a\",\n\t\"ả\":\"a\",\n\t\"ȃ\":\"a\",\n\t\"ā\":\"a\",\n\t\"ą\":\"a\",\n\t\"ᶏ\":\"a\",\n\t\"ẚ\":\"a\",\n\t\"å\":\"a\",\n\t\"ǻ\":\"a\",\n\t\"ḁ\":\"a\",\n\t\"ⱥ\":\"a\",\n\t\"ã\":\"a\",\n\t\"ꜳ\":\"aa\",\n\t\"æ\":\"ae\",\n\t\"ǽ\":\"ae\",\n\t\"ǣ\":\"ae\",\n\t\"ꜵ\":\"ao\",\n\t\"ꜷ\":\"au\",\n\t\"ꜹ\":\"av\",\n\t\"ꜻ\":\"av\",\n\t\"ꜽ\":\"ay\",\n\t\"ḃ\":\"b\",\n\t\"ḅ\":\"b\",\n\t\"ɓ\":\"b\",\n\t\"ḇ\":\"b\",\n\t\"ᵬ\":\"b\",\n\t\"ᶀ\":\"b\",\n\t\"ƀ\":\"b\",\n\t\"ƃ\":\"b\",\n\t\"ɵ\":\"o\",\n\t\"ć\":\"c\",\n\t\"č\":\"c\",\n\t\"ç\":\"c\",\n\t\"ḉ\":\"c\",\n\t\"ĉ\":\"c\",\n\t\"ɕ\":\"c\",\n\t\"ċ\":\"c\",\n\t\"ƈ\":\"c\",\n\t\"ȼ\":\"c\",\n\t\"ď\":\"d\",\n\t\"ḑ\":\"d\",\n\t\"ḓ\":\"d\",\n\t\"ȡ\":\"d\",\n\t\"ḋ\":\"d\",\n\t\"ḍ\":\"d\",\n\t\"ɗ\":\"d\",\n\t\"ᶑ\":\"d\",\n\t\"ḏ\":\"d\",\n\t\"ᵭ\":\"d\",\n\t\"ᶁ\":\"d\",\n\t\"đ\":\"d\",\n\t\"ɖ\":\"d\",\n\t\"ƌ\":\"d\",\n\t\"ı\":\"i\",\n\t\"ȷ\":\"j\",\n\t\"ɟ\":\"j\",\n\t\"ʄ\":\"j\",\n\t\"dz\":\"dz\",\n\t\"dž\":\"dz\",\n\t\"é\":\"e\",\n\t\"ĕ\":\"e\",\n\t\"ě\":\"e\",\n\t\"ȩ\":\"e\",\n\t\"ḝ\":\"e\",\n\t\"ê\":\"e\",\n\t\"ế\":\"e\",\n\t\"ệ\":\"e\",\n\t\"ề\":\"e\",\n\t\"ể\":\"e\",\n\t\"ễ\":\"e\",\n\t\"ḙ\":\"e\",\n\t\"ë\":\"e\",\n\t\"ė\":\"e\",\n\t\"ẹ\":\"e\",\n\t\"ȅ\":\"e\",\n\t\"è\":\"e\",\n\t\"ẻ\":\"e\",\n\t\"ȇ\":\"e\",\n\t\"ē\":\"e\",\n\t\"ḗ\":\"e\",\n\t\"ḕ\":\"e\",\n\t\"ⱸ\":\"e\",\n\t\"ę\":\"e\",\n\t\"ᶒ\":\"e\",\n\t\"ɇ\":\"e\",\n\t\"ẽ\":\"e\",\n\t\"ḛ\":\"e\",\n\t\"ꝫ\":\"et\",\n\t\"ḟ\":\"f\",\n\t\"ƒ\":\"f\",\n\t\"ᵮ\":\"f\",\n\t\"ᶂ\":\"f\",\n\t\"ǵ\":\"g\",\n\t\"ğ\":\"g\",\n\t\"ǧ\":\"g\",\n\t\"ģ\":\"g\",\n\t\"ĝ\":\"g\",\n\t\"ġ\":\"g\",\n\t\"ɠ\":\"g\",\n\t\"ḡ\":\"g\",\n\t\"ᶃ\":\"g\",\n\t\"ǥ\":\"g\",\n\t\"ḫ\":\"h\",\n\t\"ȟ\":\"h\",\n\t\"ḩ\":\"h\",\n\t\"ĥ\":\"h\",\n\t\"ⱨ\":\"h\",\n\t\"ḧ\":\"h\",\n\t\"ḣ\":\"h\",\n\t\"ḥ\":\"h\",\n\t\"ɦ\":\"h\",\n\t\"ẖ\":\"h\",\n\t\"ħ\":\"h\",\n\t\"ƕ\":\"hv\",\n\t\"í\":\"i\",\n\t\"ĭ\":\"i\",\n\t\"ǐ\":\"i\",\n\t\"î\":\"i\",\n\t\"ï\":\"i\",\n\t\"ḯ\":\"i\",\n\t\"ị\":\"i\",\n\t\"ȉ\":\"i\",\n\t\"ì\":\"i\",\n\t\"ỉ\":\"i\",\n\t\"ȋ\":\"i\",\n\t\"ī\":\"i\",\n\t\"į\":\"i\",\n\t\"ᶖ\":\"i\",\n\t\"ɨ\":\"i\",\n\t\"ĩ\":\"i\",\n\t\"ḭ\":\"i\",\n\t\"ꝺ\":\"d\",\n\t\"ꝼ\":\"f\",\n\t\"ᵹ\":\"g\",\n\t\"ꞃ\":\"r\",\n\t\"ꞅ\":\"s\",\n\t\"ꞇ\":\"t\",\n\t\"ꝭ\":\"is\",\n\t\"ǰ\":\"j\",\n\t\"ĵ\":\"j\",\n\t\"ʝ\":\"j\",\n\t\"ɉ\":\"j\",\n\t\"ḱ\":\"k\",\n\t\"ǩ\":\"k\",\n\t\"ķ\":\"k\",\n\t\"ⱪ\":\"k\",\n\t\"ꝃ\":\"k\",\n\t\"ḳ\":\"k\",\n\t\"ƙ\":\"k\",\n\t\"ḵ\":\"k\",\n\t\"ᶄ\":\"k\",\n\t\"ꝁ\":\"k\",\n\t\"ꝅ\":\"k\",\n\t\"ĺ\":\"l\",\n\t\"ƚ\":\"l\",\n\t\"ɬ\":\"l\",\n\t\"ľ\":\"l\",\n\t\"ļ\":\"l\",\n\t\"ḽ\":\"l\",\n\t\"ȴ\":\"l\",\n\t\"ḷ\":\"l\",\n\t\"ḹ\":\"l\",\n\t\"ⱡ\":\"l\",\n\t\"ꝉ\":\"l\",\n\t\"ḻ\":\"l\",\n\t\"ŀ\":\"l\",\n\t\"ɫ\":\"l\",\n\t\"ᶅ\":\"l\",\n\t\"ɭ\":\"l\",\n\t\"ł\":\"l\",\n\t\"lj\":\"lj\",\n\t\"ſ\":\"s\",\n\t\"ẜ\":\"s\",\n\t\"ẛ\":\"s\",\n\t\"ẝ\":\"s\",\n\t\"ḿ\":\"m\",\n\t\"ṁ\":\"m\",\n\t\"ṃ\":\"m\",\n\t\"ɱ\":\"m\",\n\t\"ᵯ\":\"m\",\n\t\"ᶆ\":\"m\",\n\t\"ń\":\"n\",\n\t\"ň\":\"n\",\n\t\"ņ\":\"n\",\n\t\"ṋ\":\"n\",\n\t\"ȵ\":\"n\",\n\t\"ṅ\":\"n\",\n\t\"ṇ\":\"n\",\n\t\"ǹ\":\"n\",\n\t\"ɲ\":\"n\",\n\t\"ṉ\":\"n\",\n\t\"ƞ\":\"n\",\n\t\"ᵰ\":\"n\",\n\t\"ᶇ\":\"n\",\n\t\"ɳ\":\"n\",\n\t\"ñ\":\"n\",\n\t\"nj\":\"nj\",\n\t\"ó\":\"o\",\n\t\"ŏ\":\"o\",\n\t\"ǒ\":\"o\",\n\t\"ô\":\"o\",\n\t\"ố\":\"o\",\n\t\"ộ\":\"o\",\n\t\"ồ\":\"o\",\n\t\"ổ\":\"o\",\n\t\"ỗ\":\"o\",\n\t\"ö\":\"o\",\n\t\"ȫ\":\"o\",\n\t\"ȯ\":\"o\",\n\t\"ȱ\":\"o\",\n\t\"ọ\":\"o\",\n\t\"ő\":\"o\",\n\t\"ȍ\":\"o\",\n\t\"ò\":\"o\",\n\t\"ỏ\":\"o\",\n\t\"ơ\":\"o\",\n\t\"ớ\":\"o\",\n\t\"ợ\":\"o\",\n\t\"ờ\":\"o\",\n\t\"ở\":\"o\",\n\t\"ỡ\":\"o\",\n\t\"ȏ\":\"o\",\n\t\"ꝋ\":\"o\",\n\t\"ꝍ\":\"o\",\n\t\"ⱺ\":\"o\",\n\t\"ō\":\"o\",\n\t\"ṓ\":\"o\",\n\t\"ṑ\":\"o\",\n\t\"ǫ\":\"o\",\n\t\"ǭ\":\"o\",\n\t\"ø\":\"o\",\n\t\"ǿ\":\"o\",\n\t\"õ\":\"o\",\n\t\"ṍ\":\"o\",\n\t\"ṏ\":\"o\",\n\t\"ȭ\":\"o\",\n\t\"ƣ\":\"oi\",\n\t\"ꝏ\":\"oo\",\n\t\"ɛ\":\"e\",\n\t\"ᶓ\":\"e\",\n\t\"ɔ\":\"o\",\n\t\"ᶗ\":\"o\",\n\t\"ȣ\":\"ou\",\n\t\"ṕ\":\"p\",\n\t\"ṗ\":\"p\",\n\t\"ꝓ\":\"p\",\n\t\"ƥ\":\"p\",\n\t\"ᵱ\":\"p\",\n\t\"ᶈ\":\"p\",\n\t\"ꝕ\":\"p\",\n\t\"ᵽ\":\"p\",\n\t\"ꝑ\":\"p\",\n\t\"ꝙ\":\"q\",\n\t\"ʠ\":\"q\",\n\t\"ɋ\":\"q\",\n\t\"ꝗ\":\"q\",\n\t\"ŕ\":\"r\",\n\t\"ř\":\"r\",\n\t\"ŗ\":\"r\",\n\t\"ṙ\":\"r\",\n\t\"ṛ\":\"r\",\n\t\"ṝ\":\"r\",\n\t\"ȑ\":\"r\",\n\t\"ɾ\":\"r\",\n\t\"ᵳ\":\"r\",\n\t\"ȓ\":\"r\",\n\t\"ṟ\":\"r\",\n\t\"ɼ\":\"r\",\n\t\"ᵲ\":\"r\",\n\t\"ᶉ\":\"r\",\n\t\"ɍ\":\"r\",\n\t\"ɽ\":\"r\",\n\t\"ↄ\":\"c\",\n\t\"ꜿ\":\"c\",\n\t\"ɘ\":\"e\",\n\t\"ɿ\":\"r\",\n\t\"ś\":\"s\",\n\t\"ṥ\":\"s\",\n\t\"š\":\"s\",\n\t\"ṧ\":\"s\",\n\t\"ş\":\"s\",\n\t\"ŝ\":\"s\",\n\t\"ș\":\"s\",\n\t\"ṡ\":\"s\",\n\t\"ṣ\":\"s\",\n\t\"ṩ\":\"s\",\n\t\"ʂ\":\"s\",\n\t\"ᵴ\":\"s\",\n\t\"ᶊ\":\"s\",\n\t\"ȿ\":\"s\",\n\t\"ɡ\":\"g\",\n\t\"ᴑ\":\"o\",\n\t\"ᴓ\":\"o\",\n\t\"ᴝ\":\"u\",\n\t\"ť\":\"t\",\n\t\"ţ\":\"t\",\n\t\"ṱ\":\"t\",\n\t\"ț\":\"t\",\n\t\"ȶ\":\"t\",\n\t\"ẗ\":\"t\",\n\t\"ⱦ\":\"t\",\n\t\"ṫ\":\"t\",\n\t\"ṭ\":\"t\",\n\t\"ƭ\":\"t\",\n\t\"ṯ\":\"t\",\n\t\"ᵵ\":\"t\",\n\t\"ƫ\":\"t\",\n\t\"ʈ\":\"t\",\n\t\"ŧ\":\"t\",\n\t\"ᵺ\":\"th\",\n\t\"ɐ\":\"a\",\n\t\"ᴂ\":\"ae\",\n\t\"ǝ\":\"e\",\n\t\"ᵷ\":\"g\",\n\t\"ɥ\":\"h\",\n\t\"ʮ\":\"h\",\n\t\"ʯ\":\"h\",\n\t\"ᴉ\":\"i\",\n\t\"ʞ\":\"k\",\n\t\"ꞁ\":\"l\",\n\t\"ɯ\":\"m\",\n\t\"ɰ\":\"m\",\n\t\"ᴔ\":\"oe\",\n\t\"ɹ\":\"r\",\n\t\"ɻ\":\"r\",\n\t\"ɺ\":\"r\",\n\t\"ⱹ\":\"r\",\n\t\"ʇ\":\"t\",\n\t\"ʌ\":\"v\",\n\t\"ʍ\":\"w\",\n\t\"ʎ\":\"y\",\n\t\"ꜩ\":\"tz\",\n\t\"ú\":\"u\",\n\t\"ŭ\":\"u\",\n\t\"ǔ\":\"u\",\n\t\"û\":\"u\",\n\t\"ṷ\":\"u\",\n\t\"ü\":\"u\",\n\t\"ǘ\":\"u\",\n\t\"ǚ\":\"u\",\n\t\"ǜ\":\"u\",\n\t\"ǖ\":\"u\",\n\t\"ṳ\":\"u\",\n\t\"ụ\":\"u\",\n\t\"ű\":\"u\",\n\t\"ȕ\":\"u\",\n\t\"ù\":\"u\",\n\t\"ủ\":\"u\",\n\t\"ư\":\"u\",\n\t\"ứ\":\"u\",\n\t\"ự\":\"u\",\n\t\"ừ\":\"u\",\n\t\"ử\":\"u\",\n\t\"ữ\":\"u\",\n\t\"ȗ\":\"u\",\n\t\"ū\":\"u\",\n\t\"ṻ\":\"u\",\n\t\"ų\":\"u\",\n\t\"ᶙ\":\"u\",\n\t\"ů\":\"u\",\n\t\"ũ\":\"u\",\n\t\"ṹ\":\"u\",\n\t\"ṵ\":\"u\",\n\t\"ᵫ\":\"ue\",\n\t\"ꝸ\":\"um\",\n\t\"ⱴ\":\"v\",\n\t\"ꝟ\":\"v\",\n\t\"ṿ\":\"v\",\n\t\"ʋ\":\"v\",\n\t\"ᶌ\":\"v\",\n\t\"ⱱ\":\"v\",\n\t\"ṽ\":\"v\",\n\t\"ꝡ\":\"vy\",\n\t\"ẃ\":\"w\",\n\t\"ŵ\":\"w\",\n\t\"ẅ\":\"w\",\n\t\"ẇ\":\"w\",\n\t\"ẉ\":\"w\",\n\t\"ẁ\":\"w\",\n\t\"ⱳ\":\"w\",\n\t\"ẘ\":\"w\",\n\t\"ẍ\":\"x\",\n\t\"ẋ\":\"x\",\n\t\"ᶍ\":\"x\",\n\t\"ý\":\"y\",\n\t\"ŷ\":\"y\",\n\t\"ÿ\":\"y\",\n\t\"ẏ\":\"y\",\n\t\"ỵ\":\"y\",\n\t\"ỳ\":\"y\",\n\t\"ƴ\":\"y\",\n\t\"ỷ\":\"y\",\n\t\"ỿ\":\"y\",\n\t\"ȳ\":\"y\",\n\t\"ẙ\":\"y\",\n\t\"ɏ\":\"y\",\n\t\"ỹ\":\"y\",\n\t\"ź\":\"z\",\n\t\"ž\":\"z\",\n\t\"ẑ\":\"z\",\n\t\"ʑ\":\"z\",\n\t\"ⱬ\":\"z\",\n\t\"ż\":\"z\",\n\t\"ẓ\":\"z\",\n\t\"ȥ\":\"z\",\n\t\"ẕ\":\"z\",\n\t\"ᵶ\":\"z\",\n\t\"ᶎ\":\"z\",\n\t\"ʐ\":\"z\",\n\t\"ƶ\":\"z\",\n\t\"ɀ\":\"z\",\n\t\"ff\":\"ff\",\n\t\"ffi\":\"ffi\",\n\t\"ffl\":\"ffl\",\n\t\"fi\":\"fi\",\n\t\"fl\":\"fl\",\n\t\"ij\":\"ij\",\n\t\"œ\":\"oe\",\n\t\"st\":\"st\",\n\t\"ₐ\":\"a\",\n\t\"ₑ\":\"e\",\n\t\"ᵢ\":\"i\",\n\t\"ⱼ\":\"j\",\n\t\"ₒ\":\"o\",\n\t\"ᵣ\":\"r\",\n\t\"ᵤ\":\"u\",\n\t\"ᵥ\":\"v\",\n\t\"ₓ\":\"x\",\n\t\"Ё\":\"YO\",\n\t\"Й\":\"I\",\n\t\"Ц\":\"TS\",\n\t\"У\":\"U\",\n\t\"К\":\"K\",\n\t\"Е\":\"E\",\n\t\"Н\":\"N\",\n\t\"Г\":\"G\",\n\t\"Ш\":\"SH\",\n\t\"Щ\":\"SCH\",\n\t\"З\":\"Z\",\n\t\"Х\":\"H\",\n\t\"Ъ\":\"'\",\n\t\"ё\":\"yo\",\n\t\"й\":\"i\",\n\t\"ц\":\"ts\",\n\t\"у\":\"u\",\n\t\"к\":\"k\",\n\t\"е\":\"e\",\n\t\"н\":\"n\",\n\t\"г\":\"g\",\n\t\"ш\":\"sh\",\n\t\"щ\":\"sch\",\n\t\"з\":\"z\",\n\t\"х\":\"h\",\n\t\"ъ\":\"'\",\n\t\"Ф\":\"F\",\n\t\"Ы\":\"I\",\n\t\"В\":\"V\",\n\t\"А\":\"a\",\n\t\"П\":\"P\",\n\t\"Р\":\"R\",\n\t\"О\":\"O\",\n\t\"Л\":\"L\",\n\t\"Д\":\"D\",\n\t\"Ж\":\"ZH\",\n\t\"Э\":\"E\",\n\t\"ф\":\"f\",\n\t\"ы\":\"i\",\n\t\"в\":\"v\",\n\t\"а\":\"a\",\n\t\"п\":\"p\",\n\t\"р\":\"r\",\n\t\"о\":\"o\",\n\t\"л\":\"l\",\n\t\"д\":\"d\",\n\t\"ж\":\"zh\",\n\t\"э\":\"e\",\n\t\"Я\":\"Ya\",\n\t\"Ч\":\"CH\",\n\t\"С\":\"S\",\n\t\"М\":\"M\",\n\t\"И\":\"I\",\n\t\"Т\":\"T\",\n\t\"Ь\":\"'\",\n\t\"Б\":\"B\",\n\t\"Ю\":\"YU\",\n\t\"я\":\"ya\",\n\t\"ч\":\"ch\",\n\t\"с\":\"s\",\n\t\"м\":\"m\",\n\t\"и\":\"i\",\n\t\"т\":\"t\",\n\t\"ь\":\"'\",\n\t\"б\":\"b\",\n\t\"ю\":\"yu\"\n};\n\nexports.transliterate = function(str) {\n\treturn str.replace(/[^A-Za-z0-9\\[\\] ]/g,function(ch) {\n\t\treturn exports.transliterationPairs[ch] || ch\n\t});\n};\n\nexports.transliterateToSafeASCII = function(str) {\n\treturn str.replace(/[^\\x00-\\x7F]/g,function(ch) {\n\t\treturn exports.transliterationPairs[ch] || \"\"\n\t});\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/utils/utils.js": {
            "title": "$:/core/modules/utils/utils.js",
            "text": "/*\\\ntitle: $:/core/modules/utils/utils.js\ntype: application/javascript\nmodule-type: utils\n\nVarious static utility functions.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar base64utf8 = require(\"$:/core/modules/utils/base64-utf8/base64-utf8.module.js\");\n\n/*\nDisplay a message, in colour if we're on a terminal\n*/\nexports.log = function(text,colour) {\n\tconsole.log($tw.node ? exports.terminalColour(colour) + text + exports.terminalColour() : text);\n};\n\nexports.terminalColour = function(colour) {\n\tif(!$tw.browser && $tw.node && process.stdout.isTTY) {\n\t\tif(colour) {\n\t\t\tvar code = exports.terminalColourLookup[colour];\n\t\t\tif(code) {\n\t\t\t\treturn \"\\x1b[\" + code + \"m\";\n\t\t\t}\n\t\t} else {\n\t\t\treturn \"\\x1b[0m\"; // Cancel colour\n\t\t}\n\t}\n\treturn \"\";\n};\n\nexports.terminalColourLookup = {\n\t\"black\": \"0;30\",\n\t\"red\": \"0;31\",\n\t\"green\": \"0;32\",\n\t\"brown/orange\": \"0;33\",\n\t\"blue\": \"0;34\",\n\t\"purple\": \"0;35\",\n\t\"cyan\": \"0;36\",\n\t\"light gray\": \"0;37\"\n};\n\n/*\nDisplay a warning, in colour if we're on a terminal\n*/\nexports.warning = function(text) {\n\texports.log(text,\"brown/orange\");\n};\n\n/*\nReturn the integer represented by the str (string).\nReturn the dflt (default) parameter if str is not a base-10 number.\n*/\nexports.getInt = function(str,deflt) {\n\tvar i = parseInt(str,10);\n\treturn isNaN(i) ? deflt : i;\n}\n\n/*\nRepeatedly replaces a substring within a string. Like String.prototype.replace, but without any of the default special handling of $ sequences in the replace string\n*/\nexports.replaceString = function(text,search,replace) {\n\treturn text.replace(search,function() {\n\t\treturn replace;\n\t});\n};\n\n/*\nRepeats a string\n*/\nexports.repeat = function(str,count) {\n\tvar result = \"\";\n\tfor(var t=0;t<count;t++) {\n\t\tresult += str;\n\t}\n\treturn result;\n};\n\n/*\nTrim whitespace from the start and end of a string\nThanks to Steven Levithan, http://blog.stevenlevithan.com/archives/faster-trim-javascript\n*/\nexports.trim = function(str) {\n\tif(typeof str === \"string\") {\n\t\treturn str.replace(/^\\s\\s*/, '').replace(/\\s\\s*$/, '');\n\t} else {\n\t\treturn str;\n\t}\n};\n\n/*\nConvert a string to sentence case (ie capitalise first letter)\n*/\nexports.toSentenceCase = function(str) {\n\treturn (str || \"\").replace(/^\\S/, function(c) {return c.toUpperCase();});\n}\n\n/*\nConvert a string to title case (ie capitalise each initial letter)\n*/\nexports.toTitleCase = function(str) {\n\treturn (str || \"\").replace(/(^|\\s)\\S/g, function(c) {return c.toUpperCase();});\n}\n\t\n/*\nFind the line break preceding a given position in a string\nReturns position immediately after that line break, or the start of the string\n*/\nexports.findPrecedingLineBreak = function(text,pos) {\n\tvar result = text.lastIndexOf(\"\\n\",pos - 1);\n\tif(result === -1) {\n\t\tresult = 0;\n\t} else {\n\t\tresult++;\n\t\tif(text.charAt(result) === \"\\r\") {\n\t\t\tresult++;\n\t\t}\n\t}\n\treturn result;\n};\n\n/*\nFind the line break following a given position in a string\n*/\nexports.findFollowingLineBreak = function(text,pos) {\n\t// Cut to just past the following line break, or to the end of the text\n\tvar result = text.indexOf(\"\\n\",pos);\n\tif(result === -1) {\n\t\tresult = text.length;\n\t} else {\n\t\tif(text.charAt(result) === \"\\r\") {\n\t\t\tresult++;\n\t\t}\n\t}\n\treturn result;\n};\n\n/*\nReturn the number of keys in an object\n*/\nexports.count = function(object) {\n\treturn Object.keys(object || {}).length;\n};\n\n/*\nDetermine whether an array-item is an object-property\n*/\nexports.hopArray = function(object,array) {\n\tfor(var i=0; i<array.length; i++) {\n\t\tif($tw.utils.hop(object,array[i])) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\n/*\nRemove entries from an array\n\tarray: array to modify\n\tvalue: a single value to remove, or an array of values to remove\n*/\nexports.removeArrayEntries = function(array,value) {\n\tvar t,p;\n\tif($tw.utils.isArray(value)) {\n\t\tfor(t=0; t<value.length; t++) {\n\t\t\tp = array.indexOf(value[t]);\n\t\t\tif(p !== -1) {\n\t\t\t\tarray.splice(p,1);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tp = array.indexOf(value);\n\t\tif(p !== -1) {\n\t\t\tarray.splice(p,1);\n\t\t}\n\t}\n};\n\n/*\nCheck whether any members of a hashmap are present in another hashmap\n*/\nexports.checkDependencies = function(dependencies,changes) {\n\tvar hit = false;\n\t$tw.utils.each(changes,function(change,title) {\n\t\tif($tw.utils.hop(dependencies,title)) {\n\t\t\thit = true;\n\t\t}\n\t});\n\treturn hit;\n};\n\nexports.extend = function(object /* [, src] */) {\n\t$tw.utils.each(Array.prototype.slice.call(arguments, 1), function(source) {\n\t\tif(source) {\n\t\t\tfor(var property in source) {\n\t\t\t\tobject[property] = source[property];\n\t\t\t}\n\t\t}\n\t});\n\treturn object;\n};\n\nexports.deepCopy = function(object) {\n\tvar result,t;\n\tif($tw.utils.isArray(object)) {\n\t\t// Copy arrays\n\t\tresult = object.slice(0);\n\t} else if(typeof object === \"object\") {\n\t\tresult = {};\n\t\tfor(t in object) {\n\t\t\tif(object[t] !== undefined) {\n\t\t\t\tresult[t] = $tw.utils.deepCopy(object[t]);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tresult = object;\n\t}\n\treturn result;\n};\n\nexports.extendDeepCopy = function(object,extendedProperties) {\n\tvar result = $tw.utils.deepCopy(object),t;\n\tfor(t in extendedProperties) {\n\t\tif(extendedProperties[t] !== undefined) {\n\t\t\tresult[t] = $tw.utils.deepCopy(extendedProperties[t]);\n\t\t}\n\t}\n\treturn result;\n};\n\nexports.deepFreeze = function deepFreeze(object) {\n\tvar property, key;\n\tif(object) {\n\t\tObject.freeze(object);\n\t\tfor(key in object) {\n\t\t\tproperty = object[key];\n\t\t\tif($tw.utils.hop(object,key) && (typeof property === \"object\") && !Object.isFrozen(property)) {\n\t\t\t\tdeepFreeze(property);\n\t\t\t}\n\t\t}\n\t}\n};\n\nexports.slowInSlowOut = function(t) {\n\treturn (1 - ((Math.cos(t * Math.PI) + 1) / 2));\n};\n\nexports.formatDateString = function(date,template) {\n\tvar result = \"\",\n\t\tt = template,\n\t\tmatches = [\n\t\t\t[/^0hh12/, function() {\n\t\t\t\treturn $tw.utils.pad($tw.utils.getHours12(date));\n\t\t\t}],\n\t\t\t[/^wYYYY/, function() {\n\t\t\t\treturn $tw.utils.getYearForWeekNo(date);\n\t\t\t}],\n\t\t\t[/^hh12/, function() {\n\t\t\t\treturn $tw.utils.getHours12(date);\n\t\t\t}],\n\t\t\t[/^DDth/, function() {\n\t\t\t\treturn date.getDate() + $tw.utils.getDaySuffix(date);\n\t\t\t}],\n\t\t\t[/^YYYY/, function() {\n\t\t\t\treturn date.getFullYear();\n\t\t\t}],\n\t\t\t[/^0hh/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getHours());\n\t\t\t}],\n\t\t\t[/^0mm/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getMinutes());\n\t\t\t}],\n\t\t\t[/^0ss/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getSeconds());\n\t\t\t}],\n\t\t\t[/^0XXX/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getMilliseconds(),3);\n\t\t\t}],\n\t\t\t[/^0DD/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getDate());\n\t\t\t}],\n\t\t\t[/^0MM/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getMonth()+1);\n\t\t\t}],\n\t\t\t[/^0WW/, function() {\n\t\t\t\treturn $tw.utils.pad($tw.utils.getWeek(date));\n\t\t\t}],\n\t\t\t[/^ddd/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Short/Day/\" + date.getDay());\n\t\t\t}],\n\t\t\t[/^mmm/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Short/Month/\" + (date.getMonth() + 1));\n\t\t\t}],\n\t\t\t[/^DDD/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Long/Day/\" + date.getDay());\n\t\t\t}],\n\t\t\t[/^MMM/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Long/Month/\" + (date.getMonth() + 1));\n\t\t\t}],\n\t\t\t[/^TZD/, function() {\n\t\t\t\tvar tz = date.getTimezoneOffset(),\n\t\t\t\tatz = Math.abs(tz);\n\t\t\t\treturn (tz < 0 ? '+' : '-') + $tw.utils.pad(Math.floor(atz / 60)) + ':' + $tw.utils.pad(atz % 60);\n\t\t\t}],\n\t\t\t[/^wYY/, function() {\n\t\t\t\treturn $tw.utils.pad($tw.utils.getYearForWeekNo(date) - 2000);\n\t\t\t}],\n\t\t\t[/^[ap]m/, function() {\n\t\t\t\treturn $tw.utils.getAmPm(date).toLowerCase();\n\t\t\t}],\n\t\t\t[/^hh/, function() {\n\t\t\t\treturn date.getHours();\n\t\t\t}],\n\t\t\t[/^mm/, function() {\n\t\t\t\treturn date.getMinutes();\n\t\t\t}],\n\t\t\t[/^ss/, function() {\n\t\t\t\treturn date.getSeconds();\n\t\t\t}],\n\t\t\t[/^XXX/, function() {\n\t\t\t\treturn date.getMilliseconds();\n\t\t\t}],\n\t\t\t[/^[AP]M/, function() {\n\t\t\t\treturn $tw.utils.getAmPm(date).toUpperCase();\n\t\t\t}],\n\t\t\t[/^DD/, function() {\n\t\t\t\treturn date.getDate();\n\t\t\t}],\n\t\t\t[/^MM/, function() {\n\t\t\t\treturn date.getMonth() + 1;\n\t\t\t}],\n\t\t\t[/^WW/, function() {\n\t\t\t\treturn $tw.utils.getWeek(date);\n\t\t\t}],\n\t\t\t[/^YY/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getFullYear() - 2000);\n\t\t\t}]\n\t\t];\n\t// If the user wants everything in UTC, shift the datestamp\n\t// Optimize for format string that essentially means\n\t// 'return raw UTC (tiddlywiki style) date string.'\n\tif(t.indexOf(\"[UTC]\") == 0 ) {\n\t\tif(t == \"[UTC]YYYY0MM0DD0hh0mm0ssXXX\")\n\t\t\treturn $tw.utils.stringifyDate(new Date());\n\t\tvar offset = date.getTimezoneOffset() ; // in minutes\n\t\tdate = new Date(date.getTime()+offset*60*1000) ;\n\t\tt = t.substr(5) ;\n\t}\n\twhile(t.length){\n\t\tvar matchString = \"\";\n\t\t$tw.utils.each(matches, function(m) {\n\t\t\tvar match = m[0].exec(t);\n\t\t\tif(match) {\n\t\t\t\tmatchString = m[1].call();\n\t\t\t\tt = t.substr(match[0].length);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif(matchString) {\n\t\t\tresult += matchString;\n\t\t} else {\n\t\t\tresult += t.charAt(0);\n\t\t\tt = t.substr(1);\n\t\t}\n\t}\n\tresult = result.replace(/\\\\(.)/g,\"$1\");\n\treturn result;\n};\n\nexports.getAmPm = function(date) {\n\treturn $tw.language.getString(\"Date/Period/\" + (date.getHours() >= 12 ? \"pm\" : \"am\"));\n};\n\nexports.getDaySuffix = function(date) {\n\treturn $tw.language.getString(\"Date/DaySuffix/\" + date.getDate());\n};\n\nexports.getWeek = function(date) {\n\tvar dt = new Date(date.getTime());\n\tvar d = dt.getDay();\n\tif(d === 0) {\n\t\td = 7; // JavaScript Sun=0, ISO Sun=7\n\t}\n\tdt.setTime(dt.getTime() + (4 - d) * 86400000);// shift day to Thurs of same week to calculate weekNo\n\tvar x = new Date(dt.getFullYear(),0,1);\n\tvar n = Math.floor((dt.getTime() - x.getTime()) / 86400000);\n\treturn Math.floor(n / 7) + 1;\n};\n\nexports.getYearForWeekNo = function(date) {\n\tvar dt = new Date(date.getTime());\n\tvar d = dt.getDay();\n\tif(d === 0) {\n\t\td = 7; // JavaScript Sun=0, ISO Sun=7\n\t}\n\tdt.setTime(dt.getTime() + (4 - d) * 86400000);// shift day to Thurs of same week\n\treturn dt.getFullYear();\n};\n\nexports.getHours12 = function(date) {\n\tvar h = date.getHours();\n\treturn h > 12 ? h-12 : ( h > 0 ? h : 12 );\n};\n\n/*\nConvert a date delta in milliseconds into a string representation of \"23 seconds ago\", \"27 minutes ago\" etc.\n\tdelta: delta in milliseconds\nReturns an object with these members:\n\tdescription: string describing the delta period\n\tupdatePeriod: time in millisecond until the string will be inaccurate\n*/\nexports.getRelativeDate = function(delta) {\n\tvar futurep = false;\n\tif(delta < 0) {\n\t\tdelta = -1 * delta;\n\t\tfuturep = true;\n\t}\n\tvar units = [\n\t\t{name: \"Years\",   duration:      365 * 24 * 60 * 60 * 1000},\n\t\t{name: \"Months\",  duration: (365/12) * 24 * 60 * 60 * 1000},\n\t\t{name: \"Days\",    duration:            24 * 60 * 60 * 1000},\n\t\t{name: \"Hours\",   duration:                 60 * 60 * 1000},\n\t\t{name: \"Minutes\", duration:                      60 * 1000},\n\t\t{name: \"Seconds\", duration:                           1000}\n\t];\n\tfor(var t=0; t<units.length; t++) {\n\t\tvar result = Math.floor(delta / units[t].duration);\n\t\tif(result >= 2) {\n\t\t\treturn {\n\t\t\t\tdelta: delta,\n\t\t\t\tdescription: $tw.language.getString(\n\t\t\t\t\t\"RelativeDate/\" + (futurep ? \"Future\" : \"Past\") + \"/\" + units[t].name,\n\t\t\t\t\t{variables:\n\t\t\t\t\t\t{period: result.toString()}\n\t\t\t\t\t}\n\t\t\t\t),\n\t\t\t\tupdatePeriod: units[t].duration\n\t\t\t};\n\t\t}\n\t}\n\treturn {\n\t\tdelta: delta,\n\t\tdescription: $tw.language.getString(\n\t\t\t\"RelativeDate/\" + (futurep ? \"Future\" : \"Past\") + \"/Second\",\n\t\t\t{variables:\n\t\t\t\t{period: \"1\"}\n\t\t\t}\n\t\t),\n\t\tupdatePeriod: 1000\n\t};\n};\n\n// Convert & to \"&amp;\", < to \"&lt;\", > to \"&gt;\", \" to \"&quot;\"\nexports.htmlEncode = function(s) {\n\tif(s) {\n\t\treturn s.toString().replace(/&/mg,\"&amp;\").replace(/</mg,\"&lt;\").replace(/>/mg,\"&gt;\").replace(/\\\"/mg,\"&quot;\");\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\n// Converts all HTML entities to their character equivalents\nexports.entityDecode = function(s) {\n\tvar converter = String.fromCodePoint || String.fromCharCode,\n\t\te = s.substr(1,s.length-2), // Strip the & and the ;\n\t\tc;\n\tif(e.charAt(0) === \"#\") {\n\t\tif(e.charAt(1) === \"x\" || e.charAt(1) === \"X\") {\n\t\t\tc = parseInt(e.substr(2),16);\n\t\t} else {\n\t\t\tc = parseInt(e.substr(1),10);\n\t\t}\n\t\tif(isNaN(c)) {\n\t\t\treturn s;\n\t\t} else {\n\t\t\treturn converter(c);\n\t\t}\n\t} else {\n\t\tc = $tw.config.htmlEntities[e];\n\t\tif(c) {\n\t\t\treturn converter(c);\n\t\t} else {\n\t\t\treturn s; // Couldn't convert it as an entity, just return it raw\n\t\t}\n\t}\n};\n\nexports.unescapeLineBreaks = function(s) {\n\treturn s.replace(/\\\\n/mg,\"\\n\").replace(/\\\\b/mg,\" \").replace(/\\\\s/mg,\"\\\\\").replace(/\\r/mg,\"\");\n};\n\n/*\n * Returns an escape sequence for given character. Uses \\x for characters <=\n * 0xFF to save space, \\u for the rest.\n *\n * The code needs to be in sync with th code template in the compilation\n * function for \"action\" nodes.\n */\n// Copied from peg.js, thanks to David Majda\nexports.escape = function(ch) {\n\tvar charCode = ch.charCodeAt(0);\n\tif(charCode <= 0xFF) {\n\t\treturn '\\\\x' + $tw.utils.pad(charCode.toString(16).toUpperCase());\n\t} else {\n\t\treturn '\\\\u' + $tw.utils.pad(charCode.toString(16).toUpperCase(),4);\n\t}\n};\n\n// Turns a string into a legal JavaScript string\n// Copied from peg.js, thanks to David Majda\nexports.stringify = function(s) {\n\t/*\n\t* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string\n\t* literal except for the closing quote character, backslash, carriage return,\n\t* line separator, paragraph separator, and line feed. Any character may\n\t* appear in the form of an escape sequence.\n\t*\n\t* For portability, we also escape all non-ASCII characters.\n\t*/\n\treturn (s || \"\")\n\t\t.replace(/\\\\/g, '\\\\\\\\')            // backslash\n\t\t.replace(/\"/g, '\\\\\"')              // double quote character\n\t\t.replace(/'/g, \"\\\\'\")              // single quote character\n\t\t.replace(/\\r/g, '\\\\r')             // carriage return\n\t\t.replace(/\\n/g, '\\\\n')             // line feed\n\t\t.replace(/[\\x00-\\x1f\\x80-\\uFFFF]/g, exports.escape); // non-ASCII characters\n};\n\n// Turns a string into a legal JSON string\n// Derived from peg.js, thanks to David Majda\nexports.jsonStringify = function(s) {\n\t// See http://www.json.org/\n\treturn (s || \"\")\n\t\t.replace(/\\\\/g, '\\\\\\\\')            // backslash\n\t\t.replace(/\"/g, '\\\\\"')              // double quote character\n\t\t.replace(/\\r/g, '\\\\r')             // carriage return\n\t\t.replace(/\\n/g, '\\\\n')             // line feed\n\t\t.replace(/\\x08/g, '\\\\b')           // backspace\n\t\t.replace(/\\x0c/g, '\\\\f')           // formfeed\n\t\t.replace(/\\t/g, '\\\\t')             // tab\n\t\t.replace(/[\\x00-\\x1f\\x80-\\uFFFF]/g,function(s) {\n\t\t\treturn '\\\\u' + $tw.utils.pad(s.charCodeAt(0).toString(16).toUpperCase(),4);\n\t\t}); // non-ASCII characters\n};\n\n/*\nEscape the RegExp special characters with a preceding backslash\n*/\nexports.escapeRegExp = function(s) {\n    return s.replace(/[\\-\\/\\\\\\^\\$\\*\\+\\?\\.\\(\\)\\|\\[\\]\\{\\}]/g, '\\\\$&');\n};\n\n// Checks whether a link target is external, i.e. not a tiddler title\nexports.isLinkExternal = function(to) {\n\tvar externalRegExp = /^(?:file|http|https|mailto|ftp|irc|news|data|skype):[^\\s<>{}\\[\\]`|\"\\\\^]+(?:\\/|\\b)/i;\n\treturn externalRegExp.test(to);\n};\n\nexports.nextTick = function(fn) {\n/*global window: false */\n\tif(typeof process === \"undefined\") {\n\t\t// Apparently it would be faster to use postMessage - http://dbaron.org/log/20100309-faster-timeouts\n\t\twindow.setTimeout(fn,4);\n\t} else {\n\t\tprocess.nextTick(fn);\n\t}\n};\n\n/*\nConvert a hyphenated CSS property name into a camel case one\n*/\nexports.unHyphenateCss = function(propName) {\n\treturn propName.replace(/-([a-z])/gi, function(match0,match1) {\n\t\treturn match1.toUpperCase();\n\t});\n};\n\n/*\nConvert a camelcase CSS property name into a dashed one (\"backgroundColor\" --> \"background-color\")\n*/\nexports.hyphenateCss = function(propName) {\n\treturn propName.replace(/([A-Z])/g, function(match0,match1) {\n\t\treturn \"-\" + match1.toLowerCase();\n\t});\n};\n\n/*\nParse a text reference of one of these forms:\n* title\n* !!field\n* title!!field\n* title##index\n* etc\nReturns an object with the following fields, all optional:\n* title: tiddler title\n* field: tiddler field name\n* index: JSON property index\n*/\nexports.parseTextReference = function(textRef) {\n\t// Separate out the title, field name and/or JSON indices\n\tvar reTextRef = /(?:(.*?)!!(.+))|(?:(.*?)##(.+))|(.*)/mg,\n\t\tmatch = reTextRef.exec(textRef),\n\t\tresult = {};\n\tif(match && reTextRef.lastIndex === textRef.length) {\n\t\t// Return the parts\n\t\tif(match[1]) {\n\t\t\tresult.title = match[1];\n\t\t}\n\t\tif(match[2]) {\n\t\t\tresult.field = match[2];\n\t\t}\n\t\tif(match[3]) {\n\t\t\tresult.title = match[3];\n\t\t}\n\t\tif(match[4]) {\n\t\t\tresult.index = match[4];\n\t\t}\n\t\tif(match[5]) {\n\t\t\tresult.title = match[5];\n\t\t}\n\t} else {\n\t\t// If we couldn't parse it\n\t\tresult.title = textRef\n\t}\n\treturn result;\n};\n\n/*\nChecks whether a string is a valid fieldname\n*/\nexports.isValidFieldName = function(name) {\n\tif(!name || typeof name !== \"string\") {\n\t\treturn false;\n\t}\n\tname = name.toLowerCase().trim();\n\tvar fieldValidatorRegEx = /^[a-z0-9\\-\\._]+$/mg;\n\treturn fieldValidatorRegEx.test(name);\n};\n\n/*\nExtract the version number from the meta tag or from the boot file\n*/\n\n// Browser version\nexports.extractVersionInfo = function() {\n\tif($tw.packageInfo) {\n\t\treturn $tw.packageInfo.version;\n\t} else {\n\t\tvar metatags = document.getElementsByTagName(\"meta\");\n\t\tfor(var t=0; t<metatags.length; t++) {\n\t\t\tvar m = metatags[t];\n\t\t\tif(m.name === \"tiddlywiki-version\") {\n\t\t\t\treturn m.content;\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nGet the animation duration in ms\n*/\nexports.getAnimationDuration = function() {\n\treturn parseInt($tw.wiki.getTiddlerText(\"$:/config/AnimationDuration\",\"400\"),10) || 0;\n};\n\n/*\nHash a string to a number\nDerived from http://stackoverflow.com/a/15710692\n*/\nexports.hashString = function(str) {\n\treturn str.split(\"\").reduce(function(a,b) {\n\t\ta = ((a << 5) - a) + b.charCodeAt(0);\n\t\treturn a & a;\n\t},0);\n};\n\n/*\nDecode a base64 string\n*/\nexports.base64Decode = function(string64) {\n\treturn base64utf8.base64.decode.call(base64utf8,string64);\n};\n\n/*\nEncode a string to base64\n*/\nexports.base64Encode = function(string64) {\n\treturn base64utf8.base64.encode.call(base64utf8,string64);\n};\n\n/*\nConvert a hashmap into a tiddler dictionary format sequence of name:value pairs\n*/\nexports.makeTiddlerDictionary = function(data) {\n\tvar output = [];\n\tfor(var name in data) {\n\t\toutput.push(name + \": \" + data[name]);\n\t}\n\treturn output.join(\"\\n\");\n};\n\n/*\nHigh resolution microsecond timer for profiling\n*/\nexports.timer = function(base) {\n\tvar m;\n\tif($tw.node) {\n\t\tvar r = process.hrtime();\n\t\tm =  r[0] * 1e3 + (r[1] / 1e6);\n\t} else if(window.performance) {\n\t\tm = performance.now();\n\t} else {\n\t\tm = Date.now();\n\t}\n\tif(typeof base !== \"undefined\") {\n\t\tm = m - base;\n\t}\n\treturn m;\n};\n\n/*\nConvert text and content type to a data URI\n*/\nexports.makeDataUri = function(text,type,_canonical_uri) {\n\ttype = type || \"text/vnd.tiddlywiki\";\n\tvar typeInfo = $tw.config.contentTypeInfo[type] || $tw.config.contentTypeInfo[\"text/plain\"],\n\t\tisBase64 = typeInfo.encoding === \"base64\",\n\t\tparts = [];\n\tif(_canonical_uri) {\n\t\tparts.push(_canonical_uri);\n\t} else {\n\t\tparts.push(\"data:\");\n\t\tparts.push(type);\n\t\tparts.push(isBase64 ? \";base64\" : \"\");\n\t\tparts.push(\",\");\n\t\tparts.push(isBase64 ? text : encodeURIComponent(text));\t\t\n\t}\n\treturn parts.join(\"\");\n};\n\n/*\nUseful for finding out the fully escaped CSS selector equivalent to a given tag. For example:\n\n$tw.utils.tagToCssSelector(\"$:/tags/Stylesheet\") --> tc-tagged-\\%24\\%3A\\%2Ftags\\%2FStylesheet\n*/\nexports.tagToCssSelector = function(tagName) {\n\treturn \"tc-tagged-\" + encodeURIComponent(tagName).replace(/[!\"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^`{\\|}~,]/mg,function(c) {\n\t\treturn \"\\\\\" + c;\n\t});\n};\n\n/*\nIE does not have sign function\n*/\nexports.sign = Math.sign || function(x) {\n\tx = +x; // convert to a number\n\tif (x === 0 || isNaN(x)) {\n\t\treturn x;\n\t}\n\treturn x > 0 ? 1 : -1;\n};\n\n/*\nIE does not have an endsWith function\n*/\nexports.strEndsWith = function(str,ending,position) {\n\tif(str.endsWith) {\n\t\treturn str.endsWith(ending,position);\n\t} else {\n\t\tif (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > str.length) {\n\t\t\tposition = str.length;\n\t\t}\n\t\tposition -= ending.length;\n\t\tvar lastIndex = str.indexOf(ending, position);\n\t\treturn lastIndex !== -1 && lastIndex === position;\n\t}\n};\n\n/*\nReturn system information useful for debugging\n*/\nexports.getSystemInfo = function(str,ending,position) {\n\tvar results = [],\n\t\tsave = function(desc,value) {\n\t\t\tresults.push(desc + \": \" + value);\n\t\t};\n\tif($tw.browser) {\n\t\tsave(\"User Agent\",navigator.userAgent);\n\t\tsave(\"Online Status\",window.navigator.onLine);\n\t}\n\tif($tw.node) {\n\t\tsave(\"Node Version\",process.version);\n\t}\n\treturn results.join(\"\\n\");\n};\n\nexports.parseNumber = function(str) {\n\treturn parseFloat(str) || 0;\n};\n\nexports.parseInt = function(str) {\n\treturn parseInt(str,10) || 0;\n};\n\nexports.stringifyNumber = function(num) {\n\treturn num + \"\";\n};\n\n})();\n",
            "type": "application/javascript",
            "module-type": "utils"
        },
        "$:/core/modules/widgets/action-createtiddler.js": {
            "title": "$:/core/modules/widgets/action-createtiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-createtiddler.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to create a new tiddler with a unique name and specified fields.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw:false, require:false, exports:false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CreateTiddlerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCreateTiddlerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCreateTiddlerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nCreateTiddlerWidget.prototype.execute = function() {\n\tthis.actionBaseTitle = this.getAttribute(\"$basetitle\");\n\tthis.hasBase = !!this.actionBaseTitle;\n\tthis.actionSaveTitle = this.getAttribute(\"$savetitle\");\n\tthis.actionSaveDraftTitle = this.getAttribute(\"$savedrafttitle\");\n\tthis.actionTimestamp = this.getAttribute(\"$timestamp\",\"yes\") === \"yes\";\n\t//Following params are new since 5.1.22\n\tthis.actionTemplate = this.getAttribute(\"$template\");\n\tthis.useTemplate = !!this.actionTemplate;\n\tthis.actionOverwrite = this.getAttribute(\"$overwrite\",\"no\");\n\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nCreateTiddlerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif($tw.utils.count(changedAttributes) > 0) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nCreateTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar title = this.wiki.getTiddlerText(\"$:/language/DefaultNewTiddlerTitle\"), // Get the initial new-tiddler title\n\t\tfields = {},\n\t\tcreationFields,\n\t\tmodificationFields;\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tfields[name] = attribute;\n\t\t}\n\t});\n\tif(this.actionTimestamp) {\n\t\tcreationFields = this.wiki.getCreationFields();\n\t\tmodificationFields = this.wiki.getModificationFields();\n\t}\n\tif(this.hasBase && this.actionOverwrite === \"no\") {\n\t\ttitle = this.wiki.generateNewTitle(this.actionBaseTitle);\n\t} else if (this.hasBase && this.actionOverwrite === \"yes\") {\n\t\ttitle = this.actionBaseTitle\n\t}\n\t// NO $basetitle BUT $template parameter is available\n\t// the title MUST be unique, otherwise the template would be overwritten\n\tif (!this.hasBase && this.useTemplate) {\n\t\ttitle = this.wiki.generateNewTitle(this.actionTemplate);\n\t} else if (!this.hasBase && !this.useTemplate) {\n\t\t// If NO $basetitle AND NO $template use initial title\n\t\t// DON'T overwrite any stuff\n\t\ttitle = this.wiki.generateNewTitle(title);\n\t}\n\tvar templateTiddler = this.wiki.getTiddler(this.actionTemplate) || {};\n\tvar tiddler = this.wiki.addTiddler(new $tw.Tiddler(templateTiddler.fields,creationFields,fields,modificationFields,{title: title}));\n\tif(this.actionSaveTitle) {\n\t\tthis.wiki.setTextReference(this.actionSaveTitle,title,this.getVariable(\"currentTiddler\"));\n\t}\n\tif(this.actionSaveDraftTitle) {\n\t\tthis.wiki.setTextReference(this.actionSaveDraftTitle,this.wiki.generateDraftTitle(title),this.getVariable(\"currentTiddler\"));\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-createtiddler\"] = CreateTiddlerWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-deletefield.js": {
            "title": "$:/core/modules/widgets/action-deletefield.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-deletefield.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to delete fields of a tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DeleteFieldWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDeleteFieldWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDeleteFieldWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nDeleteFieldWidget.prototype.execute = function() {\n\tthis.actionTiddler = this.getAttribute(\"$tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.actionField = this.getAttribute(\"$field\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nDeleteFieldWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$tiddler\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nDeleteFieldWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar self = this,\n\t\ttiddler = this.wiki.getTiddler(self.actionTiddler),\n\t\tremoveFields = {},\n\t\thasChanged = false;\n\tif(this.actionField && tiddler) {\n\t\tremoveFields[this.actionField] = undefined;\n\t\tif(this.actionField in tiddler.fields) {\n\t\t\thasChanged = true;\n\t\t}\n\t}\n\tif(tiddler) {\n\t\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\t\tif(name.charAt(0) !== \"$\" && name !== \"title\") {\n\t\t\t\tremoveFields[name] = undefined;\n\t\t\t\thasChanged = true;\n\t\t\t}\n\t\t});\n\t\tif(hasChanged) {\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,removeFields,this.wiki.getModificationFields()));\t\t\t\n\t\t}\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-deletefield\"] = DeleteFieldWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-deletetiddler.js": {
            "title": "$:/core/modules/widgets/action-deletetiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-deletetiddler.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to delete a tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DeleteTiddlerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDeleteTiddlerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDeleteTiddlerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nDeleteTiddlerWidget.prototype.execute = function() {\n\tthis.actionFilter = this.getAttribute(\"$filter\");\n\tthis.actionTiddler = this.getAttribute(\"$tiddler\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nDeleteTiddlerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$filter\"] || changedAttributes[\"$tiddler\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nDeleteTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar tiddlers = [];\n\tif(this.actionFilter) {\n\t\ttiddlers = this.wiki.filterTiddlers(this.actionFilter,this);\n\t}\n\tif(this.actionTiddler) {\n\t\ttiddlers.push(this.actionTiddler);\n\t}\n\tfor(var t=0; t<tiddlers.length; t++) {\n\t\tthis.wiki.deleteTiddler(tiddlers[t]);\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-deletetiddler\"] = DeleteTiddlerWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-listops.js": {
            "title": "$:/core/modules/widgets/action-listops.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-listops.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to apply list operations to any tiddler field (defaults to the 'list' field of the current tiddler)\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\nvar ActionListopsWidget = function(parseTreeNode, options) {\n\tthis.initialise(parseTreeNode, options);\n};\n/**\n * Inherit from the base widget class\n */\nActionListopsWidget.prototype = new Widget();\n/**\n * Render this widget into the DOM\n */\nActionListopsWidget.prototype.render = function(parent, nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n/**\n * Compute the internal state of the widget\n */\nActionListopsWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.target = this.getAttribute(\"$tiddler\", this.getVariable(\n\t\t\"currentTiddler\"));\n\tthis.filter = this.getAttribute(\"$filter\");\n\tthis.subfilter = this.getAttribute(\"$subfilter\");\n\tthis.listField = this.getAttribute(\"$field\", \"list\");\n\tthis.listIndex = this.getAttribute(\"$index\");\n\tthis.filtertags = this.getAttribute(\"$tags\");\n};\n/**\n * \tRefresh the widget by ensuring our attributes are up to date\n */\nActionListopsWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.$tiddler || changedAttributes.$filter ||\n\t\tchangedAttributes.$subfilter || changedAttributes.$field ||\n\t\tchangedAttributes.$index || changedAttributes.$tags) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n/**\n * \tInvoke the action associated with this widget\n */\nActionListopsWidget.prototype.invokeAction = function(triggeringWidget,\n\tevent) {\n\t//Apply the specified filters to the lists\n\tvar field = this.listField,\n\t\tindex,\n\t\ttype = \"!!\",\n\t\tlist = this.listField;\n\tif(this.listIndex) {\n\t\tfield = undefined;\n\t\tindex = this.listIndex;\n\t\ttype = \"##\";\n\t\tlist = this.listIndex;\n\t}\n\tif(this.filter) {\n\t\tthis.wiki.setText(this.target, field, index, $tw.utils.stringifyList(\n\t\t\tthis.wiki\n\t\t\t.filterTiddlers(this.filter, this)));\n\t}\n\tif(this.subfilter) {\n\t\tvar subfilter = \"[list[\" + this.target + type + list + \"]] \" + this.subfilter;\n\t\tthis.wiki.setText(this.target, field, index, $tw.utils.stringifyList(\n\t\t\tthis.wiki\n\t\t\t.filterTiddlers(subfilter, this)));\n\t}\n\tif(this.filtertags) {\n\t\tvar tiddler = this.wiki.getTiddler(this.target),\n\t\t\toldtags = tiddler ? (tiddler.fields.tags || []).slice(0) : [],\n\t\t\ttagfilter = \"[list[\" + this.target + \"!!tags]] \" + this.filtertags,\n\t\t\tnewtags = this.wiki.filterTiddlers(tagfilter,this);\n\t\tif($tw.utils.stringifyList(oldtags.sort()) !== $tw.utils.stringifyList(newtags.sort())) {\n\t\t\tthis.wiki.setText(this.target,\"tags\",undefined,$tw.utils.stringifyList(newtags));\t\t\t\n\t\t}\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-listops\"] = ActionListopsWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-navigate.js": {
            "title": "$:/core/modules/widgets/action-navigate.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-navigate.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to navigate to a tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar NavigateWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nNavigateWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nNavigateWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nNavigateWidget.prototype.execute = function() {\n\tthis.actionTo = this.getAttribute(\"$to\");\n\tthis.actionScroll = this.getAttribute(\"$scroll\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nNavigateWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$to\"] || changedAttributes[\"$scroll\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nNavigateWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tevent = event || {};\n\tvar bounds = triggeringWidget && triggeringWidget.getBoundingClientRect && triggeringWidget.getBoundingClientRect(),\n\t\tsuppressNavigation = event.metaKey || event.ctrlKey || (event.button === 1);\n\tif(this.actionScroll === \"yes\") {\n\t\tsuppressNavigation = false;\n\t} else if(this.actionScroll === \"no\") {\n\t\tsuppressNavigation = true;\n\t}\n\tthis.dispatchEvent({\n\t\ttype: \"tm-navigate\",\n\t\tnavigateTo: this.actionTo === undefined ? this.getVariable(\"currentTiddler\") : this.actionTo,\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tnavigateFromNode: triggeringWidget,\n\t\tnavigateFromClientRect: bounds && { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height\n\t\t},\n\t\tnavigateSuppressNavigation: suppressNavigation\n\t});\n\treturn true; // Action was invoked\n};\n\nexports[\"action-navigate\"] = NavigateWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-popup.js": {
            "title": "$:/core/modules/widgets/action-popup.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-popup.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to trigger a popup.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ActionPopupWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nActionPopupWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nActionPopupWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nActionPopupWidget.prototype.execute = function() {\n\tthis.actionState = this.getAttribute(\"$state\");\n\tthis.actionCoords = this.getAttribute(\"$coords\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nActionPopupWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$state\"] || changedAttributes[\"$coords\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nActionPopupWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\t// Trigger the popup\n\tvar popupLocationRegExp = /^\\((-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+)\\)$/,\n\t\tmatch = popupLocationRegExp.exec(this.actionCoords);\n\tif(match) {\n\t\t$tw.popup.triggerPopup({\n\t\t\tdomNode: null,\n\t\t\tdomNodeRect: {\n\t\t\t\tleft: parseFloat(match[1]),\n\t\t\t\ttop: parseFloat(match[2]),\n\t\t\t\twidth: parseFloat(match[3]),\n\t\t\t\theight: parseFloat(match[4])\n\t\t\t},\n\t\t\ttitle: this.actionState,\n\t\t\twiki: this.wiki\n\t\t});\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-popup\"] = ActionPopupWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-sendmessage.js": {
            "title": "$:/core/modules/widgets/action-sendmessage.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-sendmessage.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to send a message\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SendMessageWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSendMessageWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSendMessageWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nSendMessageWidget.prototype.execute = function() {\n\tthis.actionMessage = this.getAttribute(\"$message\");\n\tthis.actionParam = this.getAttribute(\"$param\");\n\tthis.actionName = this.getAttribute(\"$name\");\n\tthis.actionValue = this.getAttribute(\"$value\",\"\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nSendMessageWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(Object.keys(changedAttributes).length) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nSendMessageWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\t// Get the string parameter\n\tvar param = this.actionParam;\n\t// Assemble the attributes as a hashmap\n\tvar paramObject = Object.create(null);\n\tvar count = 0;\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tparamObject[name] = attribute;\n\t\t\tcount++;\n\t\t}\n\t});\n\t// Add name/value pair if present\n\tif(this.actionName) {\n\t\tparamObject[this.actionName] = this.actionValue;\n\t}\n\t// Dispatch the message\n\tthis.dispatchEvent({\n\t\ttype: this.actionMessage,\n\t\tparam: param,\n\t\tparamObject: paramObject,\n\t\ttiddlerTitle: this.getVariable(\"currentTiddler\"),\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tevent: event\n\t});\n\treturn true; // Action was invoked\n};\n\nexports[\"action-sendmessage\"] = SendMessageWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/action-setfield.js": {
            "title": "$:/core/modules/widgets/action-setfield.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/action-setfield.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to set a single field or index on a tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SetFieldWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSetFieldWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSetFieldWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nSetFieldWidget.prototype.execute = function() {\n\tthis.actionTiddler = this.getAttribute(\"$tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.actionField = this.getAttribute(\"$field\");\n\tthis.actionIndex = this.getAttribute(\"$index\");\n\tthis.actionValue = this.getAttribute(\"$value\");\n\tthis.actionTimestamp = this.getAttribute(\"$timestamp\",\"yes\") === \"yes\";\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nSetFieldWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$tiddler\"] || changedAttributes[\"$field\"] || changedAttributes[\"$index\"] || changedAttributes[\"$value\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nSetFieldWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar self = this,\n\t\toptions = {};\n\toptions.suppressTimestamp = !this.actionTimestamp;\n\tif((typeof this.actionField == \"string\") || (typeof this.actionIndex == \"string\")  || (typeof this.actionValue == \"string\")) {\n\t\tthis.wiki.setText(this.actionTiddler,this.actionField,this.actionIndex,this.actionValue,options);\n\t}\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tself.wiki.setText(self.actionTiddler,name,undefined,attribute,options);\n\t\t}\n\t});\n\treturn true; // Action was invoked\n};\n\nexports[\"action-setfield\"] = SetFieldWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/browse.js": {
            "title": "$:/core/modules/widgets/browse.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/browse.js\ntype: application/javascript\nmodule-type: widget\n\nBrowse widget for browsing for files to import\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar BrowseWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nBrowseWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nBrowseWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\tvar domNode = this.document.createElement(\"input\");\n\tdomNode.setAttribute(\"type\",\"file\");\n\tif(this.browseMultiple) {\n\t\tdomNode.setAttribute(\"multiple\",\"multiple\");\n\t}\n\tif(this.tooltip) {\n\t\tdomNode.setAttribute(\"title\",this.tooltip);\n\t}\n\t// Nw.js supports \"nwsaveas\" to force a \"save as\" dialogue that allows a new or existing file to be selected\n\tif(this.nwsaveas) {\n\t\tdomNode.setAttribute(\"nwsaveas\",this.nwsaveas);\n\t}\n\t// Nw.js supports \"webkitdirectory\" and \"nwdirectory\" to allow a directory to be selected\n\tif(this.webkitdirectory) {\n\t\tdomNode.setAttribute(\"webkitdirectory\",this.webkitdirectory);\n\t}\n\tif(this.nwdirectory) {\n\t\tdomNode.setAttribute(\"nwdirectory\",this.nwdirectory);\n\t}\n\t// Add a click event handler\n\tdomNode.addEventListener(\"change\",function (event) {\n\t\tif(self.message) {\n\t\t\tself.dispatchEvent({type: self.message, param: self.param, files: event.target.files});\n\t\t} else {\n\t\t\tself.wiki.readFiles(event.target.files,{\n\t\t\t\tcallback: function(tiddlerFieldsArray) {\n\t\t\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify(tiddlerFieldsArray)});\n\t\t\t\t},\n\t\t\t\tdeserializer: self.deserializer\n\t\t\t});\n\t\t}\n\t\treturn false;\n\t},false);\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nBrowseWidget.prototype.execute = function() {\n\tthis.browseMultiple = this.getAttribute(\"multiple\");\n\tthis.deserializer = this.getAttribute(\"deserializer\");\n\tthis.message = this.getAttribute(\"message\");\n\tthis.param = this.getAttribute(\"param\");\n\tthis.tooltip = this.getAttribute(\"tooltip\");\n\tthis.nwsaveas = this.getAttribute(\"nwsaveas\");\n\tthis.webkitdirectory = this.getAttribute(\"webkitdirectory\");\n\tthis.nwdirectory = this.getAttribute(\"nwdirectory\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nBrowseWidget.prototype.refresh = function(changedTiddlers) {\n\treturn false;\n};\n\nexports.browse = BrowseWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/button.js": {
            "title": "$:/core/modules/widgets/button.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/button.js\ntype: application/javascript\nmodule-type: widget\n\nButton widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ButtonWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nButtonWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nButtonWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\tvar tag = \"button\";\n\tif(this.buttonTag && $tw.config.htmlUnsafeElements.indexOf(this.buttonTag) === -1) {\n\t\ttag = this.buttonTag;\n\t}\n\tvar domNode = this.document.createElement(tag);\n\t// Assign classes\n\tvar classes = this[\"class\"].split(\" \") || [],\n\t\tisPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp();\n\tif(this.selectedClass) {\n\t\tif((this.set || this.setTitle) && this.setTo && this.isSelected()) {\n\t\t\t$tw.utils.pushTop(classes,this.selectedClass.split(\" \"));\n\t\t}\n\t\tif(isPoppedUp) {\n\t\t\t$tw.utils.pushTop(classes,this.selectedClass.split(\" \"));\n\t\t}\n\t}\n\tif(isPoppedUp) {\n\t\t$tw.utils.pushTop(classes,\"tc-popup-handle\");\n\t}\n\tdomNode.className = classes.join(\" \");\n\t// Assign other attributes\n\tif(this.style) {\n\t\tdomNode.setAttribute(\"style\",this.style);\n\t}\n\tif(this.tooltip) {\n\t\tdomNode.setAttribute(\"title\",this.tooltip);\n\t}\n\tif(this[\"aria-label\"]) {\n\t\tdomNode.setAttribute(\"aria-label\",this[\"aria-label\"]);\n\t}\n\t// Set the tabindex\n\tif(this.tabIndex) {\n\t\tdomNode.setAttribute(\"tabindex\",this.tabIndex);\n\t}\t\n\t// Add a click event handler\n\tdomNode.addEventListener(\"click\",function (event) {\n\t\tvar handled = false;\n\t\tif(self.invokeActions(self,event)) {\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.to) {\n\t\t\tself.navigateTo(event);\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.message) {\n\t\t\tself.dispatchMessage(event);\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.popup || self.popupTitle) {\n\t\t\tself.triggerPopup(event);\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.set || self.setTitle) {\n\t\t\tself.setTiddler();\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.actions) {\n\t\t\tself.invokeActionString(self.actions,self,event);\n\t\t}\n\t\tif(handled) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t\treturn handled;\n\t},false);\n\t// Make it draggable if required\n\tif(this.dragTiddler || this.dragFilter) {\n\t\t$tw.utils.makeDraggable({\n\t\t\tdomNode: domNode,\n\t\t\tdragTiddlerFn: function() {return self.dragTiddler;},\n\t\t\tdragFilterFn: function() {return self.dragFilter;},\n\t\t\twidget: this\n\t\t});\n\t}\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nWe don't allow actions to propagate because we trigger actions ourselves\n*/\nButtonWidget.prototype.allowActionPropagation = function() {\n\treturn false;\n};\n\nButtonWidget.prototype.getBoundingClientRect = function() {\n\treturn this.domNodes[0].getBoundingClientRect();\n};\n\nButtonWidget.prototype.isSelected = function() {\n    return this.setTitle ? (this.setField ? this.wiki.getTiddler(this.setTitle).getFieldString(this.setField) === this.setTo :\n\t\t(this.setIndex ? this.wiki.extractTiddlerDataItem(this.setTitle,this.setIndex) === this.setTo :\n\t\t\tthis.wiki.getTiddlerText(this.setTitle))) || this.defaultSetValue || this.getVariable(\"currentTiddler\") :\n\t\tthis.wiki.getTextReference(this.set,this.defaultSetValue,this.getVariable(\"currentTiddler\")) === this.setTo;\n};\n\nButtonWidget.prototype.isPoppedUp = function() {\n\tvar tiddler = this.popupTitle ? this.wiki.getTiddler(this.popupTitle) : this.wiki.getTiddler(this.popup);\n\tvar result = tiddler && tiddler.fields.text ? $tw.popup.readPopupState(tiddler.fields.text) : false;\n\treturn result;\n};\n\nButtonWidget.prototype.navigateTo = function(event) {\n\tvar bounds = this.getBoundingClientRect();\n\tthis.dispatchEvent({\n\t\ttype: \"tm-navigate\",\n\t\tnavigateTo: this.to,\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tnavigateFromNode: this,\n\t\tnavigateFromClientRect: { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height\n\t\t},\n\t\tnavigateSuppressNavigation: event.metaKey || event.ctrlKey || (event.button === 1),\n\t\tevent: event\n\t});\n};\n\nButtonWidget.prototype.dispatchMessage = function(event) {\n\tthis.dispatchEvent({type: this.message, param: this.param, tiddlerTitle: this.getVariable(\"currentTiddler\"), event: event});\n};\n\nButtonWidget.prototype.triggerPopup = function(event) {\n\tif(this.popupTitle) {\n\t\t$tw.popup.triggerPopup({\n\t\t\tdomNode: this.domNodes[0],\n\t\t\ttitle: this.popupTitle,\n\t\t\twiki: this.wiki,\n\t\t\tnoStateReference: true\n\t\t});\n\t} else {\n\t\t$tw.popup.triggerPopup({\n\t\t\tdomNode: this.domNodes[0],\n\t\t\ttitle: this.popup,\n\t\t\twiki: this.wiki\n\t\t});\n\t}\n};\n\nButtonWidget.prototype.setTiddler = function() {\n\tif(this.setTitle) {\n\t\tthis.setField ? this.wiki.setText(this.setTitle,this.setField,undefined,this.setTo) :\n\t\t\t\t(this.setIndex ? this.wiki.setText(this.setTitle,undefined,this.setIndex,this.setTo) :\n\t\t\t\tthis.wiki.setText(this.setTitle,\"text\",undefined,this.setTo));\n\t} else {\n\t\tthis.wiki.setTextReference(this.set,this.setTo,this.getVariable(\"currentTiddler\"));\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nButtonWidget.prototype.execute = function() {\n\t// Get attributes\n\tthis.actions = this.getAttribute(\"actions\");\n\tthis.to = this.getAttribute(\"to\");\n\tthis.message = this.getAttribute(\"message\");\n\tthis.param = this.getAttribute(\"param\");\n\tthis.set = this.getAttribute(\"set\");\n\tthis.setTo = this.getAttribute(\"setTo\");\n\tthis.popup = this.getAttribute(\"popup\");\n\tthis.hover = this.getAttribute(\"hover\");\n\tthis[\"class\"] = this.getAttribute(\"class\",\"\");\n\tthis[\"aria-label\"] = this.getAttribute(\"aria-label\");\n\tthis.tooltip = this.getAttribute(\"tooltip\");\n\tthis.style = this.getAttribute(\"style\");\n\tthis.selectedClass = this.getAttribute(\"selectedClass\");\n\tthis.defaultSetValue = this.getAttribute(\"default\",\"\");\n\tthis.buttonTag = this.getAttribute(\"tag\");\n\tthis.dragTiddler = this.getAttribute(\"dragTiddler\");\n\tthis.dragFilter = this.getAttribute(\"dragFilter\");\n\tthis.setTitle = this.getAttribute(\"setTitle\");\n\tthis.setField = this.getAttribute(\"setField\");\n\tthis.setIndex = this.getAttribute(\"setIndex\");\n\tthis.popupTitle = this.getAttribute(\"popupTitle\");\n\tthis.tabIndex = this.getAttribute(\"tabindex\");\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nButtonWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes[\"class\"] || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.button = ButtonWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/checkbox.js": {
            "title": "$:/core/modules/widgets/checkbox.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/checkbox.js\ntype: application/javascript\nmodule-type: widget\n\nCheckbox widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CheckboxWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCheckboxWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCheckboxWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Create our elements\n\tthis.labelDomNode = this.document.createElement(\"label\");\n\tthis.labelDomNode.setAttribute(\"class\",this.checkboxClass);\n\tthis.inputDomNode = this.document.createElement(\"input\");\n\tthis.inputDomNode.setAttribute(\"type\",\"checkbox\");\n\tif(this.getValue()) {\n\t\tthis.inputDomNode.setAttribute(\"checked\",\"true\");\n\t}\n\tthis.labelDomNode.appendChild(this.inputDomNode);\n\tthis.spanDomNode = this.document.createElement(\"span\");\n\tthis.labelDomNode.appendChild(this.spanDomNode);\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(this.inputDomNode,[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n\t// Insert the label into the DOM and render any children\n\tparent.insertBefore(this.labelDomNode,nextSibling);\n\tthis.renderChildren(this.spanDomNode,null);\n\tthis.domNodes.push(this.labelDomNode);\n};\n\nCheckboxWidget.prototype.getValue = function() {\n\tvar tiddler = this.wiki.getTiddler(this.checkboxTitle);\n\tif(tiddler) {\n\t\tif(this.checkboxTag) {\n\t\t\tif(this.checkboxInvertTag) {\n\t\t\t\treturn !tiddler.hasTag(this.checkboxTag);\n\t\t\t} else {\n\t\t\t\treturn tiddler.hasTag(this.checkboxTag);\n\t\t\t}\n\t\t}\n\t\tif(this.checkboxField) {\n\t\t\tvar value;\n\t\t\tif($tw.utils.hop(tiddler.fields,this.checkboxField)) {\n\t\t\t\tvalue = tiddler.fields[this.checkboxField] || \"\";\n\t\t\t} else {\n\t\t\t\tvalue = this.checkboxDefault || \"\";\n\t\t\t}\n\t\t\tif(value === this.checkboxChecked) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(value === this.checkboxUnchecked) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\tif(this.checkboxIndex) {\n\t\t\tvar value = this.wiki.extractTiddlerDataItem(tiddler,this.checkboxIndex,this.checkboxDefault || \"\");\n\t\t\tif(value === this.checkboxChecked) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(value === this.checkboxUnchecked) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif(this.checkboxTag) {\n\t\t\treturn false;\n\t\t}\n\t\tif(this.checkboxField) {\n\t\t\tif(this.checkboxDefault === this.checkboxChecked) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(this.checkboxDefault === this.checkboxUnchecked) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n};\n\nCheckboxWidget.prototype.handleChangeEvent = function(event) {\n\tvar checked = this.inputDomNode.checked,\n\t\ttiddler = this.wiki.getTiddler(this.checkboxTitle),\n\t\tfallbackFields = {text: \"\"},\n\t\tnewFields = {title: this.checkboxTitle},\n\t\thasChanged = false,\n\t\ttagCheck = false,\n\t\thasTag = tiddler && tiddler.hasTag(this.checkboxTag),\n\t\tvalue = checked ? this.checkboxChecked : this.checkboxUnchecked;\n\tif(this.checkboxTag && this.checkboxInvertTag === \"yes\") {\n\t\ttagCheck = hasTag === checked;\n\t} else {\n\t\ttagCheck = hasTag !== checked;\n\t}\n\t// Set the tag if specified\n\tif(this.checkboxTag && (!tiddler || tagCheck)) {\n\t\tnewFields.tags = tiddler ? (tiddler.fields.tags || []).slice(0) : [];\n\t\tvar pos = newFields.tags.indexOf(this.checkboxTag);\n\t\tif(pos !== -1) {\n\t\t\tnewFields.tags.splice(pos,1);\n\t\t}\n\t\tif(this.checkboxInvertTag === \"yes\" && !checked) {\n\t\t\tnewFields.tags.push(this.checkboxTag);\n\t\t} else if(this.checkboxInvertTag !== \"yes\" && checked) {\n\t\t\tnewFields.tags.push(this.checkboxTag);\n\t\t}\n\t\thasChanged = true;\n\t}\n\t// Set the field if specified\n\tif(this.checkboxField) {\n\t\tif(!tiddler || tiddler.fields[this.checkboxField] !== value) {\n\t\t\tnewFields[this.checkboxField] = value;\n\t\t\thasChanged = true;\n\t\t}\n\t}\n\t// Set the index if specified\n\tif(this.checkboxIndex) {\n\t\tvar indexValue = this.wiki.extractTiddlerDataItem(this.checkboxTitle,this.checkboxIndex);\n\t\tif(!tiddler || indexValue !== value) {\n\t\t\thasChanged = true;\n\t\t}\n\t}\n\tif(hasChanged) {\n\t\tif(this.checkboxIndex) {\n\t\t\tthis.wiki.setText(this.checkboxTitle,\"\",this.checkboxIndex,value);\n\t\t} else {\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),fallbackFields,tiddler,newFields,this.wiki.getModificationFields()));\n\t\t}\n\t}\n\t// Trigger actions\n\tif(this.checkboxActions) {\n\t\tthis.invokeActionString(this.checkboxActions,this,event);\n\t}\n\tif(this.checkboxCheckActions && checked) {\n\t\tthis.invokeActionString(this.checkboxCheckActions,this,event);\n\t}\n\tif(this.checkboxUncheckActions && !checked) {\n\t\tthis.invokeActionString(this.checkboxUncheckActions,this,event);\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nCheckboxWidget.prototype.execute = function() {\n\t// Get the parameters from the attributes\n\tthis.checkboxActions = this.getAttribute(\"actions\");\n\tthis.checkboxCheckActions = this.getAttribute(\"checkactions\");\n\tthis.checkboxUncheckActions = this.getAttribute(\"uncheckactions\");\n\tthis.checkboxTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.checkboxTag = this.getAttribute(\"tag\");\n\tthis.checkboxField = this.getAttribute(\"field\");\n\tthis.checkboxIndex = this.getAttribute(\"index\");\n\tthis.checkboxChecked = this.getAttribute(\"checked\");\n\tthis.checkboxUnchecked = this.getAttribute(\"unchecked\");\n\tthis.checkboxDefault = this.getAttribute(\"default\");\n\tthis.checkboxClass = this.getAttribute(\"class\",\"\");\n\tthis.checkboxInvertTag = this.getAttribute(\"invertTag\",\"\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nCheckboxWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.tag || changedAttributes.invertTag || changedAttributes.field || changedAttributes.index || changedAttributes.checked || changedAttributes.unchecked || changedAttributes[\"default\"] || changedAttributes[\"class\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\tvar refreshed = false;\n\t\tif(changedTiddlers[this.checkboxTitle]) {\n\t\t\tthis.inputDomNode.checked = this.getValue();\n\t\t\trefreshed = true;\n\t\t}\n\t\treturn this.refreshChildren(changedTiddlers) || refreshed;\n\t}\n};\n\nexports.checkbox = CheckboxWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/codeblock.js": {
            "title": "$:/core/modules/widgets/codeblock.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/codeblock.js\ntype: application/javascript\nmodule-type: widget\n\nCode block node widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CodeBlockWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCodeBlockWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCodeBlockWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar codeNode = this.document.createElement(\"code\"),\n\t\tdomNode = this.document.createElement(\"pre\");\n\tcodeNode.appendChild(this.document.createTextNode(this.getAttribute(\"code\")));\n\tdomNode.appendChild(codeNode);\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.domNodes.push(domNode);\n\tif(this.postRender) {\n\t\tthis.postRender();\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nCodeBlockWidget.prototype.execute = function() {\n\tthis.language = this.getAttribute(\"language\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nCodeBlockWidget.prototype.refresh = function(changedTiddlers) {\n\treturn false;\n};\n\nexports.codeblock = CodeBlockWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/count.js": {
            "title": "$:/core/modules/widgets/count.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/count.js\ntype: application/javascript\nmodule-type: widget\n\nCount widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CountWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCountWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCountWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar textNode = this.document.createTextNode(this.currentCount);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nCountWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.filter = this.getAttribute(\"filter\");\n\t// Execute the filter\n\tif(this.filter) {\n\t\tthis.currentCount = this.wiki.filterTiddlers(this.filter,this).length;\n\t} else {\n\t\tthis.currentCount = \"0\";\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nCountWidget.prototype.refresh = function(changedTiddlers) {\n\t// Re-execute the filter to get the count\n\tthis.computeAttributes();\n\tvar oldCount = this.currentCount;\n\tthis.execute();\n\tif(this.currentCount !== oldCount) {\n\t\t// Regenerate and rerender the widget and replace the existing DOM node\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n\n};\n\nexports.count = CountWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/diff-text.js": {
            "title": "$:/core/modules/widgets/diff-text.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/diff-text.js\ntype: application/javascript\nmodule-type: widget\n\nWidget to display a diff between two texts\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget,\n\tdmp = require(\"$:/core/modules/utils/diff-match-patch/diff_match_patch.js\");\n\nvar DiffTextWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDiffTextWidget.prototype = new Widget();\n\nDiffTextWidget.prototype.invisibleCharacters = {\n\t\"\\n\": \"↩︎\\n\",\n\t\"\\r\": \"⇠\",\n\t\"\\t\": \"⇥\\t\"\n};\n\n/*\nRender this widget into the DOM\n*/\nDiffTextWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create the diff\n\tvar dmpObject = new dmp.diff_match_patch(),\n\t\tdiffs = dmpObject.diff_main(this.getAttribute(\"source\"),this.getAttribute(\"dest\"));\n\t// Apply required cleanup\n\tswitch(this.getAttribute(\"cleanup\",\"semantic\")) {\n\t\tcase \"none\":\n\t\t\t// No cleanup\n\t\t\tbreak;\n\t\tcase \"efficiency\":\n\t\t\tdmpObject.diff_cleanupEfficiency(diffs);\n\t\t\tbreak;\n\t\tdefault: // case \"semantic\"\n\t\t\tdmpObject.diff_cleanupSemantic(diffs);\n\t\t\tbreak;\n\t}\n\t// Create the elements\n\tvar domContainer = this.document.createElement(\"div\"), \n\t\tdomDiff = this.createDiffDom(diffs);\n\tparent.insertBefore(domContainer,nextSibling);\n\t// Set variables\n\tthis.setVariable(\"diff-count\",diffs.reduce(function(acc,diff) {\n\t\tif(diff[0] !== dmp.DIFF_EQUAL) {\n\t\t\tacc++;\n\t\t}\n\t\treturn acc;\n\t},0).toString());\n\t// Render child widgets\n\tthis.renderChildren(domContainer,null);\n\t// Render the diff\n\tdomContainer.appendChild(domDiff);\n\t// Save our container\n\tthis.domNodes.push(domContainer);\n};\n\n/*\nCreate DOM elements representing a list of diffs\n*/\nDiffTextWidget.prototype.createDiffDom = function(diffs) {\n\tvar self = this;\n\t// Create the element and assign the attributes\n\tvar domPre = this.document.createElement(\"pre\"),\n\t\tdomCode = this.document.createElement(\"code\");\n\t$tw.utils.each(diffs,function(diff) {\n\t\tvar tag = diff[0] === dmp.DIFF_INSERT ? \"ins\" : (diff[0] === dmp.DIFF_DELETE ? \"del\" : \"span\"),\n\t\t\tclassName = diff[0] === dmp.DIFF_INSERT ? \"tc-diff-insert\" : (diff[0] === dmp.DIFF_DELETE ? \"tc-diff-delete\" : \"tc-diff-equal\"),\n\t\t\tdom = self.document.createElement(tag),\n\t\t\ttext = diff[1],\n\t\t\tcurrPos = 0,\n\t\t\tre = /([\\x00-\\x1F])/mg,\n\t\t\tmatch = re.exec(text),\n\t\t\tspan,\n\t\t\tprintable;\n\t\tdom.className = className;\n\t\twhile(match) {\n\t\t\tif(currPos < match.index) {\n\t\t\t\tdom.appendChild(self.document.createTextNode(text.slice(currPos,match.index)));\n\t\t\t}\n\t\t\tspan = self.document.createElement(\"span\");\n\t\t\tspan.className = \"tc-diff-invisible\";\n\t\t\tprintable = self.invisibleCharacters[match[0]] || (\"[0x\" + match[0].charCodeAt(0).toString(16) + \"]\");\n\t\t\tspan.appendChild(self.document.createTextNode(printable));\n\t\t\tdom.appendChild(span);\n\t\t\tcurrPos = match.index + match[0].length;\n\t\t\tmatch = re.exec(text);\n\t\t}\n\t\tif(currPos < text.length) {\n\t\t\tdom.appendChild(self.document.createTextNode(text.slice(currPos)));\n\t\t}\n\t\tdomCode.appendChild(dom);\n\t});\n\tdomPre.appendChild(domCode);\n\treturn domPre;\n};\n\n/*\nCompute the internal state of the widget\n*/\nDiffTextWidget.prototype.execute = function() {\n\t// Make child widgets\n\tvar parseTreeNodes;\n\tif(this.parseTreeNode && this.parseTreeNode.children && this.parseTreeNode.children.length > 0) {\n\t\tparseTreeNodes = this.parseTreeNode.children;\n\t} else {\n\t\tparseTreeNodes = [{\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: \"$:/language/Diffs/CountMessage\"}\n\t\t\t}\n\t\t}];\n\t}\n\tthis.makeChildWidgets(parseTreeNodes);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nDiffTextWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.source || changedAttributes.dest || changedAttributes.cleanup) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports[\"diff-text\"] = DiffTextWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/draggable.js": {
            "title": "$:/core/modules/widgets/draggable.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/draggable.js\ntype: application/javascript\nmodule-type: widget\n\nDraggable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DraggableWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDraggableWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDraggableWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Sanitise the specified tag\n\tvar tag = this.draggableTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"div\";\n\t}\n\t// Create our element\n\tvar domNode = this.document.createElement(tag);\n\t// Assign classes\n\tvar classes = [\"tc-draggable\"];\n\tif(this.draggableClasses) {\n\t\tclasses.push(this.draggableClasses);\n\t}\n\tdomNode.setAttribute(\"class\",classes.join(\" \"));\n\t// Add event handlers\n\t$tw.utils.makeDraggable({\n\t\tdomNode: domNode,\n\t\tdragTiddlerFn: function() {return self.getAttribute(\"tiddler\");},\n\t\tdragFilterFn: function() {return self.getAttribute(\"filter\");},\n\t\tstartActions: self.startActions,\n\t\tendActions: self.endActions,\n\t\twidget: this\n\t});\n\t// Insert the link into the DOM and render any children\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nDraggableWidget.prototype.execute = function() {\n\t// Pick up our attributes\n\tthis.draggableTag = this.getAttribute(\"tag\",\"div\");\n\tthis.draggableClasses = this.getAttribute(\"class\");\n\tthis.startActions = this.getAttribute(\"startactions\");\n\tthis.endActions = this.getAttribute(\"endactions\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nDraggableWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tag || changedAttributes[\"class\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.draggable = DraggableWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/droppable.js": {
            "title": "$:/core/modules/widgets/droppable.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/droppable.js\ntype: application/javascript\nmodule-type: widget\n\nDroppable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DroppableWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDroppableWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDroppableWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar tag = this.parseTreeNode.isBlock ? \"div\" : \"span\";\n\tif(this.droppableTag && $tw.config.htmlUnsafeElements.indexOf(this.droppableTag) === -1) {\n\t\ttag = this.droppableTag;\n\t}\n\t// Create element and assign classes\n\tvar domNode = this.document.createElement(tag),\n\t\tclasses = (this[\"class\"] || \"\").split(\" \");\n\tclasses.push(\"tc-droppable\");\n\tdomNode.className = classes.join(\" \");\n\t// Add event handlers\n\tif(this.droppableEnable) {\n\t\t$tw.utils.addEventListeners(domNode,[\n\t\t\t{name: \"dragenter\", handlerObject: this, handlerMethod: \"handleDragEnterEvent\"},\n\t\t\t{name: \"dragover\", handlerObject: this, handlerMethod: \"handleDragOverEvent\"},\n\t\t\t{name: \"dragleave\", handlerObject: this, handlerMethod: \"handleDragLeaveEvent\"},\n\t\t\t{name: \"drop\", handlerObject: this, handlerMethod: \"handleDropEvent\"}\n\t\t]);\t\t\n\t}\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n\t// Stack of outstanding enter/leave events\n\tthis.currentlyEntered = [];\n};\n\nDroppableWidget.prototype.enterDrag = function(event) {\n\tif(this.currentlyEntered.indexOf(event.target) === -1) {\n\t\tthis.currentlyEntered.push(event.target);\n\t}\n\t// If we're entering for the first time we need to apply highlighting\n\t$tw.utils.addClass(this.domNodes[0],\"tc-dragover\");\n};\n\nDroppableWidget.prototype.leaveDrag = function(event) {\n\tvar pos = this.currentlyEntered.indexOf(event.target);\n\tif(pos !== -1) {\n\t\tthis.currentlyEntered.splice(pos,1);\n\t}\n\t// Remove highlighting if we're leaving externally. The hacky second condition is to resolve a problem with Firefox whereby there is an erroneous dragenter event if the node being dragged is within the dropzone\n\tif(this.currentlyEntered.length === 0 || (this.currentlyEntered.length === 1 && this.currentlyEntered[0] === $tw.dragInProgress)) {\n\t\tthis.currentlyEntered = [];\n\t\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t}\n};\n\nDroppableWidget.prototype.handleDragEnterEvent  = function(event) {\n\tthis.enterDrag(event);\n\t// Tell the browser that we're ready to handle the drop\n\tevent.preventDefault();\n\t// Tell the browser not to ripple the drag up to any parent drop handlers\n\tevent.stopPropagation();\n\treturn false;\n};\n\nDroppableWidget.prototype.handleDragOverEvent  = function(event) {\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\t// Tell the browser that we're still interested in the drop\n\tevent.preventDefault();\n\t// Set the drop effect\n\tevent.dataTransfer.dropEffect = this.droppableEffect;\n\treturn false;\n};\n\nDroppableWidget.prototype.handleDragLeaveEvent  = function(event) {\n\tthis.leaveDrag(event);\n\treturn false;\n};\n\nDroppableWidget.prototype.handleDropEvent  = function(event) {\n\tvar self = this;\n\tthis.leaveDrag(event);\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\tvar dataTransfer = event.dataTransfer;\n\t// Remove highlighting\n\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t// Try to import the various data types we understand\n\t$tw.utils.importDataTransfer(dataTransfer,null,function(fieldsArray) {\n\t\tfieldsArray.forEach(function(fields) {\n\t\t\tself.performActions(fields.title || fields.text,event);\n\t\t});\n\t});\n\t// Tell the browser that we handled the drop\n\tevent.preventDefault();\n\t// Stop the drop ripple up to any parent handlers\n\tevent.stopPropagation();\n\treturn false;\n};\n\nDroppableWidget.prototype.performActions = function(title,event) {\n\tif(this.droppableActions) {\n\t\tvar modifierKey = event.ctrlKey && ! event.shiftKey ? \"ctrl\" : event.shiftKey && !event.ctrlKey ? \"shift\" : \n\t\t\t\tevent.ctrlKey && event.shiftKey ? \"ctrl-shift\" : \"normal\" ;\n\t\tthis.invokeActionString(this.droppableActions,this,event,{actionTiddler: title, modifier: modifierKey});\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nDroppableWidget.prototype.execute = function() {\n\tthis.droppableActions = this.getAttribute(\"actions\");\n\tthis.droppableEffect = this.getAttribute(\"effect\",\"copy\");\n\tthis.droppableTag = this.getAttribute(\"tag\");\n\tthis.droppableClass = this.getAttribute(\"class\");\n\tthis.droppableEnable = (this.getAttribute(\"enable\") || \"yes\") === \"yes\";\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nDroppableWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"class\"] || changedAttributes.tag || changedAttributes.enable) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.droppable = DroppableWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/dropzone.js": {
            "title": "$:/core/modules/widgets/dropzone.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/dropzone.js\ntype: application/javascript\nmodule-type: widget\n\nDropzone widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DropZoneWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDropZoneWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDropZoneWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\tvar domNode = this.document.createElement(\"div\");\n\tdomNode.className = this.dropzoneClass || \"tc-dropzone\";\n\t// Add event handlers\n\tif(this.dropzoneEnable) {\n\t\t$tw.utils.addEventListeners(domNode,[\n\t\t\t{name: \"dragenter\", handlerObject: this, handlerMethod: \"handleDragEnterEvent\"},\n\t\t\t{name: \"dragover\", handlerObject: this, handlerMethod: \"handleDragOverEvent\"},\n\t\t\t{name: \"dragleave\", handlerObject: this, handlerMethod: \"handleDragLeaveEvent\"},\n\t\t\t{name: \"drop\", handlerObject: this, handlerMethod: \"handleDropEvent\"},\n\t\t\t{name: \"paste\", handlerObject: this, handlerMethod: \"handlePasteEvent\"},\n\t\t\t{name: \"dragend\", handlerObject: this, handlerMethod: \"handleDragEndEvent\"}\n\t\t]);\t\t\n\t}\n\tdomNode.addEventListener(\"click\",function (event) {\n\t},false);\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n\t// Stack of outstanding enter/leave events\n\tthis.currentlyEntered = [];\n};\n\nDropZoneWidget.prototype.enterDrag = function(event) {\n\tif(this.currentlyEntered.indexOf(event.target) === -1) {\n\t\tthis.currentlyEntered.push(event.target);\n\t}\n\t// If we're entering for the first time we need to apply highlighting\n\t$tw.utils.addClass(this.domNodes[0],\"tc-dragover\");\n};\n\nDropZoneWidget.prototype.leaveDrag = function(event) {\n\tvar pos = this.currentlyEntered.indexOf(event.target);\n\tif(pos !== -1) {\n\t\tthis.currentlyEntered.splice(pos,1);\n\t}\n\t// Remove highlighting if we're leaving externally\n\tif(this.currentlyEntered.length === 0) {\n\t\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t}\n};\n\nDropZoneWidget.prototype.handleDragEnterEvent  = function(event) {\n\t// Check for this window being the source of the drag\n\tif($tw.dragInProgress) {\n\t\treturn false;\n\t}\n\tthis.enterDrag(event);\n\t// Tell the browser that we're ready to handle the drop\n\tevent.preventDefault();\n\t// Tell the browser not to ripple the drag up to any parent drop handlers\n\tevent.stopPropagation();\n};\n\nDropZoneWidget.prototype.handleDragOverEvent  = function(event) {\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\t// Check for this window being the source of the drag\n\tif($tw.dragInProgress) {\n\t\treturn false;\n\t}\n\t// Tell the browser that we're still interested in the drop\n\tevent.preventDefault();\n\tevent.dataTransfer.dropEffect = \"copy\"; // Explicitly show this is a copy\n};\n\nDropZoneWidget.prototype.handleDragLeaveEvent  = function(event) {\n\tthis.leaveDrag(event);\n};\n\nDropZoneWidget.prototype.handleDragEndEvent = function(event) {\n\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n};\n\nDropZoneWidget.prototype.handleDropEvent  = function(event) {\n\tvar self = this,\n\t\treadFileCallback = function(tiddlerFieldsArray) {\n\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify(tiddlerFieldsArray)});\n\t\t};\n\tthis.leaveDrag(event);\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\t// Check for this window being the source of the drag\n\tif($tw.dragInProgress) {\n\t\treturn false;\n\t}\n\tvar self = this,\n\t\tdataTransfer = event.dataTransfer;\n\t// Remove highlighting\n\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t// Import any files in the drop\n\tvar numFiles = 0;\n\tif(dataTransfer.files) {\n\t\tnumFiles = this.wiki.readFiles(dataTransfer.files,{\n\t\t\tcallback: readFileCallback,\n\t\t\tdeserializer: this.dropzoneDeserializer\n\t\t});\n\t}\n\t// Try to import the various data types we understand\n\tif(numFiles === 0) {\n\t\t$tw.utils.importDataTransfer(dataTransfer,this.wiki.generateNewTitle(\"Untitled\"),readFileCallback);\n\t}\n\t// Tell the browser that we handled the drop\n\tevent.preventDefault();\n\t// Stop the drop ripple up to any parent handlers\n\tevent.stopPropagation();\n};\n\nDropZoneWidget.prototype.handlePasteEvent  = function(event) {\n\tvar self = this,\n\t\treadFileCallback = function(tiddlerFieldsArray) {\n\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify(tiddlerFieldsArray)});\n\t\t};\n\t// Let the browser handle it if we're in a textarea or input box\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) == -1 && !event.target.isContentEditable) {\n\t\tvar self = this,\n\t\t\titems = event.clipboardData.items;\n\t\t// Enumerate the clipboard items\n\t\tfor(var t = 0; t<items.length; t++) {\n\t\t\tvar item = items[t];\n\t\t\tif(item.kind === \"file\") {\n\t\t\t\t// Import any files\n\t\t\t\tthis.wiki.readFile(item.getAsFile(),{\n\t\t\t\t\tcallback: readFileCallback,\n\t\t\t\t\tdeserializer: this.dropzoneDeserializer\n\t\t\t\t});\n\t\t\t} else if(item.kind === \"string\") {\n\t\t\t\t// Create tiddlers from string items\n\t\t\t\tvar type = item.type;\n\t\t\t\titem.getAsString(function(str) {\n\t\t\t\t\tvar tiddlerFields = {\n\t\t\t\t\t\ttitle: self.wiki.generateNewTitle(\"Untitled\"),\n\t\t\t\t\t\ttext: str,\n\t\t\t\t\t\ttype: type\n\t\t\t\t\t};\n\t\t\t\t\tif($tw.log.IMPORT) {\n\t\t\t\t\t\tconsole.log(\"Importing string '\" + str + \"', type: '\" + type + \"'\");\n\t\t\t\t\t}\n\t\t\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify([tiddlerFields])});\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t// Tell the browser that we've handled the paste\n\t\tevent.stopPropagation();\n\t\tevent.preventDefault();\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nDropZoneWidget.prototype.execute = function() {\n\tthis.dropzoneClass = this.getAttribute(\"class\");\n\tthis.dropzoneDeserializer = this.getAttribute(\"deserializer\");\n\tthis.dropzoneEnable = (this.getAttribute(\"enable\") || \"yes\") === \"yes\";\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nDropZoneWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.enable) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.dropzone = DropZoneWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/edit-binary.js": {
            "title": "$:/core/modules/widgets/edit-binary.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/edit-binary.js\ntype: application/javascript\nmodule-type: widget\n\nEdit-binary widget; placeholder for editing binary tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar BINARY_WARNING_MESSAGE = \"$:/core/ui/BinaryWarning\";\nvar EXPORT_BUTTON_IMAGE = \"$:/core/images/export-button\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditBinaryWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditBinaryWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditBinaryWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nEditBinaryWidget.prototype.execute = function() {\n\t// Get our parameters\n\tvar editTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tvar tiddler = this.wiki.getTiddler(editTitle);\n\tvar type = tiddler.fields.type;\n\tvar text = tiddler.fields.text;\n\t// Transclude the binary data tiddler warning message\n\tvar warn = {\n\t\ttype: \"element\",\n\t\ttag: \"p\",\n\t\tchildren: [{\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: BINARY_WARNING_MESSAGE}\n\t\t\t}\n\t\t}]\n\t};\n\t// Create download link based on draft tiddler title\n\tvar link = {\n\t\ttype: \"element\",\n\t\ttag: \"a\",\n\t\tattributes: {\n\t\t\ttitle: {type: \"indirect\", textReference: \"!!draft.title\"},\n\t\t\tdownload: {type: \"indirect\", textReference: \"!!draft.title\"}\n\t\t},\n\t\tchildren: [{\n\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: EXPORT_BUTTON_IMAGE}\n\t\t\t}\n\t\t}]\n\t};\n\t// Set the link href to internal data URI (no external)\n\tif(text) {\n\t\tlink.attributes.href = {\n\t\t\ttype: \"string\", \n\t\t\tvalue: \"data:\" + type + \";base64,\" + text\n\t\t};\n\t}\n\t// Combine warning message and download link in a div\n\tvar element = {\n\t\ttype: \"element\",\n\t\ttag: \"div\",\n\t\tattributes: {\n\t\t\tclass: {type: \"string\", value: \"tc-binary-warning\"}\n\t\t},\n\t\tchildren: [warn, link]\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets([element]);\n};\n\n/*\nRefresh by refreshing our child widget\n*/\nEditBinaryWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports[\"edit-binary\"] = EditBinaryWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/edit-bitmap.js": {
            "title": "$:/core/modules/widgets/edit-bitmap.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/edit-bitmap.js\ntype: application/javascript\nmodule-type: widget\n\nEdit-bitmap widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Default image sizes\nvar DEFAULT_IMAGE_WIDTH = 600,\n\tDEFAULT_IMAGE_HEIGHT = 370,\n\tDEFAULT_IMAGE_TYPE = \"image/png\";\n\n// Configuration tiddlers\nvar LINE_WIDTH_TITLE = \"$:/config/BitmapEditor/LineWidth\",\n\tLINE_COLOUR_TITLE = \"$:/config/BitmapEditor/Colour\",\n\tLINE_OPACITY_TITLE = \"$:/config/BitmapEditor/Opacity\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditBitmapWidget = function(parseTreeNode,options) {\n\t// Initialise the editor operations if they've not been done already\n\tif(!this.editorOperations) {\n\t\tEditBitmapWidget.prototype.editorOperations = {};\n\t\t$tw.modules.applyMethods(\"bitmapeditoroperation\",this.editorOperations);\n\t}\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditBitmapWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditBitmapWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Create the wrapper for the toolbar and render its content\n\tthis.toolbarNode = this.document.createElement(\"div\");\n\tthis.toolbarNode.className = \"tc-editor-toolbar\";\n\tparent.insertBefore(this.toolbarNode,nextSibling);\n\tthis.domNodes.push(this.toolbarNode);\n\t// Create the on-screen canvas\n\tthis.canvasDomNode = $tw.utils.domMaker(\"canvas\",{\n\t\tdocument: this.document,\n\t\t\"class\":\"tc-edit-bitmapeditor\",\n\t\teventListeners: [{\n\t\t\tname: \"touchstart\", handlerObject: this, handlerMethod: \"handleTouchStartEvent\"\n\t\t},{\n\t\t\tname: \"touchmove\", handlerObject: this, handlerMethod: \"handleTouchMoveEvent\"\n\t\t},{\n\t\t\tname: \"touchend\", handlerObject: this, handlerMethod: \"handleTouchEndEvent\"\n\t\t},{\n\t\t\tname: \"mousedown\", handlerObject: this, handlerMethod: \"handleMouseDownEvent\"\n\t\t},{\n\t\t\tname: \"mousemove\", handlerObject: this, handlerMethod: \"handleMouseMoveEvent\"\n\t\t},{\n\t\t\tname: \"mouseup\", handlerObject: this, handlerMethod: \"handleMouseUpEvent\"\n\t\t}]\n\t});\n\t// Set the width and height variables\n\tthis.setVariable(\"tv-bitmap-editor-width\",this.canvasDomNode.width + \"px\");\n\tthis.setVariable(\"tv-bitmap-editor-height\",this.canvasDomNode.height + \"px\");\n\t// Render toolbar child widgets\n\tthis.renderChildren(this.toolbarNode,null);\n\t// // Insert the elements into the DOM\n\tparent.insertBefore(this.canvasDomNode,nextSibling);\n\tthis.domNodes.push(this.canvasDomNode);\n\t// Load the image into the canvas\n\tif($tw.browser) {\n\t\tthis.loadCanvas();\n\t}\n\t// Add widget message listeners\n\tthis.addEventListeners([\n\t\t{type: \"tm-edit-bitmap-operation\", handler: \"handleEditBitmapOperationMessage\"}\n\t]);\n};\n\n/*\nHandle an edit bitmap operation message from the toolbar\n*/\nEditBitmapWidget.prototype.handleEditBitmapOperationMessage = function(event) {\n\t// Invoke the handler\n\tvar handler = this.editorOperations[event.param];\n\tif(handler) {\n\t\thandler.call(this,event);\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nEditBitmapWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.editTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nJust refresh the toolbar\n*/\nEditBitmapWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nSet the bitmap size variables and refresh the toolbar\n*/\nEditBitmapWidget.prototype.refreshToolbar = function() {\n\t// Set the width and height variables\n\tthis.setVariable(\"tv-bitmap-editor-width\",this.canvasDomNode.width + \"px\");\n\tthis.setVariable(\"tv-bitmap-editor-height\",this.canvasDomNode.height + \"px\");\n\t// Refresh each of our child widgets\n\t$tw.utils.each(this.children,function(childWidget) {\n\t\tchildWidget.refreshSelf();\n\t});\n};\n\nEditBitmapWidget.prototype.loadCanvas = function() {\n\tvar tiddler = this.wiki.getTiddler(this.editTitle),\n\t\tcurrImage = new Image();\n\t// Set up event handlers for loading the image\n\tvar self = this;\n\tcurrImage.onload = function() {\n\t\t// Copy the image to the on-screen canvas\n\t\tself.initCanvas(self.canvasDomNode,currImage.width,currImage.height,currImage);\n\t\t// And also copy the current bitmap to the off-screen canvas\n\t\tself.currCanvas = self.document.createElement(\"canvas\");\n\t\tself.initCanvas(self.currCanvas,currImage.width,currImage.height,currImage);\n\t\t// Set the width and height input boxes\n\t\tself.refreshToolbar();\n\t};\n\tcurrImage.onerror = function() {\n\t\t// Set the on-screen canvas size and clear it\n\t\tself.initCanvas(self.canvasDomNode,DEFAULT_IMAGE_WIDTH,DEFAULT_IMAGE_HEIGHT);\n\t\t// Set the off-screen canvas size and clear it\n\t\tself.currCanvas = self.document.createElement(\"canvas\");\n\t\tself.initCanvas(self.currCanvas,DEFAULT_IMAGE_WIDTH,DEFAULT_IMAGE_HEIGHT);\n\t\t// Set the width and height input boxes\n\t\tself.refreshToolbar();\n\t};\n\t// Get the current bitmap into an image object\n\tif(tiddler && tiddler.fields.type && tiddler.fields.text) {\n\t\tcurrImage.src = \"data:\" + tiddler.fields.type + \";base64,\" + tiddler.fields.text;\t\t\n\t} else {\n\t\tcurrImage.width = DEFAULT_IMAGE_WIDTH;\n\t\tcurrImage.height = DEFAULT_IMAGE_HEIGHT;\n\t\tcurrImage.onerror();\n\t}\n};\n\nEditBitmapWidget.prototype.initCanvas = function(canvas,width,height,image) {\n\tcanvas.width = width;\n\tcanvas.height = height;\n\tvar ctx = canvas.getContext(\"2d\");\n\tif(image) {\n\t\tctx.drawImage(image,0,0);\n\t} else {\n\t\tctx.fillStyle = \"#fff\";\n\t\tctx.fillRect(0,0,canvas.width,canvas.height);\n\t}\n};\n\n/*\n** Change the size of the canvas, preserving the current image\n*/\nEditBitmapWidget.prototype.changeCanvasSize = function(newWidth,newHeight) {\n\t// Create and size a new canvas\n\tvar newCanvas = this.document.createElement(\"canvas\");\n\tthis.initCanvas(newCanvas,newWidth,newHeight);\n\t// Copy the old image\n\tvar ctx = newCanvas.getContext(\"2d\");\n\tctx.drawImage(this.currCanvas,0,0);\n\t// Set the new canvas as the current one\n\tthis.currCanvas = newCanvas;\n\t// Set the size of the onscreen canvas\n\tthis.canvasDomNode.width = newWidth;\n\tthis.canvasDomNode.height = newHeight;\n\t// Paint the onscreen canvas with the offscreen canvas\n\tctx = this.canvasDomNode.getContext(\"2d\");\n\tctx.drawImage(this.currCanvas,0,0);\n};\n\n/*\n** Rotate the canvas left by 90 degrees\n*/\nEditBitmapWidget.prototype.rotateCanvasLeft = function() {\n\t// Get the current size of the image\n\tvar origWidth = this.currCanvas.width,\n\t\torigHeight = this.currCanvas.height;\n\t// Create and size a new canvas\n\tvar newCanvas = this.document.createElement(\"canvas\"),\n\t\tnewWidth = origHeight,\n\t\tnewHeight = origWidth;\n\tthis.initCanvas(newCanvas,newWidth,newHeight);\n\t// Copy the old image\n\tvar ctx = newCanvas.getContext(\"2d\");\n\tctx.save();\n\tctx.translate(newWidth / 2,newHeight / 2);\n\tctx.rotate(-Math.PI / 2);\n\tctx.drawImage(this.currCanvas,-origWidth / 2,-origHeight / 2);\n\tctx.restore();\n\t// Set the new canvas as the current one\n\tthis.currCanvas = newCanvas;\n\t// Set the size of the onscreen canvas\n\tthis.canvasDomNode.width = newWidth;\n\tthis.canvasDomNode.height = newHeight;\n\t// Paint the onscreen canvas with the offscreen canvas\n\tctx = this.canvasDomNode.getContext(\"2d\");\n\tctx.drawImage(this.currCanvas,0,0);\n};\n\nEditBitmapWidget.prototype.handleTouchStartEvent = function(event) {\n\tthis.brushDown = true;\n\tthis.strokeStart(event.touches[0].clientX,event.touches[0].clientY);\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleTouchMoveEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.strokeMove(event.touches[0].clientX,event.touches[0].clientY);\n\t}\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleTouchEndEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.brushDown = false;\n\t\tthis.strokeEnd();\n\t}\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleMouseDownEvent = function(event) {\n\tthis.strokeStart(event.clientX,event.clientY);\n\tthis.brushDown = true;\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleMouseMoveEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.strokeMove(event.clientX,event.clientY);\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\treturn false;\n\t}\n\treturn true;\n};\n\nEditBitmapWidget.prototype.handleMouseUpEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.brushDown = false;\n\t\tthis.strokeEnd();\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\treturn false;\n\t}\n\treturn true;\n};\n\nEditBitmapWidget.prototype.adjustCoordinates = function(x,y) {\n\tvar canvasRect = this.canvasDomNode.getBoundingClientRect(),\n\t\tscale = this.canvasDomNode.width/canvasRect.width;\n\treturn {x: (x - canvasRect.left) * scale, y: (y - canvasRect.top) * scale};\n};\n\nEditBitmapWidget.prototype.strokeStart = function(x,y) {\n\t// Start off a new stroke\n\tthis.stroke = [this.adjustCoordinates(x,y)];\n};\n\nEditBitmapWidget.prototype.strokeMove = function(x,y) {\n\tvar ctx = this.canvasDomNode.getContext(\"2d\"),\n\t\tt;\n\t// Add the new position to the end of the stroke\n\tthis.stroke.push(this.adjustCoordinates(x,y));\n\t// Redraw the previous image\n\tctx.drawImage(this.currCanvas,0,0);\n\t// Render the stroke\n\tctx.globalAlpha = parseFloat(this.wiki.getTiddlerText(LINE_OPACITY_TITLE,\"1.0\"));\n\tctx.strokeStyle = this.wiki.getTiddlerText(LINE_COLOUR_TITLE,\"#ff0\");\n\tctx.lineWidth = parseFloat(this.wiki.getTiddlerText(LINE_WIDTH_TITLE,\"3\"));\n\tctx.lineCap = \"round\";\n\tctx.lineJoin = \"round\";\n\tctx.beginPath();\n\tctx.moveTo(this.stroke[0].x,this.stroke[0].y);\n\tfor(t=1; t<this.stroke.length-1; t++) {\n\t\tvar s1 = this.stroke[t],\n\t\t\ts2 = this.stroke[t-1],\n\t\t\ttx = (s1.x + s2.x)/2,\n\t\t\tty = (s1.y + s2.y)/2;\n\t\tctx.quadraticCurveTo(s2.x,s2.y,tx,ty);\n\t}\n\tctx.stroke();\n};\n\nEditBitmapWidget.prototype.strokeEnd = function() {\n\t// Copy the bitmap to the off-screen canvas\n\tvar ctx = this.currCanvas.getContext(\"2d\");\n\tctx.drawImage(this.canvasDomNode,0,0);\n\t// Save the image into the tiddler\n\tthis.saveChanges();\n};\n\nEditBitmapWidget.prototype.saveChanges = function() {\n\tvar tiddler = this.wiki.getTiddler(this.editTitle) || new $tw.Tiddler({title: this.editTitle,type: DEFAULT_IMAGE_TYPE});\n\t// data URIs look like \"data:<type>;base64,<text>\"\n\tvar dataURL = this.canvasDomNode.toDataURL(tiddler.fields.type),\n\t\tposColon = dataURL.indexOf(\":\"),\n\t\tposSemiColon = dataURL.indexOf(\";\"),\n\t\tposComma = dataURL.indexOf(\",\"),\n\t\ttype = dataURL.substring(posColon+1,posSemiColon),\n\t\ttext = dataURL.substring(posComma+1);\n\tvar update = {type: type, text: text};\n\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getModificationFields(),tiddler,update,this.wiki.getCreationFields()));\n};\n\nexports[\"edit-bitmap\"] = EditBitmapWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/edit-shortcut.js": {
            "title": "$:/core/modules/widgets/edit-shortcut.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/edit-shortcut.js\ntype: application/javascript\nmodule-type: widget\n\nWidget to display an editable keyboard shortcut\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditShortcutWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditShortcutWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditShortcutWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.inputNode = this.document.createElement(\"input\");\n\t// Assign classes\n\tif(this.shortcutClass) {\n\t\tthis.inputNode.className = this.shortcutClass;\t\t\n\t}\n\t// Assign other attributes\n\tif(this.shortcutStyle) {\n\t\tthis.inputNode.setAttribute(\"style\",this.shortcutStyle);\n\t}\n\tif(this.shortcutTooltip) {\n\t\tthis.inputNode.setAttribute(\"title\",this.shortcutTooltip);\n\t}\n\tif(this.shortcutPlaceholder) {\n\t\tthis.inputNode.setAttribute(\"placeholder\",this.shortcutPlaceholder);\n\t}\n\tif(this.shortcutAriaLabel) {\n\t\tthis.inputNode.setAttribute(\"aria-label\",this.shortcutAriaLabel);\n\t}\n\t// Assign the current shortcut\n\tthis.updateInputNode();\n\t// Add event handlers\n\t$tw.utils.addEventListeners(this.inputNode,[\n\t\t{name: \"keydown\", handlerObject: this, handlerMethod: \"handleKeydownEvent\"}\n\t]);\n\t// Link into the DOM\n\tparent.insertBefore(this.inputNode,nextSibling);\n\tthis.domNodes.push(this.inputNode);\n\t// Focus the input Node if focus === \"yes\" or focus === \"true\"\n\tif(this.shortcutFocus === \"yes\" || this.shortcutFocus === \"true\") {\n\t\tthis.focus();\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nEditShortcutWidget.prototype.execute = function() {\n\tthis.shortcutTiddler = this.getAttribute(\"tiddler\");\n\tthis.shortcutField = this.getAttribute(\"field\");\n\tthis.shortcutIndex = this.getAttribute(\"index\");\n\tthis.shortcutPlaceholder = this.getAttribute(\"placeholder\");\n\tthis.shortcutDefault = this.getAttribute(\"default\",\"\");\n\tthis.shortcutClass = this.getAttribute(\"class\");\n\tthis.shortcutStyle = this.getAttribute(\"style\");\n\tthis.shortcutTooltip = this.getAttribute(\"tooltip\");\n\tthis.shortcutAriaLabel = this.getAttribute(\"aria-label\");\n\tthis.shortcutFocus = this.getAttribute(\"focus\");\n};\n\n/*\nUpdate the value of the input node\n*/\nEditShortcutWidget.prototype.updateInputNode = function() {\n\tif(this.shortcutField) {\n\t\tvar tiddler = this.wiki.getTiddler(this.shortcutTiddler);\n\t\tif(tiddler && $tw.utils.hop(tiddler.fields,this.shortcutField)) {\n\t\t\tthis.inputNode.value = tiddler.getFieldString(this.shortcutField);\n\t\t} else {\n\t\t\tthis.inputNode.value = this.shortcutDefault;\n\t\t}\n\t} else if(this.shortcutIndex) {\n\t\tthis.inputNode.value = this.wiki.extractTiddlerDataItem(this.shortcutTiddler,this.shortcutIndex,this.shortcutDefault);\n\t} else {\n\t\tthis.inputNode.value = this.wiki.getTiddlerText(this.shortcutTiddler,this.shortcutDefault);\n\t}\n};\n\n/*\nHandle a dom \"keydown\" event\n*/\nEditShortcutWidget.prototype.handleKeydownEvent = function(event) {\n\t// Ignore shift, ctrl, meta, alt\n\tif(event.keyCode && $tw.keyboardManager.getModifierKeys().indexOf(event.keyCode) === -1) {\n\t\t// Get the shortcut text representation\n\t\tvar value = $tw.keyboardManager.getPrintableShortcuts([{\n\t\t\tctrlKey: event.ctrlKey,\n\t\t\tshiftKey: event.shiftKey,\n\t\t\taltKey: event.altKey,\n\t\t\tmetaKey: event.metaKey,\n\t\t\tkeyCode: event.keyCode\n\t\t}]);\n\t\tif(value.length > 0) {\n\t\t\tthis.wiki.setText(this.shortcutTiddler,this.shortcutField,this.shortcutIndex,value[0]);\n\t\t}\n\t\t// Ignore the keydown if it was already handled\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\treturn true;\t\t\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\nfocus the input node\n*/\nEditShortcutWidget.prototype.focus = function() {\n\tif(this.inputNode.focus && this.inputNode.select) {\n\t\tthis.inputNode.focus();\n\t\tthis.inputNode.select();\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget needed re-rendering\n*/\nEditShortcutWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.placeholder || changedAttributes[\"default\"] || changedAttributes[\"class\"] || changedAttributes.style || changedAttributes.tooltip || changedAttributes[\"aria-label\"] || changedAttributes.focus) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else if(changedTiddlers[this.shortcutTiddler]) {\n\t\tthis.updateInputNode();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports[\"edit-shortcut\"] = EditShortcutWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/edit-text.js": {
            "title": "$:/core/modules/widgets/edit-text.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/edit-text.js\ntype: application/javascript\nmodule-type: widget\n\nEdit-text widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar editTextWidgetFactory = require(\"$:/core/modules/editor/factory.js\").editTextWidgetFactory,\n\tFramedEngine = require(\"$:/core/modules/editor/engines/framed.js\").FramedEngine,\n\tSimpleEngine = require(\"$:/core/modules/editor/engines/simple.js\").SimpleEngine;\n\nexports[\"edit-text\"] = editTextWidgetFactory(FramedEngine,SimpleEngine);\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/edit.js": {
            "title": "$:/core/modules/widgets/edit.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/edit.js\ntype: application/javascript\nmodule-type: widget\n\nEdit widget is a meta-widget chooses the appropriate actual editting widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n// Mappings from content type to editor type are stored in tiddlers with this prefix\nvar EDITOR_MAPPING_PREFIX = \"$:/config/EditorTypeMappings/\";\n\n/*\nCompute the internal state of the widget\n*/\nEditWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.editTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.editField = this.getAttribute(\"field\",\"text\");\n\tthis.editIndex = this.getAttribute(\"index\");\n\tthis.editClass = this.getAttribute(\"class\");\n\tthis.editPlaceholder = this.getAttribute(\"placeholder\");\n\tthis.editTabIndex = this.getAttribute(\"tabindex\");\n\tthis.editFocus = this.getAttribute(\"focus\",\"\");\n\t// Choose the appropriate edit widget\n\tthis.editorType = this.getEditorType();\n\t// Make the child widgets\n\tthis.makeChildWidgets([{\n\t\ttype: \"edit-\" + this.editorType,\n\t\tattributes: {\n\t\t\ttiddler: {type: \"string\", value: this.editTitle},\n\t\t\tfield: {type: \"string\", value: this.editField},\n\t\t\tindex: {type: \"string\", value: this.editIndex},\n\t\t\t\"class\": {type: \"string\", value: this.editClass},\n\t\t\t\"placeholder\": {type: \"string\", value: this.editPlaceholder},\n\t\t\t\"tabindex\": {type: \"string\", value: this.editTabIndex},\n\t\t\t\"focus\": {type: \"string\", value: this.editFocus}\n\t\t},\n\t\tchildren: this.parseTreeNode.children\n\t}]);\n};\n\nEditWidget.prototype.getEditorType = function() {\n\t// Get the content type of the thing we're editing\n\tvar type;\n\tif(this.editField === \"text\") {\n\t\tvar tiddler = this.wiki.getTiddler(this.editTitle);\n\t\tif(tiddler) {\n\t\t\ttype = tiddler.fields.type;\n\t\t}\n\t}\n\ttype = type || \"text/vnd.tiddlywiki\";\n\tvar editorType = this.wiki.getTiddlerText(EDITOR_MAPPING_PREFIX + type);\n\tif(!editorType) {\n\t\tvar typeInfo = $tw.config.contentTypeInfo[type];\n\t\tif(typeInfo && typeInfo.encoding === \"base64\") {\n\t\t\teditorType = \"binary\";\n\t\t} else {\n\t\t\teditorType = \"text\";\n\t\t}\n\t}\n\treturn editorType;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nEditWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\t// Refresh if an attribute has changed, or the type associated with the target tiddler has changed\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.edit = EditWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/element.js": {
            "title": "$:/core/modules/widgets/element.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/element.js\ntype: application/javascript\nmodule-type: widget\n\nElement widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ElementWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nElementWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nElementWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Neuter blacklisted elements\n\tvar tag = this.parseTreeNode.tag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"safe-\" + tag;\n\t}\n\t// Adjust headings by the current base level\n\tvar headingLevel = [\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\"].indexOf(tag);\n\tif(headingLevel !== -1) {\n\t\tvar baseLevel = parseInt(this.getVariable(\"tv-adjust-heading-level\",\"0\"),10) || 0;\n\t\theadingLevel = Math.min(Math.max(headingLevel + 1 + baseLevel,1),6);\n\t\ttag = \"h\" + headingLevel;\n\t}\n\t// Create the DOM node\n\tvar domNode = this.document.createElementNS(this.namespace,tag);\n\tthis.assignAttributes(domNode,{excludeEventAttributes: true});\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nElementWidget.prototype.execute = function() {\n\t// Select the namespace for the tag\n\tvar tagNamespaces = {\n\t\t\tsvg: \"http://www.w3.org/2000/svg\",\n\t\t\tmath: \"http://www.w3.org/1998/Math/MathML\",\n\t\t\tbody: \"http://www.w3.org/1999/xhtml\"\n\t\t};\n\tthis.namespace = tagNamespaces[this.parseTreeNode.tag];\n\tif(this.namespace) {\n\t\tthis.setVariable(\"namespace\",this.namespace);\n\t} else {\n\t\tthis.namespace = this.getVariable(\"namespace\",{defaultValue: \"http://www.w3.org/1999/xhtml\"});\n\t}\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nElementWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes(),\n\t\thasChangedAttributes = $tw.utils.count(changedAttributes) > 0;\n\tif(hasChangedAttributes) {\n\t\t// Update our attributes\n\t\tthis.assignAttributes(this.domNodes[0],{excludeEventAttributes: true});\n\t}\n\treturn this.refreshChildren(changedTiddlers) || hasChangedAttributes;\n};\n\nexports.element = ElementWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/encrypt.js": {
            "title": "$:/core/modules/widgets/encrypt.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/encrypt.js\ntype: application/javascript\nmodule-type: widget\n\nEncrypt widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EncryptWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEncryptWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEncryptWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar textNode = this.document.createTextNode(this.encryptedText);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nEncryptWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.filter = this.getAttribute(\"filter\",\"[!is[system]]\");\n\t// Encrypt the filtered tiddlers\n\tvar tiddlers = this.wiki.filterTiddlers(this.filter),\n\t\tjson = {},\n\t\tself = this;\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = self.wiki.getTiddler(title),\n\t\t\tjsonTiddler = {};\n\t\tfor(var f in tiddler.fields) {\n\t\t\tjsonTiddler[f] = tiddler.getFieldString(f);\n\t\t}\n\t\tjson[title] = jsonTiddler;\n\t});\n\tthis.encryptedText = $tw.utils.htmlEncode($tw.crypto.encrypt(JSON.stringify(json)));\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nEncryptWidget.prototype.refresh = function(changedTiddlers) {\n\t// We don't need to worry about refreshing because the encrypt widget isn't for interactive use\n\treturn false;\n};\n\nexports.encrypt = EncryptWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/entity.js": {
            "title": "$:/core/modules/widgets/entity.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/entity.js\ntype: application/javascript\nmodule-type: widget\n\nHTML entity widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EntityWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEntityWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEntityWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.execute();\n\tvar entityString = this.getAttribute(\"entity\",this.parseTreeNode.entity || \"\"),\n\t\ttextNode = this.document.createTextNode($tw.utils.entityDecode(entityString));\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nEntityWidget.prototype.execute = function() {\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nEntityWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.entity) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports.entity = EntityWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/fieldmangler.js": {
            "title": "$:/core/modules/widgets/fieldmangler.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/fieldmangler.js\ntype: application/javascript\nmodule-type: widget\n\nField mangler widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar FieldManglerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.addEventListeners([\n\t\t{type: \"tm-remove-field\", handler: \"handleRemoveFieldEvent\"},\n\t\t{type: \"tm-add-field\", handler: \"handleAddFieldEvent\"},\n\t\t{type: \"tm-remove-tag\", handler: \"handleRemoveTagEvent\"},\n\t\t{type: \"tm-add-tag\", handler: \"handleAddTagEvent\"}\n\t]);\n};\n\n/*\nInherit from the base widget class\n*/\nFieldManglerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nFieldManglerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nFieldManglerWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.mangleTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nFieldManglerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nFieldManglerWidget.prototype.handleRemoveFieldEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle),\n\t\tdeletion = {};\n\tdeletion[event.param] = undefined;\n\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,deletion));\n\treturn true;\n};\n\nFieldManglerWidget.prototype.handleAddFieldEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle),\n\t\taddition = this.wiki.getModificationFields(),\n\t\thadInvalidFieldName = false,\n\t\taddField = function(name,value) {\n\t\t\tvar trimmedName = name.toLowerCase().trim();\n\t\t\tif(!$tw.utils.isValidFieldName(trimmedName)) {\n\t\t\t\tif(!hadInvalidFieldName) {\n\t\t\t\t\talert($tw.language.getString(\n\t\t\t\t\t\t\"InvalidFieldName\",\n\t\t\t\t\t\t{variables:\n\t\t\t\t\t\t\t{fieldName: trimmedName}\n\t\t\t\t\t\t}\n\t\t\t\t\t));\n\t\t\t\t\thadInvalidFieldName = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif(!value && tiddler) {\n\t\t\t\t\tvalue = tiddler.fields[trimmedName];\n\t\t\t\t}\n\t\t\t\taddition[trimmedName] = value || \"\";\n\t\t\t}\n\t\t\treturn;\n\t\t};\n\taddition.title = this.mangleTitle;\n\tif(typeof event.param === \"string\") {\n\t\taddField(event.param,\"\");\n\t}\n\tif(typeof event.paramObject === \"object\") {\n\t\tfor(var name in event.paramObject) {\n\t\t\taddField(name,event.paramObject[name]);\n\t\t}\n\t}\n\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,addition));\n\treturn true;\n};\n\nFieldManglerWidget.prototype.handleRemoveTagEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle),\n\t\tmodification = this.wiki.getModificationFields();\n\tif(tiddler && tiddler.fields.tags) {\n\t\tvar p = tiddler.fields.tags.indexOf(event.param);\n\t\tif(p !== -1) {\n\t\t\tmodification.tags = (tiddler.fields.tags || []).slice(0);\n\t\t\tmodification.tags.splice(p,1);\n\t\t\tif(modification.tags.length === 0) {\n\t\t\t\tmodification.tags = undefined;\n\t\t\t}\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));\n\t\t}\n\t}\n\treturn true;\n};\n\nFieldManglerWidget.prototype.handleAddTagEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle),\n\t\tmodification = this.wiki.getModificationFields();\n\tif(tiddler && typeof event.param === \"string\") {\n\t\tvar tag = event.param.trim();\n\t\tif(tag !== \"\") {\n\t\t\tmodification.tags = (tiddler.fields.tags || []).slice(0);\n\t\t\t$tw.utils.pushTop(modification.tags,tag);\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));\t\t\t\n\t\t}\n\t} else if(typeof event.param === \"string\" && event.param.trim() !== \"\" && this.mangleTitle.trim() !== \"\") {\n\t\tvar tag = [];\n\t\ttag.push(event.param.trim());\n\t\tthis.wiki.addTiddler(new $tw.Tiddler({title: this.mangleTitle, tags: tag},modification));\n\t}\n\treturn true;\n};\n\nexports.fieldmangler = FieldManglerWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/fields.js": {
            "title": "$:/core/modules/widgets/fields.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/fields.js\ntype: application/javascript\nmodule-type: widget\n\nFields widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar FieldsWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nFieldsWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nFieldsWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar textNode = this.document.createTextNode(this.text);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nFieldsWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.tiddlerTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.template = this.getAttribute(\"template\");\n\tthis.sort = this.getAttribute(\"sort\",\"yes\") === \"yes\";\n\tthis.sortReverse = this.getAttribute(\"sortReverse\",\"no\") === \"yes\";\n\tthis.exclude = this.getAttribute(\"exclude\");\n\tthis.include = this.getAttribute(\"include\",null);\n\tthis.stripTitlePrefix = this.getAttribute(\"stripTitlePrefix\",\"no\") === \"yes\";\n\t// Get the value to display\n\tvar tiddler = this.wiki.getTiddler(this.tiddlerTitle);\n\n\t// Get the inclusion and exclusion list\n\tvar excludeArr = (this.exclude) ? this.exclude.split(\" \") : [\"text\"];\n\t// Include takes precedence\n\tvar includeArr = (this.include) ? this.include.split(\" \") : null;\n\n\t// Compose the template\n\tvar text = [];\n\tif(this.template && tiddler) {\n\t\tvar fields = [];\n\t\tif (includeArr) { // Include takes precedence\n\t\t\tfor(var i=0; i<includeArr.length; i++) {\n\t\t\t\tif(tiddler.fields[includeArr[i]]) {\n\t\t\t\t\tfields.push(includeArr[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor(var fieldName in tiddler.fields) {\n\t\t\t\tif(excludeArr.indexOf(fieldName) === -1) {\n\t\t\t\t\tfields.push(fieldName);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.sort) fields.sort();\n\t\tif (this.sortReverse) fields.reverse();\n\t\tfor(var f=0, fmax=fields.length; f<fmax; f++) {\n\t\t\tfieldName = fields[f];\n\t\t\tvar row = this.template,\n\t\t\t\tvalue = tiddler.getFieldString(fieldName);\n\t\t\tif(this.stripTitlePrefix && fieldName === \"title\") {\n\t\t\t\tvar reStrip = /^\\{[^\\}]+\\}(.+)/mg,\n\t\t\t\t\treMatch = reStrip.exec(value);\n\t\t\t\tif(reMatch) {\n\t\t\t\t\tvalue = reMatch[1];\n\t\t\t\t}\n\t\t\t}\n\t\t\trow = $tw.utils.replaceString(row,\"$name$\",fieldName);\n\t\t\trow = $tw.utils.replaceString(row,\"$value$\",value);\n\t\t\trow = $tw.utils.replaceString(row,\"$encoded_value$\",$tw.utils.htmlEncode(value));\n\t\t\ttext.push(row);\n\t\t}\n\t}\n\tthis.text = text.join(\"\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nFieldsWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif( changedAttributes.tiddler || changedAttributes.template || changedAttributes.exclude ||\n\t\tchangedAttributes.include || changedAttributes.sort || changedAttributes.sortReverse ||\n\t\tchangedTiddlers[this.tiddlerTitle] || changedAttributes.stripTitlePrefix) {\n\t\t\tthis.refreshSelf();\n\t\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n};\n\nexports.fields = FieldsWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/image.js": {
            "title": "$:/core/modules/widgets/image.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/image.js\ntype: application/javascript\nmodule-type: widget\n\nThe image widget displays an image referenced with an external URI or with a local tiddler title.\n\n```\n<$image src=\"TiddlerTitle\" width=\"320\" height=\"400\" class=\"classnames\">\n```\n\nThe image source can be the title of an existing tiddler or the URL of an external image.\n\nExternal images always generate an HTML `<img>` tag.\n\nTiddlers that have a _canonical_uri field generate an HTML `<img>` tag with the src attribute containing the URI.\n\nTiddlers that contain image data generate an HTML `<img>` tag with the src attribute containing a base64 representation of the image.\n\nTiddlers that contain wikitext could be rendered to a DIV of the usual size of a tiddler, and then transformed to the size requested.\n\nThe width and height attributes are interpreted as a number of pixels, and do not need to include the \"px\" suffix.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ImageWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nImageWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nImageWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\t// Determine what type of image it is\n\tvar tag = \"img\", src = \"\",\n\t\ttiddler = this.wiki.getTiddler(this.imageSource);\n\tif(!tiddler) {\n\t\t// The source isn't the title of a tiddler, so we'll assume it's a URL\n\t\tsrc = this.getVariable(\"tv-get-export-image-link\",{params: [{name: \"src\",value: this.imageSource}],defaultValue: this.imageSource});\n\t} else {\n\t\t// Check if it is an image tiddler\n\t\tif(this.wiki.isImageTiddler(this.imageSource)) {\n\t\t\tvar type = tiddler.fields.type,\n\t\t\t\ttext = tiddler.fields.text,\n\t\t\t\t_canonical_uri = tiddler.fields._canonical_uri;\n\t\t\t// If the tiddler has body text then it doesn't need to be lazily loaded\n\t\t\tif(text) {\n\t\t\t\t// Render the appropriate element for the image type\n\t\t\t\tswitch(type) {\n\t\t\t\t\tcase \"application/pdf\":\n\t\t\t\t\t\ttag = \"embed\";\n\t\t\t\t\t\tsrc = \"data:application/pdf;base64,\" + text;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"image/svg+xml\":\n\t\t\t\t\t\tsrc = \"data:image/svg+xml,\" + encodeURIComponent(text);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tsrc = \"data:\" + type + \";base64,\" + text;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else if(_canonical_uri) {\n\t\t\t\tswitch(type) {\n\t\t\t\t\tcase \"application/pdf\":\n\t\t\t\t\t\ttag = \"embed\";\n\t\t\t\t\t\tsrc = _canonical_uri;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"image/svg+xml\":\n\t\t\t\t\t\tsrc = _canonical_uri;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tsrc = _canonical_uri;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\t\n\t\t\t} else {\n\t\t\t\t// Just trigger loading of the tiddler\n\t\t\t\tthis.wiki.getTiddlerText(this.imageSource);\n\t\t\t}\n\t\t}\n\t}\n\t// Create the element and assign the attributes\n\tvar domNode = this.document.createElement(tag);\n\tdomNode.setAttribute(\"src\",src);\n\tif(this.imageClass) {\n\t\tdomNode.setAttribute(\"class\",this.imageClass);\t\t\n\t}\n\tif(this.imageWidth) {\n\t\tdomNode.setAttribute(\"width\",this.imageWidth);\n\t}\n\tif(this.imageHeight) {\n\t\tdomNode.setAttribute(\"height\",this.imageHeight);\n\t}\n\tif(this.imageTooltip) {\n\t\tdomNode.setAttribute(\"title\",this.imageTooltip);\t\t\n\t}\n\tif(this.imageAlt) {\n\t\tdomNode.setAttribute(\"alt\",this.imageAlt);\t\t\n\t}\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nImageWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.imageSource = this.getAttribute(\"source\");\n\tthis.imageWidth = this.getAttribute(\"width\");\n\tthis.imageHeight = this.getAttribute(\"height\");\n\tthis.imageClass = this.getAttribute(\"class\");\n\tthis.imageTooltip = this.getAttribute(\"tooltip\");\n\tthis.imageAlt = this.getAttribute(\"alt\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nImageWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.source || changedAttributes.width || changedAttributes.height || changedAttributes[\"class\"] || changedAttributes.tooltip || changedTiddlers[this.imageSource]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\t\n\t}\n};\n\nexports.image = ImageWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/importvariables.js": {
            "title": "$:/core/modules/widgets/importvariables.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/importvariables.js\ntype: application/javascript\nmodule-type: widget\n\nImport variable definitions from other tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ImportVariablesWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nImportVariablesWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nImportVariablesWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nImportVariablesWidget.prototype.execute = function(tiddlerList) {\n\tvar widgetPointer = this;\n\t// Get our parameters\n\tthis.filter = this.getAttribute(\"filter\");\n\t// Compute the filter\n\tthis.tiddlerList = tiddlerList || this.wiki.filterTiddlers(this.filter,this);\n\t// Accumulate the <$set> widgets from each tiddler\n\t$tw.utils.each(this.tiddlerList,function(title) {\n\t\tvar parser = widgetPointer.wiki.parseTiddler(title);\n\t\tif(parser) {\n\t\t\tvar parseTreeNode = parser.tree[0];\n\t\t\twhile(parseTreeNode && parseTreeNode.type === \"set\") {\n\t\t\t\tvar node = {\n\t\t\t\t\ttype: \"set\",\n\t\t\t\t\tattributes: parseTreeNode.attributes,\n\t\t\t\t\tparams: parseTreeNode.params,\n\t\t\t\t\tisMacroDefinition: parseTreeNode.isMacroDefinition\n\t\t\t\t};\n\t\t\t\tif (parseTreeNode.isMacroDefinition) {\n\t\t\t\t\t// Macro definitions can be folded into\n\t\t\t\t\t// current widget instead of adding\n\t\t\t\t\t// another link to the chain.\n\t\t\t\t\tvar widget = widgetPointer.makeChildWidget(node);\n\t\t\t\t\twidget.computeAttributes();\n\t\t\t\t\twidget.execute();\n\t\t\t\t\t// We SHALLOW copy over all variables\n\t\t\t\t\t// in widget. We can't use\n\t\t\t\t\t// $tw.utils.assign, because that copies\n\t\t\t\t\t// up the prototype chain, which we\n\t\t\t\t\t// don't want.\n\t\t\t\t\t$tw.utils.each(Object.keys(widget.variables), function(key) {\n\t\t\t\t\t\twidgetPointer.variables[key] = widget.variables[key];\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\twidgetPointer.makeChildWidgets([node]);\n\t\t\t\t\twidgetPointer = widgetPointer.children[0];\n\t\t\t\t}\n\t\t\t\tparseTreeNode = parseTreeNode.children && parseTreeNode.children[0];\n\t\t\t}\n\t\t} \n\t});\n\n\tif (widgetPointer != this) {\n\t\twidgetPointer.parseTreeNode.children = this.parseTreeNode.children;\n\t} else {\n\t\twidgetPointer.makeChildWidgets();\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nImportVariablesWidget.prototype.refresh = function(changedTiddlers) {\n\t// Recompute our attributes and the filter list\n\tvar changedAttributes = this.computeAttributes(),\n\t\ttiddlerList = this.wiki.filterTiddlers(this.getAttribute(\"filter\"),this);\n\t// Refresh if the filter has changed, or the list of tiddlers has changed, or any of the tiddlers in the list has changed\n\tfunction haveListedTiddlersChanged() {\n\t\tvar changed = false;\n\t\ttiddlerList.forEach(function(title) {\n\t\t\tif(changedTiddlers[title]) {\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t});\n\t\treturn changed;\n\t}\n\tif(changedAttributes.filter || !$tw.utils.isArrayEqual(this.tiddlerList,tiddlerList) || haveListedTiddlersChanged()) {\n\t\t// Compute the filter\n\t\tthis.removeChildDomNodes();\n\t\tthis.execute(tiddlerList);\n\t\tthis.renderChildren(this.parentDomNode,this.findNextSiblingDomNode());\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nexports.importvariables = ImportVariablesWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/keyboard.js": {
            "title": "$:/core/modules/widgets/keyboard.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/keyboard.js\ntype: application/javascript\nmodule-type: widget\n\nKeyboard shortcut widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar KeyboardWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nKeyboardWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nKeyboardWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar tag = this.parseTreeNode.isBlock ? \"div\" : \"span\";\n\tif(this.tag && $tw.config.htmlUnsafeElements.indexOf(this.tag) === -1) {\n\t\ttag = this.tag;\n\t}\n\t// Create element\n\tvar domNode = this.document.createElement(tag);\n\t// Assign classes\n\tvar classes = (this[\"class\"] || \"\").split(\" \");\n\tclasses.push(\"tc-keyboard\");\n\tdomNode.className = classes.join(\" \");\n\t// Add a keyboard event handler\n\tdomNode.addEventListener(\"keydown\",function (event) {\n\t\tif($tw.keyboardManager.checkKeyDescriptors(event,self.keyInfoArray)) {\n\t\t\tself.invokeActions(self,event);\n\t\t\tif(self.actions) {\n\t\t\t\tself.invokeActionString(self.actions,self,event);\n\t\t\t}\n\t\t\tself.dispatchMessage(event);\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},false);\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\nKeyboardWidget.prototype.dispatchMessage = function(event) {\n\tthis.dispatchEvent({type: this.message, param: this.param, tiddlerTitle: this.getVariable(\"currentTiddler\")});\n};\n\n/*\nCompute the internal state of the widget\n*/\nKeyboardWidget.prototype.execute = function() {\n\tvar self = this;\n\t// Get attributes\n\tthis.actions = this.getAttribute(\"actions\",\"\");\n\tthis.message = this.getAttribute(\"message\",\"\");\n\tthis.param = this.getAttribute(\"param\",\"\");\n\tthis.key = this.getAttribute(\"key\",\"\");\n\tthis.tag = this.getAttribute(\"tag\",\"\");\n\tthis.keyInfoArray = $tw.keyboardManager.parseKeyDescriptors(this.key);\n\tthis[\"class\"] = this.getAttribute(\"class\",\"\");\n\tif(this.key.substr(0,2) === \"((\" && this.key.substr(-2,2) === \"))\") {\n\t\tthis.shortcutTiddlers = [];\n\t\tvar name = this.key.substring(2,this.key.length -2);\n\t\t$tw.utils.each($tw.keyboardManager.lookupNames,function(platformDescriptor) {\n\t\t\tself.shortcutTiddlers.push(\"$:/config/\" + platformDescriptor + \"/\" + name);\n\t\t});\n\t}\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nKeyboardWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.message || changedAttributes.param || changedAttributes.key || changedAttributes[\"class\"] || changedAttributes.tag) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\t// Update the keyInfoArray if one of its shortcut-config-tiddlers has changed\n\tif(this.shortcutTiddlers && $tw.utils.hopArray(changedTiddlers,this.shortcutTiddlers)) {\n\t\tthis.keyInfoArray = $tw.keyboardManager.parseKeyDescriptors(this.key);\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.keyboard = KeyboardWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/link.js": {
            "title": "$:/core/modules/widgets/link.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/link.js\ntype: application/javascript\nmodule-type: widget\n\nLink widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar LinkWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nLinkWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nLinkWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Get the value of the tv-wikilinks configuration macro\n\tvar wikiLinksMacro = this.getVariable(\"tv-wikilinks\"),\n\t\tuseWikiLinks = wikiLinksMacro ? (wikiLinksMacro.trim() !== \"no\") : true,\n\t\tmissingLinksEnabled = !(this.hideMissingLinks && this.isMissing && !this.isShadow);\n\t// Render the link if required\n\tif(useWikiLinks && missingLinksEnabled) {\n\t\tthis.renderLink(parent,nextSibling);\n\t} else {\n\t\t// Just insert the link text\n\t\tvar domNode = this.document.createElement(\"span\");\n\t\tparent.insertBefore(domNode,nextSibling);\n\t\tthis.renderChildren(domNode,null);\n\t\tthis.domNodes.push(domNode);\n\t}\n};\n\n/*\nRender this widget into the DOM\n*/\nLinkWidget.prototype.renderLink = function(parent,nextSibling) {\n\tvar self = this;\n\t// Sanitise the specified tag\n\tvar tag = this.linkTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"a\";\n\t}\n\t// Create our element\n\tvar domNode = this.document.createElement(tag);\n\t// Assign classes\n\tvar classes = [];\n\tif(this.overrideClasses === undefined) {\n\t\tclasses.push(\"tc-tiddlylink\");\n\t\tif(this.isShadow) {\n\t\t\tclasses.push(\"tc-tiddlylink-shadow\");\n\t\t}\n\t\tif(this.isMissing && !this.isShadow) {\n\t\t\tclasses.push(\"tc-tiddlylink-missing\");\n\t\t} else {\n\t\t\tif(!this.isMissing) {\n\t\t\t\tclasses.push(\"tc-tiddlylink-resolves\");\n\t\t\t}\n\t\t}\n\t\tif(this.linkClasses) {\n\t\t\tclasses.push(this.linkClasses);\t\t\t\n\t\t}\n\t} else if(this.overrideClasses !== \"\") {\n\t\tclasses.push(this.overrideClasses)\n\t}\n\tif(classes.length > 0) {\n\t\tdomNode.setAttribute(\"class\",classes.join(\" \"));\n\t}\n\t// Set an href\n\tvar wikilinkTransformFilter = this.getVariable(\"tv-filter-export-link\"),\n\t\twikiLinkText;\n\tif(wikilinkTransformFilter) {\n\t\t// Use the filter to construct the href\n\t\twikiLinkText = this.wiki.filterTiddlers(wikilinkTransformFilter,this,function(iterator) {\n\t\t\titerator(self.wiki.getTiddler(self.to),self.to)\n\t\t})[0];\n\t} else {\n\t\t// Expand the tv-wikilink-template variable to construct the href\n\t\tvar wikiLinkTemplateMacro = this.getVariable(\"tv-wikilink-template\"),\n\t\t\twikiLinkTemplate = wikiLinkTemplateMacro ? wikiLinkTemplateMacro.trim() : \"#$uri_encoded$\";\n\t\twikiLinkText = $tw.utils.replaceString(wikiLinkTemplate,\"$uri_encoded$\",encodeURIComponent(this.to));\n\t\twikiLinkText = $tw.utils.replaceString(wikiLinkText,\"$uri_doubleencoded$\",encodeURIComponent(encodeURIComponent(this.to)));\n\t}\n\t// Override with the value of tv-get-export-link if defined\n\twikiLinkText = this.getVariable(\"tv-get-export-link\",{params: [{name: \"to\",value: this.to}],defaultValue: wikiLinkText});\n\tif(tag === \"a\") {\n\t\tdomNode.setAttribute(\"href\",wikiLinkText);\n\t}\n\t// Set the tabindex\n\tif(this.tabIndex) {\n\t\tdomNode.setAttribute(\"tabindex\",this.tabIndex);\n\t}\n\t// Set the tooltip\n\t// HACK: Performance issues with re-parsing the tooltip prevent us defaulting the tooltip to \"<$transclude field='tooltip'><$transclude field='title'/></$transclude>\"\n\tvar tooltipWikiText = this.tooltip || this.getVariable(\"tv-wikilink-tooltip\");\n\tif(tooltipWikiText) {\n\t\tvar tooltipText = this.wiki.renderText(\"text/plain\",\"text/vnd.tiddlywiki\",tooltipWikiText,{\n\t\t\t\tparseAsInline: true,\n\t\t\t\tvariables: {\n\t\t\t\t\tcurrentTiddler: this.to\n\t\t\t\t},\n\t\t\t\tparentWidget: this\n\t\t\t});\n\t\tdomNode.setAttribute(\"title\",tooltipText);\n\t}\n\tif(this[\"aria-label\"]) {\n\t\tdomNode.setAttribute(\"aria-label\",this[\"aria-label\"]);\n\t}\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(domNode,[\n\t\t{name: \"click\", handlerObject: this, handlerMethod: \"handleClickEvent\"},\n\t]);\n\t// Make the link draggable if required\n\tif(this.draggable === \"yes\") {\n\t\t$tw.utils.makeDraggable({\n\t\t\tdomNode: domNode,\n\t\t\tdragTiddlerFn: function() {return self.to;},\n\t\t\twidget: this\n\t\t});\n\t}\n\t// Insert the link into the DOM and render any children\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\nLinkWidget.prototype.handleClickEvent = function(event) {\n\t// Send the click on its way as a navigate event\n\tvar bounds = this.domNodes[0].getBoundingClientRect();\n\tthis.dispatchEvent({\n\t\ttype: \"tm-navigate\",\n\t\tnavigateTo: this.to,\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tnavigateFromNode: this,\n\t\tnavigateFromClientRect: { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height\n\t\t},\n\t\tnavigateSuppressNavigation: event.metaKey || event.ctrlKey || (event.button === 1),\n\t\tmetaKey: event.metaKey,\n\t\tctrlKey: event.ctrlKey,\n\t\taltKey: event.altKey,\n\t\tshiftKey: event.shiftKey\n\t});\n\tif(this.domNodes[0].hasAttribute(\"href\")) {\n\t\tevent.preventDefault();\n\t}\n\tevent.stopPropagation();\n\treturn false;\n};\n\n/*\nCompute the internal state of the widget\n*/\nLinkWidget.prototype.execute = function() {\n\t// Pick up our attributes\n\tthis.to = this.getAttribute(\"to\",this.getVariable(\"currentTiddler\"));\n\tthis.tooltip = this.getAttribute(\"tooltip\");\n\tthis[\"aria-label\"] = this.getAttribute(\"aria-label\");\n\tthis.linkClasses = this.getAttribute(\"class\");\n\tthis.overrideClasses = this.getAttribute(\"overrideClass\");\n\tthis.tabIndex = this.getAttribute(\"tabindex\");\n\tthis.draggable = this.getAttribute(\"draggable\",\"yes\");\n\tthis.linkTag = this.getAttribute(\"tag\",\"a\");\n\t// Determine the link characteristics\n\tthis.isMissing = !this.wiki.tiddlerExists(this.to);\n\tthis.isShadow = this.wiki.isShadowTiddler(this.to);\n\tthis.hideMissingLinks = (this.getVariable(\"tv-show-missing-links\") || \"yes\") === \"no\";\n\t// Make the child widgets\n\tvar templateTree;\n\tif(this.parseTreeNode.children && this.parseTreeNode.children.length > 0) {\n\t\ttemplateTree = this.parseTreeNode.children;\n\t} else {\n\t\t// Default template is a link to the title\n\t\ttemplateTree = [{type: \"text\", text: this.to}];\n\t}\n\tthis.makeChildWidgets(templateTree);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nLinkWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.to || changedTiddlers[this.to] || changedAttributes[\"aria-label\"] || changedAttributes.tooltip) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.link = LinkWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/linkcatcher.js": {
            "title": "$:/core/modules/widgets/linkcatcher.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/linkcatcher.js\ntype: application/javascript\nmodule-type: widget\n\nLinkcatcher widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar LinkCatcherWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.addEventListeners([\n\t\t{type: \"tm-navigate\", handler: \"handleNavigateEvent\"}\n\t]);\n};\n\n/*\nInherit from the base widget class\n*/\nLinkCatcherWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nLinkCatcherWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nLinkCatcherWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.catchTo = this.getAttribute(\"to\");\n\tthis.catchMessage = this.getAttribute(\"message\");\n\tthis.catchSet = this.getAttribute(\"set\");\n\tthis.catchSetTo = this.getAttribute(\"setTo\");\n\tthis.catchActions = this.getAttribute(\"actions\");\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n\t// When executing actions we avoid trapping navigate events, so that we don't trigger ourselves recursively\n\tthis.executingActions = false;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nLinkCatcherWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.to || changedAttributes.message || changedAttributes.set || changedAttributes.setTo) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\n/*\nHandle a tm-navigate event\n*/\nLinkCatcherWidget.prototype.handleNavigateEvent = function(event) {\n\tif(!this.executingActions) {\n\t\t// Execute the actions\n\t\tif(this.catchTo) {\n\t\t\tthis.wiki.setTextReference(this.catchTo,event.navigateTo,this.getVariable(\"currentTiddler\"));\n\t\t}\n\t\tif(this.catchMessage && this.parentWidget) {\n\t\t\tthis.parentWidget.dispatchEvent({\n\t\t\t\ttype: this.catchMessage,\n\t\t\t\tparam: event.navigateTo,\n\t\t\t\tnavigateTo: event.navigateTo\n\t\t\t});\n\t\t}\n\t\tif(this.catchSet) {\n\t\t\tvar tiddler = this.wiki.getTiddler(this.catchSet);\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: this.catchSet, text: this.catchSetTo}));\n\t\t}\n\t\tif(this.catchActions) {\n\t\t\tthis.executingActions = true;\n\t\t\tthis.invokeActionString(this.catchActions,this,event,{navigateTo: event.navigateTo});\n\t\t\tthis.executingActions = false;\n\t\t}\n\t} else {\n\t\t// This is a navigate event generated by the actions of this linkcatcher, so we don't trap it again, but just pass it to the parent\n\t\tthis.parentWidget.dispatchEvent({\n\t\t\ttype: \"tm-navigate\",\n\t\t\tparam: event.navigateTo,\n\t\t\tnavigateTo: event.navigateTo\n\t\t});\n\t}\n\treturn false;\n};\n\nexports.linkcatcher = LinkCatcherWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/list.js": {
            "title": "$:/core/modules/widgets/list.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/list.js\ntype: application/javascript\nmodule-type: widget\n\nList and list item widgets\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\n/*\nThe list widget creates list element sub-widgets that reach back into the list widget for their configuration\n*/\n\nvar ListWidget = function(parseTreeNode,options) {\n\t// Initialise the storyviews if they've not been done already\n\tif(!this.storyViews) {\n\t\tListWidget.prototype.storyViews = {};\n\t\t$tw.modules.applyMethods(\"storyview\",this.storyViews);\n\t}\n\t// Main initialisation inherited from widget.js\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nListWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nListWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n\t// Construct the storyview\n\tvar StoryView = this.storyViews[this.storyViewName];\n\tif(this.storyViewName && !StoryView) {\n\t\tStoryView = this.storyViews[\"classic\"];\n\t}\n\tif(StoryView && !this.document.isTiddlyWikiFakeDom) {\n\t\tthis.storyview = new StoryView(this);\n\t} else {\n\t\tthis.storyview = null;\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nListWidget.prototype.execute = function() {\n\t// Get our attributes\n\tthis.template = this.getAttribute(\"template\");\n\tthis.editTemplate = this.getAttribute(\"editTemplate\");\n\tthis.variableName = this.getAttribute(\"variable\",\"currentTiddler\");\n\tthis.storyViewName = this.getAttribute(\"storyview\");\n\tthis.historyTitle = this.getAttribute(\"history\");\n\t// Compose the list elements\n\tthis.list = this.getTiddlerList();\n\tvar members = [],\n\t\tself = this;\n\t// Check for an empty list\n\tif(this.list.length === 0) {\n\t\tmembers = this.getEmptyMessage();\n\t} else {\n\t\t$tw.utils.each(this.list,function(title,index) {\n\t\t\tmembers.push(self.makeItemTemplate(title));\n\t\t});\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets(members);\n\t// Clear the last history\n\tthis.history = [];\n};\n\nListWidget.prototype.getTiddlerList = function() {\n\tvar defaultFilter = \"[!is[system]sort[title]]\";\n\treturn this.wiki.filterTiddlers(this.getAttribute(\"filter\",defaultFilter),this);\n};\n\nListWidget.prototype.getEmptyMessage = function() {\n\tvar emptyMessage = this.getAttribute(\"emptyMessage\",\"\"),\n\t\tparser = this.wiki.parseText(\"text/vnd.tiddlywiki\",emptyMessage,{parseAsInline: true});\n\tif(parser) {\n\t\treturn parser.tree;\n\t} else {\n\t\treturn [];\n\t}\n};\n\n/*\nCompose the template for a list item\n*/\nListWidget.prototype.makeItemTemplate = function(title) {\n\t// Check if the tiddler is a draft\n\tvar tiddler = this.wiki.getTiddler(title),\n\t\tisDraft = tiddler && tiddler.hasField(\"draft.of\"),\n\t\ttemplate = this.template,\n\t\ttemplateTree;\n\tif(isDraft && this.editTemplate) {\n\t\ttemplate = this.editTemplate;\n\t}\n\t// Compose the transclusion of the template\n\tif(template) {\n\t\ttemplateTree = [{type: \"transclude\", attributes: {tiddler: {type: \"string\", value: template}}}];\n\t} else {\n\t\tif(this.parseTreeNode.children && this.parseTreeNode.children.length > 0) {\n\t\t\ttemplateTree = this.parseTreeNode.children;\n\t\t} else {\n\t\t\t// Default template is a link to the title\n\t\t\ttemplateTree = [{type: \"element\", tag: this.parseTreeNode.isBlock ? \"div\" : \"span\", children: [{type: \"link\", attributes: {to: {type: \"string\", value: title}}, children: [\n\t\t\t\t\t{type: \"text\", text: title}\n\t\t\t]}]}];\n\t\t}\n\t}\n\t// Return the list item\n\treturn {type: \"listitem\", itemTitle: title, variableName: this.variableName, children: templateTree};\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nListWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes(),\n\t\tresult;\n\t// Call the storyview\n\tif(this.storyview && this.storyview.refreshStart) {\n\t\tthis.storyview.refreshStart(changedTiddlers,changedAttributes);\n\t}\n\t// Completely refresh if any of our attributes have changed\n\tif(changedAttributes.filter || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.emptyMessage || changedAttributes.storyview || changedAttributes.history) {\n\t\tthis.refreshSelf();\n\t\tresult = true;\n\t} else {\n\t\t// Handle any changes to the list\n\t\tresult = this.handleListChanges(changedTiddlers);\n\t\t// Handle any changes to the history stack\n\t\tif(this.historyTitle && changedTiddlers[this.historyTitle]) {\n\t\t\tthis.handleHistoryChanges();\n\t\t}\n\t}\n\t// Call the storyview\n\tif(this.storyview && this.storyview.refreshEnd) {\n\t\tthis.storyview.refreshEnd(changedTiddlers,changedAttributes);\n\t}\n\treturn result;\n};\n\n/*\nHandle any changes to the history list\n*/\nListWidget.prototype.handleHistoryChanges = function() {\n\t// Get the history data\n\tvar newHistory = this.wiki.getTiddlerDataCached(this.historyTitle,[]);\n\t// Ignore any entries of the history that match the previous history\n\tvar entry = 0;\n\twhile(entry < newHistory.length && entry < this.history.length && newHistory[entry].title === this.history[entry].title) {\n\t\tentry++;\n\t}\n\t// Navigate forwards to each of the new tiddlers\n\twhile(entry < newHistory.length) {\n\t\tif(this.storyview && this.storyview.navigateTo) {\n\t\t\tthis.storyview.navigateTo(newHistory[entry]);\n\t\t}\n\t\tentry++;\n\t}\n\t// Update the history\n\tthis.history = newHistory;\n};\n\n/*\nProcess any changes to the list\n*/\nListWidget.prototype.handleListChanges = function(changedTiddlers) {\n\t// Get the new list\n\tvar prevList = this.list;\n\tthis.list = this.getTiddlerList();\n\t// Check for an empty list\n\tif(this.list.length === 0) {\n\t\t// Check if it was empty before\n\t\tif(prevList.length === 0) {\n\t\t\t// If so, just refresh the empty message\n\t\t\treturn this.refreshChildren(changedTiddlers);\n\t\t} else {\n\t\t\t// Replace the previous content with the empty message\n\t\t\tfor(t=this.children.length-1; t>=0; t--) {\n\t\t\t\tthis.removeListItem(t);\n\t\t\t}\n\t\t\tvar nextSibling = this.findNextSiblingDomNode();\n\t\t\tthis.makeChildWidgets(this.getEmptyMessage());\n\t\t\tthis.renderChildren(this.parentDomNode,nextSibling);\n\t\t\treturn true;\n\t\t}\n\t} else {\n\t\t// If the list was empty then we need to remove the empty message\n\t\tif(prevList.length === 0) {\n\t\t\tthis.removeChildDomNodes();\n\t\t\tthis.children = [];\n\t\t}\n\t\t// Cycle through the list, inserting and removing list items as needed\n\t\tvar hasRefreshed = false;\n\t\tfor(var t=0; t<this.list.length; t++) {\n\t\t\tvar index = this.findListItem(t,this.list[t]);\n\t\t\tif(index === undefined) {\n\t\t\t\t// The list item must be inserted\n\t\t\t\tthis.insertListItem(t,this.list[t]);\n\t\t\t\thasRefreshed = true;\n\t\t\t} else {\n\t\t\t\t// There are intervening list items that must be removed\n\t\t\t\tfor(var n=index-1; n>=t; n--) {\n\t\t\t\t\tthis.removeListItem(n);\n\t\t\t\t\thasRefreshed = true;\n\t\t\t\t}\n\t\t\t\t// Refresh the item we're reusing\n\t\t\t\tvar refreshed = this.children[t].refresh(changedTiddlers);\n\t\t\t\thasRefreshed = hasRefreshed || refreshed;\n\t\t\t}\n\t\t}\n\t\t// Remove any left over items\n\t\tfor(t=this.children.length-1; t>=this.list.length; t--) {\n\t\t\tthis.removeListItem(t);\n\t\t\thasRefreshed = true;\n\t\t}\n\t\treturn hasRefreshed;\n\t}\n};\n\n/*\nFind the list item with a given title, starting from a specified position\n*/\nListWidget.prototype.findListItem = function(startIndex,title) {\n\twhile(startIndex < this.children.length) {\n\t\tif(this.children[startIndex].parseTreeNode.itemTitle === title) {\n\t\t\treturn startIndex;\n\t\t}\n\t\tstartIndex++;\n\t}\n\treturn undefined;\n};\n\n/*\nInsert a new list item at the specified index\n*/\nListWidget.prototype.insertListItem = function(index,title) {\n\t// Create, insert and render the new child widgets\n\tvar widget = this.makeChildWidget(this.makeItemTemplate(title));\n\twidget.parentDomNode = this.parentDomNode; // Hack to enable findNextSiblingDomNode() to work\n\tthis.children.splice(index,0,widget);\n\tvar nextSibling = widget.findNextSiblingDomNode();\n\twidget.render(this.parentDomNode,nextSibling);\n\t// Animate the insertion if required\n\tif(this.storyview && this.storyview.insert) {\n\t\tthis.storyview.insert(widget);\n\t}\n\treturn true;\n};\n\n/*\nRemove the specified list item\n*/\nListWidget.prototype.removeListItem = function(index) {\n\tvar widget = this.children[index];\n\t// Animate the removal if required\n\tif(this.storyview && this.storyview.remove) {\n\t\tthis.storyview.remove(widget);\n\t} else {\n\t\twidget.removeChildDomNodes();\n\t}\n\t// Remove the child widget\n\tthis.children.splice(index,1);\n};\n\nexports.list = ListWidget;\n\nvar ListItemWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nListItemWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nListItemWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nListItemWidget.prototype.execute = function() {\n\t// Set the current list item title\n\tthis.setVariable(this.parseTreeNode.variableName,this.parseTreeNode.itemTitle);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nListItemWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.listitem = ListItemWidget;\n\n})();",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/macrocall.js": {
            "title": "$:/core/modules/widgets/macrocall.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/macrocall.js\ntype: application/javascript\nmodule-type: widget\n\nMacrocall widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar MacroCallWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nMacroCallWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nMacroCallWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nMacroCallWidget.prototype.execute = function() {\n\t// Get the parse type if specified\n\tthis.parseType = this.getAttribute(\"$type\",\"text/vnd.tiddlywiki\");\n\tthis.renderOutput = this.getAttribute(\"$output\",\"text/html\");\n\t// Merge together the parameters specified in the parse tree with the specified attributes\n\tvar params = this.parseTreeNode.params ? this.parseTreeNode.params.slice(0) : [];\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tparams.push({name: name, value: attribute});\t\t\t\n\t\t}\n\t});\n\t// Get the macro value\n\tvar macroName = this.parseTreeNode.name || this.getAttribute(\"$name\"),\n\t\tvariableInfo = this.getVariableInfo(macroName,{params: params}),\n\t\ttext = variableInfo.text,\n\t\tparseTreeNodes;\n\t// Are we rendering to HTML?\n\tif(this.renderOutput === \"text/html\") {\n\t\t// If so we'll return the parsed macro\n\t\tvar parser = this.wiki.parseText(this.parseType,text,\n\t\t\t\t\t\t\t{parseAsInline: !this.parseTreeNode.isBlock});\n\t\tparseTreeNodes = parser ? parser.tree : [];\n\t\t// Wrap the parse tree in a vars widget assigning the parameters to variables named \"__paramname__\"\n\t\tvar attributes = {};\n\t\t$tw.utils.each(variableInfo.params,function(param) {\n\t\t\tvar name = \"__\" + param.name + \"__\";\n\t\t\tattributes[name] = {\n\t\t\t\tname: name,\n\t\t\t\ttype: \"string\",\n\t\t\t\tvalue: param.value\n\t\t\t};\n\t\t});\n\t\tparseTreeNodes = [{\n\t\t\ttype: \"vars\",\n\t\t\tattributes: attributes,\n\t\t\tchildren: parseTreeNodes\n\t\t}];\n\t} else {\n\t\t// Otherwise, we'll render the text\n\t\tvar plainText = this.wiki.renderText(\"text/plain\",this.parseType,text,{parentWidget: this});\n\t\tparseTreeNodes = [{type: \"text\", text: plainText}];\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets(parseTreeNodes);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nMacroCallWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif($tw.utils.count(changedAttributes) > 0) {\n\t\t// Rerender ourselves\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.macrocall = MacroCallWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/navigator.js": {
            "title": "$:/core/modules/widgets/navigator.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/navigator.js\ntype: application/javascript\nmodule-type: widget\n\nNavigator widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar IMPORT_TITLE = \"$:/Import\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar NavigatorWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.addEventListeners([\n\t\t{type: \"tm-navigate\", handler: \"handleNavigateEvent\"},\n\t\t{type: \"tm-edit-tiddler\", handler: \"handleEditTiddlerEvent\"},\n\t\t{type: \"tm-delete-tiddler\", handler: \"handleDeleteTiddlerEvent\"},\n\t\t{type: \"tm-save-tiddler\", handler: \"handleSaveTiddlerEvent\"},\n\t\t{type: \"tm-cancel-tiddler\", handler: \"handleCancelTiddlerEvent\"},\n\t\t{type: \"tm-close-tiddler\", handler: \"handleCloseTiddlerEvent\"},\n\t\t{type: \"tm-close-all-tiddlers\", handler: \"handleCloseAllTiddlersEvent\"},\n\t\t{type: \"tm-close-other-tiddlers\", handler: \"handleCloseOtherTiddlersEvent\"},\n\t\t{type: \"tm-new-tiddler\", handler: \"handleNewTiddlerEvent\"},\n\t\t{type: \"tm-import-tiddlers\", handler: \"handleImportTiddlersEvent\"},\n\t\t{type: \"tm-perform-import\", handler: \"handlePerformImportEvent\"},\n\t\t{type: \"tm-fold-tiddler\", handler: \"handleFoldTiddlerEvent\"},\n\t\t{type: \"tm-fold-other-tiddlers\", handler: \"handleFoldOtherTiddlersEvent\"},\n\t\t{type: \"tm-fold-all-tiddlers\", handler: \"handleFoldAllTiddlersEvent\"},\n\t\t{type: \"tm-unfold-all-tiddlers\", handler: \"handleUnfoldAllTiddlersEvent\"},\n\t\t{type: \"tm-rename-tiddler\", handler: \"handleRenameTiddlerEvent\"}\n\t]);\n};\n\n/*\nInherit from the base widget class\n*/\nNavigatorWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nNavigatorWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nNavigatorWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.storyTitle = this.getAttribute(\"story\");\n\tthis.historyTitle = this.getAttribute(\"history\");\n\tthis.setVariable(\"tv-story-list\",this.storyTitle);\n\tthis.setVariable(\"tv-history-list\",this.historyTitle);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nNavigatorWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.story || changedAttributes.history) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nNavigatorWidget.prototype.getStoryList = function() {\n\treturn this.storyTitle ? this.wiki.getTiddlerList(this.storyTitle) : null;\n};\n\nNavigatorWidget.prototype.saveStoryList = function(storyList) {\n\tif(this.storyTitle) {\n\t\tvar storyTiddler = this.wiki.getTiddler(this.storyTitle);\n\t\tthis.wiki.addTiddler(new $tw.Tiddler(\n\t\t\t{title: this.storyTitle},\n\t\t\tstoryTiddler,\n\t\t\t{list: storyList}\n\t\t));\t\t\n\t}\n};\n\nNavigatorWidget.prototype.removeTitleFromStory = function(storyList,title) {\n\tif(storyList) {\n\t\tvar p = storyList.indexOf(title);\n\t\twhile(p !== -1) {\n\t\t\tstoryList.splice(p,1);\n\t\t\tp = storyList.indexOf(title);\n\t\t}\t\t\n\t}\n};\n\nNavigatorWidget.prototype.replaceFirstTitleInStory = function(storyList,oldTitle,newTitle) {\n\tif(storyList) {\n\t\tvar pos = storyList.indexOf(oldTitle);\n\t\tif(pos !== -1) {\n\t\t\tstoryList[pos] = newTitle;\n\t\t\tdo {\n\t\t\t\tpos = storyList.indexOf(oldTitle,pos + 1);\n\t\t\t\tif(pos !== -1) {\n\t\t\t\t\tstoryList.splice(pos,1);\n\t\t\t\t}\n\t\t\t} while(pos !== -1);\n\t\t} else {\n\t\t\tstoryList.splice(0,0,newTitle);\n\t\t}\t\t\n\t}\n};\n\nNavigatorWidget.prototype.addToStory = function(title,fromTitle) {\n\tif(this.storyTitle) {\n\t\tthis.wiki.addToStory(title,fromTitle,this.storyTitle,{\n\t\t\topenLinkFromInsideRiver: this.getAttribute(\"openLinkFromInsideRiver\",\"top\"),\n\t\t\topenLinkFromOutsideRiver: this.getAttribute(\"openLinkFromOutsideRiver\",\"top\")\n\t\t});\n\t}\n};\n\n/*\nAdd a new record to the top of the history stack\ntitle: a title string or an array of title strings\nfromPageRect: page coordinates of the origin of the navigation\n*/\nNavigatorWidget.prototype.addToHistory = function(title,fromPageRect) {\n\tthis.wiki.addToHistory(title,fromPageRect,this.historyTitle);\n};\n\n/*\nHandle a tm-navigate event\n*/\nNavigatorWidget.prototype.handleNavigateEvent = function(event) {\n\tevent = $tw.hooks.invokeHook(\"th-navigating\",event);\n\tif(event.navigateTo) {\n\t\tthis.addToStory(event.navigateTo,event.navigateFromTitle);\n\t\tif(!event.navigateSuppressNavigation) {\n\t\t\tthis.addToHistory(event.navigateTo,event.navigateFromClientRect);\n\t\t}\n\t}\n\treturn false;\n};\n\n// Close a specified tiddler\nNavigatorWidget.prototype.handleCloseTiddlerEvent = function(event) {\n\tvar title = event.param || event.tiddlerTitle,\n\t\tstoryList = this.getStoryList();\n\t// Look for tiddlers with this title to close\n\tthis.removeTitleFromStory(storyList,title);\n\tthis.saveStoryList(storyList);\n\treturn false;\n};\n\n// Close all tiddlers\nNavigatorWidget.prototype.handleCloseAllTiddlersEvent = function(event) {\n\tthis.saveStoryList([]);\n\treturn false;\n};\n\n// Close other tiddlers\nNavigatorWidget.prototype.handleCloseOtherTiddlersEvent = function(event) {\n\tvar title = event.param || event.tiddlerTitle;\n\tthis.saveStoryList([title]);\n\treturn false;\n};\n\n// Place a tiddler in edit mode\nNavigatorWidget.prototype.handleEditTiddlerEvent = function(event) {\n\tvar editTiddler = $tw.hooks.invokeHook(\"th-editing-tiddler\",event);\n\tif(!editTiddler) {\n\t\treturn false;\n\t}\n\tvar self = this;\n\tfunction isUnmodifiedShadow(title) {\n\t\treturn self.wiki.isShadowTiddler(title) && !self.wiki.tiddlerExists(title);\n\t}\n\tfunction confirmEditShadow(title) {\n\t\treturn confirm($tw.language.getString(\n\t\t\t\"ConfirmEditShadowTiddler\",\n\t\t\t{variables:\n\t\t\t\t{title: title}\n\t\t\t}\n\t\t));\n\t}\n\tvar title = event.param || event.tiddlerTitle;\n\tif(isUnmodifiedShadow(title) && !confirmEditShadow(title)) {\n\t\treturn false;\n\t}\n\t// Replace the specified tiddler with a draft in edit mode\n\tvar draftTiddler = this.makeDraftTiddler(title);\n\t// Update the story and history if required\n\tif(!event.paramObject || event.paramObject.suppressNavigation !== \"yes\") {\n\t\tvar draftTitle = draftTiddler.fields.title,\n\t\t\tstoryList = this.getStoryList();\n\t\tthis.removeTitleFromStory(storyList,draftTitle);\n\t\tthis.replaceFirstTitleInStory(storyList,title,draftTitle);\n\t\tthis.addToHistory(draftTitle,event.navigateFromClientRect);\n\t\tthis.saveStoryList(storyList);\n\t\treturn false;\n\t}\n};\n\n// Delete a tiddler\nNavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {\n\t// Get the tiddler we're deleting\n\tvar title = event.param || event.tiddlerTitle,\n\t\ttiddler = this.wiki.getTiddler(title),\n\t\tstoryList = this.getStoryList(),\n\t\toriginalTitle = tiddler ? tiddler.fields[\"draft.of\"] : \"\",\n\t\toriginalTiddler = originalTitle ? this.wiki.getTiddler(originalTitle) : undefined,\n\t\tconfirmationTitle;\n\tif(!tiddler) {\n\t\treturn false;\n\t}\n\t// Check if the tiddler we're deleting is in draft mode\n\tif(originalTitle) {\n\t\t// If so, we'll prompt for confirmation referencing the original tiddler\n\t\tconfirmationTitle = originalTitle;\n\t} else {\n\t\t// If not a draft, then prompt for confirmation referencing the specified tiddler\n\t\tconfirmationTitle = title;\n\t}\n\t// Seek confirmation\n\tif((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || \"\") !== \"\") && !confirm($tw.language.getString(\n\t\t\t\t\"ConfirmDeleteTiddler\",\n\t\t\t\t{variables:\n\t\t\t\t\t{title: confirmationTitle}\n\t\t\t\t}\n\t\t\t))) {\n\t\treturn false;\n\t}\n\t// Delete the original tiddler\n\tif(originalTitle) {\n\t\tif(originalTiddler) {\n\t\t\t$tw.hooks.invokeHook(\"th-deleting-tiddler\",originalTiddler);\n\t\t}\n\t\tthis.wiki.deleteTiddler(originalTitle);\n\t\tthis.removeTitleFromStory(storyList,originalTitle);\n\t}\n\t// Invoke the hook function and delete this tiddler\n\t$tw.hooks.invokeHook(\"th-deleting-tiddler\",tiddler);\n\tthis.wiki.deleteTiddler(title);\n\t// Remove the closed tiddler from the story\n\tthis.removeTitleFromStory(storyList,title);\n\tthis.saveStoryList(storyList);\n\t// Trigger an autosave\n\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n\treturn false;\n};\n\n/*\nCreate/reuse the draft tiddler for a given title\n*/\nNavigatorWidget.prototype.makeDraftTiddler = function(targetTitle) {\n\t// See if there is already a draft tiddler for this tiddler\n\tvar draftTitle = this.wiki.findDraft(targetTitle);\n\tif(draftTitle) {\n\t\treturn this.wiki.getTiddler(draftTitle);\n\t}\n\t// Get the current value of the tiddler we're editing\n\tvar tiddler = this.wiki.getTiddler(targetTitle);\n\t// Save the initial value of the draft tiddler\n\tdraftTitle = this.generateDraftTitle(targetTitle);\n\tvar draftTiddler = new $tw.Tiddler(\n\t\t\ttiddler,\n\t\t\t{\n\t\t\t\ttitle: draftTitle,\n\t\t\t\t\"draft.title\": targetTitle,\n\t\t\t\t\"draft.of\": targetTitle\n\t\t\t},\n\t\t\tthis.wiki.getModificationFields()\n\t\t);\n\tthis.wiki.addTiddler(draftTiddler);\n\treturn draftTiddler;\n};\n\n/*\nGenerate a title for the draft of a given tiddler\n*/\nNavigatorWidget.prototype.generateDraftTitle = function(title) {\n\treturn this.wiki.generateDraftTitle(title);\n};\n\n// Take a tiddler out of edit mode, saving the changes\nNavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {\n\tvar title = event.param || event.tiddlerTitle,\n\t\ttiddler = this.wiki.getTiddler(title),\n\t\tstoryList = this.getStoryList();\n\t// Replace the original tiddler with the draft\n\tif(tiddler) {\n\t\tvar draftTitle = (tiddler.fields[\"draft.title\"] || \"\").trim(),\n\t\t\tdraftOf = (tiddler.fields[\"draft.of\"] || \"\").trim();\n\t\tif(draftTitle) {\n\t\t\tvar isRename = draftOf !== draftTitle,\n\t\t\t\tisConfirmed = true;\n\t\t\tif(isRename && this.wiki.tiddlerExists(draftTitle)) {\n\t\t\t\tisConfirmed = confirm($tw.language.getString(\n\t\t\t\t\t\"ConfirmOverwriteTiddler\",\n\t\t\t\t\t{variables:\n\t\t\t\t\t\t{title: draftTitle}\n\t\t\t\t\t}\n\t\t\t\t));\n\t\t\t}\n\t\t\tif(isConfirmed) {\n\t\t\t\t// Create the new tiddler and pass it through the th-saving-tiddler hook\n\t\t\t\tvar newTiddler = new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,{\n\t\t\t\t\ttitle: draftTitle,\n\t\t\t\t\t\"draft.title\": undefined,\n\t\t\t\t\t\"draft.of\": undefined\n\t\t\t\t},this.wiki.getModificationFields());\n\t\t\t\tnewTiddler = $tw.hooks.invokeHook(\"th-saving-tiddler\",newTiddler);\n\t\t\t\tthis.wiki.addTiddler(newTiddler);\n\t\t\t\t// If enabled, relink references to renamed tiddler\n\t\t\t\tvar shouldRelink = this.getAttribute(\"relinkOnRename\",\"no\").toLowerCase().trim() === \"yes\";\n\t\t\t\tif(isRename && shouldRelink && this.wiki.tiddlerExists(draftOf)) {\nconsole.log(\"Relinking '\" + draftOf + \"' to '\" + draftTitle + \"'\");\n\t\t\t\t\tthis.wiki.relinkTiddler(draftOf,draftTitle);\n\t\t\t\t}\n\t\t\t\t// Remove the draft tiddler\n\t\t\t\tthis.wiki.deleteTiddler(title);\n\t\t\t\t// Remove the original tiddler if we're renaming it\n\t\t\t\tif(isRename) {\n\t\t\t\t\tthis.wiki.deleteTiddler(draftOf);\n\t\t\t\t}\n\t\t\t\t// #2381 always remove new title & old\n\t\t\t\tthis.removeTitleFromStory(storyList,draftTitle);\n\t\t\t\tthis.removeTitleFromStory(storyList,draftOf);\n\t\t\t\tif(!event.paramObject || event.paramObject.suppressNavigation !== \"yes\") {\n\t\t\t\t\t// Replace the draft in the story with the original\n\t\t\t\t\tthis.replaceFirstTitleInStory(storyList,title,draftTitle);\n\t\t\t\t\tthis.addToHistory(draftTitle,event.navigateFromClientRect);\n\t\t\t\t\tif(draftTitle !== this.storyTitle) {\n\t\t\t\t\t\tthis.saveStoryList(storyList);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Trigger an autosave\n\t\t\t\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n};\n\n// Take a tiddler out of edit mode without saving the changes\nNavigatorWidget.prototype.handleCancelTiddlerEvent = function(event) {\n\tevent = $tw.hooks.invokeHook(\"th-cancelling-tiddler\", event);\n\t// Flip the specified tiddler from draft back to the original\n\tvar draftTitle = event.param || event.tiddlerTitle,\n\t\tdraftTiddler = this.wiki.getTiddler(draftTitle),\n\t\toriginalTitle = draftTiddler && draftTiddler.fields[\"draft.of\"];\n\tif(draftTiddler && originalTitle) {\n\t\t// Ask for confirmation if the tiddler text has changed\n\t\tvar isConfirmed = true,\n\t\t\toriginalTiddler = this.wiki.getTiddler(originalTitle),\n\t\t\tstoryList = this.getStoryList();\n\t\tif(this.wiki.isDraftModified(draftTitle)) {\n\t\t\tisConfirmed = confirm($tw.language.getString(\n\t\t\t\t\"ConfirmCancelTiddler\",\n\t\t\t\t{variables:\n\t\t\t\t\t{title: draftTitle}\n\t\t\t\t}\n\t\t\t));\n\t\t}\n\t\t// Remove the draft tiddler\n\t\tif(isConfirmed) {\n\t\t\tthis.wiki.deleteTiddler(draftTitle);\n\t\t\tif(!event.paramObject || event.paramObject.suppressNavigation !== \"yes\") {\n\t\t\t\tif(originalTiddler) {\n\t\t\t\t\tthis.replaceFirstTitleInStory(storyList,draftTitle,originalTitle);\n\t\t\t\t\tthis.addToHistory(originalTitle,event.navigateFromClientRect);\n\t\t\t\t} else {\n\t\t\t\t\tthis.removeTitleFromStory(storyList,draftTitle);\n\t\t\t\t}\n\t\t\t\tthis.saveStoryList(storyList);\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n};\n\n// Create a new draft tiddler\n// event.param can either be the title of a template tiddler, or a hashmap of fields.\n//\n// The title of the newly created tiddler follows these rules:\n// * If a hashmap was used and a title field was specified, use that title\n// * If a hashmap was used without a title field, use a default title, if necessary making it unique with a numeric suffix\n// * If a template tiddler was used, use the title of the template, if necessary making it unique with a numeric suffix\n//\n// If a draft of the target tiddler already exists then it is reused\nNavigatorWidget.prototype.handleNewTiddlerEvent = function(event) {\n\tevent = $tw.hooks.invokeHook(\"th-new-tiddler\", event);\n\t// Get the story details\n\tvar storyList = this.getStoryList(),\n\t\ttemplateTiddler, additionalFields, title, draftTitle, existingTiddler;\n\t// Get the template tiddler (if any)\n\tif(typeof event.param === \"string\") {\n\t\t// Get the template tiddler\n\t\ttemplateTiddler = this.wiki.getTiddler(event.param);\n\t\t// Generate a new title\n\t\ttitle = this.wiki.generateNewTitle(event.param || $tw.language.getString(\"DefaultNewTiddlerTitle\"));\n\t}\n\t// Get the specified additional fields\n\tif(typeof event.paramObject === \"object\") {\n\t\tadditionalFields = event.paramObject;\n\t}\n\tif(typeof event.param === \"object\") { // Backwards compatibility with 5.1.3\n\t\tadditionalFields = event.param;\n\t}\n\tif(additionalFields && additionalFields.title) {\n\t\ttitle = additionalFields.title;\n\t}\n\t// Make a copy of the additional fields excluding any blank ones\n\tvar filteredAdditionalFields = $tw.utils.extend({},additionalFields);\n\tObject.keys(filteredAdditionalFields).forEach(function(fieldName) {\n\t\tif(filteredAdditionalFields[fieldName] === \"\") {\n\t\t\tdelete filteredAdditionalFields[fieldName];\n\t\t}\n\t});\n\t// Generate a title if we don't have one\n\ttitle = title || this.wiki.generateNewTitle($tw.language.getString(\"DefaultNewTiddlerTitle\"));\n\t// Find any existing draft for this tiddler\n\tdraftTitle = this.wiki.findDraft(title);\n\t// Pull in any existing tiddler\n\tif(draftTitle) {\n\t\texistingTiddler = this.wiki.getTiddler(draftTitle);\n\t} else {\n\t\tdraftTitle = this.generateDraftTitle(title);\n\t\texistingTiddler = this.wiki.getTiddler(title);\n\t}\n\t// Merge the tags\n\tvar mergedTags = [];\n\tif(existingTiddler && existingTiddler.fields.tags) {\n\t\t$tw.utils.pushTop(mergedTags,existingTiddler.fields.tags);\n\t}\n\tif(additionalFields && additionalFields.tags) {\n\t\t// Merge tags\n\t\tmergedTags = $tw.utils.pushTop(mergedTags,$tw.utils.parseStringArray(additionalFields.tags));\n\t}\n\tif(templateTiddler && templateTiddler.fields.tags) {\n\t\t// Merge tags\n\t\tmergedTags = $tw.utils.pushTop(mergedTags,templateTiddler.fields.tags);\n\t}\n\t// Save the draft tiddler\n\tvar draftTiddler = new $tw.Tiddler({\n\t\t\ttext: \"\",\n\t\t\t\"draft.title\": title\n\t\t},\n\t\ttemplateTiddler,\n\t\tadditionalFields,\n\t\tthis.wiki.getCreationFields(),\n\t\texistingTiddler,\n\t\tfilteredAdditionalFields,\n\t\t{\n\t\t\ttitle: draftTitle,\n\t\t\t\"draft.of\": title,\n\t\t\ttags: mergedTags\n\t\t},this.wiki.getModificationFields());\n\tthis.wiki.addTiddler(draftTiddler);\n\t// Update the story to insert the new draft at the top and remove any existing tiddler\n\tif(storyList && storyList.indexOf(draftTitle) === -1) {\n\t\tvar slot = storyList.indexOf(event.navigateFromTitle);\n\t\tif(slot === -1) {\n\t\t\tslot = this.getAttribute(\"openLinkFromOutsideRiver\",\"top\") === \"bottom\" ? storyList.length - 1 : slot;\n\t\t}\n\t\tstoryList.splice(slot + 1,0,draftTitle);\n\t}\n\tif(storyList && storyList.indexOf(title) !== -1) {\n\t\tstoryList.splice(storyList.indexOf(title),1);\n\t}\n\tthis.saveStoryList(storyList);\n\t// Add a new record to the top of the history stack\n\tthis.addToHistory(draftTitle);\n\treturn false;\n};\n\n// Import JSON tiddlers into a pending import tiddler\nNavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {\n\t// Get the tiddlers\n\tvar tiddlers = [];\n\ttry {\n\t\ttiddlers = JSON.parse(event.param);\n\t} catch(e) {\n\t}\n\t// Get the current $:/Import tiddler\n\tvar importTiddler = this.wiki.getTiddler(IMPORT_TITLE),\n\t\timportData = this.wiki.getTiddlerData(IMPORT_TITLE,{}),\n\t\tnewFields = new Object({\n\t\t\ttitle: IMPORT_TITLE,\n\t\t\ttype: \"application/json\",\n\t\t\t\"plugin-type\": \"import\",\n\t\t\t\"status\": \"pending\"\n\t\t}),\n\t\tincomingTiddlers = [];\n\t// Process each tiddler\n\timportData.tiddlers = importData.tiddlers || {};\n\t$tw.utils.each(tiddlers,function(tiddlerFields) {\n\t\ttiddlerFields.title = $tw.utils.trim(tiddlerFields.title);\n\t\tvar title = tiddlerFields.title;\n\t\tif(title) {\n\t\t\tincomingTiddlers.push(title);\n\t\t\timportData.tiddlers[title] = tiddlerFields;\n\t\t}\n\t});\n\t// Give the active upgrader modules a chance to process the incoming tiddlers\n\tvar messages = this.wiki.invokeUpgraders(incomingTiddlers,importData.tiddlers);\n\t$tw.utils.each(messages,function(message,title) {\n\t\tnewFields[\"message-\" + title] = message;\n\t});\n\t// Deselect any suppressed tiddlers\n\t$tw.utils.each(importData.tiddlers,function(tiddler,title) {\n\t\tif($tw.utils.count(tiddler) === 0) {\n\t\t\tnewFields[\"selection-\" + title] = \"unchecked\";\n\t\t}\n\t});\n\t// Save the $:/Import tiddler\n\tnewFields.text = JSON.stringify(importData,null,$tw.config.preferences.jsonSpaces);\n\tthis.wiki.addTiddler(new $tw.Tiddler(importTiddler,newFields));\n\t// Update the story and history details\n\tif(this.getVariable(\"tv-auto-open-on-import\") !== \"no\") {\n\t\tvar storyList = this.getStoryList(),\n\t\t\thistory = [];\n\t\t// Add it to the story\n\t\tif(storyList && storyList.indexOf(IMPORT_TITLE) === -1) {\n\t\t\tstoryList.unshift(IMPORT_TITLE);\n\t\t}\n\t\t// And to history\n\t\thistory.push(IMPORT_TITLE);\n\t\t// Save the updated story and history\n\t\tthis.saveStoryList(storyList);\n\t\tthis.addToHistory(history);\n\t}\n\treturn false;\n};\n\n//\nNavigatorWidget.prototype.handlePerformImportEvent = function(event) {\n\tvar self = this,\n\t\timportTiddler = this.wiki.getTiddler(event.param),\n\t\timportData = this.wiki.getTiddlerDataCached(event.param,{tiddlers: {}}),\n\t\timportReport = [];\n\t// Add the tiddlers to the store\n\timportReport.push($tw.language.getString(\"Import/Imported/Hint\") + \"\\n\");\n\t$tw.utils.each(importData.tiddlers,function(tiddlerFields) {\n\t\tvar title = tiddlerFields.title;\n\t\tif(title && importTiddler && importTiddler.fields[\"selection-\" + title] !== \"unchecked\") {\n\t\t\tvar tiddler = new $tw.Tiddler(tiddlerFields);\n\t\t\ttiddler = $tw.hooks.invokeHook(\"th-importing-tiddler\",tiddler);\n\t\t\tself.wiki.addTiddler(tiddler);\n\t\t\timportReport.push(\"# [[\" + tiddlerFields.title + \"]]\");\n\t\t}\n\t});\n\t// Replace the $:/Import tiddler with an import report\n\tthis.wiki.addTiddler(new $tw.Tiddler({\n\t\ttitle: event.param,\n\t\ttext: importReport.join(\"\\n\"),\n\t\t\"status\": \"complete\"\n\t}));\n\t// Navigate to the $:/Import tiddler\n\tthis.addToHistory([event.param]);\n\t// Trigger an autosave\n\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n};\n\nNavigatorWidget.prototype.handleFoldTiddlerEvent = function(event) {\n\tvar paramObject = event.paramObject || {};\n\tif(paramObject.foldedState) {\n\t\tvar foldedState = this.wiki.getTiddlerText(paramObject.foldedState,\"show\") === \"show\" ? \"hide\" : \"show\";\n\t\tthis.wiki.setText(paramObject.foldedState,\"text\",null,foldedState);\n\t}\n};\n\nNavigatorWidget.prototype.handleFoldOtherTiddlersEvent = function(event) {\n\tvar self = this,\n\t\tparamObject = event.paramObject || {},\n\t\tprefix = paramObject.foldedStatePrefix;\n\t$tw.utils.each(this.getStoryList(),function(title) {\n\t\tself.wiki.setText(prefix + title,\"text\",null,event.param === title ? \"show\" : \"hide\");\n\t});\n};\n\nNavigatorWidget.prototype.handleFoldAllTiddlersEvent = function(event) {\n\tvar self = this,\n\t\tparamObject = event.paramObject || {},\n\t\tprefix = paramObject.foldedStatePrefix || \"$:/state/folded/\";\n\t$tw.utils.each(this.getStoryList(),function(title) {\n\t\tself.wiki.setText(prefix + title,\"text\",null,\"hide\");\n\t});\n};\n\nNavigatorWidget.prototype.handleUnfoldAllTiddlersEvent = function(event) {\n\tvar self = this,\n\t\tparamObject = event.paramObject || {},\n\t\tprefix = paramObject.foldedStatePrefix;\n\t$tw.utils.each(this.getStoryList(),function(title) {\n\t\tself.wiki.setText(prefix + title,\"text\",null,\"show\");\n\t});\n};\n\nNavigatorWidget.prototype.handleRenameTiddlerEvent = function(event) {\n\tvar paramObject = event.paramObject || {},\n\t\tfrom = paramObject.from || event.tiddlerTitle,\n\t\tto = paramObject.to;\n\tthis.wiki.renameTiddler(from,to);\n};\n\nexports.navigator = NavigatorWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/password.js": {
            "title": "$:/core/modules/widgets/password.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/password.js\ntype: application/javascript\nmodule-type: widget\n\nPassword widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar PasswordWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nPasswordWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nPasswordWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Get the current password\n\tvar password = $tw.browser ? $tw.utils.getPassword(this.passwordName) || \"\" : \"\";\n\t// Create our element\n\tvar domNode = this.document.createElement(\"input\");\n\tdomNode.setAttribute(\"type\",\"password\");\n\tdomNode.setAttribute(\"value\",password);\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(domNode,[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n\t// Insert the label into the DOM and render any children\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\nPasswordWidget.prototype.handleChangeEvent = function(event) {\n\tvar password = this.domNodes[0].value;\n\treturn $tw.utils.savePassword(this.passwordName,password);\n};\n\n/*\nCompute the internal state of the widget\n*/\nPasswordWidget.prototype.execute = function() {\n\t// Get the parameters from the attributes\n\tthis.passwordName = this.getAttribute(\"name\",\"\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nPasswordWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.name) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.password = PasswordWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/qualify.js": {
            "title": "$:/core/modules/widgets/qualify.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/qualify.js\ntype: application/javascript\nmodule-type: widget\n\nQualify text to a variable \n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar QualifyWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nQualifyWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nQualifyWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nQualifyWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.qualifyName = this.getAttribute(\"name\");\n\tthis.qualifyTitle = this.getAttribute(\"title\");\n\t// Set context variable\n\tif(this.qualifyName) {\n\t\tthis.setVariable(this.qualifyName,this.qualifyTitle + \"-\" + this.getStateQualifier());\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nQualifyWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.name || changedAttributes.title) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.qualify = QualifyWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/radio.js": {
            "title": "$:/core/modules/widgets/radio.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/radio.js\ntype: application/javascript\nmodule-type: widget\n\nSet a field or index at a given tiddler via radio buttons\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar RadioWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nRadioWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nRadioWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\tvar isChecked = this.getValue() === this.radioValue;\n\t// Create our elements\n\tthis.labelDomNode = this.document.createElement(\"label\");\n\tthis.labelDomNode.setAttribute(\"class\",\n   \t\t\"tc-radio \" + this.radioClass + (isChecked ? \" tc-radio-selected\" : \"\")\n  \t);\n\tthis.inputDomNode = this.document.createElement(\"input\");\n\tthis.inputDomNode.setAttribute(\"type\",\"radio\");\n\tif(isChecked) {\n\t\tthis.inputDomNode.setAttribute(\"checked\",\"true\");\n\t}\n\tthis.labelDomNode.appendChild(this.inputDomNode);\n\tthis.spanDomNode = this.document.createElement(\"span\");\n\tthis.labelDomNode.appendChild(this.spanDomNode);\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(this.inputDomNode,[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n\t// Insert the label into the DOM and render any children\n\tparent.insertBefore(this.labelDomNode,nextSibling);\n\tthis.renderChildren(this.spanDomNode,null);\n\tthis.domNodes.push(this.labelDomNode);\n};\n\nRadioWidget.prototype.getValue = function() {\n\tvar value,\n\t\ttiddler = this.wiki.getTiddler(this.radioTitle);\n\tif (this.radioIndex) {\n\t\tvalue = this.wiki.extractTiddlerDataItem(this.radioTitle,this.radioIndex);\n\t} else {\n\t\tvalue = tiddler && tiddler.getFieldString(this.radioField);\n\t}\n\treturn value;\n};\n\nRadioWidget.prototype.setValue = function() {\n\tif(this.radioIndex) {\n\t\tthis.wiki.setText(this.radioTitle,\"\",this.radioIndex,this.radioValue);\n\t} else {\n\t\tvar tiddler = this.wiki.getTiddler(this.radioTitle),\n\t\t\taddition = {};\n\t\taddition[this.radioField] = this.radioValue;\n\t\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),{title: this.radioTitle},tiddler,addition,this.wiki.getModificationFields()));\n\t}\n};\n\nRadioWidget.prototype.handleChangeEvent = function(event) {\n\tif(this.inputDomNode.checked) {\n\t\tthis.setValue();\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nRadioWidget.prototype.execute = function() {\n\t// Get the parameters from the attributes\n\tthis.radioTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.radioField = this.getAttribute(\"field\",\"text\");\n\tthis.radioIndex = this.getAttribute(\"index\");\n\tthis.radioValue = this.getAttribute(\"value\");\n\tthis.radioClass = this.getAttribute(\"class\",\"\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nRadioWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.value || changedAttributes[\"class\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\tvar refreshed = false;\n\t\tif(changedTiddlers[this.radioTitle]) {\n\t\t\tthis.inputDomNode.checked = this.getValue() === this.radioValue;\n\t\t\trefreshed = true;\n\t\t}\n\t\treturn this.refreshChildren(changedTiddlers) || refreshed;\n\t}\n};\n\nexports.radio = RadioWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/range.js": {
            "title": "$:/core/modules/widgets/range.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/range.js\ntype: application/javascript\nmodule-type: widget\n\nRange widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar RangeWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nRangeWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nRangeWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Create our elements\n\tthis.inputDomNode = this.document.createElement(\"input\");\n\tthis.inputDomNode.setAttribute(\"type\",\"range\");\n\tthis.inputDomNode.setAttribute(\"class\",this.elementClass);\n\tif(this.minValue){\n\t\tthis.inputDomNode.setAttribute(\"min\", this.minValue);\n\t}\n\tif(this.maxValue){\n\t\tthis.inputDomNode.setAttribute(\"max\", this.maxValue);\n\t}\n\tif(this.increment){\n\t\tthis.inputDomNode.setAttribute(\"step\", this.increment);\n\t}\n\tthis.inputDomNode.value = this.getValue();\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(this.inputDomNode,[\n\t\t{name: \"input\", handlerObject: this, handlerMethod: \"handleInputEvent\"},\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleInputEvent\"}\t\t\n\t]);\n\t// Insert the label into the DOM and render any children\n\tparent.insertBefore(this.inputDomNode,nextSibling);\n\tthis.domNodes.push(this.inputDomNode);\n};\n\nRangeWidget.prototype.getValue = function() {\n\tvar tiddler = this.wiki.getTiddler(this.tiddlerTitle),\n\t\tfieldName = this.tiddlerField || \"text\",\n\t\tvalue   = this.defaultValue;\n\tif(tiddler) {\n\t\tif(this.tiddlerIndex) {\n\t\t\tvalue = this.wiki.extractTiddlerDataItem(tiddler,this.tiddlerIndex,this.defaultValue || \"\");\n\t\t} else {\n\t\t\tif($tw.utils.hop(tiddler.fields,fieldName)) {\n\t\t\t\tvalue = tiddler.fields[fieldName] || \"\";\n\t\t\t} else {\n\t\t\t\tvalue = this.defaultValue || \"\";\n\t\t\t}\n\t\t}\n\t}\n\treturn value;\n};\n\nRangeWidget.prototype.handleInputEvent = function(event) {\n\tif(this.getValue() !== this.inputDomNode.value) {\n\t\tif(this.tiddlerIndex) {\n\t\t\tthis.wiki.setText(this.tiddlerTitle,\"\",this.tiddlerIndex,this.inputDomNode.value);\n\t\t} else {\n\t\t\tthis.wiki.setText(this.tiddlerTitle,this.tiddlerField,null,this.inputDomNode.value);\n\t\t}\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nRangeWidget.prototype.execute = function() {\n\t// Get the parameters from the attributes\n\tthis.tiddlerTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.tiddlerField = this.getAttribute(\"field\");\n\tthis.tiddlerIndex = this.getAttribute(\"index\");\n\tthis.minValue = this.getAttribute(\"min\");\n\tthis.maxValue = this.getAttribute(\"max\");\n\tthis.increment = this.getAttribute(\"increment\");\n\tthis.defaultValue = this.getAttribute(\"default\");\n\tthis.elementClass = this.getAttribute(\"class\",\"\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nRangeWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes['min'] || changedAttributes['max'] || changedAttributes['increment'] || changedAttributes[\"default\"] || changedAttributes[\"class\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\tvar refreshed = false;\n\t\tif(changedTiddlers[this.tiddlerTitle]) {\n\t\t\tvar value = this.getValue();\n\t\t\tif(this.inputDomNode.value !== value) {\n\t\t\t\tthis.inputDomNode.value = value;\t\t\t\t\n\t\t\t}\n\t\t\trefreshed = true;\n\t\t}\n\t\treturn this.refreshChildren(changedTiddlers) || refreshed;\n\t}\n};\n\nexports.range = RangeWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/raw.js": {
            "title": "$:/core/modules/widgets/raw.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/raw.js\ntype: application/javascript\nmodule-type: widget\n\nRaw widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar RawWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nRawWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nRawWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.execute();\n\tvar div = this.document.createElement(\"div\");\n\tdiv.innerHTML=this.parseTreeNode.html;\n\tparent.insertBefore(div,nextSibling);\n\tthis.domNodes.push(div);\t\n};\n\n/*\nCompute the internal state of the widget\n*/\nRawWidget.prototype.execute = function() {\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nRawWidget.prototype.refresh = function(changedTiddlers) {\n\treturn false;\n};\n\nexports.raw = RawWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/reveal.js": {
            "title": "$:/core/modules/widgets/reveal.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/reveal.js\ntype: application/javascript\nmodule-type: widget\n\nReveal widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar RevealWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nRevealWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nRevealWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar tag = this.parseTreeNode.isBlock ? \"div\" : \"span\";\n\tif(this.revealTag && $tw.config.htmlUnsafeElements.indexOf(this.revealTag) === -1) {\n\t\ttag = this.revealTag;\n\t}\n\tvar domNode = this.document.createElement(tag);\n\tvar classes = this[\"class\"].split(\" \") || [];\n\tclasses.push(\"tc-reveal\");\n\tdomNode.className = classes.join(\" \");\n\tif(this.style) {\n\t\tdomNode.setAttribute(\"style\",this.style);\n\t}\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tif(!domNode.isTiddlyWikiFakeDom && this.type === \"popup\" && this.isOpen) {\n\t\tthis.positionPopup(domNode);\n\t\t$tw.utils.addClass(domNode,\"tc-popup\"); // Make sure that clicks don't dismiss popups within the revealed content\n\t}\n\tif(!this.isOpen) {\n\t\tdomNode.setAttribute(\"hidden\",\"true\");\n\t}\n\tthis.domNodes.push(domNode);\n};\n\nRevealWidget.prototype.positionPopup = function(domNode) {\n\tdomNode.style.position = \"absolute\";\n\tdomNode.style.zIndex = \"1000\";\n\tvar left,top;\n\tswitch(this.position) {\n\t\tcase \"left\":\n\t\t\tleft = this.popup.left - domNode.offsetWidth;\n\t\t\ttop = this.popup.top;\n\t\t\tbreak;\n\t\tcase \"above\":\n\t\t\tleft = this.popup.left;\n\t\t\ttop = this.popup.top - domNode.offsetHeight;\n\t\t\tbreak;\n\t\tcase \"aboveright\":\n\t\t\tleft = this.popup.left + this.popup.width;\n\t\t\ttop = this.popup.top + this.popup.height - domNode.offsetHeight;\n\t\t\tbreak;\n\t\tcase \"right\":\n\t\t\tleft = this.popup.left + this.popup.width;\n\t\t\ttop = this.popup.top;\n\t\t\tbreak;\n\t\tcase \"belowleft\":\n\t\t\tleft = this.popup.left + this.popup.width - domNode.offsetWidth;\n\t\t\ttop = this.popup.top + this.popup.height;\n\t\t\tbreak;\n\t\tdefault: // Below\n\t\t\tleft = this.popup.left;\n\t\t\ttop = this.popup.top + this.popup.height;\n\t\t\tbreak;\n\t}\n\tif(!this.positionAllowNegative) {\n\t\tleft = Math.max(0,left);\n\t\ttop = Math.max(0,top);\n\t}\n\tdomNode.style.left = left + \"px\";\n\tdomNode.style.top = top + \"px\";\n};\n\n/*\nCompute the internal state of the widget\n*/\nRevealWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.state = this.getAttribute(\"state\");\n\tthis.revealTag = this.getAttribute(\"tag\");\n\tthis.type = this.getAttribute(\"type\");\n\tthis.text = this.getAttribute(\"text\");\n\tthis.position = this.getAttribute(\"position\");\n\tthis.positionAllowNegative = this.getAttribute(\"positionAllowNegative\") === \"yes\";\n\tthis[\"class\"] = this.getAttribute(\"class\",\"\");\n\tthis.style = this.getAttribute(\"style\",\"\");\n\tthis[\"default\"] = this.getAttribute(\"default\",\"\");\n\tthis.animate = this.getAttribute(\"animate\",\"no\");\n\tthis.retain = this.getAttribute(\"retain\",\"no\");\n\tthis.openAnimation = this.animate === \"no\" ? undefined : \"open\";\n\tthis.closeAnimation = this.animate === \"no\" ? undefined : \"close\";\n\t// Compute the title of the state tiddler and read it\n\tthis.stateTiddlerTitle = this.state;\n\tthis.stateTitle = this.getAttribute(\"stateTitle\");\n\tthis.stateField = this.getAttribute(\"stateField\");\n\tthis.stateIndex = this.getAttribute(\"stateIndex\");\n\tthis.readState();\n\t// Construct the child widgets\n\tvar childNodes = this.isOpen ? this.parseTreeNode.children : [];\n\tthis.hasChildNodes = this.isOpen;\n\tthis.makeChildWidgets(childNodes);\n};\n\n/*\nRead the state tiddler\n*/\nRevealWidget.prototype.readState = function() {\n\t// Read the information from the state tiddler\n\tvar state,\n\t    defaultState = this[\"default\"];\n\tif(this.stateTitle) {\n\t\tvar stateTitleTiddler = this.wiki.getTiddler(this.stateTitle);\n\t\tif(this.stateField) {\n\t\t\tstate = stateTitleTiddler ? stateTitleTiddler.getFieldString(this.stateField) || defaultState : defaultState;\n\t\t} else if(this.stateIndex) {\n\t\t\tstate = stateTitleTiddler ? this.wiki.extractTiddlerDataItem(this.stateTitle,this.stateIndex) || defaultState : defaultState;\n\t\t} else if(stateTitleTiddler) {\n\t\t\tstate = this.wiki.getTiddlerText(this.stateTitle) || defaultState;\n\t\t} else {\n\t\t\tstate = defaultState;\n\t\t}\n\t} else {\n\t\tstate = this.stateTiddlerTitle ? this.wiki.getTextReference(this.state,this[\"default\"],this.getVariable(\"currentTiddler\")) : this[\"default\"];\n\t}\n\tif(state === null) {\n\t\tstate = this[\"default\"];\n\t}\n\tswitch(this.type) {\n\t\tcase \"popup\":\n\t\t\tthis.readPopupState(state);\n\t\t\tbreak;\n\t\tcase \"match\":\n\t\t\tthis.isOpen = this.text === state;\n\t\t\tbreak;\n\t\tcase \"nomatch\":\n\t\t\tthis.isOpen = this.text !== state;\n\t\t\tbreak;\n\t\tcase \"lt\":\n\t\t\tthis.isOpen = !!(this.compareStateText(state) < 0);\n\t\t\tbreak;\n\t\tcase \"gt\":\n\t\t\tthis.isOpen = !!(this.compareStateText(state) > 0);\n\t\t\tbreak;\n\t\tcase \"lteq\":\n\t\t\tthis.isOpen = !(this.compareStateText(state) > 0);\n\t\t\tbreak;\n\t\tcase \"gteq\":\n\t\t\tthis.isOpen = !(this.compareStateText(state) < 0);\n\t\t\tbreak;\n\t}\n};\n\nRevealWidget.prototype.compareStateText = function(state) {\n\treturn state.localeCompare(this.text,undefined,{numeric: true,sensitivity: \"case\"});\n};\n\nRevealWidget.prototype.readPopupState = function(state) {\n\tvar popupLocationRegExp = /^\\((-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+)\\)$/,\n\t\tmatch = popupLocationRegExp.exec(state);\n\t// Check if the state matches the location regexp\n\tif(match) {\n\t\t// If so, we're open\n\t\tthis.isOpen = true;\n\t\t// Get the location\n\t\tthis.popup = {\n\t\t\tleft: parseFloat(match[1]),\n\t\t\ttop: parseFloat(match[2]),\n\t\t\twidth: parseFloat(match[3]),\n\t\t\theight: parseFloat(match[4])\n\t\t};\n\t} else {\n\t\t// If not, we're closed\n\t\tthis.isOpen = false;\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nRevealWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.state || changedAttributes.type || changedAttributes.text || changedAttributes.position || changedAttributes.positionAllowNegative || changedAttributes[\"default\"] || changedAttributes.animate || changedAttributes.stateTitle || changedAttributes.stateField || changedAttributes.stateIndex) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\tvar currentlyOpen = this.isOpen;\n\t\tthis.readState();\n\t\tif(this.isOpen !== currentlyOpen) {\n\t\t\tif(this.retain === \"yes\") {\n\t\t\t\tthis.updateState();\n\t\t\t} else {\n\t\t\t\tthis.refreshSelf();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\n/*\nCalled by refresh() to dynamically show or hide the content\n*/\nRevealWidget.prototype.updateState = function() {\n\tvar self = this;\n\t// Read the current state\n\tthis.readState();\n\t// Construct the child nodes if needed\n\tvar domNode = this.domNodes[0];\n\tif(this.isOpen && !this.hasChildNodes) {\n\t\tthis.hasChildNodes = true;\n\t\tthis.makeChildWidgets(this.parseTreeNode.children);\n\t\tthis.renderChildren(domNode,null);\n\t}\n\t// Animate our DOM node\n\tif(!domNode.isTiddlyWikiFakeDom && this.type === \"popup\" && this.isOpen) {\n\t\tthis.positionPopup(domNode);\n\t\t$tw.utils.addClass(domNode,\"tc-popup\"); // Make sure that clicks don't dismiss popups within the revealed content\n\n\t}\n\tif(this.isOpen) {\n\t\tdomNode.removeAttribute(\"hidden\");\n        $tw.anim.perform(this.openAnimation,domNode);\n\t} else {\n\t\t$tw.anim.perform(this.closeAnimation,domNode,{callback: function() {\n\t\t\t//make sure that the state hasn't changed during the close animation\n\t\t\tself.readState()\n\t\t\tif(!self.isOpen) {\n\t\t\t\tdomNode.setAttribute(\"hidden\",\"true\");\n\t\t\t}\n\t\t}});\n\t}\n};\n\nexports.reveal = RevealWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/scrollable.js": {
            "title": "$:/core/modules/widgets/scrollable.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/scrollable.js\ntype: application/javascript\nmodule-type: widget\n\nScrollable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ScrollableWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.scaleFactor = 1;\n\tthis.addEventListeners([\n\t\t{type: \"tm-scroll\", handler: \"handleScrollEvent\"}\n\t]);\n\tif($tw.browser) {\n\t\tthis.requestAnimationFrame = window.requestAnimationFrame ||\n\t\t\twindow.webkitRequestAnimationFrame ||\n\t\t\twindow.mozRequestAnimationFrame ||\n\t\t\tfunction(callback) {\n\t\t\t\treturn window.setTimeout(callback, 1000/60);\n\t\t\t};\n\t\tthis.cancelAnimationFrame = window.cancelAnimationFrame ||\n\t\t\twindow.webkitCancelAnimationFrame ||\n\t\t\twindow.webkitCancelRequestAnimationFrame ||\n\t\t\twindow.mozCancelAnimationFrame ||\n\t\t\twindow.mozCancelRequestAnimationFrame ||\n\t\t\tfunction(id) {\n\t\t\t\twindow.clearTimeout(id);\n\t\t\t};\n\t}\n};\n\n/*\nInherit from the base widget class\n*/\nScrollableWidget.prototype = new Widget();\n\nScrollableWidget.prototype.cancelScroll = function() {\n\tif(this.idRequestFrame) {\n\t\tthis.cancelAnimationFrame.call(window,this.idRequestFrame);\n\t\tthis.idRequestFrame = null;\n\t}\n};\n\n/*\nHandle a scroll event\n*/\nScrollableWidget.prototype.handleScrollEvent = function(event) {\n\t// Pass the scroll event through if our offsetsize is larger than our scrollsize\n\tif(this.outerDomNode.scrollWidth <= this.outerDomNode.offsetWidth && this.outerDomNode.scrollHeight <= this.outerDomNode.offsetHeight && this.fallthrough === \"yes\") {\n\t\treturn true;\n\t}\n\tthis.scrollIntoView(event.target);\n\treturn false; // Handled event\n};\n\n/*\nScroll an element into view\n*/\nScrollableWidget.prototype.scrollIntoView = function(element) {\n\tvar duration = $tw.utils.getAnimationDuration();\n\tthis.cancelScroll();\n\tthis.startTime = Date.now();\n\tvar scrollPosition = {\n\t\tx: this.outerDomNode.scrollLeft,\n\t\ty: this.outerDomNode.scrollTop\n\t};\n\t// Get the client bounds of the element and adjust by the scroll position\n\tvar scrollableBounds = this.outerDomNode.getBoundingClientRect(),\n\t\tclientTargetBounds = element.getBoundingClientRect(),\n\t\tbounds = {\n\t\t\tleft: clientTargetBounds.left + scrollPosition.x - scrollableBounds.left,\n\t\t\ttop: clientTargetBounds.top + scrollPosition.y - scrollableBounds.top,\n\t\t\twidth: clientTargetBounds.width,\n\t\t\theight: clientTargetBounds.height\n\t\t};\n\t// We'll consider the horizontal and vertical scroll directions separately via this function\n\tvar getEndPos = function(targetPos,targetSize,currentPos,currentSize) {\n\t\t\t// If the target is already visible then stay where we are\n\t\t\tif(targetPos >= currentPos && (targetPos + targetSize) <= (currentPos + currentSize)) {\n\t\t\t\treturn currentPos;\n\t\t\t// If the target is above/left of the current view, then scroll to its top/left\n\t\t\t} else if(targetPos <= currentPos) {\n\t\t\t\treturn targetPos;\n\t\t\t// If the target is smaller than the window and the scroll position is too far up, then scroll till the target is at the bottom of the window\n\t\t\t} else if(targetSize < currentSize && currentPos < (targetPos + targetSize - currentSize)) {\n\t\t\t\treturn targetPos + targetSize - currentSize;\n\t\t\t// If the target is big, then just scroll to the top\n\t\t\t} else if(currentPos < targetPos) {\n\t\t\t\treturn targetPos;\n\t\t\t// Otherwise, stay where we are\n\t\t\t} else {\n\t\t\t\treturn currentPos;\n\t\t\t}\n\t\t},\n\t\tendX = getEndPos(bounds.left,bounds.width,scrollPosition.x,this.outerDomNode.offsetWidth),\n\t\tendY = getEndPos(bounds.top,bounds.height,scrollPosition.y,this.outerDomNode.offsetHeight);\n\t// Only scroll if necessary\n\tif(endX !== scrollPosition.x || endY !== scrollPosition.y) {\n\t\tvar self = this,\n\t\t\tdrawFrame;\n\t\tdrawFrame = function () {\n\t\t\tvar t;\n\t\t\tif(duration <= 0) {\n\t\t\t\tt = 1;\n\t\t\t} else {\n\t\t\t\tt = ((Date.now()) - self.startTime) / duration;\t\n\t\t\t}\n\t\t\tif(t >= 1) {\n\t\t\t\tself.cancelScroll();\n\t\t\t\tt = 1;\n\t\t\t}\n\t\t\tt = $tw.utils.slowInSlowOut(t);\n\t\t\tself.outerDomNode.scrollLeft = scrollPosition.x + (endX - scrollPosition.x) * t;\n\t\t\tself.outerDomNode.scrollTop = scrollPosition.y + (endY - scrollPosition.y) * t;\n\t\t\tif(t < 1) {\n\t\t\t\tself.idRequestFrame = self.requestAnimationFrame.call(window,drawFrame);\n\t\t\t}\n\t\t};\n\t\tdrawFrame();\n\t}\n};\n\n/*\nRender this widget into the DOM\n*/\nScrollableWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create elements\n\tthis.outerDomNode = this.document.createElement(\"div\");\n\t$tw.utils.setStyle(this.outerDomNode,[\n\t\t{overflowY: \"auto\"},\n\t\t{overflowX: \"auto\"},\n\t\t{webkitOverflowScrolling: \"touch\"}\n\t]);\n\tthis.innerDomNode = this.document.createElement(\"div\");\n\tthis.outerDomNode.appendChild(this.innerDomNode);\n\t// Assign classes\n\tthis.outerDomNode.className = this[\"class\"] || \"\";\n\t// Insert element\n\tparent.insertBefore(this.outerDomNode,nextSibling);\n\tthis.renderChildren(this.innerDomNode,null);\n\tthis.domNodes.push(this.outerDomNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nScrollableWidget.prototype.execute = function() {\n\t// Get attributes\n\tthis.fallthrough = this.getAttribute(\"fallthrough\",\"yes\");\n\tthis[\"class\"] = this.getAttribute(\"class\");\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nScrollableWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"class\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.scrollable = ScrollableWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/select.js": {
            "title": "$:/core/modules/widgets/select.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/select.js\ntype: application/javascript\nmodule-type: widget\n\nSelect widget:\n\n```\n<$select tiddler=\"MyTiddler\" field=\"text\">\n<$list filter=\"[tag[chapter]]\">\n<option value=<<currentTiddler>>>\n<$view field=\"description\"/>\n</option>\n</$list>\n</$select>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SelectWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSelectWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSelectWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n\tthis.setSelectValue();\n\t$tw.utils.addEventListeners(this.getSelectDomNode(),[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n};\n\n/*\nHandle a change event\n*/\nSelectWidget.prototype.handleChangeEvent = function(event) {\n\t// Get the new value and assign it to the tiddler\n\tif(this.selectMultiple == false) {\n\t\tvar value = this.getSelectDomNode().value;\n\t} else {\n\t\tvar value = this.getSelectValues()\n\t\t\t\tvalue = $tw.utils.stringifyList(value);\n\t}\n\tthis.wiki.setText(this.selectTitle,this.selectField,this.selectIndex,value);\n\t// Trigger actions\n\tif(this.selectActions) {\n\t\tthis.invokeActionString(this.selectActions,this,event);\n\t}\n};\n\n/*\nIf necessary, set the value of the select element to the current value\n*/\nSelectWidget.prototype.setSelectValue = function() {\n\tvar value = this.selectDefault;\n\t// Get the value\n\tif(this.selectIndex) {\n\t\tvalue = this.wiki.extractTiddlerDataItem(this.selectTitle,this.selectIndex,value);\n\t} else {\n\t\tvar tiddler = this.wiki.getTiddler(this.selectTitle);\n\t\tif(tiddler) {\n\t\t\tif(this.selectField === \"text\") {\n\t\t\t\t// Calling getTiddlerText() triggers lazy loading of skinny tiddlers\n\t\t\t\tvalue = this.wiki.getTiddlerText(this.selectTitle);\n\t\t\t} else {\n\t\t\t\tif($tw.utils.hop(tiddler.fields,this.selectField)) {\n\t\t\t\t\tvalue = tiddler.getFieldString(this.selectField);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif(this.selectField === \"title\") {\n\t\t\t\tvalue = this.selectTitle;\n\t\t\t}\n\t\t}\n\t}\n\t// Assign it to the select element if it's different than the current value\n\tif (this.selectMultiple) {\n\t\tvalue = value === undefined ? \"\" : value;\n\t\tvar select = this.getSelectDomNode();\n\t\tvar values = Array.isArray(value) ? value : $tw.utils.parseStringArray(value);\n\t\tfor(var i=0; i < select.children.length; i++){\n\t\t\tselect.children[i].selected = values.indexOf(select.children[i].value) !== -1\n\t\t}\n\t} else {\n\t\tvar domNode = this.getSelectDomNode();\n\t\tif(domNode.value !== value) {\n\t\t\tdomNode.value = value;\n\t\t}\n\t}\n};\n\n/*\nGet the DOM node of the select element\n*/\nSelectWidget.prototype.getSelectDomNode = function() {\n\treturn this.children[0].domNodes[0];\n};\n\n// Return an array of the selected opion values\n// select is an HTML select element\nSelectWidget.prototype.getSelectValues = function() {\n\tvar select, result, options, opt;\n\tselect = this.getSelectDomNode();\n\tresult = [];\n\toptions = select && select.options;\n\tfor (var i=0; i<options.length; i++) {\n\t\topt = options[i];\n\t\tif (opt.selected) {\n\t\t\tresult.push(opt.value || opt.text);\n\t\t}\n\t}\n\treturn result;\n}\n\n/*\nCompute the internal state of the widget\n*/\nSelectWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.selectActions = this.getAttribute(\"actions\");\n\tthis.selectTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.selectField = this.getAttribute(\"field\",\"text\");\n\tthis.selectIndex = this.getAttribute(\"index\");\n\tthis.selectClass = this.getAttribute(\"class\");\n\tthis.selectDefault = this.getAttribute(\"default\");\n\tthis.selectMultiple = this.getAttribute(\"multiple\", false);\n\tthis.selectSize = this.getAttribute(\"size\");\n\tthis.selectTooltip = this.getAttribute(\"tooltip\");\n\t// Make the child widgets\n\tvar selectNode = {\n\t\ttype: \"element\",\n\t\ttag: \"select\",\n\t\tchildren: this.parseTreeNode.children\n\t};\n\tif(this.selectClass) {\n\t\t$tw.utils.addAttributeToParseTreeNode(selectNode,\"class\",this.selectClass);\n\t}\n\tif(this.selectMultiple) {\n\t\t$tw.utils.addAttributeToParseTreeNode(selectNode,\"multiple\",\"multiple\");\n\t}\n\tif(this.selectSize) {\n\t\t$tw.utils.addAttributeToParseTreeNode(selectNode,\"size\",this.selectSize);\n\t}\n\tif(this.selectTooltip) {\n\t\t$tw.utils.addAttributeToParseTreeNode(selectNode,\"title\",this.selectTooltip);\n\t}\n\tthis.makeChildWidgets([selectNode]);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nSelectWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\t// If we're using a different tiddler/field/index then completely refresh ourselves\n\tif(changedAttributes.selectTitle || changedAttributes.selectField || changedAttributes.selectIndex || changedAttributes.selectTooltip) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t// If the target tiddler value has changed, just update setting and refresh the children\n\t} else {\n\t\tvar childrenRefreshed = this.refreshChildren(changedTiddlers);\n\t\tif(changedTiddlers[this.selectTitle] || childrenRefreshed) {\n\t\t\tthis.setSelectValue();\n\t\t} \n\t\treturn childrenRefreshed;\n\t}\n};\n\nexports.select = SelectWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/set.js": {
            "title": "$:/core/modules/widgets/set.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/set.js\ntype: application/javascript\nmodule-type: widget\n\nSet variable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SetWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSetWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSetWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nSetWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.setName = this.getAttribute(\"name\",\"currentTiddler\");\n\tthis.setFilter = this.getAttribute(\"filter\");\n\tthis.setSelect = this.getAttribute(\"select\");\n\tthis.setTiddler = this.getAttribute(\"tiddler\");\n\tthis.setSubTiddler = this.getAttribute(\"subtiddler\");\n\tthis.setField = this.getAttribute(\"field\");\n\tthis.setIndex = this.getAttribute(\"index\");\n\tthis.setValue = this.getAttribute(\"value\");\n\tthis.setEmptyValue = this.getAttribute(\"emptyValue\");\n\t// Set context variable\n\tthis.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,!!this.parseTreeNode.isMacroDefinition);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nGet the value to be assigned\n*/\nSetWidget.prototype.getValue = function() {\n\tvar value = this.setValue;\n\tif(this.setTiddler) {\n\t\tvar tiddler;\n\t\tif(this.setSubTiddler) {\n\t\t\ttiddler = this.wiki.getSubTiddler(this.setTiddler,this.setSubTiddler);\n\t\t} else {\n\t\t\ttiddler = this.wiki.getTiddler(this.setTiddler);\t\t\t\n\t\t}\n\t\tif(!tiddler) {\n\t\t\tvalue = this.setEmptyValue;\n\t\t} else if(this.setField) {\n\t\t\tvalue = tiddler.getFieldString(this.setField) || this.setEmptyValue;\n\t\t} else if(this.setIndex) {\n\t\t\tvalue = this.wiki.extractTiddlerDataItem(this.setTiddler,this.setIndex,this.setEmptyValue);\n\t\t} else {\n\t\t\tvalue = tiddler.fields.text || this.setEmptyValue ;\n\t\t}\n\t} else if(this.setFilter) {\n\t\tvar results = this.wiki.filterTiddlers(this.setFilter,this);\n\t\tif(this.setValue == null) {\n\t\t\tvar select;\n\t\t\tif(this.setSelect) {\n\t\t\t\tselect = parseInt(this.setSelect,10);\n\t\t\t}\n\t\t\tif(select !== undefined) {\n\t\t\t\tvalue = results[select] || \"\";\n\t\t\t} else {\n\t\t\t\tvalue = $tw.utils.stringifyList(results);\t\t\t\n\t\t\t}\n\t\t}\n\t\tif(results.length === 0 && this.setEmptyValue !== undefined) {\n\t\t\tvalue = this.setEmptyValue;\n\t\t}\n\t} else if(!value && this.setEmptyValue) {\n\t\tvalue = this.setEmptyValue;\n\t}\n\treturn value || \"\";\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nSetWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.name || changedAttributes.filter || changedAttributes.select || changedAttributes.tiddler || (this.setTiddler && changedTiddlers[this.setTiddler]) || changedAttributes.field || changedAttributes.index || changedAttributes.value || changedAttributes.emptyValue ||\n\t   (this.setFilter && this.getValue() != this.variables[this.setName].value)) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.setvariable = SetWidget;\nexports.set = SetWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/text.js": {
            "title": "$:/core/modules/widgets/text.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/text.js\ntype: application/javascript\nmodule-type: widget\n\nText node widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar TextNodeWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nTextNodeWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nTextNodeWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar text = this.getAttribute(\"text\",this.parseTreeNode.text || \"\");\n\ttext = text.replace(/\\r/mg,\"\");\n\tvar textNode = this.document.createTextNode(text);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nTextNodeWidget.prototype.execute = function() {\n\t// Nothing to do for a text node\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nTextNodeWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.text) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports.text = TextNodeWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/tiddler.js": {
            "title": "$:/core/modules/widgets/tiddler.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/tiddler.js\ntype: application/javascript\nmodule-type: widget\n\nTiddler widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar TiddlerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nTiddlerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nTiddlerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nTiddlerWidget.prototype.execute = function() {\n\tthis.tiddlerState = this.computeTiddlerState();\n\tthis.setVariable(\"currentTiddler\",this.tiddlerState.currentTiddler);\n\tthis.setVariable(\"missingTiddlerClass\",this.tiddlerState.missingTiddlerClass);\n\tthis.setVariable(\"shadowTiddlerClass\",this.tiddlerState.shadowTiddlerClass);\n\tthis.setVariable(\"systemTiddlerClass\",this.tiddlerState.systemTiddlerClass);\n\tthis.setVariable(\"tiddlerTagClasses\",this.tiddlerState.tiddlerTagClasses);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nCompute the tiddler state flags\n*/\nTiddlerWidget.prototype.computeTiddlerState = function() {\n\t// Get our parameters\n\tthis.tiddlerTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t// Compute the state\n\tvar state = {\n\t\tcurrentTiddler: this.tiddlerTitle || \"\",\n\t\tmissingTiddlerClass: (this.wiki.tiddlerExists(this.tiddlerTitle) || this.wiki.isShadowTiddler(this.tiddlerTitle)) ? \"tc-tiddler-exists\" : \"tc-tiddler-missing\",\n\t\tshadowTiddlerClass: this.wiki.isShadowTiddler(this.tiddlerTitle) ? \"tc-tiddler-shadow\" : \"\",\n\t\tsystemTiddlerClass: this.wiki.isSystemTiddler(this.tiddlerTitle) ? \"tc-tiddler-system\" : \"\",\n\t\ttiddlerTagClasses: this.getTagClasses()\n\t};\n\t// Compute a simple hash to make it easier to detect changes\n\tstate.hash = state.currentTiddler + state.missingTiddlerClass + state.shadowTiddlerClass + state.systemTiddlerClass + state.tiddlerTagClasses;\n\treturn state;\n};\n\n/*\nCreate a string of CSS classes derived from the tags of the current tiddler\n*/\nTiddlerWidget.prototype.getTagClasses = function() {\n\tvar tiddler = this.wiki.getTiddler(this.tiddlerTitle);\n\tif(tiddler) {\n\t\tvar tags = [];\n\t\t$tw.utils.each(tiddler.fields.tags,function(tag) {\n\t\t\ttags.push(\"tc-tagged-\" + encodeURIComponent(tag));\n\t\t});\n\t\treturn tags.join(\" \");\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nTiddlerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes(),\n\t\tnewTiddlerState = this.computeTiddlerState();\n\tif(changedAttributes.tiddler || newTiddlerState.hash !== this.tiddlerState.hash) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nexports.tiddler = TiddlerWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/transclude.js": {
            "title": "$:/core/modules/widgets/transclude.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/transclude.js\ntype: application/javascript\nmodule-type: widget\n\nTransclude widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar TranscludeWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nTranscludeWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nTranscludeWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nTranscludeWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.transcludeTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.transcludeSubTiddler = this.getAttribute(\"subtiddler\");\n\tthis.transcludeField = this.getAttribute(\"field\");\n\tthis.transcludeIndex = this.getAttribute(\"index\");\n\tthis.transcludeMode = this.getAttribute(\"mode\");\n\t// Parse the text reference\n\tvar parseAsInline = !this.parseTreeNode.isBlock;\n\tif(this.transcludeMode === \"inline\") {\n\t\tparseAsInline = true;\n\t} else if(this.transcludeMode === \"block\") {\n\t\tparseAsInline = false;\n\t}\n\tvar parser = this.wiki.parseTextReference(\n\t\t\t\t\t\tthis.transcludeTitle,\n\t\t\t\t\t\tthis.transcludeField,\n\t\t\t\t\t\tthis.transcludeIndex,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tparseAsInline: parseAsInline,\n\t\t\t\t\t\t\tsubTiddler: this.transcludeSubTiddler\n\t\t\t\t\t\t}),\n\t\tparseTreeNodes = parser ? parser.tree : this.parseTreeNode.children;\n\t// Set context variables for recursion detection\n\tvar recursionMarker = this.makeRecursionMarker();\n\tthis.setVariable(\"transclusion\",recursionMarker);\n\t// Check for recursion\n\tif(parser) {\n\t\tif(this.parentWidget && this.parentWidget.hasVariable(\"transclusion\",recursionMarker)) {\n\t\t\tparseTreeNodes = [{type: \"element\", tag: \"span\", attributes: {\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-error\"}\n\t\t\t}, children: [\n\t\t\t\t{type: \"text\", text: $tw.language.getString(\"Error/RecursiveTransclusion\")}\n\t\t\t]}];\n\t\t}\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets(parseTreeNodes);\n};\n\n/*\nCompose a string comprising the title, field and/or index to identify this transclusion for recursion detection\n*/\nTranscludeWidget.prototype.makeRecursionMarker = function() {\n\tvar output = [];\n\toutput.push(\"{\");\n\toutput.push(this.getVariable(\"currentTiddler\",{defaultValue: \"\"}));\n\toutput.push(\"|\");\n\toutput.push(this.transcludeTitle || \"\");\n\toutput.push(\"|\");\n\toutput.push(this.transcludeField || \"\");\n\toutput.push(\"|\");\n\toutput.push(this.transcludeIndex || \"\");\n\toutput.push(\"|\");\n\toutput.push(this.transcludeSubTiddler || \"\");\n\toutput.push(\"}\");\n\treturn output.join(\"\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nTranscludeWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedTiddlers[this.transcludeTitle]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nexports.transclude = TranscludeWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/vars.js": {
            "title": "$:/core/modules/widgets/vars.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/vars.js\ntype: application/javascript\nmodule-type: widget\n\nThis widget allows multiple variables to be set in one go:\n\n```\n\\define helloworld() Hello world!\n<$vars greeting=\"Hi\" me={{!!title}} sentence=<<helloworld>>>\n  <<greeting>>! I am <<me>> and I say: <<sentence>>\n</$vars>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar VarsWidget = function(parseTreeNode,options) {\n\t// Call the constructor\n\tWidget.call(this);\n\t// Initialise\t\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nVarsWidget.prototype = Object.create(Widget.prototype);\n\n/*\nRender this widget into the DOM\n*/\nVarsWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nVarsWidget.prototype.execute = function() {\n\t// Parse variables\n\tvar self = this;\n\t$tw.utils.each(this.attributes,function(val,key) {\n\t\tif(key.charAt(0) !== \"$\") {\n\t\t\tself.setVariable(key,val);\n\t\t}\n\t});\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nVarsWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(Object.keys(changedAttributes).length) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports[\"vars\"] = VarsWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/view.js": {
            "title": "$:/core/modules/widgets/view.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/view.js\ntype: application/javascript\nmodule-type: widget\n\nView widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ViewWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nViewWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nViewWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tif(this.text) {\n\t\tvar textNode = this.document.createTextNode(this.text);\n\t\tparent.insertBefore(textNode,nextSibling);\n\t\tthis.domNodes.push(textNode);\n\t} else {\n\t\tthis.makeChildWidgets();\n\t\tthis.renderChildren(parent,nextSibling);\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nViewWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.viewTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.viewSubtiddler = this.getAttribute(\"subtiddler\");\n\tthis.viewField = this.getAttribute(\"field\",\"text\");\n\tthis.viewIndex = this.getAttribute(\"index\");\n\tthis.viewFormat = this.getAttribute(\"format\",\"text\");\n\tthis.viewTemplate = this.getAttribute(\"template\",\"\");\n\tthis.viewMode = this.getAttribute(\"mode\",\"block\");\n\tswitch(this.viewFormat) {\n\t\tcase \"htmlwikified\":\n\t\t\tthis.text = this.getValueAsHtmlWikified(this.viewMode);\n\t\t\tbreak;\n\t\tcase \"plainwikified\":\n\t\t\tthis.text = this.getValueAsPlainWikified(this.viewMode);\n\t\t\tbreak;\n\t\tcase \"htmlencodedplainwikified\":\n\t\t\tthis.text = this.getValueAsHtmlEncodedPlainWikified(this.viewMode);\n\t\t\tbreak;\n\t\tcase \"htmlencoded\":\n\t\t\tthis.text = this.getValueAsHtmlEncoded();\n\t\t\tbreak;\n\t\tcase \"urlencoded\":\n\t\t\tthis.text = this.getValueAsUrlEncoded();\n\t\t\tbreak;\n\t\tcase \"doubleurlencoded\":\n\t\t\tthis.text = this.getValueAsDoubleUrlEncoded();\n\t\t\tbreak;\n\t\tcase \"date\":\n\t\t\tthis.text = this.getValueAsDate(this.viewTemplate);\n\t\t\tbreak;\n\t\tcase \"relativedate\":\n\t\t\tthis.text = this.getValueAsRelativeDate();\n\t\t\tbreak;\n\t\tcase \"stripcomments\":\n\t\t\tthis.text = this.getValueAsStrippedComments();\n\t\t\tbreak;\n\t\tcase \"jsencoded\":\n\t\t\tthis.text = this.getValueAsJsEncoded();\n\t\t\tbreak;\n\t\tdefault: // \"text\"\n\t\t\tthis.text = this.getValueAsText();\n\t\t\tbreak;\n\t}\n};\n\n/*\nThe various formatter functions are baked into this widget for the moment. Eventually they will be replaced by macro functions\n*/\n\n/*\nRetrieve the value of the widget. Options are:\nasString: Optionally return the value as a string\n*/\nViewWidget.prototype.getValue = function(options) {\n\toptions = options || {};\n\tvar value = options.asString ? \"\" : undefined;\n\tif(this.viewIndex) {\n\t\tvalue = this.wiki.extractTiddlerDataItem(this.viewTitle,this.viewIndex);\n\t} else {\n\t\tvar tiddler;\n\t\tif(this.viewSubtiddler) {\n\t\t\ttiddler = this.wiki.getSubTiddler(this.viewTitle,this.viewSubtiddler);\t\n\t\t} else {\n\t\t\ttiddler = this.wiki.getTiddler(this.viewTitle);\n\t\t}\n\t\tif(tiddler) {\n\t\t\tif(this.viewField === \"text\" && !this.viewSubtiddler) {\n\t\t\t\t// Calling getTiddlerText() triggers lazy loading of skinny tiddlers\n\t\t\t\tvalue = this.wiki.getTiddlerText(this.viewTitle);\n\t\t\t} else {\n\t\t\t\tif($tw.utils.hop(tiddler.fields,this.viewField)) {\n\t\t\t\t\tif(options.asString) {\n\t\t\t\t\t\tvalue = tiddler.getFieldString(this.viewField);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvalue = tiddler.fields[this.viewField];\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif(this.viewField === \"title\") {\n\t\t\t\tvalue = this.viewTitle;\n\t\t\t}\n\t\t}\n\t}\n\treturn value;\n};\n\nViewWidget.prototype.getValueAsText = function() {\n\treturn this.getValue({asString: true});\n};\n\nViewWidget.prototype.getValueAsHtmlWikified = function(mode) {\n\treturn this.wiki.renderText(\"text/html\",\"text/vnd.tiddlywiki\",this.getValueAsText(),{\n\t\tparseAsInline: mode !== \"block\",\n\t\tparentWidget: this\n\t});\n};\n\nViewWidget.prototype.getValueAsPlainWikified = function(mode) {\n\treturn this.wiki.renderText(\"text/plain\",\"text/vnd.tiddlywiki\",this.getValueAsText(),{\n\t\tparseAsInline: mode !== \"block\",\n\t\tparentWidget: this\n\t});\n};\n\nViewWidget.prototype.getValueAsHtmlEncodedPlainWikified = function(mode) {\n\treturn $tw.utils.htmlEncode(this.wiki.renderText(\"text/plain\",\"text/vnd.tiddlywiki\",this.getValueAsText(),{\n\t\tparseAsInline: mode !== \"block\",\n\t\tparentWidget: this\n\t}));\n};\n\nViewWidget.prototype.getValueAsHtmlEncoded = function() {\n\treturn $tw.utils.htmlEncode(this.getValueAsText());\n};\n\nViewWidget.prototype.getValueAsUrlEncoded = function() {\n\treturn encodeURIComponent(this.getValueAsText());\n};\n\nViewWidget.prototype.getValueAsDoubleUrlEncoded = function() {\n\treturn encodeURIComponent(encodeURIComponent(this.getValueAsText()));\n};\n\nViewWidget.prototype.getValueAsDate = function(format) {\n\tformat = format || \"YYYY MM DD 0hh:0mm\";\n\tvar value = $tw.utils.parseDate(this.getValue());\n\tif(value && $tw.utils.isDate(value) && value.toString() !== \"Invalid Date\") {\n\t\treturn $tw.utils.formatDateString(value,format);\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\nViewWidget.prototype.getValueAsRelativeDate = function(format) {\n\tvar value = $tw.utils.parseDate(this.getValue());\n\tif(value && $tw.utils.isDate(value) && value.toString() !== \"Invalid Date\") {\n\t\treturn $tw.utils.getRelativeDate((new Date()) - (new Date(value))).description;\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\nViewWidget.prototype.getValueAsStrippedComments = function() {\n\tvar lines = this.getValueAsText().split(\"\\n\"),\n\t\tout = [];\n\tfor(var line=0; line<lines.length; line++) {\n\t\tvar text = lines[line];\n\t\tif(!/^\\s*\\/\\/#/.test(text)) {\n\t\t\tout.push(text);\n\t\t}\n\t}\n\treturn out.join(\"\\n\");\n};\n\nViewWidget.prototype.getValueAsJsEncoded = function() {\n\treturn $tw.utils.stringify(this.getValueAsText());\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nViewWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.template || changedAttributes.format || changedTiddlers[this.viewTitle]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports.view = ViewWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/widget.js": {
            "title": "$:/core/modules/widgets/widget.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/widget.js\ntype: application/javascript\nmodule-type: widget\n\nWidget base class\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nCreate a widget object for a parse tree node\n\tparseTreeNode: reference to the parse tree node to be rendered\n\toptions: see below\nOptions include:\n\twiki: mandatory reference to wiki associated with this render tree\n\tparentWidget: optional reference to a parent renderer node for the context chain\n\tdocument: optional document object to use instead of global document\n*/\nvar Widget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInitialise widget properties. These steps are pulled out of the constructor so that we can reuse them in subclasses\n*/\nWidget.prototype.initialise = function(parseTreeNode,options) {\n\t// Bail if parseTreeNode is undefined, meaning  that the widget constructor was called without any arguments so that it can be subclassed\n\tif(parseTreeNode === undefined) {\n\t\treturn;\n\t}\n\toptions = options || {};\n\t// Save widget info\n\tthis.parseTreeNode = parseTreeNode;\n\tthis.wiki = options.wiki;\n\tthis.parentWidget = options.parentWidget;\n\tthis.variablesConstructor = function() {};\n\tthis.variablesConstructor.prototype = this.parentWidget ? this.parentWidget.variables : {};\n\tthis.variables = new this.variablesConstructor();\n\tthis.document = options.document;\n\tthis.attributes = {};\n\tthis.children = [];\n\tthis.domNodes = [];\n\tthis.eventListeners = {};\n\t// Hashmap of the widget classes\n\tif(!this.widgetClasses) {\n\t\t// Get widget classes\n\t\tWidget.prototype.widgetClasses = $tw.modules.applyMethods(\"widget\");\n\t\t// Process any subclasses\n\t\t$tw.modules.forEachModuleOfType(\"widget-subclass\",function(title,module) {\n\t\t\tif(module.baseClass) {\n\t\t\t\tvar baseClass = Widget.prototype.widgetClasses[module.baseClass];\n\t\t\t\tif(!baseClass) {\n\t\t\t\t\tthrow \"Module '\" + title + \"' is attemping to extend a non-existent base class '\" + module.baseClass + \"'\";\n\t\t\t\t}\n\t\t\t\tvar subClass = module.constructor;\n\t\t\t\tsubClass.prototype = new baseClass();\n\t\t\t\t$tw.utils.extend(subClass.prototype,module.prototype);\n\t\t\t\tWidget.prototype.widgetClasses[module.name || module.baseClass] = subClass;\n\t\t\t}\n\t\t});\n\t}\n};\n\n/*\nRender this widget into the DOM\n*/\nWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nWidget.prototype.execute = function() {\n\tthis.makeChildWidgets();\n};\n\n/*\nSet the value of a context variable\nname: name of the variable\nvalue: value of the variable\nparams: array of {name:, default:} for each parameter\nisMacroDefinition: true if the variable is set via a \\define macro pragma (and hence should have variable substitution performed)\n*/\nWidget.prototype.setVariable = function(name,value,params,isMacroDefinition) {\n\tthis.variables[name] = {value: value, params: params, isMacroDefinition: !!isMacroDefinition};\n};\n\n/*\nGet the prevailing value of a context variable\nname: name of variable\noptions: see below\nOptions include\nparams: array of {name:, value:} for each parameter\ndefaultValue: default value if the variable is not defined\n\nReturns an object with the following fields:\n\nparams: array of {name:,value:} of parameters passed to wikitext variables\ntext: text of variable, with parameters properly substituted\n*/\nWidget.prototype.getVariableInfo = function(name,options) {\n\toptions = options || {};\n\tvar actualParams = options.params || [],\n\t\tparentWidget = this.parentWidget;\n\t// Check for the variable defined in the parent widget (or an ancestor in the prototype chain)\n\tif(parentWidget && name in parentWidget.variables) {\n\t\tvar variable = parentWidget.variables[name],\n\t\t\tvalue = variable.value,\n\t\t\tparams = this.resolveVariableParameters(variable.params,actualParams);\n\t\t// Substitute any parameters specified in the definition\n\t\t$tw.utils.each(params,function(param) {\n\t\t\tvalue = $tw.utils.replaceString(value,new RegExp(\"\\\\$\" + $tw.utils.escapeRegExp(param.name) + \"\\\\$\",\"mg\"),param.value);\n\t\t});\n\t\t// Only substitute variable references if this variable was defined with the \\define pragma\n\t\tif(variable.isMacroDefinition) {\n\t\t\tvalue = this.substituteVariableReferences(value);\t\t\t\n\t\t}\n\t\treturn {\n\t\t\ttext: value,\n\t\t\tparams: params\n\t\t};\n\t}\n\t// If the variable doesn't exist in the parent widget then look for a macro module\n\treturn {\n\t\ttext: this.evaluateMacroModule(name,actualParams,options.defaultValue)\n\t};\n};\n\n/*\nSimplified version of getVariableInfo() that just returns the text\n*/\nWidget.prototype.getVariable = function(name,options) {\n\treturn this.getVariableInfo(name,options).text;\n};\n\nWidget.prototype.resolveVariableParameters = function(formalParams,actualParams) {\n\tformalParams = formalParams || [];\n\tactualParams = actualParams || [];\n\tvar nextAnonParameter = 0, // Next candidate anonymous parameter in macro call\n\t\tparamInfo, paramValue,\n\t\tresults = [];\n\t// Step through each of the parameters in the macro definition\n\tfor(var p=0; p<formalParams.length; p++) {\n\t\t// Check if we've got a macro call parameter with the same name\n\t\tparamInfo = formalParams[p];\n\t\tparamValue = undefined;\n\t\tfor(var m=0; m<actualParams.length; m++) {\n\t\t\tif(actualParams[m].name === paramInfo.name) {\n\t\t\t\tparamValue = actualParams[m].value;\n\t\t\t}\n\t\t}\n\t\t// If not, use the next available anonymous macro call parameter\n\t\twhile(nextAnonParameter < actualParams.length && actualParams[nextAnonParameter].name) {\n\t\t\tnextAnonParameter++;\n\t\t}\n\t\tif(paramValue === undefined && nextAnonParameter < actualParams.length) {\n\t\t\tparamValue = actualParams[nextAnonParameter++].value;\n\t\t}\n\t\t// If we've still not got a value, use the default, if any\n\t\tparamValue = paramValue || paramInfo[\"default\"] || \"\";\n\t\t// Store the parameter name and value\n\t\tresults.push({name: paramInfo.name, value: paramValue});\n\t}\n\treturn results;\n};\n\nWidget.prototype.substituteVariableReferences = function(text) {\n\tvar self = this;\n\treturn (text || \"\").replace(/\\$\\(([^\\)\\$]+)\\)\\$/g,function(match,p1,offset,string) {\n\t\treturn self.getVariable(p1,{defaultValue: \"\"});\n\t});\n};\n\nWidget.prototype.evaluateMacroModule = function(name,actualParams,defaultValue) {\n\tif($tw.utils.hop($tw.macros,name)) {\n\t\tvar macro = $tw.macros[name],\n\t\t\targs = [];\n\t\tif(macro.params.length > 0) {\n\t\t\tvar nextAnonParameter = 0, // Next candidate anonymous parameter in macro call\n\t\t\t\tparamInfo, paramValue;\n\t\t\t// Step through each of the parameters in the macro definition\n\t\t\tfor(var p=0; p<macro.params.length; p++) {\n\t\t\t\t// Check if we've got a macro call parameter with the same name\n\t\t\t\tparamInfo = macro.params[p];\n\t\t\t\tparamValue = undefined;\n\t\t\t\tfor(var m=0; m<actualParams.length; m++) {\n\t\t\t\t\tif(actualParams[m].name === paramInfo.name) {\n\t\t\t\t\t\tparamValue = actualParams[m].value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// If not, use the next available anonymous macro call parameter\n\t\t\t\twhile(nextAnonParameter < actualParams.length && actualParams[nextAnonParameter].name) {\n\t\t\t\t\tnextAnonParameter++;\n\t\t\t\t}\n\t\t\t\tif(paramValue === undefined && nextAnonParameter < actualParams.length) {\n\t\t\t\t\tparamValue = actualParams[nextAnonParameter++].value;\n\t\t\t\t}\n\t\t\t\t// If we've still not got a value, use the default, if any\n\t\t\t\tparamValue = paramValue || paramInfo[\"default\"] || \"\";\n\t\t\t\t// Save the parameter\n\t\t\t\targs.push(paramValue);\n\t\t\t}\n\t\t}\n\t\telse for(var i=0; i<actualParams.length; ++i) {\n\t\t\targs.push(actualParams[i].value);\n\t\t}\n\t\treturn (macro.run.apply(this,args) || \"\").toString();\n\t} else {\n\t\treturn defaultValue;\n\t}\n};\n\n/*\nCheck whether a given context variable value exists in the parent chain\n*/\nWidget.prototype.hasVariable = function(name,value) {\n\tvar node = this;\n\twhile(node) {\n\t\tif($tw.utils.hop(node.variables,name) && node.variables[name].value === value) {\n\t\t\treturn true;\n\t\t}\n\t\tnode = node.parentWidget;\n\t}\n\treturn false;\n};\n\n/*\nConstruct a qualifying string based on a hash of concatenating the values of a given variable in the parent chain\n*/\nWidget.prototype.getStateQualifier = function(name) {\n\tthis.qualifiers = this.qualifiers || Object.create(null);\n\tname = name || \"transclusion\";\n\tif(this.qualifiers[name]) {\n\t\treturn this.qualifiers[name];\n\t} else {\n\t\tvar output = [],\n\t\t\tnode = this;\n\t\twhile(node && node.parentWidget) {\n\t\t\tif($tw.utils.hop(node.parentWidget.variables,name)) {\n\t\t\t\toutput.push(node.getVariable(name));\n\t\t\t}\n\t\t\tnode = node.parentWidget;\n\t\t}\n\t\tvar value = $tw.utils.hashString(output.join(\"\"));\n\t\tthis.qualifiers[name] = value;\n\t\treturn value;\n\t}\n};\n\n/*\nCompute the current values of the attributes of the widget. Returns a hashmap of the names of the attributes that have changed\n*/\nWidget.prototype.computeAttributes = function() {\n\tvar changedAttributes = {},\n\t\tself = this,\n\t\tvalue;\n\t$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {\n\t\tif(attribute.type === \"filtered\") {\n\t\t\tvalue = self.wiki.filterTiddlers(attribute.filter,self)[0] || \"\";\n\t\t} else if(attribute.type === \"indirect\") {\n\t\t\tvalue = self.wiki.getTextReference(attribute.textReference,\"\",self.getVariable(\"currentTiddler\"));\n\t\t} else if(attribute.type === \"macro\") {\n\t\t\tvalue = self.getVariable(attribute.value.name,{params: attribute.value.params});\n\t\t} else { // String attribute\n\t\t\tvalue = attribute.value;\n\t\t}\n\t\t// Check whether the attribute has changed\n\t\tif(self.attributes[name] !== value) {\n\t\t\tself.attributes[name] = value;\n\t\t\tchangedAttributes[name] = true;\n\t\t}\n\t});\n\treturn changedAttributes;\n};\n\n/*\nCheck for the presence of an attribute\n*/\nWidget.prototype.hasAttribute = function(name) {\n\treturn $tw.utils.hop(this.attributes,name);\n};\n\n/*\nGet the value of an attribute\n*/\nWidget.prototype.getAttribute = function(name,defaultText) {\n\tif($tw.utils.hop(this.attributes,name)) {\n\t\treturn this.attributes[name];\n\t} else {\n\t\treturn defaultText;\n\t}\n};\n\n/*\nAssign the computed attributes of the widget to a domNode\noptions include:\nexcludeEventAttributes: ignores attributes whose name begins with \"on\"\n*/\nWidget.prototype.assignAttributes = function(domNode,options) {\n\toptions = options || {};\n\tvar self = this;\n\t$tw.utils.each(this.attributes,function(v,a) {\n\t\t// Check exclusions\n\t\tif(options.excludeEventAttributes && a.substr(0,2) === \"on\") {\n\t\t\tv = undefined;\n\t\t}\n\t\tif(v !== undefined) {\n\t\t\tvar b = a.split(\":\");\n\t\t\t// Setting certain attributes can cause a DOM error (eg xmlns on the svg element)\n\t\t\ttry {\n\t\t\t\tif (b.length == 2 && b[0] == \"xlink\"){\n\t\t\t\t\tdomNode.setAttributeNS(\"http://www.w3.org/1999/xlink\",b[1],v);\n\t\t\t\t} else {\n\t\t\t\t\tdomNode.setAttributeNS(null,a,v);\n\t\t\t\t}\n\t\t\t} catch(e) {\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\nMake child widgets correspondng to specified parseTreeNodes\n*/\nWidget.prototype.makeChildWidgets = function(parseTreeNodes) {\n\tthis.children = [];\n\tvar self = this;\n\t$tw.utils.each(parseTreeNodes || (this.parseTreeNode && this.parseTreeNode.children),function(childNode) {\n\t\tself.children.push(self.makeChildWidget(childNode));\n\t});\n};\n\n/*\nConstruct the widget object for a parse tree node\n*/\nWidget.prototype.makeChildWidget = function(parseTreeNode) {\n\tvar WidgetClass = this.widgetClasses[parseTreeNode.type];\n\tif(!WidgetClass) {\n\t\tWidgetClass = this.widgetClasses.text;\n\t\tparseTreeNode = {type: \"text\", text: \"Undefined widget '\" + parseTreeNode.type + \"'\"};\n\t}\n\treturn new WidgetClass(parseTreeNode,{\n\t\twiki: this.wiki,\n\t\tvariables: {},\n\t\tparentWidget: this,\n\t\tdocument: this.document\n\t});\n};\n\n/*\nGet the next sibling of this widget\n*/\nWidget.prototype.nextSibling = function() {\n\tif(this.parentWidget) {\n\t\tvar index = this.parentWidget.children.indexOf(this);\n\t\tif(index !== -1 && index < this.parentWidget.children.length-1) {\n\t\t\treturn this.parentWidget.children[index+1];\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nGet the previous sibling of this widget\n*/\nWidget.prototype.previousSibling = function() {\n\tif(this.parentWidget) {\n\t\tvar index = this.parentWidget.children.indexOf(this);\n\t\tif(index !== -1 && index > 0) {\n\t\t\treturn this.parentWidget.children[index-1];\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nRender the children of this widget into the DOM\n*/\nWidget.prototype.renderChildren = function(parent,nextSibling) {\n\tvar children = this.children;\n\tfor(var i = 0; i < children.length; i++) {\n\t\tchildren[i].render(parent,nextSibling);\n\t};\n};\n\n/*\nAdd a list of event listeners from an array [{type:,handler:},...]\n*/\nWidget.prototype.addEventListeners = function(listeners) {\n\tvar self = this;\n\t$tw.utils.each(listeners,function(listenerInfo) {\n\t\tself.addEventListener(listenerInfo.type,listenerInfo.handler);\n\t});\n};\n\n/*\nAdd an event listener\n*/\nWidget.prototype.addEventListener = function(type,handler) {\n\tvar self = this;\n\tif(typeof handler === \"string\") { // The handler is a method name on this widget\n\t\tthis.eventListeners[type] = function(event) {\n\t\t\treturn self[handler].call(self,event);\n\t\t};\n\t} else { // The handler is a function\n\t\tthis.eventListeners[type] = function(event) {\n\t\t\treturn handler.call(self,event);\n\t\t};\n\t}\n};\n\n/*\nDispatch an event to a widget. If the widget doesn't handle the event then it is also dispatched to the parent widget\n*/\nWidget.prototype.dispatchEvent = function(event) {\n\t// Dispatch the event if this widget handles it\n\tvar listener = this.eventListeners[event.type];\n\tif(listener) {\n\t\t// Don't propagate the event if the listener returned false\n\t\tif(!listener(event)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t// Dispatch the event to the parent widget\n\tif(this.parentWidget) {\n\t\treturn this.parentWidget.dispatchEvent(event);\n\t}\n\treturn true;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nRebuild a previously rendered widget\n*/\nWidget.prototype.refreshSelf = function() {\n\tvar nextSibling = this.findNextSiblingDomNode();\n\tthis.removeChildDomNodes();\n\tthis.render(this.parentDomNode,nextSibling);\n};\n\n/*\nRefresh all the children of a widget\n*/\nWidget.prototype.refreshChildren = function(changedTiddlers) {\n\tvar children = this.children,\n\t\trefreshed = false;\n\tfor (var i = 0; i < children.length; i++) {\n\t\trefreshed = children[i].refresh(changedTiddlers) || refreshed;\n\t}\n\treturn refreshed;\n};\n\n/*\nFind the next sibling in the DOM to this widget. This is done by scanning the widget tree through all next siblings and their descendents that share the same parent DOM node\n*/\nWidget.prototype.findNextSiblingDomNode = function(startIndex) {\n\t// Refer to this widget by its index within its parents children\n\tvar parent = this.parentWidget,\n\t\tindex = startIndex !== undefined ? startIndex : parent.children.indexOf(this);\nif(index === -1) {\n\tthrow \"node not found in parents children\";\n}\n\t// Look for a DOM node in the later siblings\n\twhile(++index < parent.children.length) {\n\t\tvar domNode = parent.children[index].findFirstDomNode();\n\t\tif(domNode) {\n\t\t\treturn domNode;\n\t\t}\n\t}\n\t// Go back and look for later siblings of our parent if it has the same parent dom node\n\tvar grandParent = parent.parentWidget;\n\tif(grandParent && parent.parentDomNode === this.parentDomNode) {\n\t\tindex = grandParent.children.indexOf(parent);\n\t\tif(index !== -1) {\n\t\t\treturn parent.findNextSiblingDomNode(index);\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nFind the first DOM node generated by a widget or its children\n*/\nWidget.prototype.findFirstDomNode = function() {\n\t// Return the first dom node of this widget, if we've got one\n\tif(this.domNodes.length > 0) {\n\t\treturn this.domNodes[0];\n\t}\n\t// Otherwise, recursively call our children\n\tfor(var t=0; t<this.children.length; t++) {\n\t\tvar domNode = this.children[t].findFirstDomNode();\n\t\tif(domNode) {\n\t\t\treturn domNode;\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nRemove any DOM nodes created by this widget or its children\n*/\nWidget.prototype.removeChildDomNodes = function() {\n\t// If this widget has directly created DOM nodes, delete them and exit. This assumes that any child widgets are contained within the created DOM nodes, which would normally be the case\n\tif(this.domNodes.length > 0) {\n\t\t$tw.utils.each(this.domNodes,function(domNode) {\n\t\t\tdomNode.parentNode.removeChild(domNode);\n\t\t});\n\t\tthis.domNodes = [];\n\t} else {\n\t\t// Otherwise, ask the child widgets to delete their DOM nodes\n\t\t$tw.utils.each(this.children,function(childWidget) {\n\t\t\tchildWidget.removeChildDomNodes();\n\t\t});\n\t}\n};\n\n/*\nInvoke the action widgets that are descendents of the current widget.\n*/\nWidget.prototype.invokeActions = function(triggeringWidget,event) {\n\tvar handled = false;\n\t// For each child widget\n\tfor(var t=0; t<this.children.length; t++) {\n\t\tvar child = this.children[t];\n\t\t// Invoke the child if it is an action widget\n\t\tif(child.invokeAction) {\n\t\t\tchild.refreshSelf();\n\t\t\tif(child.invokeAction(triggeringWidget,event)) {\n\t\t\t\thandled = true;\n\t\t\t}\n\t\t}\n\t\t// Propagate through through the child if it permits it\n\t\tif(child.allowActionPropagation() && child.invokeActions(triggeringWidget,event)) {\n\t\t\thandled = true;\n\t\t}\n\t}\n\treturn handled;\n};\n\n/*\nInvoke the action widgets defined in a string\n*/\nWidget.prototype.invokeActionString = function(actions,triggeringWidget,event,variables) {\n\tactions = actions || \"\";\n\tvar parser = this.wiki.parseText(\"text/vnd.tiddlywiki\",actions,{\n\t\t\tparentWidget: this,\n\t\t\tdocument: this.document\n\t\t}),\n\t\twidgetNode = this.wiki.makeWidget(parser,{\n\t\t\tparentWidget: this,\n\t\t\tdocument: this.document,\n\t\t\tvariables: variables\n\t\t});\n\tvar container = this.document.createElement(\"div\");\n\twidgetNode.render(container,null);\n\treturn widgetNode.invokeActions(this,event);\n};\n\nWidget.prototype.allowActionPropagation = function() {\n\treturn true;\n};\n\nexports.widget = Widget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/widgets/wikify.js": {
            "title": "$:/core/modules/widgets/wikify.js",
            "text": "/*\\\ntitle: $:/core/modules/widgets/wikify.js\ntype: application/javascript\nmodule-type: widget\n\nWidget to wikify text into a variable\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar WikifyWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nWikifyWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nWikifyWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nWikifyWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.wikifyName = this.getAttribute(\"name\");\n\tthis.wikifyText = this.getAttribute(\"text\");\n\tthis.wikifyType = this.getAttribute(\"type\");\n\tthis.wikifyMode = this.getAttribute(\"mode\",\"block\");\n\tthis.wikifyOutput = this.getAttribute(\"output\",\"text\");\n\t// Create the parse tree\n\tthis.wikifyParser = this.wiki.parseText(this.wikifyType,this.wikifyText,{\n\t\t\tparseAsInline: this.wikifyMode === \"inline\"\n\t\t});\n\t// Create the widget tree \n\tthis.wikifyWidgetNode = this.wiki.makeWidget(this.wikifyParser,{\n\t\t\tdocument: $tw.fakeDocument,\n\t\t\tparentWidget: this\n\t\t});\n\t// Render the widget tree to the container\n\tthis.wikifyContainer = $tw.fakeDocument.createElement(\"div\");\n\tthis.wikifyWidgetNode.render(this.wikifyContainer,null);\n\tthis.wikifyResult = this.getResult();\n\t// Set context variable\n\tthis.setVariable(this.wikifyName,this.wikifyResult);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nReturn the result string\n*/\nWikifyWidget.prototype.getResult = function() {\n\tvar result;\n\tswitch(this.wikifyOutput) {\n\t\tcase \"text\":\n\t\t\tresult = this.wikifyContainer.textContent;\n\t\t\tbreak;\n\t\tcase \"formattedtext\":\n\t\t\tresult = this.wikifyContainer.formattedTextContent;\n\t\t\tbreak;\n\t\tcase \"html\":\n\t\t\tresult = this.wikifyContainer.innerHTML;\n\t\t\tbreak;\n\t\tcase \"parsetree\":\n\t\t\tresult = JSON.stringify(this.wikifyParser.tree,0,$tw.config.preferences.jsonSpaces);\n\t\t\tbreak;\n\t\tcase \"widgettree\":\n\t\t\tresult = JSON.stringify(this.getWidgetTree(),0,$tw.config.preferences.jsonSpaces);\n\t\t\tbreak;\n\t}\n\treturn result;\n};\n\n/*\nReturn a string of the widget tree\n*/\nWikifyWidget.prototype.getWidgetTree = function() {\n\tvar copyNode = function(widgetNode,resultNode) {\n\t\t\tvar type = widgetNode.parseTreeNode.type;\n\t\t\tresultNode.type = type;\n\t\t\tswitch(type) {\n\t\t\t\tcase \"element\":\n\t\t\t\t\tresultNode.tag = widgetNode.parseTreeNode.tag;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"text\":\n\t\t\t\t\tresultNode.text = widgetNode.parseTreeNode.text;\n\t\t\t\t\tbreak;\t\n\t\t\t}\n\t\t\tif(Object.keys(widgetNode.attributes || {}).length > 0) {\n\t\t\t\tresultNode.attributes = {};\n\t\t\t\t$tw.utils.each(widgetNode.attributes,function(attr,attrName) {\n\t\t\t\t\tresultNode.attributes[attrName] = widgetNode.getAttribute(attrName);\n\t\t\t\t});\n\t\t\t}\n\t\t\tif(Object.keys(widgetNode.children || {}).length > 0) {\n\t\t\t\tresultNode.children = [];\n\t\t\t\t$tw.utils.each(widgetNode.children,function(widgetChildNode) {\n\t\t\t\t\tvar node = {};\n\t\t\t\t\tresultNode.children.push(node);\n\t\t\t\t\tcopyNode(widgetChildNode,node);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tresults = {};\n\tcopyNode(this.wikifyWidgetNode,results);\n\treturn results;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nWikifyWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\t// Refresh ourselves entirely if any of our attributes have changed\n\tif(changedAttributes.name || changedAttributes.text || changedAttributes.type || changedAttributes.mode || changedAttributes.output) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\t// Refresh the widget tree\n\t\tif(this.wikifyWidgetNode.refresh(changedTiddlers)) {\n\t\t\t// Check if there was any change\n\t\t\tvar result = this.getResult();\n\t\t\tif(result !== this.wikifyResult) {\n\t\t\t\t// If so, save the change\n\t\t\t\tthis.wikifyResult = result;\n\t\t\t\tthis.setVariable(this.wikifyName,this.wikifyResult);\n\t\t\t\t// Refresh each of our child widgets\n\t\t\t\t$tw.utils.each(this.children,function(childWidget) {\n\t\t\t\t\tchildWidget.refreshSelf();\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t// Just refresh the children\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.wikify = WikifyWidget;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "widget"
        },
        "$:/core/modules/wiki-bulkops.js": {
            "title": "$:/core/modules/wiki-bulkops.js",
            "text": "/*\\\ntitle: $:/core/modules/wiki-bulkops.js\ntype: application/javascript\nmodule-type: wikimethod\n\nBulk tiddler operations such as rename.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nRename a tiddler, and relink any tags or lists that reference it.\n*/\nfunction renameTiddler(fromTitle,toTitle,options) {\n\tfromTitle = (fromTitle || \"\").trim();\n\ttoTitle = (toTitle || \"\").trim();\n\toptions = options || {};\n\tif(fromTitle && toTitle && fromTitle !== toTitle) {\n\t\t// Rename the tiddler itself\n\t\tvar oldTiddler = this.getTiddler(fromTitle),\n\t\t\tnewTiddler = new $tw.Tiddler(oldTiddler,{title: toTitle},this.getModificationFields());\n\t\tnewTiddler = $tw.hooks.invokeHook(\"th-renaming-tiddler\",newTiddler,oldTiddler);\n\t\tthis.addTiddler(newTiddler);\n\t\tthis.deleteTiddler(fromTitle);\n\t\t// Rename any tags or lists that reference it\n\t\tthis.relinkTiddler(fromTitle,toTitle,options)\n\t}\n}\n\n/*\nRelink any tags or lists that reference a given tiddler\n*/\nfunction relinkTiddler(fromTitle,toTitle,options) {\n\tvar self = this;\n\tfromTitle = (fromTitle || \"\").trim();\n\ttoTitle = (toTitle || \"\").trim();\n\toptions = options || {};\n\tif(fromTitle && toTitle && fromTitle !== toTitle) {\n\t\tthis.each(function(tiddler,title) {\n\t\t\tvar type = tiddler.fields.type || \"\";\n\t\t\t// Don't touch plugins or JavaScript modules\n\t\t\tif(!tiddler.fields[\"plugin-type\"] && type !== \"application/javascript\") {\n\t\t\t\tvar tags = tiddler.fields.tags ? tiddler.fields.tags.slice(0) : undefined,\n\t\t\t\t\tlist = tiddler.fields.list ? tiddler.fields.list.slice(0) : undefined,\n\t\t\t\t\tisModified = false;\n\t\t\t\tif(!options.dontRenameInTags) {\n\t\t\t\t\t// Rename tags\n\t\t\t\t\t$tw.utils.each(tags,function (title,index) {\n\t\t\t\t\t\tif(title === fromTitle) {\nconsole.log(\"Renaming tag '\" + tags[index] + \"' to '\" + toTitle + \"' of tiddler '\" + tiddler.fields.title + \"'\");\n\t\t\t\t\t\t\ttags[index] = toTitle;\n\t\t\t\t\t\t\tisModified = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif(!options.dontRenameInLists) {\n\t\t\t\t\t// Rename lists\n\t\t\t\t\t$tw.utils.each(list,function (title,index) {\n\t\t\t\t\t\tif(title === fromTitle) {\nconsole.log(\"Renaming list item '\" + list[index] + \"' to '\" + toTitle + \"' of tiddler '\" + tiddler.fields.title + \"'\");\n\t\t\t\t\t\t\tlist[index] = toTitle;\n\t\t\t\t\t\t\tisModified = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif(isModified) {\n\t\t\t\t\tvar newTiddler = new $tw.Tiddler(tiddler,{tags: tags, list: list},self.getModificationFields())\n\t\t\t\t\tnewTiddler = $tw.hooks.invokeHook(\"th-relinking-tiddler\",newTiddler,tiddler);\n\t\t\t\t\tself.addTiddler(newTiddler);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n};\n\nexports.renameTiddler = renameTiddler;\nexports.relinkTiddler = relinkTiddler;\n\n})();\n",
            "type": "application/javascript",
            "module-type": "wikimethod"
        },
        "$:/core/modules/wiki.js": {
            "title": "$:/core/modules/wiki.js",
            "text": "/*\\\ntitle: $:/core/modules/wiki.js\ntype: application/javascript\nmodule-type: wikimethod\n\nExtension methods for the $tw.Wiki object\n\nAdds the following properties to the wiki object:\n\n* `eventListeners` is a hashmap by type of arrays of listener functions\n* `changedTiddlers` is a hashmap describing changes to named tiddlers since wiki change events were last dispatched. Each entry is a hashmap containing two fields:\n\tmodified: true/false\n\tdeleted: true/false\n* `changeCount` is a hashmap by tiddler title containing a numerical index that starts at zero and is incremented each time a tiddler is created changed or deleted\n* `caches` is a hashmap by tiddler title containing a further hashmap of named cache objects. Caches are automatically cleared when a tiddler is modified or deleted\n* `globalCache` is a hashmap by cache name of cache objects that are cleared whenever any tiddler change occurs\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nvar USER_NAME_TITLE = \"$:/status/UserName\",\n\tTIMESTAMP_DISABLE_TITLE = \"$:/config/TimestampDisable\";\n\n/*\nAdd available indexers to this wiki\n*/\nexports.addIndexersToWiki = function() {\n\tvar self = this;\n\t$tw.utils.each($tw.modules.applyMethods(\"indexer\"),function(Indexer,name) {\n\t\tself.addIndexer(new Indexer(self),name);\n\t});\n};\n\n/*\nGet the value of a text reference. Text references can have any of these forms:\n\t<tiddlertitle>\n\t<tiddlertitle>!!<fieldname>\n\t!!<fieldname> - specifies a field of the current tiddlers\n\t<tiddlertitle>##<index>\n*/\nexports.getTextReference = function(textRef,defaultText,currTiddlerTitle) {\n\tvar tr = $tw.utils.parseTextReference(textRef),\n\t\ttitle = tr.title || currTiddlerTitle;\n\tif(tr.field) {\n\t\tvar tiddler = this.getTiddler(title);\n\t\tif(tr.field === \"title\") { // Special case so we can return the title of a non-existent tiddler\n\t\t\treturn title;\n\t\t} else if(tiddler && $tw.utils.hop(tiddler.fields,tr.field)) {\n\t\t\treturn tiddler.getFieldString(tr.field);\n\t\t} else {\n\t\t\treturn defaultText;\n\t\t}\n\t} else if(tr.index) {\n\t\treturn this.extractTiddlerDataItem(title,tr.index,defaultText);\n\t} else {\n\t\treturn this.getTiddlerText(title,defaultText);\n\t}\n};\n\nexports.setTextReference = function(textRef,value,currTiddlerTitle) {\n\tvar tr = $tw.utils.parseTextReference(textRef),\n\t\ttitle = tr.title || currTiddlerTitle;\n\tthis.setText(title,tr.field,tr.index,value);\n};\n\nexports.setText = function(title,field,index,value,options) {\n\toptions = options || {};\n\tvar creationFields = options.suppressTimestamp ? {} : this.getCreationFields(),\n\t\tmodificationFields = options.suppressTimestamp ? {} : this.getModificationFields();\n\t// Check if it is a reference to a tiddler field\n\tif(index) {\n\t\tvar data = this.getTiddlerData(title,Object.create(null));\n\t\tif(value !== undefined) {\n\t\t\tdata[index] = value;\n\t\t} else {\n\t\t\tdelete data[index];\n\t\t}\n\t\tthis.setTiddlerData(title,data,modificationFields);\n\t} else {\n\t\tvar tiddler = this.getTiddler(title),\n\t\t\tfields = {title: title};\n\t\tfields[field || \"text\"] = value;\n\t\tthis.addTiddler(new $tw.Tiddler(creationFields,tiddler,fields,modificationFields));\n\t}\n};\n\nexports.deleteTextReference = function(textRef,currTiddlerTitle) {\n\tvar tr = $tw.utils.parseTextReference(textRef),\n\t\ttitle,tiddler,fields;\n\t// Check if it is a reference to a tiddler\n\tif(tr.title && !tr.field) {\n\t\tthis.deleteTiddler(tr.title);\n\t// Else check for a field reference\n\t} else if(tr.field) {\n\t\ttitle = tr.title || currTiddlerTitle;\n\t\ttiddler = this.getTiddler(title);\n\t\tif(tiddler && $tw.utils.hop(tiddler.fields,tr.field)) {\n\t\t\tfields = Object.create(null);\n\t\t\tfields[tr.field] = undefined;\n\t\t\tthis.addTiddler(new $tw.Tiddler(tiddler,fields,this.getModificationFields()));\n\t\t}\n\t}\n};\n\nexports.addEventListener = function(type,listener) {\n\tthis.eventListeners = this.eventListeners || {};\n\tthis.eventListeners[type] = this.eventListeners[type]  || [];\n\tthis.eventListeners[type].push(listener);\t\n};\n\nexports.removeEventListener = function(type,listener) {\n\tvar listeners = this.eventListeners[type];\n\tif(listeners) {\n\t\tvar p = listeners.indexOf(listener);\n\t\tif(p !== -1) {\n\t\t\tlisteners.splice(p,1);\n\t\t}\n\t}\n};\n\nexports.dispatchEvent = function(type /*, args */) {\n\tvar args = Array.prototype.slice.call(arguments,1),\n\t\tlisteners = this.eventListeners[type];\n\tif(listeners) {\n\t\tfor(var p=0; p<listeners.length; p++) {\n\t\t\tvar listener = listeners[p];\n\t\t\tlistener.apply(listener,args);\n\t\t}\n\t}\n};\n\n/*\nCauses a tiddler to be marked as changed, incrementing the change count, and triggers event handlers.\nThis method should be called after the changes it describes have been made to the wiki.tiddlers[] array.\n\ttitle: Title of tiddler\n\tisDeleted: defaults to false (meaning the tiddler has been created or modified),\n\t\ttrue if the tiddler has been deleted\n*/\nexports.enqueueTiddlerEvent = function(title,isDeleted) {\n\t// Record the touch in the list of changed tiddlers\n\tthis.changedTiddlers = this.changedTiddlers || Object.create(null);\n\tthis.changedTiddlers[title] = this.changedTiddlers[title] || Object.create(null);\n\tthis.changedTiddlers[title][isDeleted ? \"deleted\" : \"modified\"] = true;\n\t// Increment the change count\n\tthis.changeCount = this.changeCount || Object.create(null);\n\tif($tw.utils.hop(this.changeCount,title)) {\n\t\tthis.changeCount[title]++;\n\t} else {\n\t\tthis.changeCount[title] = 1;\n\t}\n\t// Trigger events\n\tthis.eventListeners = this.eventListeners || {};\n\tif(!this.eventsTriggered) {\n\t\tvar self = this;\n\t\t$tw.utils.nextTick(function() {\n\t\t\tvar changes = self.changedTiddlers;\n\t\t\tself.changedTiddlers = Object.create(null);\n\t\t\tself.eventsTriggered = false;\n\t\t\tif($tw.utils.count(changes) > 0) {\n\t\t\t\tself.dispatchEvent(\"change\",changes);\n\t\t\t}\n\t\t});\n\t\tthis.eventsTriggered = true;\n\t}\n};\n\nexports.getSizeOfTiddlerEventQueue = function() {\n\treturn $tw.utils.count(this.changedTiddlers);\n};\n\nexports.clearTiddlerEventQueue = function() {\n\tthis.changedTiddlers = Object.create(null);\n\tthis.changeCount = Object.create(null);\n};\n\nexports.getChangeCount = function(title) {\n\tthis.changeCount = this.changeCount || Object.create(null);\n\tif($tw.utils.hop(this.changeCount,title)) {\n\t\treturn this.changeCount[title];\n\t} else {\n\t\treturn 0;\n\t}\n};\n\n/*\nGenerate an unused title from the specified base\n*/\nexports.generateNewTitle = function(baseTitle,options) {\n\toptions = options || {};\n\tvar c = 0,\n\t\ttitle = baseTitle;\n\twhile(this.tiddlerExists(title) || this.isShadowTiddler(title) || this.findDraft(title)) {\n\t\ttitle = baseTitle + \n\t\t\t(options.prefix || \" \") + \n\t\t\t(++c);\n\t}\n\treturn title;\n};\n\nexports.isSystemTiddler = function(title) {\n\treturn title && title.indexOf(\"$:/\") === 0;\n};\n\nexports.isTemporaryTiddler = function(title) {\n\treturn title && title.indexOf(\"$:/temp/\") === 0;\n};\n\nexports.isImageTiddler = function(title) {\n\tvar tiddler = this.getTiddler(title);\n\tif(tiddler) {\t\t\n\t\tvar contentTypeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || \"text/vnd.tiddlywiki\"];\n\t\treturn !!contentTypeInfo && contentTypeInfo.flags.indexOf(\"image\") !== -1;\n\t} else {\n\t\treturn null;\n\t}\n};\n\nexports.isBinaryTiddler = function(title) {\n\tvar tiddler = this.getTiddler(title);\n\tif(tiddler) {\t\t\n\t\tvar contentTypeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || \"text/vnd.tiddlywiki\"];\n\t\treturn !!contentTypeInfo && contentTypeInfo.encoding === \"base64\";\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nLike addTiddler() except it will silently reject any plugin tiddlers that are older than the currently loaded version. Returns true if the tiddler was imported\n*/\nexports.importTiddler = function(tiddler) {\n\tvar existingTiddler = this.getTiddler(tiddler.fields.title);\n\t// Check if we're dealing with a plugin\n\tif(tiddler && tiddler.hasField(\"plugin-type\") && tiddler.hasField(\"version\") && existingTiddler && existingTiddler.hasField(\"plugin-type\") && existingTiddler.hasField(\"version\")) {\n\t\t// Reject the incoming plugin if it is older\n\t\tif(!$tw.utils.checkVersions(tiddler.fields.version,existingTiddler.fields.version)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t// Fall through to adding the tiddler\n\tthis.addTiddler(tiddler);\n\treturn true;\n};\n\n/*\nReturn a hashmap of the fields that should be set when a tiddler is created\n*/\nexports.getCreationFields = function() {\n\tif(this.getTiddlerText(TIMESTAMP_DISABLE_TITLE,\"\").toLowerCase() !== \"yes\") {\n\t\tvar fields = {\n\t\t\t\tcreated: new Date()\n\t\t\t},\n\t\t\tcreator = this.getTiddlerText(USER_NAME_TITLE);\n\t\tif(creator) {\n\t\t\tfields.creator = creator;\n\t\t}\n\t\treturn fields;\n\t} else {\n\t\treturn {};\n\t}\n};\n\n/*\nReturn a hashmap of the fields that should be set when a tiddler is modified\n*/\nexports.getModificationFields = function() {\n\tif(this.getTiddlerText(TIMESTAMP_DISABLE_TITLE,\"\").toLowerCase() !== \"yes\") {\n\t\tvar fields = Object.create(null),\n\t\t\tmodifier = this.getTiddlerText(USER_NAME_TITLE);\n\t\tfields.modified = new Date();\n\t\tif(modifier) {\n\t\t\tfields.modifier = modifier;\n\t\t}\n\t\treturn fields;\n\t} else {\n\t\treturn {};\n\t}\n};\n\n/*\nReturn a sorted array of tiddler titles.  Options include:\nsortField: field to sort by\nexcludeTag: tag to exclude\nincludeSystem: whether to include system tiddlers (defaults to false)\n*/\nexports.getTiddlers = function(options) {\n\toptions = options || Object.create(null);\n\tvar self = this,\n\t\tsortField = options.sortField || \"title\",\n\t\ttiddlers = [], t, titles = [];\n\tthis.each(function(tiddler,title) {\n\t\tif(options.includeSystem || !self.isSystemTiddler(title)) {\n\t\t\tif(!options.excludeTag || !tiddler.hasTag(options.excludeTag)) {\n\t\t\t\ttiddlers.push(tiddler);\n\t\t\t}\n\t\t}\n\t});\n\ttiddlers.sort(function(a,b) {\n\t\tvar aa = a.fields[sortField].toLowerCase() || \"\",\n\t\t\tbb = b.fields[sortField].toLowerCase() || \"\";\n\t\tif(aa < bb) {\n\t\t\treturn -1;\n\t\t} else {\n\t\t\tif(aa > bb) {\n\t\t\t\treturn 1;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n\tfor(t=0; t<tiddlers.length; t++) {\n\t\ttitles.push(tiddlers[t].fields.title);\n\t}\n\treturn titles;\n};\n\nexports.countTiddlers = function(excludeTag) {\n\tvar tiddlers = this.getTiddlers({excludeTag: excludeTag});\n\treturn $tw.utils.count(tiddlers);\n};\n\n/*\nReturns a function iterator(callback) that iterates through the specified titles, and invokes the callback with callback(tiddler,title)\n*/\nexports.makeTiddlerIterator = function(titles) {\n\tvar self = this;\n\tif(!$tw.utils.isArray(titles)) {\n\t\ttitles = Object.keys(titles);\n\t} else {\n\t\ttitles = titles.slice(0);\n\t}\n\treturn function(callback) {\n\t\ttitles.forEach(function(title) {\n\t\t\tcallback(self.getTiddler(title),title);\n\t\t});\n\t};\n};\n\n/*\nSort an array of tiddler titles by a specified field\n\ttitles: array of titles (sorted in place)\n\tsortField: name of field to sort by\n\tisDescending: true if the sort should be descending\n\tisCaseSensitive: true if the sort should consider upper and lower case letters to be different\n*/\nexports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric) {\n\tvar self = this;\n\ttitles.sort(function(a,b) {\n\t\tvar x,y,\n\t\t\tcompareNumbers = function(x,y) {\n\t\t\t\tvar result = \n\t\t\t\t\tisNaN(x) && !isNaN(y) ? (isDescending ? -1 : 1) :\n\t\t\t\t\t!isNaN(x) && isNaN(y) ? (isDescending ? 1 : -1) :\n\t\t\t\t\t\t\t\t\t\t\t(isDescending ? y - x :  x - y);\n\t\t\t\treturn result;\n\t\t\t};\n\t\tif(sortField !== \"title\") {\n\t\t\tvar tiddlerA = self.getTiddler(a),\n\t\t\t\ttiddlerB = self.getTiddler(b);\n\t\t\tif(tiddlerA) {\n\t\t\t\ta = tiddlerA.fields[sortField] || \"\";\n\t\t\t} else {\n\t\t\t\ta = \"\";\n\t\t\t}\n\t\t\tif(tiddlerB) {\n\t\t\t\tb = tiddlerB.fields[sortField] || \"\";\n\t\t\t} else {\n\t\t\t\tb = \"\";\n\t\t\t}\n\t\t}\n\t\tx = Number(a);\n\t\ty = Number(b);\n\t\tif(isNumeric && (!isNaN(x) || !isNaN(y))) {\n\t\t\treturn compareNumbers(x,y);\n\t\t} else if(isAlphaNumeric) {\n\t\t\treturn isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: \"base\"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: \"base\"});\n\t\t} else if($tw.utils.isDate(a) && $tw.utils.isDate(b)) {\n\t\t\treturn isDescending ? b - a : a - b;\n\t\t} else {\n\t\t\ta = String(a);\n\t\t\tb = String(b);\n\t\t\tif(!isCaseSensitive) {\n\t\t\t\ta = a.toLowerCase();\n\t\t\t\tb = b.toLowerCase();\n\t\t\t}\n\t\t\treturn isDescending ? b.localeCompare(a) : a.localeCompare(b);\n\t\t}\n\t});\n};\n\n/*\nFor every tiddler invoke a callback(title,tiddler) with `this` set to the wiki object. Options include:\nsortField: field to sort by\nexcludeTag: tag to exclude\nincludeSystem: whether to include system tiddlers (defaults to false)\n*/\nexports.forEachTiddler = function(/* [options,]callback */) {\n\tvar arg = 0,\n\t\toptions = arguments.length >= 2 ? arguments[arg++] : {},\n\t\tcallback = arguments[arg++],\n\t\ttitles = this.getTiddlers(options),\n\t\tt, tiddler;\n\tfor(t=0; t<titles.length; t++) {\n\t\ttiddler = this.getTiddler(titles[t]);\n\t\tif(tiddler) {\n\t\t\tcallback.call(this,tiddler.fields.title,tiddler);\n\t\t}\n\t}\n};\n\n/*\nReturn an array of tiddler titles that are directly linked within the given parse tree\n */\nexports.extractLinks = function(parseTreeRoot) {\n\t// Count up the links\n\tvar links = [],\n\t\tcheckParseTree = function(parseTree) {\n\t\t\tfor(var t=0; t<parseTree.length; t++) {\n\t\t\t\tvar parseTreeNode = parseTree[t];\n\t\t\t\tif(parseTreeNode.type === \"link\" && parseTreeNode.attributes.to && parseTreeNode.attributes.to.type === \"string\") {\n\t\t\t\t\tvar value = parseTreeNode.attributes.to.value;\n\t\t\t\t\tif(links.indexOf(value) === -1) {\n\t\t\t\t\t\tlinks.push(value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(parseTreeNode.children) {\n\t\t\t\t\tcheckParseTree(parseTreeNode.children);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\tcheckParseTree(parseTreeRoot);\n\treturn links;\n};\n\n/*\nReturn an array of tiddler titles that are directly linked from the specified tiddler\n*/\nexports.getTiddlerLinks = function(title) {\n\tvar self = this;\n\t// We'll cache the links so they only get computed if the tiddler changes\n\treturn this.getCacheForTiddler(title,\"links\",function() {\n\t\t// Parse the tiddler\n\t\tvar parser = self.parseTiddler(title);\n\t\tif(parser) {\n\t\t\treturn self.extractLinks(parser.tree);\n\t\t}\n\t\treturn [];\n\t});\n};\n\n/*\nReturn an array of tiddler titles that link to the specified tiddler\n*/\nexports.getTiddlerBacklinks = function(targetTitle) {\n\tvar self = this,\n\t\tbacklinksIndexer = this.getIndexer(\"BacklinksIndexer\"),\n\t\tbacklinks = backlinksIndexer && backlinksIndexer.lookup(targetTitle);\n\n\tif(!backlinks) {\n\t\tbacklinks = [];\n\t\tthis.forEachTiddler(function(title,tiddler) {\n\t\t\tvar links = self.getTiddlerLinks(title);\n\t\t\tif(links.indexOf(targetTitle) !== -1) {\n\t\t\t\tbacklinks.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn backlinks;\n};\n\n/*\nReturn a hashmap of tiddler titles that are referenced but not defined. Each value is the number of times the missing tiddler is referenced\n*/\nexports.getMissingTitles = function() {\n\tvar self = this,\n\t\tmissing = [];\n// We should cache the missing tiddler list, even if we recreate it every time any tiddler is modified\n\tthis.forEachTiddler(function(title,tiddler) {\n\t\tvar links = self.getTiddlerLinks(title);\n\t\t$tw.utils.each(links,function(link) {\n\t\t\tif((!self.tiddlerExists(link) && !self.isShadowTiddler(link)) && missing.indexOf(link) === -1) {\n\t\t\t\tmissing.push(link);\n\t\t\t}\n\t\t});\n\t});\n\treturn missing;\n};\n\nexports.getOrphanTitles = function() {\n\tvar self = this,\n\t\torphans = this.getTiddlers();\n\tthis.forEachTiddler(function(title,tiddler) {\n\t\tvar links = self.getTiddlerLinks(title);\n\t\t$tw.utils.each(links,function(link) {\n\t\t\tvar p = orphans.indexOf(link);\n\t\t\tif(p !== -1) {\n\t\t\t\torphans.splice(p,1);\n\t\t\t}\n\t\t});\n\t});\n\treturn orphans; // Todo\n};\n\n/*\nRetrieves a list of the tiddler titles that are tagged with a given tag\n*/\nexports.getTiddlersWithTag = function(tag) {\n\t// Try to use the indexer\n\tvar self = this,\n\t\ttagIndexer = this.getIndexer(\"TagIndexer\"),\n\t\tresults = tagIndexer && tagIndexer.subIndexers[3].lookup(tag);\n\tif(!results) {\n\t\t// If not available, perform a manual scan\n\t\tresults = this.getGlobalCache(\"taglist-\" + tag,function() {\n\t\t\tvar tagmap = self.getTagMap();\n\t\t\treturn self.sortByList(tagmap[tag],tag);\n\t\t});\n\t}\n\treturn results;\n};\n\n/*\nGet a hashmap by tag of arrays of tiddler titles\n*/\nexports.getTagMap = function() {\n\tvar self = this;\n\treturn this.getGlobalCache(\"tagmap\",function() {\n\t\tvar tags = Object.create(null),\n\t\t\tstoreTags = function(tagArray,title) {\n\t\t\t\tif(tagArray) {\n\t\t\t\t\tfor(var index=0; index<tagArray.length; index++) {\n\t\t\t\t\t\tvar tag = tagArray[index];\n\t\t\t\t\t\tif($tw.utils.hop(tags,tag)) {\n\t\t\t\t\t\t\ttags[tag].push(title);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttags[tag] = [title];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\ttitle, tiddler;\n\t\t// Collect up all the tags\n\t\tself.eachShadow(function(tiddler,title) {\n\t\t\tif(!self.tiddlerExists(title)) {\n\t\t\t\ttiddler = self.getTiddler(title);\n\t\t\t\tstoreTags(tiddler.fields.tags,title);\n\t\t\t}\n\t\t});\n\t\tself.each(function(tiddler,title) {\n\t\t\tstoreTags(tiddler.fields.tags,title);\n\t\t});\n\t\treturn tags;\n\t});\n};\n\n/*\nLookup a given tiddler and return a list of all the tiddlers that include it in the specified list field\n*/\nexports.findListingsOfTiddler = function(targetTitle,fieldName) {\n\tfieldName = fieldName || \"list\";\n\tvar titles = [];\n\tthis.each(function(tiddler,title) {\n\t\tvar list = $tw.utils.parseStringArray(tiddler.fields[fieldName]);\n\t\tif(list && list.indexOf(targetTitle) !== -1) {\n\t\t\ttitles.push(title);\n\t\t}\n\t});\n\treturn titles;\n};\n\n/*\nSorts an array of tiddler titles according to an ordered list\n*/\nexports.sortByList = function(array,listTitle) {\n\tvar self = this,\n\t\treplacedTitles = Object.create(null);\n\t// Given a title, this function will place it in the correct location\n\t// within titles.\n\tfunction moveItemInList(title) {\n\t\tif(!$tw.utils.hop(replacedTitles, title)) {\n\t\t\treplacedTitles[title] = true;\n\t\t\tvar newPos = -1,\n\t\t\t\ttiddler = self.getTiddler(title);\n\t\t\tif(tiddler) {\n\t\t\t\tvar beforeTitle = tiddler.fields[\"list-before\"],\n\t\t\t\t\tafterTitle = tiddler.fields[\"list-after\"];\n\t\t\t\tif(beforeTitle === \"\") {\n\t\t\t\t\tnewPos = 0;\n\t\t\t\t} else if(afterTitle === \"\") {\n\t\t\t\t\tnewPos = titles.length;\n\t\t\t\t} else if(beforeTitle) {\n\t\t\t\t\t// if this title is placed relative\n\t\t\t\t\t// to another title, make sure that\n\t\t\t\t\t// title is placed before we place\n\t\t\t\t\t// this one.\n\t\t\t\t\tmoveItemInList(beforeTitle);\n\t\t\t\t\tnewPos = titles.indexOf(beforeTitle);\n\t\t\t\t} else if(afterTitle) {\n\t\t\t\t\t// Same deal\n\t\t\t\t\tmoveItemInList(afterTitle);\n\t\t\t\t\tnewPos = titles.indexOf(afterTitle);\n\t\t\t\t\tif(newPos >= 0) {\n\t\t\t\t\t\t++newPos;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// If a new position is specified, let's move it\n\t\t\t\tif (newPos !== -1) {\n\t\t\t\t\t// get its current Pos, and make sure\n\t\t\t\t\t// sure that it's _actually_ in the list\n\t\t\t\t\t// and that it would _actually_ move\n\t\t\t\t\t// (#4275) We don't bother calling\n\t\t\t\t\t//         indexOf unless we have a new\n\t\t\t\t\t//         position to work with\n\t\t\t\t\tvar currPos = titles.indexOf(title);\n\t\t\t\t\tif(currPos >= 0 && newPos !== currPos) {\n\t\t\t\t\t\t// move it!\n\t\t\t\t\t\ttitles.splice(currPos,1);\n\t\t\t\t\t\tif(newPos >= currPos) {\n\t\t\t\t\t\t\tnewPos--;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttitles.splice(newPos,0,title);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tvar list = this.getTiddlerList(listTitle);\n\tif(!array || array.length === 0) {\n\t\treturn [];\n\t} else {\n\t\tvar titles = [], t, title;\n\t\t// First place any entries that are present in the list\n\t\tfor(t=0; t<list.length; t++) {\n\t\t\ttitle = list[t];\n\t\t\tif(array.indexOf(title) !== -1) {\n\t\t\t\ttitles.push(title);\n\t\t\t}\n\t\t}\n\t\t// Then place any remaining entries\n\t\tfor(t=0; t<array.length; t++) {\n\t\t\ttitle = array[t];\n\t\t\tif(list.indexOf(title) === -1) {\n\t\t\t\ttitles.push(title);\n\t\t\t}\n\t\t}\n\t\t// Finally obey the list-before and list-after fields of each tiddler in turn\n\t\tvar sortedTitles = titles.slice(0);\n\t\tfor(t=0; t<sortedTitles.length; t++) {\n\t\t\ttitle = sortedTitles[t];\n\t\t\tmoveItemInList(title);\n\t\t}\n\t\treturn titles;\n\t}\n};\n\nexports.getSubTiddler = function(title,subTiddlerTitle) {\n\tvar bundleInfo = this.getPluginInfo(title) || this.getTiddlerDataCached(title);\n\tif(bundleInfo && bundleInfo.tiddlers) {\n\t\tvar subTiddler = bundleInfo.tiddlers[subTiddlerTitle];\n\t\tif(subTiddler) {\n\t\t\treturn new $tw.Tiddler(subTiddler);\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nRetrieve a tiddler as a JSON string of the fields\n*/\nexports.getTiddlerAsJson = function(title) {\n\tvar tiddler = this.getTiddler(title);\n\tif(tiddler) {\n\t\tvar fields = Object.create(null);\n\t\t$tw.utils.each(tiddler.fields,function(value,name) {\n\t\t\tfields[name] = tiddler.getFieldString(name);\n\t\t});\n\t\treturn JSON.stringify(fields);\n\t} else {\n\t\treturn JSON.stringify({title: title});\n\t}\n};\n\nexports.getTiddlersAsJson = function(filter,spaces) {\n\tvar tiddlers = this.filterTiddlers(filter),\n\t\tspaces = (spaces === undefined) ? $tw.config.preferences.jsonSpaces : spaces,\n\t\tdata = [];\n\tfor(var t=0;t<tiddlers.length; t++) {\n\t\tvar tiddler = this.getTiddler(tiddlers[t]);\n\t\tif(tiddler) {\n\t\t\tvar fields = new Object();\n\t\t\tfor(var field in tiddler.fields) {\n\t\t\t\tfields[field] = tiddler.getFieldString(field);\n\t\t\t}\n\t\t\tdata.push(fields);\n\t\t}\n\t}\n\treturn JSON.stringify(data,null,spaces);\n};\n\n/*\nGet the content of a tiddler as a JavaScript object. How this is done depends on the type of the tiddler:\n\napplication/json: the tiddler JSON is parsed into an object\napplication/x-tiddler-dictionary: the tiddler is parsed as sequence of name:value pairs\n\nOther types currently just return null.\n\ntitleOrTiddler: string tiddler title or a tiddler object\ndefaultData: default data to be returned if the tiddler is missing or doesn't contain data\n\nNote that the same value is returned for repeated calls for the same tiddler data. The value is frozen to prevent modification; otherwise modifications would be visible to all callers\n*/\nexports.getTiddlerDataCached = function(titleOrTiddler,defaultData) {\n\tvar self = this,\n\t\ttiddler = titleOrTiddler;\n\tif(!(tiddler instanceof $tw.Tiddler)) {\n\t\ttiddler = this.getTiddler(tiddler);\t\n\t}\n\tif(tiddler) {\n\t\treturn this.getCacheForTiddler(tiddler.fields.title,\"data\",function() {\n\t\t\t// Return the frozen value\n\t\t\tvar value = self.getTiddlerData(tiddler.fields.title,undefined);\n\t\t\t$tw.utils.deepFreeze(value);\n\t\t\treturn value;\n\t\t}) || defaultData;\n\t} else {\n\t\treturn defaultData;\n\t}\n};\n\n/*\nAlternative, uncached version of getTiddlerDataCached(). The return value can be mutated freely and reused\n*/\nexports.getTiddlerData = function(titleOrTiddler,defaultData) {\n\tvar tiddler = titleOrTiddler,\n\t\tdata;\n\tif(!(tiddler instanceof $tw.Tiddler)) {\n\t\ttiddler = this.getTiddler(tiddler);\t\n\t}\n\tif(tiddler && tiddler.fields.text) {\n\t\tswitch(tiddler.fields.type) {\n\t\t\tcase \"application/json\":\n\t\t\t\t// JSON tiddler\n\t\t\t\ttry {\n\t\t\t\t\tdata = JSON.parse(tiddler.fields.text);\n\t\t\t\t} catch(ex) {\n\t\t\t\t\treturn defaultData;\n\t\t\t\t}\n\t\t\t\treturn data;\n\t\t\tcase \"application/x-tiddler-dictionary\":\n\t\t\t\treturn $tw.utils.parseFields(tiddler.fields.text);\n\t\t}\n\t}\n\treturn defaultData;\n};\n\n/*\nExtract an indexed field from within a data tiddler\n*/\nexports.extractTiddlerDataItem = function(titleOrTiddler,index,defaultText) {\n\tvar data = this.getTiddlerDataCached(titleOrTiddler,Object.create(null)),\n\t\ttext;\n\tif(data && $tw.utils.hop(data,index)) {\n\t\ttext = data[index];\n\t}\n\tif(typeof text === \"string\" || typeof text === \"number\") {\n\t\treturn text.toString();\n\t} else {\n\t\treturn defaultText;\n\t}\n};\n\n/*\nSet a tiddlers content to a JavaScript object. Currently this is done by setting the tiddler's type to \"application/json\" and setting the text to the JSON text of the data.\ntitle: title of tiddler\ndata: object that can be serialised to JSON\nfields: optional hashmap of additional tiddler fields to be set\n*/\nexports.setTiddlerData = function(title,data,fields) {\n\tvar existingTiddler = this.getTiddler(title),\n\t\tnewFields = {\n\t\t\ttitle: title\n\t};\n\tif(existingTiddler && existingTiddler.fields.type === \"application/x-tiddler-dictionary\") {\n\t\tnewFields.text = $tw.utils.makeTiddlerDictionary(data);\n\t} else {\n\t\tnewFields.type = \"application/json\";\n\t\tnewFields.text = JSON.stringify(data,null,$tw.config.preferences.jsonSpaces);\n\t}\n\tthis.addTiddler(new $tw.Tiddler(this.getCreationFields(),existingTiddler,fields,newFields,this.getModificationFields()));\n};\n\n/*\nReturn the content of a tiddler as an array containing each line\n*/\nexports.getTiddlerList = function(title,field,index) {\n\tif(index) {\n\t\treturn $tw.utils.parseStringArray(this.extractTiddlerDataItem(title,index,\"\"));\n\t}\n\tfield = field || \"list\";\n\tvar tiddler = this.getTiddler(title);\n\tif(tiddler) {\n\t\treturn ($tw.utils.parseStringArray(tiddler.fields[field]) || []).slice(0);\n\t}\n\treturn [];\n};\n\n// Return a named global cache object. Global cache objects are cleared whenever a tiddler change occurs\nexports.getGlobalCache = function(cacheName,initializer) {\n\tthis.globalCache = this.globalCache || Object.create(null);\n\tif($tw.utils.hop(this.globalCache,cacheName)) {\n\t\treturn this.globalCache[cacheName];\n\t} else {\n\t\tthis.globalCache[cacheName] = initializer();\n\t\treturn this.globalCache[cacheName];\n\t}\n};\n\nexports.clearGlobalCache = function() {\n\tthis.globalCache = Object.create(null);\n};\n\n// Return the named cache object for a tiddler. If the cache doesn't exist then the initializer function is invoked to create it\nexports.getCacheForTiddler = function(title,cacheName,initializer) {\n\tthis.caches = this.caches || Object.create(null);\n\tvar caches = this.caches[title];\n\tif(caches && caches[cacheName]) {\n\t\treturn caches[cacheName];\n\t} else {\n\t\tif(!caches) {\n\t\t\tcaches = Object.create(null);\n\t\t\tthis.caches[title] = caches;\n\t\t}\n\t\tcaches[cacheName] = initializer();\n\t\treturn caches[cacheName];\n\t}\n};\n\n// Clear all caches associated with a particular tiddler, or, if the title is null, clear all the caches for all the tiddlers\nexports.clearCache = function(title) {\n\tif(title) {\n\t\tthis.caches = this.caches || Object.create(null);\n\t\tif($tw.utils.hop(this.caches,title)) {\n\t\t\tdelete this.caches[title];\n\t\t}\n\t} else {\n\t\tthis.caches = Object.create(null);\n\t}\n};\n\nexports.initParsers = function(moduleType) {\n\t// Install the parser modules\n\t$tw.Wiki.parsers = {};\n\tvar self = this;\n\t$tw.modules.forEachModuleOfType(\"parser\",function(title,module) {\n\t\tfor(var f in module) {\n\t\t\tif($tw.utils.hop(module,f)) {\n\t\t\t\t$tw.Wiki.parsers[f] = module[f]; // Store the parser class\n\t\t\t}\n\t\t}\n\t});\n\t// Use the generic binary parser for any binary types not registered so far\n\tif($tw.Wiki.parsers[\"application/octet-stream\"]) {\n\t\tObject.keys($tw.config.contentTypeInfo).forEach(function(type) {\n\t\t\tif(!$tw.utils.hop($tw.Wiki.parsers,type) && $tw.config.contentTypeInfo[type].encoding === \"base64\") {\n\t\t\t\t$tw.Wiki.parsers[type] = $tw.Wiki.parsers[\"application/octet-stream\"];\n\t\t\t}\n\t\t});\t\t\n\t}\n};\n\n/*\nParse a block of text of a specified MIME type\n\ttype: content type of text to be parsed\n\ttext: text\n\toptions: see below\nOptions include:\n\tparseAsInline: if true, the text of the tiddler will be parsed as an inline run\n\t_canonical_uri: optional string of the canonical URI of this content\n*/\nexports.parseText = function(type,text,options) {\n\ttext = text || \"\";\n\toptions = options || {};\n\t// Select a parser\n\tvar Parser = $tw.Wiki.parsers[type];\n\tif(!Parser && $tw.utils.getFileExtensionInfo(type)) {\n\t\tParser = $tw.Wiki.parsers[$tw.utils.getFileExtensionInfo(type).type];\n\t}\n\tif(!Parser) {\n\t\tParser = $tw.Wiki.parsers[options.defaultType || \"text/vnd.tiddlywiki\"];\n\t}\n\tif(!Parser) {\n\t\treturn null;\n\t}\n\t// Return the parser instance\n\treturn new Parser(type,text,{\n\t\tparseAsInline: options.parseAsInline,\n\t\twiki: this,\n\t\t_canonical_uri: options._canonical_uri\n\t});\n};\n\n/*\nParse a tiddler according to its MIME type\n*/\nexports.parseTiddler = function(title,options) {\n\toptions = $tw.utils.extend({},options);\n\tvar cacheType = options.parseAsInline ? \"inlineParseTree\" : \"blockParseTree\",\n\t\ttiddler = this.getTiddler(title),\n\t\tself = this;\n\treturn tiddler ? this.getCacheForTiddler(title,cacheType,function() {\n\t\t\tif(tiddler.hasField(\"_canonical_uri\")) {\n\t\t\t\toptions._canonical_uri = tiddler.fields._canonical_uri;\n\t\t\t}\n\t\t\treturn self.parseText(tiddler.fields.type,tiddler.fields.text,options);\n\t\t}) : null;\n};\n\nexports.parseTextReference = function(title,field,index,options) {\n\tvar tiddler,text;\n\tif(options.subTiddler) {\n\t\ttiddler = this.getSubTiddler(title,options.subTiddler);\n\t} else {\n\t\ttiddler = this.getTiddler(title);\n\t\tif(field === \"text\" || (!field && !index)) {\n\t\t\tthis.getTiddlerText(title); // Force the tiddler to be lazily loaded\n\t\t\treturn this.parseTiddler(title,options);\n\t\t}\n\t}\n\tif(field === \"text\" || (!field && !index)) {\n\t\tif(tiddler && tiddler.fields) {\n\t\t\treturn this.parseText(tiddler.fields.type,tiddler.fields.text,options);\t\t\t\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t} else if(field) {\n\t\tif(field === \"title\") {\n\t\t\ttext = title;\n\t\t} else {\n\t\t\tif(!tiddler || !tiddler.hasField(field)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\ttext = tiddler.fields[field];\n\t\t}\n\t\treturn this.parseText(\"text/vnd.tiddlywiki\",text.toString(),options);\n\t} else if(index) {\n\t\tthis.getTiddlerText(title); // Force the tiddler to be lazily loaded\n\t\ttext = this.extractTiddlerDataItem(tiddler,index,undefined);\n\t\tif(text === undefined) {\n\t\t\treturn null;\n\t\t}\n\t\treturn this.parseText(\"text/vnd.tiddlywiki\",text,options);\n\t}\n};\n\n/*\nMake a widget tree for a parse tree\nparser: parser object\noptions: see below\nOptions include:\ndocument: optional document to use\nvariables: hashmap of variables to set\nparentWidget: optional parent widget for the root node\n*/\nexports.makeWidget = function(parser,options) {\n\toptions = options || {};\n\tvar widgetNode = {\n\t\t\ttype: \"widget\",\n\t\t\tchildren: []\n\t\t},\n\t\tcurrWidgetNode = widgetNode;\n\t// Create set variable widgets for each variable\n\t$tw.utils.each(options.variables,function(value,name) {\n\t\tvar setVariableWidget = {\n\t\t\ttype: \"set\",\n\t\t\tattributes: {\n\t\t\t\tname: {type: \"string\", value: name},\n\t\t\t\tvalue: {type: \"string\", value: value}\n\t\t\t},\n\t\t\tchildren: []\n\t\t};\n\t\tcurrWidgetNode.children = [setVariableWidget];\n\t\tcurrWidgetNode = setVariableWidget;\n\t});\n\t// Add in the supplied parse tree nodes\n\tcurrWidgetNode.children = parser ? parser.tree : [];\n\t// Create the widget\n\treturn new widget.widget(widgetNode,{\n\t\twiki: this,\n\t\tdocument: options.document || $tw.fakeDocument,\n\t\tparentWidget: options.parentWidget\n\t});\n};\n\n/*\nMake a widget tree for transclusion\ntitle: target tiddler title\noptions: as for wiki.makeWidget() plus:\noptions.field: optional field to transclude (defaults to \"text\")\noptions.mode: transclusion mode \"inline\" or \"block\"\noptions.children: optional array of children for the transclude widget\noptions.importVariables: optional importvariables filter string for macros to be included\noptions.importPageMacros: optional boolean; if true, equivalent to passing \"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\" to options.importVariables\n*/\nexports.makeTranscludeWidget = function(title,options) {\n\toptions = options || {};\n\tvar parseTreeDiv = {tree: [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"div\",\n\t\t\tchildren: []}]},\n\t\tparseTreeImportVariables = {\n\t\t\ttype: \"importvariables\",\n\t\t\tattributes: {\n\t\t\t\tfilter: {\n\t\t\t\t\tname: \"filter\",\n\t\t\t\t\ttype: \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\tisBlock: false,\n\t\t\tchildren: []},\n\t\tparseTreeTransclude = {\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {\n\t\t\t\t\tname: \"tiddler\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalue: title}},\n\t\t\tisBlock: !options.parseAsInline};\n\tif(options.importVariables || options.importPageMacros) {\n\t\tif(options.importVariables) {\n\t\t\tparseTreeImportVariables.attributes.filter.value = options.importVariables;\n\t\t} else if(options.importPageMacros) {\n\t\t\tparseTreeImportVariables.attributes.filter.value = \"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\";\n\t\t}\n\t\tparseTreeDiv.tree[0].children.push(parseTreeImportVariables);\n\t\tparseTreeImportVariables.children.push(parseTreeTransclude);\n\t} else {\n\t\tparseTreeDiv.tree[0].children.push(parseTreeTransclude);\n\t}\n\tif(options.field) {\n\t\tparseTreeTransclude.attributes.field = {type: \"string\", value: options.field};\n\t}\n\tif(options.mode) {\n\t\tparseTreeTransclude.attributes.mode = {type: \"string\", value: options.mode};\n\t}\n\tif(options.children) {\n\t\tparseTreeTransclude.children = options.children;\n\t}\n\treturn $tw.wiki.makeWidget(parseTreeDiv,options);\n};\n\n/*\nParse text in a specified format and render it into another format\n\toutputType: content type for the output\n\ttextType: content type of the input text\n\ttext: input text\n\toptions: see below\nOptions include:\nvariables: hashmap of variables to set\nparentWidget: optional parent widget for the root node\n*/\nexports.renderText = function(outputType,textType,text,options) {\n\toptions = options || {};\n\tvar parser = this.parseText(textType,text,options),\n\t\twidgetNode = this.makeWidget(parser,options);\n\tvar container = $tw.fakeDocument.createElement(\"div\");\n\twidgetNode.render(container,null);\n\treturn outputType === \"text/html\" ? container.innerHTML : container.textContent;\n};\n\n/*\nParse text from a tiddler and render it into another format\n\toutputType: content type for the output\n\ttitle: title of the tiddler to be rendered\n\toptions: see below\nOptions include:\nvariables: hashmap of variables to set\nparentWidget: optional parent widget for the root node\n*/\nexports.renderTiddler = function(outputType,title,options) {\n\toptions = options || {};\n\tvar parser = this.parseTiddler(title,options),\n\t\twidgetNode = this.makeWidget(parser,options);\n\tvar container = $tw.fakeDocument.createElement(\"div\");\n\twidgetNode.render(container,null);\n\treturn outputType === \"text/html\" ? container.innerHTML : (outputType === \"text/plain-formatted\" ? container.formattedTextContent : container.textContent);\n};\n\n/*\nReturn an array of tiddler titles that match a search string\n\ttext: The text string to search for\n\toptions: see below\nOptions available:\n\tsource: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title)\n\texclude: An array of tiddler titles to exclude from the search\n\tinvert: If true returns tiddlers that do not contain the specified string\n\tcaseSensitive: If true forces a case sensitive search\n\tfield: If specified, restricts the search to the specified field, or an array of field names\n\tanchored: If true, forces all but regexp searches to be anchored to the start of text\n\texcludeField: If true, the field options are inverted to specify the fields that are not to be searched\n\tThe search mode is determined by the first of these boolean flags to be true\n\t\tliteral: searches for literal string\n\t\twhitespace: same as literal except runs of whitespace are treated as a single space\n\t\tregexp: treats the search term as a regular expression\n\t\twords: (default) treats search string as a list of tokens, and matches if all tokens are found, regardless of adjacency or ordering\n*/\nexports.search = function(text,options) {\n\toptions = options || {};\n\tvar self = this,\n\t\tt,\n\t\tinvert = !!options.invert;\n\t// Convert the search string into a regexp for each term\n\tvar terms, searchTermsRegExps,\n\t\tflags = options.caseSensitive ? \"\" : \"i\",\n\t\tanchor = options.anchored ? \"^\" : \"\";\n\tif(options.literal) {\n\t\tif(text.length === 0) {\n\t\t\tsearchTermsRegExps = null;\n\t\t} else {\n\t\t\tsearchTermsRegExps = [new RegExp(\"(\" + anchor + $tw.utils.escapeRegExp(text) + \")\",flags)];\n\t\t}\n\t} else if(options.whitespace) {\n\t\tterms = [];\n\t\t$tw.utils.each(text.split(/\\s+/g),function(term) {\n\t\t\tif(term) {\n\t\t\t\tterms.push($tw.utils.escapeRegExp(term));\n\t\t\t}\n\t\t});\n\t\tsearchTermsRegExps = [new RegExp(\"(\" + anchor + terms.join(\"\\\\s+\") + \")\",flags)];\n\t} else if(options.regexp) {\n\t\ttry {\n\t\t\tsearchTermsRegExps = [new RegExp(\"(\" + text + \")\",flags)];\t\t\t\n\t\t} catch(e) {\n\t\t\tsearchTermsRegExps = null;\n\t\t\tconsole.log(\"Regexp error parsing /(\" + text + \")/\" + flags + \": \",e);\n\t\t}\n\t} else {\n\t\tterms = text.split(/ +/);\n\t\tif(terms.length === 1 && terms[0] === \"\") {\n\t\t\tsearchTermsRegExps = null;\n\t\t} else {\n\t\t\tsearchTermsRegExps = [];\n\t\t\tfor(t=0; t<terms.length; t++) {\n\t\t\t\tsearchTermsRegExps.push(new RegExp(\"(\" + anchor + $tw.utils.escapeRegExp(terms[t]) + \")\",flags));\n\t\t\t}\n\t\t}\n\t}\n\t// Accumulate the array of fields to be searched or excluded from the search\n\tvar fields = [];\n\tif(options.field) {\n\t\tif($tw.utils.isArray(options.field)) {\n\t\t\t$tw.utils.each(options.field,function(fieldName) {\n\t\t\t\tif(fieldName) {\n\t\t\t\t\tfields.push(fieldName);\t\t\t\t\t\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tfields.push(options.field);\n\t\t}\n\t}\n\t// Use default fields if none specified and we're not excluding fields (excluding fields with an empty field array is the same as searching all fields)\n\tif(fields.length === 0 && !options.excludeField) {\n\t\tfields.push(\"title\");\n\t\tfields.push(\"tags\");\n\t\tfields.push(\"text\");\n\t}\n\t// Function to check a given tiddler for the search term\n\tvar searchTiddler = function(title) {\n\t\tif(!searchTermsRegExps) {\n\t\t\treturn true;\n\t\t}\n\t\tvar notYetFound = searchTermsRegExps.slice();\n\n\t\tvar tiddler = self.getTiddler(title);\n\t\tif(!tiddler) {\n\t\t\ttiddler = new $tw.Tiddler({title: title, text: \"\", type: \"text/vnd.tiddlywiki\"});\n\t\t}\n\t\tvar contentTypeInfo = $tw.config.contentTypeInfo[tiddler.fields.type] || $tw.config.contentTypeInfo[\"text/vnd.tiddlywiki\"],\n\t\t\tsearchFields;\n\t\t// Get the list of fields we're searching\n\t\tif(options.excludeField) {\n\t\t\tsearchFields = Object.keys(tiddler.fields);\n\t\t\t$tw.utils.each(fields,function(fieldName) {\n\t\t\t\tvar p = searchFields.indexOf(fieldName);\n\t\t\t\tif(p !== -1) {\n\t\t\t\t\tsearchFields.splice(p,1);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsearchFields = fields;\n\t\t}\n\t\tfor(var fieldIndex=0; notYetFound.length>0 && fieldIndex<searchFields.length; fieldIndex++) {\n\t\t\t// Don't search the text field if the content type is binary\n\t\t\tvar fieldName = searchFields[fieldIndex];\n\t\t\tif(fieldName === \"text\" && contentTypeInfo.encoding !== \"utf8\") {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tvar str = tiddler.fields[fieldName],\n\t\t\t\tt;\n\t\t\tif(str) {\n\t\t\t\tif($tw.utils.isArray(str)) {\n\t\t\t\t\t// If the field value is an array, test each regexp against each field array entry and fail if each regexp doesn't match at least one field array entry\n\t\t\t\t\tfor(var s=0; s<str.length; s++) {\n\t\t\t\t\t\tfor(t=0; t<notYetFound.length;) {\n\t\t\t\t\t\t\tif(notYetFound[t].test(str[s])) {\n\t\t\t\t\t\t\t\tnotYetFound.splice(t, 1);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tt++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// If the field isn't an array, force it to a string and test each regexp against it and fail if any do not match\n\t\t\t\t\tstr = tiddler.getFieldString(fieldName);\n\t\t\t\t\tfor(t=0; t<notYetFound.length;) {\n\t\t\t\t\t\tif(notYetFound[t].test(str)) {\n\t\t\t\t\t\t\tnotYetFound.splice(t, 1);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\treturn notYetFound.length == 0;\n\t};\n\t// Loop through all the tiddlers doing the search\n\tvar results = [],\n\t\tsource = options.source || this.each;\n\tsource(function(tiddler,title) {\n\t\tif(searchTiddler(title) !== options.invert) {\n\t\t\tresults.push(title);\n\t\t}\n\t});\n\t// Remove any of the results we have to exclude\n\tif(options.exclude) {\n\t\tfor(t=0; t<options.exclude.length; t++) {\n\t\t\tvar p = results.indexOf(options.exclude[t]);\n\t\t\tif(p !== -1) {\n\t\t\t\tresults.splice(p,1);\n\t\t\t}\n\t\t}\n\t}\n\treturn results;\n};\n\n/*\nTrigger a load for a tiddler if it is skinny. Returns the text, or undefined if the tiddler is missing, null if the tiddler is being lazily loaded.\n*/\nexports.getTiddlerText = function(title,defaultText) {\n\tvar tiddler = this.getTiddler(title);\n\t// Return undefined if the tiddler isn't found\n\tif(!tiddler) {\n\t\treturn defaultText;\n\t}\n\tif(!tiddler.hasField(\"_is_skinny\")) {\n\t\t// Just return the text if we've got it\n\t\treturn tiddler.fields.text || \"\";\n\t} else {\n\t\t// Tell any listeners about the need to lazily load this tiddler\n\t\tthis.dispatchEvent(\"lazyLoad\",title);\n\t\t// Indicate that the text is being loaded\n\t\treturn null;\n\t}\n};\n\n/*\nCheck whether the text of a tiddler matches a given value. By default, the comparison is case insensitive, and any spaces at either end of the tiddler text is trimmed\n*/\nexports.checkTiddlerText = function(title,targetText,options) {\n\toptions = options || {};\n\tvar text = this.getTiddlerText(title,\"\");\n\tif(!options.noTrim) {\n\t\ttext = text.trim();\n\t}\n\tif(!options.caseSensitive) {\n\t\ttext = text.toLowerCase();\n\t\ttargetText = targetText.toLowerCase();\n\t}\n\treturn text === targetText;\n}\n\n/*\nRead an array of browser File objects, invoking callback(tiddlerFieldsArray) once they're all read\n*/\nexports.readFiles = function(files,options) {\n\tvar callback;\n\tif(typeof options === \"function\") {\n\t\tcallback = options;\n\t\toptions = {};\n\t} else {\n\t\tcallback = options.callback;\n\t}\n\tvar result = [],\n\t\toutstanding = files.length,\n\t\treadFileCallback = function(tiddlerFieldsArray) {\n\t\t\tresult.push.apply(result,tiddlerFieldsArray);\n\t\t\tif(--outstanding === 0) {\n\t\t\t\tcallback(result);\n\t\t\t}\n\t\t};\n\tfor(var f=0; f<files.length; f++) {\n\t\tthis.readFile(files[f],$tw.utils.extend({},options,{callback: readFileCallback}));\n\t}\n\treturn files.length;\n};\n\n/*\nRead a browser File object, invoking callback(tiddlerFieldsArray) with an array of tiddler fields objects\n*/\nexports.readFile = function(file,options) {\n\tvar callback;\n\tif(typeof options === \"function\") {\n\t\tcallback = options;\n\t\toptions = {};\n\t} else {\n\t\tcallback = options.callback;\n\t}\n\t// Get the type, falling back to the filename extension\n\tvar self = this,\n\t\ttype = file.type;\n\tif(type === \"\" || !type) {\n\t\tvar dotPos = file.name.lastIndexOf(\".\");\n\t\tif(dotPos !== -1) {\n\t\t\tvar fileExtensionInfo = $tw.utils.getFileExtensionInfo(file.name.substr(dotPos));\n\t\t\tif(fileExtensionInfo) {\n\t\t\t\ttype = fileExtensionInfo.type;\n\t\t\t}\n\t\t}\n\t}\n\t// Figure out if we're reading a binary file\n\tvar contentTypeInfo = $tw.config.contentTypeInfo[type],\n\t\tisBinary = contentTypeInfo ? contentTypeInfo.encoding === \"base64\" : false;\n\t// Log some debugging information\n\tif($tw.log.IMPORT) {\n\t\tconsole.log(\"Importing file '\" + file.name + \"', type: '\" + type + \"', isBinary: \" + isBinary);\n\t}\n\t// Give the hook a chance to process the drag\n\tif($tw.hooks.invokeHook(\"th-importing-file\",{\n\t\tfile: file,\n\t\ttype: type,\n\t\tisBinary: isBinary,\n\t\tcallback: callback\n\t}) !== true) {\n\t\tthis.readFileContent(file,type,isBinary,options.deserializer,callback);\n\t}\n};\n\n/*\nLower level utility to read the content of a browser File object, invoking callback(tiddlerFieldsArray) with an array of tiddler fields objects\n*/\nexports.readFileContent = function(file,type,isBinary,deserializer,callback) {\n\tvar self = this;\n\t// Create the FileReader\n\tvar reader = new FileReader();\n\t// Onload\n\treader.onload = function(event) {\n\t\tvar text = event.target.result,\n\t\t\ttiddlerFields = {title: file.name || \"Untitled\", type: type};\n\t\tif(isBinary) {\n\t\t\tvar commaPos = text.indexOf(\",\");\n\t\t\tif(commaPos !== -1) {\n\t\t\t\ttext = text.substr(commaPos + 1);\n\t\t\t}\n\t\t}\n\t\t// Check whether this is an encrypted TiddlyWiki file\n\t\tvar encryptedJson = $tw.utils.extractEncryptedStoreArea(text);\n\t\tif(encryptedJson) {\n\t\t\t// If so, attempt to decrypt it with the current password\n\t\t\t$tw.utils.decryptStoreAreaInteractive(encryptedJson,function(tiddlers) {\n\t\t\t\tcallback(tiddlers);\n\t\t\t});\n\t\t} else {\n\t\t\t// Otherwise, just try to deserialise any tiddlers in the file\n\t\t\tcallback(self.deserializeTiddlers(type,text,tiddlerFields,{deserializer: deserializer}));\n\t\t}\n\t};\n\t// Kick off the read\n\tif(isBinary) {\n\t\treader.readAsDataURL(file);\n\t} else {\n\t\treader.readAsText(file);\n\t}\n};\n\n/*\nFind any existing draft of a specified tiddler\n*/\nexports.findDraft = function(targetTitle) {\n\tvar draftTitle = undefined;\n\tthis.forEachTiddler({includeSystem: true},function(title,tiddler) {\n\t\tif(tiddler.fields[\"draft.title\"] && tiddler.fields[\"draft.of\"] === targetTitle) {\n\t\t\tdraftTitle = title;\n\t\t}\n\t});\n\treturn draftTitle;\n}\n\n/*\nCheck whether the specified draft tiddler has been modified.\nIf the original tiddler doesn't exist, create  a vanilla tiddler variable,\nto check if additional fields have been added.\n*/\nexports.isDraftModified = function(title) {\n\tvar tiddler = this.getTiddler(title);\n\tif(!tiddler.isDraft()) {\n\t\treturn false;\n\t}\n\tvar ignoredFields = [\"created\", \"modified\", \"title\", \"draft.title\", \"draft.of\"],\n\t\torigTiddler = this.getTiddler(tiddler.fields[\"draft.of\"]) || new $tw.Tiddler({text:\"\", tags:[]}),\n\t\ttitleModified = tiddler.fields[\"draft.title\"] !== tiddler.fields[\"draft.of\"];\n\treturn titleModified || !tiddler.isEqual(origTiddler,ignoredFields);\n};\n\n/*\nAdd a new record to the top of the history stack\ntitle: a title string or an array of title strings\nfromPageRect: page coordinates of the origin of the navigation\nhistoryTitle: title of history tiddler (defaults to $:/HistoryList)\n*/\nexports.addToHistory = function(title,fromPageRect,historyTitle) {\n\tvar story = new $tw.Story({wiki: this, historyTitle: historyTitle});\n\tstory.addToHistory(title,fromPageRect);\t\t\n};\n\n/*\nAdd a new tiddler to the story river\ntitle: a title string or an array of title strings\nfromTitle: the title of the tiddler from which the navigation originated\nstoryTitle: title of story tiddler (defaults to $:/StoryList)\noptions: see story.js\n*/\nexports.addToStory = function(title,fromTitle,storyTitle,options) {\n\tvar story = new $tw.Story({wiki: this, storyTitle: storyTitle});\n\tstory.addToStory(title,fromTitle,options);\t\t\n};\n\n/*\nGenerate a title for the draft of a given tiddler\n*/\nexports.generateDraftTitle = function(title) {\n\tvar c = 0,\n\t\tdraftTitle,\n\t\tusername = this.getTiddlerText(\"$:/status/UserName\"),\n\t\tattribution = username ? \" by \" + username : \"\";\n\tdo {\n\t\tdraftTitle = \"Draft \" + (c ? (c + 1) + \" \" : \"\") + \"of '\" + title + \"'\" + attribution;\n\t\tc++;\n\t} while(this.tiddlerExists(draftTitle));\n\treturn draftTitle;\n};\n\n/*\nInvoke the available upgrader modules\ntitles: array of tiddler titles to be processed\ntiddlers: hashmap by title of tiddler fields of pending import tiddlers. These can be modified by the upgraders. An entry with no fields indicates a tiddler that was pending import has been suppressed. When entries are added to the pending import the tiddlers hashmap may have entries that are not present in the titles array\nReturns a hashmap of messages keyed by tiddler title.\n*/\nexports.invokeUpgraders = function(titles,tiddlers) {\n\t// Collect up the available upgrader modules\n\tvar self = this;\n\tif(!this.upgraderModules) {\n\t\tthis.upgraderModules = [];\n\t\t$tw.modules.forEachModuleOfType(\"upgrader\",function(title,module) {\n\t\t\tif(module.upgrade) {\n\t\t\t\tself.upgraderModules.push(module);\n\t\t\t}\n\t\t});\n\t}\n\t// Invoke each upgrader in turn\n\tvar messages = {};\n\tfor(var t=0; t<this.upgraderModules.length; t++) {\n\t\tvar upgrader = this.upgraderModules[t],\n\t\t\tupgraderMessages = upgrader.upgrade(this,titles,tiddlers);\n\t\t$tw.utils.extend(messages,upgraderMessages);\n\t}\n\treturn messages;\n};\n\n// Determine whether a plugin by title is dynamically loadable\nexports.doesPluginRequireReload = function(title) {\n\treturn this.doesPluginInfoRequireReload(this.getPluginInfo(title) || this.getTiddlerDataCached(title));\n};\n\n// Determine whether a plugin info structure is dynamically loadable\nexports.doesPluginInfoRequireReload = function(pluginInfo) {\n\tif(pluginInfo) {\n\t\tvar foundModule = false;\n\t\t$tw.utils.each(pluginInfo.tiddlers,function(tiddler) {\n\t\t\tif(tiddler.type === \"application/javascript\" && $tw.utils.hop(tiddler,\"module-type\")) {\n\t\t\t\tfoundModule = true;\n\t\t\t}\n\t\t});\n\t\treturn foundModule;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n})();\n\n",
            "type": "application/javascript",
            "module-type": "wikimethod"
        },
        "$:/palettes/Blanca": {
            "title": "$:/palettes/Blanca",
            "name": "Blanca",
            "description": "A clean white palette to let you focus",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #66cccc\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #999999\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #ffffff\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #7897f3\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #ccc\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #ffffff\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #7897f3\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #eeeeee\ntab-border-selected: #cccccc\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ffeedd\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: #eee\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #ff9900\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/Blue": {
            "title": "$:/palettes/Blue",
            "name": "Blue",
            "description": "A blue theme",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #fff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour foreground>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333353\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #999999\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #ddddff\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #5778d8\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #ffffff\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: <<colour page-background>>\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #5959c0\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: #ccccdd\ntab-border-selected: #ccccdd\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #eeeeff\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #666666\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #ffffff\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #ffffff\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #5959c0\ntoolbar-new-button: #5eb95e\ntoolbar-options-button: rgb(128, 88, 165)\ntoolbar-save-button: #0e90d2\ntoolbar-info-button: #0e90d2\ntoolbar-edit-button: rgb(243, 123, 29)\ntoolbar-close-button: #dd514c\ntoolbar-delete-button: #dd514c\ntoolbar-cancel-button: rgb(243, 123, 29)\ntoolbar-done-button: #5eb95e\nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/Muted": {
            "title": "$:/palettes/Muted",
            "name": "Muted",
            "description": "Bright tiddlers on a muted background",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #bbb\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #6f6f70\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #29a6ee\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #c2c1c2\nsidebar-foreground-shadow: rgba(255,255,255,0)\nsidebar-foreground: #d3d2d4\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #6f6f70\nsidebar-tab-background: #666667\nsidebar-tab-border-selected: #999\nsidebar-tab-border: #515151\nsidebar-tab-divider: #999\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: #999\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #d1d0d2\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #d5ad34\ntag-foreground: #ffffff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #182955\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/ContrastLight": {
            "title": "$:/palettes/ContrastLight",
            "name": "Contrast (Light)",
            "description": "High contrast and unambiguous (light version)",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #f00\nalert-border: <<colour background>>\nalert-highlight: <<colour foreground>>\nalert-muted-foreground: #800\nbackground: #fff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: <<colour background>>\nbutton-foreground: <<colour foreground>>\nbutton-border: <<colour foreground>>\ncode-background: <<colour background>>\ncode-border: <<colour foreground>>\ncode-foreground: <<colour foreground>>\ndirty-indicator: #f00\ndownload-background: #080\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: <<colour foreground>>\ndropdown-tab-background: <<colour foreground>>\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #00a\nexternal-link-foreground: #00e\nforeground: #000\nmessage-background: <<colour foreground>>\nmessage-border: <<colour background>>\nmessage-foreground: <<colour background>>\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: <<colour foreground>>\nmodal-footer-background: <<colour background>>\nmodal-footer-border: <<colour foreground>>\nmodal-header-border: <<colour foreground>>\nmuted-foreground: <<colour foreground>>\nnotification-background: <<colour background>>\nnotification-border: <<colour foreground>>\npage-background: <<colour background>>\npre-background: <<colour background>>\npre-border: <<colour foreground>>\nprimary: #00f\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: <<colour background>>\nsidebar-controls-foreground: <<colour foreground>>\nsidebar-foreground-shadow: rgba(0,0,0, 0)\nsidebar-foreground: <<colour foreground>>\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: <<colour foreground>>\nsidebar-tab-background-selected: <<colour background>>\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: <<colour foreground>>\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: <<colour foreground>>\nsidebar-tiddler-link-foreground: <<colour primary>>\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: <<colour foreground>>\ntab-border-selected: <<colour foreground>>\ntab-border: <<colour foreground>>\ntab-divider: <<colour foreground>>\ntab-foreground-selected: <<colour foreground>>\ntab-foreground: <<colour background>>\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #000\ntag-foreground: #fff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour foreground>>\ntiddler-controls-foreground-hover: #ddd\ntiddler-controls-foreground-selected: #fdd\ntiddler-controls-foreground: <<colour foreground>>\ntiddler-editor-background: <<colour background>>\ntiddler-editor-border-image: <<colour foreground>>\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: <<colour background>>\ntiddler-editor-fields-odd: <<colour background>>\ntiddler-info-background: <<colour background>>\ntiddler-info-border: <<colour foreground>>\ntiddler-info-tab-background: <<colour background>>\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: <<colour foreground>>\ntiddler-title-foreground: <<colour foreground>>\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: <<colour foreground>>\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/ContrastDark": {
            "title": "$:/palettes/ContrastDark",
            "name": "Contrast (Dark)",
            "description": "High contrast and unambiguous (dark version)",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #f00\nalert-border: <<colour background>>\nalert-highlight: <<colour foreground>>\nalert-muted-foreground: #800\nbackground: #000\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: <<colour background>>\nbutton-foreground: <<colour foreground>>\nbutton-border: <<colour foreground>>\ncode-background: <<colour background>>\ncode-border: <<colour foreground>>\ncode-foreground: <<colour foreground>>\ndirty-indicator: #f00\ndownload-background: #080\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: <<colour foreground>>\ndropdown-tab-background: <<colour foreground>>\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #00a\nexternal-link-foreground: #00e\nforeground: #fff\nmessage-background: <<colour foreground>>\nmessage-border: <<colour background>>\nmessage-foreground: <<colour background>>\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: <<colour foreground>>\nmodal-footer-background: <<colour background>>\nmodal-footer-border: <<colour foreground>>\nmodal-header-border: <<colour foreground>>\nmuted-foreground: <<colour foreground>>\nnotification-background: <<colour background>>\nnotification-border: <<colour foreground>>\npage-background: <<colour background>>\npre-background: <<colour background>>\npre-border: <<colour foreground>>\nprimary: #00f\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: <<colour background>>\nsidebar-controls-foreground: <<colour foreground>>\nsidebar-foreground-shadow: rgba(0,0,0, 0)\nsidebar-foreground: <<colour foreground>>\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: <<colour foreground>>\nsidebar-tab-background-selected: <<colour background>>\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: <<colour foreground>>\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: <<colour foreground>>\nsidebar-tiddler-link-foreground: <<colour primary>>\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: <<colour foreground>>\ntab-border-selected: <<colour foreground>>\ntab-border: <<colour foreground>>\ntab-divider: <<colour foreground>>\ntab-foreground-selected: <<colour foreground>>\ntab-foreground: <<colour background>>\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #fff\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: <<colour foreground>>\ntiddler-controls-foreground-hover: #ddd\ntiddler-controls-foreground-selected: #fdd\ntiddler-controls-foreground: <<colour foreground>>\ntiddler-editor-background: <<colour background>>\ntiddler-editor-border-image: <<colour foreground>>\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: <<colour background>>\ntiddler-editor-fields-odd: <<colour background>>\ntiddler-info-background: <<colour background>>\ntiddler-info-border: <<colour foreground>>\ntiddler-info-tab-background: <<colour background>>\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: <<colour foreground>>\ntiddler-title-foreground: <<colour foreground>>\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: <<colour foreground>>\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/DarkPhotos": {
            "title": "$:/palettes/DarkPhotos",
            "created": "20150402111612188",
            "description": "Good with dark photo backgrounds",
            "modified": "20150402112344080",
            "name": "DarkPhotos",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: \nbutton-foreground: \nbutton-border: \ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #ddd\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #336438\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #5778d8\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #ccf\nsidebar-controls-foreground: #fff\nsidebar-foreground-shadow: rgba(0,0,0, 0.5)\nsidebar-foreground: #fff\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #eee\nsidebar-tab-background-selected: rgba(255,255,255, 0.8)\nsidebar-tab-background: rgba(255,255,255, 0.4)\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: rgba(255,255,255, 0.2)\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #aaf\nsidebar-tiddler-link-foreground: #ddf\nsite-title-foreground: #fff\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ec6\ntag-foreground: #ffffff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #182955\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/GruvboxDark": {
            "title": "$:/palettes/GruvboxDark",
            "name": "Gruvbox Dark",
            "description": "Retro groove color scheme",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "license": "https://github.com/morhetz/gruvbox",
            "text": "alert-background: #cc241d\nalert-border: #cc241d\nalert-highlight: #d79921\nalert-muted-foreground: #504945\nbackground: #3c3836\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: #504945\nbutton-foreground: #fbf1c7\nbutton-border: transparent\ncode-background: #504945\ncode-border: #504945\ncode-foreground: #fb4934\ndiff-delete-background: #fb4934\ndiff-delete-foreground: <<colour foreground>>\ndiff-equal-background: \ndiff-equal-foreground: <<colour foreground>>\ndiff-insert-background: #b8bb26\ndiff-insert-foreground: <<colour foreground>>\ndiff-invisible-background: \ndiff-invisible-foreground: <<colour muted-foreground>>\ndirty-indicator: #fb4934\ndownload-background: #b8bb26\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: #665c54\ndropdown-border: <<colour background>>\ndropdown-tab-background-selected: #ebdbb2\ndropdown-tab-background: #665c54\ndropzone-background: #98971a\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #d3869b\nexternal-link-foreground: #8ec07c\nforeground: #fbf1c7\nmenubar-background: #504945\nmenubar-foreground: <<colour foreground>>\nmessage-background: #83a598\nmessage-border: #83a598\nmessage-foreground: #3c3836\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #504945\nmodal-footer-background: #3c3836\nmodal-footer-border: #3c3836\nmodal-header-border: #3c3836\nmuted-foreground: #d5c4a1\nnotification-background: <<colour primary>>\nnotification-border: <<colour primary>>\npage-background: #282828\npre-background: #504945\npre-border: #504945\nprimary: #d79921\nselect-tag-background: #665c54\nselect-tag-foreground: <<colour foreground>>\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #7c6f64\nsidebar-controls-foreground: #504945\nsidebar-foreground-shadow: transparent\nsidebar-foreground: #fbf1c7\nsidebar-muted-foreground-hover: #7c6f64\nsidebar-muted-foreground: #504945\nsidebar-tab-background-selected: #bdae93\nsidebar-tab-background: #3c3836\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: #bdae93\nsidebar-tab-divider: <<colour page-background>>\nsidebar-tab-foreground-selected: #282828\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #458588\nsidebar-tiddler-link-foreground: #98971a\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #B48EAD\ntab-background-selected: #ebdbb2\ntab-background: #665c54\ntab-border-selected: #665c54\ntab-border: #665c54\ntab-divider: #bdae93\ntab-foreground-selected: #282828\ntab-foreground: #ebdbb2\ntable-border: #7c6f64\ntable-footer-background: #665c54\ntable-header-background: #504945\ntag-background: #d3869b\ntag-foreground: #282828\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #7c6f64\ntiddler-controls-foreground-selected: #7c6f64\ntiddler-controls-foreground: #665c54\ntiddler-editor-background: #282828\ntiddler-editor-border-image: #282828\ntiddler-editor-border: #282828\ntiddler-editor-fields-even: #504945\ntiddler-editor-fields-odd: #7c6f64\ntiddler-info-background: #32302f\ntiddler-info-border: #ebdbb2\ntiddler-info-tab-background: #ebdbb2\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #7c6f64\ntiddler-title-foreground: #a89984\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #504945\nvery-muted-foreground: #bdae93\nwikilist-background: <<colour page-background>>\nwikilist-button-background: <<colour button-background>>\nwikilist-button-foreground: <<colour button-foreground>>\nwikilist-item: <<colour background>>\nwikilist-toolbar-background: <<colour background>>\nwikilist-toolbar-foreground: <<colour foreground>>\nwikilist-title: <<colour foreground>>\nwikilist-title-svg: <<colour wikilist-title>>\nwikilist-url: <<colour muted-foreground>>\nwikilist-button-open-hover: <<colour primary>>\nwikilist-button-open: <<colour dropzone-background>>\nwikilist-button-remove: <<colour dirty-indicator>>\nwikilist-button-remove-hover: <<colour alert-background>>\nwikilist-droplink-dragover: <<colour dropzone-background>>\nwikilist-button-reveal: <<colour sidebar-tiddler-link-foreground-hover>>\nwikilist-button-reveal-hover: <<colour message-background>>"
        },
        "$:/palettes/Nord": {
            "title": "$:/palettes/Nord",
            "name": "Nord",
            "description": "An arctic, north-bluish color palette.",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "license": "MIT, arcticicestudio, https://github.com/arcticicestudio/nord/blob/develop/LICENSE.md",
            "text": "alert-background: #D08770\nalert-border: #D08770\nalert-highlight: #B48EAD\nalert-muted-foreground: #4C566A\nbackground: #3b4252\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: #4C566A\nbutton-foreground: #D8DEE9\nbutton-border: transparent\ncode-background: #2E3440\ncode-border: #2E3440\ncode-foreground: #BF616A\ndiff-delete-background: #BF616A\ndiff-delete-foreground: <<colour foreground>>\ndiff-equal-background: \ndiff-equal-foreground: <<colour foreground>>\ndiff-insert-background: #A3BE8C\ndiff-insert-foreground: <<colour foreground>>\ndiff-invisible-background: \ndiff-invisible-foreground: <<colour muted-foreground>>\ndirty-indicator: #BF616A\ndownload-background: #A3BE8C\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour background>>\ndropdown-tab-background-selected: #ECEFF4\ndropdown-tab-background: #4C566A\ndropzone-background: #A3BE8C\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #5E81AC\nexternal-link-foreground: #8FBCBB\nforeground: #d8dee9\nmenubar-background: #2E3440\nmenubar-foreground: #d8dee9\nmessage-background: #2E3440\nmessage-border: #2E3440\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #3b4252\nmodal-footer-background: #3b4252\nmodal-footer-border: #3b4252\nmodal-header-border: #3b4252\nmuted-foreground: #4C566A\nnotification-background: <<colour primary>>\nnotification-border: #EBCB8B\npage-background: #2e3440\npre-background: #2E3440\npre-border: #2E3440\nprimary: #5E81AC\nselect-tag-background: #3b4252\nselect-tag-foreground: <<colour foreground>>\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #D8DEE9\nsidebar-controls-foreground: #4C566A\nsidebar-foreground-shadow: transparent\nsidebar-foreground: #D8DEE9\nsidebar-muted-foreground-hover: #4C566A\nsidebar-muted-foreground: #4C566A\nsidebar-tab-background-selected: #ECEFF4\nsidebar-tab-background: #4C566A\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: #4C566A\nsidebar-tab-divider: <<colour page-background>>\nsidebar-tab-foreground-selected: #4C566A\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #A3BE8C\nsidebar-tiddler-link-foreground: #81A1C1\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #B48EAD\ntab-background-selected: #ECEFF4\ntab-background: #4C566A\ntab-border-selected: #4C566A\ntab-border: #4C566A\ntab-divider: #4C566A\ntab-foreground-selected: #4C566A\ntab-foreground: #D8DEE9\ntable-border: #4C566A\ntable-footer-background: #2e3440\ntable-header-background: #2e3440\ntag-background: #A3BE8C\ntag-foreground: #4C566A\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: \ntiddler-controls-foreground-selected: #EBCB8B\ntiddler-controls-foreground: #4C566A\ntiddler-editor-background: #2e3440\ntiddler-editor-border-image: #2e3440\ntiddler-editor-border: #2e3440\ntiddler-editor-fields-even: #2e3440\ntiddler-editor-fields-odd: #2e3440\ntiddler-info-background: #2e3440\ntiddler-info-border: #2e3440\ntiddler-info-tab-background: #2e3440\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #4C566A\ntiddler-title-foreground: #81A1C1\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #2d3038\nvery-muted-foreground: #2d3038\n"
        },
        "$:/palettes/Rocker": {
            "title": "$:/palettes/Rocker",
            "name": "Rocker",
            "description": "A dark theme",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #999999\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #000\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #cc0000\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #ffffff\nsidebar-foreground-shadow: rgba(255,255,255, 0.0)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #000\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #ffbb99\nsidebar-tiddler-link-foreground: #cc0000\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ffbb99\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #cc0000\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/SolarFlare": {
            "title": "$:/palettes/SolarFlare",
            "name": "Solar Flare",
            "description": "Warm, relaxing earth colours",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": ": Background Tones\n\nbase03: #002b36\nbase02: #073642\n\n: Content Tones\n\nbase01: #586e75\nbase00: #657b83\nbase0: #839496\nbase1: #93a1a1\n\n: Background Tones\n\nbase2: #eee8d5\nbase3: #fdf6e3\n\n: Accent Colors\n\nyellow: #b58900\norange: #cb4b16\nred: #dc322f\nmagenta: #d33682\nviolet: #6c71c4\nblue: #268bd2\ncyan: #2aa198\ngreen: #859900\n\n: Additional Tones (RA)\n\nbase10: #c0c4bb\nviolet-muted: #7c81b0\nblue-muted: #4e7baa\n\nyellow-hot: #ffcc44\norange-hot: #eb6d20\nred-hot: #ff2222\nblue-hot: #2298ee\ngreen-hot: #98ee22\n\n: Palette\n\n: Do not use colour macro for background and foreground\nbackground: #fdf6e3\n    download-foreground: <<colour background>>\n    dragger-foreground: <<colour background>>\n    dropdown-background: <<colour background>>\n    modal-background: <<colour background>>\n    sidebar-foreground-shadow: <<colour background>>\n    tiddler-background: <<colour background>>\n    tiddler-border: <<colour background>>\n    tiddler-link-background: <<colour background>>\n    tab-background-selected: <<colour background>>\n        dropdown-tab-background-selected: <<colour tab-background-selected>>\nforeground: #657b83\n    dragger-background: <<colour foreground>>\n    tab-foreground: <<colour foreground>>\n        tab-foreground-selected: <<colour tab-foreground>>\n            sidebar-tab-foreground-selected: <<colour tab-foreground-selected>>\n        sidebar-tab-foreground: <<colour tab-foreground>>\n    sidebar-button-foreground: <<colour foreground>>\n    sidebar-controls-foreground: <<colour foreground>>\n    sidebar-foreground: <<colour foreground>>\n: base03\n: base02\n: base01\n    alert-muted-foreground: <<colour base01>>\n: base00\n    code-foreground: <<colour base00>>\n    message-foreground: <<colour base00>>\n    tag-foreground: <<colour base00>>\n: base0\n    sidebar-tiddler-link-foreground: <<colour base0>>\n: base1\n    muted-foreground: <<colour base1>>\n        blockquote-bar: <<colour muted-foreground>>\n        dropdown-border: <<colour muted-foreground>>\n        sidebar-muted-foreground: <<colour muted-foreground>>\n        tiddler-title-foreground: <<colour muted-foreground>>\n            site-title-foreground: <<colour tiddler-title-foreground>>\n: base2\n    modal-footer-background: <<colour base2>>\n    page-background: <<colour base2>>\n        modal-backdrop: <<colour page-background>>\n        notification-background: <<colour page-background>>\n        code-background: <<colour page-background>>\n            code-border: <<colour code-background>>\n        pre-background: <<colour page-background>>\n            pre-border: <<colour pre-background>>\n        sidebar-tab-background-selected: <<colour page-background>>\n    table-header-background: <<colour base2>>\n    tag-background: <<colour base2>>\n    tiddler-editor-background: <<colour base2>>\n    tiddler-info-background: <<colour base2>>\n    tiddler-info-tab-background: <<colour base2>>\n    tab-background: <<colour base2>>\n        dropdown-tab-background: <<colour tab-background>>\n: base3\n    alert-background: <<colour base3>>\n    message-background: <<colour base3>>\n: yellow\n: orange\n: red\n: magenta\n    alert-highlight: <<colour magenta>>\n: violet\n    external-link-foreground: <<colour violet>>\n: blue\n: cyan\n: green\n: base10\n    tiddler-controls-foreground: <<colour base10>>\n: violet-muted\n    external-link-foreground-visited: <<colour violet-muted>>\n: blue-muted\n    primary: <<colour blue-muted>>\n        download-background: <<colour primary>>\n        tiddler-link-foreground: <<colour primary>>\n\nalert-border: #b99e2f\ndirty-indicator: #ff0000\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nmessage-border: #cfd6e6\nmodal-border: #999999\nselect-tag-background:\nselect-tag-foreground:\nsidebar-controls-foreground-hover:\nsidebar-muted-foreground-hover:\nsidebar-tab-background: #ded8c5\nsidebar-tiddler-link-foreground-hover:\nstatic-alert-foreground: #aaaaaa\ntab-border: #cccccc\n    modal-footer-border: <<colour tab-border>>\n    modal-header-border: <<colour tab-border>>\n    notification-border: <<colour tab-border>>\n    sidebar-tab-border: <<colour tab-border>>\n    tab-border-selected: <<colour tab-border>>\n        sidebar-tab-border-selected: <<colour tab-border-selected>>\ntab-divider: #d8d8d8\n    sidebar-tab-divider: <<colour tab-divider>>\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-border: #dddddd\ntiddler-subtitle-foreground: #c0c0c0\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\n"
        },
        "$:/palettes/SolarizedLight": {
            "title": "$:/palettes/SolarizedLight",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "description": "Precision colors for machines and people",
            "license": "MIT, Ethan Schoonover, https://github.com/altercation/solarized/blob/master/LICENSE",
            "name": "SolarizedLight",
            "text": "alert-background: #eee8d5\nalert-border: #073642\nalert-highlight: #cb4b16\nalert-muted-foreground: #586e75\nbackground: #fdf6e3\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: #cb4b16\nbutton-foreground: #fdf6e3\nbutton-border: transparent\ncode-background: #eee8d5\ncode-border: #93a1a1\ncode-foreground: #d33682\ndiff-delete-background: #BF616A\ndiff-delete-foreground: <<colour foreground>>\ndiff-equal-background: \ndiff-equal-foreground: <<colour foreground>>\ndiff-insert-background: #859900\ndiff-insert-foreground: <<colour foreground>>\ndiff-invisible-background: \ndiff-invisible-foreground: <<colour muted-foreground>>\ndirty-indicator: #D08770\ndownload-background: #859900\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour background>>\ndropdown-tab-background-selected: #fdf6e3\ndropdown-tab-background: #93a1a1\ndropzone-background: #859900\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: #d33682\nexternal-link-foreground-visited: #b58900\nexternal-link-foreground: #cb4b16\nforeground: #839496\nmessage-background: #586e75\nmessage-border: #586e75\nmessage-foreground: #eee8d5\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #eee8d5\nmodal-footer-background: #eee8d5\nmodal-footer-border: #eee8d5\nmodal-header-border: #eee8d5\nmuted-foreground: #93a1a1\nnotification-background: #EBCB8B\nnotification-border: #D08770\npage-background: #eee8d5\npre-background: #eee8d5\npre-border: #93a1a1\nprimary: #2aa198\nselect-tag-background: #eee8d5\nselect-tag-foreground: <<colour foreground>>\nsidebar-button-foreground: #eee8d5\nsidebar-controls-foreground-hover: #268bd2\nsidebar-controls-foreground: #586e75\nsidebar-foreground-shadow: transparent\nsidebar-foreground: #839496\nsidebar-muted-foreground-hover: #657b83\nsidebar-muted-foreground: #93a1a1\nsidebar-tab-background-selected: #eee8d5\nsidebar-tab-background: #839496\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: #657b83\nsidebar-tab-divider: <<colour page-background>>\nsidebar-tab-foreground-selected: #839496\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #859900\nsidebar-tiddler-link-foreground: #268bd2\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #dc322f\ntab-background-selected: #fdf6e3\ntab-background: #839496\ntab-border-selected: #93a1a1\ntab-border: #93a1a1\ntab-divider: #fdf6e3\ntab-foreground-selected: #839496\ntab-foreground: #eee8d5\ntable-border: #657b83\ntable-footer-background: #657b83\ntable-header-background: #93a1a1\ntag-background: #6c71c4\ntag-foreground: #eee8d5\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #b58900\ntiddler-controls-foreground-selected: #b58900\ntiddler-controls-foreground: #073642\ntiddler-editor-background: #eee8d5\ntiddler-editor-border-image: #eee8d5\ntiddler-editor-border: #eee8d5\ntiddler-editor-fields-even: #eee8d5\ntiddler-editor-fields-odd: #fdf6e3\ntiddler-info-background: #eee8d5\ntiddler-info-border: #eee8d5\ntiddler-info-tab-background: #586e75\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #586e75\ntiddler-title-foreground: #073642\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #839496\nvery-muted-foreground: #93a1a1\n"
        },
        "$:/palettes/SpartanDay": {
            "title": "$:/palettes/SpartanDay",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "description": "Cold, spartan day colors",
            "name": "Spartan Day",
            "text": "alert-background: <<colour background>>\nalert-border: <<colour very-muted-foreground>>\nalert-highlight: <<colour very-muted-foreground>>\nalert-muted-foreground: <<colour muted-foreground>>\nbackground: #FAFAFA\nblockquote-bar: <<colour page-background>>\nbutton-background: transparent\nbutton-foreground: inherit\nbutton-border: <<colour tag-background>>\ncode-background: #ececec\ncode-border: #ececec\ncode-foreground: \ndirty-indicator: #c80000\ndownload-background: <<colour primary>>\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: #FFFFFF\ndropdown-border: <<colour dropdown-background>>\ndropdown-tab-background-selected: <<colour dropdown-background>>\ndropdown-tab-background: #F5F5F5\ndropzone-background: <<colour tag-background>>\nexternal-link-background-hover: transparent\nexternal-link-background-visited: transparent\nexternal-link-background: transparent\nexternal-link-foreground-hover: \nexternal-link-foreground-visited: \nexternal-link-foreground: \nforeground: rgba(0, 0, 0, 0.87)\nmessage-background: <<colour background>>\nmessage-border: <<colour very-muted-foreground>>\nmessage-foreground: rgba(0, 0, 0, 0.54)\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: <<colour very-muted-foreground>>\nmodal-footer-background: <<colour background>>\nmodal-footer-border: <<colour very-muted-foreground>>\nmodal-header-border: <<colour very-muted-foreground>>\nmuted-foreground: rgba(0, 0, 0, 0.54)\nnotification-background: <<colour dropdown-background>>\nnotification-border: <<colour dropdown-background>>\npage-background: #f4f4f4\npre-background: #ececec\npre-border: #ececec\nprimary: #3949ab\nselect-tag-background: <<colour background>>\nselect-tag-foreground: <<colour foreground>>\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #aeaeae\nsidebar-controls-foreground: #c6c6c6\nsidebar-foreground-shadow: transparent\nsidebar-foreground: rgba(0, 0, 0, 0.54)\nsidebar-muted-foreground-hover: rgba(0, 0, 0, 0.54)\nsidebar-muted-foreground: rgba(0, 0, 0, 0.38)\nsidebar-tab-background-selected: <<colour page-background>>\nsidebar-tab-background: transparent\nsidebar-tab-border-selected: <<colour table-border>>\nsidebar-tab-border: transparent\nsidebar-tab-divider: <<colour table-border>>\nsidebar-tab-foreground-selected: rgba(0, 0, 0, 0.87)\nsidebar-tab-foreground: rgba(0, 0, 0, 0.54)\nsidebar-tiddler-link-foreground-hover: rgba(0, 0, 0, 0.87)\nsidebar-tiddler-link-foreground: rgba(0, 0, 0, 0.54)\nsite-title-foreground: rgba(0, 0, 0, 0.87)\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: transparent\ntab-border-selected: <<colour table-border>>\ntab-border: transparent\ntab-divider: <<colour table-border>>\ntab-foreground-selected: rgba(0, 0, 0, 0.87)\ntab-foreground: rgba(0, 0, 0, 0.54)\ntable-border: #d8d8d8\ntable-footer-background: <<colour tiddler-editor-fields-odd>>\ntable-header-background: <<colour tiddler-editor-fields-even>>\ntag-background: #ec6\ntag-foreground: <<colour button-foreground>>\ntiddler-background: <<colour background>>\ntiddler-border: #f9f9f9\ntiddler-controls-foreground-hover: <<colour sidebar-controls-foreground-hover>>\ntiddler-controls-foreground-selected: <<colour sidebar-controls-foreground-hover>>\ntiddler-controls-foreground: <<colour sidebar-controls-foreground>>\ntiddler-editor-background: transparent\ntiddler-editor-border-image: \ntiddler-editor-border: #e8e7e7\ntiddler-editor-fields-even: rgba(0, 0, 0, 0.1)\ntiddler-editor-fields-odd: rgba(0, 0, 0, 0.04)\ntiddler-info-background: #F5F5F5\ntiddler-info-border: #F5F5F5\ntiddler-info-tab-background: <<colour tiddler-editor-fields-odd>>\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: <<colour muted-foreground>>\ntiddler-title-foreground: #000000\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: <<colour very-muted-foreground>>\nvery-muted-foreground: rgba(0, 0, 0, 0.12)\n"
        },
        "$:/palettes/SpartanNight": {
            "title": "$:/palettes/SpartanNight",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "description": "Dark spartan colors",
            "name": "Spartan Night",
            "text": "alert-background: <<colour background>>\nalert-border: <<colour very-muted-foreground>>\nalert-highlight: <<colour very-muted-foreground>>\nalert-muted-foreground: <<colour muted-foreground>>\nbackground: #303030\nblockquote-bar: <<colour page-background>>\nbutton-background: transparent\nbutton-foreground: inherit\nbutton-border: <<colour tag-background>>\ncode-background: <<colour pre-background>>\ncode-border: <<colour pre-border>>\ncode-foreground: rgba(255, 255, 255, 0.54)\ndirty-indicator: #c80000\ndownload-background: <<colour primary>>\ndownload-foreground: <<colour foreground>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: #424242\ndropdown-border: <<colour dropdown-background>>\ndropdown-tab-background-selected: <<colour dropdown-background>>\ndropdown-tab-background: #050505\ndropzone-background: <<colour tag-background>>\nexternal-link-background-hover: transparent\nexternal-link-background-visited: transparent\nexternal-link-background: transparent\nexternal-link-foreground-hover: \nexternal-link-foreground-visited: #7c318c\nexternal-link-foreground: #9e3eb3\nforeground: rgba(255, 255, 255, 0.7)\nmessage-background: <<colour background>>\nmessage-border: <<colour very-muted-foreground>>\nmessage-foreground: rgba(255, 255, 255, 0.54)\nmodal-backdrop: <<colour page-background>>\nmodal-background: <<colour background>>\nmodal-border: <<colour very-muted-foreground>>\nmodal-footer-background: <<colour background>>\nmodal-footer-border: <<colour background>>\nmodal-header-border: <<colour very-muted-foreground>>\nmuted-foreground: rgba(255, 255, 255, 0.54)\nnotification-background: <<colour dropdown-background>>\nnotification-border: <<colour dropdown-background>>\npage-background: #212121\npre-background: #2a2a2a\npre-border: transparent\nprimary: #5656f3\nselect-tag-background: <<colour background>>\nselect-tag-foreground: <<colour foreground>>\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #494949\nsidebar-controls-foreground: #5d5d5d\nsidebar-foreground-shadow: transparent\nsidebar-foreground: rgba(255, 255, 255, 0.54)\nsidebar-muted-foreground-hover: rgba(255, 255, 255, 0.54)\nsidebar-muted-foreground: rgba(255, 255, 255, 0.38)\nsidebar-tab-background-selected: <<colour page-background>>\nsidebar-tab-background: transparent\nsidebar-tab-border-selected: <<colour table-border>>\nsidebar-tab-border: transparent\nsidebar-tab-divider: <<colour table-border>>\nsidebar-tab-foreground-selected: rgba(255, 255, 255, 0.87)\nsidebar-tab-foreground: rgba(255, 255, 255, 0.54)\nsidebar-tiddler-link-foreground-hover: rgba(255, 255, 255, 0.7)\nsidebar-tiddler-link-foreground: rgba(255, 255, 255, 0.54)\nsite-title-foreground: rgba(255, 255, 255, 0.7)\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: transparent\ntab-border-selected: <<colour table-border>>\ntab-border: transparent\ntab-divider: <<colour table-border>>\ntab-foreground-selected: rgba(255, 255, 255, 0.87)\ntab-foreground: rgba(255, 255, 255, 0.54)\ntable-border: #3a3a3a\ntable-footer-background: <<colour tiddler-editor-fields-odd>>\ntable-header-background: <<colour tiddler-editor-fields-even>>\ntag-background: #ec6\ntag-foreground: <<colour button-foreground>>\ntiddler-background: <<colour background>>\ntiddler-border: rgb(55,55,55)\ntiddler-controls-foreground-hover: <<colour sidebar-controls-foreground-hover>>\ntiddler-controls-foreground-selected: <<colour sidebar-controls-foreground-hover>>\ntiddler-controls-foreground: <<colour sidebar-controls-foreground>>\ntiddler-editor-background: transparent\ntiddler-editor-border-image: \ntiddler-editor-border: rgba(255, 255, 255, 0.08)\ntiddler-editor-fields-even: rgba(255, 255, 255, 0.1)\ntiddler-editor-fields-odd: rgba(255, 255, 255, 0.04)\ntiddler-info-background: #454545\ntiddler-info-border: #454545\ntiddler-info-tab-background: <<colour tiddler-editor-fields-odd>>\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: <<colour muted-foreground>>\ntiddler-title-foreground: #FFFFFF\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: <<colour very-muted-foreground>>\nvery-muted-foreground: rgba(255, 255, 255, 0.12)\n"
        },
        "$:/palettes/Twilight": {
            "title": "$:/palettes/Twilight",
            "tags": "$:/tags/Palette",
            "author": "Thomas Elmiger",
            "type": "application/x-tiddler-dictionary",
            "name": "Twilight",
            "description": "Delightful, soft darkness.",
            "text": "alert-background: rgb(255, 255, 102)\nalert-border: rgb(232, 232, 125)\nalert-highlight: rgb(255, 51, 51)\nalert-muted-foreground: rgb(224, 82, 82)\nbackground: rgb(38, 38, 38)\nblockquote-bar: rgba(240, 196, 117, 0.7)\nbutton-background: rgb(63, 63, 63)\nbutton-border: rgb(127, 127, 127)\nbutton-foreground: rgb(179, 179, 179)\ncode-background: rgba(0,0,0,0.03)\ncode-border: rgba(0,0,0,0.08)\ncode-foreground: rgb(255, 94, 94)\ndiff-delete-background: #ffc9c9\ndiff-delete-foreground: <<colour foreground>>\ndiff-equal-background: \ndiff-equal-foreground: <<colour foreground>>\ndiff-insert-background: #aaefad\ndiff-insert-foreground: <<colour foreground>>\ndiff-invisible-background: \ndiff-invisible-foreground: <<colour muted-foreground>>\ndirty-indicator: rgb(255, 94, 94)\ndownload-background: #19a974\ndownload-foreground: rgb(38, 38, 38)\ndragger-background: rgb(179, 179, 179)\ndragger-foreground: rgb(38, 38, 38)\ndropdown-background: rgb(38, 38, 38)\ndropdown-border: rgb(255, 255, 255)\ndropdown-tab-background: rgba(0,0,0,.1)\ndropdown-tab-background-selected: rgba(255,255,255,1)\ndropzone-background: #9eebcf\nexternal-link-background: inherit\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-foreground: rgb(179, 179, 255)\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: rgb(153, 153, 255)\nforeground: rgb(179, 179, 179)\nmessage-background: <<colour tag-foreground>>\nmessage-border: #96ccff\nmessage-foreground: <<colour tag-background>>\nmodal-backdrop: rgb(179, 179, 179)\nmodal-background: rgb(38, 38, 38)\nmodal-border: rgba(0,0,0,.5)\nmodal-footer-background: #f4f4f4\nmodal-footer-border: rgba(0,0,0,.1)\nmodal-header-border: rgba(0,0,0,.2)\nmuted-foreground: rgb(255, 255, 255)\nnotification-background: <<colour tag-foreground>>\nnotification-border: <<colour tag-background>>\npage-background: rgb(26, 26, 26)\npre-background: rgb(25, 25, 25)\npre-border: rgba(0,0,0,.2)\nprimary: rgb(255, 201, 102)\nselect-tag-background: \nselect-tag-foreground: \nsidebar-button-foreground: rgb(179, 179, 179)\nsidebar-controls-foreground: rgb(153, 153, 153)\nsidebar-controls-foreground-hover: <<colour tiddler-controls-foreground-hover>>\nsidebar-foreground: rgb(141, 141, 141)\nsidebar-foreground-shadow: transparent\nsidebar-muted-foreground: rgba(0, 0, 0, 0.5)\nsidebar-muted-foreground-hover: rgb(141, 141, 141)\nsidebar-tab-background: rgba(141, 141, 141, 0.2)\nsidebar-tab-background-selected: rgb(26, 26, 26)\nsidebar-tab-border: rgb(127, 127, 127)\nsidebar-tab-border-selected: rgb(127, 127, 127)\nsidebar-tab-divider: rgb(127, 127, 127)\nsidebar-tab-foreground: rgb(179, 179, 179)\nsidebar-tab-foreground-selected: rgb(179, 179, 179)\nsidebar-tiddler-link-foreground: rgb(179, 179, 179)\nsidebar-tiddler-link-foreground-hover: rgb(115, 115, 115)\nsite-title-foreground: rgb(255, 201, 102)\nstatic-alert-foreground: rgba(0,0,0,.3)\ntab-background: rgba(0,0,0,0.125)\ntab-background-selected: rgb(38, 38, 38)\ntab-border: rgb(255, 201, 102)\ntab-border-selected: rgb(255, 201, 102)\ntab-divider: rgb(255, 201, 102)\ntab-foreground: rgb(179, 179, 179)\ntab-foreground-selected: rgb(179, 179, 179)\ntable-border: rgba(255,255,255,.3)\ntable-footer-background: rgba(0,0,0,.4)\ntable-header-background: rgba(0,0,0,.1)\ntag-background: rgb(255, 201, 102)\ntag-foreground: rgb(25, 25, 25)\ntiddler-background: rgb(38, 38, 38)\ntiddler-border: rgba(240, 196, 117, 0.7)\ntiddler-controls-foreground: rgb(128, 128, 128)\ntiddler-controls-foreground-hover: rgba(255, 255, 255, 0.8)\ntiddler-controls-foreground-selected: rgba(255, 255, 255, 0.9)\ntiddler-editor-background: rgb(33, 33, 33)\ntiddler-editor-border: rgb(63, 63, 63)\ntiddler-editor-border-image: rgb(25, 25, 25)\ntiddler-editor-fields-even: rgb(33, 33, 33)\ntiddler-editor-fields-odd: rgb(28, 28, 28)\ntiddler-info-background: rgb(43, 43, 43)\ntiddler-info-border: rgb(25, 25, 25)\ntiddler-info-tab-background: rgb(43, 43, 43)\ntiddler-link-background: rgb(38, 38, 38)\ntiddler-link-foreground: rgb(204, 204, 255)\ntiddler-subtitle-foreground: rgb(255, 255, 255)\ntiddler-title-foreground: rgb(255, 192, 76)\ntoolbar-cancel-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-done-button: \ntoolbar-edit-button: \ntoolbar-info-button: \ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \nuntagged-background: rgb(255, 255, 255)\nvery-muted-foreground: rgba(240, 196, 117, 0.7)\n"
        },
        "$:/palettes/Vanilla": {
            "title": "$:/palettes/Vanilla",
            "name": "Vanilla",
            "description": "Pale and unobtrusive",
            "tags": "$:/tags/Palette",
            "type": "application/x-tiddler-dictionary",
            "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndiff-delete-background: #ffc9c9\ndiff-delete-foreground: <<colour foreground>>\ndiff-equal-background: \ndiff-equal-foreground: <<colour foreground>>\ndiff-insert-background: #aaefad\ndiff-insert-foreground: <<colour foreground>>\ndiff-invisible-background: \ndiff-invisible-foreground: <<colour muted-foreground>>\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #bbb\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #f4f4f4\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #5778d8\nselect-tag-background:\nselect-tag-foreground:\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #aaaaaa\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #f4f4f4\nsidebar-tab-background: #e0e0e0\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: #e4e4e4\nsidebar-tab-foreground-selected:\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #999999\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ec6\ntag-foreground: #ffffff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #182955\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\nwikilist-background: #e5e5e5\nwikilist-item: #fff\nwikilist-info: #000\nwikilist-title: #666\nwikilist-title-svg: <<colour wikilist-title>>\nwikilist-url: #aaa\nwikilist-button-open: #4fb82b\nwikilist-button-open-hover: green\nwikilist-button-reveal: #5778d8\nwikilist-button-reveal-hover: blue\nwikilist-button-remove: #d85778\nwikilist-button-remove-hover: red\nwikilist-toolbar-background: #d3d3d3\nwikilist-toolbar-foreground: #888\nwikilist-droplink-dragover: rgba(255,192,192,0.5)\nwikilist-button-background: #acacac\nwikilist-button-foreground: #000\n"
        },
        "$:/core/readme": {
            "title": "$:/core/readme",
            "text": "This plugin contains TiddlyWiki's core components, comprising:\n\n* JavaScript code modules\n* Icons\n* Templates needed to create TiddlyWiki's user interface\n* British English (''en-GB'') translations of the localisable strings used by the core\n"
        },
        "$:/library/sjcl.js/license": {
            "title": "$:/library/sjcl.js/license",
            "type": "text/plain",
            "text": "SJCL is open. You can use, modify and redistribute it under a BSD\nlicense or under the GNU GPL, version 2.0.\n\n---------------------------------------------------------------------\n\nhttp://opensource.org/licenses/BSD-2-Clause\n\nCopyright (c) 2009-2015, Emily Stark, Mike Hamburg and Dan Boneh at\nStanford University. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n1. Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright\nnotice, this list of conditions and the following disclaimer in the\ndocumentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\nIS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\nTO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nHOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---------------------------------------------------------------------\n\nhttp://opensource.org/licenses/GPL-2.0\n\nThe Stanford Javascript Crypto Library (hosted here on GitHub) is a\nproject by the Stanford Computer Security Lab to build a secure,\npowerful, fast, small, easy-to-use, cross-browser library for\ncryptography in Javascript.\n\nCopyright (c) 2009-2015, Emily Stark, Mike Hamburg and Dan Boneh at\nStanford University.\n\nThis program is free software; you can redistribute it and/or modify it\nunder the terms of the GNU General Public License as published by the\nFree Software Foundation; either version 2 of the License, or (at your\noption) any later version.\n\nThis program is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\nPublic License for more details.\n\nYou should have received a copy of the GNU General Public License along\nwith this program; if not, write to the Free Software Foundation, Inc.,\n59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"
        },
        "$:/core/templates/MOTW.html": {
            "title": "$:/core/templates/MOTW.html",
            "text": "\\rules only filteredtranscludeinline transcludeinline entity\n<!-- The following comment is called a MOTW comment and is necessary for the TiddlyIE Internet Explorer extension -->\n<!-- saved from url=(0021)https://tiddlywiki.com -->&#13;&#10;"
        },
        "$:/core/templates/alltiddlers.template.html": {
            "title": "$:/core/templates/alltiddlers.template.html",
            "type": "text/vnd.tiddlywiki-html",
            "text": "<!-- This template is provided for backwards compatibility with older versions of TiddlyWiki -->\n\n<$set name=\"exportFilter\" value=\"[!is[system]sort[title]]\">\n\n{{$:/core/templates/exporters/StaticRiver}}\n\n</$set>\n"
        },
        "$:/core/templates/canonical-uri-external-image": {
            "title": "$:/core/templates/canonical-uri-external-image",
            "text": "<!--\n\nThis template is used to assign the ''_canonical_uri'' field to external images.\n\nChange the `./images/` part to a different base URI. The URI can be relative or absolute.\n\n-->\n./images/<$view field=\"title\" format=\"doubleurlencoded\"/>"
        },
        "$:/core/templates/canonical-uri-external-raw": {
            "title": "$:/core/templates/canonical-uri-external-raw",
            "text": "<!--\n\nThis template is used to assign the ''_canonical_uri'' field to external raw files that are stored in the same directory\n\n-->\n<$view field=\"title\" format=\"doubleurlencoded\"/>"
        },
        "$:/core/templates/canonical-uri-external-text": {
            "title": "$:/core/templates/canonical-uri-external-text",
            "text": "<!--\n\nThis template is used to assign the ''_canonical_uri'' field to external text files.\n\nChange the `./text/` part to a different base URI. The URI can be relative or absolute.\n\n-->\n./text/<$view field=\"title\" format=\"doubleurlencoded\"/>.tid"
        },
        "$:/core/templates/css-tiddler": {
            "title": "$:/core/templates/css-tiddler",
            "text": "<!--\n\nThis template is used for saving CSS tiddlers as a style tag with data attributes representing the tiddler fields.\n\n-->`<style`<$fields template=' data-tiddler-$name$=\"$encoded_value$\"'></$fields>` type=\"text/css\">`<$view field=\"text\" format=\"text\" />`</style>`"
        },
        "$:/core/templates/exporters/CsvFile": {
            "title": "$:/core/templates/exporters/CsvFile",
            "tags": "$:/tags/Exporter",
            "description": "{{$:/language/Exporters/CsvFile}}",
            "extension": ".csv",
            "text": "\\define renderContent()\n<$text text=<<csvtiddlers filter:\"\"\"$(exportFilter)$\"\"\" format:\"quoted-comma-sep\">>/>\n\\end\n<<renderContent>>\n"
        },
        "$:/core/templates/exporters/JsonFile": {
            "title": "$:/core/templates/exporters/JsonFile",
            "tags": "$:/tags/Exporter",
            "description": "{{$:/language/Exporters/JsonFile}}",
            "extension": ".json",
            "text": "\\define renderContent()\n<$text text=<<jsontiddlers filter:\"\"\"$(exportFilter)$\"\"\">>/>\n\\end\n<<renderContent>>\n"
        },
        "$:/core/templates/exporters/StaticRiver": {
            "title": "$:/core/templates/exporters/StaticRiver",
            "tags": "$:/tags/Exporter",
            "description": "{{$:/language/Exporters/StaticRiver}}",
            "extension": ".html",
            "text": "\\define tv-wikilink-template() #$uri_encoded$\n\\define tv-config-toolbar-icons() no\n\\define tv-config-toolbar-text() no\n\\define tv-config-toolbar-class() tc-btn-invisible\n\\rules only filteredtranscludeinline transcludeinline\n<!doctype html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"{{$:/core/templates/version}}\" />\n<meta name=\"format-detection\" content=\"telephone=no\">\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<title>{{$:/core/wiki/title}}</title>\n<div id=\"styleArea\">\n{{$:/boot/boot.css||$:/core/templates/css-tiddler}}\n</div>\n<style type=\"text/css\">\n{{$:/core/ui/PageStylesheet||$:/core/templates/wikified-tiddler}}\n</style>\n</head>\n<body class=\"tc-body\">\n{{$:/StaticBanner||$:/core/templates/html-tiddler}}\n<section class=\"tc-story-river\">\n{{$:/core/templates/exporters/StaticRiver/Content||$:/core/templates/html-tiddler}}\n</section>\n</body>\n</html>\n"
        },
        "$:/core/templates/exporters/StaticRiver/Content": {
            "title": "$:/core/templates/exporters/StaticRiver/Content",
            "text": "\\define renderContent()\n{{{ $(exportFilter)$ ||$:/core/templates/static-tiddler}}}\n\\end\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n<<renderContent>>\n"
        },
        "$:/core/templates/exporters/TidFile": {
            "title": "$:/core/templates/exporters/TidFile",
            "tags": "$:/tags/Exporter",
            "description": "{{$:/language/Exporters/TidFile}}",
            "extension": ".tid",
            "text": "\\define renderContent()\n{{{ $(exportFilter)$ +[limit[1]] ||$:/core/templates/tid-tiddler}}}\n\\end\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n<<renderContent>>"
        },
        "$:/core/save/all-external-js": {
            "title": "$:/core/save/all-external-js",
            "text": "\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\\define saveTiddlerFilter()\n[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$\n\\end\n{{$:/core/templates/tiddlywiki5-external-js.html}}\n"
        },
        "$:/core/templates/tiddlywiki5.js": {
            "title": "$:/core/templates/tiddlywiki5.js",
            "text": "\\rules only filteredtranscludeinline transcludeinline codeinline\n\n/*\n{{ $:/core/copyright.txt ||$:/core/templates/plain-text-tiddler}}\n`*/\n`<!--~~ Library modules ~~-->\n{{{ [is[system]type[application/javascript]library[yes]] ||$:/core/templates/plain-text-tiddler}}}\n<!--~~ Boot prefix ~~-->\n{{ $:/boot/bootprefix.js ||$:/core/templates/plain-text-tiddler}}\n<!--~~ Core plugin ~~-->\n{{$:/core/templates/tiddlywiki5.js/tiddlers}}\n<!--~~ Boot kernel ~~-->\n{{ $:/boot/boot.js ||$:/core/templates/plain-text-tiddler}}\n"
        },
        "$:/core/templates/tiddlywiki5.js/tiddlers": {
            "title": "$:/core/templates/tiddlywiki5.js/tiddlers",
            "text": "`\n$tw.preloadTiddlerArray(`<$text text=<<jsontiddlers \"[[$:/core]]\">>/>`);\n$tw.preloadTiddlerArray([{\n\ttitle: \"$:/config/SaveWikiButton/Template\",\n\ttext: \"$:/core/save/all-external-js\"\n}]);\n`\n"
        },
        "$:/core/templates/tiddlywiki5-external-js.html": {
            "title": "$:/core/templates/tiddlywiki5-external-js.html",
            "text": "\\rules only filteredtranscludeinline transcludeinline\n<!doctype html>\n{{$:/core/templates/MOTW.html}}<html lang=\"`<$text text={{{ [{$:/language}get[name]] }}}/>`\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<!--~~ Raw markup for the top of the head section ~~-->\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}}\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge\"/>\n<meta name=\"application-name\" content=\"TiddlyWiki\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"{{$:/core/templates/version}}\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\" />\n<meta name=\"copyright\" content=\"{{$:/core/copyright.txt}}\" />\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<title>{{$:/core/wiki/title}}</title>\n<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->\n\n<!--~~ Raw markup ~~-->\n{{{ [all[shadows+tiddlers]tag[$:/core/wiki/rawmarkup]] [all[shadows+tiddlers]tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}\n</head>\n<body class=\"tc-body\">\n<!--~~ Raw markup for the top of the body section ~~-->\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}}\n<!--~~ Static styles ~~-->\n<div id=\"styleArea\">\n{{$:/boot/boot.css||$:/core/templates/css-tiddler}}\n</div>\n<!--~~ Static content for Google and browsers without JavaScript ~~-->\n<noscript>\n<div id=\"splashArea\">\n{{$:/core/templates/static.area}}\n</div>\n</noscript>\n<!--~~ Ordinary tiddlers ~~-->\n{{$:/core/templates/store.area.template.html}}\n<!--~~ Raw markup for the bottom of the body section ~~-->\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}\n</body>\n<script src=\"%24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js\" onerror=\"alert('Error: Cannot load tiddlywiki.js');\"></script>\n</html>\n"
        },
        "$:/core/templates/html-div-skinny-tiddler": {
            "title": "$:/core/templates/html-div-skinny-tiddler",
            "text": "<!--\n\nThis template is a variant of $:/core/templates/html-div-tiddler used for saving skinny tiddlers (with no text field)\n\n-->`<div`<$fields template=' $name$=\"$encoded_value$\"'></$fields>`>\n<pre></pre>\n</div>`\n"
        },
        "$:/core/templates/html-div-tiddler": {
            "title": "$:/core/templates/html-div-tiddler",
            "text": "<!--\n\nThis template is used for saving tiddlers as an HTML DIV tag with attributes representing the tiddler fields.\n\n-->`<div`<$fields template=' $name$=\"$encoded_value$\"'></$fields>`>\n<pre>`<$view field=\"text\" format=\"htmlencoded\" />`</pre>\n</div>`\n"
        },
        "$:/core/templates/html-tiddler": {
            "title": "$:/core/templates/html-tiddler",
            "text": "<!--\n\nThis template is used for saving tiddlers as raw HTML\n\n--><$view field=\"text\" format=\"htmlwikified\" />"
        },
        "$:/core/templates/javascript-tiddler": {
            "title": "$:/core/templates/javascript-tiddler",
            "text": "<!--\n\nThis template is used for saving JavaScript tiddlers as a script tag with data attributes representing the tiddler fields.\n\n-->`<script`<$fields template=' data-tiddler-$name$=\"$encoded_value$\"'></$fields>` type=\"text/javascript\">`<$view field=\"text\" format=\"text\" />`</script>`"
        },
        "$:/core/templates/json-tiddler": {
            "title": "$:/core/templates/json-tiddler",
            "text": "<!--\n\nThis template is used for saving tiddlers as raw JSON\n\n--><$text text=<<jsontiddler>>/>"
        },
        "$:/core/templates/module-tiddler": {
            "title": "$:/core/templates/module-tiddler",
            "text": "<!--\n\nThis template is used for saving JavaScript tiddlers as a script tag with data attributes representing the tiddler fields. The body of the tiddler is wrapped in a call to the `$tw.modules.define` function in order to define the body of the tiddler as a module\n\n-->`<script`<$fields template=' data-tiddler-$name$=\"$encoded_value$\"'></$fields>` type=\"text/javascript\" data-module=\"yes\">$tw.modules.define(\"`<$view field=\"title\" format=\"jsencoded\" />`\",\"`<$view field=\"module-type\" format=\"jsencoded\" />`\",function(module,exports,require) {`<$view field=\"text\" format=\"text\" />`});\n</script>`"
        },
        "$:/core/templates/plain-text-tiddler": {
            "title": "$:/core/templates/plain-text-tiddler",
            "text": "<$view field=\"text\" format=\"text\" />"
        },
        "$:/core/templates/raw-static-tiddler": {
            "title": "$:/core/templates/raw-static-tiddler",
            "text": "<!--\n\nThis template is used for saving tiddlers as static HTML\n\n--><$view field=\"text\" format=\"plainwikified\" />"
        },
        "$:/core/save/all": {
            "title": "$:/core/save/all",
            "text": "\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\\define saveTiddlerFilter()\n[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$\n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n"
        },
        "$:/core/save/empty": {
            "title": "$:/core/save/empty",
            "text": "\\define saveTiddlerFilter()\n[is[system]] -[prefix[$:/state/popup/]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]\n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n"
        },
        "$:/core/save/lazy-all": {
            "title": "$:/core/save/lazy-all",
            "text": "\\define saveTiddlerFilter()\n[is[system]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] \n\\end\n\\define skinnySaveTiddlerFilter()\n[!is[system]]\n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n"
        },
        "$:/core/save/lazy-images": {
            "title": "$:/core/save/lazy-images",
            "text": "\\define saveTiddlerFilter()\n[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[!is[system]is[image]] +[sort[title]] \n\\end\n\\define skinnySaveTiddlerFilter()\n[is[image]]\n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n"
        },
        "$:/core/templates/server/static.sidebar.wikitext": {
            "title": "$:/core/templates/server/static.sidebar.wikitext",
            "text": "\\whitespace trim\n<div class=\"tc-sidebar-scrollable\" style=\"overflow: auto;\">\n<div class=\"tc-sidebar-header\">\n<h1 class=\"tc-site-title\">\n<$transclude tiddler=\"$:/SiteTitle\"/>\n</h1>\n<div class=\"tc-site-subtitle\">\n<$transclude tiddler=\"$:/SiteSubtitle\"/>\n</div>\n<h2>\n</h2>\n<div class=\"tc-sidebar-lists\">\n<$list filter={{$:/DefaultTiddlers}}>\n<div class=\"tc-menu-list-subitem\">\n<$link><$text text=<<currentTiddler>>/></$link>\n</div>\n</$list>\n</div>\n<!-- Currently disabled the recent list as it is unweildy when the responsive narrow view kicks in\n<h2>\n{{$:/language/SideBar/Recent/Caption}}\n</h2>\n<div class=\"tc-sidebar-lists\">\n<$macrocall $name=\"timeline\" format={{$:/language/RecentChanges/DateFormat}}/>\n</div>\n</div>\n</div>\n-->\n"
        },
        "$:/core/templates/server/static.tiddler.html": {
            "title": "$:/core/templates/server/static.tiddler.html",
            "text": "\\whitespace trim\n\\define tv-wikilink-template() $uri_encoded$\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content={{$:/core/templates/version}} />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\">\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<link rel=\"stylesheet\" href=\"%24%3A%2Fcore%2Ftemplates%2Fstatic.template.css\">\n<title><$view field=\"caption\" format=\"plainwikified\"><$view field=\"title\"/></$view>: <$view tiddler=\"$:/core/wiki/title\" format=\"plainwikified\"/></title>\n</head>\n<body class=\"tc-body\">\n<$transclude tiddler=\"$:/core/templates/server/static.sidebar.wikitext\" mode=\"inline\"/>\n<section class=\"tc-story-river\">\n<div class=\"tc-tiddler-frame\">\n<$transclude tiddler=\"$:/core/templates/server/static.tiddler.wikitext\" mode=\"inline\"/>\n</div>\n</section>\n</body>\n</html>"
        },
        "$:/core/templates/server/static.tiddler.wikitext": {
            "title": "$:/core/templates/server/static.tiddler.wikitext",
            "text": "\\whitespace trim\n<div class=\"tc-tiddler-title\">\n<div class=\"tc-titlebar\">\n<h2><$text text=<<currentTiddler>>/></h2>\n</div>\n</div>\n<div class=\"tc-subtitle\">\n<$link to={{!!modifier}}>\n<$view field=\"modifier\"/>\n</$link> <$view field=\"modified\" format=\"date\" template={{$:/language/Tiddler/DateFormat}}/>\n</div>\n<div class=\"tc-tags-wrapper\">\n<$list filter=\"[all[current]tags[]sort[title]]\">\n<a href={{{ [<currentTiddler>encodeuricomponent[]] }}}>\n<$macrocall $name=\"tag-pill\" tag=<<currentTiddler>>/>\n</a>\n</$list>\n</div>\n<div class=\"tc-tiddler-body\">\n<$transclude mode=\"block\"/>\n</div>\n"
        },
        "$:/core/templates/single.tiddler.window": {
            "title": "$:/core/templates/single.tiddler.window",
            "text": "\\whitespace trim\n\\define containerClasses()\ntc-page-container tc-page-view-$(storyviewTitle)$ tc-language-$(languageTitle)$\n\\end\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\n<$set name=\"tv-config-toolbar-icons\" value={{$:/config/Toolbar/Icons}}>\n\n<$set name=\"tv-config-toolbar-text\" value={{$:/config/Toolbar/Text}}>\n\n<$set name=\"tv-config-toolbar-class\" value={{$:/config/Toolbar/ButtonClass}}>\n\n<$set name=\"tv-show-missing-links\" value={{$:/config/MissingLinks}}>\n\n<$set name=\"storyviewTitle\" value={{$:/view}}>\n\n<$set name=\"languageTitle\" value={{{ [{$:/language}get[name]] }}}>\n\n<div class=<<containerClasses>>>\n\n<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\">\n\n<$transclude mode=\"block\"/>\n\n</$navigator>\n\n</div>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/templates/split-recipe": {
            "title": "$:/core/templates/split-recipe",
            "text": "<$list filter=\"[!is[system]]\">\ntiddler: <$view field=\"title\" format=\"urlencoded\"/>.tid\n</$list>\n"
        },
        "$:/core/templates/static-tiddler": {
            "title": "$:/core/templates/static-tiddler",
            "text": "<a name=<<currentTiddler>>>\n<$transclude tiddler=\"$:/core/ui/ViewTemplate\"/>\n</a>"
        },
        "$:/core/templates/static.area": {
            "title": "$:/core/templates/static.area",
            "text": "<$reveal type=\"nomatch\" state=\"$:/isEncrypted\" text=\"yes\">\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawStaticContent]!has[draft.of]] ||$:/core/templates/raw-static-tiddler}}}\n{{$:/core/templates/static.content||$:/core/templates/html-tiddler}}\n</$reveal>\n<$reveal type=\"match\" state=\"$:/isEncrypted\" text=\"yes\">\nThis file contains an encrypted ~TiddlyWiki. Enable ~JavaScript and enter the decryption password when prompted.\n</$reveal>\n<!-- ensure splash screen isn't shown when JS is disabled -->\n`<style>\n.tc-remove-when-wiki-loaded {display: none;}\n</style>`\n"
        },
        "$:/core/templates/static.content": {
            "title": "$:/core/templates/static.content",
            "text": "<!-- For Google, and people without JavaScript-->\nThis [[TiddlyWiki|https://tiddlywiki.com]] contains the following tiddlers:\n\n<ul>\n<$list filter=<<saveTiddlerFilter>>>\n<li><$view field=\"title\" format=\"text\"></$view></li>\n</$list>\n</ul>\n"
        },
        "$:/core/templates/static.template.css": {
            "title": "$:/core/templates/static.template.css",
            "text": "{{$:/boot/boot.css||$:/core/templates/plain-text-tiddler}}\n\n{{$:/core/ui/PageStylesheet||$:/core/templates/wikified-tiddler}}\n"
        },
        "$:/core/templates/static.template.html": {
            "title": "$:/core/templates/static.template.html",
            "type": "text/vnd.tiddlywiki-html",
            "text": "\\define tv-wikilink-template() static/$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\\rules only filteredtranscludeinline transcludeinline\n<!doctype html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"{{$:/core/templates/version}}\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\">\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<title>{{$:/core/wiki/title}}</title>\n<div id=\"styleArea\">\n{{$:/boot/boot.css||$:/core/templates/css-tiddler}}\n</div>\n<style type=\"text/css\">\n{{$:/core/ui/PageStylesheet||$:/core/templates/wikified-tiddler}}\n</style>\n</head>\n<body class=\"tc-body\">\n{{$:/StaticBanner||$:/core/templates/html-tiddler}}\n{{$:/core/ui/PageTemplate||$:/core/templates/html-tiddler}}\n</body>\n</html>\n"
        },
        "$:/core/templates/static.tiddler.html": {
            "title": "$:/core/templates/static.tiddler.html",
            "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\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n`<!doctype html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"`{{$:/core/templates/version}}`\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\">\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<link rel=\"stylesheet\" href=\"static.css\">\n<title>`<$view field=\"caption\"><$view field=\"title\"/></$view>: {{$:/core/wiki/title}}`</title>\n</head>\n<body class=\"tc-body\">\n`{{$:/StaticBanner||$:/core/templates/html-tiddler}}`\n<section class=\"tc-story-river\">\n`<$view tiddler=\"$:/core/ui/ViewTemplate\" format=\"htmlwikified\"/>`\n</section>\n</body>\n</html>\n`"
        },
        "$:/core/templates/store.area.template.html": {
            "title": "$:/core/templates/store.area.template.html",
            "text": "<$reveal type=\"nomatch\" state=\"$:/isEncrypted\" text=\"yes\">\n`<div id=\"storeArea\" style=\"display:none;\">`\n<$list filter=<<saveTiddlerFilter>> template=\"$:/core/templates/html-div-tiddler\"/>\n<$list filter={{{ [<skinnySaveTiddlerFilter>] }}} template=\"$:/core/templates/html-div-skinny-tiddler\"/>\n`</div>`\n</$reveal>\n<$reveal type=\"match\" state=\"$:/isEncrypted\" text=\"yes\">\n`<!--~~ Encrypted tiddlers ~~-->`\n`<pre id=\"encryptedStoreArea\" type=\"text/plain\" style=\"display:none;\">`\n<$encrypt filter=<<saveTiddlerFilter>>/>\n`</pre>`\n</$reveal>"
        },
        "$:/core/templates/tid-tiddler": {
            "title": "$:/core/templates/tid-tiddler",
            "text": "<!--\n\nThis template is used for saving tiddlers in TiddlyWeb *.tid format\n\n--><$fields exclude='text bag' template='$name$: $value$\n'></$fields>`\n`<$view field=\"text\" format=\"text\" />"
        },
        "$:/core/templates/tiddler-metadata": {
            "title": "$:/core/templates/tiddler-metadata",
            "text": "<!--\n\nThis template is used for saving tiddler metadata *.meta files\n\n--><$fields exclude='text bag' template='$name$: $value$\n'></$fields>"
        },
        "$:/core/templates/tiddlywiki5.html": {
            "title": "$:/core/templates/tiddlywiki5.html",
            "text": "<$set name=\"saveTiddlerAndShadowsFilter\" filter=\"[subfilter<saveTiddlerFilter>] [subfilter<saveTiddlerFilter>plugintiddlers[]]\">\n`<!doctype html>\n`{{$:/core/templates/MOTW.html}}`<html lang=\"`<$text text={{{ [{$:/language}get[name]] }}}/>`\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<!--~~ Raw markup for the top of the head section ~~-->\n`{{{ [<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}}`\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge\"/>\n<meta name=\"application-name\" content=\"TiddlyWiki\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"`{{$:/core/templates/version}}`\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\" />\n<meta name=\"copyright\" content=\"`{{$:/core/copyright.txt}}`\" />\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<title>`{{$:/core/wiki/title}}`</title>\n<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->\n\n<!--~~ Raw markup ~~-->\n`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}\n{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}\n{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}`\n</head>\n<body class=\"tc-body\">\n<!--~~ Raw markup for the top of the body section ~~-->\n`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}}`\n<!--~~ Static styles ~~-->\n<div id=\"styleArea\">\n`{{$:/boot/boot.css||$:/core/templates/css-tiddler}}`\n</div>\n<!--~~ Static content for Google and browsers without JavaScript ~~-->\n<noscript>\n<div id=\"splashArea\">\n`{{$:/core/templates/static.area}}`\n</div>\n</noscript>\n<!--~~ Ordinary tiddlers ~~-->\n`{{$:/core/templates/store.area.template.html}}`\n<!--~~ Library modules ~~-->\n<div id=\"libraryModules\" style=\"display:none;\">\n`{{{ [is[system]type[application/javascript]library[yes]] ||$:/core/templates/javascript-tiddler}}}`\n</div>\n<!--~~ Boot kernel prologue ~~-->\n<div id=\"bootKernelPrefix\" style=\"display:none;\">\n`{{ $:/boot/bootprefix.js ||$:/core/templates/javascript-tiddler}}`\n</div>\n<!--~~ Boot kernel ~~-->\n<div id=\"bootKernel\" style=\"display:none;\">\n`{{ $:/boot/boot.js ||$:/core/templates/javascript-tiddler}}`\n</div>\n<!--~~ Raw markup for the bottom of the body section ~~-->\n`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}`\n</body>\n</html>`\n"
        },
        "$:/core/templates/version": {
            "title": "$:/core/templates/version",
            "text": "<<version>>"
        },
        "$:/core/templates/wikified-tiddler": {
            "title": "$:/core/templates/wikified-tiddler",
            "text": "<$transclude />"
        },
        "$:/core/ui/AboveStory/tw2-plugin-check": {
            "title": "$:/core/ui/AboveStory/tw2-plugin-check",
            "tags": "$:/tags/AboveStory",
            "text": "\\define lingo-base() $:/language/AboveStory/ClassicPlugin/\n<$list filter=\"[all[system+tiddlers]tag[systemConfig]limit[1]]\">\n\n<div class=\"tc-message-box\">\n\n<<lingo Warning>>\n\n<ul>\n\n<$list filter=\"[all[system+tiddlers]tag[systemConfig]]\">\n\n<li>\n\n<$link><$view field=\"title\"/></$link>\n\n</li>\n\n</$list>\n\n</ul>\n\n</div>\n\n</$list>\n"
        },
        "$:/core/ui/Actions/new-image": {
            "title": "$:/core/ui/Actions/new-image",
            "tags": "$:/tags/Actions",
            "description": "create a new image tiddler",
            "text": "\\define get-type()\nimage/$(imageType)$\n\\end\n<$vars imageType={{$:/config/NewImageType}}>\n<$action-sendmessage $message=\"tm-new-tiddler\" type=<<get-type>> tags={{$:/config/NewTiddler/Tags!!tags}}/>\n</$vars>\n"
        },
        "$:/core/ui/Actions/new-journal": {
            "title": "$:/core/ui/Actions/new-journal",
            "tags": "$:/tags/Actions",
            "description": "create a new journal tiddler",
            "text": "<$vars journalTitleTemplate={{$:/config/NewJournal/Title}} journalTags={{$:/config/NewJournal/Tags!!tags}} journalText={{$:/config/NewJournal/Text}}>\n<$wikify name=\"journalTitle\" text=\"\"\"<$macrocall $name=\"now\" format=<<journalTitleTemplate>>/>\"\"\">\n<$reveal type=\"nomatch\" state=<<journalTitle>> text=\"\">\n<$action-sendmessage $message=\"tm-new-tiddler\" title=<<journalTitle>> tags=<<journalTags>> text={{{ [<journalTitle>get[]] }}}/>\n</$reveal>\n<$reveal type=\"match\" state=<<journalTitle>> text=\"\">\n<$action-sendmessage $message=\"tm-new-tiddler\" title=<<journalTitle>> tags=<<journalTags>> text=<<journalText>>/>\n</$reveal>\n</$wikify>\n</$vars>\n"
        },
        "$:/core/ui/Actions/new-tiddler": {
            "title": "$:/core/ui/Actions/new-tiddler",
            "tags": "$:/tags/Actions",
            "description": "create a new empty tiddler",
            "text": "<$action-sendmessage $message=\"tm-new-tiddler\" tags={{$:/config/NewTiddler/Tags!!tags}}/>\n"
        },
        "$:/core/ui/AdvancedSearch/Filter": {
            "title": "$:/core/ui/AdvancedSearch/Filter",
            "tags": "$:/tags/AdvancedSearch",
            "caption": "{{$:/language/Search/Filter/Caption}}",
            "text": "\\define lingo-base() $:/language/Search/\n<<lingo Filter/Hint>>\n\n<div class=\"tc-search tc-advanced-search\">\n<$edit-text tiddler=\"$:/temp/advancedsearch\" type=\"search\" tag=\"input\" focus={{$:/config/Search/AutoFocus}}/>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/AdvancedSearch/FilterButton]!has[draft.of]]\"><$transclude/></$list>\n</div>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$set name=\"resultCount\" value=\"\"\"<$count filter={{$:/temp/advancedsearch}}/>\"\"\">\n<div class=\"tc-search-results\">\n<<lingo Filter/Matches>>\n<$list filter={{$:/temp/advancedsearch}} template=\"$:/core/ui/ListItemTemplate\"/>\n</div>\n</$set>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Filter/FilterButtons/clear": {
            "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/clear",
            "tags": "$:/tags/AdvancedSearch/FilterButton",
            "text": "<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" $field=\"text\" $value=\"\"/>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Filter/FilterButtons/delete": {
            "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/delete",
            "tags": "$:/tags/AdvancedSearch/FilterButton",
            "text": "<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button popup=<<qualify \"$:/state/filterDeleteDropdown\">> class=\"tc-btn-invisible\">\n{{$:/core/images/delete-button}}\n</$button>\n</$reveal>\n\n<$reveal state=<<qualify \"$:/state/filterDeleteDropdown\">> type=\"popup\" position=\"belowleft\" animate=\"yes\">\n<div class=\"tc-block-dropdown-wrapper\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<div class=\"tc-dropdown-item-plain\">\n<$set name=\"resultCount\" value=\"\"\"<$count filter={{$:/temp/advancedsearch}}/>\"\"\">\nAre you sure you wish to delete <<resultCount>> tiddler(s)?\n</$set>\n</div>\n<div class=\"tc-dropdown-item-plain\">\n<$button class=\"tc-btn\">\n<$action-deletetiddler $filter={{$:/temp/advancedsearch}}/>\nDelete these tiddlers\n</$button>\n</div>\n</div>\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Filter/FilterButtons/dropdown": {
            "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/dropdown",
            "tags": "$:/tags/AdvancedSearch/FilterButton",
            "text": "<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/filterDropdown\">> class=\"tc-btn-invisible\">\n{{$:/core/images/down-arrow}}\n</$button>\n</span>\n\n<$reveal state=<<qualify \"$:/state/filterDropdown\">> type=\"popup\" position=\"belowleft\" animate=\"yes\">\n<$set name=\"tv-show-missing-links\" value=\"yes\">\n<$linkcatcher to=\"$:/temp/advancedsearch\">\n<div class=\"tc-block-dropdown-wrapper\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Filter]]\"><$link to={{!!filter}}><$transclude field=\"description\"/></$link>\n</$list>\n</div>\n</div>\n</$linkcatcher>\n</$set>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Filter/FilterButtons/export": {
            "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/export",
            "tags": "$:/tags/AdvancedSearch/FilterButton",
            "text": "<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$macrocall $name=\"exportButton\" exportFilter={{$:/temp/advancedsearch}} lingoBase=\"$:/language/Buttons/ExportTiddlers/\"/>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Shadows": {
            "title": "$:/core/ui/AdvancedSearch/Shadows",
            "tags": "$:/tags/AdvancedSearch",
            "caption": "{{$:/language/Search/Shadows/Caption}}",
            "text": "\\define lingo-base() $:/language/Search/\n<$linkcatcher to=\"$:/temp/advancedsearch\">\n\n<<lingo Shadows/Hint>>\n\n<div class=\"tc-search\">\n<$edit-text tiddler=\"$:/temp/advancedsearch\" type=\"search\" tag=\"input\" focus={{$:/config/Search/AutoFocus}}/>\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" $field=\"text\" $value=\"\"/>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n\n</$linkcatcher>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n\n<$list filter=\"[{$:/temp/advancedsearch}minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n\n<$set name=\"resultCount\" value=\"\"\"<$count filter=\"[all[shadows]search{$:/temp/advancedsearch}] -[[$:/temp/advancedsearch]]\"/>\"\"\">\n\n<div class=\"tc-search-results\">\n\n<<lingo Shadows/Matches>>\n\n<$list filter=\"[all[shadows]search{$:/temp/advancedsearch}sort[title]limit[250]] -[[$:/temp/advancedsearch]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n\n</div>\n\n</$set>\n\n</$list>\n\n</$reveal>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"match\" text=\"\">\n\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/Standard": {
            "title": "$:/core/ui/AdvancedSearch/Standard",
            "tags": "$:/tags/AdvancedSearch",
            "caption": "{{$:/language/Search/Standard/Caption}}",
            "text": "\\define lingo-base() $:/language/Search/\n<$linkcatcher to=\"$:/temp/advancedsearch\">\n\n<<lingo Standard/Hint>>\n\n<div class=\"tc-search\">\n<$edit-text tiddler=\"$:/temp/advancedsearch\" type=\"search\" tag=\"input\" focus={{$:/config/Search/AutoFocus}}/>\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" $field=\"text\" $value=\"\"/>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n\n</$linkcatcher>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$list filter=\"[{$:/temp/advancedsearch}minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n<$set name=\"searchTiddler\" value=\"$:/temp/advancedsearch\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]butfirst[]limit[1]]\" emptyMessage=\"\"\"\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\">\n<$transclude/>\n</$list>\n\"\"\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\" default={{$:/config/SearchResults/Default}}/>\n</$list>\n</$set>\n</$list>\n</$reveal>\n"
        },
        "$:/core/ui/AdvancedSearch/System": {
            "title": "$:/core/ui/AdvancedSearch/System",
            "tags": "$:/tags/AdvancedSearch",
            "caption": "{{$:/language/Search/System/Caption}}",
            "text": "\\define lingo-base() $:/language/Search/\n<$linkcatcher to=\"$:/temp/advancedsearch\">\n\n<<lingo System/Hint>>\n\n<div class=\"tc-search\">\n<$edit-text tiddler=\"$:/temp/advancedsearch\" type=\"search\" tag=\"input\" focus={{$:/config/Search/AutoFocus}}/>\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" $field=\"text\" $value=\"\"/>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n\n</$linkcatcher>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n\n<$list filter=\"[{$:/temp/advancedsearch}minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n\n<$set name=\"resultCount\" value=\"\"\"<$count filter=\"[is[system]search{$:/temp/advancedsearch}] -[[$:/temp/advancedsearch]]\"/>\"\"\">\n\n<div class=\"tc-search-results\">\n\n<<lingo System/Matches>>\n\n<$list filter=\"[is[system]search{$:/temp/advancedsearch}sort[title]limit[250]] -[[$:/temp/advancedsearch]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n\n</div>\n\n</$set>\n\n</$list>\n\n</$reveal>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"match\" text=\"\">\n\n</$reveal>\n"
        },
        "$:/AdvancedSearch": {
            "title": "$:/AdvancedSearch",
            "icon": "$:/core/images/advanced-search-button",
            "color": "#bbb",
            "text": "<div class=\"tc-advanced-search\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/AdvancedSearch]!has[draft.of]]\" \"$:/core/ui/AdvancedSearch/System\">>\n</div>\n"
        },
        "$:/core/ui/AlertTemplate": {
            "title": "$:/core/ui/AlertTemplate",
            "text": "<div class=\"tc-alert\">\n<div class=\"tc-alert-toolbar\">\n<$button class=\"tc-btn-invisible\"><$action-deletetiddler $tiddler=<<currentTiddler>>/>{{$:/core/images/cancel-button}}</$button>\n</div>\n<div class=\"tc-alert-subtitle\">\n<$wikify name=\"format\" text=<<lingo Tiddler/DateFormat>>>\n<$view field=\"component\"/> - <$view field=\"modified\" format=\"date\" template=<<format>>/> <$reveal type=\"nomatch\" state=\"!!count\" text=\"\"><span class=\"tc-alert-highlight\">({{$:/language/Count}}: <$view field=\"count\"/>)</span></$reveal>\n</$wikify>\n</div>\n<div class=\"tc-alert-body\">\n\n<$transclude/>\n\n</div>\n</div>\n"
        },
        "$:/core/ui/BinaryWarning": {
            "title": "$:/core/ui/BinaryWarning",
            "text": "\\define lingo-base() $:/language/BinaryWarning/\n<<lingo Prompt>>\n"
        },
        "$:/core/ui/Components/plugin-info": {
            "title": "$:/core/ui/Components/plugin-info",
            "text": "\\define lingo-base() $:/language/ControlPanel/Plugins/\n\n\\define popup-state-macro()\n$(qualified-state)$-$(currentTiddler)$\n\\end\n\n\\define tabs-state-macro()\n$(popup-state)$-$(pluginInfoType)$\n\\end\n\n\\define plugin-icon-title()\n$(currentTiddler)$/icon\n\\end\n\n\\define plugin-disable-title()\n$:/config/Plugins/Disabled/$(currentTiddler)$\n\\end\n\n\\define plugin-table-body(type,disabledMessage,default-popup-state)\n<div class=\"tc-plugin-info-chunk tc-plugin-info-toggle\">\n<$reveal type=\"nomatch\" state=<<popup-state>> text=\"yes\" default=\"\"\"$default-popup-state$\"\"\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"yes\">\n{{$:/core/images/chevron-right}}\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<popup-state>> text=\"yes\" default=\"\"\"$default-popup-state$\"\"\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"no\">\n{{$:/core/images/chevron-down}}\n</$button>\n</$reveal>\n</div>\n<div class=\"tc-plugin-info-chunk tc-plugin-info-icon\">\n<$transclude tiddler=<<currentTiddler>> subtiddler=<<plugin-icon-title>>>\n<$transclude tiddler=\"$:/core/images/plugin-generic-$type$\"/>\n</$transclude>\n</div>\n<div class=\"tc-plugin-info-chunk tc-plugin-info-description\">\n<h1>\n''<$text text={{{ [<currentTiddler>get[name]] ~[<currentTiddler>split[/]last[1]] }}}/>'': <$view field=\"description\"><$view field=\"title\"/></$view> $disabledMessage$\n</h1>\n<h2>\n<$view field=\"title\"/>\n</h2>\n<h2>\n<div><em><$view field=\"version\"/></em></div>\n</h2>\n</div>\n\\end\n\n\\define plugin-info(type,default-popup-state)\n<$set name=\"popup-state\" value=<<popup-state-macro>>>\n<$reveal type=\"nomatch\" state=<<plugin-disable-title>> text=\"yes\">\n<$link to={{!!title}} class=\"tc-plugin-info\">\n<<plugin-table-body type:\"$type$\" default-popup-state:\"\"\"$default-popup-state$\"\"\">>\n</$link>\n</$reveal>\n<$reveal type=\"match\" state=<<plugin-disable-title>> text=\"yes\">\n<$link to={{!!title}} class=\"tc-plugin-info tc-plugin-info-disabled\">\n<<plugin-table-body type:\"$type$\" default-popup-state:\"\"\"$default-popup-state$\"\"\" disabledMessage:\"<$macrocall $name='lingo' title='Disabled/Status'/>\">>\n</$link>\n</$reveal>\n<$reveal type=\"match\" text=\"yes\" state=<<popup-state>> default=\"\"\"$default-popup-state$\"\"\">\n<div class=\"tc-plugin-info-dropdown\">\n<div class=\"tc-plugin-info-dropdown-body\">\n<$list filter=\"[all[current]] -[[$:/core]]\">\n<div style=\"float:right;\">\n<$reveal type=\"nomatch\" state=<<plugin-disable-title>> text=\"yes\">\n<$button set=<<plugin-disable-title>> setTo=\"yes\" tooltip={{$:/language/ControlPanel/Plugins/Disable/Hint}} aria-label={{$:/language/ControlPanel/Plugins/Disable/Caption}}>\n<<lingo Disable/Caption>>\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<plugin-disable-title>> text=\"yes\">\n<$button set=<<plugin-disable-title>> setTo=\"no\" tooltip={{$:/language/ControlPanel/Plugins/Enable/Hint}} aria-label={{$:/language/ControlPanel/Plugins/Enable/Caption}}>\n<<lingo Enable/Caption>>\n</$button>\n</$reveal>\n</div>\n</$list>\n<$set name=\"tabsList\" filter=\"[<currentTiddler>list[]] contents\">\n<$macrocall $name=\"tabs\" state=<<tabs-state-macro>> tabsList=<<tabsList>> default={{{ [enlist<tabsList>] }}} template=\"$:/core/ui/PluginInfo\"/>\n</$set>\n</div>\n</div>\n</$reveal>\n</$set>\n\\end\n\n<$macrocall $name=\"plugin-info\" type=<<plugin-type>> default-popup-state=<<default-popup-state>>/>\n"
        },
        "$:/core/ui/Components/tag-link": {
            "title": "$:/core/ui/Components/tag-link",
            "text": "<$link>\n<$set name=\"backgroundColor\" value={{!!color}}>\n<span style=<<tag-styles>> class=\"tc-tag-label\">\n<$view field=\"title\" format=\"text\"/>\n</span>\n</$set>\n</$link>"
        },
        "$:/core/ui/ControlPanel/Advanced": {
            "title": "$:/core/ui/ControlPanel/Advanced",
            "tags": "$:/tags/ControlPanel/Info",
            "caption": "{{$:/language/ControlPanel/Advanced/Caption}}",
            "text": "{{$:/language/ControlPanel/Advanced/Hint}}\n\n<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Advanced]!has[draft.of]]\" \"$:/core/ui/ControlPanel/TiddlerFields\">>\n</div>\n"
        },
        "$:/core/ui/ControlPanel/Appearance": {
            "title": "$:/core/ui/ControlPanel/Appearance",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/Appearance/Caption}}",
            "text": "{{$:/language/ControlPanel/Appearance/Hint}}\n\n<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Appearance]!has[draft.of]]\" \"$:/core/ui/ControlPanel/Theme\">>\n</div>\n"
        },
        "$:/core/ui/ControlPanel/Basics": {
            "title": "$:/core/ui/ControlPanel/Basics",
            "tags": "$:/tags/ControlPanel/Info",
            "caption": "{{$:/language/ControlPanel/Basics/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Basics/\n\n\\define show-filter-count(filter)\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" $value=\"\"\"$filter$\"\"\"/>\n<$action-setfield $tiddler=\"$:/state/tab--1498284803\" $value=\"$:/core/ui/AdvancedSearch/Filter\"/>\n<$action-navigate $to=\"$:/AdvancedSearch\"/>\n''<$count filter=\"\"\"$filter$\"\"\"/>''\n{{$:/core/images/advanced-search-button}}\n</$button>\n\\end\n\n|<<lingo Version/Prompt>> |''<<version>>'' |\n|<$link to=\"$:/SiteTitle\"><<lingo Title/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteTitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/SiteSubtitle\"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteSubtitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/status/UserName\"><<lingo Username/Prompt>></$link> |<$edit-text tiddler=\"$:/status/UserName\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/config/AnimationDuration\"><<lingo AnimDuration/Prompt>></$link> |<$edit-text tiddler=\"$:/config/AnimationDuration\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/DefaultTiddlers\"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit tag=\"textarea\" tiddler=\"$:/DefaultTiddlers\" class=\"tc-edit-texteditor\"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |\n|<$link to=\"$:/language/DefaultNewTiddlerTitle\"><<lingo NewTiddler/Title/Prompt>></$link> |<$edit-text tiddler=\"$:/language/DefaultNewTiddlerTitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/config/NewJournal/Title\"><<lingo NewJournal/Title/Prompt>></$link> |<$edit-text tiddler=\"$:/config/NewJournal/Title\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/config/NewJournal/Text\"><<lingo NewJournal/Text/Prompt>></$link> |<$edit tiddler=\"$:/config/NewJournal/Text\" tag=\"textarea\" class=\"tc-edit-texteditor\" default=\"\"/> |\n|<$link to=\"$:/config/NewTiddler/Tags\"><<lingo NewTiddler/Tags/Prompt>></$link> |<$list filter=\"[[$:/config/NewTiddler/Tags]]\" template=\"$:/core/ui/EditTemplate/tags\"/> |\n|<$link to=\"$:/config/NewJournal/Tags\"><<lingo NewJournal/Tags/Prompt>></$link> |<$list filter=\"[[$:/config/NewJournal/Tags]]\" template=\"$:/core/ui/EditTemplate/tags\"/> |\n|<$link to=\"$:/config/AutoFocus\"><<lingo AutoFocus/Prompt>></$link> |{{$:/snippets/minifocusswitcher}} |\n|<<lingo Language/Prompt>> |{{$:/snippets/minilanguageswitcher}} |\n|<<lingo Tiddlers/Prompt>> |<<show-filter-count \"[!is[system]sort[title]]\">> |\n|<<lingo Tags/Prompt>> |<<show-filter-count \"[tags[]sort[title]]\">> |\n|<<lingo SystemTiddlers/Prompt>> |<<show-filter-count \"[is[system]sort[title]]\">> |\n|<<lingo ShadowTiddlers/Prompt>> |<<show-filter-count \"[all[shadows]sort[title]]\">> |\n|<<lingo OverriddenShadowTiddlers/Prompt>> |<<show-filter-count \"[is[tiddler]is[shadow]sort[title]]\">> |\n"
        },
        "$:/core/ui/ControlPanel/EditorTypes": {
            "title": "$:/core/ui/ControlPanel/EditorTypes",
            "tags": "$:/tags/ControlPanel/Advanced",
            "caption": "{{$:/language/ControlPanel/EditorTypes/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/EditorTypes/\n\n<<lingo Hint>>\n\n<table>\n<tbody>\n<tr>\n<th><<lingo Type/Caption>></th>\n<th><<lingo Editor/Caption>></th>\n</tr>\n<$list filter=\"[all[shadows+tiddlers]prefix[$:/config/EditorTypeMappings/]sort[title]]\">\n<tr>\n<td>\n<$link>\n<$list filter=\"[all[current]removeprefix[$:/config/EditorTypeMappings/]]\">\n<$text text={{!!title}}/>\n</$list>\n</$link>\n</td>\n<td>\n<$view field=\"text\"/>\n</td>\n</tr>\n</$list>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/ControlPanel/Info": {
            "title": "$:/core/ui/ControlPanel/Info",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/Info/Caption}}",
            "text": "{{$:/language/ControlPanel/Info/Hint}}\n\n<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Info]!has[draft.of]]\" \"$:/core/ui/ControlPanel/Basics\">>\n</div>\n"
        },
        "$:/core/ui/ControlPanel/KeyboardShortcuts": {
            "title": "$:/core/ui/ControlPanel/KeyboardShortcuts",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/KeyboardShortcuts/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/KeyboardShortcuts/\n\n\\define new-shortcut(title)\n<div class=\"tc-dropdown-item-plain\">\n<$edit-shortcut tiddler=\"$title$\" placeholder={{$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt}} focus=\"true\" style=\"width:auto;\"/> <$button>\n<<lingo Add/Caption>>\n<$action-listops\n\t$tiddler=\"$(shortcutTitle)$\"\n\t$field=\"text\"\n\t$subfilter=\"[{$title$}]\"\n/>\n<$action-deletetiddler\n\t$tiddler=\"$title$\"\n/>\n</$button>\n</div>\n\\end\n\n\\define shortcut-list-item(caption)\n<td>\n</td>\n<td style=\"text-align:right;font-size:0.7em;\">\n<<lingo Platform/$caption$>>\n</td>\n<td>\n<div style=\"position:relative;\">\n<$button popup=<<qualify \"$:/state/dropdown/$(shortcutTitle)$\">> class=\"tc-btn-invisible\">\n{{$:/core/images/edit-button}}\n</$button>\n<$macrocall $name=\"displayshortcuts\" $output=\"text/html\" shortcuts={{$(shortcutTitle)$}} prefix=\"<kbd>\" separator=\"</kbd> <kbd>\" suffix=\"</kbd>\"/>\n\n<$reveal state=<<qualify \"$:/state/dropdown/$(shortcutTitle)$\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-block-dropdown-wrapper\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown tc-popup-keep\">\n<$list filter=\"[list[$(shortcutTitle)$!!text]sort[title]]\" variable=\"shortcut\" emptyMessage=\"\"\"\n<div class=\"tc-dropdown-item-plain\">\n//<<lingo NoShortcuts/Caption>>//\n</div>\n\"\"\">\n<div class=\"tc-dropdown-item-plain\">\n<$button class=\"tc-btn-invisible\" tooltip={{$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint}}>\n<$action-listops\n\t$tiddler=\"$(shortcutTitle)$\"\n\t$field=\"text\"\n\t$subfilter=\"+[remove<shortcut>]\"\n/>\n<small>{{$:/core/images/close-button}}</small>\n</$button>\n<kbd>\n<$macrocall $name=\"displayshortcuts\" $output=\"text/html\" shortcuts=<<shortcut>>/>\n</kbd>\n</div>\n</$list>\n<hr/>\n<$macrocall $name=\"new-shortcut\" title=<<qualify \"$:/state/new-shortcut/$(shortcutTitle)$\">>/>\n</div>\n</div>\n</$reveal>\n</div>\n</td>\n\\end\n\n\\define shortcut-list(caption,prefix)\n<tr>\n<$list filter=\"[[$prefix$$(shortcutName)$]]\" variable=\"shortcutTitle\">\n<<shortcut-list-item \"$caption$\">>\n</$list>\n</tr>\n\\end\n\n\\define shortcut-editor()\n<<shortcut-list \"All\" \"$:/config/shortcuts/\">>\n<<shortcut-list \"Mac\" \"$:/config/shortcuts-mac/\">>\n<<shortcut-list \"NonMac\" \"$:/config/shortcuts-not-mac/\">>\n<<shortcut-list \"Linux\" \"$:/config/shortcuts-linux/\">>\n<<shortcut-list \"NonLinux\" \"$:/config/shortcuts-not-linux/\">>\n<<shortcut-list \"Windows\" \"$:/config/shortcuts-windows/\">>\n<<shortcut-list \"NonWindows\" \"$:/config/shortcuts-not-windows/\">>\n\\end\n\n\\define shortcut-preview()\n<$macrocall $name=\"displayshortcuts\" $output=\"text/html\" shortcuts={{$(shortcutPrefix)$$(shortcutName)$}} prefix=\"<kbd>\" separator=\"</kbd> <kbd>\" suffix=\"</kbd>\"/>\n\\end\n\n\\define shortcut-item-inner()\n<tr>\n<td>\n<$reveal type=\"nomatch\" state=<<dropdownStateTitle>> text=\"open\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield\n\t$tiddler=<<dropdownStateTitle>>\n\t$value=\"open\"\n/>\n{{$:/core/images/right-arrow}}\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<dropdownStateTitle>> text=\"open\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield\n\t$tiddler=<<dropdownStateTitle>>\n\t$value=\"close\"\n/>\n{{$:/core/images/down-arrow}}\n</$button>\n</$reveal>\n''<$text text=<<shortcutName>>/>''\n</td>\n<td>\n<$transclude tiddler=\"$:/config/ShortcutInfo/$(shortcutName)$\"/>\n</td>\n<td>\n<$list filter=\"$:/config/shortcuts/ $:/config/shortcuts-mac/ $:/config/shortcuts-not-mac/ $:/config/shortcuts-linux/ $:/config/shortcuts-not-linux/ $:/config/shortcuts-windows/ $:/config/shortcuts-not-windows/\" variable=\"shortcutPrefix\">\n<<shortcut-preview>>\n</$list>\n</td>\n</tr>\n<$set name=\"dropdownState\" value={{$(dropdownStateTitle)$}}>\n<$list filter=\"[<dropdownState>match[open]]\" variable=\"listItem\">\n<<shortcut-editor>>\n</$list>\n</$set>\n\\end\n\n\\define shortcut-item()\n<$set name=\"dropdownStateTitle\" value=<<qualify \"$:/state/dropdown/keyboardshortcut/$(shortcutName)$\">>>\n<<shortcut-item-inner>>\n</$set>\n\\end\n\n<table>\n<tbody>\n<$list filter=\"[all[shadows+tiddlers]removeprefix[$:/config/ShortcutInfo/]]\" variable=\"shortcutName\">\n<<shortcut-item>>\n</$list>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/ControlPanel/LoadedModules": {
            "title": "$:/core/ui/ControlPanel/LoadedModules",
            "tags": "$:/tags/ControlPanel/Advanced",
            "caption": "{{$:/language/ControlPanel/LoadedModules/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/\n<<lingo LoadedModules/Hint>>\n\n{{$:/snippets/modules}}\n"
        },
        "$:/core/ui/ControlPanel/Modals/AddPlugins": {
            "title": "$:/core/ui/ControlPanel/Modals/AddPlugins",
            "subtitle": "{{$:/core/images/download-button}} {{$:/language/ControlPanel/Plugins/Add/Caption}}",
            "text": "\\define install-plugin-actions()\n<$action-sendmessage $message=\"tm-load-plugin-from-library\" url={{!!url}} title={{$(assetInfo)$!!original-title}}/>\n<$set name=\"url\" value={{!!url}}>\n<$set name=\"currentTiddler\" value=<<assetInfo>>>\n<$list filter=\"[enlist{!!dependents}] [{!!parent-plugin}] +[sort[title]]\" variable=\"dependency\">\n<$action-sendmessage $message=\"tm-load-plugin-from-library\" url=<<url>> title=<<dependency>>/>\n</$list>\n</$set>\n</$set>\n\\end\n\n\\define install-plugin-button()\n<div>\n<$set name=\"libraryVersion\" value={{{ [<assetInfo>get[version]] }}}>\n<$set name=\"installedVersion\" value={{{ [<assetInfo>get[original-title]get[version]] }}}>\n<$set name=\"reinstall-type\" value={{{ [<libraryVersion>compare:version:eq<installedVersion>then[tc-reinstall]] [<libraryVersion>compare:version:gt<installedVersion>then[tc-reinstall-upgrade]] [<libraryVersion>compare:version:lt<installedVersion>then[tc-reinstall-downgrade]] }}}>\n<$button actions=<<install-plugin-actions>> class={{{ [<assetInfo>get[original-title]has[version]then<reinstall-type>] tc-btn-invisible tc-install-plugin +[join[ ]] }}}>\n{{$:/core/images/download-button}}\n<$list filter=\"[<assetInfo>get[original-title]get[version]]\" variable=\"ignore\" emptyMessage=\"{{$:/language/ControlPanel/Plugins/Install/Caption}}\">\n<$list filter=\"[<libraryVersion>compare:version:gt<installedVersion>]\" variable=\"ignore\" emptyMessage=\"\"\"\n<$list filter=\"[<libraryVersion>compare:version:lt<installedVersion>]\" variable=\"ignore\" emptyMessage=\"{{$:/language/ControlPanel/Plugins/Reinstall/Caption}}\">\n{{$:/language/ControlPanel/Plugins/Downgrade/Caption}}\n</$list>\n\"\"\">\n{{$:/language/ControlPanel/Plugins/Update/Caption}}\n</$list>\n</$list>\n</$button>\n<div>\n</div>\n<$reveal stateTitle=<<assetInfo>> stateField=\"requires-reload\" type=\"match\" text=\"yes\">{{$:/language/ControlPanel/Plugins/PluginWillRequireReload}}</$reveal>\n</$set>\n</$set>\n</$set>\n</div>\n\\end\n\n\\define popup-state-macro()\n$:/state/add-plugin-info/$(connectionTiddler)$/$(assetInfo)$\n\\end\n\n\\define display-plugin-info(type)\n<$set name=\"popup-state\" value=<<popup-state-macro>>>\n<div class=\"tc-plugin-info\">\n<div class=\"tc-plugin-info-chunk tc-plugin-info-toggle\">\n<$reveal type=\"nomatch\" state=<<popup-state>> text=\"yes\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"yes\">\n{{$:/core/images/chevron-right}}\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<popup-state>> text=\"yes\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"no\">\n{{$:/core/images/chevron-down}}\n</$button>\n</$reveal>\n</div>\n<div class=\"tc-plugin-info-chunk tc-plugin-info-icon\">\n<$list filter=\"[<assetInfo>has[icon]]\" emptyMessage=\"\"\"<$transclude tiddler=\"$:/core/images/plugin-generic-$type$\"/>\"\"\">\n<img src={{$(assetInfo)$!!icon}}/>\n</$list>\n</div>\n<div class=\"tc-plugin-info-chunk tc-plugin-info-description\">\n<h1><strong><$text text={{{ [<assetInfo>get[name]] ~[<assetInfo>get[original-title]split[/]last[1]] }}}/></strong>: <$view tiddler=<<assetInfo>> field=\"description\"/></h1>\n<h2><$view tiddler=<<assetInfo>> field=\"original-title\"/></h2>\n<div><em><$view tiddler=<<assetInfo>> field=\"version\"/></em></div>\n<$list filter=\"[<assetInfo>get[original-title]get[version]]\" variable=\"installedVersion\"><div><em>{{$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint}}</em></div></$list>\n</div>\n<div class=\"tc-plugin-info-chunk tc-plugin-info-buttons\">\n<<install-plugin-button>>\n</div>\n</div>\n<$set name=\"original-title\" value={{{ [<assetInfo>get[original-title]] }}}>\n<$reveal type=\"match\" text=\"yes\" state=<<popup-state>>>\n<div class=\"tc-plugin-info-dropdown\">\n<$list filter=\"[enlist{!!dependents}] [<currentTiddler>get[parent-plugin]] +[limit[1]] ~[<assetInfo>get[original-title]!is[tiddler]]\" variable=\"ignore\">\n<div class=\"tc-plugin-info-dropdown-message\">\n<$list filter=\"[<assetInfo>get[original-title]!is[tiddler]]\">\n{{$:/language/ControlPanel/Plugins/NotInstalled/Hint}}\n</$list>\n<$set name=\"currentTiddler\" value=<<assetInfo>>>\n<$list filter=\"[enlist{!!dependents}] [<currentTiddler>get[parent-plugin]] +[limit[1]]\" variable=\"ignore\">\n<div>\n{{$:/language/ControlPanel/Plugins/AlsoRequires}}\n<$list filter=\"[enlist{!!dependents}] [{!!parent-plugin}] +[sort[title]]\" variable=\"dependency\">\n<$text text=<<dependency>>/>\n</$list>\n</div>\n</$list>\n</$set>\n</div>\n</$list>\n<div class=\"tc-plugin-info-dropdown-body\">\n<$transclude tiddler=<<assetInfo>> field=\"readme\" mode=\"block\"/>\n</div>\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[$type$]has[parent-plugin]parent-plugin<original-title>limit[1]]\" variable=\"ignore\">\n<div class=\"tc-plugin-info-sub-plugins\">\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[$type$]has[parent-plugin]parent-plugin<original-title>sort[title]]\" variable=\"assetInfo\">\n<<display-plugin-info \"$type$\">>\n</$list>\n</div>\n</$list>\n</div>\n</$reveal>\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[$type$]has[parent-plugin]parent-plugin<original-title>limit[1]]\" variable=\"ignore\">\n<$reveal type=\"nomatch\" text=\"yes\" state=<<popup-state>> tag=\"div\" class=\"tc-plugin-info-sub-plugin-indicator\">\n<$wikify name=\"count\" text=\"\"\"<$count filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[$type$]has[parent-plugin]parent-plugin<original-title>]\"/>\"\"\">\n<$button class=\"tc-btn-invisible\" set=<<popup-state>> setTo=\"yes\">\n{{$:/language/ControlPanel/Plugins/SubPluginPrompt}}\n</$button>\n</$wikify>\n</$reveal>\n</$list>\n</$set>\n</$set>\n\\end\n\n\\define load-plugin-library-button()\n<$button class=\"tc-btn-big-green\">\n<$action-sendmessage $message=\"tm-load-plugin-library\" url={{!!url}} infoTitlePrefix=\"$:/temp/RemoteAssetInfo/\"/>\n{{$:/core/images/chevron-right}} {{$:/language/ControlPanel/Plugins/OpenPluginLibrary}}\n</$button>\n\\end\n\n\\define display-server-assets(type)\n{{$:/language/Search/Search}}: <$edit-text tiddler=\"\"\"$:/temp/RemoteAssetSearch/$(currentTiddler)$\"\"\" default=\"\" type=\"search\" tag=\"input\"/>\n<$reveal state=\"\"\"$:/temp/RemoteAssetSearch/$(currentTiddler)$\"\"\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"\"\"$:/temp/RemoteAssetSearch/$(currentTiddler)$\"\"\" $field=\"text\" $value=\"\"/>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n<div class=\"tc-plugin-library-listing\">\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[$type$]search:author,description,original-title,readme,title{$:/temp/RemoteAssetSearch/$(currentTiddler)$}sort[title]]\" variable=\"assetInfo\">\n<$list filter=\"[[$:/temp/RemoteAssetSearch/$(currentTiddler)$]has[text]] ~[<assetInfo>!has[parent-plugin]]\" variable=\"ignore\"><!-- Hide sub-plugins if we're not searching -->\n<<display-plugin-info \"$type$\">>\n</$list>\n</$list>\n</div>\n\\end\n\n\\define display-server-connection()\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/ServerConnection]suffix{!!url}]\" variable=\"connectionTiddler\" emptyMessage=<<load-plugin-library-button>>>\n\n<$set name=\"transclusion\" value=<<connectionTiddler>>>\n\n<<tabs \"[[$:/core/ui/ControlPanel/Plugins/Add/Updates]] [[$:/core/ui/ControlPanel/Plugins/Add/Plugins]] [[$:/core/ui/ControlPanel/Plugins/Add/Themes]] [[$:/core/ui/ControlPanel/Plugins/Add/Languages]]\" \"$:/core/ui/ControlPanel/Plugins/Add/Plugins\">>\n\n</$set>\n\n</$list>\n\\end\n\n\\define close-library-button()\n<$reveal type='nomatch' state='$:/temp/ServerConnection/$(PluginLibraryURL)$' text=''>\n<$button class='tc-btn-big-green'>\n<$action-sendmessage $message=\"tm-unload-plugin-library\" url={{!!url}}/>\n{{$:/core/images/chevron-left}} {{$:/language/ControlPanel/Plugins/ClosePluginLibrary}}\n<$action-deletetiddler $filter=\"[prefix[$:/temp/ServerConnection/$(PluginLibraryURL)$]][prefix[$:/temp/RemoteAssetInfo/$(PluginLibraryURL)$]]\"/>\n</$button>\n</$reveal>\n\\end\n\n\\define plugin-library-listing()\n<div class=\"tc-tab-set\">\n<$set name=\"defaultTab\" value={{{ [all[tiddlers+shadows]tag[$:/tags/PluginLibrary]] }}}>\n<div class=\"tc-tab-buttons\">\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/PluginLibrary]]\">\n<$button set=<<qualify \"$:/state/addplugins/tab\">> setTo=<<currentTiddler>> default=<<defaultTab>> selectedClass=\"tc-tab-selected\">\n<$set name=\"tv-wikilinks\" value=\"no\">\n<$transclude field=\"caption\"/>\n</$set>\n</$button>\n</$list>\n</div>\n<div class=\"tc-tab-divider\"/>\n<div class=\"tc-tab-content\">\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/PluginLibrary]]\">\n<$reveal type=\"match\" state=<<qualify \"$:/state/addplugins/tab\">> text=<<currentTiddler>> default=<<defaultTab>>>\n<h2><$link><$transclude field=\"caption\"><$view field=\"title\"/></$transclude></$link></h2>\n//<$view field=\"url\"/>//\n<$transclude mode=\"block\"/>\n<$set name=PluginLibraryURL value={{!!url}}>\n<<close-library-button>>\n</$set>\n<<display-server-connection>>\n</$reveal>\n</$list>\n</div>\n</$set>\n</div>\n\\end\n\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\n<div>\n<<plugin-library-listing>>\n</div>\n"
        },
        "$:/core/ui/ControlPanel/Palette": {
            "title": "$:/core/ui/ControlPanel/Palette",
            "tags": "$:/tags/ControlPanel/Appearance",
            "caption": "{{$:/language/ControlPanel/Palette/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Palette/\n\n{{$:/snippets/paletteswitcher}}\n\n<$reveal type=\"nomatch\" state=\"$:/state/ShowPaletteEditor\" text=\"yes\">\n\n<$button set=\"$:/state/ShowPaletteEditor\" setTo=\"yes\"><<lingo ShowEditor/Caption>></$button>\n\n</$reveal>\n\n<$reveal type=\"match\" state=\"$:/state/ShowPaletteEditor\" text=\"yes\">\n\n<$button set=\"$:/state/ShowPaletteEditor\" setTo=\"no\"><<lingo HideEditor/Caption>></$button>\n{{$:/PaletteManager}}\n\n</$reveal>\n\n"
        },
        "$:/core/ui/ControlPanel/Parsing": {
            "title": "$:/core/ui/ControlPanel/Parsing",
            "tags": "$:/tags/ControlPanel/Advanced",
            "caption": "{{$:/language/ControlPanel/Parsing/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Parsing/\n\n\\define toggle(Type)\n<$checkbox\ntiddler=\"\"\"$:/config/WikiParserRules/$Type$/$(rule)$\"\"\"\nfield=\"text\"\nchecked=\"enable\"\nunchecked=\"disable\"\ndefault=\"enable\">\n<<rule>>\n</$checkbox>\n\\end\n\n\\define rules(type,Type)\n<$list filter=\"[wikiparserrules[$type$]]\" variable=\"rule\">\n<dd><<toggle $Type$>></dd>\n</$list>\n\\end\n\n<<lingo Hint>>\n\n<dl>\n<dt><<lingo Pragma/Caption>></dt>\n<<rules pragma Pragma>>\n<dt><<lingo Inline/Caption>></dt>\n<<rules inline Inline>>\n<dt><<lingo Block/Caption>></dt>\n<<rules block Block>>\n</dl>"
        },
        "$:/core/ui/ControlPanel/Plugins/Add/Languages": {
            "title": "$:/core/ui/ControlPanel/Plugins/Add/Languages",
            "caption": "{{$:/language/ControlPanel/Plugins/Languages/Caption}} (<$count filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[language]]\"/>)",
            "text": "<<display-server-assets language>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Add/Plugins": {
            "title": "$:/core/ui/ControlPanel/Plugins/Add/Plugins",
            "caption": "{{$:/language/ControlPanel/Plugins/Plugins/Caption}}  (<$count filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[plugin]]\"/>)",
            "text": "<<display-server-assets plugin>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Add/Themes": {
            "title": "$:/core/ui/ControlPanel/Plugins/Add/Themes",
            "caption": "{{$:/language/ControlPanel/Plugins/Themes/Caption}}  (<$count filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[theme]]\"/>)",
            "text": "<<display-server-assets theme>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Add/Updates": {
            "title": "$:/core/ui/ControlPanel/Plugins/Add/Updates",
            "caption": "<$importvariables filter=\"$:/core/ui/ControlPanel/Plugins/Add/Updates\">{{$:/language/ControlPanel/Plugins/Updates/Caption}} (<<update-count>>)</$importvariables>",
            "text": "\\define each-updateable-plugin(body)\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}sort[title]]\" variable=\"assetInfo\">\n<$set name=\"libraryVersion\" value={{{ [<assetInfo>get[version]] }}}>\n<$list filter=\"[<assetInfo>get[original-title]has[version]!version<libraryVersion>]\" variable=\"ignore\">\n<$set name=\"installedVersion\" value={{{ [<assetInfo>get[original-title]get[version]] }}}>\n<$list filter=\"[<installedversion>!match<libraryVersion>]\" variable=\"ignore\">\n$body$\n</$list>\n</$set>\n</$list>\n</$set>\n</$list>\n\\end\n\n\\define update-all-actions()\n<$macrocall $name=\"each-updateable-plugin\" body=\"\"\"\n<<install-plugin-actions>>\n\"\"\"/>\n\\end\n\n\\define update-count()\n<$wikify name=\"count-filter\" text=<<each-updateable-plugin \"&#91;&#91;<$text text=<<assetInfo>>/>]]\">>><$count filter=<<count-filter>>/></$wikify>\n\\end\n\n<$button actions=<<update-all-actions>> class=\"tc-btn-invisible tc-install-plugin tc-reinstall-upgrade\">\n{{$:/core/images/download-button}} {{||$:/language/ControlPanel/Plugins/Updates/UpdateAll/Caption}}\n</$button>\n\n<div class=\"tc-plugin-library-listing\">\n<$macrocall $name=\"each-updateable-plugin\" body=\"\"\"\n<$macrocall $name=\"display-plugin-info\" type={{{ [<assetInfo>get[original-plugin-type]] }}}/>\n\"\"\"/>\n</div>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/AddPlugins": {
            "title": "$:/core/ui/ControlPanel/Plugins/AddPlugins",
            "text": "\\define lingo-base() $:/language/ControlPanel/Plugins/\n\n<$button message=\"tm-modal\" param=\"$:/core/ui/ControlPanel/Modals/AddPlugins\" tooltip={{$:/language/ControlPanel/Plugins/Add/Hint}} class=\"tc-btn-big-green tc-primary-btn\">\n{{$:/core/images/download-button}} <<lingo Add/Caption>>\n</$button>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Installed/Languages": {
            "title": "$:/core/ui/ControlPanel/Plugins/Installed/Languages",
            "caption": "{{$:/language/ControlPanel/Plugins/Languages/Caption}} (<$count filter=\"[!has[draft.of]plugin-type[language]]\"/>)",
            "text": "<<plugin-table language>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Installed/Plugins": {
            "title": "$:/core/ui/ControlPanel/Plugins/Installed/Plugins",
            "caption": "{{$:/language/ControlPanel/Plugins/Plugins/Caption}} (<$count filter=\"[!has[draft.of]plugin-type[plugin]]\"/>)",
            "text": "<<plugin-table plugin>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins/Installed/Themes": {
            "title": "$:/core/ui/ControlPanel/Plugins/Installed/Themes",
            "caption": "{{$:/language/ControlPanel/Plugins/Themes/Caption}} (<$count filter=\"[!has[draft.of]plugin-type[theme]]\"/>)",
            "text": "<<plugin-table theme>>\n"
        },
        "$:/core/ui/ControlPanel/Plugins": {
            "title": "$:/core/ui/ControlPanel/Plugins",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/Plugins/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Plugins/\n\n\\define plugin-table(type)\n<$set name=\"plugin-type\" value=\"\"\"$type$\"\"\">\n<$set name=\"qualified-state\" value=<<qualify \"$:/state/plugin-info\">>>\n<$list filter=\"[!has[draft.of]plugin-type[$type$]sort[title]]\" emptyMessage=<<lingo \"Empty/Hint\">> template=\"$:/core/ui/Components/plugin-info\"/>\n</$set>\n</$set>\n\\end\n\n{{$:/core/ui/ControlPanel/Plugins/AddPlugins}}\n\n<<lingo Installed/Hint>>\n\n<<tabs \"[[$:/core/ui/ControlPanel/Plugins/Installed/Plugins]] [[$:/core/ui/ControlPanel/Plugins/Installed/Themes]] [[$:/core/ui/ControlPanel/Plugins/Installed/Languages]]\" \"$:/core/ui/ControlPanel/Plugins/Installed/Plugins\">>\n"
        },
        "$:/core/ui/ControlPanel/Saving/DownloadSaver": {
            "title": "$:/core/ui/ControlPanel/Saving/DownloadSaver",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/DownloadSaver/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Saving/DownloadSaver/\n\n<<lingo Hint>>\n\n!! <$link to=\"$:/config/DownloadSaver/AutoSave\"><<lingo AutoSave/Hint>></$link>\n\n<$checkbox tiddler=\"$:/config/DownloadSaver/AutoSave\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> <<lingo AutoSave/Description>> </$checkbox>\n"
        },
        "$:/core/ui/ControlPanel/Saving/General": {
            "title": "$:/core/ui/ControlPanel/Saving/General",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/General/Caption}}",
            "list-before": "",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/\n\n{{$:/language/ControlPanel/Saving/General/Hint}}\n\n!! <$link to=\"$:/config/AutoSave\"><<lingo AutoSave/Caption>></$link>\n\n<<lingo AutoSave/Hint>>\n\n<$radio tiddler=\"$:/config/AutoSave\" value=\"yes\"> <<lingo AutoSave/Enabled/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/AutoSave\" value=\"no\"> <<lingo AutoSave/Disabled/Description>> </$radio>\n"
        },
        "$:/core/ui/ControlPanel/Saving/GitHub": {
            "title": "$:/core/ui/ControlPanel/Saving/GitHub",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/GitService/GitHub/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Saving/GitService/\n\\define service-name() ~GitHub\n\n<<lingo Description>>\n\n|<<lingo UserName>> |<$edit-text tiddler=\"$:/GitHub/Username\" default=\"\" tag=\"input\"/> |\n|<<lingo GitHub/Password>> |<$password name=\"github\"/> |\n|<<lingo Repo>> |<$edit-text tiddler=\"$:/GitHub/Repo\" default=\"\" tag=\"input\"/> |\n|<<lingo Branch>> |<$edit-text tiddler=\"$:/GitHub/Branch\" default=\"master\" tag=\"input\"/> |\n|<<lingo Path>> |<$edit-text tiddler=\"$:/GitHub/Path\" default=\"\" tag=\"input\"/> |\n|<<lingo Filename>> |<$edit-text tiddler=\"$:/GitHub/Filename\" default=\"\" tag=\"input\"/> |\n|<<lingo ServerURL>> |<$edit-text tiddler=\"$:/GitHub/ServerURL\" default=\"https://api.github.com\" tag=\"input\"/> |"
        },
        "$:/core/ui/ControlPanel/Saving/GitLab": {
            "title": "$:/core/ui/ControlPanel/Saving/GitLab",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/GitService/GitLab/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Saving/GitService/\n\\define service-name() ~GitLab\n\n<<lingo Description>>\n\n|<<lingo UserName>> |<$edit-text tiddler=\"$:/GitLab/Username\" default=\"\" tag=\"input\"/> |\n|<<lingo GitLab/Password>> |<$password name=\"gitlab\"/> |\n|<<lingo Repo>> |<$edit-text tiddler=\"$:/GitLab/Repo\" default=\"\" tag=\"input\"/> |\n|<<lingo Branch>> |<$edit-text tiddler=\"$:/GitLab/Branch\" default=\"master\" tag=\"input\"/> |\n|<<lingo Path>> |<$edit-text tiddler=\"$:/GitLab/Path\" default=\"\" tag=\"input\"/> |\n|<<lingo Filename>> |<$edit-text tiddler=\"$:/GitLab/Filename\" default=\"\" tag=\"input\"/> |\n|<<lingo ServerURL>> |<$edit-text tiddler=\"$:/GitLab/ServerURL\" default=\"https://gitlab.com/api/v4\" tag=\"input\"/> |"
        },
        "$:/core/ui/ControlPanel/Saving/TiddlySpot": {
            "title": "$:/core/ui/ControlPanel/Saving/TiddlySpot",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/TiddlySpot/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Saving/TiddlySpot/\n\n\\define backupURL()\nhttp://$(userName)$.tiddlyspot.com/backup/\n\\end\n\\define backupLink()\n<$reveal type=\"nomatch\" state=\"$:/UploadName\" text=\"\">\n<$set name=\"userName\" value={{$:/UploadName}}>\n<$reveal type=\"match\" state=\"$:/UploadURL\" text=\"\">\n<<backupURL>>\n</$reveal>\n<$reveal type=\"nomatch\" state=\"$:/UploadURL\" text=\"\">\n<$macrocall $name=resolvePath source={{$:/UploadBackupDir}} root={{$:/UploadURL}}>>\n</$reveal>\n</$set>\n</$reveal>\n\\end\n\n<<lingo Description>>\n\n|<<lingo UserName>> |<$edit-text tiddler=\"$:/UploadName\" default=\"\" tag=\"input\"/> |\n|<<lingo Password>> |<$password name=\"upload\"/> |\n|<<lingo Backups>> |<<backupLink>> |\n\n''<<lingo Advanced/Heading>>''\n\n|<<lingo ServerURL>>  |<$edit-text tiddler=\"$:/UploadURL\" default=\"\" tag=\"input\"/> |\n|<<lingo Filename>> |<$edit-text tiddler=\"$:/UploadFilename\" default=\"index.html\" tag=\"input\"/> |\n|<<lingo UploadDir>> |<$edit-text tiddler=\"$:/UploadDir\" default=\".\" tag=\"input\"/> |\n|<<lingo BackupDir>> |<$edit-text tiddler=\"$:/UploadBackupDir\" default=\".\" tag=\"input\"/> |\n\n<<lingo TiddlySpot/Hint>>"
        },
        "$:/core/ui/ControlPanel/Saving/Gitea": {
            "title": "$:/core/ui/ControlPanel/Saving/Gitea",
            "tags": "$:/tags/ControlPanel/Saving",
            "caption": "{{$:/language/ControlPanel/Saving/GitService/Gitea/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Saving/GitService/\n\\define service-name() ~Gitea\n\n<<lingo Description>>\n\n|<<lingo UserName>> |<$edit-text tiddler=\"$:/Gitea/Username\" default=\"\" tag=\"input\"/> |\n|<<lingo Gitea/Password>> |<$password name=\"Gitea\"/> |\n|<<lingo Repo>> |<$edit-text tiddler=\"$:/Gitea/Repo\" default=\"\" tag=\"input\"/> |\n|<<lingo Branch>> |<$edit-text tiddler=\"$:/Gitea/Branch\" default=\"master\" tag=\"input\"/> |\n|<<lingo Path>> |<$edit-text tiddler=\"$:/Gitea/Path\" default=\"\" tag=\"input\"/> |\n|<<lingo Filename>> |<$edit-text tiddler=\"$:/Gitea/Filename\" default=\"\" tag=\"input\"/> |\n|<<lingo ServerURL>> |<$edit-text tiddler=\"$:/Gitea/ServerURL\" default=\"https://gitea/api/v1\" tag=\"input\"/> |\n"
        },
        "$:/core/ui/ControlPanel/Saving": {
            "title": "$:/core/ui/ControlPanel/Saving",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/Saving/Caption}}",
            "text": "{{$:/language/ControlPanel/Saving/Hint}}\n\n<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Saving]!has[draft.of]]\" \"$:/core/ui/ControlPanel/Saving/General\">>\n</div>\n"
        },
        "$:/core/buttonstyles/Borderless": {
            "title": "$:/core/buttonstyles/Borderless",
            "tags": "$:/tags/ToolbarButtonStyle",
            "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless}}",
            "text": "tc-btn-invisible"
        },
        "$:/core/buttonstyles/Boxed": {
            "title": "$:/core/buttonstyles/Boxed",
            "tags": "$:/tags/ToolbarButtonStyle",
            "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed}}",
            "text": "tc-btn-boxed"
        },
        "$:/core/buttonstyles/Rounded": {
            "title": "$:/core/buttonstyles/Rounded",
            "tags": "$:/tags/ToolbarButtonStyle",
            "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded}}",
            "text": "tc-btn-rounded"
        },
        "$:/core/ui/ControlPanel/Settings/CamelCase": {
            "title": "$:/core/ui/ControlPanel/Settings/CamelCase",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/CamelCase/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/CamelCase/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/WikiParserRules/Inline/wikilink\" field=\"text\" checked=\"enable\" unchecked=\"disable\" default=\"enable\"> <$link to=\"$:/config/WikiParserRules/Inline/wikilink\"><<lingo Description>></$link> </$checkbox>\n"
        },
        "$:/core/ui/ControlPanel/Settings/DefaultMoreSidebarTab": {
            "title": "$:/core/ui/ControlPanel/Settings/DefaultMoreSidebarTab",
            "caption": "{{$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Caption}}",
            "tags": "$:/tags/ControlPanel/Settings",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/DefaultMoreSidebarTab/\n\n<$link to=\"$:/config/DefaultMoreSidebarTab\"><<lingo Hint>></$link>\n\n<$select tiddler=\"$:/config/DefaultMoreSidebarTab\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]\">\n<option value=<<currentTiddler>>><$transclude field=\"caption\"><$text text=<<currentTiddler>>/></$transclude></option>\n</$list>\n</$select>\n"
        },
        "$:/core/ui/ControlPanel/Settings/DefaultSidebarTab": {
            "title": "$:/core/ui/ControlPanel/Settings/DefaultSidebarTab",
            "caption": "{{$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption}}",
            "tags": "$:/tags/ControlPanel/Settings",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/DefaultSidebarTab/\n\n<$link to=\"$:/config/DefaultSidebarTab\"><<lingo Hint>></$link>\n\n<$select tiddler=\"$:/config/DefaultSidebarTab\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SideBar]!has[draft.of]]\">\n<option value=<<currentTiddler>>><$transclude field=\"caption\"><$text text=<<currentTiddler>>/></$transclude></option>\n</$list>\n</$select>\n"
        },
        "$:/core/ui/ControlPanel/Settings/EditorToolbar": {
            "title": "$:/core/ui/ControlPanel/Settings/EditorToolbar",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/EditorToolbar/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/EditorToolbar/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/TextEditor/EnableToolbar\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/TextEditor/EnableToolbar\"><<lingo Description>></$link> </$checkbox>\n\n"
        },
        "$:/core/ui/ControlPanel/Settings/InfoPanelMode": {
            "title": "$:/core/ui/ControlPanel/Settings/InfoPanelMode",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/InfoPanelMode/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/InfoPanelMode/\n<$link to=\"$:/config/TiddlerInfo/Mode\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/TiddlerInfo/Mode\" value=\"popup\"> <<lingo Popup/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/TiddlerInfo/Mode\" value=\"sticky\"> <<lingo Sticky/Description>> </$radio>\n"
        },
        "$:/core/ui/ControlPanel/Settings/LinkToBehaviour": {
            "title": "$:/core/ui/ControlPanel/Settings/LinkToBehaviour",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/LinkToBehaviour/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/LinkToBehaviour/\n\n<$link to=\"$:/config/Navigation/openLinkFromInsideRiver\"><<lingo \"InsideRiver/Hint\">></$link>\n\n<$select tiddler=\"$:/config/Navigation/openLinkFromInsideRiver\">\n  <option value=\"above\"><<lingo \"OpenAbove\">></option>\n  <option value=\"below\"><<lingo \"OpenBelow\">></option>\n  <option value=\"top\"><<lingo \"OpenAtTop\">></option>\n  <option value=\"bottom\"><<lingo \"OpenAtBottom\">></option>\n</$select>\n\n<$link to=\"$:/config/Navigation/openLinkFromOutsideRiver\"><<lingo \"OutsideRiver/Hint\">></$link>\n\n<$select tiddler=\"$:/config/Navigation/openLinkFromOutsideRiver\">\n  <option value=\"top\"><<lingo \"OpenAtTop\">></option>\n  <option value=\"bottom\"><<lingo \"OpenAtBottom\">></option>\n</$select>\n"
        },
        "$:/core/ui/ControlPanel/Settings/MissingLinks": {
            "title": "$:/core/ui/ControlPanel/Settings/MissingLinks",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/MissingLinks/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/MissingLinks/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/MissingLinks\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/MissingLinks\"><<lingo Description>></$link> </$checkbox>\n\n"
        },
        "$:/core/ui/ControlPanel/Settings/NavigationAddressBar": {
            "title": "$:/core/ui/ControlPanel/Settings/NavigationAddressBar",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/NavigationAddressBar/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/NavigationAddressBar/\n\n<$link to=\"$:/config/Navigation/UpdateAddressBar\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateAddressBar\" value=\"permaview\"> <<lingo Permaview/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateAddressBar\" value=\"permalink\"> <<lingo Permalink/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateAddressBar\" value=\"no\"> <<lingo No/Description>> </$radio>\n"
        },
        "$:/core/ui/ControlPanel/Settings/NavigationHistory": {
            "title": "$:/core/ui/ControlPanel/Settings/NavigationHistory",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/NavigationHistory/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/NavigationHistory/\n<$link to=\"$:/config/Navigation/UpdateHistory\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateHistory\" value=\"yes\"> <<lingo Yes/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateHistory\" value=\"no\"> <<lingo No/Description>> </$radio>\n"
        },
        "$:/core/ui/ControlPanel/Settings/NavigationPermalinkviewMode": {
            "title": "$:/core/ui/ControlPanel/Settings/NavigationPermalinkviewMode",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/NavigationPermalinkviewMode/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/Navigation/Permalinkview/CopyToClipboard\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/Navigation/Permalinkview/CopyToClipboard\"><<lingo CopyToClipboard/Description>></$link> </$checkbox>\n\n<$checkbox tiddler=\"$:/config/Navigation/Permalinkview/UpdateAddressBar\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/Navigation/Permalinkview/UpdateAddressBar\"><<lingo UpdateAddressBar/Description>></$link> </$checkbox>\n"
        },
        "$:/core/ui/ControlPanel/Settings/PerformanceInstrumentation": {
            "title": "$:/core/ui/ControlPanel/Settings/PerformanceInstrumentation",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/PerformanceInstrumentation/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/Performance/Instrumentation\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> <$link to=\"$:/config/Performance/Instrumentation\"><<lingo Description>></$link> </$checkbox>\n"
        },
        "$:/core/ui/ControlPanel/Settings/TitleLinks": {
            "title": "$:/core/ui/ControlPanel/Settings/TitleLinks",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/TitleLinks/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/TitleLinks/\n<$link to=\"$:/config/Tiddlers/TitleLinks\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/Tiddlers/TitleLinks\" value=\"yes\"> <<lingo Yes/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Tiddlers/TitleLinks\" value=\"no\"> <<lingo No/Description>> </$radio>\n"
        },
        "$:/core/ui/ControlPanel/Settings/ToolbarButtonStyle": {
            "title": "$:/core/ui/ControlPanel/Settings/ToolbarButtonStyle",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/ToolbarButtonStyle/\n<$link to=\"$:/config/Toolbar/ButtonClass\"><<lingo \"Hint\">></$link>\n\n<$select tiddler=\"$:/config/Toolbar/ButtonClass\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ToolbarButtonStyle]]\">\n<option value={{!!text}}>{{!!caption}}</option>\n</$list>\n</$select>\n"
        },
        "$:/core/ui/ControlPanel/Settings/ToolbarButtons": {
            "title": "$:/core/ui/ControlPanel/Settings/ToolbarButtons",
            "tags": "$:/tags/ControlPanel/Settings",
            "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtons/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/ToolbarButtons/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/Toolbar/Icons\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/Toolbar/Icons\"><<lingo Icons/Description>></$link> </$checkbox>\n\n<$checkbox tiddler=\"$:/config/Toolbar/Text\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> <$link to=\"$:/config/Toolbar/Text\"><<lingo Text/Description>></$link> </$checkbox>\n"
        },
        "$:/core/ui/ControlPanel/Settings": {
            "title": "$:/core/ui/ControlPanel/Settings",
            "tags": "$:/tags/ControlPanel",
            "caption": "{{$:/language/ControlPanel/Settings/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/Settings/\n\n<<lingo Hint>>\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Settings]]\">\n\n<div style=\"border-top:1px solid #eee;\">\n\n!! <$link><$transclude field=\"caption\"/></$link>\n\n<$transclude/>\n\n</div>\n\n</$list>\n"
        },
        "$:/core/ui/ControlPanel/StoryView": {
            "title": "$:/core/ui/ControlPanel/StoryView",
            "tags": "$:/tags/ControlPanel/Appearance",
            "caption": "{{$:/language/ControlPanel/StoryView/Caption}}",
            "text": "{{$:/snippets/viewswitcher}}\n"
        },
        "$:/core/ui/ControlPanel/Stylesheets": {
            "title": "$:/core/ui/ControlPanel/Stylesheets",
            "tags": "$:/tags/ControlPanel/Advanced",
            "caption": "{{$:/language/ControlPanel/Stylesheets/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/\n\n<<lingo Stylesheets/Hint>>\n\n{{$:/snippets/peek-stylesheets}}\n"
        },
        "$:/core/ui/ControlPanel/Theme": {
            "title": "$:/core/ui/ControlPanel/Theme",
            "tags": "$:/tags/ControlPanel/Appearance",
            "caption": "{{$:/language/ControlPanel/Theme/Caption}}",
            "text": "{{$:/snippets/themeswitcher}}\n"
        },
        "$:/core/ui/ControlPanel/TiddlerFields": {
            "title": "$:/core/ui/ControlPanel/TiddlerFields",
            "tags": "$:/tags/ControlPanel/Advanced",
            "caption": "{{$:/language/ControlPanel/TiddlerFields/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/\n\n<<lingo TiddlerFields/Hint>>\n\n{{$:/snippets/allfields}}"
        },
        "$:/core/ui/ControlPanel/Toolbars/EditToolbar": {
            "title": "$:/core/ui/ControlPanel/Toolbars/EditToolbar",
            "tags": "$:/tags/ControlPanel/Toolbars",
            "caption": "{{$:/language/ControlPanel/Toolbars/EditToolbar/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/EditToolbarButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/EditToolbar/Hint}}\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/EditToolbar\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/ItemTemplate\"/>\n\n</$set>\n\n</$set>"
        },
        "$:/core/ui/ControlPanel/Toolbars/EditorItemTemplate": {
            "title": "$:/core/ui/ControlPanel/Toolbars/EditorItemTemplate",
            "text": "\\define config-title()\n$(config-base)$$(currentTiddler)$\n\\end\n\n<$draggable tiddler=<<currentTiddler>>>\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <span class=\"tc-icon-wrapper\"><$transclude tiddler={{!!icon}}/></span> <$transclude field=\"caption\"/> -- <i class=\"tc-muted\"><$transclude field=\"description\"/></i>\n</$draggable>\n"
        },
        "$:/core/ui/ControlPanel/Toolbars/EditorToolbar": {
            "title": "$:/core/ui/ControlPanel/Toolbars/EditorToolbar",
            "tags": "$:/tags/ControlPanel/Toolbars",
            "caption": "{{$:/language/ControlPanel/Toolbars/EditorToolbar/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/EditorToolbarButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/EditorToolbar/Hint}}\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/EditorToolbar\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/EditorItemTemplate\"/>\n"
        },
        "$:/core/ui/ControlPanel/Toolbars/ItemTemplate": {
            "title": "$:/core/ui/ControlPanel/Toolbars/ItemTemplate",
            "text": "\\define config-title()\n$(config-base)$$(currentTiddler)$\n\\end\n\n<$draggable tiddler=<<currentTiddler>>>\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <span class=\"tc-icon-wrapper\"> <$transclude field=\"caption\"/> <i class=\"tc-muted\">-- <$transclude field=\"description\"/></i></span>\n</$draggable>\n"
        },
        "$:/core/ui/ControlPanel/Toolbars/PageControls": {
            "title": "$:/core/ui/ControlPanel/Toolbars/PageControls",
            "tags": "$:/tags/ControlPanel/Toolbars",
            "caption": "{{$:/language/ControlPanel/Toolbars/PageControls/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/PageControlButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/PageControls/Hint}}\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/PageControls\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/ItemTemplate\"/>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/ControlPanel/Toolbars/ViewToolbar": {
            "title": "$:/core/ui/ControlPanel/Toolbars/ViewToolbar",
            "tags": "$:/tags/ControlPanel/Toolbars",
            "caption": "{{$:/language/ControlPanel/Toolbars/ViewToolbar/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/ViewToolbarButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/ViewToolbar/Hint}}\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/ViewToolbar\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/ItemTemplate\"/>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/ControlPanel/Toolbars": {
            "title": "$:/core/ui/ControlPanel/Toolbars",
            "tags": "$:/tags/ControlPanel/Appearance",
            "caption": "{{$:/language/ControlPanel/Toolbars/Caption}}",
            "text": "{{$:/language/ControlPanel/Toolbars/Hint}}\n\n<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Toolbars]!has[draft.of]]\" \"$:/core/ui/ControlPanel/Toolbars/ViewToolbar\" \"$:/state/tabs/controlpanel/toolbars\" \"tc-vertical\">>\n</div>\n"
        },
        "$:/ControlPanel": {
            "title": "$:/ControlPanel",
            "icon": "$:/core/images/options-button",
            "color": "#bbb",
            "text": "<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel]!has[draft.of]]\" \"$:/core/ui/ControlPanel/Info\">>\n</div>\n"
        },
        "$:/core/ui/DefaultSearchResultList": {
            "title": "$:/core/ui/DefaultSearchResultList",
            "tags": "$:/tags/SearchResults",
            "caption": "{{$:/language/Search/DefaultResults/Caption}}",
            "text": "\\define searchResultList()\n//<small>{{$:/language/Search/Matches/Title}}</small>//\n\n<$list filter=\"[!is[system]search:title{$(searchTiddler)$}sort[title]limit[250]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n\n//<small>{{$:/language/Search/Matches/All}}</small>//\n\n<$list filter=\"[!is[system]search{$(searchTiddler)$}sort[title]limit[250]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n\n\\end\n<<searchResultList>>\n"
        },
        "$:/core/ui/EditTemplate/body/preview/diffs-current": {
            "title": "$:/core/ui/EditTemplate/body/preview/diffs-current",
            "tags": "$:/tags/EditPreview",
            "caption": "differences from current",
            "list-after": "$:/core/ui/EditTemplate/body/preview/output",
            "text": "<$list filter=\"[<currentTiddler>!is[image]]\" emptyMessage={{$:/core/ui/EditTemplate/body/preview/output}}>\n\n<$macrocall $name=\"compareTiddlerText\" sourceTiddlerTitle={{!!draft.of}} destTiddlerTitle=<<currentTiddler>>/>\n\n</$list>\n\n"
        },
        "$:/core/ui/EditTemplate/body/preview/diffs-shadow": {
            "title": "$:/core/ui/EditTemplate/body/preview/diffs-shadow",
            "tags": "$:/tags/EditPreview",
            "caption": "differences from shadow (if any)",
            "list-after": "$:/core/ui/EditTemplate/body/preview/output",
            "text": "<$list filter=\"[<currentTiddler>!is[image]]\" emptyMessage={{$:/core/ui/EditTemplate/body/preview/output}}>\n\n<$macrocall $name=\"compareTiddlerText\" sourceTiddlerTitle={{{ [{!!draft.of}shadowsource[]] }}} sourceSubTiddlerTitle={{!!draft.of}} destTiddlerTitle=<<currentTiddler>>/>\n\n</$list>\n\n"
        },
        "$:/core/ui/EditTemplate/body/preview/output": {
            "title": "$:/core/ui/EditTemplate/body/preview/output",
            "tags": "$:/tags/EditPreview",
            "caption": "{{$:/language/EditTemplate/Body/Preview/Type/Output}}",
            "text": "\\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]]\n<$set name=\"tv-tiddler-preview\" value=\"yes\">\n\n<$transclude />\n\n</$set>\n"
        },
        "$:/state/showeditpreview": {
            "title": "$:/state/showeditpreview",
            "text": "no"
        },
        "$:/core/ui/EditTemplate/body/editor": {
            "title": "$:/core/ui/EditTemplate/body/editor",
            "text": "<$edit\n\n  field=\"text\"\n  class=\"tc-edit-texteditor tc-edit-texteditor-body\"\n  placeholder={{$:/language/EditTemplate/Body/Placeholder}}\n  tabindex={{$:/config/EditTabIndex}}\n  focus={{{ [{$:/config/AutoFocus}match[text]then[true]] ~[[false]] }}}\n\n><$set\n\n  name=\"targetTiddler\"\n  value=<<currentTiddler>>\n\n><$list\n\n  filter=\"[all[shadows+tiddlers]tag[$:/tags/EditorToolbar]!has[draft.of]]\"\n\n><$reveal\n\n  type=\"nomatch\"\n  state=<<config-visibility-title>>\n  text=\"hide\"\n  class=\"tc-text-editor-toolbar-item-wrapper\"\n\n><$transclude\n\n  tiddler=\"$:/core/ui/EditTemplate/body/toolbar/button\"\n  mode=\"inline\"\n\n/></$reveal></$list></$set></$edit>\n"
        },
        "$:/core/ui/EditTemplate/body/toolbar/button": {
            "title": "$:/core/ui/EditTemplate/body/toolbar/button",
            "text": "\\define toolbar-button-icon()\n<$list\n\n  filter=\"[all[current]!has[custom-icon]]\"\n  variable=\"no-custom-icon\"\n\n><$transclude\n\n  tiddler={{!!icon}}\n\n/></$list>\n\\end\n\n\\define toolbar-button-tooltip()\n{{!!description}}<$macrocall $name=\"displayshortcuts\" $output=\"text/plain\" shortcuts={{!!shortcuts}} prefix=\"` - [\" separator=\"] [\" suffix=\"]`\"/>\n\\end\n\n\\define toolbar-button()\n<$list\n\n  filter={{!!condition}}\n  variable=\"list-condition\"\n\n><$wikify\n\n  name=\"tooltip-text\"\n  text=<<toolbar-button-tooltip>>\n  mode=\"inline\"\n  output=\"text\"\n\n><$list\n\n  filter=\"[all[current]!has[dropdown]]\"\n  variable=\"no-dropdown\"\n\n><$button\n\n  class=\"tc-btn-invisible $(buttonClasses)$\"\n  tooltip=<<tooltip-text>>\n  actions={{!!actions}}\n\n><span\n\n  data-tw-keyboard-shortcut={{!!shortcuts}}\n\n/><<toolbar-button-icon>><$transclude\n\n  tiddler=<<currentTiddler>>\n  field=\"text\"\n\n/></$button></$list><$list\n\n  filter=\"[all[current]has[dropdown]]\"\n  variable=\"dropdown\"\n\n><$set\n\n  name=\"dropdown-state\"\n  value=<<qualify \"$:/state/EditorToolbarDropdown\">>\n\n><$button\n\n  popup=<<dropdown-state>>\n  class=\"tc-popup-keep tc-btn-invisible $(buttonClasses)$\"\n  selectedClass=\"tc-selected\"\n  tooltip=<<tooltip-text>>\n  actions={{!!actions}}\n\n><span\n\n  data-tw-keyboard-shortcut={{!!shortcuts}}\n\n/><<toolbar-button-icon>><$transclude\n\n  tiddler=<<currentTiddler>>\n  field=\"text\"\n\n/></$button><$reveal\n\n  state=<<dropdown-state>>\n  type=\"popup\"\n  position=\"below\"\n  animate=\"yes\"\n  tag=\"span\"\n\n><div\n\n  class=\"tc-drop-down tc-popup-keep\"\n\n><$transclude\n\n  tiddler={{!!dropdown}}\n  mode=\"block\"\n\n/></div></$reveal></$set></$list></$wikify></$list>\n\\end\n\n\\define toolbar-button-outer()\n<$set\n\n  name=\"buttonClasses\"\n  value={{!!button-classes}}\n\n><<toolbar-button>></$set>\n\\end\n\n<<toolbar-button-outer>>"
        },
        "$:/core/ui/EditTemplate/body": {
            "title": "$:/core/ui/EditTemplate/body",
            "tags": "$:/tags/EditTemplate",
            "text": "\\define lingo-base() $:/language/EditTemplate/Body/\n\\define config-visibility-title()\n$:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$\n\\end\n<$list filter=\"[all[current]has[_canonical_uri]]\">\n\n<div class=\"tc-message-box\">\n\n<<lingo External/Hint>>\n\n<a href={{!!_canonical_uri}}><$text text={{!!_canonical_uri}}/></a>\n\n<$edit-text field=\"_canonical_uri\" class=\"tc-edit-fields\" tabindex={{$:/config/EditTabIndex}}></$edit-text>\n\n</div>\n\n</$list>\n\n<$list filter=\"[all[current]!has[_canonical_uri]]\">\n\n<$reveal state=\"$:/state/showeditpreview\" type=\"match\" text=\"yes\">\n\n<div class=\"tc-tiddler-preview\">\n\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/editor\" mode=\"inline\"/>\n\n<div class=\"tc-tiddler-preview-preview\">\n\n<$transclude tiddler={{$:/state/editpreviewtype}} mode=\"inline\">\n\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/preview/output\" mode=\"inline\"/>\n\n</$transclude>\n\n</div>\n\n</div>\n\n</$reveal>\n\n<$reveal state=\"$:/state/showeditpreview\" type=\"nomatch\" text=\"yes\">\n\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/editor\" mode=\"inline\"/>\n\n</$reveal>\n\n</$list>\n"
        },
        "$:/core/ui/EditTemplate/controls": {
            "title": "$:/core/ui/EditTemplate/controls",
            "tags": "$:/tags/EditTemplate",
            "text": "\\define config-title()\n$:/config/EditToolbarButtons/Visibility/$(listItem)$\n\\end\n<div class=\"tc-tiddler-title tc-tiddler-edit-title\">\n<$view field=\"title\"/>\n<span class=\"tc-tiddler-controls tc-titlebar\"><$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditToolbar]!has[draft.of]]\" variable=\"listItem\"><$reveal type=\"nomatch\" state=<<config-title>> text=\"hide\"><$transclude tiddler=<<listItem>>/></$reveal></$list></span>\n<div style=\"clear: both;\"></div>\n</div>\n"
        },
        "$:/core/ui/EditTemplate/fields": {
            "title": "$:/core/ui/EditTemplate/fields",
            "tags": "$:/tags/EditTemplate",
            "text": "\\define lingo-base() $:/language/EditTemplate/\n\\define config-title()\n$:/config/EditTemplateFields/Visibility/$(currentField)$\n\\end\n\n\\define config-filter()\n[[hide]] -[title{$(config-title)$}]\n\\end\n\n\\define current-tiddler-new-field-selector()\n[data-tiddler-title=\"$(currentTiddlerCSSescaped)$\"] .tc-edit-field-add-name input\n\\end\n\n\\define new-field-actions()\n<$action-sendmessage $message=\"tm-add-field\" $name={{{ [<newFieldNameTiddler>get[text]] }}} $value={{{ [<newFieldValueTiddler>get[text]] }}}/>\n<$action-deletetiddler $tiddler=<<newFieldNameTiddler>>/>\n<$action-deletetiddler $tiddler=<<newFieldValueTiddler>>/>\n<$action-sendmessage $message=\"tm-focus-selector\" $param=<<current-tiddler-new-field-selector>>/>\n\\end\n\n\\define new-field()\n<$vars name={{{ [<newFieldNameTiddler>get[text]] }}}>\n<$reveal type=\"nomatch\" text=\"\" default=<<name>>>\n<$button tooltip=<<lingo Fields/Add/Button/Hint>>>\n<$action-sendmessage $message=\"tm-add-field\"\n$name=<<name>>\n$value={{{ [<newFieldValueTiddler>get[text]] }}}/>\n<$action-deletetiddler $tiddler=<<newFieldNameTiddler>>/>\n<$action-deletetiddler $tiddler=<<newFieldValueTiddler>>/>\n<<lingo Fields/Add/Button>>\n</$button>\n</$reveal>\n<$reveal type=\"match\" text=\"\" default=<<name>>>\n<$button>\n<<lingo Fields/Add/Button>>\n</$button>\n</$reveal>\n</$vars>\n\\end\n\\whitespace trim\n\n<div class=\"tc-edit-fields\">\n<table class=\"tc-edit-fields\">\n<tbody>\n<$list filter=\"[all[current]fields[]] +[sort[title]]\" variable=\"currentField\" storyview=\"pop\">\n<$list filter=<<config-filter>> variable=\"temp\">\n<tr class=\"tc-edit-field\">\n<td class=\"tc-edit-field-name\">\n<$text text=<<currentField>>/>:</td>\n<td class=\"tc-edit-field-value\">\n<$edit-text tiddler=<<currentTiddler>> field=<<currentField>> placeholder={{$:/language/EditTemplate/Fields/Add/Value/Placeholder}} tabindex={{$:/config/EditTabIndex}}/>\n</td>\n<td class=\"tc-edit-field-remove\">\n<$button class=\"tc-btn-invisible\" tooltip={{$:/language/EditTemplate/Field/Remove/Hint}} aria-label={{$:/language/EditTemplate/Field/Remove/Caption}}>\n<$action-deletefield $field=<<currentField>>/>\n{{$:/core/images/delete-button}}\n</$button>\n</td>\n</tr>\n</$list>\n</$list>\n</tbody>\n</table>\n</div>\n\n<$fieldmangler>\n<div class=\"tc-edit-field-add\">\n<em class=\"tc-edit\">\n<<lingo Fields/Add/Prompt>>&nbsp;&nbsp;\n</em>\n<span class=\"tc-edit-field-add-name\">\n<$edit-text tiddler=<<newFieldNameTiddler>> tag=\"input\" default=\"\" placeholder={{$:/language/EditTemplate/Fields/Add/Name/Placeholder}} focusPopup=<<qualify \"$:/state/popup/field-dropdown\">> class=\"tc-edit-texteditor tc-popup-handle\" tabindex={{$:/config/EditTabIndex}} focus={{{ [{$:/config/AutoFocus}match[fields]then[true]] ~[[false]] }}}/>\n</span>&nbsp;\n<$button popup=<<qualify \"$:/state/popup/field-dropdown\">> class=\"tc-btn-invisible tc-btn-dropdown\" tooltip={{$:/language/EditTemplate/Field/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Field/Dropdown/Caption}}>{{$:/core/images/down-arrow}}</$button>&nbsp;\n<$reveal state=<<qualify \"$:/state/popup/field-dropdown\">> type=\"nomatch\" text=\"\" default=\"\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<$set name=\"tv-show-missing-links\" value=\"yes\">\n<$linkcatcher to=<<newFieldNameTiddler>>>\n<div class=\"tc-dropdown-item\">\n<<lingo Fields/Add/Dropdown/User>>\n</div>\n<$set name=\"newFieldName\" value={{{ [<newFieldNameTiddler>get[text]] }}}>\n<$list filter=\"[!is[shadow]!is[system]fields[]search:title<newFieldName>sort[]] -created -creator -draft.of -draft.title -modified -modifier -tags -text -title -type\"  variable=\"currentField\">\n<$link to=<<currentField>>>\n<$text text=<<currentField>>/>\n</$link>\n</$list>\n<div class=\"tc-dropdown-item\">\n<<lingo Fields/Add/Dropdown/System>>\n</div>\n<$list filter=\"[fields[]search:title<newFieldName>sort[]] -[!is[shadow]!is[system]fields[]]\" variable=\"currentField\">\n<$link to=<<currentField>>>\n<$text text=<<currentField>>/>\n</$link>\n</$list>\n</$set>\n</$linkcatcher>\n</$set>\n</div>\n</$reveal>\n<span class=\"tc-edit-field-add-value\">\n<$set name=\"currentTiddlerCSSescaped\" value={{{ [<currentTiddler>escapecss[]] }}}>\n<$keyboard key=\"((add-field))\" actions=<<new-field-actions>>>\n<$edit-text tiddler=<<newFieldValueTiddler>> tag=\"input\" default=\"\" placeholder={{$:/language/EditTemplate/Fields/Add/Value/Placeholder}} class=\"tc-edit-texteditor\" tabindex={{$:/config/EditTabIndex}}/>\n</$keyboard>\n</$set>\n</span>&nbsp;\n<span class=\"tc-edit-field-add-button\">\n<$macrocall $name=\"new-field\"/>\n</span>\n</div>\n</$fieldmangler>\n"
        },
        "$:/core/ui/EditTemplate/shadow": {
            "title": "$:/core/ui/EditTemplate/shadow",
            "tags": "$:/tags/EditTemplate",
            "text": "\\define lingo-base() $:/language/EditTemplate/Shadow/\n\\define pluginLinkBody()\n<$link to=\"\"\"$(pluginTitle)$\"\"\">\n<$text text=\"\"\"$(pluginTitle)$\"\"\"/>\n</$link>\n\\end\n<$list filter=\"[all[current]get[draft.of]is[shadow]!is[tiddler]]\">\n\n<$list filter=\"[all[current]shadowsource[]]\" variable=\"pluginTitle\">\n\n<$set name=\"pluginLink\" value=<<pluginLinkBody>>>\n<div class=\"tc-message-box\">\n\n<<lingo Warning>>\n\n</div>\n</$set>\n</$list>\n\n</$list>\n\n<$list filter=\"[all[current]get[draft.of]is[shadow]is[tiddler]]\">\n\n<$list filter=\"[all[current]shadowsource[]]\" variable=\"pluginTitle\">\n\n<$set name=\"pluginLink\" value=<<pluginLinkBody>>>\n<div class=\"tc-message-box\">\n\n<<lingo OverriddenWarning>>\n\n</div>\n</$set>\n</$list>\n\n</$list>"
        },
        "$:/core/ui/EditTemplate/tags": {
            "title": "$:/core/ui/EditTemplate/tags",
            "tags": "$:/tags/EditTemplate",
            "text": "\\whitespace trim\n\n\\define lingo-base() $:/language/EditTemplate/\n\n\\define tag-styles()\nbackground-color:$(backgroundColor)$;\nfill:$(foregroundColor)$;\ncolor:$(foregroundColor)$;\n\\end\n\n\\define tag-body-inner(colour,fallbackTarget,colourA,colourB,icon)\n\\whitespace trim\n<$vars foregroundColor=<<contrastcolour target:\"\"\"$colour$\"\"\" fallbackTarget:\"\"\"$fallbackTarget$\"\"\" colourA:\"\"\"$colourA$\"\"\" colourB:\"\"\"$colourB$\"\"\">> backgroundColor=\"\"\"$colour$\"\"\">\n<span style=<<tag-styles>> class=\"tc-tag-label tc-tag-list-item\">\n<$transclude tiddler=\"\"\"$icon$\"\"\"/><$view field=\"title\" format=\"text\" />\n<$button message=\"tm-remove-tag\" param={{!!title}} class=\"tc-btn-invisible tc-remove-tag-button\">{{$:/core/images/close-button}}</$button>\n</span>\n</$vars>\n\\end\n\n\\define tag-body(colour,palette,icon)\n<$macrocall $name=\"tag-body-inner\" colour=\"\"\"$colour$\"\"\" fallbackTarget={{$palette$##tag-background}} colourA={{$palette$##foreground}} colourB={{$palette$##background}} icon=\"\"\"$icon$\"\"\"/>\n\\end\n\n<div class=\"tc-edit-tags\">\n<$fieldmangler>\n<$list filter=\"[all[current]tags[]sort[title]]\" storyview=\"pop\">\n<$macrocall $name=\"tag-body\" colour={{!!color}} palette={{$:/palette}} icon={{!!icon}}/>\n</$list>\n<$set name=\"tabIndex\" value={{$:/config/EditTabIndex}}>\n<$macrocall $name=\"tag-picker\"/>\n</$set>\n</$fieldmangler>\n</div>\n"
        },
        "$:/core/ui/EditTemplate/title": {
            "title": "$:/core/ui/EditTemplate/title",
            "tags": "$:/tags/EditTemplate",
            "text": "<$edit-text field=\"draft.title\" class=\"tc-titlebar tc-edit-texteditor\" focus={{{ [{$:/config/AutoFocus}match[title]then[true]] ~[[false]] }}} tabindex={{$:/config/EditTabIndex}}/>\n\n<$vars pattern=\"\"\"[\\|\\[\\]{}]\"\"\" bad-chars=\"\"\"`| [ ] { }`\"\"\">\n\n<$list filter=\"[all[current]regexp:draft.title<pattern>]\" variable=\"listItem\">\n\n<div class=\"tc-message-box\">\n\n{{$:/core/images/warning}} {{$:/language/EditTemplate/Title/BadCharacterWarning}}\n\n</div>\n\n</$list>\n\n</$vars>\n\n<$reveal state=\"!!draft.title\" type=\"nomatch\" text={{!!draft.of}} tag=\"div\">\n\n<$list filter=\"[{!!draft.title}!is[missing]]\" variable=\"listItem\">\n\n<div class=\"tc-message-box\">\n\n{{$:/core/images/warning}} {{$:/language/EditTemplate/Title/Exists/Prompt}}\n\n</div>\n\n</$list>\n\n<$list filter=\"[{!!draft.of}!is[missing]]\" variable=\"listItem\">\n\n<$vars fromTitle={{!!draft.of}} toTitle={{!!draft.title}}>\n\n<$checkbox tiddler=\"$:/config/RelinkOnRename\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> {{$:/language/EditTemplate/Title/Relink/Prompt}}</$checkbox>\n\n<$list filter=\"[title<fromTitle>backlinks[]limit[1]]\" variable=\"listItem\">\n\n<$vars stateTiddler=<<qualify \"$:/state/edit/references\">> >\n\n<$reveal type=\"nomatch\" state=<<stateTiddler>> text=\"show\">\n<$button set=<<stateTiddler>> setTo=\"show\" class=\"tc-btn-invisible\">{{$:/core/images/right-arrow}} \n<<lingo EditTemplate/Title/References/Prompt>></$button>\n</$reveal>\n<$reveal type=\"match\" state=<<stateTiddler>> text=\"show\">\n<$button set=<<stateTiddler>> setTo=\"hide\" class=\"tc-btn-invisible\">{{$:/core/images/down-arrow}} \n<<lingo EditTemplate/Title/References/Prompt>></$button>\n</$reveal>\n\n<$reveal type=\"match\" state=<<stateTiddler>> text=\"show\">\n<$tiddler tiddler=<<fromTitle>> >\n<$transclude tiddler=\"$:/core/ui/TiddlerInfo/References\"/>\n</$tiddler>\n</$reveal>\n\n</$vars>\n\n</$list>\n\n</$vars>\n\n</$list>\n\n</$reveal>\n"
        },
        "$:/core/ui/EditTemplate/type": {
            "title": "$:/core/ui/EditTemplate/type",
            "tags": "$:/tags/EditTemplate",
            "text": "\\define lingo-base() $:/language/EditTemplate/\n\\whitespace trim\n<div class=\"tc-type-selector\"><$fieldmangler>\n<em class=\"tc-edit\"><<lingo Type/Prompt>></em>&nbsp;&nbsp;<$edit-text field=\"type\" tag=\"input\" default=\"\" placeholder={{$:/language/EditTemplate/Type/Placeholder}} focusPopup=<<qualify \"$:/state/popup/type-dropdown\">> class=\"tc-edit-typeeditor tc-edit-texteditor tc-popup-handle\" tabindex={{$:/config/EditTabIndex}} focus={{{ [{$:/config/AutoFocus}match[type]then[true]] ~[[false]] }}}/>&nbsp;<$button popup=<<qualify \"$:/state/popup/type-dropdown\">> class=\"tc-btn-invisible tc-btn-dropdown\" tooltip={{$:/language/EditTemplate/Type/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Type/Dropdown/Caption}}>{{$:/core/images/down-arrow}}</$button>&nbsp;<$button message=\"tm-remove-field\" param=\"type\" class=\"tc-btn-invisible tc-btn-icon\" tooltip={{$:/language/EditTemplate/Type/Delete/Hint}} aria-label={{$:/language/EditTemplate/Type/Delete/Caption}}>{{$:/core/images/delete-button}}</$button>\n</$fieldmangler></div>\n\n<div class=\"tc-block-dropdown-wrapper\">\n<$set name=\"tv-show-missing-links\" value=\"yes\">\n<$reveal state=<<qualify \"$:/state/popup/type-dropdown\">> type=\"nomatch\" text=\"\" default=\"\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<$linkcatcher to=\"!!type\">\n<$list filter='[all[shadows+tiddlers]prefix[$:/language/Docs/Types/]each[group]sort[group-sort]]'>\n<div class=\"tc-dropdown-item\">\n<$text text={{!!group}}/>\n</div>\n<$list filter=\"[all[shadows+tiddlers]prefix[$:/language/Docs/Types/]group{!!group}] +[sort[description]]\"><$link to={{!!name}}><$view field=\"description\"/> (<$view field=\"name\"/>)</$link>\n</$list>\n</$list>\n</$linkcatcher>\n</div>\n</$reveal>\n</$set>\n</div>\n"
        },
        "$:/core/ui/EditTemplate": {
            "title": "$:/core/ui/EditTemplate",
            "text": "\\define save-tiddler-actions()\n<$action-sendmessage $message=\"tm-add-tag\" $param={{{ [<newTagNameTiddler>get[text]] }}}/>\n<$action-deletetiddler $tiddler=<<newTagNameTiddler>>/>\n<$action-sendmessage $message=\"tm-add-field\" $name={{{ [<newFieldNameTiddler>get[text]] }}} $value={{{ [<newFieldValueTiddler>get[text]] }}}/>\n<$action-deletetiddler $tiddler=<<newFieldNameTiddler>>/>\n<$action-deletetiddler $tiddler=<<newFieldValueTiddler>>/>\n<$action-sendmessage $message=\"tm-save-tiddler\"/>\n\\end\n<div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ tc-tiddler-frame tc-tiddler-edit-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}}>\n<$fieldmangler>\n<$vars storyTiddler=<<currentTiddler>> newTagNameTiddler=<<qualify \"$:/temp/NewTagName\">> newFieldNameTiddler=<<qualify \"$:/temp/NewFieldName\">> newFieldValueTiddler=<<qualify \"$:/temp/NewFieldValue\">>>\n<$keyboard key=\"((cancel-edit-tiddler))\" message=\"tm-cancel-tiddler\">\n<$keyboard key=\"((save-tiddler))\" actions=<<save-tiddler-actions>>>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditTemplate]!has[draft.of]]\" variable=\"listItem\">\n<$set name=\"tv-config-toolbar-class\" filter=\"[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]\">\n<$transclude tiddler=<<listItem>>/>\n</$set>\n</$list>\n</$keyboard>\n</$keyboard>\n</$vars>\n</$fieldmangler>\n</div>\n"
        },
        "$:/core/ui/Buttons/cancel": {
            "title": "$:/core/ui/Buttons/cancel",
            "tags": "$:/tags/EditToolbar",
            "caption": "{{$:/core/images/cancel-button}} {{$:/language/Buttons/Cancel/Caption}}",
            "description": "{{$:/language/Buttons/Cancel/Hint}}",
            "text": "<$button message=\"tm-cancel-tiddler\" tooltip={{$:/language/Buttons/Cancel/Hint}} aria-label={{$:/language/Buttons/Cancel/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/cancel-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Cancel/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/delete": {
            "title": "$:/core/ui/Buttons/delete",
            "tags": "$:/tags/EditToolbar $:/tags/ViewToolbar",
            "caption": "{{$:/core/images/delete-button}} {{$:/language/Buttons/Delete/Caption}}",
            "description": "{{$:/language/Buttons/Delete/Hint}}",
            "text": "<$button message=\"tm-delete-tiddler\" tooltip={{$:/language/Buttons/Delete/Hint}} aria-label={{$:/language/Buttons/Delete/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/delete-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Delete/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/save": {
            "title": "$:/core/ui/Buttons/save",
            "tags": "$:/tags/EditToolbar",
            "caption": "{{$:/core/images/done-button}} {{$:/language/Buttons/Save/Caption}}",
            "description": "{{$:/language/Buttons/Save/Hint}}",
            "text": "\\define save-tiddler-button()\n<$fieldmangler><$button tooltip={{$:/language/Buttons/Save/Hint}} aria-label={{$:/language/Buttons/Save/Caption}} class=<<tv-config-toolbar-class>>>\n<<save-tiddler-actions>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/done-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Save/Caption}}/></span>\n</$list>\n</$button></$fieldmangler>\n\\end\n<<save-tiddler-button>>\n"
        },
        "$:/core/ui/EditorToolbar/bold": {
            "title": "$:/core/ui/EditorToolbar/bold",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/bold",
            "caption": "{{$:/language/Buttons/Bold/Caption}}",
            "description": "{{$:/language/Buttons/Bold/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((bold))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"''\"\n\tsuffix=\"''\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/clear-dropdown": {
            "title": "$:/core/ui/EditorToolbar/clear-dropdown",
            "text": "''{{$:/language/Buttons/Clear/Hint}}''\n\n<div class=\"tc-colour-chooser\">\n\n<$macrocall $name=\"colour-picker\" actions=\"\"\"\n\n<$action-sendmessage\n\t$message=\"tm-edit-bitmap-operation\"\n\t$param=\"clear\"\n\tcolour=<<colour-picker-value>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n\"\"\"/>\n\n</div>\n"
        },
        "$:/core/ui/EditorToolbar/clear": {
            "title": "$:/core/ui/EditorToolbar/clear",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/erase",
            "caption": "{{$:/language/Buttons/Clear/Caption}}",
            "description": "{{$:/language/Buttons/Clear/Hint}}",
            "condition": "[<targetTiddler>is[image]]",
            "dropdown": "$:/core/ui/EditorToolbar/clear-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/editor-height-dropdown": {
            "title": "$:/core/ui/EditorToolbar/editor-height-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/EditorHeight/\n''<<lingo Hint>>''\n\n<$radio tiddler=\"$:/config/TextEditor/EditorHeight/Mode\" value=\"auto\"> {{$:/core/images/auto-height}} <<lingo Caption/Auto>></$radio>\n\n<$radio tiddler=\"$:/config/TextEditor/EditorHeight/Mode\" value=\"fixed\"> {{$:/core/images/fixed-height}} <<lingo Caption/Fixed>> <$edit-text tag=\"input\" tiddler=\"$:/config/TextEditor/EditorHeight/Height\" default=\"100px\"/></$radio>\n"
        },
        "$:/core/ui/EditorToolbar/editor-height": {
            "title": "$:/core/ui/EditorToolbar/editor-height",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/fixed-height",
            "custom-icon": "yes",
            "caption": "{{$:/language/Buttons/EditorHeight/Caption}}",
            "description": "{{$:/language/Buttons/EditorHeight/Hint}}",
            "condition": "[<targetTiddler>type[]] [<targetTiddler>get[type]prefix[text/]] +[first[]]",
            "dropdown": "$:/core/ui/EditorToolbar/editor-height-dropdown",
            "text": "<$reveal tag=\"span\" state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"fixed\">\n{{$:/core/images/fixed-height}}\n</$reveal>\n<$reveal tag=\"span\" state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"auto\">\n{{$:/core/images/auto-height}}\n</$reveal>\n"
        },
        "$:/core/ui/EditorToolbar/excise-dropdown": {
            "title": "$:/core/ui/EditorToolbar/excise-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/Excise/\n\n\\define body(config-title)\n''<<lingo Hint>>''\n\n<<lingo Caption/NewTitle>> <$edit-text tag=\"input\" tiddler=\"$config-title$/new-title\" default=\"\" focus=\"true\"/>\n\n<$set name=\"new-title\" value={{$config-title$/new-title}}>\n<$list filter=\"\"\"[<new-title>is[tiddler]]\"\"\">\n<div class=\"tc-error\">\n<<lingo Caption/TiddlerExists>>\n</div>\n</$list>\n</$set>\n\n<$checkbox tiddler=\"\"\"$config-title$/tagnew\"\"\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"false\"> <<lingo Caption/Tag>></$checkbox>\n\n<<lingo Caption/Replace>> <$select tiddler=\"\"\"$config-title$/type\"\"\" default=\"transclude\">\n<option value=\"link\"><<lingo Caption/Replace/Link>></option>\n<option value=\"transclude\"><<lingo Caption/Replace/Transclusion>></option>\n<option value=\"macro\"><<lingo Caption/Replace/Macro>></option>\n</$select>\n\n<$reveal state=\"\"\"$config-title$/type\"\"\" type=\"match\" text=\"macro\">\n<<lingo Caption/MacroName>> <$edit-text tag=\"input\" tiddler=\"\"\"$config-title$/macro-title\"\"\" default=\"translink\"/>\n</$reveal>\n\n<$button>\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"excise\"\n\ttitle={{$config-title$/new-title}}\n\ttype={{$config-title$/type}}\n\tmacro={{$config-title$/macro-title}}\n\ttagnew={{$config-title$/tagnew}}\n/>\n<$action-deletetiddler\n\t$tiddler=\"$config-title$/new-title\"\n/>\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n<<lingo Caption/Excise>>\n</$button>\n\\end\n\n<$macrocall $name=\"body\" config-title=<<qualify \"$:/state/Excise/\">>/>\n"
        },
        "$:/core/ui/EditorToolbar/excise": {
            "title": "$:/core/ui/EditorToolbar/excise",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/excise",
            "caption": "{{$:/language/Buttons/Excise/Caption}}",
            "description": "{{$:/language/Buttons/Excise/Hint}}",
            "condition": "[<targetTiddler>type[]] [<targetTiddler>type[text/vnd.tiddlywiki]] +[first[]]",
            "shortcuts": "((excise))",
            "dropdown": "$:/core/ui/EditorToolbar/excise-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/heading-1": {
            "title": "$:/core/ui/EditorToolbar/heading-1",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-1",
            "caption": "{{$:/language/Buttons/Heading1/Caption}}",
            "description": "{{$:/language/Buttons/Heading1/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "button-classes": "tc-text-editor-toolbar-item-start-group",
            "shortcuts": "((heading-1))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"1\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/heading-2": {
            "title": "$:/core/ui/EditorToolbar/heading-2",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-2",
            "caption": "{{$:/language/Buttons/Heading2/Caption}}",
            "description": "{{$:/language/Buttons/Heading2/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((heading-2))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"2\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/heading-3": {
            "title": "$:/core/ui/EditorToolbar/heading-3",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-3",
            "caption": "{{$:/language/Buttons/Heading3/Caption}}",
            "description": "{{$:/language/Buttons/Heading3/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((heading-3))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"3\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/heading-4": {
            "title": "$:/core/ui/EditorToolbar/heading-4",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-4",
            "caption": "{{$:/language/Buttons/Heading4/Caption}}",
            "description": "{{$:/language/Buttons/Heading4/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((heading-4))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"4\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/heading-5": {
            "title": "$:/core/ui/EditorToolbar/heading-5",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-5",
            "caption": "{{$:/language/Buttons/Heading5/Caption}}",
            "description": "{{$:/language/Buttons/Heading5/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((heading-5))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"5\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/heading-6": {
            "title": "$:/core/ui/EditorToolbar/heading-6",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/heading-6",
            "caption": "{{$:/language/Buttons/Heading6/Caption}}",
            "description": "{{$:/language/Buttons/Heading6/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((heading-6))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"6\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/italic": {
            "title": "$:/core/ui/EditorToolbar/italic",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/italic",
            "caption": "{{$:/language/Buttons/Italic/Caption}}",
            "description": "{{$:/language/Buttons/Italic/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((italic))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"//\"\n\tsuffix=\"//\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/line-width-dropdown": {
            "title": "$:/core/ui/EditorToolbar/line-width-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/LineWidth/\n\n\\define toolbar-line-width-inner()\n<$button tag=\"a\" tooltip=\"\"\"$(line-width)$\"\"\">\n\n<$action-setfield\n\t$tiddler=\"$:/config/BitmapEditor/LineWidth\"\n\t$value=\"$(line-width)$\"\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<div style=\"display: inline-block; margin: 4px calc(80px - $(line-width)$); background-color: #000; width: calc(100px + $(line-width)$ * 2); height: $(line-width)$; border-radius: 120px; vertical-align: middle;\"/>\n\n<span style=\"margin-left: 8px;\">\n\n<$text text=\"\"\"$(line-width)$\"\"\"/>\n\n<$reveal state=\"$:/config/BitmapEditor/LineWidth\" type=\"match\" text=\"\"\"$(line-width)$\"\"\" tag=\"span\">\n\n<$entity entity=\"&nbsp;\"/>\n\n<$entity entity=\"&#x2713;\"/>\n\n</$reveal>\n\n</span>\n\n</$button>\n\\end\n\n''<<lingo Hint>>''\n\n<$list filter={{$:/config/BitmapEditor/LineWidths}} variable=\"line-width\">\n\n<<toolbar-line-width-inner>>\n\n</$list>\n"
        },
        "$:/core/ui/EditorToolbar/line-width": {
            "title": "$:/core/ui/EditorToolbar/line-width",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/line-width",
            "caption": "{{$:/language/Buttons/LineWidth/Caption}}",
            "description": "{{$:/language/Buttons/LineWidth/Hint}}",
            "condition": "[<targetTiddler>is[image]]",
            "dropdown": "$:/core/ui/EditorToolbar/line-width-dropdown",
            "text": "<$text text={{$:/config/BitmapEditor/LineWidth}}/>"
        },
        "$:/core/ui/EditorToolbar/link-dropdown": {
            "title": "$:/core/ui/EditorToolbar/link-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/Link/\n\n\\define add-link-actions()\n<$action-sendmessage $message=\"tm-edit-text-operation\" $param=\"make-link\" text={{$(linkTiddler)$}} />\n<$action-deletetiddler $tiddler=<<dropdown-state>> />\n<$action-deletetiddler $tiddler=<<searchTiddler>> />\n<$action-deletetiddler $tiddler=<<linkTiddler>> />\n\\end\n\n\\define external-link()\n<$button class=\"tc-btn-invisible\" style=\"width: auto; display: inline-block; background-colour: inherit;\" actions=<<add-link-actions>>>\n{{$:/core/images/chevron-right}}\n</$button>\n\\end\n\n\\define body(config-title)\n''<<lingo Hint>>''\n\n<$vars searchTiddler=\"\"\"$config-title$/search\"\"\" linkTiddler=\"\"\"$config-title$/link\"\"\" linktext=\"\" >\n\n<$vars linkTiddler=<<searchTiddler>>>\n<$keyboard key=\"ENTER\" actions=<<add-link-actions>>>\n<$edit-text tiddler=<<searchTiddler>> type=\"search\" tag=\"input\" focus=\"true\" placeholder={{$:/language/Search/Search}} default=\"\"/>\n<$reveal tag=\"span\" state=<<searchTiddler>> type=\"nomatch\" text=\"\">\n<<external-link>>\n<$button class=\"tc-btn-invisible\" style=\"width: auto; display: inline-block; background-colour: inherit;\">\n<$action-setfield $tiddler=<<searchTiddler>> text=\"\" />\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</$keyboard>\n</$vars>\n\n<$reveal tag=\"div\" state=<<searchTiddler>> type=\"nomatch\" text=\"\">\n\n<$linkcatcher actions=<<add-link-actions>> to=<<linkTiddler>>>\n\n{{$:/core/ui/SearchResults}}\n\n</$linkcatcher>\n\n</$reveal>\n\n</$vars>\n\n\\end\n\n<$macrocall $name=\"body\" config-title=<<qualify \"$:/state/Link/\">>/>"
        },
        "$:/core/ui/EditorToolbar/link": {
            "title": "$:/core/ui/EditorToolbar/link",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/link",
            "caption": "{{$:/language/Buttons/Link/Caption}}",
            "description": "{{$:/language/Buttons/Link/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "button-classes": "tc-text-editor-toolbar-item-start-group",
            "shortcuts": "((link))",
            "dropdown": "$:/core/ui/EditorToolbar/link-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/linkify": {
            "title": "$:/core/ui/EditorToolbar/linkify",
            "caption": "{{$:/language/Buttons/Linkify/Caption}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "description": "{{$:/language/Buttons/Linkify/Hint}}",
            "icon": "$:/core/images/linkify",
            "list-before": "$:/core/ui/EditorToolbar/mono-block",
            "shortcuts": "((linkify))",
            "tags": "$:/tags/EditorToolbar",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"[[\"\n\tsuffix=\"]]\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/list-bullet": {
            "title": "$:/core/ui/EditorToolbar/list-bullet",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/list-bullet",
            "caption": "{{$:/language/Buttons/ListBullet/Caption}}",
            "description": "{{$:/language/Buttons/ListBullet/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((list-bullet))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"*\"\n\tcount=\"1\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/list-number": {
            "title": "$:/core/ui/EditorToolbar/list-number",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/list-number",
            "caption": "{{$:/language/Buttons/ListNumber/Caption}}",
            "description": "{{$:/language/Buttons/ListNumber/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((list-number))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"#\"\n\tcount=\"1\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/mono-block": {
            "title": "$:/core/ui/EditorToolbar/mono-block",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/mono-block",
            "caption": "{{$:/language/Buttons/MonoBlock/Caption}}",
            "description": "{{$:/language/Buttons/MonoBlock/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "button-classes": "tc-text-editor-toolbar-item-start-group",
            "shortcuts": "((mono-block))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-lines\"\n\tprefix=\"\n```\"\n\tsuffix=\"```\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/mono-line": {
            "title": "$:/core/ui/EditorToolbar/mono-line",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/mono-line",
            "caption": "{{$:/language/Buttons/MonoLine/Caption}}",
            "description": "{{$:/language/Buttons/MonoLine/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((mono-line))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"`\"\n\tsuffix=\"`\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/more-dropdown": {
            "title": "$:/core/ui/EditorToolbar/more-dropdown",
            "text": "\\define config-title()\n$:/config/EditorToolbarButtons/Visibility/$(toolbarItem)$\n\\end\n\n\\define conditional-button()\n<$list filter={{$(toolbarItem)$!!condition}} variable=\"condition\">\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/toolbar/button\" mode=\"inline\"/> <$transclude tiddler=<<toolbarItem>> field=\"description\"/>\n</$list>\n\\end\n\n<div class=\"tc-text-editor-toolbar-more\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditorToolbar]!has[draft.of]] -[[$:/core/ui/EditorToolbar/more]]\">\n<$reveal type=\"match\" state=<<config-visibility-title>> text=\"hide\" tag=\"div\">\n<<conditional-button>>\n</$reveal>\n</$list>\n</div>\n"
        },
        "$:/core/ui/EditorToolbar/more": {
            "title": "$:/core/ui/EditorToolbar/more",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/down-arrow",
            "caption": "{{$:/language/Buttons/More/Caption}}",
            "description": "{{$:/language/Buttons/More/Hint}}",
            "condition": "[<targetTiddler>]",
            "dropdown": "$:/core/ui/EditorToolbar/more-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/opacity-dropdown": {
            "title": "$:/core/ui/EditorToolbar/opacity-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/Opacity/\n\n\\define toolbar-opacity-inner()\n<$button tag=\"a\" tooltip=\"\"\"$(opacity)$\"\"\">\n\n<$action-setfield\n\t$tiddler=\"$:/config/BitmapEditor/Opacity\"\n\t$value=\"$(opacity)$\"\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<div style=\"display: inline-block; vertical-align: middle; background-color: $(current-paint-colour)$; opacity: $(opacity)$; width: 1em; height: 1em; border-radius: 50%;\"/>\n\n<span style=\"margin-left: 8px;\">\n\n<$text text=\"\"\"$(opacity)$\"\"\"/>\n\n<$reveal state=\"$:/config/BitmapEditor/Opacity\" type=\"match\" text=\"\"\"$(opacity)$\"\"\" tag=\"span\">\n\n<$entity entity=\"&nbsp;\"/>\n\n<$entity entity=\"&#x2713;\"/>\n\n</$reveal>\n\n</span>\n\n</$button>\n\\end\n\n\\define toolbar-opacity()\n''<<lingo Hint>>''\n\n<$list filter={{$:/config/BitmapEditor/Opacities}} variable=\"opacity\">\n\n<<toolbar-opacity-inner>>\n\n</$list>\n\\end\n\n<$set name=\"current-paint-colour\" value={{$:/config/BitmapEditor/Colour}}>\n\n<$set name=\"current-opacity\" value={{$:/config/BitmapEditor/Opacity}}>\n\n<<toolbar-opacity>>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/EditorToolbar/opacity": {
            "title": "$:/core/ui/EditorToolbar/opacity",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/opacity",
            "caption": "{{$:/language/Buttons/Opacity/Caption}}",
            "description": "{{$:/language/Buttons/Opacity/Hint}}",
            "condition": "[<targetTiddler>is[image]]",
            "dropdown": "$:/core/ui/EditorToolbar/opacity-dropdown",
            "text": "<$text text={{$:/config/BitmapEditor/Opacity}}/>\n"
        },
        "$:/core/ui/EditorToolbar/paint-dropdown": {
            "title": "$:/core/ui/EditorToolbar/paint-dropdown",
            "text": "''{{$:/language/Buttons/Paint/Hint}}''\n\n<$macrocall $name=\"colour-picker\" actions=\"\"\"\n\n<$action-setfield\n\t$tiddler=\"$:/config/BitmapEditor/Colour\"\n\t$value=<<colour-picker-value>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n\"\"\"/>\n"
        },
        "$:/core/ui/EditorToolbar/paint": {
            "title": "$:/core/ui/EditorToolbar/paint",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/paint",
            "caption": "{{$:/language/Buttons/Paint/Caption}}",
            "description": "{{$:/language/Buttons/Paint/Hint}}",
            "condition": "[<targetTiddler>is[image]]",
            "dropdown": "$:/core/ui/EditorToolbar/paint-dropdown",
            "text": "\\define toolbar-paint()\n<div style=\"display: inline-block; vertical-align: middle; background-color: $(colour-picker-value)$; width: 1em; height: 1em; border-radius: 50%;\"/>\n\\end\n<$set name=\"colour-picker-value\" value={{$:/config/BitmapEditor/Colour}}>\n<<toolbar-paint>>\n</$set>\n"
        },
        "$:/core/ui/EditorToolbar/picture-dropdown": {
            "title": "$:/core/ui/EditorToolbar/picture-dropdown",
            "text": "\\define replacement-text()\n[img[$(imageTitle)$]]\n\\end\n\n''{{$:/language/Buttons/Picture/Hint}}''\n\n<$macrocall $name=\"image-picker\" actions=\"\"\"\n\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"replace-selection\"\n\ttext=<<replacement-text>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n\"\"\"/>\n"
        },
        "$:/core/ui/EditorToolbar/picture": {
            "title": "$:/core/ui/EditorToolbar/picture",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/picture",
            "caption": "{{$:/language/Buttons/Picture/Caption}}",
            "description": "{{$:/language/Buttons/Picture/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((picture))",
            "dropdown": "$:/core/ui/EditorToolbar/picture-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/preview-type-dropdown": {
            "title": "$:/core/ui/EditorToolbar/preview-type-dropdown",
            "text": "\\define preview-type-button()\n<$button tag=\"a\">\n\n<$action-setfield $tiddler=\"$:/state/editpreviewtype\" $value=\"$(previewType)$\"/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<$transclude tiddler=<<previewType>> field=\"caption\" mode=\"inline\">\n\n<$view tiddler=<<previewType>> field=\"title\" mode=\"inline\"/>\n\n</$transclude> \n\n<$reveal tag=\"span\" state=\"$:/state/editpreviewtype\" type=\"match\" text=<<previewType>> default=\"$:/core/ui/EditTemplate/body/preview/output\">\n\n<$entity entity=\"&nbsp;\"/>\n\n<$entity entity=\"&#x2713;\"/>\n\n</$reveal>\n\n</$button>\n\\end\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditPreview]!has[draft.of]]\" variable=\"previewType\">\n\n<<preview-type-button>>\n\n</$list>\n"
        },
        "$:/core/ui/EditorToolbar/preview-type": {
            "title": "$:/core/ui/EditorToolbar/preview-type",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/chevron-down",
            "caption": "{{$:/language/Buttons/PreviewType/Caption}}",
            "description": "{{$:/language/Buttons/PreviewType/Hint}}",
            "condition": "[all[shadows+tiddlers]tag[$:/tags/EditPreview]!has[draft.of]butfirst[]limit[1]]",
            "button-classes": "tc-text-editor-toolbar-item-adjunct",
            "dropdown": "$:/core/ui/EditorToolbar/preview-type-dropdown"
        },
        "$:/core/ui/EditorToolbar/preview": {
            "title": "$:/core/ui/EditorToolbar/preview",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/preview-open",
            "custom-icon": "yes",
            "caption": "{{$:/language/Buttons/Preview/Caption}}",
            "description": "{{$:/language/Buttons/Preview/Hint}}",
            "condition": "[<targetTiddler>]",
            "button-classes": "tc-text-editor-toolbar-item-start-group",
            "shortcuts": "((preview))",
            "text": "<$reveal state=\"$:/state/showeditpreview\" type=\"match\" text=\"yes\" tag=\"span\">\n{{$:/core/images/preview-open}}\n<$action-setfield $tiddler=\"$:/state/showeditpreview\" $value=\"no\"/>\n</$reveal>\n<$reveal state=\"$:/state/showeditpreview\" type=\"nomatch\" text=\"yes\" tag=\"span\">\n{{$:/core/images/preview-closed}}\n<$action-setfield $tiddler=\"$:/state/showeditpreview\" $value=\"yes\"/>\n</$reveal>\n"
        },
        "$:/core/ui/EditorToolbar/quote": {
            "title": "$:/core/ui/EditorToolbar/quote",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/quote",
            "caption": "{{$:/language/Buttons/Quote/Caption}}",
            "description": "{{$:/language/Buttons/Quote/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((quote))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-lines\"\n\tprefix=\"\n<<<\"\n\tsuffix=\"<<<\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/rotate-left": {
            "title": "$:/core/ui/EditorToolbar/rotate-left",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/rotate-left",
            "caption": "{{$:/language/Buttons/RotateLeft/Caption}}",
            "description": "{{$:/language/Buttons/RotateLeft/Hint}}",
            "condition": "[<targetTiddler>is[image]]",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-bitmap-operation\"\n\t$param=\"rotate-left\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/size-dropdown": {
            "title": "$:/core/ui/EditorToolbar/size-dropdown",
            "text": "\\define lingo-base() $:/language/Buttons/Size/\n\n\\define toolbar-button-size-preset(config-title)\n<$set name=\"width\" filter=\"$(sizePair)$ +[first[]]\">\n\n<$set name=\"height\" filter=\"$(sizePair)$ +[last[]]\">\n\n<$button tag=\"a\">\n\n<$action-setfield\n\t$tiddler=\"\"\"$config-title$/new-width\"\"\"\n\t$value=<<width>>\n/>\n\n<$action-setfield\n\t$tiddler=\"\"\"$config-title$/new-height\"\"\"\n\t$value=<<height>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=\"\"\"$config-title$/presets-popup\"\"\"\n/>\n\n<$text text=<<width>>/> &times; <$text text=<<height>>/>\n\n</$button>\n\n</$set>\n\n</$set>\n\\end\n\n\\define toolbar-button-size(config-title)\n''{{$:/language/Buttons/Size/Hint}}''\n\n<<lingo Caption/Width>> <$edit-text tag=\"input\" tiddler=\"\"\"$config-title$/new-width\"\"\" default=<<tv-bitmap-editor-width>> focus=\"true\" size=\"8\"/> <<lingo Caption/Height>> <$edit-text tag=\"input\" tiddler=\"\"\"$config-title$/new-height\"\"\" default=<<tv-bitmap-editor-height>> size=\"8\"/> <$button popup=\"\"\"$config-title$/presets-popup\"\"\" class=\"tc-btn-invisible tc-popup-keep\" style=\"width: auto; display: inline-block; background-colour: inherit;\" selectedClass=\"tc-selected\">\n{{$:/core/images/down-arrow}}\n</$button>\n\n<$reveal tag=\"span\" state=\"\"\"$config-title$/presets-popup\"\"\" type=\"popup\" position=\"belowleft\" animate=\"yes\">\n\n<div class=\"tc-drop-down tc-popup-keep\">\n\n<$list filter={{$:/config/BitmapEditor/ImageSizes}} variable=\"sizePair\">\n\n<$macrocall $name=\"toolbar-button-size-preset\" config-title=\"$config-title$\"/>\n\n</$list>\n\n</div>\n\n</$reveal>\n\n<$button>\n<$action-sendmessage\n\t$message=\"tm-edit-bitmap-operation\"\n\t$param=\"resize\"\n\twidth={{$config-title$/new-width}}\n\theight={{$config-title$/new-height}}\n/>\n<$action-deletetiddler\n\t$tiddler=\"\"\"$config-title$/new-width\"\"\"\n/>\n<$action-deletetiddler\n\t$tiddler=\"\"\"$config-title$/new-height\"\"\"\n/>\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n<<lingo Caption/Resize>>\n</$button>\n\\end\n\n<$macrocall $name=\"toolbar-button-size\" config-title=<<qualify \"$:/state/Size/\">>/>\n"
        },
        "$:/core/ui/EditorToolbar/size": {
            "title": "$:/core/ui/EditorToolbar/size",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/size",
            "caption": "{{$:/language/Buttons/Size/Caption}}",
            "description": "{{$:/language/Buttons/Size/Hint}}",
            "condition": "[<targetTiddler>is[image]]",
            "dropdown": "$:/core/ui/EditorToolbar/size-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/stamp-dropdown": {
            "title": "$:/core/ui/EditorToolbar/stamp-dropdown",
            "text": "\\define toolbar-button-stamp-inner()\n<$button tag=\"a\">\n\n<$list filter=\"[[$(snippetTitle)$]addsuffix[/prefix]is[missing]removesuffix[/prefix]addsuffix[/suffix]is[missing]]\">\n\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"replace-selection\"\n\ttext={{$(snippetTitle)$}}\n/>\n\n</$list>\n\n\n<$list filter=\"[[$(snippetTitle)$]addsuffix[/prefix]is[missing]removesuffix[/prefix]addsuffix[/suffix]!is[missing]] [[$(snippetTitle)$]addsuffix[/prefix]!is[missing]removesuffix[/prefix]addsuffix[/suffix]is[missing]] [[$(snippetTitle)$]addsuffix[/prefix]!is[missing]removesuffix[/prefix]addsuffix[/suffix]!is[missing]]\">\n\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix={{{ [[$(snippetTitle)$]addsuffix[/prefix]get[text]] }}}\nsuffix={{{ [[$(snippetTitle)$]addsuffix[/suffix]get[text]] }}}\n/>\n\n</$list>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<$transclude tiddler=<<snippetTitle>> field=\"caption\" mode=\"inline\">\n\n<$view tiddler=<<snippetTitle>> field=\"title\" />\n\n</$transclude>\n\n</$button>\n\\end\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TextEditor/Snippet]!has[draft.of]sort[caption]]\" variable=\"snippetTitle\">\n\n<<toolbar-button-stamp-inner>>\n\n</$list>\n\n----\n\n<$button tag=\"a\">\n\n<$action-sendmessage\n\t$message=\"tm-new-tiddler\"\n\ttags=\"$:/tags/TextEditor/Snippet\"\n\tcaption={{$:/language/Buttons/Stamp/New/Title}}\n\ttext={{$:/language/Buttons/Stamp/New/Text}}\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<em>\n\n<$text text={{$:/language/Buttons/Stamp/Caption/New}}/>\n\n</em>\n\n</$button>\n"
        },
        "$:/core/ui/EditorToolbar/stamp": {
            "title": "$:/core/ui/EditorToolbar/stamp",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/stamp",
            "caption": "{{$:/language/Buttons/Stamp/Caption}}",
            "description": "{{$:/language/Buttons/Stamp/Hint}}",
            "condition": "[<targetTiddler>type[]] [<targetTiddler>get[type]prefix[text/]] +[first[]]",
            "shortcuts": "((stamp))",
            "dropdown": "$:/core/ui/EditorToolbar/stamp-dropdown",
            "text": ""
        },
        "$:/core/ui/EditorToolbar/strikethrough": {
            "title": "$:/core/ui/EditorToolbar/strikethrough",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/strikethrough",
            "caption": "{{$:/language/Buttons/Strikethrough/Caption}}",
            "description": "{{$:/language/Buttons/Strikethrough/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((strikethrough))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"~~\"\n\tsuffix=\"~~\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/subscript": {
            "title": "$:/core/ui/EditorToolbar/subscript",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/subscript",
            "caption": "{{$:/language/Buttons/Subscript/Caption}}",
            "description": "{{$:/language/Buttons/Subscript/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((subscript))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\",,\"\n\tsuffix=\",,\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/superscript": {
            "title": "$:/core/ui/EditorToolbar/superscript",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/superscript",
            "caption": "{{$:/language/Buttons/Superscript/Caption}}",
            "description": "{{$:/language/Buttons/Superscript/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((superscript))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"^^\"\n\tsuffix=\"^^\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/transcludify": {
            "title": "$:/core/ui/EditorToolbar/transcludify",
            "caption": "{{$:/language/Buttons/Transcludify/Caption}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "description": "{{$:/language/Buttons/Transcludify/Hint}}",
            "icon": "$:/core/images/transcludify",
            "list-before": "$:/core/ui/EditorToolbar/mono-block",
            "shortcuts": "((transcludify))",
            "tags": "$:/tags/EditorToolbar",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"{{\"\n\tsuffix=\"}}\"\n/>\n"
        },
        "$:/core/ui/EditorToolbar/underline": {
            "title": "$:/core/ui/EditorToolbar/underline",
            "tags": "$:/tags/EditorToolbar",
            "icon": "$:/core/images/underline",
            "caption": "{{$:/language/Buttons/Underline/Caption}}",
            "description": "{{$:/language/Buttons/Underline/Hint}}",
            "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]",
            "shortcuts": "((underline))",
            "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"__\"\n\tsuffix=\"__\"\n/>\n"
        },
        "$:/core/Filters/AllTags": {
            "title": "$:/core/Filters/AllTags",
            "tags": "$:/tags/Filter",
            "filter": "[tags[]!is[system]sort[title]]",
            "description": "{{$:/language/Filters/AllTags}}",
            "text": ""
        },
        "$:/core/Filters/AllTiddlers": {
            "title": "$:/core/Filters/AllTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[!is[system]sort[title]]",
            "description": "{{$:/language/Filters/AllTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/Drafts": {
            "title": "$:/core/Filters/Drafts",
            "tags": "$:/tags/Filter",
            "filter": "[has[draft.of]sort[title]]",
            "description": "{{$:/language/Filters/Drafts}}",
            "text": ""
        },
        "$:/core/Filters/Missing": {
            "title": "$:/core/Filters/Missing",
            "tags": "$:/tags/Filter",
            "filter": "[all[missing]sort[title]]",
            "description": "{{$:/language/Filters/Missing}}",
            "text": ""
        },
        "$:/core/Filters/Orphans": {
            "title": "$:/core/Filters/Orphans",
            "tags": "$:/tags/Filter",
            "filter": "[all[orphans]sort[title]]",
            "description": "{{$:/language/Filters/Orphans}}",
            "text": ""
        },
        "$:/core/Filters/OverriddenShadowTiddlers": {
            "title": "$:/core/Filters/OverriddenShadowTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[is[shadow]]",
            "description": "{{$:/language/Filters/OverriddenShadowTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/RecentSystemTiddlers": {
            "title": "$:/core/Filters/RecentSystemTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[has[modified]!sort[modified]limit[50]]",
            "description": "{{$:/language/Filters/RecentSystemTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/RecentTiddlers": {
            "title": "$:/core/Filters/RecentTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[!is[system]has[modified]!sort[modified]limit[50]]",
            "description": "{{$:/language/Filters/RecentTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/SessionTiddlers": {
            "title": "$:/core/Filters/SessionTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[haschanged[]]",
            "description": "{{$:/language/Filters/SessionTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/ShadowTiddlers": {
            "title": "$:/core/Filters/ShadowTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[all[shadows]sort[title]]",
            "description": "{{$:/language/Filters/ShadowTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/StoryList": {
            "title": "$:/core/Filters/StoryList",
            "tags": "$:/tags/Filter",
            "filter": "[list[$:/StoryList]] -$:/AdvancedSearch",
            "description": "{{$:/language/Filters/StoryList}}",
            "text": ""
        },
        "$:/core/Filters/SystemTags": {
            "title": "$:/core/Filters/SystemTags",
            "tags": "$:/tags/Filter",
            "filter": "[all[shadows+tiddlers]tags[]is[system]sort[title]]",
            "description": "{{$:/language/Filters/SystemTags}}",
            "text": ""
        },
        "$:/core/Filters/SystemTiddlers": {
            "title": "$:/core/Filters/SystemTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[is[system]sort[title]]",
            "description": "{{$:/language/Filters/SystemTiddlers}}",
            "text": ""
        },
        "$:/core/Filters/TypedTiddlers": {
            "title": "$:/core/Filters/TypedTiddlers",
            "tags": "$:/tags/Filter",
            "filter": "[!is[system]has[type]each[type]sort[type]] -[type[text/vnd.tiddlywiki]]",
            "description": "{{$:/language/Filters/TypedTiddlers}}",
            "text": ""
        },
        "$:/core/ui/ImportListing": {
            "title": "$:/core/ui/ImportListing",
            "text": "\\define lingo-base() $:/language/Import/\n\n\\define messageField()\nmessage-$(payloadTiddler)$\n\\end\n\n\\define selectionField()\nselection-$(payloadTiddler)$\n\\end\n\n\\define previewPopupState()\n$(currentTiddler)$!!popup-$(payloadTiddler)$\n\\end\n\n\\define select-all-actions()\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" variable=\"payloadTiddler\">\n<$action-setfield $field={{{ [<payloadTiddler>addprefix[selection-]] }}} $value={{$:/state/import/select-all}}/>\n</$list>\n\\end\n\n<table>\n<tbody>\n<tr>\n<th>\n<$checkbox tiddler=\"$:/state/import/select-all\" field=\"text\" checked=\"checked\" unchecked=\"unchecked\" default=\"checked\" actions=<<select-all-actions>>>\n<<lingo Listing/Select/Caption>>\n</$checkbox>\n</th>\n<th>\n<<lingo Listing/Title/Caption>>\n</th>\n<th>\n<<lingo Listing/Status/Caption>>\n</th>\n</tr>\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" variable=\"payloadTiddler\">\n<tr>\n<td>\n<$checkbox field=<<selectionField>> checked=\"checked\" unchecked=\"unchecked\" default=\"checked\"/>\n</td>\n<td>\n<$reveal type=\"nomatch\" stateTitle=<<previewPopupState>> text=\"yes\" tag=\"div\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" setTitle=<<previewPopupState>> setTo=\"yes\">\n{{$:/core/images/right-arrow}}&nbsp;<$text text=<<payloadTiddler>>/>\n</$button>\n</$reveal>\n<$reveal type=\"match\" stateTitle=<<previewPopupState>> text=\"yes\" tag=\"div\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" setTitle=<<previewPopupState>> setTo=\"no\">\n{{$:/core/images/down-arrow}}&nbsp;<$text text=<<payloadTiddler>>/>\n</$button>\n</$reveal>\n</td>\n<td>\n<$view field=<<messageField>>/>\n</td>\n</tr>\n<tr>\n<td colspan=\"3\">\n<$reveal type=\"match\" text=\"yes\" stateTitle=<<previewPopupState>> tag=\"div\">\n<$list filter=\"[{$:/state/importpreviewtype}has[text]]\" variable=\"listItem\" emptyMessage={{$:/core/ui/ImportPreviews/Text}}>\n<$transclude tiddler={{$:/state/importpreviewtype}}/>\n</$list>\n</$reveal>\n</td>\n</tr>\n</$list>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/ImportPreviews/Diff": {
            "title": "$:/core/ui/ImportPreviews/Diff",
            "tags": "$:/tags/ImportPreview",
            "caption": "{{$:/language/Import/Listing/Preview/Diff}}",
            "text": "<$macrocall $name=\"compareTiddlerText\" sourceTiddlerTitle=<<payloadTiddler>> destTiddlerTitle=<<currentTiddler>> destSubTiddlerTitle=<<payloadTiddler>>/>\n"
        },
        "$:/core/ui/ImportPreviews/DiffFields": {
            "title": "$:/core/ui/ImportPreviews/DiffFields",
            "tags": "$:/tags/ImportPreview",
            "caption": "{{$:/language/Import/Listing/Preview/DiffFields}}",
            "text": "<$macrocall $name=\"compareTiddlers\" sourceTiddlerTitle=<<payloadTiddler>> destTiddlerTitle=<<currentTiddler>> destSubTiddlerTitle=<<payloadTiddler>> exclude=\"text\"/>\n"
        },
        "$:/core/ui/ImportPreviews/Fields": {
            "title": "$:/core/ui/ImportPreviews/Fields",
            "tags": "$:/tags/ImportPreview",
            "caption": "{{$:/language/Import/Listing/Preview/Fields}}",
            "text": "<table class=\"tc-view-field-table\">\n<tbody>\n<$list filter=\"[<payloadTiddler>subtiddlerfields<currentTiddler>sort[]] -text\" variable=\"fieldName\">\n<tr class=\"tc-view-field\">\n<td class=\"tc-view-field-name\">\n<$text text=<<fieldName>>/>\n</td>\n<td class=\"tc-view-field-value\">\n<$view field=<<fieldName>> tiddler=<<currentTiddler>> subtiddler=<<payloadTiddler>>/>\n</td>\n</tr>\n</$list>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/ImportPreviews/Text": {
            "title": "$:/core/ui/ImportPreviews/Text",
            "tags": "$:/tags/ImportPreview",
            "caption": "{{$:/language/Import/Listing/Preview/Text}}",
            "text": "<$transclude tiddler=<<currentTiddler>> subtiddler=<<payloadTiddler>> mode=\"block\"/>\n"
        },
        "$:/core/ui/ImportPreviews/TextRaw": {
            "title": "$:/core/ui/ImportPreviews/TextRaw",
            "tags": "$:/tags/ImportPreview",
            "caption": "{{$:/language/Import/Listing/Preview/TextRaw}}",
            "text": "<pre><code><$view tiddler=<<currentTiddler>> subtiddler=<<payloadTiddler>> /></code></pre>"
        },
        "$:/core/ui/KeyboardShortcuts/advanced-search": {
            "title": "$:/core/ui/KeyboardShortcuts/advanced-search",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((advanced-search))",
            "text": "<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\">\n<$action-navigate $to=\"$:/AdvancedSearch\"/>\n<$action-sendmessage $message=\"tm-focus-selector\" $param=\"\"\"[data-tiddler-title=\"$:/AdvancedSearch\"] .tc-search input\"\"\"/>\n</$navigator>\n"
        },
        "$:/core/ui/KeyboardShortcuts/new-image": {
            "title": "$:/core/ui/KeyboardShortcuts/new-image",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((new-image))",
            "text": "<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>\n{{$:/core/ui/Actions/new-image}}\n</$navigator>\n"
        },
        "$:/core/ui/KeyboardShortcuts/new-journal": {
            "title": "$:/core/ui/KeyboardShortcuts/new-journal",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((new-journal))",
            "text": "<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>\n{{$:/core/ui/Actions/new-journal}}\n</$navigator>\n"
        },
        "$:/core/ui/KeyboardShortcuts/new-tiddler": {
            "title": "$:/core/ui/KeyboardShortcuts/new-tiddler",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((new-tiddler))",
            "text": "<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>\n{{$:/core/ui/Actions/new-tiddler}}\n</$navigator>\n"
        },
        "$:/core/ui/KeyboardShortcuts/sidebar-search": {
            "title": "$:/core/ui/KeyboardShortcuts/sidebar-search",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((sidebar-search))",
            "text": "<$action-sendmessage $message=\"tm-focus-selector\" $param=\".tc-search input\"/>\n"
        },
        "$:/core/ui/KeyboardShortcut/toggle-sidebar": {
            "title": "$:/core/ui/KeyboardShortcut/toggle-sidebar",
            "tags": "$:/tags/KeyboardShortcut",
            "key": "((toggle-sidebar))",
            "text": "<$list filter=\"[[$:/state/sidebar]is[missing]] [{$:/state/sidebar}removeprefix[yes]]\" emptyMessage=\"\"\"\n<$action-setfield $tiddler=\"$:/state/sidebar\" text=\"yes\"/>\n\"\"\">\n<$action-setfield $tiddler=\"$:/state/sidebar\" text=\"no\"/>\n</$list>\n"
        },
        "$:/core/ui/ListItemTemplate": {
            "title": "$:/core/ui/ListItemTemplate",
            "text": "<div class=\"tc-menu-list-item\">\n<$link />\n</div>"
        },
        "$:/Manager/ItemMain/Fields": {
            "title": "$:/Manager/ItemMain/Fields",
            "tags": "$:/tags/Manager/ItemMain",
            "caption": "{{$:/language/Manager/Item/Fields}}",
            "text": "<table>\n<tbody>\n<$list filter=\"[all[current]fields[]sort[title]] -text\" template=\"$:/core/ui/TiddlerFieldTemplate\" variable=\"listItem\"/>\n</tbody>\n</table>\n"
        },
        "$:/Manager/ItemMain/RawText": {
            "title": "$:/Manager/ItemMain/RawText",
            "tags": "$:/tags/Manager/ItemMain",
            "caption": "{{$:/language/Manager/Item/RawText}}",
            "text": "<pre><code><$view/></code></pre>\n"
        },
        "$:/Manager/ItemMain/WikifiedText": {
            "title": "$:/Manager/ItemMain/WikifiedText",
            "tags": "$:/tags/Manager/ItemMain",
            "caption": "{{$:/language/Manager/Item/WikifiedText}}",
            "text": "<$transclude mode=\"block\"/>\n"
        },
        "$:/Manager/ItemSidebar/Colour": {
            "title": "$:/Manager/ItemSidebar/Colour",
            "tags": "$:/tags/Manager/ItemSidebar",
            "caption": "{{$:/language/Manager/Item/Colour}}",
            "text": "\\define swatch-styles()\nheight: 1em;\nbackground-color: $(colour)$\n\\end\n\n<$vars colour={{!!color}}>\n<p style=<<swatch-styles>>/>\n</$vars>\n<p>\n<$edit-text field=\"color\" tag=\"input\" type=\"color\"/> / <$edit-text field=\"color\" tag=\"input\" type=\"text\" size=\"9\"/>\n</p>\n"
        },
        "$:/Manager/ItemSidebar/Icon": {
            "title": "$:/Manager/ItemSidebar/Icon",
            "tags": "$:/tags/Manager/ItemSidebar",
            "caption": "{{$:/language/Manager/Item/Icon}}",
            "text": "<p>\n<div class=\"tc-manager-icon-editor\">\n<$button popup=<<qualify \"$:/state/popup/image-picker\">> class=\"tc-btn-invisible\">\n<$transclude tiddler={{!!icon}}>\n{{$:/language/Manager/Item/Icon/None}}\n</$transclude>\n</$button>\n<div class=\"tc-block-dropdown-wrapper\" style=\"position: static;\">\n<$reveal state=<<qualify \"$:/state/popup/image-picker\">> type=\"nomatch\" text=\"\" default=\"\" tag=\"div\" class=\"tc-popup\">\n<div class=\"tc-block-dropdown tc-popup-keep\" style=\"width: 80%; left: 10%; right: 10%; padding: 0.5em;\">\n<$macrocall $name=\"image-picker-include-tagged-images\" actions=\"\"\"\n<$action-setfield $field=\"icon\" $value=<<imageTitle>>/>\n<$action-deletetiddler $tiddler=<<qualify \"$:/state/popup/image-picker\">>/>\n\"\"\"/>\n</div>\n</$reveal>\n</div>\n</div>\n</p>\n"
        },
        "$:/Manager/ItemSidebar/Tags": {
            "title": "$:/Manager/ItemSidebar/Tags",
            "tags": "$:/tags/Manager/ItemSidebar",
            "caption": "{{$:/language/Manager/Item/Tags}}",
            "text": "\\define tag-checkbox-actions()\n<$action-listops\n\t$tiddler=\"$:/config/Manager/RecentTags\"\n\t$subfilter=\"[<tag>] [list[$:/config/Manager/RecentTags]] +[limit[12]]\"\n/>\n\\end\n\n\\define tag-picker-actions()\n<<tag-checkbox-actions>>\n<$action-listops\n\t$tiddler=<<currentTiddler>>\n\t$field=\"tags\"\n\t$subfilter=\"[<tag>] [all[current]tags[]]\"\n/>\n\\end\n\n<p>\n<$list filter=\"[all[current]tags[]] [list[$:/config/Manager/RecentTags]] +[sort[title]] \" variable=\"tag\">\n<div>\n<$checkbox tiddler=<<currentTiddler>> tag=<<tag>> actions=<<tag-checkbox-actions>>>\n<$macrocall $name=\"tag-pill\" tag=<<tag>>/>\n</$checkbox>\n</div>\n</$list>\n</p>\n<p>\n<$macrocall $name=\"tag-picker\" actions=<<tag-picker-actions>>/>\n</p>\n"
        },
        "$:/Manager/ItemSidebar/Tools": {
            "title": "$:/Manager/ItemSidebar/Tools",
            "tags": "$:/tags/Manager/ItemSidebar",
            "caption": "{{$:/language/Manager/Item/Tools}}",
            "text": "<p>\n<$button to=<<currentTiddler>>>{{$:/core/images/link}} open</$button>\n</p>\n<p>\n<$button message=\"tm-edit-tiddler\" param=<<currentTiddler>>>{{$:/core/images/edit-button}} edit</$button>\n</p>\n"
        },
        "$:/Manager": {
            "title": "$:/Manager",
            "icon": "$:/core/images/list",
            "color": "#bbb",
            "text": "\\define lingo-base() $:/language/Manager/\n\n\\define list-item-content-item()\n<div class=\"tc-manager-list-item-content-item\">\n\t<$vars state-title=\"\"\"$:/state/popup/manager/item/$(listItem)$\"\"\">\n\t\t<$reveal state=<<state-title>> type=\"match\" text=\"show\" default=\"show\" tag=\"div\">\n\t\t\t<$button set=<<state-title>> setTo=\"hide\" class=\"tc-btn-invisible tc-manager-list-item-content-item-heading\">\n\t\t\t\t{{$:/core/images/down-arrow}} <$transclude tiddler=<<listItem>> field=\"caption\"/>\n\t\t\t</$button>\n\t\t</$reveal>\n\t\t<$reveal state=<<state-title>> type=\"nomatch\" text=\"show\" default=\"show\" tag=\"div\">\n\t\t\t<$button set=<<state-title>> setTo=\"show\" class=\"tc-btn-invisible tc-manager-list-item-content-item-heading\">\n\t\t\t\t{{$:/core/images/right-arrow}} <$transclude tiddler=<<listItem>> field=\"caption\"/>\n\t\t\t</$button>\n\t\t</$reveal>\n\t\t<$reveal state=<<state-title>> type=\"match\" text=\"show\" default=\"show\" tag=\"div\" class=\"tc-manager-list-item-content-item-body\">\n\t\t\t<$transclude tiddler=<<listItem>>/>\n\t\t</$reveal>\n\t</$vars>\n</div>\n\\end\n\n<div class=\"tc-manager-wrapper\">\n\t<div class=\"tc-manager-controls\">\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/Show/Prompt>> <$select tiddler=\"$:/config/Manager/Show\" default=\"tiddlers\">\n\t\t\t\t<option value=\"tiddlers\"><<lingo Controls/Show/Option/Tiddlers>></option>\n\t\t\t\t<option value=\"tags\"><<lingo Controls/Show/Option/Tags>></option>\n\t\t\t</$select>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/Search/Prompt>> <$edit-text tiddler=\"$:/config/Manager/Filter\" tag=\"input\" default=\"\" placeholder={{$:/language/Manager/Controls/Search/Placeholder}}/>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/FilterByTag/Prompt>> <$select tiddler=\"$:/config/Manager/Tag\" default=\"\">\n\t\t\t\t<option value=\"\"><<lingo Controls/FilterByTag/None>></option>\n\t\t\t\t<$list filter=\"[!is{$:/config/Manager/System}tags[]!is[system]sort[title]]\" variable=\"tag\">\n\t\t\t\t\t<option value=<<tag>>><$text text=<<tag>>/></option>\n\t\t\t\t</$list>\n\t\t\t</$select>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/Sort/Prompt>> <$select tiddler=\"$:/config/Manager/Sort\" default=\"title\">\n\t\t\t\t<optgroup label=\"Common\">\n\t\t\t\t\t<$list filter=\"title modified modifier created creator created\" variable=\"field\">\n\t\t\t\t\t\t<option value=<<field>>><$text text=<<field>>/></option>\n\t\t\t\t\t</$list>\n\t\t\t\t</optgroup>\n\t\t\t\t<optgroup label=\"All\">\n\t\t\t\t\t<$list filter=\"[all{$:/config/Manager/Show}!is{$:/config/Manager/System}fields[]sort[title]] -title -modified -modifier -created -creator -created\" variable=\"field\">\n\t\t\t\t\t\t<option value=<<field>>><$text text=<<field>>/></option>\n\t\t\t\t\t</$list>\n\t\t\t\t</optgroup>\n\t\t\t</$select>\n\t\t\t<$checkbox tiddler=\"$:/config/Manager/Order\" field=\"text\" checked=\"reverse\" unchecked=\"forward\" default=\"forward\">\n\t\t\t\t<<lingo Controls/Order/Prompt>>\n\t\t\t</$checkbox>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<$checkbox tiddler=\"$:/config/Manager/System\" field=\"text\" checked=\"\" unchecked=\"system\" default=\"system\">\n\t\t\t\t{{$:/language/SystemTiddlers/Include/Prompt}}\n\t\t\t</$checkbox>\n\t\t</div>\n\t</div>\n\t<div class=\"tc-manager-list\">\n\t\t<$list filter=\"[all{$:/config/Manager/Show}!is{$:/config/Manager/System}search{$:/config/Manager/Filter}tag:strict{$:/config/Manager/Tag}sort{$:/config/Manager/Sort}order{$:/config/Manager/Order}]\">\n\t\t\t<$vars transclusion=<<currentTiddler>>>\n\t\t\t\t<div style=\"tc-manager-list-item\">\n\t\t\t\t\t<$button popup=<<qualify \"$:/state/manager/popup\">> class=\"tc-btn-invisible tc-manager-list-item-heading\" selectedClass=\"tc-manager-list-item-heading-selected\">\n\t\t\t\t\t\t<$text text=<<currentTiddler>>/>\n\t\t\t\t\t</$button>\n\t\t\t\t\t<$reveal state=<<qualify \"$:/state/manager/popup\">> type=\"nomatch\" text=\"\" default=\"\" tag=\"div\" class=\"tc-manager-list-item-content tc-popup-handle\">\n\t\t\t\t\t\t<div class=\"tc-manager-list-item-content-tiddler\">\n\t\t\t\t\t\t\t<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Manager/ItemMain]!has[draft.of]]\" variable=\"listItem\">\n\t\t\t\t\t\t\t\t<<list-item-content-item>>\n\t\t\t\t\t\t\t</$list>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"tc-manager-list-item-content-sidebar\">\n\t\t\t\t\t\t\t<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Manager/ItemSidebar]!has[draft.of]]\" variable=\"listItem\">\n\t\t\t\t\t\t\t\t<<list-item-content-item>>\n\t\t\t\t\t\t\t</$list>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</$reveal>\n\t\t\t\t</div>\n\t\t\t</$vars>\n\t\t</$list>\n\t</div>\n</div>\n"
        },
        "$:/core/ui/MissingTemplate": {
            "title": "$:/core/ui/MissingTemplate",
            "text": "<div class=\"tc-tiddler-missing\">\n<$button popup=<<qualify \"$:/state/popup/missing\">> class=\"tc-btn-invisible tc-missing-tiddler-label\">\n<$view field=\"title\" format=\"text\" />\n</$button>\n<$reveal state=<<qualify \"$:/state/popup/missing\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n<$transclude tiddler=\"$:/core/ui/ListItemTemplate\"/>\n<hr>\n<$list filter=\"[all[current]backlinks[]sort[title]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n</div>\n</$reveal>\n</div>\n"
        },
        "$:/core/ui/MoreSideBar/All": {
            "title": "$:/core/ui/MoreSideBar/All",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/All/Caption}}",
            "text": "<$list filter={{$:/core/Filters/AllTiddlers!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/Drafts": {
            "title": "$:/core/ui/MoreSideBar/Drafts",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Drafts/Caption}}",
            "text": "<$list filter={{$:/core/Filters/Drafts!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/Explorer": {
            "title": "$:/core/ui/MoreSideBar/Explorer",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Explorer/Caption}}",
            "text": "<<tree \"$:/\">>\n"
        },
        "$:/core/ui/MoreSideBar/Missing": {
            "title": "$:/core/ui/MoreSideBar/Missing",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Missing/Caption}}",
            "text": "<$list filter={{$:/core/Filters/Missing!!filter}} template=\"$:/core/ui/MissingTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/Orphans": {
            "title": "$:/core/ui/MoreSideBar/Orphans",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Orphans/Caption}}",
            "text": "<$list filter={{$:/core/Filters/Orphans!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/Plugins": {
            "title": "$:/core/ui/MoreSideBar/Plugins",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/ControlPanel/Plugins/Caption}}",
            "text": "\n{{$:/language/ControlPanel/Plugins/Installed/Hint}}\n\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/MoreSideBar/Plugins]!has[draft.of]]\" \"$:/core/ui/MoreSideBar/Plugins/Plugins\">>\n"
        },
        "$:/core/ui/MoreSideBar/Recent": {
            "title": "$:/core/ui/MoreSideBar/Recent",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Recent/Caption}}",
            "text": "<$macrocall $name=\"timeline\" format={{$:/language/RecentChanges/DateFormat}}/>\n"
        },
        "$:/core/ui/MoreSideBar/Shadows": {
            "title": "$:/core/ui/MoreSideBar/Shadows",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Shadows/Caption}}",
            "text": "<$list filter={{$:/core/Filters/ShadowTiddlers!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/System": {
            "title": "$:/core/ui/MoreSideBar/System",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/System/Caption}}",
            "text": "<$list filter={{$:/core/Filters/SystemTiddlers!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/MoreSideBar/Tags": {
            "title": "$:/core/ui/MoreSideBar/Tags",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Tags/Caption}}",
            "text": "<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n{{$:/core/ui/Buttons/tag-manager}}\n\n</$set>\n\n</$set>\n\n</$set>\n\n<$list filter={{$:/core/Filters/AllTags!!filter}}>\n\n<$transclude tiddler=\"$:/core/ui/TagTemplate\"/>\n\n</$list>\n\n<hr class=\"tc-untagged-separator\">\n\n{{$:/core/ui/UntaggedTemplate}}\n"
        },
        "$:/core/ui/MoreSideBar/Types": {
            "title": "$:/core/ui/MoreSideBar/Types",
            "tags": "$:/tags/MoreSideBar",
            "caption": "{{$:/language/SideBar/Types/Caption}}",
            "text": "<$list filter={{$:/core/Filters/TypedTiddlers!!filter}}>\n<div class=\"tc-menu-list-item\">\n<$view field=\"type\"/>\n<$list filter=\"[type{!!type}!is[system]sort[title]]\">\n<div class=\"tc-menu-list-subitem\">\n<$link to={{!!title}}><$view field=\"title\"/></$link>\n</div>\n</$list>\n</div>\n</$list>\n"
        },
        "$:/core/ui/MoreSideBar/Plugins/Languages": {
            "title": "$:/core/ui/MoreSideBar/Plugins/Languages",
            "tags": "$:/tags/MoreSideBar/Plugins",
            "caption": "{{$:/language/ControlPanel/Plugins/Languages/Caption}}",
            "text": "<$list filter=\"[!has[draft.of]plugin-type[language]sort[description]]\" template=\"$:/core/ui/PluginListItemTemplate\" emptyMessage={{$:/language/ControlPanel/Plugins/Empty/Hint}}/>\n"
        },
        "$:/core/ui/MoreSideBar/Plugins/Plugins": {
            "title": "$:/core/ui/MoreSideBar/Plugins/Plugins",
            "tags": "$:/tags/MoreSideBar/Plugins",
            "caption": "{{$:/language/ControlPanel/Plugins/Plugins/Caption}}",
            "text": "<$list filter=\"[!has[draft.of]plugin-type[plugin]sort[description]]\" template=\"$:/core/ui/PluginListItemTemplate\" emptyMessage={{$:/language/ControlPanel/Plugins/Empty/Hint}}>>/>\n"
        },
        "$:/core/ui/MoreSideBar/Plugins/Theme": {
            "title": "$:/core/ui/MoreSideBar/Plugins/Theme",
            "tags": "$:/tags/MoreSideBar/Plugins",
            "caption": "{{$:/language/ControlPanel/Plugins/Themes/Caption}}",
            "text": "<$list filter=\"[!has[draft.of]plugin-type[theme]sort[description]]\" template=\"$:/core/ui/PluginListItemTemplate\" emptyMessage={{$:/language/ControlPanel/Plugins/Empty/Hint}}/>\n"
        },
        "$:/core/ui/Buttons/advanced-search": {
            "title": "$:/core/ui/Buttons/advanced-search",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/advanced-search-button}} {{$:/language/Buttons/AdvancedSearch/Caption}}",
            "description": "{{$:/language/Buttons/AdvancedSearch/Hint}}",
            "text": "\\whitespace trim\n\\define control-panel-button(class)\n<$button to=\"$:/AdvancedSearch\" tooltip={{$:/language/Buttons/AdvancedSearch/Hint}} aria-label={{$:/language/Buttons/AdvancedSearch/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/advanced-search-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/AdvancedSearch/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/AdvancedSearch]]\" emptyMessage=<<control-panel-button>>>\n<<control-panel-button \"tc-selected\">>\n</$list>\n"
        },
        "$:/core/ui/Buttons/close-all": {
            "title": "$:/core/ui/Buttons/close-all",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/close-all-button}} {{$:/language/Buttons/CloseAll/Caption}}",
            "description": "{{$:/language/Buttons/CloseAll/Hint}}",
            "text": "<$button message=\"tm-close-all-tiddlers\" tooltip={{$:/language/Buttons/CloseAll/Hint}} aria-label={{$:/language/Buttons/CloseAll/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/close-all-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/CloseAll/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/control-panel": {
            "title": "$:/core/ui/Buttons/control-panel",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/options-button}} {{$:/language/Buttons/ControlPanel/Caption}}",
            "description": "{{$:/language/Buttons/ControlPanel/Hint}}",
            "text": "\\whitespace trim\n\\define control-panel-button(class)\n<$button to=\"$:/ControlPanel\" tooltip={{$:/language/Buttons/ControlPanel/Hint}} aria-label={{$:/language/Buttons/ControlPanel/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/options-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/ControlPanel/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/ControlPanel]]\" emptyMessage=<<control-panel-button>>>\n<<control-panel-button \"tc-selected\">>\n</$list>\n"
        },
        "$:/core/ui/Buttons/encryption": {
            "title": "$:/core/ui/Buttons/encryption",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/locked-padlock}} {{$:/language/Buttons/Encryption/Caption}}",
            "description": "{{$:/language/Buttons/Encryption/Hint}}",
            "text": "\\whitespace trim\n<$reveal type=\"match\" state=\"$:/isEncrypted\" text=\"yes\">\n<$button message=\"tm-clear-password\" tooltip={{$:/language/Buttons/Encryption/ClearPassword/Hint}} aria-label={{$:/language/Buttons/Encryption/ClearPassword/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/locked-padlock}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Encryption/ClearPassword/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>\n<$reveal type=\"nomatch\" state=\"$:/isEncrypted\" text=\"yes\">\n<$button message=\"tm-set-password\" tooltip={{$:/language/Buttons/Encryption/SetPassword/Hint}} aria-label={{$:/language/Buttons/Encryption/SetPassword/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/unlocked-padlock}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Encryption/SetPassword/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/export-page": {
            "title": "$:/core/ui/Buttons/export-page",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/export-button}} {{$:/language/Buttons/ExportPage/Caption}}",
            "description": "{{$:/language/Buttons/ExportPage/Hint}}",
            "text": "<$macrocall $name=\"exportButton\" exportFilter=\"[!is[system]sort[title]]\" lingoBase=\"$:/language/Buttons/ExportPage/\"/>"
        },
        "$:/core/ui/Buttons/fold-all": {
            "title": "$:/core/ui/Buttons/fold-all",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/fold-all-button}} {{$:/language/Buttons/FoldAll/Caption}}",
            "description": "{{$:/language/Buttons/FoldAll/Hint}}",
            "text": "<$button tooltip={{$:/language/Buttons/FoldAll/Hint}} aria-label={{$:/language/Buttons/FoldAll/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-all-tiddlers\" $param=<<currentTiddler>> foldedStatePrefix=\"$:/state/folded/\"/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\" variable=\"listItem\">\n{{$:/core/images/fold-all-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/FoldAll/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/full-screen": {
            "title": "$:/core/ui/Buttons/full-screen",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/full-screen-button}} {{$:/language/Buttons/FullScreen/Caption}}",
            "description": "{{$:/language/Buttons/FullScreen/Hint}}",
            "text": "<$button message=\"tm-full-screen\" tooltip={{$:/language/Buttons/FullScreen/Hint}} aria-label={{$:/language/Buttons/FullScreen/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/full-screen-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/FullScreen/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/home": {
            "title": "$:/core/ui/Buttons/home",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/home-button}} {{$:/language/Buttons/Home/Caption}}",
            "description": "{{$:/language/Buttons/Home/Hint}}",
            "text": "<$button message=\"tm-home\" tooltip={{$:/language/Buttons/Home/Hint}} aria-label={{$:/language/Buttons/Home/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/home-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Home/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/import": {
            "title": "$:/core/ui/Buttons/import",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/import-button}} {{$:/language/Buttons/Import/Caption}}",
            "description": "{{$:/language/Buttons/Import/Hint}}",
            "text": "<div class=\"tc-file-input-wrapper\">\n<$button tooltip={{$:/language/Buttons/Import/Hint}} aria-label={{$:/language/Buttons/Import/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/import-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Import/Caption}}/></span>\n</$list>\n</$button>\n<$browse tooltip={{$:/language/Buttons/Import/Hint}}/>\n</div>"
        },
        "$:/core/ui/Buttons/language": {
            "title": "$:/core/ui/Buttons/language",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/globe}} {{$:/language/Buttons/Language/Caption}}",
            "description": "{{$:/language/Buttons/Language/Hint}}",
            "text": "\\whitespace trim\n\\define flag-title()\n$(languagePluginTitle)$/icon\n\\end\n<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/language\">> tooltip={{$:/language/Buttons/Language/Hint}} aria-label={{$:/language/Buttons/Language/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n<span class=\"tc-image-button\">\n<$set name=\"languagePluginTitle\" value={{$:/language}}>\n<$image source=<<flag-title>>/>\n</$set>\n</span>\n</$list>\n<$text text=\" \"/>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Language/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/language\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n{{$:/snippets/languageswitcher}}\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/manager": {
            "title": "$:/core/ui/Buttons/manager",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/list}} {{$:/language/Buttons/Manager/Caption}}",
            "description": "{{$:/language/Buttons/Manager/Hint}}",
            "text": "\\whitespace trim\n\\define manager-button(class)\n<$button to=\"$:/Manager\" tooltip={{$:/language/Buttons/Manager/Hint}} aria-label={{$:/language/Buttons/Manager/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/list}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Manager/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/Manager]]\" emptyMessage=<<manager-button>>>\n<<manager-button \"tc-selected\">>\n</$list>\n"
        },
        "$:/core/ui/Buttons/more-page-actions": {
            "title": "$:/core/ui/Buttons/more-page-actions",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/down-arrow}} {{$:/language/Buttons/More/Caption}}",
            "description": "{{$:/language/Buttons/More/Hint}}",
            "text": "\\define config-title()\n$:/config/PageControlButtons/Visibility/$(listItem)$\n\\end\n<$button popup=<<qualify \"$:/state/popup/more\">> tooltip={{$:/language/Buttons/More/Hint}} aria-label={{$:/language/Buttons/More/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/down-arrow}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/More/Caption}}/></span>\n</$list>\n</$button><$reveal state=<<qualify \"$:/state/popup/more\">> type=\"popup\" position=\"below\" animate=\"yes\">\n\n<div class=\"tc-drop-down\">\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"tc-btn-invisible\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]] -[[$:/core/ui/Buttons/more-page-actions]]\" variable=\"listItem\">\n\n<$reveal type=\"match\" state=<<config-title>> text=\"hide\">\n\n<$set name=\"tv-config-toolbar-class\" filter=\"[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$set>\n\n</$reveal>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</div>\n\n</$reveal>"
        },
        "$:/core/ui/Buttons/new-image": {
            "title": "$:/core/ui/Buttons/new-image",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/new-image-button}} {{$:/language/Buttons/NewImage/Caption}}",
            "description": "{{$:/language/Buttons/NewImage/Hint}}",
            "text": "\\whitespace trim\n<$button tooltip={{$:/language/Buttons/NewImage/Hint}} aria-label={{$:/language/Buttons/NewImage/Caption}} class=<<tv-config-toolbar-class>> actions={{$:/core/ui/Actions/new-image}}>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/new-image-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewImage/Caption}}/></span>\n</$list>\n</$button>\n"
        },
        "$:/core/ui/Buttons/new-journal": {
            "title": "$:/core/ui/Buttons/new-journal",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/new-journal-button}} {{$:/language/Buttons/NewJournal/Caption}}",
            "description": "{{$:/language/Buttons/NewJournal/Hint}}",
            "text": "\\whitespace trim\n\\define journalButton()\n<$button tooltip={{$:/language/Buttons/NewJournal/Hint}} aria-label={{$:/language/Buttons/NewJournal/Caption}} class=<<tv-config-toolbar-class>> actions={{$:/core/ui/Actions/new-journal}}>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/new-journal-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewJournal/Caption}}/></span>\n</$list>\n</$button>\n\\end\n<<journalButton>>\n"
        },
        "$:/core/ui/Buttons/new-tiddler": {
            "title": "$:/core/ui/Buttons/new-tiddler",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/new-button}} {{$:/language/Buttons/NewTiddler/Caption}}",
            "description": "{{$:/language/Buttons/NewTiddler/Hint}}",
            "text": "\\whitespace trim\n<$button actions={{$:/core/ui/Actions/new-tiddler}} tooltip={{$:/language/Buttons/NewTiddler/Hint}} aria-label={{$:/language/Buttons/NewTiddler/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/new-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewTiddler/Caption}}/></span>\n</$list>\n</$button>\n"
        },
        "$:/core/ui/Buttons/palette": {
            "title": "$:/core/ui/Buttons/palette",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/palette}} {{$:/language/Buttons/Palette/Caption}}",
            "description": "{{$:/language/Buttons/Palette/Hint}}",
            "text": "\\whitespace trim\n<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/palette\">> tooltip={{$:/language/Buttons/Palette/Hint}} aria-label={{$:/language/Buttons/Palette/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/palette}}\n</$list>\n<$text text=\" \"/>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Palette/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/palette\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\" style=\"font-size:0.7em;\">\n{{$:/snippets/paletteswitcher}}\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/print": {
            "title": "$:/core/ui/Buttons/print",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/print-button}} {{$:/language/Buttons/Print/Caption}}",
            "description": "{{$:/language/Buttons/Print/Hint}}",
            "text": "<$button message=\"tm-print\" tooltip={{$:/language/Buttons/Print/Hint}} aria-label={{$:/language/Buttons/Print/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/print-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Print/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/refresh": {
            "title": "$:/core/ui/Buttons/refresh",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/refresh-button}} {{$:/language/Buttons/Refresh/Caption}}",
            "description": "{{$:/language/Buttons/Refresh/Hint}}",
            "text": "<$button message=\"tm-browser-refresh\" tooltip={{$:/language/Buttons/Refresh/Hint}} aria-label={{$:/language/Buttons/Refresh/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/refresh-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Refresh/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/save-wiki": {
            "title": "$:/core/ui/Buttons/save-wiki",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/save-button}} {{$:/language/Buttons/SaveWiki/Caption}}",
            "description": "{{$:/language/Buttons/SaveWiki/Hint}}",
            "text": "<$button tooltip={{$:/language/Buttons/SaveWiki/Hint}} aria-label={{$:/language/Buttons/SaveWiki/Caption}} class=<<tv-config-toolbar-class>>>\n<$wikify name=\"site-title\" text={{$:/config/SaveWikiButton/Filename}}>\n<$action-sendmessage $message=\"tm-save-wiki\" $param={{$:/config/SaveWikiButton/Template}} filename=<<site-title>>/>\n</$wikify>\n<span class=\"tc-dirty-indicator\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/save-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/SaveWiki/Caption}}/></span>\n</$list>\n</span>\n</$button>"
        },
        "$:/core/ui/Buttons/storyview": {
            "title": "$:/core/ui/Buttons/storyview",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/storyview-classic}} {{$:/language/Buttons/StoryView/Caption}}",
            "description": "{{$:/language/Buttons/StoryView/Hint}}",
            "text": "\\whitespace trim\n\\define icon()\n$:/core/images/storyview-$(storyview)$\n\\end\n<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/storyview\">> tooltip={{$:/language/Buttons/StoryView/Hint}} aria-label={{$:/language/Buttons/StoryView/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n<$set name=\"storyview\" value={{$:/view}}>\n<$transclude tiddler=<<icon>>/>\n</$set>\n</$list>\n<$text text=\" \"/>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/StoryView/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/storyview\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n{{$:/snippets/viewswitcher}}\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/tag-manager": {
            "title": "$:/core/ui/Buttons/tag-manager",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/tag-button}} {{$:/language/Buttons/TagManager/Caption}}",
            "description": "{{$:/language/Buttons/TagManager/Hint}}",
            "text": "\\whitespace trim\n\\define control-panel-button(class)\n<$button to=\"$:/TagManager\" tooltip={{$:/language/Buttons/TagManager/Hint}} aria-label={{$:/language/Buttons/TagManager/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/tag-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/TagManager/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/TagManager]]\" emptyMessage=<<control-panel-button>>>\n<<control-panel-button \"tc-selected\">>\n</$list>\n"
        },
        "$:/core/ui/Buttons/theme": {
            "title": "$:/core/ui/Buttons/theme",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/theme-button}} {{$:/language/Buttons/Theme/Caption}}",
            "description": "{{$:/language/Buttons/Theme/Hint}}",
            "text": "\\whitespace trim\n<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/theme\">> tooltip={{$:/language/Buttons/Theme/Hint}} aria-label={{$:/language/Buttons/Theme/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/theme-button}}\n</$list>\n<$text text=\" \"/>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Theme/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/theme\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n<$linkcatcher to=\"$:/theme\">\n{{$:/snippets/themeswitcher}}\n</$linkcatcher>\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/timestamp": {
            "title": "$:/core/ui/Buttons/timestamp",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/timestamp-on}} {{$:/language/Buttons/Timestamp/Caption}}",
            "description": "{{$:/language/Buttons/Timestamp/Hint}}",
            "text": "\\whitespace trim\n<$reveal type=\"nomatch\" state=\"$:/config/TimestampDisable\" text=\"yes\">\n<$button tooltip={{$:/language/Buttons/Timestamp/On/Hint}} aria-label={{$:/language/Buttons/Timestamp/On/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-setfield $tiddler=\"$:/config/TimestampDisable\" $value=\"yes\"/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/timestamp-on}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Timestamp/On/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=\"$:/config/TimestampDisable\" text=\"yes\">\n<$button tooltip={{$:/language/Buttons/Timestamp/Off/Hint}} aria-label={{$:/language/Buttons/Timestamp/Off/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-setfield $tiddler=\"$:/config/TimestampDisable\" $value=\"no\"/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/timestamp-off}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Timestamp/Off/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/unfold-all": {
            "title": "$:/core/ui/Buttons/unfold-all",
            "tags": "$:/tags/PageControls",
            "caption": "{{$:/core/images/unfold-all-button}} {{$:/language/Buttons/UnfoldAll/Caption}}",
            "description": "{{$:/language/Buttons/UnfoldAll/Hint}}",
            "text": "<$button tooltip={{$:/language/Buttons/UnfoldAll/Hint}} aria-label={{$:/language/Buttons/UnfoldAll/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-unfold-all-tiddlers\" $param=<<currentTiddler>> foldedStatePrefix=\"$:/state/folded/\"/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\" variable=\"listItem\">\n{{$:/core/images/unfold-all-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/UnfoldAll/Caption}}/></span>\n</$list>\n</$button>"
        },
        "$:/core/ui/PageTemplate/pagecontrols": {
            "title": "$:/core/ui/PageTemplate/pagecontrols",
            "text": "\\whitespace trim\n\\define config-title()\n$:/config/PageControlButtons/Visibility/$(listItem)$\n\\end\n<div class=\"tc-page-controls\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]\" variable=\"listItem\">\n<$set name=\"hidden\" value=<<config-title>>>\n<$list filter=\"[<hidden>!text[hide]]\" storyview=\"pop\" variable=\"ignore\">\n<$set name=\"tv-config-toolbar-class\" filter=\"[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]\">\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n</$set>\n</$list>\n</$set>\n</$list>\n</div>\n"
        },
        "$:/core/ui/PageStylesheet": {
            "title": "$:/core/ui/PageStylesheet",
            "text": "\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\n<$set name=\"currentTiddler\" value={{$:/language}}>\n\n<$set name=\"languageTitle\" value={{!!name}}>\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Stylesheet]!has[draft.of]]\">\n<$transclude mode=\"block\"/>\n</$list>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/PageTemplate/alerts": {
            "title": "$:/core/ui/PageTemplate/alerts",
            "tags": "$:/tags/PageTemplate",
            "text": "<div class=\"tc-alerts\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Alert]!has[draft.of]]\" template=\"$:/core/ui/AlertTemplate\" storyview=\"pop\"/>\n\n</div>\n"
        },
        "$:/core/ui/PageTemplate/drafts": {
            "title": "$:/core/ui/PageTemplate/drafts",
            "tags": "$:/tags/PageTemplate",
            "text": "\\whitespace trim\n<$reveal state=\"$:/status/IsReadOnly\" type=\"nomatch\" text=\"yes\" tag=\"div\" class=\"tc-drafts-list\">\n<$list filter=\"[has[draft.of]!sort[modified]] -[list[$:/StoryList]]\">\n<$link>\n{{$:/core/images/edit-button}} <$text text=<<currentTiddler>>/>\n</$link>\n</$list>\n</$reveal>\n"
        },
        "$:/core/ui/PageTemplate/pluginreloadwarning": {
            "title": "$:/core/ui/PageTemplate/pluginreloadwarning",
            "tags": "$:/tags/PageTemplate",
            "text": "\\define lingo-base() $:/language/\n\n<$list filter=\"[{$:/status/RequireReloadDueToPluginChange}match[yes]]\">\n\n<$reveal type=\"nomatch\" state=\"$:/temp/HidePluginWarning\" text=\"yes\">\n\n<div class=\"tc-plugin-reload-warning\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n<<lingo PluginReloadWarning>> <$button set=\"$:/temp/HidePluginWarning\" setTo=\"yes\" class=\"tc-btn-invisible\">{{$:/core/images/close-button}}</$button>\n\n</$set>\n\n</div>\n\n</$reveal>\n\n</$list>\n"
        },
        "$:/core/ui/PageTemplate/sidebar": {
            "title": "$:/core/ui/PageTemplate/sidebar",
            "tags": "$:/tags/PageTemplate",
            "text": "\\whitespace trim\n\\define config-title()\n$:/config/SideBarSegments/Visibility/$(listItem)$\n\\end\n\n<$scrollable fallthrough=\"no\" class=\"tc-sidebar-scrollable\">\n\n<div class=\"tc-sidebar-header\">\n\n<$reveal state=\"$:/state/sidebar\" type=\"match\" text=\"yes\" default=\"yes\" retain=\"yes\" animate=\"yes\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SideBarSegment]!has[draft.of]]\" variable=\"listItem\">\n\n<$reveal type=\"nomatch\" state=<<config-title>> text=\"hide\"  tag=\"div\">\n\n<$transclude tiddler=<<listItem>> mode=\"block\"/>\n\n</$reveal>\n\n</$list>\n\n</$reveal>\n\n</div>\n\n</$scrollable>\n"
        },
        "$:/core/ui/PageTemplate/story": {
            "title": "$:/core/ui/PageTemplate/story",
            "tags": "$:/tags/PageTemplate",
            "text": "\\whitespace trim\n<section class=\"tc-story-river\">\n\n<section class=\"story-backdrop\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/AboveStory]!has[draft.of]]\">\n\n<$transclude/>\n\n</$list>\n\n</section>\n\n<$list filter=\"[list[$:/StoryList]]\" history=\"$:/HistoryList\" template={{$:/config/ui/ViewTemplate}} editTemplate={{$:/config/ui/EditTemplate}} storyview={{$:/view}} emptyMessage={{$:/config/EmptyStoryMessage}}/>\n\n<section class=\"story-frontdrop\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/BelowStory]!has[draft.of]]\">\n\n<$transclude/>\n\n</$list>\n\n</section>\n\n</section>\n"
        },
        "$:/core/ui/PageTemplate/topleftbar": {
            "title": "$:/core/ui/PageTemplate/topleftbar",
            "tags": "$:/tags/PageTemplate",
            "text": "<span class=\"tc-topbar tc-topbar-left\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TopLeftBar]!has[draft.of]]\" variable=\"listItem\" storyview=\"pop\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$list>\n\n</span>\n"
        },
        "$:/core/ui/PageTemplate/toprightbar": {
            "title": "$:/core/ui/PageTemplate/toprightbar",
            "tags": "$:/tags/PageTemplate",
            "text": "<span class=\"tc-topbar tc-topbar-right\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TopRightBar]!has[draft.of]]\" variable=\"listItem\" storyview=\"pop\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$list>\n\n</span>\n"
        },
        "$:/core/ui/PageTemplate": {
            "title": "$:/core/ui/PageTemplate",
            "text": "\\whitespace trim\n\\define containerClasses()\ntc-page-container tc-page-view-$(storyviewTitle)$ tc-language-$(languageTitle)$\n\\end\n\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\n<$set name=\"tv-config-toolbar-icons\" value={{$:/config/Toolbar/Icons}}>\n\n<$set name=\"tv-config-toolbar-text\" value={{$:/config/Toolbar/Text}}>\n\n<$set name=\"tv-config-toolbar-class\" value={{$:/config/Toolbar/ButtonClass}}>\n\n<$set name=\"tv-enable-drag-and-drop\" value={{$:/config/DragAndDrop/Enable}}>\n\n<$set name=\"tv-show-missing-links\" value={{$:/config/MissingLinks}}>\n\n<$set name=\"storyviewTitle\" value={{$:/view}}>\n\n<$set name=\"languageTitle\" value={{{ [{$:/language}get[name]] }}}>\n\n<div class=<<containerClasses>>>\n\n<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>\n\n<$dropzone enable=<<tv-enable-drag-and-drop>>>\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageTemplate]!has[draft.of]]\" variable=\"listItem\">\n\n<$transclude tiddler=<<listItem>>/>\n\n</$list>\n\n</$dropzone>\n\n</$navigator>\n\n</div>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n"
        },
        "$:/PaletteManager": {
            "title": "$:/PaletteManager",
            "text": "\\define lingo-base() $:/language/ControlPanel/Palette/Editor/\n\\define describePaletteColour(colour)\n<$transclude tiddler=\"$:/language/Docs/PaletteColours/$colour$\"><$text text=\"$colour$\"/></$transclude>\n\\end\n\\define edit-colour-placeholder()\n edit $(colourName)$\n\\end\n\\define colour-tooltip(showhide) $showhide$ editor for $(newColourName)$ \n\\define resolve-colour(macrocall)\n\\import $:/core/macros/utils\n\\whitespace trim\n<$wikify name=\"name\" text=\"\"\"$macrocall$\"\"\">\n<<name>>\n</$wikify>\n\\end\n\\define delete-colour-index-actions() <$action-setfield $index=<<colourName>>/>\n\\define palette-manager-colour-row-segment()\n\\whitespace trim\n<$edit-text index=<<colourName>> tag=\"input\" placeholder=<<edit-colour-placeholder>> default=\"\"/>\n<br>\n<$edit-text index=<<colourName>> type=\"color\" tag=\"input\" class=\"tc-palette-manager-colour-input\"/>\n<$list filter=\"[<currentTiddler>getindex<colourName>removeprefix[<<]removesuffix[>>]] [<currentTiddler>getindex<colourName>removeprefix[<$]removesuffix[/>]]\" variable=\"ignore\">\n<$set name=\"state\" value={{{ [[$:/state/palettemanager/]addsuffix<currentTiddler>addsuffix[/]addsuffix<colourName>] }}}>\n<$wikify name=\"newColourName\" text=\"\"\"<$macrocall $name=\"resolve-colour\" macrocall={{{ [<currentTiddler>getindex<colourName>] }}}/>\"\"\">\n<$reveal state=<<state>> type=\"nomatch\" text=\"show\">\n<$button tooltip=<<colour-tooltip show>> aria-label=<<colour-tooltip show>> class=\"tc-btn-invisible\" set=<<state>> setTo=\"show\">{{$:/core/images/down-arrow}}&nbsp;<$text text=<<newColourName>>/></$button><br>\n</$reveal>\n<$reveal state=<<state>> type=\"match\" text=\"show\">\n<$button tooltip=<<colour-tooltip hide>> aria-label=<<colour-tooltip show>> class=\"tc-btn-invisible\" actions=\"\"\"<$action-deletetiddler $tiddler=<<state>>/>\"\"\">{{$:/core/images/up-arrow}}&nbsp;<$text text=<<newColourName>>/></$button><br>\n</$reveal>\n<$reveal state=<<state>> type=\"match\" text=\"show\">\n<$set name=\"colourName\" value=<<newColourName>>>\n<br>\n<<palette-manager-colour-row-segment>>\n<br><br>\n</$set>\n</$reveal>\n</$wikify>\n</$set>\n</$list>\n\\end\n\\define palette-manager-colour-row()\n\\whitespace trim\n<tr>\n<td>\n<span style=\"float:right;\">\n<$button tooltip=<<lingo Delete/Hint>> aria-label=<<lingo Delete/Hint>> class=\"tc-btn-invisible\" actions=<<delete-colour-index-actions>>>\n{{$:/core/images/delete-button}}</$button>\n</span>\n''<$macrocall $name=\"describePaletteColour\" colour=<<colourName>>/>''<br/>\n<$macrocall $name=\"colourName\" $output=\"text/plain\"/>\n</td>\n<td>\n<<palette-manager-colour-row-segment>>\n</td>\n</tr>\n\\end\n\\define palette-manager-table()\n\\whitespace trim\n<table>\n<tbody>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Palette]indexes[]]\" variable=\"colourName\">\n<$list filter=\"[<currentTiddler>indexes[]removeprefix<colourName>suffix[]]\" variable=\"ignore\" emptyMessage=\"\"\"\n<$list filter=\"[{$:/state/palettemanager/showexternal}removeprefix[yes]suffix[]]\" variable=\"ignore\">\n<<palette-manager-colour-row>>\n</$list>\n\"\"\">\n<<palette-manager-colour-row>>\n</$list>\n</$list>\n</tbody>\n</table>\n\\end\n<$set name=\"currentTiddler\" value={{$:/palette}}>\n\n<<lingo Prompt>> <$link to={{$:/palette}}><$macrocall $name=\"currentTiddler\" $output=\"text/plain\"/></$link>\n\n<$list filter=\"[all[current]is[shadow]is[tiddler]]\" variable=\"listItem\">\n<<lingo Prompt/Modified>>\n<$button message=\"tm-delete-tiddler\" param={{$:/palette}}><<lingo Reset/Caption>></$button>\n</$list>\n\n<$list filter=\"[all[current]is[shadow]!is[tiddler]]\" variable=\"listItem\">\n<<lingo Clone/Prompt>>\n</$list>\n\n<$button message=\"tm-new-tiddler\" param={{$:/palette}}><<lingo Clone/Caption>></$button>\n\n<$checkbox tiddler=\"$:/state/palettemanager/showexternal\" field=\"text\" checked=\"yes\" unchecked=\"no\">&nbsp;<<lingo Names/External/Show>></$checkbox>\n\n<<palette-manager-table>>\n"
        },
        "$:/core/ui/PluginInfo": {
            "title": "$:/core/ui/PluginInfo",
            "text": "\\define localised-info-tiddler-title()\n$(currentTiddler)$/$(languageTitle)$/$(currentTab)$\n\\end\n\\define info-tiddler-title()\n$(currentTiddler)$/$(currentTab)$\n\\end\n\\define default-tiddler-title()\n$:/core/ui/PluginInfo/Default/$(currentTab)$\n\\end\n<$transclude tiddler=<<localised-info-tiddler-title>> mode=\"block\">\n<$transclude tiddler=<<currentTiddler>> subtiddler=<<localised-info-tiddler-title>> mode=\"block\">\n<$transclude tiddler=<<currentTiddler>> subtiddler=<<info-tiddler-title>> mode=\"block\">\n<$transclude tiddler=<<default-tiddler-title>> mode=\"block\">\n{{$:/language/ControlPanel/Plugin/NoInfoFound/Hint}}\n</$transclude>\n</$transclude>\n</$transclude>\n</$transclude>\n"
        },
        "$:/core/ui/PluginInfo/Default/contents": {
            "title": "$:/core/ui/PluginInfo/Default/contents",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/Advanced/PluginInfo/\n<<lingo Hint>>\n<ul>\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" emptyMessage=<<lingo Empty/Hint>>>\n<li>\n<$link />\n</li>\n</$list>\n</ul>\n"
        },
        "$:/core/ui/PluginListItemTemplate": {
            "title": "$:/core/ui/PluginListItemTemplate",
            "text": "<div class=\"tc-menu-list-item\">\n<$link to={{!!title}}><$view field=\"description\"><$view field=\"title\"/></$view></$link>\n</div>"
        },
        "$:/core/ui/SearchResults": {
            "title": "$:/core/ui/SearchResults",
            "text": "<div class=\"tc-search-results\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]butfirst[]limit[1]]\" emptyMessage=\"\"\"\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\">\n<$transclude mode=\"block\"/>\n</$list>\n\"\"\">\n\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\" default={{$:/config/SearchResults/Default}}/>\n\n</$list>\n\n</div>\n"
        },
        "$:/core/ui/SideBar/More": {
            "title": "$:/core/ui/SideBar/More",
            "tags": "$:/tags/SideBar",
            "caption": "{{$:/language/SideBar/More/Caption}}",
            "text": "<div class=\"tc-more-sidebar\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]\" default={{$:/config/DefaultMoreSidebarTab}} state=\"$:/state/tab/moresidebar\" class=\"tc-vertical tc-sidebar-tabs-more\" />\n</div>"
        },
        "$:/core/ui/SideBar/Open": {
            "title": "$:/core/ui/SideBar/Open",
            "tags": "$:/tags/SideBar",
            "caption": "{{$:/language/SideBar/Open/Caption}}",
            "text": "\\whitespace trim\n\\define lingo-base() $:/language/CloseAll/\n\n\\define drop-actions()\n<$action-listops $tiddler=<<tv-story-list>> $subfilter=\"+[insertbefore:currentTiddler<actionTiddler>]\"/>\n\\end\n\n\\define placeholder()\n<div class=\"tc-droppable-placeholder\"/>\n\\end\n\n\\define droppable-item(button)\n\\whitespace trim\n<$droppable actions=<<drop-actions>> enable=<<tv-allow-drag-and-drop>>>\n<<placeholder>>\n<div>\n$button$\n</div>\n</$droppable>\n\\end\n\n<div class=\"tc-sidebar-tab-open\">\n<$list filter=\"[list<tv-story-list>]\" history=<<tv-history-list>> storyview=\"pop\">\n<div class=\"tc-sidebar-tab-open-item\">\n<$macrocall $name=\"droppable-item\" button=\"\"\"<$button message=\"tm-close-tiddler\" tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class=\"tc-btn-invisible tc-btn-mini\">{{$:/core/images/close-button}}</$button>&nbsp;<$link to={{!!title}}><$view field=\"title\"/></$link>\"\"\"/>\n</div>\n</$list>\n<$tiddler tiddler=\"\">\n<div>\n<$macrocall $name=\"droppable-item\" button=\"\"\"<$button message=\"tm-close-all-tiddlers\" class=\"tc-btn-invisible tc-btn-mini\"><<lingo Button>></$button>\"\"\"/>\n</div>\n</$tiddler>\n</div>\n"
        },
        "$:/core/ui/SideBar/Recent": {
            "title": "$:/core/ui/SideBar/Recent",
            "tags": "$:/tags/SideBar",
            "caption": "{{$:/language/SideBar/Recent/Caption}}",
            "text": "<$macrocall $name=\"timeline\" format={{$:/language/RecentChanges/DateFormat}}/>\n"
        },
        "$:/core/ui/SideBar/Tools": {
            "title": "$:/core/ui/SideBar/Tools",
            "tags": "$:/tags/SideBar",
            "caption": "{{$:/language/SideBar/Tools/Caption}}",
            "text": "\\define lingo-base() $:/language/ControlPanel/\n\\define config-title()\n$:/config/PageControlButtons/Visibility/$(listItem)$\n\\end\n\n<<lingo Basics/Version/Prompt>> <<version>>\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]\" variable=\"listItem\">\n\n<div style=\"position:relative;\" class={{{ [<listItem>encodeuricomponent[]addprefix[tc-btn-]] }}}>\n\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <$transclude tiddler=<<listItem>>/> <i class=\"tc-muted\"><$transclude tiddler=<<listItem>> field=\"description\"/></i>\n\n</div>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/SideBarLists": {
            "title": "$:/core/ui/SideBarLists",
            "text": "<$transclude tiddler=\"$:/core/ui/SideBarSegments/search\"/>\n\n<$transclude tiddler=\"$:/core/ui/SideBarSegments/tabs\"/>\n\n"
        },
        "$:/core/ui/SideBarSegments/page-controls": {
            "title": "$:/core/ui/SideBarSegments/page-controls",
            "tags": "$:/tags/SideBarSegment",
            "text": "{{||$:/core/ui/PageTemplate/pagecontrols}}\n"
        },
        "$:/core/ui/SideBarSegments/search": {
            "title": "$:/core/ui/SideBarSegments/search",
            "tags": "$:/tags/SideBarSegment",
            "text": "\\whitespace trim\n<div class=\"tc-sidebar-lists tc-sidebar-search\">\n\n<$set name=\"searchTiddler\" value=\"$:/temp/search\">\n<div class=\"tc-search\">\n<$edit-text tiddler=\"$:/temp/search\" type=\"search\" tag=\"input\" focus={{$:/config/Search/AutoFocus}} focusPopup=<<qualify \"$:/state/popup/search-dropdown\">> class=\"tc-popup-handle\"/>\n<$reveal state=\"$:/temp/search\" type=\"nomatch\" text=\"\">\n<$button tooltip={{$:/language/Buttons/AdvancedSearch/Hint}} aria-label={{$:/language/Buttons/AdvancedSearch/Caption}} class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" text={{$:/temp/search}}/>\n<$action-setfield $tiddler=\"$:/temp/search\" text=\"\"/>\n<$action-navigate $to=\"$:/AdvancedSearch\"/>\n{{$:/core/images/advanced-search-button}}\n</$button>\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/search\" text=\"\" />\n{{$:/core/images/close-button}}\n</$button>\n<$button popup=<<qualify \"$:/state/popup/search-dropdown\">> class=\"tc-btn-invisible\">\n{{$:/core/images/down-arrow}}\n<$list filter=\"[{$:/temp/search}minlength{$:/config/Search/MinLength}limit[1]]\" variable=\"listItem\">\n<$set name=\"searchTerm\" value={{{ [<searchTiddler>get[text]] }}}>\n<$set name=\"resultCount\" value=\"\"\"<$count filter=\"[!is[system]search<searchTerm>]\"/>\"\"\">\n{{$:/language/Search/Matches}}\n</$set>\n</$set>\n</$list>\n</$button>\n</$reveal>\n<$reveal state=\"$:/temp/search\" type=\"match\" text=\"\">\n<$button to=\"$:/AdvancedSearch\" tooltip={{$:/language/Buttons/AdvancedSearch/Hint}} aria-label={{$:/language/Buttons/AdvancedSearch/Caption}} class=\"tc-btn-invisible\">\n{{$:/core/images/advanced-search-button}}\n</$button>\n</$reveal>\n</div>\n\n<$reveal tag=\"div\" class=\"tc-block-dropdown-wrapper\" state=\"$:/temp/search\" type=\"nomatch\" text=\"\">\n\n<$reveal tag=\"div\" class=\"tc-block-dropdown tc-search-drop-down tc-popup-handle\" state=<<qualify \"$:/state/popup/search-dropdown\">> type=\"nomatch\" text=\"\" default=\"\">\n\n<$list filter=\"[{$:/temp/search}minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n\n{{$:/core/ui/SearchResults}}\n\n</$list>\n\n</$reveal>\n\n</$reveal>\n\n</$set>\n\n</div>\n"
        },
        "$:/core/ui/SideBarSegments/site-subtitle": {
            "title": "$:/core/ui/SideBarSegments/site-subtitle",
            "tags": "$:/tags/SideBarSegment",
            "text": "<div class=\"tc-site-subtitle\">\n\n<$transclude tiddler=\"$:/SiteSubtitle\" mode=\"inline\"/>\n\n</div>\n"
        },
        "$:/core/ui/SideBarSegments/site-title": {
            "title": "$:/core/ui/SideBarSegments/site-title",
            "tags": "$:/tags/SideBarSegment",
            "text": "<h1 class=\"tc-site-title\">\n\n<$transclude tiddler=\"$:/SiteTitle\" mode=\"inline\"/>\n\n</h1>\n"
        },
        "$:/core/ui/SideBarSegments/tabs": {
            "title": "$:/core/ui/SideBarSegments/tabs",
            "tags": "$:/tags/SideBarSegment",
            "text": "<div class=\"tc-sidebar-lists tc-sidebar-tabs\">\n\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/SideBar]!has[draft.of]]\" default={{$:/config/DefaultSidebarTab}} state=\"$:/state/tab/sidebar\" class=\"tc-sidebar-tabs-main\"/>\n\n</div>\n"
        },
        "$:/TagManager": {
            "title": "$:/TagManager",
            "icon": "$:/core/images/tag-button",
            "color": "#bbb",
            "text": "\\define lingo-base() $:/language/TagManager/\n\\define iconEditorTab(type)\n\\whitespace trim\n<$link to=\"\"><<lingo Icons/None>></$link>\n<$list filter=\"[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[sort[title]] +[$type$is[system]]\">\n<$link to={{!!title}}>\n<$transclude/> <$view field=\"title\"/>\n</$link>\n</$list>\n\\end\n\\define iconEditor(title)\n\\whitespace trim\n<div class=\"tc-drop-down-wrapper\">\n<$button popupTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} class=\"tc-btn-invisible tc-btn-dropdown\">{{$:/core/images/down-arrow}}</$button>\n<$reveal stateTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} type=\"popup\" position=\"belowleft\" text=\"\" default=\"\">\n<div class=\"tc-drop-down\">\n<$linkcatcher actions=\"\"\"<$action-setfield $tiddler=<<__title__>> icon=<<navigateTo>>/>\"\"\">\n<<iconEditorTab type:\"!\">>\n<hr/>\n<<iconEditorTab type:\"\">>\n</$linkcatcher>\n</div>\n</$reveal>\n</div>\n\\end\n\\define toggleButton(state)\n\\whitespace trim\n<$reveal stateTitle=<<__state__>> type=\"match\" text=\"closed\" default=\"closed\">\n<$button setTitle=<<__state__>> setTo=\"open\" class=\"tc-btn-invisible tc-btn-dropdown\" selectedClass=\"tc-selected\">\n{{$:/core/images/info-button}}\n</$button>\n</$reveal>\n<$reveal stateTitle=<<__state__>> type=\"match\" text=\"open\" default=\"closed\">\n<$button setTitle=<<__state__>> setTo=\"closed\" class=\"tc-btn-invisible tc-btn-dropdown\" selectedClass=\"tc-selected\">\n{{$:/core/images/info-button}}\n</$button>\n</$reveal>\n\\end\n\\whitespace trim\n<table class=\"tc-tag-manager-table\">\n<tbody>\n<tr>\n<th><<lingo Colour/Heading>></th>\n<th class=\"tc-tag-manager-tag\"><<lingo Tag/Heading>></th>\n<th><<lingo Count/Heading>></th>\n<th><<lingo Icon/Heading>></th>\n<th><<lingo Info/Heading>></th>\n</tr>\n<$list filter=\"[tags[]!is[system]sort[title]]\">\n<tr>\n<td><$edit-text field=\"color\" tag=\"input\" type=\"color\"/></td>\n<td>{{||$:/core/ui/TagTemplate}}</td>\n<td><$count filter=\"[all[current]tagging[]]\"/></td>\n<td>\n<$macrocall $name=\"iconEditor\" title={{!!title}}/>\n</td>\n<td>\n<$macrocall $name=\"toggleButton\" state={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} /> \n</td>\n</tr>\n<tr>\n<td></td>\n<td colspan=\"4\">\n<$reveal stateTitle={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} type=\"match\" text=\"open\" default=\"\">\n<table>\n<tbody>\n<tr><td><<lingo Colour/Heading>></td><td><$edit-text field=\"color\" tag=\"input\" type=\"text\" size=\"9\"/></td></tr>\n<tr><td><<lingo Icon/Heading>></td><td><$edit-text field=\"icon\" tag=\"input\" size=\"45\"/></td></tr>\n</tbody>\n</table>\n</$reveal>\n</td>\n</tr>\n</$list>\n<tr>\n<td></td>\n<td style=\"position:relative;\">\n{{$:/core/ui/UntaggedTemplate}}\n</td>\n<td>\n<small class=\"tc-menu-list-count\"><$count filter=\"[untagged[]!is[system]] -[tags[]]\"/></small>\n</td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/TagTemplate": {
            "title": "$:/core/ui/TagTemplate",
            "text": "\\whitespace trim\n<span class=\"tc-tag-list-item\">\n<$set name=\"transclusion\" value=<<currentTiddler>>>\n<$macrocall $name=\"tag-pill-body\" tag=<<currentTiddler>> icon={{!!icon}} colour={{!!color}} palette={{$:/palette}} element-tag=\"\"\"$button\"\"\" element-attributes=\"\"\"popup=<<qualify \"$:/state/popup/tag\">> dragFilter='[all[current]tagging[]]' tag='span'\"\"\"/>\n<$reveal state=<<qualify \"$:/state/popup/tag\">> type=\"popup\" position=\"below\" animate=\"yes\" class=\"tc-drop-down\">\n<$set name=\"tv-show-missing-links\" value=\"yes\">\n<$transclude tiddler=\"$:/core/ui/ListItemTemplate\"/>\n</$set>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TagDropdown]!has[draft.of]]\" variable=\"listItem\"> \n<$transclude tiddler=<<listItem>>/> \n</$list>\n<hr>\n<$macrocall $name=\"list-tagged-draggable\" tag=<<currentTiddler>>/>\n</$reveal>\n</$set>\n</span>\n"
        },
        "$:/core/ui/TiddlerFieldTemplate": {
            "title": "$:/core/ui/TiddlerFieldTemplate",
            "text": "<tr class=\"tc-view-field\">\n<td class=\"tc-view-field-name\">\n<$text text=<<listItem>>/>\n</td>\n<td class=\"tc-view-field-value\">\n<$view field=<<listItem>>/>\n</td>\n</tr>"
        },
        "$:/core/ui/TiddlerFields": {
            "title": "$:/core/ui/TiddlerFields",
            "text": "<table class=\"tc-view-field-table\">\n<tbody>\n<$list filter=\"[all[current]fields[]sort[title]] -text\" template=\"$:/core/ui/TiddlerFieldTemplate\" variable=\"listItem\"/>\n</tbody>\n</table>\n"
        },
        "$:/core/ui/TiddlerInfo/Advanced/PluginInfo": {
            "title": "$:/core/ui/TiddlerInfo/Advanced/PluginInfo",
            "tags": "$:/tags/TiddlerInfo/Advanced",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/Advanced/PluginInfo/\n<$list filter=\"[all[current]has[plugin-type]]\">\n\n! <<lingo Heading>>\n\n<<lingo Hint>>\n<ul>\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" emptyMessage=<<lingo Empty/Hint>>>\n<li>\n<$link to={{!!title}}>\n<$view field=\"title\"/>\n</$link>\n</li>\n</$list>\n</ul>\n\n</$list>\n"
        },
        "$:/core/ui/TiddlerInfo/Advanced/ShadowInfo": {
            "title": "$:/core/ui/TiddlerInfo/Advanced/ShadowInfo",
            "tags": "$:/tags/TiddlerInfo/Advanced",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/Advanced/ShadowInfo/\n<$set name=\"infoTiddler\" value=<<currentTiddler>>>\n\n''<<lingo Heading>>''\n\n<$list filter=\"[all[current]!is[shadow]]\">\n\n<<lingo NotShadow/Hint>>\n\n</$list>\n\n<$list filter=\"[all[current]is[shadow]]\">\n\n<<lingo Shadow/Hint>>\n\n<$list filter=\"[all[current]shadowsource[]]\">\n\n<$set name=\"pluginTiddler\" value=<<currentTiddler>>>\n<<lingo Shadow/Source>>\n</$set>\n\n</$list>\n\n<$list filter=\"[all[current]is[shadow]is[tiddler]]\">\n\n<<lingo OverriddenShadow/Hint>>\n\n</$list>\n\n\n</$list>\n</$set>\n"
        },
        "$:/core/ui/TiddlerInfo/Advanced": {
            "title": "$:/core/ui/TiddlerInfo/Advanced",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/Advanced/Caption}}",
            "text": "<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TiddlerInfo/Advanced]!has[draft.of]]\" variable=\"listItem\">\n<$transclude tiddler=<<listItem>>/>\n\n</$list>\n"
        },
        "$:/core/ui/TiddlerInfo/Fields": {
            "title": "$:/core/ui/TiddlerInfo/Fields",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/Fields/Caption}}",
            "text": "<$transclude tiddler=\"$:/core/ui/TiddlerFields\"/>\n"
        },
        "$:/core/ui/TiddlerInfo/List": {
            "title": "$:/core/ui/TiddlerInfo/List",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/List/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[list{!!title}]\" emptyMessage=<<lingo List/Empty>> template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/TiddlerInfo/Listed": {
            "title": "$:/core/ui/TiddlerInfo/Listed",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/Listed/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[all[current]listed[]!is[system]]\" emptyMessage=<<lingo Listed/Empty>> template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/TiddlerInfo/References": {
            "title": "$:/core/ui/TiddlerInfo/References",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/References/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[all[current]backlinks[]sort[title]]\" emptyMessage=<<lingo References/Empty>> template=\"$:/core/ui/ListItemTemplate\">\n</$list>"
        },
        "$:/core/ui/TiddlerInfo/Tagging": {
            "title": "$:/core/ui/TiddlerInfo/Tagging",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/Tagging/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[all[current]tagging[]]\" emptyMessage=<<lingo Tagging/Empty>> template=\"$:/core/ui/ListItemTemplate\"/>\n"
        },
        "$:/core/ui/TiddlerInfo/Tools": {
            "title": "$:/core/ui/TiddlerInfo/Tools",
            "tags": "$:/tags/TiddlerInfo",
            "caption": "{{$:/language/TiddlerInfo/Tools/Caption}}",
            "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\\define config-title()\n$:/config/ViewToolbarButtons/Visibility/$(listItem)$\n\\end\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]]\" variable=\"listItem\">\n\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <$transclude tiddler=<<listItem>>/> <i class=\"tc-muted\"><$transclude tiddler=<<listItem>> field=\"description\"/></i>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n"
        },
        "$:/core/ui/TiddlerInfo": {
            "title": "$:/core/ui/TiddlerInfo",
            "text": "<div style=\"position:relative;\">\n<div class=\"tc-tiddler-controls\" style=\"position:absolute;right:0;\">\n<$reveal state=\"$:/config/TiddlerInfo/Mode\" type=\"match\" text=\"sticky\">\n<$button set=<<tiddlerInfoState>> setTo=\"\" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=\"tc-btn-invisible\">\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n</div>\n\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/TiddlerInfo]!has[draft.of]]\" default={{$:/config/TiddlerInfo/Default}}/>"
        },
        "$:/core/ui/TopBar/menu": {
            "title": "$:/core/ui/TopBar/menu",
            "tags": "$:/tags/TopRightBar",
            "text": "<$list filter=\"[[$:/state/sidebar]get[text]] +[else[yes]!match[no]]\" variable=\"ignore\">\n<$button set=\"$:/state/sidebar\" setTo=\"no\" tooltip={{$:/language/Buttons/HideSideBar/Hint}} aria-label={{$:/language/Buttons/HideSideBar/Caption}} class=\"tc-btn-invisible\">{{$:/core/images/chevron-right}}</$button>\n</$list>\n<$list filter=\"[[$:/state/sidebar]get[text]] +[else[yes]match[no]]\" variable=\"ignore\">\n<$button set=\"$:/state/sidebar\" setTo=\"yes\" tooltip={{$:/language/Buttons/ShowSideBar/Hint}} aria-label={{$:/language/Buttons/ShowSideBar/Caption}} class=\"tc-btn-invisible\">{{$:/core/images/chevron-left}}</$button>\n</$list>\n"
        },
        "$:/core/ui/UntaggedTemplate": {
            "title": "$:/core/ui/UntaggedTemplate",
            "text": "\\define lingo-base() $:/language/SideBar/\n<$button popup=<<qualify \"$:/state/popup/tag\">> class=\"tc-btn-invisible tc-untagged-label tc-tag-label\">\n<<lingo Tags/Untagged/Caption>>\n</$button>\n<$reveal state=<<qualify \"$:/state/popup/tag\">> type=\"popup\" position=\"below\">\n<div class=\"tc-drop-down\">\n<$list filter=\"[untagged[]!is[system]] -[tags[]] +[sort[title]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/ViewTemplate/body": {
            "title": "$:/core/ui/ViewTemplate/body",
            "tags": "$:/tags/ViewTemplate",
            "text": "<$reveal tag=\"div\" class=\"tc-tiddler-body\" type=\"nomatch\" stateTitle=<<folded-state>> text=\"hide\" retain=\"yes\" animate=\"yes\">\n\n<$list filter=\"[all[current]!has[plugin-type]!field:hide-body[yes]]\">\n\n<$transclude>\n\n<$transclude tiddler=\"$:/language/MissingTiddler/Hint\"/>\n\n</$transclude>\n\n</$list>\n\n</$reveal>\n"
        },
        "$:/core/ui/ViewTemplate/classic": {
            "title": "$:/core/ui/ViewTemplate/classic",
            "tags": "$:/tags/ViewTemplate $:/tags/EditTemplate",
            "text": "\\define lingo-base() $:/language/ClassicWarning/\n<$list filter=\"[all[current]type[text/x-tiddlywiki]]\">\n<div class=\"tc-message-box\">\n\n<<lingo Hint>>\n\n<$button set=\"!!type\" setTo=\"text/vnd.tiddlywiki\"><<lingo Upgrade/Caption>></$button>\n\n</div>\n</$list>\n"
        },
        "$:/core/ui/ViewTemplate/import": {
            "title": "$:/core/ui/ViewTemplate/import",
            "tags": "$:/tags/ViewTemplate",
            "text": "\\define lingo-base() $:/language/Import/\n\n\\define buttons()\n<$button message=\"tm-delete-tiddler\" param=<<currentTiddler>>><<lingo Listing/Cancel/Caption>></$button>\n<$button message=\"tm-perform-import\" param=<<currentTiddler>>><<lingo Listing/Import/Caption>></$button>\n<<lingo Listing/Preview>> <$select tiddler=\"$:/state/importpreviewtype\" default=\"$:/core/ui/ImportPreviews/Text\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ImportPreview]!has[draft.of]]\">\n<option value=<<currentTiddler>>>{{!!caption}}</option>\n</$list>\n</$select>\n\\end\n\n<$list filter=\"[all[current]field:plugin-type[import]]\">\n\n<div class=\"tc-import\">\n\n<<lingo Listing/Hint>>\n\n<<buttons>>\n\n{{||$:/core/ui/ImportListing}}\n\n<<buttons>>\n\n</div>\n\n</$list>\n"
        },
        "$:/core/ui/ViewTemplate/plugin": {
            "title": "$:/core/ui/ViewTemplate/plugin",
            "tags": "$:/tags/ViewTemplate",
            "text": "<$list filter=\"[all[current]has[plugin-type]] -[all[current]field:plugin-type[import]]\">\n<$set name=\"plugin-type\" value={{!!plugin-type}}>\n<$set name=\"default-popup-state\" value=\"yes\">\n<$set name=\"qualified-state\" value=<<qualify \"$:/state/plugin-info\">>>\n{{||$:/core/ui/Components/plugin-info}}\n</$set>\n</$set>\n</$set>\n</$list>\n"
        },
        "$:/core/ui/ViewTemplate/subtitle": {
            "title": "$:/core/ui/ViewTemplate/subtitle",
            "tags": "$:/tags/ViewTemplate",
            "text": "\\whitespace trim\n<$reveal type=\"nomatch\" stateTitle=<<folded-state>> text=\"hide\" tag=\"div\" retain=\"yes\" animate=\"yes\">\n<div class=\"tc-subtitle\">\n<$link to={{!!modifier}} />\n<$view field=\"modified\" format=\"date\" template={{$:/language/Tiddler/DateFormat}}/>\n</div>\n</$reveal>\n"
        },
        "$:/core/ui/ViewTemplate/tags": {
            "title": "$:/core/ui/ViewTemplate/tags",
            "tags": "$:/tags/ViewTemplate",
            "text": "<$reveal type=\"nomatch\" stateTitle=<<folded-state>> text=\"hide\" tag=\"div\" retain=\"yes\" animate=\"yes\">\n<div class=\"tc-tags-wrapper\"><$list filter=\"[all[current]tags[]sort[title]]\" template=\"$:/core/ui/TagTemplate\" storyview=\"pop\"/></div>\n</$reveal>\n"
        },
        "$:/core/ui/ViewTemplate/title": {
            "title": "$:/core/ui/ViewTemplate/title",
            "tags": "$:/tags/ViewTemplate",
            "text": "\\whitespace trim\n\\define title-styles()\nfill:$(foregroundColor)$;\n\\end\n\\define config-title()\n$:/config/ViewToolbarButtons/Visibility/$(listItem)$\n\\end\n<div class=\"tc-tiddler-title\">\n<div class=\"tc-titlebar\">\n<span class=\"tc-tiddler-controls\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]]\" variable=\"listItem\"><$reveal type=\"nomatch\" state=<<config-title>> text=\"hide\"><$set name=\"tv-config-toolbar-class\" filter=\"[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]\"><$transclude tiddler=<<listItem>>/></$set></$reveal></$list>\n</span>\n<$set name=\"tv-wikilinks\" value={{$:/config/Tiddlers/TitleLinks}}>\n<$link>\n<$set name=\"foregroundColor\" value={{!!color}}>\n<span class=\"tc-tiddler-title-icon\" style=<<title-styles>>>\n<$transclude tiddler={{!!icon}}>\n<$transclude tiddler={{$:/config/DefaultTiddlerIcon}}/>\n</$transclude>\n</span>\n</$set>\n<$list filter=\"[all[current]removeprefix[$:/]]\">\n<h2 class=\"tc-title\" title={{$:/language/SystemTiddler/Tooltip}}>\n<span class=\"tc-system-title-prefix\">$:/</span><$text text=<<currentTiddler>>/>\n</h2>\n</$list>\n<$list filter=\"[all[current]!prefix[$:/]]\">\n<h2 class=\"tc-title\">\n<$view field=\"title\"/>\n</h2>\n</$list>\n</$link>\n</$set>\n</div>\n\n<$reveal type=\"nomatch\" text=\"\" default=\"\" state=<<tiddlerInfoState>> class=\"tc-tiddler-info tc-popup-handle\" animate=\"yes\" retain=\"yes\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TiddlerInfoSegment]!has[draft.of]] [[$:/core/ui/TiddlerInfo]]\" variable=\"listItem\"><$transclude tiddler=<<listItem>> mode=\"block\"/></$list>\n\n</$reveal>\n</div>"
        },
        "$:/core/ui/ViewTemplate/unfold": {
            "title": "$:/core/ui/ViewTemplate/unfold",
            "tags": "$:/tags/ViewTemplate",
            "text": "<$reveal tag=\"div\" type=\"nomatch\" state=\"$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar\" text=\"hide\">\n<$reveal tag=\"div\" type=\"nomatch\" stateTitle=<<folded-state>> text=\"hide\" default=\"show\" retain=\"yes\" animate=\"yes\">\n<$button tooltip={{$:/language/Buttons/Fold/Hint}} aria-label={{$:/language/Buttons/Fold/Caption}} class=\"tc-fold-banner\">\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n{{$:/core/images/chevron-up}}\n</$button>\n</$reveal>\n<$reveal tag=\"div\" type=\"nomatch\" stateTitle=<<folded-state>> text=\"show\" default=\"show\" retain=\"yes\" animate=\"yes\">\n<$button tooltip={{$:/language/Buttons/Unfold/Hint}} aria-label={{$:/language/Buttons/Unfold/Caption}} class=\"tc-unfold-banner\">\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n{{$:/core/images/chevron-down}}\n</$button>\n</$reveal>\n</$reveal>\n"
        },
        "$:/core/ui/ViewTemplate": {
            "title": "$:/core/ui/ViewTemplate",
            "text": "\\define folded-state()\n$:/state/folded/$(currentTiddler)$\n\\end\n\\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]]\n<$vars storyTiddler=<<currentTiddler>> tiddlerInfoState=<<qualify \"$:/state/popup/tiddler-info\">>><div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ tc-tiddler-frame tc-tiddler-view-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[shadow]is[tiddler]then[tc-tiddler-overridden-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}}><$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]\" variable=\"listItem\"><$transclude tiddler=<<listItem>>/></$list>\n</div>\n</$vars>\n"
        },
        "$:/core/ui/Buttons/clone": {
            "title": "$:/core/ui/Buttons/clone",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/clone-button}} {{$:/language/Buttons/Clone/Caption}}",
            "description": "{{$:/language/Buttons/Clone/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-new-tiddler\" param=<<currentTiddler>> tooltip={{$:/language/Buttons/Clone/Hint}} aria-label={{$:/language/Buttons/Clone/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/clone-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Clone/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/close-others": {
            "title": "$:/core/ui/Buttons/close-others",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/close-others-button}} {{$:/language/Buttons/CloseOthers/Caption}}",
            "description": "{{$:/language/Buttons/CloseOthers/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-close-other-tiddlers\" param=<<currentTiddler>> tooltip={{$:/language/Buttons/CloseOthers/Hint}} aria-label={{$:/language/Buttons/CloseOthers/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/close-others-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/CloseOthers/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/close": {
            "title": "$:/core/ui/Buttons/close",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/close-button}} {{$:/language/Buttons/Close/Caption}}",
            "description": "{{$:/language/Buttons/Close/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-close-tiddler\" tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/close-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text={{$:/language/Buttons/Close/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/edit": {
            "title": "$:/core/ui/Buttons/edit",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/edit-button}} {{$:/language/Buttons/Edit/Caption}}",
            "description": "{{$:/language/Buttons/Edit/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-edit-tiddler\" tooltip={{$:/language/Buttons/Edit/Hint}} aria-label={{$:/language/Buttons/Edit/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/edit-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Edit/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/export-tiddler": {
            "title": "$:/core/ui/Buttons/export-tiddler",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/export-button}} {{$:/language/Buttons/ExportTiddler/Caption}}",
            "description": "{{$:/language/Buttons/ExportTiddler/Hint}}",
            "text": "\\define makeExportFilter()\n[[$(currentTiddler)$]]\n\\end\n<$macrocall $name=\"exportButton\" exportFilter=<<makeExportFilter>> lingoBase=\"$:/language/Buttons/ExportTiddler/\" baseFilename=<<currentTiddler>>/>"
        },
        "$:/core/ui/Buttons/fold-bar": {
            "title": "$:/core/ui/Buttons/fold-bar",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/chevron-up}} {{$:/language/Buttons/Fold/FoldBar/Caption}}",
            "description": "{{$:/language/Buttons/Fold/FoldBar/Hint}}",
            "text": "<!-- This dummy toolbar button is here to allow visibility of the fold-bar to be controlled as if it were a toolbar button -->"
        },
        "$:/core/ui/Buttons/fold-others": {
            "title": "$:/core/ui/Buttons/fold-others",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/fold-others-button}} {{$:/language/Buttons/FoldOthers/Caption}}",
            "description": "{{$:/language/Buttons/FoldOthers/Hint}}",
            "text": "\\whitespace trim\n<$button tooltip={{$:/language/Buttons/FoldOthers/Hint}} aria-label={{$:/language/Buttons/FoldOthers/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-other-tiddlers\" $param=<<currentTiddler>> foldedStatePrefix=\"$:/state/folded/\"/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\" variable=\"listItem\">\n{{$:/core/images/fold-others-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/FoldOthers/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/fold": {
            "title": "$:/core/ui/Buttons/fold",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/fold-button}} {{$:/language/Buttons/Fold/Caption}}",
            "description": "{{$:/language/Buttons/Fold/Hint}}",
            "text": "\\whitespace trim\n<$reveal type=\"nomatch\" stateTitle=<<folded-state>> text=\"hide\" default=\"show\">\n<$button tooltip={{$:/language/Buttons/Fold/Hint}} aria-label={{$:/language/Buttons/Fold/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\" variable=\"listItem\">\n{{$:/core/images/fold-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Fold/Caption}}/>\n</span>\n</$list>\n</$button>\n</$reveal>\n<$reveal type=\"match\" stateTitle=<<folded-state>> text=\"hide\" default=\"show\">\n<$button tooltip={{$:/language/Buttons/Unfold/Hint}} aria-label={{$:/language/Buttons/Unfold/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\" variable=\"listItem\">\n{{$:/core/images/unfold-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Unfold/Caption}}/>\n</span>\n</$list>\n</$button>\n</$reveal>\n"
        },
        "$:/core/ui/Buttons/info": {
            "title": "$:/core/ui/Buttons/info",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/info-button}} {{$:/language/Buttons/Info/Caption}}",
            "description": "{{$:/language/Buttons/Info/Hint}}",
            "text": "\\whitespace trim\n\\define button-content()\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/info-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text={{$:/language/Buttons/Info/Caption}}/>\n</span>\n</$list>\n\\end\n<$reveal state=\"$:/config/TiddlerInfo/Mode\" type=\"match\" text=\"popup\">\n<$button popup=<<tiddlerInfoState>> tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$macrocall $name=\"button-content\" mode=\"inline\"/>\n</$button>\n</$reveal>\n<$reveal state=\"$:/config/TiddlerInfo/Mode\" type=\"match\" text=\"sticky\">\n<$reveal state=<<tiddlerInfoState>> type=\"match\" text=\"\" default=\"\">\n<$button set=<<tiddlerInfoState>> setTo=\"yes\" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$macrocall $name=\"button-content\" mode=\"inline\"/>\n</$button>\n</$reveal>\n<$reveal state=<<tiddlerInfoState>> type=\"nomatch\" text=\"\" default=\"\">\n<$button set=<<tiddlerInfoState>> setTo=\"\" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$macrocall $name=\"button-content\" mode=\"inline\"/>\n</$button>\n</$reveal>\n</$reveal>"
        },
        "$:/core/ui/Buttons/more-tiddler-actions": {
            "title": "$:/core/ui/Buttons/more-tiddler-actions",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/down-arrow}} {{$:/language/Buttons/More/Caption}}",
            "description": "{{$:/language/Buttons/More/Hint}}",
            "text": "\\whitespace trim\n\\define config-title()\n$:/config/ViewToolbarButtons/Visibility/$(listItem)$\n\\end\n<$button popup=<<qualify \"$:/state/popup/more\">> tooltip={{$:/language/Buttons/More/Hint}} aria-label={{$:/language/Buttons/More/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/down-arrow}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/More/Caption}}/>\n</span>\n</$list>\n</$button>\n<$reveal state=<<qualify \"$:/state/popup/more\">> type=\"popup\" position=\"belowleft\" animate=\"yes\">\n\n<div class=\"tc-drop-down\">\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"tc-btn-invisible\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]] -[[$:/core/ui/Buttons/more-tiddler-actions]]\" variable=\"listItem\">\n\n<$reveal type=\"match\" state=<<config-title>> text=\"hide\">\n\n<$set name=\"tv-config-toolbar-class\" filter=\"[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$set>\n\n</$reveal>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</div>\n\n</$reveal>"
        },
        "$:/core/ui/Buttons/new-here": {
            "title": "$:/core/ui/Buttons/new-here",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/new-here-button}} {{$:/language/Buttons/NewHere/Caption}}",
            "description": "{{$:/language/Buttons/NewHere/Hint}}",
            "text": "\\whitespace trim\n\\define newHereActions()\n<$set name=\"tags\" filter=\"[<currentTiddler>] [{$:/config/NewTiddler/Tags!!tags}]\">\n<$action-sendmessage $message=\"tm-new-tiddler\" tags=<<tags>>/>\n</$set>\n\\end\n\\define newHereButton()\n<$button actions=<<newHereActions>> tooltip={{$:/language/Buttons/NewHere/Hint}} aria-label={{$:/language/Buttons/NewHere/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/new-here-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text={{$:/language/Buttons/NewHere/Caption}}/>\n</span>\n</$list>\n</$button>\n\\end\n<<newHereButton>>\n"
        },
        "$:/core/ui/Buttons/new-journal-here": {
            "title": "$:/core/ui/Buttons/new-journal-here",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/new-journal-button}} {{$:/language/Buttons/NewJournalHere/Caption}}",
            "description": "{{$:/language/Buttons/NewJournalHere/Hint}}",
            "text": "\\whitespace trim\n\\define journalButtonTags()\n[[$(currentTiddlerTag)$]] $(journalTags)$\n\\end\n\\define journalButton()\n<$button tooltip={{$:/language/Buttons/NewJournalHere/Hint}} aria-label={{$:/language/Buttons/NewJournalHere/Caption}} class=<<tv-config-toolbar-class>>>\n<$wikify name=\"journalTitle\" text=\"\"\"<$macrocall $name=\"now\" format=<<journalTitleTemplate>>/>\"\"\">\n<$action-sendmessage $message=\"tm-new-tiddler\" title=<<journalTitle>> tags=<<journalButtonTags>>/>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/new-journal-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text={{$:/language/Buttons/NewJournalHere/Caption}}/>\n</span>\n</$list>\n</$wikify>\n</$button>\n\\end\n<$set name=\"journalTitleTemplate\" value={{$:/config/NewJournal/Title}}>\n<$set name=\"journalTags\" value={{$:/config/NewJournal/Tags!!tags}}>\n<$set name=\"currentTiddlerTag\" value=<<currentTiddler>>>\n<<journalButton>>\n</$set>\n</$set>\n</$set>\n"
        },
        "$:/core/ui/Buttons/open-window": {
            "title": "$:/core/ui/Buttons/open-window",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/open-window}} {{$:/language/Buttons/OpenWindow/Caption}}",
            "description": "{{$:/language/Buttons/OpenWindow/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-open-window\" tooltip={{$:/language/Buttons/OpenWindow/Hint}} aria-label={{$:/language/Buttons/OpenWindow/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/open-window}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/OpenWindow/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/permalink": {
            "title": "$:/core/ui/Buttons/permalink",
            "tags": "$:/tags/ViewToolbar",
            "caption": "{{$:/core/images/permalink-button}} {{$:/language/Buttons/Permalink/Caption}}",
            "description": "{{$:/language/Buttons/Permalink/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-permalink\" tooltip={{$:/language/Buttons/Permalink/Hint}} aria-label={{$:/language/Buttons/Permalink/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/permalink-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Permalink/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/core/ui/Buttons/permaview": {
            "title": "$:/core/ui/Buttons/permaview",
            "tags": "$:/tags/ViewToolbar $:/tags/PageControls",
            "caption": "{{$:/core/images/permaview-button}} {{$:/language/Buttons/Permaview/Caption}}",
            "description": "{{$:/language/Buttons/Permaview/Hint}}",
            "text": "\\whitespace trim\n<$button message=\"tm-permaview\" tooltip={{$:/language/Buttons/Permaview/Hint}} aria-label={{$:/language/Buttons/Permaview/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/permaview-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text=\" \"/>\n<$text text={{$:/language/Buttons/Permaview/Caption}}/>\n</span>\n</$list>\n</$button>"
        },
        "$:/DefaultTiddlers": {
            "title": "$:/DefaultTiddlers",
            "text": "GettingStarted\n"
        },
        "$:/temp/advancedsearch": {
            "title": "$:/temp/advancedsearch",
            "text": ""
        },
        "$:/snippets/allfields": {
            "title": "$:/snippets/allfields",
            "text": "\\define renderfield(title)\n<tr class=\"tc-view-field\"><td class=\"tc-view-field-name\">''$title$'':</td><td class=\"tc-view-field-value\">//{{$:/language/Docs/Fields/$title$}}//</td></tr>\n\\end\n<table class=\"tc-view-field-table\"><tbody><$list filter=\"[fields[]sort[title]]\" variable=\"listItem\"><$macrocall $name=\"renderfield\" title=<<listItem>>/></$list>\n</tbody></table>\n"
        },
        "$:/config/AnimationDuration": {
            "title": "$:/config/AnimationDuration",
            "text": "400"
        },
        "$:/config/AutoFocus": {
            "title": "$:/config/AutoFocus",
            "text": "title"
        },
        "$:/config/AutoSave": {
            "title": "$:/config/AutoSave",
            "text": "yes"
        },
        "$:/config/BitmapEditor/Colour": {
            "title": "$:/config/BitmapEditor/Colour",
            "text": "#444"
        },
        "$:/config/BitmapEditor/ImageSizes": {
            "title": "$:/config/BitmapEditor/ImageSizes",
            "text": "[[62px 100px]] [[100px 62px]] [[124px 200px]] [[200px 124px]] [[248px 400px]] [[371px 600px]] [[400px 248px]] [[556px 900px]] [[600px 371px]] [[742px 1200px]] [[900px 556px]] [[1200px 742px]]"
        },
        "$:/config/BitmapEditor/LineWidth": {
            "title": "$:/config/BitmapEditor/LineWidth",
            "text": "3px"
        },
        "$:/config/BitmapEditor/LineWidths": {
            "title": "$:/config/BitmapEditor/LineWidths",
            "text": "0.25px 0.5px 1px 2px 3px 4px 6px 8px 10px 16px 20px 28px 40px 56px 80px"
        },
        "$:/config/BitmapEditor/Opacities": {
            "title": "$:/config/BitmapEditor/Opacities",
            "text": "0.01 0.025 0.05 0.075 0.1 0.15 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0"
        },
        "$:/config/BitmapEditor/Opacity": {
            "title": "$:/config/BitmapEditor/Opacity",
            "text": "1.0"
        },
        "$:/config/DefaultMoreSidebarTab": {
            "title": "$:/config/DefaultMoreSidebarTab",
            "text": "$:/core/ui/MoreSideBar/Tags"
        },
        "$:/config/DefaultSidebarTab": {
            "title": "$:/config/DefaultSidebarTab",
            "text": "$:/core/ui/SideBar/Open"
        },
        "$:/config/DownloadSaver/AutoSave": {
            "title": "$:/config/DownloadSaver/AutoSave",
            "text": "no"
        },
        "$:/config/Drafts/TypingTimeout": {
            "title": "$:/config/Drafts/TypingTimeout",
            "text": "400"
        },
        "$:/config/EditTemplateFields/Visibility/title": {
            "title": "$:/config/EditTemplateFields/Visibility/title",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/tags": {
            "title": "$:/config/EditTemplateFields/Visibility/tags",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/text": {
            "title": "$:/config/EditTemplateFields/Visibility/text",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/creator": {
            "title": "$:/config/EditTemplateFields/Visibility/creator",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/created": {
            "title": "$:/config/EditTemplateFields/Visibility/created",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/modified": {
            "title": "$:/config/EditTemplateFields/Visibility/modified",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/modifier": {
            "title": "$:/config/EditTemplateFields/Visibility/modifier",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/type": {
            "title": "$:/config/EditTemplateFields/Visibility/type",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/draft.title": {
            "title": "$:/config/EditTemplateFields/Visibility/draft.title",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/draft.of": {
            "title": "$:/config/EditTemplateFields/Visibility/draft.of",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/revision": {
            "title": "$:/config/EditTemplateFields/Visibility/revision",
            "text": "hide"
        },
        "$:/config/EditTemplateFields/Visibility/bag": {
            "title": "$:/config/EditTemplateFields/Visibility/bag",
            "text": "hide"
        },
        "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-4": {
            "title": "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-4",
            "text": "hide"
        },
        "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-5": {
            "title": "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-5",
            "text": "hide"
        },
        "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-6": {
            "title": "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-6",
            "text": "hide"
        },
        "$:/config/EditorTypeMappings/image/gif": {
            "title": "$:/config/EditorTypeMappings/image/gif",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/webp": {
            "title": "$:/config/EditorTypeMappings/image/webp",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/heic": {
            "title": "$:/config/EditorTypeMappings/image/heic",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/heif": {
            "title": "$:/config/EditorTypeMappings/image/heif",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/jpeg": {
            "title": "$:/config/EditorTypeMappings/image/jpeg",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/jpg": {
            "title": "$:/config/EditorTypeMappings/image/jpg",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/png": {
            "title": "$:/config/EditorTypeMappings/image/png",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/image/x-icon": {
            "title": "$:/config/EditorTypeMappings/image/x-icon",
            "text": "bitmap"
        },
        "$:/config/EditorTypeMappings/text/vnd.tiddlywiki": {
            "title": "$:/config/EditorTypeMappings/text/vnd.tiddlywiki",
            "text": "text"
        },
        "$:/config/Manager/Show": {
            "title": "$:/config/Manager/Show",
            "text": "tiddlers"
        },
        "$:/config/Manager/Filter": {
            "title": "$:/config/Manager/Filter",
            "text": ""
        },
        "$:/config/Manager/Order": {
            "title": "$:/config/Manager/Order",
            "text": "forward"
        },
        "$:/config/Manager/Sort": {
            "title": "$:/config/Manager/Sort",
            "text": "title"
        },
        "$:/config/Manager/System": {
            "title": "$:/config/Manager/System",
            "text": "system"
        },
        "$:/config/Manager/Tag": {
            "title": "$:/config/Manager/Tag",
            "text": ""
        },
        "$:/state/popup/manager/item/$:/Manager/ItemMain/RawText": {
            "title": "$:/state/popup/manager/item/$:/Manager/ItemMain/RawText",
            "text": "hide"
        },
        "$:/config/MissingLinks": {
            "title": "$:/config/MissingLinks",
            "text": "yes"
        },
        "$:/config/Navigation/UpdateAddressBar": {
            "title": "$:/config/Navigation/UpdateAddressBar",
            "text": "no"
        },
        "$:/config/Navigation/UpdateHistory": {
            "title": "$:/config/Navigation/UpdateHistory",
            "text": "no"
        },
        "$:/config/NewImageType": {
            "title": "$:/config/NewImageType",
            "text": "jpeg"
        },
        "$:/config/OfficialPluginLibrary": {
            "title": "$:/config/OfficialPluginLibrary",
            "tags": "$:/tags/PluginLibrary",
            "url": "https://tiddlywiki.com/library/v5.1.22/index.html",
            "caption": "{{$:/language/OfficialPluginLibrary}}",
            "text": "{{$:/language/OfficialPluginLibrary/Hint}}\n"
        },
        "$:/config/Navigation/openLinkFromInsideRiver": {
            "title": "$:/config/Navigation/openLinkFromInsideRiver",
            "text": "below"
        },
        "$:/config/Navigation/openLinkFromOutsideRiver": {
            "title": "$:/config/Navigation/openLinkFromOutsideRiver",
            "text": "top"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/advanced-search": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/advanced-search",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/close-all": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/close-all",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/encryption": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/encryption",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/export-page": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/export-page",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/fold-all": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/fold-all",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/full-screen": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/full-screen",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/refresh": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/refresh",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/import": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/import",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/language": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/language",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/tag-manager": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/tag-manager",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/manager": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/manager",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/more-page-actions": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/more-page-actions",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-journal": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-journal",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-image": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-image",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/palette": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/palette",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/permaview": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/permaview",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/print": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/print",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/storyview": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/storyview",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/timestamp": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/timestamp",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/theme": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/theme",
            "text": "hide"
        },
        "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/unfold-all": {
            "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/unfold-all",
            "text": "hide"
        },
        "$:/config/Performance/Instrumentation": {
            "title": "$:/config/Performance/Instrumentation",
            "text": "no"
        },
        "$:/config/RegisterPluginType/plugin": {
            "title": "$:/config/RegisterPluginType/plugin",
            "text": "yes"
        },
        "$:/config/RegisterPluginType/theme": {
            "title": "$:/config/RegisterPluginType/theme",
            "text": "no"
        },
        "$:/config/RegisterPluginType/language": {
            "title": "$:/config/RegisterPluginType/language",
            "text": "no"
        },
        "$:/config/RegisterPluginType/info": {
            "title": "$:/config/RegisterPluginType/info",
            "text": "no"
        },
        "$:/config/RegisterPluginType/import": {
            "title": "$:/config/RegisterPluginType/import",
            "text": "no"
        },
        "$:/config/SaveWikiButton/Template": {
            "title": "$:/config/SaveWikiButton/Template",
            "text": "$:/core/save/all"
        },
        "$:/config/SaverFilter": {
            "title": "$:/config/SaverFilter",
            "text": "[all[]] -[[$:/HistoryList]] -[[$:/StoryList]] -[[$:/Import]] -[[$:/isEncrypted]] -[[$:/UploadName]] -[prefix[$:/state/]] -[prefix[$:/temp/]]"
        },
        "$:/config/Search/AutoFocus": {
            "title": "$:/config/Search/AutoFocus",
            "text": "true"
        },
        "$:/config/Search/MinLength": {
            "title": "$:/config/Search/MinLength",
            "text": "3"
        },
        "$:/config/SearchResults/Default": {
            "title": "$:/config/SearchResults/Default",
            "text": "$:/core/ui/DefaultSearchResultList"
        },
        "$:/config/Server/ExternalFilters/[all[tiddlers]!is[system]sort[title]]": {
            "title": "$:/config/Server/ExternalFilters/[all[tiddlers]!is[system]sort[title]]",
            "text": "yes"
        },
        "$:/config/ShortcutInfo/add-field": {
            "title": "$:/config/ShortcutInfo/add-field",
            "text": "{{$:/language/EditTemplate/Fields/Add/Button/Hint}}"
        },
        "$:/config/ShortcutInfo/advanced-search": {
            "title": "$:/config/ShortcutInfo/advanced-search",
            "text": "{{$:/language/Buttons/AdvancedSearch/Hint}}"
        },
        "$:/config/ShortcutInfo/bold": {
            "title": "$:/config/ShortcutInfo/bold",
            "text": "{{$:/language/Buttons/Bold/Hint}}"
        },
        "$:/config/ShortcutInfo/cancel-edit-tiddler": {
            "title": "$:/config/ShortcutInfo/cancel-edit-tiddler",
            "text": "{{$:/language/Buttons/Cancel/Hint}}"
        },
        "$:/config/ShortcutInfo/excise": {
            "title": "$:/config/ShortcutInfo/excise",
            "text": "{{$:/language/Buttons/Excise/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-1": {
            "title": "$:/config/ShortcutInfo/heading-1",
            "text": "{{$:/language/Buttons/Heading1/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-2": {
            "title": "$:/config/ShortcutInfo/heading-2",
            "text": "{{$:/language/Buttons/Heading2/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-3": {
            "title": "$:/config/ShortcutInfo/heading-3",
            "text": "{{$:/language/Buttons/Heading3/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-4": {
            "title": "$:/config/ShortcutInfo/heading-4",
            "text": "{{$:/language/Buttons/Heading4/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-5": {
            "title": "$:/config/ShortcutInfo/heading-5",
            "text": "{{$:/language/Buttons/Heading5/Hint}}"
        },
        "$:/config/ShortcutInfo/heading-6": {
            "title": "$:/config/ShortcutInfo/heading-6",
            "text": "{{$:/language/Buttons/Heading6/Hint}}"
        },
        "$:/config/ShortcutInfo/italic": {
            "title": "$:/config/ShortcutInfo/italic",
            "text": "{{$:/language/Buttons/Italic/Hint}}"
        },
        "$:/config/ShortcutInfo/link": {
            "title": "$:/config/ShortcutInfo/link",
            "text": "{{$:/language/Buttons/Link/Hint}}"
        },
        "$:/config/ShortcutInfo/list-bullet": {
            "title": "$:/config/ShortcutInfo/list-bullet",
            "text": "{{$:/language/Buttons/ListBullet/Hint}}"
        },
        "$:/config/ShortcutInfo/list-number": {
            "title": "$:/config/ShortcutInfo/list-number",
            "text": "{{$:/language/Buttons/ListNumber/Hint}}"
        },
        "$:/config/ShortcutInfo/mono-block": {
            "title": "$:/config/ShortcutInfo/mono-block",
            "text": "{{$:/language/Buttons/MonoBlock/Hint}}"
        },
        "$:/config/ShortcutInfo/mono-line": {
            "title": "$:/config/ShortcutInfo/mono-line",
            "text": "{{$:/language/Buttons/MonoLine/Hint}}"
        },
        "$:/config/ShortcutInfo/new-image": {
            "title": "$:/config/ShortcutInfo/new-image",
            "text": "{{$:/language/Buttons/NewImage/Hint}}"
        },
        "$:/config/ShortcutInfo/new-journal": {
            "title": "$:/config/ShortcutInfo/new-journal",
            "text": "{{$:/language/Buttons/NewJournal/Hint}}"
        },
        "$:/config/ShortcutInfo/new-tiddler": {
            "title": "$:/config/ShortcutInfo/new-tiddler",
            "text": "{{$:/language/Buttons/NewTiddler/Hint}}"
        },
        "$:/config/ShortcutInfo/picture": {
            "title": "$:/config/ShortcutInfo/picture",
            "text": "{{$:/language/Buttons/Picture/Hint}}"
        },
        "$:/config/ShortcutInfo/preview": {
            "title": "$:/config/ShortcutInfo/preview",
            "text": "{{$:/language/Buttons/Preview/Hint}}"
        },
        "$:/config/ShortcutInfo/quote": {
            "title": "$:/config/ShortcutInfo/quote",
            "text": "{{$:/language/Buttons/Quote/Hint}}"
        },
        "$:/config/ShortcutInfo/save-tiddler": {
            "title": "$:/config/ShortcutInfo/save-tiddler",
            "text": "{{$:/language/Buttons/Save/Hint}}"
        },
        "$:/config/ShortcutInfo/sidebar-search": {
            "title": "$:/config/ShortcutInfo/sidebar-search",
            "text": "{{$:/language/Buttons/SidebarSearch/Hint}}"
        },
        "$:/config/ShortcutInfo/stamp": {
            "title": "$:/config/ShortcutInfo/stamp",
            "text": "{{$:/language/Buttons/Stamp/Hint}}"
        },
        "$:/config/ShortcutInfo/strikethrough": {
            "title": "$:/config/ShortcutInfo/strikethrough",
            "text": "{{$:/language/Buttons/Strikethrough/Hint}}"
        },
        "$:/config/ShortcutInfo/subscript": {
            "title": "$:/config/ShortcutInfo/subscript",
            "text": "{{$:/language/Buttons/Subscript/Hint}}"
        },
        "$:/config/ShortcutInfo/superscript": {
            "title": "$:/config/ShortcutInfo/superscript",
            "text": "{{$:/language/Buttons/Superscript/Hint}}"
        },
        "$:/config/ShortcutInfo/toggle-sidebar": {
            "title": "$:/config/ShortcutInfo/toggle-sidebar",
            "text": "{{$:/language/Buttons/ToggleSidebar/Hint}}"
        },
        "$:/config/ShortcutInfo/underline": {
            "title": "$:/config/ShortcutInfo/underline",
            "text": "{{$:/language/Buttons/Underline/Hint}}"
        },
        "$:/config/SyncFilter": {
            "title": "$:/config/SyncFilter",
            "text": "[is[tiddler]] -[[$:/HistoryList]] -[[$:/Import]] -[[$:/isEncrypted]] -[prefix[$:/status/]] -[prefix[$:/state/]] -[prefix[$:/temp/]]"
        },
        "$:/config/Tags/MinLength": {
            "title": "$:/config/Tags/MinLength",
            "text": "0"
        },
        "$:/config/TextEditor/EditorHeight/Height": {
            "title": "$:/config/TextEditor/EditorHeight/Height",
            "text": "400px"
        },
        "$:/config/TextEditor/EditorHeight/Mode": {
            "title": "$:/config/TextEditor/EditorHeight/Mode",
            "text": "auto"
        },
        "$:/config/TiddlerInfo/Default": {
            "title": "$:/config/TiddlerInfo/Default",
            "text": "$:/core/ui/TiddlerInfo/Fields"
        },
        "$:/config/TiddlerInfo/Mode": {
            "title": "$:/config/TiddlerInfo/Mode",
            "text": "popup"
        },
        "$:/config/Tiddlers/TitleLinks": {
            "title": "$:/config/Tiddlers/TitleLinks",
            "text": "no"
        },
        "$:/config/Toolbar/ButtonClass": {
            "title": "$:/config/Toolbar/ButtonClass",
            "text": "tc-btn-invisible"
        },
        "$:/config/Toolbar/Icons": {
            "title": "$:/config/Toolbar/Icons",
            "text": "yes"
        },
        "$:/config/Toolbar/Text": {
            "title": "$:/config/Toolbar/Text",
            "text": "no"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/clone": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/clone",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/close-others": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/close-others",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/export-tiddler": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/export-tiddler",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/info": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/info",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/more-tiddler-actions": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/more-tiddler-actions",
            "text": "show"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-here": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-here",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-journal-here": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-journal-here",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/open-window": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/open-window",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permalink": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permalink",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permaview": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permaview",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/delete": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/delete",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar",
            "text": "hide"
        },
        "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-others": {
            "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-others",
            "text": "hide"
        },
        "$:/config/shortcuts-mac/bold": {
            "title": "$:/config/shortcuts-mac/bold",
            "text": "meta-B"
        },
        "$:/config/shortcuts-mac/italic": {
            "title": "$:/config/shortcuts-mac/italic",
            "text": "meta-I"
        },
        "$:/config/shortcuts-mac/underline": {
            "title": "$:/config/shortcuts-mac/underline",
            "text": "meta-U"
        },
        "$:/config/shortcuts-mac/new-image": {
            "title": "$:/config/shortcuts-mac/new-image",
            "text": "ctrl-I"
        },
        "$:/config/shortcuts-mac/new-journal": {
            "title": "$:/config/shortcuts-mac/new-journal",
            "text": "ctrl-J"
        },
        "$:/config/shortcuts-mac/new-tiddler": {
            "title": "$:/config/shortcuts-mac/new-tiddler",
            "text": "ctrl-N"
        },
        "$:/config/shortcuts-not-mac/bold": {
            "title": "$:/config/shortcuts-not-mac/bold",
            "text": "ctrl-B"
        },
        "$:/config/shortcuts-not-mac/italic": {
            "title": "$:/config/shortcuts-not-mac/italic",
            "text": "ctrl-I"
        },
        "$:/config/shortcuts-not-mac/underline": {
            "title": "$:/config/shortcuts-not-mac/underline",
            "text": "ctrl-U"
        },
        "$:/config/shortcuts-not-mac/new-image": {
            "title": "$:/config/shortcuts-not-mac/new-image",
            "text": "alt-I"
        },
        "$:/config/shortcuts-not-mac/new-journal": {
            "title": "$:/config/shortcuts-not-mac/new-journal",
            "text": "alt-J"
        },
        "$:/config/shortcuts-not-mac/new-tiddler": {
            "title": "$:/config/shortcuts-not-mac/new-tiddler",
            "text": "alt-N"
        },
        "$:/config/shortcuts/add-field": {
            "title": "$:/config/shortcuts/add-field",
            "text": "enter"
        },
        "$:/config/shortcuts/advanced-search": {
            "title": "$:/config/shortcuts/advanced-search",
            "text": "ctrl-shift-A"
        },
        "$:/config/shortcuts/cancel-edit-tiddler": {
            "title": "$:/config/shortcuts/cancel-edit-tiddler",
            "text": "escape"
        },
        "$:/config/shortcuts/excise": {
            "title": "$:/config/shortcuts/excise",
            "text": "ctrl-E"
        },
        "$:/config/shortcuts/sidebar-search": {
            "title": "$:/config/shortcuts/sidebar-search",
            "text": "ctrl-shift-F"
        },
        "$:/config/shortcuts/heading-1": {
            "title": "$:/config/shortcuts/heading-1",
            "text": "ctrl-1"
        },
        "$:/config/shortcuts/heading-2": {
            "title": "$:/config/shortcuts/heading-2",
            "text": "ctrl-2"
        },
        "$:/config/shortcuts/heading-3": {
            "title": "$:/config/shortcuts/heading-3",
            "text": "ctrl-3"
        },
        "$:/config/shortcuts/heading-4": {
            "title": "$:/config/shortcuts/heading-4",
            "text": "ctrl-4"
        },
        "$:/config/shortcuts/heading-5": {
            "title": "$:/config/shortcuts/heading-5",
            "text": "ctrl-5"
        },
        "$:/config/shortcuts/heading-6": {
            "title": "$:/config/shortcuts/heading-6",
            "text": "ctrl-6"
        },
        "$:/config/shortcuts/link": {
            "title": "$:/config/shortcuts/link",
            "text": "ctrl-L"
        },
        "$:/config/shortcuts/linkify": {
            "title": "$:/config/shortcuts/linkify",
            "text": "alt-shift-L"
        },
        "$:/config/shortcuts/list-bullet": {
            "title": "$:/config/shortcuts/list-bullet",
            "text": "ctrl-shift-L"
        },
        "$:/config/shortcuts/list-number": {
            "title": "$:/config/shortcuts/list-number",
            "text": "ctrl-shift-N"
        },
        "$:/config/shortcuts/mono-block": {
            "title": "$:/config/shortcuts/mono-block",
            "text": "ctrl-shift-M"
        },
        "$:/config/shortcuts/mono-line": {
            "title": "$:/config/shortcuts/mono-line",
            "text": "ctrl-M"
        },
        "$:/config/shortcuts/picture": {
            "title": "$:/config/shortcuts/picture",
            "text": "ctrl-shift-I"
        },
        "$:/config/shortcuts/preview": {
            "title": "$:/config/shortcuts/preview",
            "text": "alt-P"
        },
        "$:/config/shortcuts/quote": {
            "title": "$:/config/shortcuts/quote",
            "text": "ctrl-Q"
        },
        "$:/config/shortcuts/save-tiddler": {
            "title": "$:/config/shortcuts/save-tiddler",
            "text": "ctrl+enter"
        },
        "$:/config/shortcuts/stamp": {
            "title": "$:/config/shortcuts/stamp",
            "text": "ctrl-S"
        },
        "$:/config/shortcuts/strikethrough": {
            "title": "$:/config/shortcuts/strikethrough",
            "text": "ctrl-T"
        },
        "$:/config/shortcuts/subscript": {
            "title": "$:/config/shortcuts/subscript",
            "text": "ctrl-shift-B"
        },
        "$:/config/shortcuts/superscript": {
            "title": "$:/config/shortcuts/superscript",
            "text": "ctrl-shift-P"
        },
        "$:/config/shortcuts/toggle-sidebar": {
            "title": "$:/config/shortcuts/toggle-sidebar",
            "text": "alt-shift-S"
        },
        "$:/config/shortcuts/transcludify": {
            "title": "$:/config/shortcuts/transcludify",
            "text": "alt-shift-T"
        },
        "$:/config/ui/EditTemplate": {
            "title": "$:/config/ui/EditTemplate",
            "text": "$:/core/ui/EditTemplate"
        },
        "$:/config/ui/ViewTemplate": {
            "title": "$:/config/ui/ViewTemplate",
            "text": "$:/core/ui/ViewTemplate"
        },
        "$:/config/WikiParserRules/Inline/wikilink": {
            "title": "$:/config/WikiParserRules/Inline/wikilink",
            "text": "enable"
        },
        "$:/snippets/currpalettepreview": {
            "title": "$:/snippets/currpalettepreview",
            "text": "\\define swatchStyle()\nbackground-color: $(swatchColour)$;\n\\end\n\\define swatch()\n<$set name=\"swatchColour\" value={{##$(colour)$}}\n><div class=\"tc-swatch\" style=<<swatchStyle>> title=<<colour>>/></$set>\n\\end\n<div class=\"tc-swatches-horiz\"><$list filter=\"\nforeground\nbackground\nmuted-foreground\nprimary\npage-background\ntab-background\ntiddler-info-background\n\" variable=\"colour\"><<swatch>></$list></div>"
        },
        "$:/snippets/download-wiki-button": {
            "title": "$:/snippets/download-wiki-button",
            "text": "\\define lingo-base() $:/language/ControlPanel/Tools/Download/\n<$button class=\"tc-btn-big-green\">\n<$action-sendmessage $message=\"tm-download-file\" $param=\"$:/core/save/all\" filename=\"index.html\"/>\n<<lingo Full/Caption>> {{$:/core/images/save-button}}\n</$button>"
        },
        "$:/language": {
            "title": "$:/language",
            "text": "$:/languages/en-GB"
        },
        "$:/snippets/languageswitcher": {
            "title": "$:/snippets/languageswitcher",
            "text": "\\define flag-title()\n$(languagePluginTitle)$/icon\n\\end\n\n<$linkcatcher to=\"$:/language\">\n<div class=\"tc-chooser tc-language-chooser\">\n<$list filter=\"[[$:/languages/en-GB]] [plugin-type[language]sort[description]]\">\n<$set name=\"cls\" filter=\"[all[current]field:title{$:/language}]\" value=\"tc-chooser-item tc-chosen\" emptyValue=\"tc-chooser-item\"><div class=<<cls>>>\n<$link>\n<span class=\"tc-image-button\">\n<$set name=\"languagePluginTitle\" value=<<currentTiddler>>>\n<$transclude subtiddler=<<flag-title>>>\n<$list filter=\"[all[current]field:title[$:/languages/en-GB]]\">\n<$transclude tiddler=\"$:/languages/en-GB/icon\"/>\n</$list>\n</$transclude>\n</$set>\n</span>\n<$view field=\"description\">\n<$view field=\"name\">\n<$view field=\"title\"/>\n</$view>\n</$view>\n</$link>\n</div>\n</$set>\n</$list>\n</div>\n</$linkcatcher>"
        },
        "$:/core/macros/CSS": {
            "title": "$:/core/macros/CSS",
            "tags": "$:/tags/Macro",
            "text": "\\define colour(name)\n<$transclude tiddler={{$:/palette}} index=\"$name$\"><$transclude tiddler=\"$:/palettes/Vanilla\" index=\"$name$\"><$transclude tiddler=\"$:/config/DefaultColourMappings/$name$\"/></$transclude></$transclude>\n\\end\n\n\\define color(name)\n<<colour $name$>>\n\\end\n\n\\define box-shadow(shadow)\n``\n  -webkit-box-shadow: $shadow$;\n     -moz-box-shadow: $shadow$;\n          box-shadow: $shadow$;\n``\n\\end\n\n\\define filter(filter)\n``\n  -webkit-filter: $filter$;\n     -moz-filter: $filter$;\n          filter: $filter$;\n``\n\\end\n\n\\define transition(transition)\n``\n  -webkit-transition: $transition$;\n     -moz-transition: $transition$;\n          transition: $transition$;\n``\n\\end\n\n\\define transform-origin(origin)\n``\n  -webkit-transform-origin: $origin$;\n     -moz-transform-origin: $origin$;\n          transform-origin: $origin$;\n``\n\\end\n\n\\define background-linear-gradient(gradient)\n``\nbackground-image: linear-gradient($gradient$);\nbackground-image: -o-linear-gradient($gradient$);\nbackground-image: -moz-linear-gradient($gradient$);\nbackground-image: -webkit-linear-gradient($gradient$);\nbackground-image: -ms-linear-gradient($gradient$);\n``\n\\end\n\n\\define column-count(columns)\n``\n-moz-column-count: $columns$;\n-webkit-column-count: $columns$;\ncolumn-count: $columns$;\n``\n\\end\n\n\\define datauri(title)\n<$macrocall $name=\"makedatauri\" type={{$title$!!type}} text={{$title$}} _canonical_uri={{$title$!!_canonical_uri}}/>\n\\end\n\n\\define if-sidebar(text)\n<$reveal state=\"$:/state/sidebar\" type=\"match\" text=\"yes\" default=\"yes\">$text$</$reveal>\n\\end\n\n\\define if-no-sidebar(text)\n<$reveal state=\"$:/state/sidebar\" type=\"nomatch\" text=\"yes\" default=\"yes\">$text$</$reveal>\n\\end\n\n\\define if-background-attachment(text)\n<$reveal state=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\" type=\"nomatch\" text=\"\">$text$</$reveal>\n\\end\n"
        },
        "$:/core/macros/colour-picker": {
            "title": "$:/core/macros/colour-picker",
            "tags": "$:/tags/Macro",
            "text": "\\define colour-picker-update-recent()\n<$action-listops\n\t$tiddler=\"$:/config/ColourPicker/Recent\"\n\t$subfilter=\"$(colour-picker-value)$ [list[$:/config/ColourPicker/Recent]remove[$(colour-picker-value)$]] +[limit[8]]\"\n/>\n\\end\n\n\\define colour-picker-inner(actions)\n<$button tag=\"a\" tooltip=\"\"\"$(colour-picker-value)$\"\"\">\n\n$(colour-picker-update-recent)$\n\n$actions$\n\n<span style=\"display:inline-block; background-color: $(colour-picker-value)$; width: 100%; height: 100%; border-radius: 50%;\"/>\n\n</$button>\n\\end\n\n\\define colour-picker-recent-inner(actions)\n<$set name=\"colour-picker-value\" value=\"$(recentColour)$\">\n<$macrocall $name=\"colour-picker-inner\" actions=\"\"\"$actions$\"\"\"/>\n</$set>\n\\end\n\n\\define colour-picker-recent(actions)\n{{$:/language/ColourPicker/Recent}} <$list filter=\"[list[$:/config/ColourPicker/Recent]]\" variable=\"recentColour\">\n<$macrocall $name=\"colour-picker-recent-inner\" actions=\"\"\"$actions$\"\"\"/></$list>\n\\end\n\n\\define colour-picker(actions)\n<div class=\"tc-colour-chooser\">\n\n<$macrocall $name=\"colour-picker-recent\" actions=\"\"\"$actions$\"\"\"/>\n\n---\n\n<$list filter=\"LightPink Pink Crimson LavenderBlush PaleVioletRed HotPink DeepPink MediumVioletRed Orchid Thistle Plum Violet Magenta Fuchsia DarkMagenta Purple MediumOrchid DarkViolet DarkOrchid Indigo BlueViolet MediumPurple MediumSlateBlue SlateBlue DarkSlateBlue Lavender GhostWhite Blue MediumBlue MidnightBlue DarkBlue Navy RoyalBlue CornflowerBlue LightSteelBlue LightSlateGrey SlateGrey DodgerBlue AliceBlue SteelBlue LightSkyBlue SkyBlue DeepSkyBlue LightBlue PowderBlue CadetBlue Azure LightCyan PaleTurquoise Cyan Aqua DarkTurquoise DarkSlateGrey DarkCyan Teal MediumTurquoise LightSeaGreen Turquoise Aquamarine MediumAquamarine MediumSpringGreen MintCream SpringGreen MediumSeaGreen SeaGreen Honeydew LightGreen PaleGreen DarkSeaGreen LimeGreen Lime ForestGreen Green DarkGreen Chartreuse LawnGreen GreenYellow DarkOliveGreen YellowGreen OliveDrab Beige LightGoldenrodYellow Ivory LightYellow Yellow Olive DarkKhaki LemonChiffon PaleGoldenrod Khaki Gold Cornsilk Goldenrod DarkGoldenrod FloralWhite OldLace Wheat Moccasin Orange PapayaWhip BlanchedAlmond NavajoWhite AntiqueWhite Tan BurlyWood Bisque DarkOrange Linen Peru PeachPuff SandyBrown Chocolate SaddleBrown Seashell Sienna LightSalmon Coral OrangeRed DarkSalmon Tomato MistyRose Salmon Snow LightCoral RosyBrown IndianRed Red Brown FireBrick DarkRed Maroon White WhiteSmoke Gainsboro LightGrey Silver DarkGrey Grey DimGrey Black\" variable=\"colour-picker-value\">\n<$macrocall $name=\"colour-picker-inner\" actions=\"\"\"$actions$\"\"\"/>\n</$list>\n\n---\n\n<$edit-text tiddler=\"$:/config/ColourPicker/New\" tag=\"input\" default=\"\" placeholder=\"\"/>\n<$edit-text tiddler=\"$:/config/ColourPicker/New\" type=\"color\" tag=\"input\"/>\n<$set name=\"colour-picker-value\" value={{$:/config/ColourPicker/New}}>\n<$macrocall $name=\"colour-picker-inner\" actions=\"\"\"$actions$\"\"\"/>\n</$set>\n\n</div>\n\n\\end\n"
        },
        "$:/core/macros/copy-to-clipboard": {
            "title": "$:/core/macros/copy-to-clipboard",
            "tags": "$:/tags/Macro",
            "text": "\\define copy-to-clipboard(src,class:\"tc-btn-invisible\",style)\n<$button class=<<__class__>> style=<<__style__>> message=\"tm-copy-to-clipboard\" param=<<__src__>> tooltip={{$:/language/Buttons/CopyToClipboard/Hint}}>\n{{$:/core/images/copy-clipboard}} <$text text={{$:/language/Buttons/CopyToClipboard/Caption}}/>\n</$button>\n\\end\n\n\\define copy-to-clipboard-above-right(src,class:\"tc-btn-invisible\",style)\n<div style=\"position: relative;\">\n<div style=\"position: absolute; bottom: 0; right: 0;\">\n<$macrocall $name=\"copy-to-clipboard\" src=<<__src__>> class=<<__class__>> style=<<__style__>>/>\n</div>\n</div>\n\\end\n\n"
        },
        "$:/core/macros/diff": {
            "title": "$:/core/macros/diff",
            "tags": "$:/tags/Macro",
            "text": "\\define compareTiddlerText(sourceTiddlerTitle,sourceSubTiddlerTitle,destTiddlerTitle,destSubTiddlerTitle)\n<$set name=\"source\" tiddler=<<__sourceTiddlerTitle__>> subtiddler=<<__sourceSubTiddlerTitle__>>>\n<$set name=\"dest\" tiddler=<<__destTiddlerTitle__>> subtiddler=<<__destSubTiddlerTitle__>>>\n<$diff-text source=<<source>> dest=<<dest>>/>\n</$set>\n</$set>\n\\end\n\n\\define compareTiddlers(sourceTiddlerTitle,sourceSubTiddlerTitle,destTiddlerTitle,destSubTiddlerTitle,exclude)\n<table class=\"tc-diff-tiddlers\">\n<tbody>\n<$set name=\"sourceFields\" filter=\"[<__sourceTiddlerTitle__>fields[]sort[]]\">\n<$set name=\"destFields\" filter=\"[<__destSubTiddlerTitle__>subtiddlerfields<__destTiddlerTitle__>sort[]]\">\n<$list filter=\"[enlist<sourceFields>] [enlist<destFields>] -[enlist<__exclude__>] +[sort[]]\" variable=\"fieldName\">\n<tr>\n<th>\n<$text text=<<fieldName>>/> \n</th>\n<td>\n<$set name=\"source\" tiddler=<<__sourceTiddlerTitle__>> subtiddler=<<__sourceSubTiddlerTitle__>> field=<<fieldName>>>\n<$set name=\"dest\" tiddler=<<__destTiddlerTitle__>> subtiddler=<<__destSubTiddlerTitle__>> field=<<fieldName>>>\n<$diff-text source=<<source>> dest=<<dest>>>\n</$diff-text>\n</$set>\n</$set>\n</td>\n</tr>\n</$list>\n</$set>\n</$set>\n</tbody>\n</table>\n\\end\n"
        },
        "$:/core/macros/dumpvariables": {
            "title": "$:/core/macros/dumpvariables",
            "tags": "$:/tags/Macro",
            "text": "\\define dumpvariables()\n<ul>\n<$list filter=\"[variables[]]\" variable=\"varname\">\n<li>\n<strong><code><$text text=<<varname>>/></code></strong>:<br/>\n<$codeblock code={{{ [<varname>getvariable[]] }}}/>\n</li>\n</$list>\n</ul>\n\\end\n"
        },
        "$:/core/macros/export": {
            "title": "$:/core/macros/export",
            "tags": "$:/tags/Macro",
            "text": "\\define exportButtonFilename(baseFilename)\n$baseFilename$$(extension)$\n\\end\n\n\\define exportButton(exportFilter:\"[!is[system]sort[title]]\",lingoBase,baseFilename:\"tiddlers\")\n<span class=\"tc-popup-keep\"><$button popup=<<qualify \"$:/state/popup/export\">> tooltip={{$lingoBase$Hint}} aria-label={{$lingoBase$Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>match[yes]]\">\n{{$:/core/images/export-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>match[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$lingoBase$Caption}}/></span>\n</$list>\n</$button></span><$reveal state=<<qualify \"$:/state/popup/export\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Exporter]]\">\n<$set name=\"extension\" value={{!!extension}}>\n<$button class=\"tc-btn-invisible\">\n<$action-sendmessage $message=\"tm-download-file\" $param=<<currentTiddler>> exportFilter=\"\"\"$exportFilter$\"\"\" filename=<<exportButtonFilename \"\"\"$baseFilename$\"\"\">>/>\n<$action-deletetiddler $tiddler=<<qualify \"$:/state/popup/export\">>/>\n<$transclude field=\"description\"/>\n</$button>\n</$set>\n</$list>\n</div>\n</$reveal>\n\\end\n"
        },
        "$:/core/macros/image-picker": {
            "title": "$:/core/macros/image-picker",
            "created": "20170715180840889",
            "modified": "20170715180914005",
            "tags": "$:/tags/Macro",
            "type": "text/vnd.tiddlywiki",
            "text": "\\define image-picker-thumbnail(actions)\n<$button tag=\"a\" tooltip=\"\"\"$(imageTitle)$\"\"\">\n$actions$\n<$transclude tiddler=<<imageTitle>>/>\n</$button>\n\\end\n\n\\define image-picker-list(filter,actions)\n<$list filter=\"\"\"$filter$\"\"\" variable=\"imageTitle\">\n<$macrocall $name=\"image-picker-thumbnail\" actions=\"\"\"$actions$\"\"\"/>\n</$list>\n\\end\n\n\\define image-picker(actions,filter:\"[all[shadows+tiddlers]is[image]] -[type[application/pdf]] +[!has[draft.of]$subfilter$sort[title]]\",subfilter:\"\")\n<div class=\"tc-image-chooser\">\n<$vars state-system=<<qualify \"$:/state/image-picker/system\">>>\n<$checkbox tiddler=<<state-system>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"hide\">\n{{$:/language/SystemTiddlers/Include/Prompt}}\n</$checkbox>\n<$reveal state=<<state-system>> type=\"match\" text=\"hide\" default=\"hide\" tag=\"div\">\n<$macrocall $name=\"image-picker-list\" filter=\"\"\"$filter$ +[!is[system]]\"\"\" actions=\"\"\"$actions$\"\"\"/>\n</$reveal>\n<$reveal state=<<state-system>> type=\"nomatch\" text=\"hide\" default=\"hide\" tag=\"div\">\n<$macrocall $name=\"image-picker-list\" filter=\"\"\"$filter$\"\"\" actions=\"\"\"$actions$\"\"\"/>\n</$reveal>\n</$vars>\n</div>\n\\end\n\n\\define image-picker-include-tagged-images(actions)\n<$macrocall $name=\"image-picker\" filter=\"[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[!has[draft.of]sort[title]]\" actions=\"\"\"$actions$\"\"\"/>\n\\end\n"
        },
        "$:/core/macros/lingo": {
            "title": "$:/core/macros/lingo",
            "tags": "$:/tags/Macro",
            "text": "\\define lingo-base()\n$:/language/\n\\end\n\n\\define lingo(title)\n{{$(lingo-base)$$title$}}\n\\end\n"
        },
        "$:/core/macros/list": {
            "title": "$:/core/macros/list",
            "tags": "$:/tags/Macro",
            "text": "\\define list-links(filter,type:\"ul\",subtype:\"li\",class:\"\",emptyMessage)\n\\whitespace trim\n<$type$ class=\"$class$\">\n<$list filter=\"$filter$\" emptyMessage=<<__emptyMessage__>>>\n<$subtype$>\n<$link to={{!!title}}>\n<$transclude field=\"caption\">\n<$view field=\"title\"/>\n</$transclude>\n</$link>\n</$subtype$>\n</$list>\n</$type$>\n\\end\n\n\\define list-links-draggable-drop-actions()\n<$action-listops $tiddler=<<targetTiddler>> $field=<<targetField>> $subfilter=\"+[insertbefore:currentTiddler<actionTiddler>]\"/>\n\\end\n\n\\define list-links-draggable(tiddler,field:\"list\",type:\"ul\",subtype:\"li\",class:\"\",itemTemplate)\n\\whitespace trim\n<span class=\"tc-links-draggable-list\">\n<$vars targetTiddler=\"\"\"$tiddler$\"\"\" targetField=\"\"\"$field$\"\"\">\n<$type$ class=\"$class$\">\n<$list filter=\"[list[$tiddler$!!$field$]]\">\n<$droppable actions=<<list-links-draggable-drop-actions>> tag=\"\"\"$subtype$\"\"\" enable=<<tv-enable-drag-and-drop>>>\n<div class=\"tc-droppable-placeholder\"/>\n<div>\n<$transclude tiddler=\"\"\"$itemTemplate$\"\"\">\n<$link to={{!!title}}>\n<$transclude field=\"caption\">\n<$view field=\"title\"/>\n</$transclude>\n</$link>\n</$transclude>\n</div>\n</$droppable>\n</$list>\n</$type$>\n<$tiddler tiddler=\"\">\n<$droppable actions=<<list-links-draggable-drop-actions>> tag=\"div\" enable=<<tv-enable-drag-and-drop>>>\n<div class=\"tc-droppable-placeholder\">\n&nbsp;\n</div>\n<div style=\"height:0.5em;\"/>\n</$droppable>\n</$tiddler>\n</$vars>\n</span>\n\\end\n\n\\define list-tagged-draggable-drop-actions(tag)\n<!-- Save the current ordering of the tiddlers with this tag -->\n<$set name=\"order\" filter=\"[<__tag__>tagging[]]\">\n<!-- Remove any list-after or list-before fields from the tiddlers with this tag -->\n<$list filter=\"[<__tag__>tagging[]]\">\n<$action-deletefield $field=\"list-before\"/>\n<$action-deletefield $field=\"list-after\"/>\n</$list>\n<!-- Save the new order to the Tag Tiddler -->\n<$action-listops $tiddler=<<__tag__>> $field=\"list\" $filter=\"+[enlist<order>] +[insertbefore:currentTiddler<actionTiddler>]\"/>\n<!-- Make sure the newly added item has the right tag -->\n<!-- Removing this line makes dragging tags within the dropdown work as intended -->\n<!--<$action-listops $tiddler=<<actionTiddler>> $tags=<<__tag__>>/>-->\n<!-- Using the following 5 lines as replacement makes dragging titles from outside into the dropdown apply the tag -->\n<$list filter=\"[<actionTiddler>!contains:tags<__tag__>]\">\n<$fieldmangler tiddler=<<actionTiddler>>>\n<$action-sendmessage $message=\"tm-add-tag\" $param=<<__tag__>>/>\n</$fieldmangler>\n</$list>\n</$set>\n\\end\n\n\\define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:\"div\",storyview:\"\")\n\\whitespace trim\n<span class=\"tc-tagged-draggable-list\">\n<$set name=\"tag\" value=<<__tag__>>>\n<$list filter=\"[<__tag__>tagging[]$subFilter$]\" emptyMessage=<<__emptyMessage__>> storyview=<<__storyview__>>>\n<$elementTag$ class=\"tc-menu-list-item\">\n<$droppable actions=\"\"\"<$macrocall $name=\"list-tagged-draggable-drop-actions\" tag=<<__tag__>>/>\"\"\" enable=<<tv-enable-drag-and-drop>>>\n<$elementTag$ class=\"tc-droppable-placeholder\"/>\n<$elementTag$>\n<$transclude tiddler=\"\"\"$itemTemplate$\"\"\">\n<$link to={{!!title}}>\n<$view field=\"title\"/>\n</$link>\n</$transclude>\n</$elementTag$>\n</$droppable>\n</$elementTag$>\n</$list>\n<$tiddler tiddler=\"\">\n<$droppable actions=\"\"\"<$macrocall $name=\"list-tagged-draggable-drop-actions\" tag=<<__tag__>>/>\"\"\" enable=<<tv-enable-drag-and-drop>>>\n<$elementTag$ class=\"tc-droppable-placeholder\"/>\n<$elementTag$ style=\"height:0.5em;\">\n</$elementTag$>\n</$droppable>\n</$tiddler>\n</$set>\n</span>\n\\end\n"
        },
        "$:/core/macros/tabs": {
            "title": "$:/core/macros/tabs",
            "tags": "$:/tags/Macro",
            "text": "\\define tabs(tabsList,default,state:\"$:/state/tab\",class,template,buttonTemplate,retain)\n<div class=\"tc-tab-set $class$\">\n<div class=\"tc-tab-buttons $class$\">\n<$list filter=\"$tabsList$\" variable=\"currentTab\" storyview=\"pop\"><$set name=\"save-currentTiddler\" value=<<currentTiddler>>><$tiddler tiddler=<<currentTab>>><$button set=<<qualify \"$state$\">> setTo=<<currentTab>> default=\"$default$\" selectedClass=\"tc-tab-selected\" tooltip={{!!tooltip}}>\n<$tiddler tiddler=<<save-currentTiddler>>>\n<$set name=\"tv-wikilinks\" value=\"no\">\n<$transclude tiddler=\"$buttonTemplate$\" mode=\"inline\">\n<$transclude tiddler=<<currentTab>> field=\"caption\">\n<$macrocall $name=\"currentTab\" $type=\"text/plain\" $output=\"text/plain\"/>\n</$transclude>\n</$transclude>\n</$set></$tiddler></$button></$tiddler></$set></$list>\n</div>\n<div class=\"tc-tab-divider $class$\"/>\n<div class=\"tc-tab-content $class$\">\n<$list filter=\"$tabsList$\" variable=\"currentTab\">\n\n<$reveal type=\"match\" state=<<qualify \"$state$\">> text=<<currentTab>> default=\"$default$\" retain=\"\"\"$retain$\"\"\">\n\n<$transclude tiddler=\"$template$\" mode=\"block\">\n\n<$transclude tiddler=<<currentTab>> mode=\"block\"/>\n\n</$transclude>\n\n</$reveal>\n\n</$list>\n</div>\n</div>\n\\end\n"
        },
        "$:/core/macros/tag-picker": {
            "title": "$:/core/macros/tag-picker",
            "tags": "$:/tags/Macro",
            "text": "\\define add-tag-actions()\n<$action-sendmessage $message=\"tm-add-tag\" $param={{{ [<newTagNameTiddler>get[text]] }}}/>\n<$action-deletetiddler $tiddler=<<newTagNameTiddler>>/>\n\\end\n\n\\define tag-button()\n<$button class=\"tc-btn-invisible\" tag=\"a\" tooltip={{$:/language/EditTemplate/Tags/Add/Button/Hint}}>\n<$action-sendmessage $message=\"tm-add-tag\" $param=<<tag>>/>\n<$action-deletetiddler $tiddler=<<newTagNameTiddler>>/>\n<$macrocall $name=\"tag-pill\" tag=<<tag>>/>\n</$button>\n\\end\n\n\\define tag-picker-inner()\n\\whitespace trim\n<div class=\"tc-edit-add-tag\">\n<span class=\"tc-add-tag-name\">\n<$keyboard key=\"ENTER\" actions=<<add-tag-actions>>>\n<$edit-text tiddler=<<newTagNameTiddler>> tag=\"input\" default=\"\" placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}} focusPopup=<<qualify \"$:/state/popup/tags-auto-complete\">> class=\"tc-edit-texteditor tc-popup-handle\" tabindex=<<tabIndex>> focus={{{ [{$:/config/AutoFocus}match[tags]then[true]] ~[[false]] }}}/>\n</$keyboard>\n</span>&nbsp;<$button popup=<<qualify \"$:/state/popup/tags-auto-complete\">> class=\"tc-btn-invisible\" tooltip={{$:/language/EditTemplate/Tags/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Tags/Dropdown/Caption}}>{{$:/core/images/down-arrow}}</$button>&nbsp;<span class=\"tc-add-tag-button\">\n<$set name=\"tag\" value={{{ [<newTagNameTiddler>get[text]] }}}>\n<$button set=\"$:/temp/NewTagName\" setTo=\"\" class=\"\">\n<<add-tag-actions>>\n<$action-deletetiddler $tiddler=<<newTagNameTiddler>>/>\n{{$:/language/EditTemplate/Tags/Add/Button}}\n</$button>\n</$set>\n</span>\n</div>\n<div class=\"tc-block-dropdown-wrapper\">\n<$reveal state=<<qualify \"$:/state/popup/tags-auto-complete\">> type=\"nomatch\" text=\"\" default=\"\">\n<div class=\"tc-block-dropdown\">\n<$set name=\"newTagName\" value={{{ [<newTagNameTiddler>get[text]] }}}>\n<$list filter=\"[<newTagName>minlength{$:/config/Tags/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n<$list filter=\"[tags[]!is[system]search:title<newTagName>sort[]]\" variable=\"tag\">\n<<tag-button>>\n</$list></$list>\n<hr>\n<$list filter=\"[<newTagName>minlength{$:/config/Tags/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n<$list filter=\"[tags[]is[system]search:title<newTagName>sort[]]\" variable=\"tag\">\n<<tag-button>>\n</$list></$list>\n</$set>\n</div>\n</$reveal>\n</div>\n\\end\n\\define tag-picker()\n\\whitespace trim\n<$list filter=\"[<newTagNameTiddler>match[]]\" emptyMessage=<<tag-picker-inner>>>\n<$set name=\"newTagNameTiddler\" value=<<qualify \"$:/temp/NewTagName\">>>\n<<tag-picker-inner>>\n</$set>\n</$list>\n\\end\n"
        },
        "$:/core/macros/tag": {
            "title": "$:/core/macros/tag",
            "tags": "$:/tags/Macro",
            "text": "\\define tag-pill-styles()\nbackground-color:$(backgroundColor)$;\nfill:$(foregroundColor)$;\ncolor:$(foregroundColor)$;\n\\end\n\n\\define tag-pill-inner(tag,icon,colour,fallbackTarget,colourA,colourB,element-tag,element-attributes,actions)\n<$vars foregroundColor=<<contrastcolour target:\"\"\"$colour$\"\"\" fallbackTarget:\"\"\"$fallbackTarget$\"\"\" colourA:\"\"\"$colourA$\"\"\" colourB:\"\"\"$colourB$\"\"\">> backgroundColor=\"\"\"$colour$\"\"\">\n<$element-tag$ $element-attributes$ class=\"tc-tag-label tc-btn-invisible\" style=<<tag-pill-styles>>>\n$actions$<$transclude tiddler=\"\"\"$icon$\"\"\"/><$view tiddler=<<__tag__>> field=\"title\" format=\"text\" />\n</$element-tag$>\n</$vars>\n\\end\n\n\\define tag-pill-body(tag,icon,colour,palette,element-tag,element-attributes,actions)\n<$macrocall $name=\"tag-pill-inner\" tag=<<__tag__>> icon=\"\"\"$icon$\"\"\" colour=\"\"\"$colour$\"\"\" fallbackTarget={{$palette$##tag-background}} colourA={{$palette$##foreground}} colourB={{$palette$##background}} element-tag=\"\"\"$element-tag$\"\"\" element-attributes=\"\"\"$element-attributes$\"\"\" actions=\"\"\"$actions$\"\"\"/>\n\\end\n\n\\define tag-pill(tag,element-tag:\"span\",element-attributes:\"\",actions:\"\")\n<span class=\"tc-tag-list-item\">\n<$macrocall $name=\"tag-pill-body\" tag=<<__tag__>> icon={{{ [<__tag__>get[icon]] }}} colour={{{ [<__tag__>get[color]] }}} palette={{$:/palette}} element-tag=\"\"\"$element-tag$\"\"\" element-attributes=\"\"\"$element-attributes$\"\"\" actions=\"\"\"$actions$\"\"\"/>\n</span>\n\\end\n\n\\define tag(tag)\n{{$tag$||$:/core/ui/TagTemplate}}\n\\end\n"
        },
        "$:/core/macros/thumbnails": {
            "title": "$:/core/macros/thumbnails",
            "tags": "$:/tags/Macro",
            "text": "\\define thumbnail(link,icon,color,background-color,image,caption,width:\"280\",height:\"157\")\n<$link to=\"\"\"$link$\"\"\"><div class=\"tc-thumbnail-wrapper\">\n<div class=\"tc-thumbnail-image\" style=\"width:$width$px;height:$height$px;\"><$reveal type=\"nomatch\" text=\"\" default=\"\"\"$image$\"\"\" tag=\"div\" style=\"width:$width$px;height:$height$px;\">\n[img[$image$]]\n</$reveal><$reveal type=\"match\" text=\"\" default=\"\"\"$image$\"\"\" tag=\"div\" class=\"tc-thumbnail-background\" style=\"width:$width$px;height:$height$px;background-color:$background-color$;\"></$reveal></div><div class=\"tc-thumbnail-icon\" style=\"fill:$color$;color:$color$;\">\n$icon$\n</div><div class=\"tc-thumbnail-caption\">\n$caption$\n</div>\n</div></$link>\n\\end\n\n\\define thumbnail-right(link,icon,color,background-color,image,caption,width:\"280\",height:\"157\")\n<div class=\"tc-thumbnail-right-wrapper\"><<thumbnail \"\"\"$link$\"\"\" \"\"\"$icon$\"\"\" \"\"\"$color$\"\"\" \"\"\"$background-color$\"\"\" \"\"\"$image$\"\"\" \"\"\"$caption$\"\"\" \"\"\"$width$\"\"\" \"\"\"$height$\"\"\">></div>\n\\end\n\n\\define list-thumbnails(filter,width:\"280\",height:\"157\")\n<$list filter=\"\"\"$filter$\"\"\"><$macrocall $name=\"thumbnail\" link={{!!link}} icon={{!!icon}} color={{!!color}} background-color={{!!background-color}} image={{!!image}} caption={{!!caption}} width=\"\"\"$width$\"\"\" height=\"\"\"$height$\"\"\"/></$list>\n\\end\n"
        },
        "$:/core/macros/timeline": {
            "title": "$:/core/macros/timeline",
            "created": "20141212105914482",
            "modified": "20141212110330815",
            "tags": "$:/tags/Macro",
            "text": "\\define timeline-title()\n\\whitespace trim\n<!-- Override this macro with a global macro \n     of the same name if you need to change \n     how titles are displayed on the timeline \n     -->\n<$view field=\"title\"/>\n\\end\n\\define timeline(limit:\"100\",format:\"DDth MMM YYYY\",subfilter:\"\",dateField:\"modified\")\n<div class=\"tc-timeline\">\n<$list filter=\"[!is[system]$subfilter$has[$dateField$]!sort[$dateField$]limit[$limit$]eachday[$dateField$]]\">\n<div class=\"tc-menu-list-item\">\n<$view field=\"$dateField$\" format=\"date\" template=\"$format$\"/>\n<$list filter=\"[sameday:$dateField${!!$dateField$}!is[system]$subfilter$!sort[$dateField$]]\">\n<div class=\"tc-menu-list-subitem\">\n<$link to={{!!title}}><<timeline-title>></$link>\n</div>\n</$list>\n</div>\n</$list>\n</div>\n\\end\n"
        },
        "$:/core/macros/toc": {
            "title": "$:/core/macros/toc",
            "tags": "$:/tags/Macro",
            "text": "\\define toc-caption()\n<$set name=\"tv-wikilinks\" value=\"no\">\n  <$transclude field=\"caption\">\n    <$view field=\"title\"/>\n  </$transclude>\n</$set>\n\\end\n\n\\define toc-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<ol class=\"tc-toc\">\n  <$list filter=\"\"\"[all[shadows+tiddlers]tag<__tag__>!has[draft.of]$sort$] -[<__tag__>] -[enlist<__exclude__>]\"\"\">\n    <$vars item=<<currentTiddler>> path={{{ [<__path__>addsuffix[/]addsuffix<__tag__>] }}}>\n      <$set name=\"excluded\" filter=\"\"\"[enlist<__exclude__>] [<__tag__>]\"\"\">\n        <$set name=\"toc-item-class\" filter=<<__itemClassFilter__>> emptyValue=\"toc-item-selected\" value=\"toc-item\">\n          <li class=<<toc-item-class>>>\n            <$list filter=\"[all[current]toc-link[no]]\" emptyMessage=\"<$link><$view field='caption'><$view field='title'/></$view></$link>\">\n              <<toc-caption>>\n            </$list>\n            <$macrocall $name=\"toc-body\" tag=<<item>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<excluded>> path=<<path>>/>\n          </li>\n        </$set>\n      </$set>\n    </$vars>\n  </$list>\n</ol>\n\\end\n\n\\define toc(tag,sort:\"\",itemClassFilter:\"\")\n<$macrocall $name=\"toc-body\"  tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> />\n\\end\n\n\\define toc-linked-expandable-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<!-- helper function -->\n<$qualify name=\"toc-state\" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>\n  <$set name=\"toc-item-class\" filter=<<__itemClassFilter__>> emptyValue=\"toc-item-selected\" value=\"toc-item\">\n    <li class=<<toc-item-class>>>\n    <$link>\n      <$reveal type=\"nomatch\" stateTitle=<<toc-state>> text=\"open\">\n        <$button setTitle=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible tc-popup-keep\">\n          {{$:/core/images/right-arrow}}\n        </$button>\n      </$reveal>\n      <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n        <$button setTitle=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible tc-popup-keep\">\n          {{$:/core/images/down-arrow}}\n        </$button>\n      </$reveal>\n      <<toc-caption>>\n    </$link>\n    <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n      <$macrocall $name=\"toc-expandable\" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>\n    </$reveal>\n    </li>\n  </$set>\n</$qualify>\n\\end\n\n\\define toc-unlinked-expandable-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<!-- helper function -->\n<$qualify name=\"toc-state\" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>\n  <$set name=\"toc-item-class\" filter=<<__itemClassFilter__>> emptyValue=\"toc-item-selected\" value=\"toc-item\">\n    <li class=<<toc-item-class>>>\n      <$reveal type=\"nomatch\" stateTitle=<<toc-state>> text=\"open\">\n        <$button setTitle=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible tc-popup-keep\">\n          {{$:/core/images/right-arrow}}\n          <<toc-caption>>\n        </$button>\n      </$reveal>\n      <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n        <$button setTitle=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible tc-popup-keep\">\n          {{$:/core/images/down-arrow}}\n          <<toc-caption>>\n        </$button>\n      </$reveal>\n      <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n        <$macrocall $name=\"toc-expandable\" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>\n      </$reveal>\n    </li>\n  </$set>\n</$qualify>\n\\end\n\n\\define toc-expandable-empty-message()\n<$macrocall $name=\"toc-linked-expandable-body\" tag=<<tag>> sort=<<sort>> itemClassFilter=<<itemClassFilter>> exclude=<<excluded>> path=<<path>>/>\n\\end\n\n\\define toc-expandable(tag,sort:\"\",itemClassFilter:\"\",exclude,path)\n<$vars tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> path={{{ [<__path__>addsuffix[/]addsuffix<__tag__>] }}}>\n  <$set name=\"excluded\" filter=\"\"\"[enlist<__exclude__>] [<__tag__>]\"\"\">\n    <ol class=\"tc-toc toc-expandable\">\n      <$list filter=\"\"\"[all[shadows+tiddlers]tag<__tag__>!has[draft.of]$sort$] -[<__tag__>] -[enlist<__exclude__>]\"\"\">\n        <$list filter=\"[all[current]toc-link[no]]\" emptyMessage=<<toc-expandable-empty-message>> >\n          <$macrocall $name=\"toc-unlinked-expandable-body\" tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=\"\"\"itemClassFilter\"\"\" exclude=<<excluded>> path=<<path>> />\n        </$list>\n      </$list>\n    </ol>\n  </$set>\n</$vars>\n\\end\n\n\\define toc-linked-selective-expandable-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<$qualify name=\"toc-state\" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>\n  <$set name=\"toc-item-class\" filter=<<__itemClassFilter__>> emptyValue=\"toc-item-selected\" value=\"toc-item\" >\n    <li class=<<toc-item-class>>>\n      <$link>\n          <$list filter=\"[all[current]tagging[]$sort$limit[1]]\" variable=\"ignore\" emptyMessage=\"<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button>\">\n          <$reveal type=\"nomatch\" stateTitle=<<toc-state>> text=\"open\">\n            <$button setTitle=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible tc-popup-keep\">\n              {{$:/core/images/right-arrow}}\n            </$button>\n          </$reveal>\n          <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n            <$button setTitle=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible tc-popup-keep\">\n              {{$:/core/images/down-arrow}}\n            </$button>\n          </$reveal>\n        </$list>\n        <<toc-caption>>\n      </$link>\n      <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n        <$macrocall $name=\"toc-selective-expandable\" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>\n      </$reveal>\n    </li>\n  </$set>\n</$qualify>\n\\end\n\n\\define toc-unlinked-selective-expandable-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<$qualify name=\"toc-state\" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>\n  <$set name=\"toc-item-class\" filter=<<__itemClassFilter__>> emptyValue=\"toc-item-selected\" value=\"toc-item\">\n    <li class=<<toc-item-class>>>\n      <$list filter=\"[all[current]tagging[]$sort$limit[1]]\" variable=\"ignore\" emptyMessage=\"<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button> <$view field='caption'><$view field='title'/></$view>\">\n        <$reveal type=\"nomatch\" stateTitle=<<toc-state>> text=\"open\">\n          <$button setTitle=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible tc-popup-keep\">\n            {{$:/core/images/right-arrow}}\n            <<toc-caption>>\n          </$button>\n        </$reveal>\n        <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n          <$button setTitle=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible tc-popup-keep\">\n            {{$:/core/images/down-arrow}}\n            <<toc-caption>>\n          </$button>\n        </$reveal>\n      </$list>\n      <$reveal type=\"match\" stateTitle=<<toc-state>> text=\"open\">\n        <$macrocall $name=\"toc-selective-expandable\" tag=<<currentTiddler>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<__exclude__>> path=<<__path__>>/>\n      </$reveal>\n    </li>\n  </$set>\n</$qualify>\n\\end\n\n\\define toc-selective-expandable-empty-message()\n<$macrocall $name=\"toc-linked-selective-expandable-body\" tag=<<tag>> sort=<<sort>> itemClassFilter=<<itemClassFilter>> exclude=<<excluded>> path=<<path>>/>\n\\end\n\n\\define toc-selective-expandable(tag,sort:\"\",itemClassFilter,exclude,path)\n<$vars tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> path={{{ [<__path__>addsuffix[/]addsuffix<__tag__>] }}}>\n  <$set name=\"excluded\" filter=\"\"\"[enlist<__exclude__>] [<__tag__>]\"\"\">\n    <ol class=\"tc-toc toc-selective-expandable\">\n      <$list filter=\"\"\"[all[shadows+tiddlers]tag<__tag__>!has[draft.of]$sort$] -[<__tag__>] -[enlist<__exclude__>]\"\"\">\n        <$list filter=\"[all[current]toc-link[no]]\" variable=\"ignore\" emptyMessage=<<toc-selective-expandable-empty-message>> >\n          <$macrocall $name=\"toc-unlinked-selective-expandable-body\" tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=<<__itemClassFilter__>> exclude=<<excluded>> path=<<path>>/>\n        </$list>\n      </$list>\n    </ol>\n  </$set>\n</$vars>\n\\end\n\n\\define toc-tabbed-external-nav(tag,sort:\"\",selectedTiddler:\"$:/temp/toc/selectedTiddler\",unselectedText,missingText,template:\"\")\n<$tiddler tiddler={{{ [<__selectedTiddler__>get[text]] }}}>\n  <div class=\"tc-tabbed-table-of-contents\">\n    <$linkcatcher to=<<__selectedTiddler__>>>\n      <div class=\"tc-table-of-contents\">\n        <$macrocall $name=\"toc-selective-expandable\" tag=<<__tag__>> sort=<<__sort__>> itemClassFilter=\"[all[current]] -[<__selectedTiddler__>get[text]]\"/>\n      </div>\n    </$linkcatcher>\n    <div class=\"tc-tabbed-table-of-contents-content\">\n      <$reveal stateTitle=<<__selectedTiddler__>> type=\"nomatch\" text=\"\">\n        <$transclude mode=\"block\" tiddler=<<__template__>>>\n          <h1><<toc-caption>></h1>\n          <$transclude mode=\"block\">$missingText$</$transclude>\n        </$transclude>\n      </$reveal>\n      <$reveal stateTitle=<<__selectedTiddler__>> type=\"match\" text=\"\">\n        $unselectedText$\n      </$reveal>\n    </div>\n  </div>\n</$tiddler>\n\\end\n\n\\define toc-tabbed-internal-nav(tag,sort:\"\",selectedTiddler:\"$:/temp/toc/selectedTiddler\",unselectedText,missingText,template:\"\")\n<$linkcatcher to=<<__selectedTiddler__>>>\n  <$macrocall $name=\"toc-tabbed-external-nav\" tag=<<__tag__>> sort=<<__sort__>> selectedTiddler=<<__selectedTiddler__>> unselectedText=<<__unselectedText__>> missingText=<<__missingText__>> template=<<__template__>>/>\n</$linkcatcher>\n\\end\n\n"
        },
        "$:/core/macros/translink": {
            "title": "$:/core/macros/translink",
            "tags": "$:/tags/Macro",
            "text": "\\define translink(title,mode:\"block\")\n<div style=\"border:1px solid #ccc; padding: 0.5em; background: black; foreground; white;\">\n<$link to=\"\"\"$title$\"\"\">\n<$text text=\"\"\"$title$\"\"\"/>\n</$link>\n<div style=\"border:1px solid #ccc; padding: 0.5em; background: white; foreground; black;\">\n<$transclude tiddler=\"\"\"$title$\"\"\" mode=\"$mode$\">\n\"<$text text=\"\"\"$title$\"\"\"/>\" is missing\n</$transclude>\n</div>\n</div>\n\\end\n"
        },
        "$:/core/macros/tree": {
            "title": "$:/core/macros/tree",
            "tags": "$:/tags/Macro",
            "text": "\\define leaf-link(full-title,chunk,separator: \"/\")\n<$link to=<<__full-title__>>><$text text=<<__chunk__>>/></$link>\n\\end\n\n\\define leaf-node(prefix,chunk)\n<li>\n<$list filter=\"[<__prefix__>addsuffix<__chunk__>is[shadow]] [<__prefix__>addsuffix<__chunk__>is[tiddler]]\" variable=\"full-title\">\n<$list filter=\"[<full-title>removeprefix<__prefix__>]\" variable=\"chunk\">\n<span>{{$:/core/images/file}}</span> <$macrocall $name=\"leaf-link\" full-title=<<full-title>> chunk=<<chunk>>/>\n</$list>\n</$list>\n</li>\n\\end\n\n\\define branch-node(prefix,chunk,separator: \"/\")\n<li>\n<$set name=\"reveal-state\" value={{{ [[$:/state/tree/]addsuffix<__prefix__>addsuffix<__chunk__>] }}}>\n<$reveal type=\"nomatch\" stateTitle=<<reveal-state>> text=\"show\">\n<$button setTitle=<<reveal-state>> setTo=\"show\" class=\"tc-btn-invisible\">\n{{$:/core/images/folder}} <$text text=<<__chunk__>>/>\n</$button>\n</$reveal>\n<$reveal type=\"match\" stateTitle=<<reveal-state>> text=\"show\">\n<$button setTitle=<<reveal-state>> setTo=\"hide\" class=\"tc-btn-invisible\">\n{{$:/core/images/folder}} <$text text=<<__chunk__>>/>\n</$button>\n</$reveal>\n<span>(<$count filter=\"[all[shadows+tiddlers]removeprefix<__prefix__>removeprefix<__chunk__>] -[<__prefix__>addsuffix<__chunk__>]\"/>)</span>\n<$reveal type=\"match\" stateTitle=<<reveal-state>> text=\"show\">\n<$macrocall $name=\"tree-node\" prefix={{{ [<__prefix__>addsuffix<__chunk__>] }}} separator=<<__separator__>>/>\n</$reveal>\n</$set>\n</li>\n\\end\n\n\\define tree-node(prefix,separator: \"/\")\n<ol>\n<$list filter=\"[all[shadows+tiddlers]removeprefix<__prefix__>splitbefore<__separator__>sort[]!suffix<__separator__>]\" variable=\"chunk\">\n<$macrocall $name=\"leaf-node\" prefix=<<__prefix__>> chunk=<<chunk>> separator=<<__separator__>>/>\n</$list>\n<$list filter=\"[all[shadows+tiddlers]removeprefix<__prefix__>splitbefore<__separator__>sort[]suffix<__separator__>]\" variable=\"chunk\">\n<$macrocall $name=\"branch-node\" prefix=<<__prefix__>> chunk=<<chunk>> separator=<<__separator__>>/>\n</$list>\n</ol>\n\\end\n\n\\define tree(prefix: \"$:/\",separator: \"/\")\n<div class=\"tc-tree\">\n<span><$text text=<<__prefix__>>/></span>\n<div>\n<$macrocall $name=\"tree-node\" prefix=<<__prefix__>> separator=<<__separator__>>/>\n</div>\n</div>\n\\end\n"
        },
        "$:/core/macros/utils": {
            "title": "$:/core/macros/utils",
            "text": "\\define colour(colour)\n$colour$\n\\end\n"
        },
        "$:/snippets/minifocusswitcher": {
            "title": "$:/snippets/minifocusswitcher",
            "text": "<$select tiddler=\"$:/config/AutoFocus\">\n<$list filter=\"title tags text type fields\">\n<option value=<<currentTiddler>>><<currentTiddler>></option>\n</$list>\n</$select>\n"
        },
        "$:/snippets/minilanguageswitcher": {
            "title": "$:/snippets/minilanguageswitcher",
            "text": "<$select tiddler=\"$:/language\">\n<$list filter=\"[[$:/languages/en-GB]] [plugin-type[language]sort[title]]\">\n<option value=<<currentTiddler>>><$view field=\"description\"><$view field=\"name\"><$view field=\"title\"/></$view></$view></option>\n</$list>\n</$select>"
        },
        "$:/snippets/minithemeswitcher": {
            "title": "$:/snippets/minithemeswitcher",
            "text": "\\define lingo-base() $:/language/ControlPanel/Theme/\n<<lingo Prompt>> <$select tiddler=\"$:/theme\">\n<$list filter=\"[plugin-type[theme]sort[title]]\">\n<option value=<<currentTiddler>>><$view field=\"name\"><$view field=\"title\"/></$view></option>\n</$list>\n</$select>"
        },
        "$:/snippets/modules": {
            "title": "$:/snippets/modules",
            "text": "\\define describeModuleType(type)\n{{$:/language/Docs/ModuleTypes/$type$}}\n\\end\n<$list filter=\"[moduletypes[]]\">\n\n!! <$macrocall $name=\"currentTiddler\" $type=\"text/plain\" $output=\"text/plain\"/>\n\n<$macrocall $name=\"describeModuleType\" type=<<currentTiddler>>/>\n\n<ul><$list filter=\"[all[current]modules[]]\"><li><$link><<currentTiddler>></$link>\n</li>\n</$list>\n</ul>\n</$list>\n"
        },
        "$:/palette": {
            "title": "$:/palette",
            "text": "$:/palettes/Vanilla"
        },
        "$:/snippets/paletteeditor": {
            "title": "$:/snippets/paletteeditor",
            "text": "<$transclude tiddler=\"$:/PaletteManager\"/>\n"
        },
        "$:/snippets/palettepreview": {
            "title": "$:/snippets/palettepreview",
            "text": "<$set name=\"currentTiddler\" value={{$:/palette}}>\n{{||$:/snippets/currpalettepreview}}\n</$set>\n"
        },
        "$:/snippets/paletteswitcher": {
            "title": "$:/snippets/paletteswitcher",
            "text": "<$linkcatcher to=\"$:/palette\">\n<div class=\"tc-chooser\"><$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Palette]sort[name]]\"><$set name=\"cls\" filter=\"[all[current]prefix{$:/palette}]\" value=\"tc-chooser-item tc-chosen\" emptyValue=\"tc-chooser-item\"><div class=<<cls>>><$link to={{!!title}}>''<$view field=\"name\" format=\"text\"/>'' - <$view field=\"description\" format=\"text\"/>{{||$:/snippets/currpalettepreview}}</$link>\n</div></$set>\n</$list>\n</div>\n</$linkcatcher>\n"
        },
        "$:/snippets/peek-stylesheets": {
            "title": "$:/snippets/peek-stylesheets",
            "text": "\\define expandable-stylesheets-list()\n<ol>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Stylesheet]!has[draft.of]]\">\n<$vars state=<<qualify \"$:/state/peek-stylesheets/open/\">>>\n<$set name=\"state\" value={{{ [<state>addsuffix<currentTiddler>] }}}>\n<li>\n<$reveal type=\"match\" state=<<state>> text=\"yes\" tag=\"span\">\n<$button set=<<state>> setTo=\"no\" class=\"tc-btn-invisible\">\n{{$:/core/images/down-arrow}}\n</$button>\n</$reveal>\n<$reveal type=\"nomatch\" state=<<state>> text=\"yes\" tag=\"span\">\n<$button set=<<state>> setTo=\"yes\" class=\"tc-btn-invisible\">\n{{$:/core/images/right-arrow}}\n</$button>\n</$reveal>\n<$link>\n<$view field=\"title\"/>\n</$link>\n<$reveal type=\"match\" state=<<state>> text=\"yes\" tag=\"div\">\n<$set name=\"source\" tiddler=<<currentTiddler>>>\n<$wikify name=\"styles\" text=<<source>>>\n<pre>\n<code>\n<$text text=<<styles>>/>\n</code>\n</pre>\n</$wikify>\n</$set>\n</$reveal>\n</li>\n</$set>\n</$vars>\n</$list>\n</ol>\n\\end\n\n\\define stylesheets-list()\n<ol>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Stylesheet]!has[draft.of]]\">\n<li>\n<$link>\n<$view field=\"title\"/>\n</$link>\n<$set name=\"source\" tiddler=<<currentTiddler>>>\n<$wikify name=\"styles\" text=<<source>>>\n<pre>\n<code>\n<$text text=<<styles>>/>\n</code>\n</pre>\n</$wikify>\n</$set>\n</li>\n</$list>\n</ol>\n\\end\n\n<$vars modeState=<<qualify \"$:/state/peek-stylesheets/mode/\">>>\n\n<$reveal type=\"nomatch\" state=<<modeState>> text=\"expanded\" tag=\"div\">\n<$button set=<<modeState>> setTo=\"expanded\" class=\"tc-btn-invisible\">{{$:/core/images/chevron-right}} {{$:/language/ControlPanel/Stylesheets/Expand/Caption}}</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<modeState>> text=\"expanded\" tag=\"div\">\n<$button set=<<modeState>> setTo=\"restored\" class=\"tc-btn-invisible\">{{$:/core/images/chevron-down}} {{$:/language/ControlPanel/Stylesheets/Restore/Caption}}</$button>\n</$reveal>\n\n<$reveal type=\"nomatch\" state=<<modeState>> text=\"expanded\" tag=\"div\">\n<<expandable-stylesheets-list>>\n</$reveal>\n<$reveal type=\"match\" state=<<modeState>> text=\"expanded\" tag=\"div\">\n<<stylesheets-list>>\n</$reveal>\n\n</$vars>\n"
        },
        "$:/temp/search": {
            "title": "$:/temp/search",
            "text": ""
        },
        "$:/tags/AdvancedSearch": {
            "title": "$:/tags/AdvancedSearch",
            "list": "[[$:/core/ui/AdvancedSearch/Standard]] [[$:/core/ui/AdvancedSearch/System]] [[$:/core/ui/AdvancedSearch/Shadows]] [[$:/core/ui/AdvancedSearch/Filter]]"
        },
        "$:/tags/AdvancedSearch/FilterButton": {
            "title": "$:/tags/AdvancedSearch/FilterButton",
            "list": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/dropdown $:/core/ui/AdvancedSearch/Filter/FilterButtons/clear $:/core/ui/AdvancedSearch/Filter/FilterButtons/export $:/core/ui/AdvancedSearch/Filter/FilterButtons/delete"
        },
        "$:/tags/ControlPanel": {
            "title": "$:/tags/ControlPanel",
            "list": "$:/core/ui/ControlPanel/Info $:/core/ui/ControlPanel/Appearance $:/core/ui/ControlPanel/Settings $:/core/ui/ControlPanel/Saving $:/core/ui/ControlPanel/Plugins $:/core/ui/ControlPanel/Tools $:/core/ui/ControlPanel/Internals"
        },
        "$:/tags/ControlPanel/Info": {
            "title": "$:/tags/ControlPanel/Info",
            "list": "$:/core/ui/ControlPanel/Basics $:/core/ui/ControlPanel/Advanced"
        },
        "$:/tags/ControlPanel/Plugins": {
            "title": "$:/tags/ControlPanel/Plugins",
            "list": "[[$:/core/ui/ControlPanel/Plugins/Installed]] [[$:/core/ui/ControlPanel/Plugins/Add]]"
        },
        "$:/tags/EditTemplate": {
            "title": "$:/tags/EditTemplate",
            "list": "[[$:/core/ui/EditTemplate/controls]] [[$:/core/ui/EditTemplate/title]] [[$:/core/ui/EditTemplate/tags]] [[$:/core/ui/EditTemplate/shadow]] [[$:/core/ui/ViewTemplate/classic]] [[$:/core/ui/EditTemplate/body]] [[$:/core/ui/EditTemplate/type]] [[$:/core/ui/EditTemplate/fields]]"
        },
        "$:/tags/EditToolbar": {
            "title": "$:/tags/EditToolbar",
            "list": "[[$:/core/ui/Buttons/delete]] [[$:/core/ui/Buttons/cancel]] [[$:/core/ui/Buttons/save]]"
        },
        "$:/tags/EditorToolbar": {
            "title": "$:/tags/EditorToolbar",
            "list": "$:/core/ui/EditorToolbar/paint $:/core/ui/EditorToolbar/opacity $:/core/ui/EditorToolbar/line-width $:/core/ui/EditorToolbar/rotate-left $:/core/ui/EditorToolbar/clear $:/core/ui/EditorToolbar/bold $:/core/ui/EditorToolbar/italic $:/core/ui/EditorToolbar/strikethrough $:/core/ui/EditorToolbar/underline $:/core/ui/EditorToolbar/superscript $:/core/ui/EditorToolbar/subscript $:/core/ui/EditorToolbar/mono-line $:/core/ui/EditorToolbar/mono-block $:/core/ui/EditorToolbar/quote $:/core/ui/EditorToolbar/list-bullet $:/core/ui/EditorToolbar/list-number $:/core/ui/EditorToolbar/heading-1 $:/core/ui/EditorToolbar/heading-2 $:/core/ui/EditorToolbar/heading-3 $:/core/ui/EditorToolbar/heading-4 $:/core/ui/EditorToolbar/heading-5 $:/core/ui/EditorToolbar/heading-6 $:/core/ui/EditorToolbar/link $:/core/ui/EditorToolbar/excise $:/core/ui/EditorToolbar/picture $:/core/ui/EditorToolbar/stamp $:/core/ui/EditorToolbar/size $:/core/ui/EditorToolbar/editor-height $:/core/ui/EditorToolbar/more $:/core/ui/EditorToolbar/preview $:/core/ui/EditorToolbar/preview-type"
        },
        "$:/tags/Manager/ItemMain": {
            "title": "$:/tags/Manager/ItemMain",
            "list": "$:/Manager/ItemMain/WikifiedText $:/Manager/ItemMain/RawText $:/Manager/ItemMain/Fields"
        },
        "$:/tags/Manager/ItemSidebar": {
            "title": "$:/tags/Manager/ItemSidebar",
            "list": "$:/Manager/ItemSidebar/Tags $:/Manager/ItemSidebar/Colour $:/Manager/ItemSidebar/Icon $:/Manager/ItemSidebar/Tools"
        },
        "$:/tags/MoreSideBar": {
            "title": "$:/tags/MoreSideBar",
            "list": "[[$:/core/ui/MoreSideBar/All]] [[$:/core/ui/MoreSideBar/Recent]] [[$:/core/ui/MoreSideBar/Tags]] [[$:/core/ui/MoreSideBar/Missing]] [[$:/core/ui/MoreSideBar/Drafts]] [[$:/core/ui/MoreSideBar/Orphans]] [[$:/core/ui/MoreSideBar/Types]] [[$:/core/ui/MoreSideBar/System]] [[$:/core/ui/MoreSideBar/Shadows]] [[$:/core/ui/MoreSideBar/Explorer]] [[$:/core/ui/MoreSideBar/Plugins]]",
            "text": ""
        },
        "$:/tags/PageControls": {
            "title": "$:/tags/PageControls",
            "list": "[[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/more-page-actions]]"
        },
        "$:/tags/PageTemplate": {
            "title": "$:/tags/PageTemplate",
            "list": "[[$:/core/ui/PageTemplate/topleftbar]] [[$:/core/ui/PageTemplate/toprightbar]] [[$:/core/ui/PageTemplate/sidebar]] [[$:/core/ui/PageTemplate/story]] [[$:/core/ui/PageTemplate/alerts]]",
            "text": ""
        },
        "$:/tags/PluginLibrary": {
            "title": "$:/tags/PluginLibrary",
            "list": "$:/config/OfficialPluginLibrary"
        },
        "$:/tags/SideBar": {
            "title": "$:/tags/SideBar",
            "list": "[[$:/core/ui/SideBar/Open]] [[$:/core/ui/SideBar/Recent]] [[$:/core/ui/SideBar/Tools]] [[$:/core/ui/SideBar/More]]",
            "text": ""
        },
        "$:/tags/SideBarSegment": {
            "title": "$:/tags/SideBarSegment",
            "list": "[[$:/core/ui/SideBarSegments/site-title]] [[$:/core/ui/SideBarSegments/site-subtitle]] [[$:/core/ui/SideBarSegments/page-controls]] [[$:/core/ui/SideBarSegments/search]] [[$:/core/ui/SideBarSegments/tabs]]"
        },
        "$:/tags/TiddlerInfo": {
            "title": "$:/tags/TiddlerInfo",
            "list": "[[$:/core/ui/TiddlerInfo/Tools]] [[$:/core/ui/TiddlerInfo/References]] [[$:/core/ui/TiddlerInfo/Tagging]] [[$:/core/ui/TiddlerInfo/List]] [[$:/core/ui/TiddlerInfo/Listed]] [[$:/core/ui/TiddlerInfo/Fields]]",
            "text": ""
        },
        "$:/tags/TiddlerInfo/Advanced": {
            "title": "$:/tags/TiddlerInfo/Advanced",
            "list": "[[$:/core/ui/TiddlerInfo/Advanced/ShadowInfo]] [[$:/core/ui/TiddlerInfo/Advanced/PluginInfo]]"
        },
        "$:/tags/ViewTemplate": {
            "title": "$:/tags/ViewTemplate",
            "list": "[[$:/core/ui/ViewTemplate/title]] [[$:/core/ui/ViewTemplate/unfold]] [[$:/core/ui/ViewTemplate/subtitle]] [[$:/core/ui/ViewTemplate/tags]] [[$:/core/ui/ViewTemplate/classic]] [[$:/core/ui/ViewTemplate/body]]"
        },
        "$:/tags/ViewToolbar": {
            "title": "$:/tags/ViewToolbar",
            "list": "[[$:/core/ui/Buttons/more-tiddler-actions]] [[$:/core/ui/Buttons/info]] [[$:/core/ui/Buttons/new-here]] [[$:/core/ui/Buttons/new-journal-here]] [[$:/core/ui/Buttons/clone]] [[$:/core/ui/Buttons/export-tiddler]] [[$:/core/ui/Buttons/edit]] [[$:/core/ui/Buttons/delete]] [[$:/core/ui/Buttons/permalink]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/open-window]] [[$:/core/ui/Buttons/close-others]] [[$:/core/ui/Buttons/close]] [[$:/core/ui/Buttons/fold-others]] [[$:/core/ui/Buttons/fold]]"
        },
        "$:/snippets/themeswitcher": {
            "title": "$:/snippets/themeswitcher",
            "text": "<$linkcatcher to=\"$:/theme\">\n<div class=\"tc-chooser\"><$list filter=\"[plugin-type[theme]sort[title]]\"><$set name=\"cls\" filter=\"[all[current]field:title{$:/theme}] [[$:/theme]!has[text]addsuffix[s/tiddlywiki/vanilla]field:title<currentTiddler>] +[limit[1]]\" value=\"tc-chooser-item tc-chosen\" emptyValue=\"tc-chooser-item\"><div class=<<cls>>><$link to={{!!title}}>''<$view field=\"name\" format=\"text\"/>'' <$view field=\"description\" format=\"text\"/></$link></div>\n</$set>\n</$list>\n</div>\n</$linkcatcher>"
        },
        "$:/core/wiki/title": {
            "title": "$:/core/wiki/title",
            "text": "{{$:/SiteTitle}} --- {{$:/SiteSubtitle}}"
        },
        "$:/view": {
            "title": "$:/view",
            "text": "classic"
        },
        "$:/snippets/viewswitcher": {
            "title": "$:/snippets/viewswitcher",
            "text": "\\define icon()\n$:/core/images/storyview-$(storyview)$\n\\end\n<$linkcatcher to=\"$:/view\">\n<div class=\"tc-chooser tc-viewswitcher\">\n<$list filter=\"[storyviews[]]\" variable=\"storyview\">\n<$set name=\"cls\" filter=\"[<storyview>prefix{$:/view}]\" value=\"tc-chooser-item tc-chosen\" emptyValue=\"tc-chooser-item\"><div class=<<cls>>>\n<$link to=<<storyview>>><$transclude tiddler=<<icon>>/><$text text=<<storyview>>/></$link>\n</div>\n</$set>\n</$list>\n</div>\n</$linkcatcher>"
        }
    }
}
About
TableOfContents
index.html
/
Thorbijoern/wiki
Thorbijoern
{
    "tiddlers": {
        "Untitled": {
            "title": "Untitled",
            "text": "* OBT Monitor\n** reparieren - OBT soll den mal vorbei bringen",
            "type": "text/plain"
        }
    }
}
no

$:/palettes/GruvboxDark
a non-linear personal web notebook; collecting knowledge and nice ideas for humanity
Thorbijoern's Wiki
show
show
show
show
show
show
show
show
show
show
show
show
show
show
hide
show
show
show
show
show
show
show
show
show
show
show
show
show
$:/core/ui/EditTemplate/body/preview/output
hide
hide

yes
yes
$:/core/ui/AdvancedSearch/Filter
$:/themes/tiddlywiki/vanilla/themetweaks
$:/core/ui/ControlPanel/Basics
$:/core/ui/ControlPanel/Plugins/Add/Plugins
$:/core/ui/ControlPanel/Plugins/Installed/Plugins
$:/core/ui/ControlPanel/KeyboardShortcuts
$:/core/ui/ControlPanel/Saving/GitHub
$:/core/ui/MoreSideBar/Drafts
$:/core/ui/SideBar/Recent
$:/core/ui/ControlPanel/Toolbars/EditToolbar
close
close
close
close
open
close
close
close
close
close
close
close
close
close
close
close
close
close
close
open
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
open
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
open
close
close
close
close
close
open
close
close
close
close
close
close
close
close
close
close
close
open
open
close
close
close
close
close
close
close
close
close
close
close
close
close
close
close
open
close
close
close
close
close
close
close
close
open
close
close
open
close
close
close
close
close
close
no


[is[tiddler]is[shadow]sort[title]]
{
    "tiddlers": {
        "$:/info/browser": {
            "title": "$:/info/browser",
            "text": "yes"
        },
        "$:/info/node": {
            "title": "$:/info/node",
            "text": "no"
        },
        "$:/info/url/full": {
            "title": "$:/info/url/full",
            "text": "https://thorbijoern.github.io/wiki/"
        },
        "$:/info/url/host": {
            "title": "$:/info/url/host",
            "text": "thorbijoern.github.io"
        },
        "$:/info/url/hostname": {
            "title": "$:/info/url/hostname",
            "text": "thorbijoern.github.io"
        },
        "$:/info/url/protocol": {
            "title": "$:/info/url/protocol",
            "text": "https:"
        },
        "$:/info/url/port": {
            "title": "$:/info/url/port",
            "text": ""
        },
        "$:/info/url/pathname": {
            "title": "$:/info/url/pathname",
            "text": "/wiki/"
        },
        "$:/info/url/search": {
            "title": "$:/info/url/search",
            "text": ""
        },
        "$:/info/url/origin": {
            "title": "$:/info/url/origin",
            "text": "https://thorbijoern.github.io"
        },
        "$:/info/browser/screen/width": {
            "title": "$:/info/browser/screen/width",
            "text": "1920"
        },
        "$:/info/browser/screen/height": {
            "title": "$:/info/browser/screen/height",
            "text": "1080"
        },
        "$:/info/browser/language": {
            "title": "$:/info/browser/language",
            "text": "de"
        }
    }
}





































































































loaded
$:/themes/tiddlywiki/vanilla
{
    "tiddlers": {
        "$:/themes/tiddlywiki/snowwhite/base": {
            "title": "$:/themes/tiddlywiki/snowwhite/base",
            "tags": "[[$:/tags/Stylesheet]]",
            "text": "\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\n\n.tc-sidebar-header {\n\ttext-shadow: 0 1px 0 <<colour sidebar-foreground-shadow>>;\n}\n\n.tc-tiddler-info {\n\t<<box-shadow \"inset 1px 2px 3px rgba(0,0,0,0.1)\">>\n}\n\n@media screen {\n\t.tc-tiddler-frame {\n\t\t<<box-shadow \"1px 1px 5px rgba(0, 0, 0, 0.3)\">>\n\t}\n}\n\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\t.tc-tiddler-frame {\n\t\t<<box-shadow none>>\n\t}\n}\n\n.tc-page-controls button svg, .tc-tiddler-controls button svg, .tc-topbar button svg {\n\t<<transition \"fill 150ms ease-in-out\">>\n}\n\n.tc-tiddler-controls button.tc-selected,\n.tc-page-controls button.tc-selected {\n\t<<filter \"drop-shadow(0px -1px 2px rgba(0,0,0,0.25))\">>\n}\n\n.tc-tiddler-frame input.tc-edit-texteditor {\n\t<<box-shadow \"inset 0 1px 8px rgba(0, 0, 0, 0.15)\">>\n}\n\n.tc-edit-tags {\n\t<<box-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<<box-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<<box-shadow \"2px 2px 5px rgba(0, 0, 0, 0.5)\">>\n}\n\n.tc-drop-down {\n\tborder-radius: 4px;\n\t<<box-shadow \"2px 2px 10px rgba(0, 0, 0, 0.5)\">>\n}\n\n.tc-block-dropdown {\n\tborder-radius: 4px;\n\t<<box-shadow \"2px 2px 10px rgba(0, 0, 0, 0.5)\">>\n}\n\n.tc-modal {\n\tborder-radius: 6px;\n\t<<box-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<<box-shadow \"inset 0 1px 0 #fff\">>;\n}\n\n\n.tc-alert {\n\tborder-radius: 6px;\n\t<<box-shadow \"0 3px 7px rgba(0,0,0,0.6)\">>\n}\n\n.tc-notification {\n\tborder-radius: 6px;\n\t<<box-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<<background-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<<background-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<<background-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<<box-shadow \"1px 1px 3px rgba(0,0,0,0.5)\">>\n}\n\n.tc-plugin-info {\n\t<<box-shadow \"1px 1px 3px rgba(0,0,0,0.5)\">>\n}\n"
        }
    }
}
{
    "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<div class=\"tc-drop-down-wrapper\">\n<$button popup=<<qualify \"$:/state/popup/themetweaks/backgroundimage\">> class=\"tc-btn-invisible tc-btn-dropdown\">{{$:/core/images/down-arrow}}</$button>\n<$reveal state=<<qualify \"$:/state/popup/themetweaks/backgroundimage\">> type=\"popup\" position=\"belowleft\" text=\"\" default=\"\">\n<div class=\"tc-drop-down\">\n<$macrocall $name=\"image-picker\" actions=\"\"\"\n\n<$action-setfield\n\t$tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\"\n\t$value=<<imageTitle>>\n/>\n\n\"\"\"/>\n</div>\n</$reveal>\n</div>\n\\end\n\n\\define backgroundimageattachment-dropdown()\n<$select tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment\" default=\"scroll\">\n<option value=\"scroll\"><<lingo Settings/BackgroundImageAttachment/Scroll>></option>\n<option value=\"fixed\"><<lingo Settings/BackgroundImageAttachment/Fixed>></option>\n</$select>\n\\end\n\n\\define backgroundimagesize-dropdown()\n<$select tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize\" default=\"scroll\">\n<option value=\"auto\"><<lingo Settings/BackgroundImageSize/Auto>></option>\n<option value=\"cover\"><<lingo Settings/BackgroundImageSize/Cover>></option>\n<option value=\"contain\"><<lingo Settings/BackgroundImageSize/Contain>></option>\n</$select>\n\\end\n\n<<lingo ThemeTweaks/Hint>>\n\n! <<lingo Options>>\n\n|<$link to=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\"><<lingo Options/SidebarLayout>></$link> |<$select tiddler=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\"><option value=\"fixed-fluid\"><<lingo Options/SidebarLayout/Fixed-Fluid>></option><option value=\"fluid-fixed\"><<lingo Options/SidebarLayout/Fluid-Fixed>></option></$select> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/options/stickytitles\"><<lingo Options/StickyTitles>></$link><br>//<<lingo Options/StickyTitles/Hint>>// |<$select tiddler=\"$:/themes/tiddlywiki/vanilla/options/stickytitles\"><option value=\"no\">{{$:/language/No}}</option><option value=\"yes\">{{$:/language/Yes}}</option></$select> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/options/codewrapping\"><<lingo Options/CodeWrapping>></$link> |<$select tiddler=\"$:/themes/tiddlywiki/vanilla/options/codewrapping\"><option value=\"pre\">{{$:/language/No}}</option><option value=\"pre-wrap\">{{$:/language/Yes}}</option></$select> |\n\n! <<lingo Settings>>\n\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/fontfamily\"><<lingo Settings/FontFamily>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/settings/fontfamily\" default=\"\" tag=\"input\"/> | |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/codefontfamily\"><<lingo Settings/CodeFontFamily>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/settings/codefontfamily\" default=\"\" tag=\"input\"/> | |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/editorfontfamily\"><<lingo Settings/EditorFontFamily>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/settings/editorfontfamily\" default=\"\" tag=\"input\"/> | |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\"><<lingo Settings/BackgroundImage>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\" default=\"\" tag=\"input\"/> |<<backgroundimage-dropdown>> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment\"><<lingo Settings/BackgroundImageAttachment>></$link> |<<backgroundimageattachment-dropdown>> | |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize\"><<lingo Settings/BackgroundImageSize>></$link> |<<backgroundimagesize-dropdown>> | |\n\n! <<lingo Metrics>>\n\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/fontsize\"><<lingo Metrics/FontSize>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/fontsize\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/lineheight\"><<lingo Metrics/LineHeight>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/lineheight\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize\"><<lingo Metrics/BodyFontSize>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/bodylineheight\"><<lingo Metrics/BodyLineHeight>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/bodylineheight\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storyleft\"><<lingo Metrics/StoryLeft>></$link><br>//<<lingo Metrics/StoryLeft/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storyleft\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storytop\"><<lingo Metrics/StoryTop>></$link><br>//<<lingo Metrics/StoryTop/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storytop\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storyright\"><<lingo Metrics/StoryRight>></$link><br>//<<lingo Metrics/StoryRight/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storyright\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storywidth\"><<lingo Metrics/StoryWidth>></$link><br>//<<lingo Metrics/StoryWidth/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storywidth\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth\"><<lingo Metrics/TiddlerWidth>></$link><br>//<<lingo Metrics/TiddlerWidth/Hint>>//<br> |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint\"><<lingo Metrics/SidebarBreakpoint>></$link><br>//<<lingo Metrics/SidebarBreakpoint/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth\"><<lingo Metrics/SidebarWidth>></$link><br>//<<lingo Metrics/SidebarWidth/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth\" default=\"\" tag=\"input\"/> |\n"
        },
        "$:/themes/tiddlywiki/vanilla/base": {
            "title": "$:/themes/tiddlywiki/vanilla/base",
            "tags": "[[$:/tags/Stylesheet]]",
            "text": "\\define custom-background-datauri()\n<$set name=\"background\" value={{$:/themes/tiddlywiki/vanilla/settings/backgroundimage}}>\n<$list filter=\"[<background>is[image]]\">\n`background: url(`\n<$list filter=\"[<background>!has[_canonical_uri]]\">\n`\"`<$macrocall $name=\"datauri\" title={{$:/themes/tiddlywiki/vanilla/settings/backgroundimage}}/>`\"`\n</$list>\n<$list filter=\"[<background>has[_canonical_uri]]\">\n`\"`<$view tiddler={{$:/themes/tiddlywiki/vanilla/settings/backgroundimage}} field=\"_canonical_uri\"/>`\"`\n</$list>\n`) center center;`\n`background-attachment: `{{$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment}}`;\n-webkit-background-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;\n-moz-background-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;\n-o-background-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;\nbackground-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;`\n</$list>\n</$set>\n\\end\n\n\\define if-fluid-fixed(text,hiddenSidebarText)\n<$reveal state=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\" type=\"match\" text=\"fluid-fixed\">\n$text$\n<$reveal state=\"$:/state/sidebar\" type=\"nomatch\" text=\"yes\" default=\"yes\">\n$hiddenSidebarText$\n</$reveal>\n</$reveal>\n\\end\n\n\\define if-editor-height-fixed(then,else)\n<$reveal state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"fixed\">\n$then$\n</$reveal>\n<$reveal state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"auto\">\n$else$\n</$reveal>\n\\end\n\n\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline macrocallblock\n\n/*\n** Start with the normalize CSS reset, and then belay some of its effects\n*/\n\n{{$:/themes/tiddlywiki/vanilla/reset}}\n\n*, input[type=\"search\"] {\n\tbox-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\t-webkit-box-sizing: border-box;\n}\n\nhtml button {\n\tline-height: 1.2;\n\tcolor: <<colour button-foreground>>;\n\tbackground: <<colour button-background>>;\n\tborder-color: <<colour button-border>>;\n}\n\n/*\n** Basic element styles\n*/\n\nhtml {\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/fontfamily}};\n\ttext-rendering: optimizeLegibility; /* Enables kerning and ligatures etc. */\n\t-webkit-font-smoothing: antialiased;\n\t-moz-osx-font-smoothing: grayscale;\n}\n\nhtml:-webkit-full-screen {\n\tbackground-color: <<colour page-background>>;\n}\n\nbody.tc-body {\n\tfont-size: {{$:/themes/tiddlywiki/vanilla/metrics/fontsize}};\n\tline-height: {{$:/themes/tiddlywiki/vanilla/metrics/lineheight}};\n\tword-wrap: break-word;\n\t<<custom-background-datauri>>\n\tcolor: <<colour foreground>>;\n\tbackground-color: <<colour page-background>>;\n\tfill: <<colour foreground>>;\n}\n\n<<if-background-attachment \"\"\"\n\nbody.tc-body {\n        background-color: transparent;\n}\n\n\"\"\">>\n\nh1, h2, h3, h4, h5, h6 {\n\tline-height: 1.2;\n\tfont-weight: 300;\n}\n\npre {\n\tdisplay: block;\n\tpadding: 14px;\n\tmargin-top: 1em;\n\tmargin-bottom: 1em;\n\tword-break: normal;\n\tword-wrap: break-word;\n\twhite-space: {{$:/themes/tiddlywiki/vanilla/options/codewrapping}};\n\tbackground-color: <<colour pre-background>>;\n\tborder: 1px solid <<colour pre-border>>;\n\tpadding: 0 3px 2px;\n\tborder-radius: 3px;\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/codefontfamily}};\n}\n\ncode {\n\tcolor: <<colour code-foreground>>;\n\tbackground-color: <<colour code-background>>;\n\tborder: 1px solid <<colour code-border>>;\n\twhite-space: {{$:/themes/tiddlywiki/vanilla/options/codewrapping}};\n\tpadding: 0 3px 2px;\n\tborder-radius: 3px;\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/codefontfamily}};\n}\n\nblockquote {\n\tborder-left: 5px solid <<colour blockquote-bar>>;\n\tmargin-left: 25px;\n\tpadding-left: 10px;\n\tquotes: \"\\201C\"\"\\201D\"\"\\2018\"\"\\2019\";\n}\n\nblockquote > div {\n\tmargin-top: 1em;\n\tmargin-bottom: 1em;\n}\n\nblockquote.tc-big-quote {\n\tfont-family: Georgia, serif;\n\tposition: relative;\n\tbackground: <<colour pre-background>>;\n\tborder-left: none;\n\tmargin-left: 50px;\n\tmargin-right: 50px;\n\tpadding: 10px;\n    border-radius: 8px;\n}\n\nblockquote.tc-big-quote cite:before {\n\tcontent: \"\\2014 \\2009\";\n}\n\nblockquote.tc-big-quote:before {\n\tfont-family: Georgia, serif;\n\tcolor: <<colour blockquote-bar>>;\n\tcontent: open-quote;\n\tfont-size: 8em;\n\tline-height: 0.1em;\n\tmargin-right: 0.25em;\n\tvertical-align: -0.4em;\n\tposition: absolute;\n    left: -50px;\n    top: 42px;\n}\n\nblockquote.tc-big-quote:after {\n\tfont-family: Georgia, serif;\n\tcolor: <<colour blockquote-bar>>;\n\tcontent: close-quote;\n\tfont-size: 8em;\n\tline-height: 0.1em;\n\tmargin-right: 0.25em;\n\tvertical-align: -0.4em;\n\tposition: absolute;\n    right: -80px;\n    bottom: -20px;\n}\n\ndl dt {\n\tfont-weight: bold;\n\tmargin-top: 6px;\n}\n\nbutton, textarea, input, select {\n\toutline-color: <<colour primary>>;\n}\n\ntextarea,\ninput[type=text],\ninput[type=search],\ninput[type=\"\"],\ninput:not([type]) {\n\tcolor: <<colour foreground>>;\n\tbackground: <<colour background>>;\n}\n\ninput[type=\"checkbox\"] {\n  vertical-align: middle;\n}\n\n.tc-muted {\n\tcolor: <<colour muted-foreground>>;\n}\n\nsvg.tc-image-button {\n\tpadding: 0px 1px 1px 0px;\n}\n\n.tc-icon-wrapper > svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\nkbd {\n\tdisplay: inline-block;\n\tpadding: 3px 5px;\n\tfont-size: 0.8em;\n\tline-height: 1.2;\n\tcolor: <<colour foreground>>;\n\tvertical-align: middle;\n\tbackground-color: <<colour background>>;\n\tborder: solid 1px <<colour muted-foreground>>;\n\tborder-bottom-color: <<colour muted-foreground>>;\n\tborder-radius: 3px;\n\tbox-shadow: inset 0 -1px 0 <<colour muted-foreground>>;\n}\n\n/*\nMarkdown likes putting code elements inside pre elements\n*/\npre > code {\n\tpadding: 0;\n\tborder: none;\n\tbackground-color: inherit;\n\tcolor: inherit;\n}\n\ntable {\n\tborder: 1px solid <<colour table-border>>;\n\twidth: auto;\n\tmax-width: 100%;\n\tcaption-side: bottom;\n\tmargin-top: 1em;\n\tmargin-bottom: 1em;\n\t/* next 2 elements needed, since normalize 8.0.1 */\n\tborder-collapse: collapse;\n\tborder-spacing: 0;\n}\n\ntable th, table td {\n\tpadding: 0 7px 0 7px;\n\tborder-top: 1px solid <<colour table-border>>;\n\tborder-left: 1px solid <<colour table-border>>;\n}\n\ntable thead tr td, table th {\n\tbackground-color: <<colour table-header-background>>;\n\tfont-weight: bold;\n}\n\ntable tfoot tr td {\n\tbackground-color: <<colour table-footer-background>>;\n}\n\n.tc-csv-table {\n\twhite-space: nowrap;\n}\n\n.tc-tiddler-frame img,\n.tc-tiddler-frame svg,\n.tc-tiddler-frame canvas,\n.tc-tiddler-frame embed,\n.tc-tiddler-frame iframe {\n\tmax-width: 100%;\n}\n\n.tc-tiddler-body > embed,\n.tc-tiddler-body > iframe {\n\twidth: 100%;\n\theight: 600px;\n}\n\n/*\n** Links\n*/\n\nbutton.tc-tiddlylink,\na.tc-tiddlylink {\n\ttext-decoration: none;\n\tfont-weight: 500;\n\tcolor: <<colour tiddler-link-foreground>>;\n\t-webkit-user-select: inherit; /* Otherwise the draggable attribute makes links impossible to select */\n}\n\n.tc-sidebar-lists a.tc-tiddlylink {\n\tcolor: <<colour sidebar-tiddler-link-foreground>>;\n}\n\n.tc-sidebar-lists a.tc-tiddlylink:hover {\n\tcolor: <<colour sidebar-tiddler-link-foreground-hover>>;\n}\n\nbutton.tc-tiddlylink:hover,\na.tc-tiddlylink:hover {\n\ttext-decoration: underline;\n}\n\na.tc-tiddlylink-resolves {\n}\n\na.tc-tiddlylink-shadow {\n\tfont-weight: bold;\n}\n\na.tc-tiddlylink-shadow.tc-tiddlylink-resolves {\n\tfont-weight: normal;\n}\n\na.tc-tiddlylink-missing {\n\tfont-style: italic;\n}\n\na.tc-tiddlylink-external {\n\ttext-decoration: underline;\n\tcolor: <<colour external-link-foreground>>;\n\tbackground-color: <<colour external-link-background>>;\n}\n\na.tc-tiddlylink-external:visited {\n\tcolor: <<colour external-link-foreground-visited>>;\n\tbackground-color: <<colour external-link-background-visited>>;\n}\n\na.tc-tiddlylink-external:hover {\n\tcolor: <<colour external-link-foreground-hover>>;\n\tbackground-color: <<colour external-link-background-hover>>;\n}\n\n/*\n** Drag and drop styles\n*/\n\n.tc-tiddler-dragger {\n\tposition: relative;\n\tz-index: -10000;\n}\n\n.tc-tiddler-dragger-inner {\n\tposition: absolute;\n\ttop: -1000px;\n\tleft: -1000px;\n\tdisplay: inline-block;\n\tpadding: 8px 20px;\n\tfont-size: 16.9px;\n\tfont-weight: bold;\n\tline-height: 20px;\n\tcolor: <<colour dragger-foreground>>;\n\ttext-shadow: 0 1px 0 rgba(0, 0, 0, 1);\n\twhite-space: nowrap;\n\tvertical-align: baseline;\n\tbackground-color: <<colour dragger-background>>;\n\tborder-radius: 20px;\n}\n\n.tc-tiddler-dragger-cover {\n\tposition: absolute;\n\tbackground-color: <<colour page-background>>;\n}\n\n.tc-dropzone {\n\tposition: relative;\n}\n\n.tc-dropzone.tc-dragover:before {\n\tz-index: 10000;\n\tdisplay: block;\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbackground: <<colour dropzone-background>>;\n\ttext-align: center;\n\tcontent: \"<<lingo DropMessage>>\";\n}\n\n.tc-droppable > .tc-droppable-placeholder {\n\tdisplay: none;\n}\n\n.tc-droppable.tc-dragover > .tc-droppable-placeholder {\n\tdisplay: block;\n\tborder: 2px dashed <<colour dropzone-background>>;\n}\n\n.tc-draggable {\n\tcursor: move;\n}\n\n.tc-sidebar-tab-open .tc-droppable-placeholder, .tc-tagged-draggable-list .tc-droppable-placeholder,\n.tc-links-draggable-list .tc-droppable-placeholder {\n\tline-height: 2em;\n\theight: 2em;\n}\n\n.tc-sidebar-tab-open-item {\n\tposition: relative;\n}\n\n.tc-sidebar-tab-open .tc-btn-invisible.tc-btn-mini svg {\n\tfont-size: 0.7em;\n\tfill: <<colour muted-foreground>>;\n}\n\n/*\n** Plugin reload warning\n*/\n\n.tc-plugin-reload-warning {\n\tz-index: 1000;\n\tdisplay: block;\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbackground: <<colour alert-background>>;\n\ttext-align: center;\n}\n\n/*\n** Buttons\n*/\n\nbutton svg, button img, label svg, label img {\n\tvertical-align: middle;\n}\n\n.tc-btn-invisible {\n\tpadding: 0;\n\tmargin: 0;\n\tbackground: none;\n\tborder: none;\n    \tcursor: pointer;\n\tcolor: <<colour foreground>>;\n}\n\n.tc-btn-boxed {\n\tfont-size: 0.6em;\n\tpadding: 0.2em;\n\tmargin: 1px;\n\tbackground: none;\n\tborder: 1px solid <<colour tiddler-controls-foreground>>;\n\tborder-radius: 0.25em;\n}\n\nhtml body.tc-body .tc-btn-boxed svg {\n\tfont-size: 1.6666em;\n}\n\n.tc-btn-boxed:hover {\n\tbackground: <<colour muted-foreground>>;\n\tcolor: <<colour background>>;\n}\n\nhtml body.tc-body .tc-btn-boxed:hover svg {\n\tfill: <<colour background>>;\n}\n\n.tc-btn-rounded {\n\tfont-size: 0.5em;\n\tline-height: 2;\n\tpadding: 0em 0.3em 0.2em 0.4em;\n\tmargin: 1px;\n\tborder: 1px solid <<colour muted-foreground>>;\n\tbackground: <<colour muted-foreground>>;\n\tcolor: <<colour background>>;\n\tborder-radius: 2em;\n}\n\nhtml body.tc-body .tc-btn-rounded svg {\n\tfont-size: 1.6666em;\n\tfill: <<colour background>>;\n}\n\n.tc-btn-rounded:hover {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tbackground: <<colour background>>;\n\tcolor: <<colour muted-foreground>>;\n}\n\nhtml body.tc-body .tc-btn-rounded:hover svg {\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-btn-icon svg {\n\theight: 1em;\n\twidth: 1em;\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-btn-text {\n\tpadding: 0;\n\tmargin: 0;\n}\n\n/* used for documentation \"fake\" buttons */\n.tc-btn-standard {\n\tline-height: 1.8;\n\tcolor: #667;\n\tbackground-color: #e0e0e0;\n\tborder: 1px solid #888;\n\tpadding: 2px 1px 2px 1px;\n\tmargin: 1px 4px 1px 4px;\n}\n\n.tc-btn-big-green {\n\tdisplay: inline-block;\n\tpadding: 8px;\n\tmargin: 4px 8px 4px 8px;\n\tbackground: <<colour download-background>>;\n\tcolor: <<colour download-foreground>>;\n\tfill: <<colour download-foreground>>;\n\tborder: none;\n\tborder-radius: 2px;\n\tfont-size: 1.2em;\n\tline-height: 1.4em;\n\ttext-decoration: none;\n}\n\n.tc-btn-big-green svg,\n.tc-btn-big-green img {\n\theight: 2em;\n\twidth: 2em;\n\tvertical-align: middle;\n\tfill: <<colour download-foreground>>;\n}\n\n.tc-primary-btn {\n \tbackground: <<colour primary>>;\n}\n\n.tc-sidebar-lists input {\n\tcolor: <<colour foreground>>;\n}\n\n.tc-sidebar-lists button {\n\tcolor: <<colour sidebar-button-foreground>>;\n\tfill: <<colour sidebar-button-foreground>>;\n}\n\n.tc-sidebar-lists button.tc-btn-mini {\n\tcolor: <<colour sidebar-muted-foreground>>;\n}\n\n.tc-sidebar-lists button.tc-btn-mini:hover {\n\tcolor: <<colour sidebar-muted-foreground-hover>>;\n}\n\nbutton svg.tc-image-button, button .tc-image-button img {\n\theight: 1em;\n\twidth: 1em;\n}\n\n.tc-unfold-banner {\n\tposition: absolute;\n\tpadding: 0;\n\tmargin: 0;\n\tbackground: none;\n\tborder: none;\n\twidth: 100%;\n\twidth: calc(100% + 2px);\n\tmargin-left: -43px;\n\ttext-align: center;\n\tborder-top: 2px solid <<colour tiddler-info-background>>;\n\tmargin-top: 4px;\n}\n\n.tc-unfold-banner:hover {\n\tbackground: <<colour tiddler-info-background>>;\n\tborder-top: 2px solid <<colour tiddler-info-border>>;\n}\n\n.tc-unfold-banner svg, .tc-fold-banner svg {\n\theight: 0.75em;\n\tfill: <<colour tiddler-controls-foreground>>;\n}\n\n.tc-unfold-banner:hover svg, .tc-fold-banner:hover svg {\n\tfill: <<colour tiddler-controls-foreground-hover>>;\n}\n\n.tc-fold-banner {\n\tposition: absolute;\n\tpadding: 0;\n\tmargin: 0;\n\tbackground: none;\n\tborder: none;\n\twidth: 23px;\n\ttext-align: center;\n\tmargin-left: -35px;\n\ttop: 6px;\n\tbottom: 6px;\n}\n\n.tc-fold-banner:hover {\n\tbackground: <<colour tiddler-info-background>>;\n}\n\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\t.tc-unfold-banner {\n\t\tposition: static;\n\t\twidth: calc(100% + 59px);\n\t}\n\n\t.tc-fold-banner {\n\t\twidth: 16px;\n\t\tmargin-left: -16px;\n\t\tfont-size: 0.75em;\n\t}\n\n}\n\n/*\n** Tags and missing tiddlers\n*/\n\n.tc-tag-list-item {\n\tposition: relative;\n\tdisplay: inline-block;\n\tmargin-right: 7px;\n}\n\n.tc-tags-wrapper {\n\tmargin: 4px 0 14px 0;\n}\n\n.tc-missing-tiddler-label {\n\tfont-style: italic;\n\tfont-weight: normal;\n\tdisplay: inline-block;\n\tfont-size: 11.844px;\n\tline-height: 14px;\n\twhite-space: nowrap;\n\tvertical-align: baseline;\n}\n\nbutton.tc-tag-label, span.tc-tag-label {\n\tdisplay: inline-block;\n\tpadding: 0.16em 0.7em;\n\tfont-size: 0.9em;\n\tfont-weight: 400;\n\tline-height: 1.2em;\n\tcolor: <<colour tag-foreground>>;\n\twhite-space: nowrap;\n\tvertical-align: baseline;\n\tbackground-color: <<colour tag-background>>;\n\tborder-radius: 1em;\n}\n\n.tc-sidebar-scrollable .tc-tag-label {\n\ttext-shadow: none;\n}\n\n.tc-untagged-separator {\n\twidth: 10em;\n\tleft: 0;\n\tmargin-left: 0;\n\tborder: 0;\n\theight: 1px;\n\tbackground: <<colour tab-divider>>;\n}\n\nbutton.tc-untagged-label {\n\tbackground-color: <<colour untagged-background>>;\n}\n\n.tc-tag-label svg, .tc-tag-label img {\n\theight: 1em;\n\twidth: 1em;\n\tmargin-right: 3px; \n\tmargin-bottom: 1px;\n\tvertical-align: text-bottom;\n}\n\n.tc-edit-tags button.tc-remove-tag-button svg {\n\tfont-size: 0.7em;\n\tvertical-align: middle;\n}\n\n.tc-tag-manager-table .tc-tag-label {\n\twhite-space: normal;\n}\n\n.tc-tag-manager-tag {\n\twidth: 100%;\n}\n\nbutton.tc-btn-invisible.tc-remove-tag-button {\n\toutline: none;\n}\n\n/*\n** Page layout\n*/\n\n.tc-topbar {\n\tposition: fixed;\n\tz-index: 1200;\n}\n\n.tc-topbar-left {\n\tleft: 29px;\n\ttop: 5px;\n}\n\n.tc-topbar-right {\n\ttop: 5px;\n\tright: 29px;\n}\n\n.tc-topbar button {\n\tpadding: 8px;\n}\n\n.tc-topbar svg {\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-topbar button:hover svg {\n\tfill: <<colour foreground>>;\n}\n\n.tc-sidebar-header {\n\tcolor: <<colour sidebar-foreground>>;\n\tfill: <<colour sidebar-foreground>>;\n}\n\n.tc-sidebar-header .tc-title a.tc-tiddlylink-resolves {\n\tfont-weight: 300;\n}\n\n.tc-sidebar-header .tc-sidebar-lists p {\n\tmargin-top: 3px;\n\tmargin-bottom: 3px;\n}\n\n.tc-sidebar-header .tc-missing-tiddler-label {\n\tcolor: <<colour sidebar-foreground>>;\n}\n\n.tc-advanced-search input {\n\twidth: 60%;\n}\n\n.tc-search a svg {\n\twidth: 1.2em;\n\theight: 1.2em;\n\tvertical-align: middle;\n}\n\n.tc-page-controls {\n\tmargin-top: 14px;\n\tfont-size: 1.5em;\n}\n\n.tc-page-controls .tc-drop-down {\n  font-size: 1rem;\n}\n\n.tc-page-controls button {\n\tmargin-right: 0.5em;\n}\n\n.tc-page-controls a.tc-tiddlylink:hover {\n\ttext-decoration: none;\n}\n\n.tc-page-controls img {\n\twidth: 1em;\n}\n\n.tc-page-controls svg {\n\tfill: <<colour sidebar-controls-foreground>>;\n}\n\n.tc-page-controls button:hover svg, .tc-page-controls a:hover svg {\n\tfill: <<colour sidebar-controls-foreground-hover>>;\n}\n\n.tc-menu-list-item {\n\twhite-space: nowrap;\n}\n\n.tc-menu-list-count {\n\tfont-weight: bold;\n}\n\n.tc-menu-list-subitem {\n\tpadding-left: 7px;\n}\n\n.tc-story-river {\n\tposition: relative;\n}\n\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\t.tc-sidebar-header {\n\t\tpadding: 14px;\n\t\tmin-height: 32px;\n\t\tmargin-top: {{$:/themes/tiddlywiki/vanilla/metrics/storytop}};\n\t}\n\n\t.tc-story-river {\n\t\tposition: relative;\n\t\tpadding: 0;\n\t}\n}\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\t.tc-message-box {\n\t\tmargin: 21px -21px 21px -21px;\n\t}\n\n\t.tc-sidebar-scrollable {\n\t\tposition: fixed;\n\t\ttop: {{$:/themes/tiddlywiki/vanilla/metrics/storytop}};\n\t\tleft: {{$:/themes/tiddlywiki/vanilla/metrics/storyright}};\n\t\tbottom: 0;\n\t\tright: 0;\n\t\toverflow-y: auto;\n\t\toverflow-x: auto;\n\t\t-webkit-overflow-scrolling: touch;\n\t\tmargin: 0 0 0 -42px;\n\t\tpadding: 71px 0 28px 42px;\n\t}\n\n\thtml[dir=\"rtl\"] .tc-sidebar-scrollable {\n\t\tleft: auto;\n\t\tright: {{$:/themes/tiddlywiki/vanilla/metrics/storyright}};\n\t}\n\n\t.tc-story-river {\n\t\tposition: relative;\n\t\tleft: {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}};\n\t\ttop: {{$:/themes/tiddlywiki/vanilla/metrics/storytop}};\n\t\twidth: {{$:/themes/tiddlywiki/vanilla/metrics/storywidth}};\n\t\tpadding: 42px 42px 42px 42px;\n\t}\n\n<<if-no-sidebar \"\n\n\t.tc-story-river {\n\t\twidth: calc(100% - {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}});\n\t}\n\n\">>\n\n}\n\n@media print {\n\n\tbody.tc-body {\n\t\tbackground-color: transparent;\n\t}\n\n\t.tc-sidebar-header, .tc-topbar {\n\t\tdisplay: none;\n\t}\n\n\t.tc-story-river {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t}\n\n\t.tc-story-river .tc-tiddler-frame {\n\t\tmargin: 0;\n\t\tborder: none;\n\t\tpadding: 0;\n\t}\n}\n\n/*\n** Tiddler styles\n*/\n\n.tc-tiddler-frame {\n\tposition: relative;\n\tmargin-bottom: 28px;\n\tbackground-color: <<colour tiddler-background>>;\n\tborder: 1px solid <<colour tiddler-border>>;\n}\n\n{{$:/themes/tiddlywiki/vanilla/sticky}}\n\n.tc-tiddler-info {\n\tpadding: 14px 42px 14px 42px;\n\tbackground-color: <<colour tiddler-info-background>>;\n\tborder-top: 1px solid <<colour tiddler-info-border>>;\n\tborder-bottom: 1px solid <<colour tiddler-info-border>>;\n}\n\n.tc-tiddler-info p {\n\tmargin-top: 3px;\n\tmargin-bottom: 3px;\n}\n\n.tc-tiddler-info .tc-tab-buttons button.tc-tab-selected {\n\tbackground-color: <<colour tiddler-info-tab-background>>;\n\tborder-bottom: 1px solid <<colour tiddler-info-tab-background>>;\n}\n\n.tc-view-field-table {\n\twidth: 100%;\n}\n\n.tc-view-field-name {\n\twidth: 1%; /* Makes this column be as narrow as possible */\n\ttext-align: right;\n\tfont-style: italic;\n\tfont-weight: 200;\n}\n\n.tc-view-field-value {\n}\n\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\t.tc-tiddler-frame {\n\t\tpadding: 14px 14px 14px 14px;\n\t}\n\n\t.tc-tiddler-info {\n\t\tmargin: 0 -14px 0 -14px;\n\t}\n}\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\t.tc-tiddler-frame {\n\t\tpadding: 28px 42px 42px 42px;\n\t\twidth: {{$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth}};\n\t\tborder-radius: 2px;\n\t}\n\n<<if-no-sidebar \"\n\n\t.tc-tiddler-frame {\n\t\twidth: 100%;\n\t}\n\n\">>\n\n\t.tc-tiddler-info {\n\t\tmargin: 0 -42px 0 -42px;\n\t}\n}\n\n.tc-site-title,\n.tc-titlebar {\n\tfont-weight: 300;\n\tfont-size: 2.35em;\n\tline-height: 1.2em;\n\tcolor: <<colour tiddler-title-foreground>>;\n\tmargin: 0;\n}\n\n.tc-site-title {\n\tcolor: <<colour site-title-foreground>>;\n}\n\n.tc-tiddler-title-icon {\n\tvertical-align: middle;\n\tmargin-right: .1em;\n}\n\n.tc-system-title-prefix {\n\tcolor: <<colour muted-foreground>>;\n}\n\n.tc-titlebar h2 {\n\tfont-size: 1em;\n\tdisplay: inline;\n}\n\n.tc-titlebar img {\n\theight: 1em;\n}\n\n.tc-subtitle {\n\tfont-size: 0.9em;\n\tcolor: <<colour tiddler-subtitle-foreground>>;\n\tfont-weight: 300;\n}\n\n.tc-subtitle .tc-tiddlylink {\n\tmargin-right: .3em;\n}\n\n.tc-tiddler-missing .tc-title {\n  font-style: italic;\n  font-weight: normal;\n}\n\n.tc-tiddler-frame .tc-tiddler-controls {\n\tfloat: right;\n}\n\n.tc-tiddler-controls .tc-drop-down {\n\tfont-size: 0.6em;\n}\n\n.tc-tiddler-controls .tc-drop-down .tc-drop-down {\n\tfont-size: 1em;\n}\n\n.tc-tiddler-controls > span > button,\n.tc-tiddler-controls > span > span > button,\n.tc-tiddler-controls > span > span > span > button {\n\tvertical-align: baseline;\n\tmargin-left:5px;\n}\n\n.tc-tiddler-controls button svg, .tc-tiddler-controls button img,\n.tc-search button svg, .tc-search a svg {\n\tfill: <<colour tiddler-controls-foreground>>;\n}\n\n.tc-tiddler-controls button svg, .tc-tiddler-controls button img {\n\theight: 0.75em;\n}\n\n.tc-search button svg, .tc-search a svg {\n    height: 1.2em;\n    width: 1.2em;\n    margin: 0 0.25em;\n}\n\n.tc-tiddler-controls button.tc-selected svg,\n.tc-page-controls button.tc-selected svg  {\n\tfill: <<colour tiddler-controls-foreground-selected>>;\n}\n\n.tc-tiddler-controls button.tc-btn-invisible:hover svg,\n.tc-search button:hover svg, .tc-search a:hover svg {\n\tfill: <<colour tiddler-controls-foreground-hover>>;\n}\n\n@media print {\n\t.tc-tiddler-controls {\n\t\tdisplay: none;\n\t}\n}\n\n.tc-tiddler-help { /* Help prompts within tiddler template */\n\tcolor: <<colour muted-foreground>>;\n\tmargin-top: 14px;\n}\n\n.tc-tiddler-help a.tc-tiddlylink {\n\tcolor: <<colour very-muted-foreground>>;\n}\n\n.tc-tiddler-frame .tc-edit-texteditor {\n\twidth: 100%;\n\tmargin: 4px 0 4px 0;\n}\n\n.tc-tiddler-frame input.tc-edit-texteditor,\n.tc-tiddler-frame textarea.tc-edit-texteditor,\n.tc-tiddler-frame iframe.tc-edit-texteditor {\n\tpadding: 3px 3px 3px 3px;\n\tborder: 1px solid <<colour tiddler-editor-border>>;\n\tbackground-color: <<colour tiddler-editor-background>>;\n\tline-height: 1.3em;\n\t-webkit-appearance: none;\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/editorfontfamily}};\n}\n\n.tc-tiddler-frame .tc-binary-warning {\n\twidth: 100%;\n\theight: 5em;\n\ttext-align: center;\n\tpadding: 3em 3em 6em 3em;\n\tbackground: <<colour alert-background>>;\n\tborder: 1px solid <<colour alert-border>>;\n}\n\ncanvas.tc-edit-bitmapeditor  {\n\tborder: 6px solid <<colour tiddler-editor-border-image>>;\n\tcursor: crosshair;\n\t-moz-user-select: none;\n\t-webkit-user-select: none;\n\t-ms-user-select: none;\n\tmargin-top: 6px;\n\tmargin-bottom: 6px;\n}\n\n.tc-edit-bitmapeditor-width {\n\tdisplay: block;\n}\n\n.tc-edit-bitmapeditor-height {\n\tdisplay: block;\n}\n\n.tc-tiddler-body {\n\tclear: both;\n}\n\n.tc-tiddler-frame .tc-tiddler-body {\n\tfont-size: {{$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize}};\n\tline-height: {{$:/themes/tiddlywiki/vanilla/metrics/bodylineheight}};\n}\n\n.tc-titlebar, .tc-tiddler-edit-title {\n\toverflow: hidden; /* https://github.com/Jermolene/TiddlyWiki5/issues/282 */\n}\n\nhtml body.tc-body.tc-single-tiddler-window {\n\tmargin: 1em;\n\tbackground: <<colour tiddler-background>>;\n}\n\n.tc-single-tiddler-window img,\n.tc-single-tiddler-window svg,\n.tc-single-tiddler-window canvas,\n.tc-single-tiddler-window embed,\n.tc-single-tiddler-window iframe {\n\tmax-width: 100%;\n}\n\n/*\n** Editor\n*/\n\n.tc-editor-toolbar {\n\tmargin-top: 8px;\n}\n\n.tc-editor-toolbar button {\n\tvertical-align: middle;\n\tbackground-color: <<colour tiddler-controls-foreground>>;\n\tcolor: <<colour tiddler-controls-foreground-selected>>;\n\tfill: <<colour tiddler-controls-foreground-selected>>;\n\tborder-radius: 4px;\n\tpadding: 3px;\n\tmargin: 2px 0 2px 4px;\n}\n\n.tc-editor-toolbar button.tc-text-editor-toolbar-item-adjunct {\n\tmargin-left: 1px;\n\twidth: 1em;\n\tborder-radius: 8px;\n}\n\n.tc-editor-toolbar button.tc-text-editor-toolbar-item-start-group {\n\tmargin-left: 11px;\n}\n\n.tc-editor-toolbar button.tc-selected {\n\tbackground-color: <<colour primary>>;\n}\n\n.tc-editor-toolbar button svg {\n\twidth: 1.6em;\n\theight: 1.2em;\n}\n\n.tc-editor-toolbar button:hover {\n\tbackground-color: <<colour tiddler-controls-foreground-selected>>;\n\tfill: <<colour background>>;\n\tcolor: <<colour background>>;\n}\n\n.tc-editor-toolbar .tc-text-editor-toolbar-more {\n\twhite-space: normal;\n}\n\n.tc-editor-toolbar .tc-text-editor-toolbar-more button {\n\tdisplay: inline-block;\n\tpadding: 3px;\n\twidth: auto;\n}\n\n.tc-editor-toolbar .tc-search-results {\n\tpadding: 0;\n}\n\n/*\n** Adjustments for fluid-fixed mode\n*/\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n<<if-fluid-fixed text:\"\"\"\n\n\t.tc-story-river {\n\t\tpadding-right: 0;\n\t\tposition: relative;\n\t\twidth: auto;\n\t\tleft: 0;\n\t\tmargin-left: {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}};\n\t\tmargin-right: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}};\n\t}\n\n\t.tc-tiddler-frame {\n\t\twidth: 100%;\n\t}\n\n\t.tc-sidebar-scrollable {\n\t\tleft: auto;\n\t\tbottom: 0;\n\t\tright: 0;\n\t\twidth: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}};\n\t}\n\n\tbody.tc-body .tc-storyview-zoomin-tiddler {\n\t\twidth: 100%;\n\t\twidth: calc(100% - 42px);\n\t}\n\n\"\"\" hiddenSidebarText:\"\"\"\n\n\t.tc-story-river {\n\t\tpadding-right: 3em;\n\t\tmargin-right: 0;\n\t}\n\n\tbody.tc-body .tc-storyview-zoomin-tiddler {\n\t\twidth: 100%;\n\t\twidth: calc(100% - 84px);\n\t}\n\n\"\"\">>\n\n}\n\n/*\n** Toolbar buttons\n*/\n\n.tc-page-controls svg.tc-image-new-button {\n  fill: <<colour toolbar-new-button>>;\n}\n\n.tc-page-controls svg.tc-image-options-button {\n  fill: <<colour toolbar-options-button>>;\n}\n\n.tc-page-controls svg.tc-image-save-button {\n  fill: <<colour toolbar-save-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-info-button {\n  fill: <<colour toolbar-info-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-edit-button {\n  fill: <<colour toolbar-edit-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-close-button {\n  fill: <<colour toolbar-close-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-delete-button {\n  fill: <<colour toolbar-delete-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-cancel-button {\n  fill: <<colour toolbar-cancel-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-done-button {\n  fill: <<colour toolbar-done-button>>;\n}\n\n/*\n** Tiddler edit mode\n*/\n\n.tc-tiddler-edit-frame em.tc-edit {\n\tcolor: <<colour muted-foreground>>;\n\tfont-style: normal;\n}\n\n.tc-edit-type-dropdown a.tc-tiddlylink-missing {\n\tfont-style: normal;\n}\n\n.tc-type-selector .tc-edit-typeeditor {\n\twidth: 20%;\n}\n\n.tc-edit-tags {\n\tborder: 1px solid <<colour tiddler-editor-border>>;\n\tpadding: 4px 8px 4px 8px;\n}\n\n.tc-edit-add-tag {\n\tdisplay: inline-block;\n}\n\n.tc-edit-add-tag .tc-add-tag-name input {\n\twidth: 50%;\n}\n\n.tc-edit-add-tag .tc-keyboard {\n\tdisplay:inline;\n}\n\n.tc-edit-tags .tc-tag-label {\n\tdisplay: inline-block;\n}\n\n.tc-edit-tags-list {\n\tmargin: 14px 0 14px 0;\n}\n\n.tc-remove-tag-button {\n\tpadding-left: 4px;\n}\n\n.tc-tiddler-preview {\n\toverflow: auto;\n}\n\n.tc-tiddler-preview-preview {\n\tfloat: right;\n\twidth: 49%;\n\tborder: 1px solid <<colour tiddler-editor-border>>;\n\tmargin: 4px 0 3px 3px;\n\tpadding: 3px 3px 3px 3px;\n}\n\n<<if-editor-height-fixed then:\"\"\"\n\n.tc-tiddler-preview-preview {\n\toverflow-y: scroll;\n\theight: {{$:/config/TextEditor/EditorHeight/Height}};\n}\n\n\"\"\">>\n\n.tc-tiddler-frame .tc-tiddler-preview .tc-edit-texteditor {\n\twidth: 49%;\n}\n\n.tc-tiddler-frame .tc-tiddler-preview canvas.tc-edit-bitmapeditor {\n\tmax-width: 49%;\n}\n\n.tc-edit-fields {\n\twidth: 100%;\n}\n\n\n.tc-edit-fields table, .tc-edit-fields tr, .tc-edit-fields td {\n\tborder: none;\n\tpadding: 4px;\n}\n\n.tc-edit-fields > tbody > .tc-edit-field:nth-child(odd) {\n\tbackground-color: <<colour tiddler-editor-fields-odd>>;\n}\n\n.tc-edit-fields > tbody > .tc-edit-field:nth-child(even) {\n\tbackground-color: <<colour tiddler-editor-fields-even>>;\n}\n\n.tc-edit-field-name {\n\ttext-align: right;\n}\n\n.tc-edit-field-value input {\n\twidth: 100%;\n}\n\n.tc-edit-field-remove {\n}\n\n.tc-edit-field-remove svg {\n\theight: 1em;\n\twidth: 1em;\n\tfill: <<colour muted-foreground>>;\n\tvertical-align: middle;\n}\n\n.tc-edit-field-add-name {\n\tdisplay: inline-block;\n\twidth: 15%;\n}\n\n.tc-edit-field-add-value {\n\tdisplay: inline-block;\n\twidth: 40%;\n}\n\n.tc-edit-field-add-button {\n\tdisplay: inline-block;\n\twidth: 10%;\n}\n\n/*\n** Storyview Classes\n*/\n\n.tc-viewswitcher .tc-image-button {\n\tmargin-right: .3em;\n}\n\n.tc-storyview-zoomin-tiddler {\n\tposition: absolute;\n\tdisplay: block;\n\twidth: 100%;\n}\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\t.tc-storyview-zoomin-tiddler {\n\t\twidth: calc(100% - 84px);\n\t}\n\n}\n\n/*\n** Dropdowns\n*/\n\n.tc-btn-dropdown {\n\ttext-align: left;\n}\n\n.tc-btn-dropdown svg, .tc-btn-dropdown img {\n\theight: 1em;\n\twidth: 1em;\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-drop-down-wrapper {\n\tposition: relative;\n}\n\n.tc-drop-down {\n\tmin-width: 380px;\n\tborder: 1px solid <<colour dropdown-border>>;\n\tbackground-color: <<colour dropdown-background>>;\n\tpadding: 7px 0 7px 0;\n\tmargin: 4px 0 0 0;\n\twhite-space: nowrap;\n\ttext-shadow: none;\n\tline-height: 1.4;\n}\n\n.tc-drop-down .tc-drop-down {\n\tmargin-left: 14px;\n}\n\n.tc-drop-down button svg, .tc-drop-down a svg  {\n\tfill: <<colour foreground>>;\n}\n\n.tc-drop-down button.tc-btn-invisible:hover svg {\n\tfill: <<colour foreground>>;\n}\n\n.tc-drop-down .tc-drop-down-info {\n\tpadding-left: 14px;\n}\n\n.tc-drop-down p {\n\tpadding: 0 14px 0 14px;\n}\n\n.tc-drop-down svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\n.tc-drop-down img {\n\twidth: 1em;\n}\n\n.tc-drop-down a, .tc-drop-down button {\n\tdisplay: block;\n\tpadding: 0 14px 0 14px;\n\twidth: 100%;\n\ttext-align: left;\n\tcolor: <<colour foreground>>;\n\tline-height: 1.4;\n}\n\n.tc-drop-down .tc-tab-set .tc-tab-buttons button {\n\tdisplay: inline-block;\n    width: auto;\n    margin-bottom: 0px;\n    border-bottom-left-radius: 0;\n    border-bottom-right-radius: 0;\n}\n\n.tc-drop-down .tc-prompt {\n\tpadding: 0 14px;\n}\n\n.tc-drop-down .tc-chooser {\n\tborder: none;\n}\n\n.tc-drop-down .tc-chooser .tc-swatches-horiz {\n\tfont-size: 0.4em;\n\tpadding-left: 1.2em;\n}\n\n.tc-drop-down .tc-file-input-wrapper {\n\twidth: 100%;\n}\n\n.tc-drop-down .tc-file-input-wrapper button {\n\tcolor: <<colour foreground>>;\n}\n\n.tc-drop-down a:hover, .tc-drop-down button:hover, .tc-drop-down .tc-file-input-wrapper:hover button {\n\tcolor: <<colour tiddler-link-background>>;\n\tbackground-color: <<colour tiddler-link-foreground>>;\n\ttext-decoration: none;\n}\n\n.tc-drop-down .tc-tab-buttons button {\n\tbackground-color: <<colour dropdown-tab-background>>;\n}\n\n.tc-drop-down .tc-tab-buttons button.tc-tab-selected {\n\tbackground-color: <<colour dropdown-tab-background-selected>>;\n\tborder-bottom: 1px solid <<colour dropdown-tab-background-selected>>;\n}\n\n.tc-drop-down-bullet {\n\tdisplay: inline-block;\n\twidth: 0.5em;\n}\n\n.tc-drop-down .tc-tab-contents a {\n\tpadding: 0 0.5em 0 0.5em;\n}\n\n.tc-block-dropdown-wrapper {\n\tposition: relative;\n}\n\n.tc-block-dropdown {\n\tposition: absolute;\n\tmin-width: 220px;\n\tborder: 1px solid <<colour dropdown-border>>;\n\tbackground-color: <<colour dropdown-background>>;\n\tpadding: 7px 0;\n\tmargin: 4px 0 0 0;\n\twhite-space: nowrap;\n\tz-index: 1000;\n\ttext-shadow: none;\n}\n\n.tc-block-dropdown.tc-search-drop-down {\n\tmargin-left: -12px;\n}\n\n.tc-block-dropdown a {\n\tdisplay: block;\n\tpadding: 4px 14px 4px 14px;\n}\n\n.tc-block-dropdown.tc-search-drop-down a {\n\tdisplay: block;\n\tpadding: 0px 10px 0px 10px;\n}\n\n.tc-drop-down .tc-dropdown-item-plain,\n.tc-block-dropdown .tc-dropdown-item-plain {\n\tpadding: 4px 14px 4px 7px;\n}\n\n.tc-drop-down .tc-dropdown-item,\n.tc-block-dropdown .tc-dropdown-item {\n\tpadding: 4px 14px 4px 7px;\n\tcolor: <<colour muted-foreground>>;\n}\n\n.tc-block-dropdown a:hover {\n\tcolor: <<colour tiddler-link-background>>;\n\tbackground-color: <<colour tiddler-link-foreground>>;\n\ttext-decoration: none;\n}\n\n.tc-search-results {\n\tpadding: 0 7px 0 7px;\n}\n\n.tc-image-chooser, .tc-colour-chooser {\n\twhite-space: normal;\n}\n\n.tc-image-chooser a,\n.tc-colour-chooser a {\n\tdisplay: inline-block;\n\tvertical-align: top;\n\ttext-align: center;\n\tposition: relative;\n}\n\n.tc-image-chooser a {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tpadding: 2px;\n\tmargin: 2px;\n\twidth: 4em;\n\theight: 4em;\n}\n\n.tc-colour-chooser a {\n\tpadding: 3px;\n\twidth: 2em;\n\theight: 2em;\n\tvertical-align: middle;\n}\n\n.tc-image-chooser a:hover,\n.tc-colour-chooser a:hover {\n\tbackground: <<colour primary>>;\n\tpadding: 0px;\n\tborder: 3px solid <<colour primary>>;\n}\n\n.tc-image-chooser a svg,\n.tc-image-chooser a img {\n\tdisplay: inline-block;\n\twidth: auto;\n\theight: auto;\n\tmax-width: 3.5em;\n\tmax-height: 3.5em;\n\tposition: absolute;\n\ttop: 0;\n\tbottom: 0;\n\tleft: 0;\n\tright: 0;\n\tmargin: auto;\n}\n\n/*\n** Modals\n*/\n\n.tc-modal-wrapper {\n\tposition: fixed;\n\toverflow: auto;\n\toverflow-y: scroll;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\tleft: 0;\n\tz-index: 900;\n}\n\n.tc-modal-backdrop {\n\tposition: fixed;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\tleft: 0;\n\tz-index: 1000;\n\tbackground-color: <<colour modal-backdrop>>;\n}\n\n.tc-modal {\n\tz-index: 1100;\n\tbackground-color: <<colour modal-background>>;\n\tborder: 1px solid <<colour modal-border>>;\n}\n\n@media (max-width: 55em) {\n\t.tc-modal {\n\t\tposition: fixed;\n\t\ttop: 1em;\n\t\tleft: 1em;\n\t\tright: 1em;\n\t}\n\n\t.tc-modal-body {\n\t\toverflow-y: auto;\n\t\tmax-height: 400px;\n\t\tmax-height: 60vh;\n\t}\n}\n\n@media (min-width: 55em) {\n\t.tc-modal {\n\t\tposition: fixed;\n\t\ttop: 2em;\n\t\tleft: 25%;\n\t\twidth: 50%;\n\t}\n\n\t.tc-modal-body {\n\t\toverflow-y: auto;\n\t\tmax-height: 400px;\n\t\tmax-height: 60vh;\n\t}\n}\n\n.tc-modal-header {\n\tpadding: 9px 15px;\n\tborder-bottom: 1px solid <<colour modal-header-border>>;\n}\n\n.tc-modal-header h3 {\n\tmargin: 0;\n\tline-height: 30px;\n}\n\n.tc-modal-header img, .tc-modal-header svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\n.tc-modal-body {\n\tpadding: 15px;\n}\n\n.tc-modal-footer {\n\tpadding: 14px 15px 15px;\n\tmargin-bottom: 0;\n\ttext-align: right;\n\tbackground-color: <<colour modal-footer-background>>;\n\tborder-top: 1px solid <<colour modal-footer-border>>;\n}\n\n/*\n** Notifications\n*/\n\n.tc-notification {\n\tposition: fixed;\n\ttop: 14px;\n\tright: 42px;\n\tz-index: 1300;\n\tmax-width: 280px;\n\tpadding: 0 14px 0 14px;\n\tbackground-color: <<colour notification-background>>;\n\tborder: 1px solid <<colour notification-border>>;\n}\n\n/*\n** Tabs\n*/\n\n.tc-tab-set.tc-vertical {\n\tdisplay: -webkit-flex;\n\tdisplay: flex;\n}\n\n.tc-tab-buttons {\n\tfont-size: 0.85em;\n\tpadding-top: 1em;\n\tmargin-bottom: -2px;\n}\n\n.tc-tab-buttons.tc-vertical  {\n\tz-index: 100;\n\tdisplay: block;\n\tpadding-top: 14px;\n\tvertical-align: top;\n\ttext-align: right;\n\tmargin-bottom: inherit;\n\tmargin-right: -1px;\n\tmax-width: 33%;\n\t-webkit-flex: 0 0 auto;\n\tflex: 0 0 auto;\n}\n\n.tc-tab-buttons button.tc-tab-selected {\n\tcolor: <<colour tab-foreground-selected>>;\n\tbackground-color: <<colour tab-background-selected>>;\n\tborder-left: 1px solid <<colour tab-border-selected>>;\n\tborder-top: 1px solid <<colour tab-border-selected>>;\n\tborder-right: 1px solid <<colour tab-border-selected>>;\n}\n\n.tc-tab-buttons button {\n\tcolor: <<colour tab-foreground>>;\n\tpadding: 3px 5px 3px 5px;\n\tmargin-right: 0.3em;\n\tfont-weight: 300;\n\tborder: none;\n\tbackground: inherit;\n\tbackground-color: <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-right: 1px solid <<colour tab-border>>;\n\tborder-top-left-radius: 2px;\n\tborder-top-right-radius: 2px;\n\tborder-bottom-left-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n\n.tc-tab-buttons.tc-vertical button {\n\tdisplay: block;\n\twidth: 100%;\n\tmargin-top: 3px;\n\tmargin-right: 0;\n\ttext-align: right;\n\tbackground-color: <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n\tborder-right: none;\n\tborder-top-left-radius: 2px;\n\tborder-bottom-left-radius: 2px;\n\tborder-top-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n\n.tc-tab-buttons.tc-vertical button.tc-tab-selected {\n\tbackground-color: <<colour tab-background-selected>>;\n\tborder-right: 1px solid <<colour tab-background-selected>>;\n}\n\n.tc-tab-divider {\n\tborder-top: 1px solid <<colour tab-divider>>;\n}\n\n.tc-tab-divider.tc-vertical  {\n\tdisplay: none;\n}\n\n.tc-tab-content {\n\tmargin-top: 14px;\n}\n\n.tc-tab-content.tc-vertical  {\n\tdisplay: inline-block;\n\tvertical-align: top;\n\tpadding-top: 0;\n\tpadding-left: 14px;\n\tborder-left: 1px solid <<colour tab-border>>;\n\t-webkit-flex: 1 0 70%;\n\tflex: 1 0 70%;\n\toverflow: auto;\n}\n\n.tc-sidebar-lists .tc-tab-buttons {\n\tmargin-bottom: -1px;\n}\n\n.tc-sidebar-lists .tc-tab-buttons button.tc-tab-selected {\n\tbackground-color: <<colour sidebar-tab-background-selected>>;\n\tcolor: <<colour sidebar-tab-foreground-selected>>;\n\tborder-left: 1px solid <<colour sidebar-tab-border-selected>>;\n\tborder-top: 1px solid <<colour sidebar-tab-border-selected>>;\n\tborder-right: 1px solid <<colour sidebar-tab-border-selected>>;\n}\n\n.tc-sidebar-lists .tc-tab-buttons button {\n\tbackground-color: <<colour sidebar-tab-background>>;\n\tcolor: <<colour sidebar-tab-foreground>>;\n\tborder-left: 1px solid <<colour sidebar-tab-border>>;\n\tborder-top: 1px solid <<colour sidebar-tab-border>>;\n\tborder-right: 1px solid <<colour sidebar-tab-border>>;\n}\n\n.tc-sidebar-lists .tc-tab-divider {\n\tborder-top: 1px solid <<colour sidebar-tab-divider>>;\n}\n\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button {\n\tdisplay: block;\n\twidth: 100%;\n\tbackground-color: <<colour sidebar-tab-background>>;\n\tborder-top: none;\n\tborder-left: none;\n\tborder-bottom: none;\n\tborder-right: 1px solid #ccc;\n\tmargin-bottom: inherit;\n}\n\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button.tc-tab-selected {\n\tbackground-color: <<colour sidebar-tab-background-selected>>;\n\tborder: none;\n}\n\n/*\n** Manager\n*/\n\n.tc-manager-wrapper {\n\t\n}\n\n.tc-manager-controls {\n\t\n}\n\n.tc-manager-control {\n\tmargin: 0.5em 0;\n}\n\n.tc-manager-list {\n\twidth: 100%;\n\tborder-top: 1px solid <<colour muted-foreground>>;\n\tborder-left: 1px solid <<colour muted-foreground>>;\n\tborder-right: 1px solid <<colour muted-foreground>>;\n}\n\n.tc-manager-list-item {\n\n}\n\n.tc-manager-list-item-heading {\n    display: block;\n    width: 100%;\n    text-align: left;\t\n\tborder-bottom: 1px solid <<colour muted-foreground>>;\n\tpadding: 3px;\n}\n\n.tc-manager-list-item-heading-selected {\n\tfont-weight: bold;\n\tcolor: <<colour background>>;\n\tfill: <<colour background>>;\n\tbackground-color: <<colour foreground>>;\n}\n\n.tc-manager-list-item-heading:hover {\n\tbackground: <<colour primary>>;\n\tcolor: <<colour background>>;\n}\n\n.tc-manager-list-item-content {\n\tdisplay: flex;\n}\n\n.tc-manager-list-item-content-sidebar {\n    flex: 1 0;\n    background: <<colour tiddler-editor-background>>;\n    border-right: 0.5em solid <<colour muted-foreground>>;\n    border-bottom: 0.5em solid <<colour muted-foreground>>;\n    white-space: nowrap;\n}\n\n.tc-manager-list-item-content-item-heading {\n\tdisplay: block;\n\twidth: 100%;\n\ttext-align: left;\n    background: <<colour muted-foreground>>;\n\ttext-transform: uppercase;\n\tfont-size: 0.6em;\n\tfont-weight: bold;\n    padding: 0.5em 0 0.5em 0;\n}\n\n.tc-manager-list-item-content-item-body {\n\tpadding: 0 0.5em 0 0.5em;\n}\n\n.tc-manager-list-item-content-item-body > pre {\n\tmargin: 0.5em 0 0.5em 0;\n\tborder: none;\n\tbackground: inherit;\n}\n\n.tc-manager-list-item-content-tiddler {\n    flex: 3 1;\n    border-left: 0.5em solid <<colour muted-foreground>>;\n    border-right: 0.5em solid <<colour muted-foreground>>;\n    border-bottom: 0.5em solid <<colour muted-foreground>>;\n}\n\n.tc-manager-list-item-content-item-body > table {\n\tborder: none;\n\tpadding: 0;\n\tmargin: 0;\n}\n\n.tc-manager-list-item-content-item-body > table td {\n\tborder: none;\n}\n\n.tc-manager-icon-editor > button {\n\twidth: 100%;\n}\n\n.tc-manager-icon-editor > button > svg,\n.tc-manager-icon-editor > button > button {\n\twidth: 100%;\n\theight: auto;\n}\n\n/*\n** Alerts\n*/\n\n.tc-alerts {\n\tposition: fixed;\n\ttop: 28px;\n\tleft: 0;\n\tright: 0;\n\tmax-width: 50%;\n\tz-index: 20000;\n}\n\n.tc-alert {\n\tposition: relative;\n\tmargin: 14px;\n\tpadding: 7px;\n\tborder: 1px solid <<colour alert-border>>;\n\tbackground-color: <<colour alert-background>>;\n}\n\n.tc-alert-toolbar {\n\tposition: absolute;\n\ttop: 7px;\n\tright: 7px;\n    line-height: 0;\n}\n\n.tc-alert-toolbar svg {\n\tfill: <<colour alert-muted-foreground>>;\n}\n\n.tc-alert-subtitle {\n\tcolor: <<colour alert-muted-foreground>>;\n\tfont-weight: bold;\n    font-size: 0.8em;\n    margin-bottom: 0.5em;\n}\n\n.tc-alert-body > p {\n\tmargin: 0;\n}\n\n.tc-alert-highlight {\n\tcolor: <<colour alert-highlight>>;\n}\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\t.tc-static-alert {\n\t\tposition: relative;\n\t}\n\n\t.tc-static-alert-inner {\n\t\tposition: absolute;\n\t\tz-index: 100;\n\t}\n\n}\n\n.tc-static-alert-inner {\n\tpadding: 0 2px 2px 42px;\n\tcolor: <<colour static-alert-foreground>>;\n}\n\n/*\n** Floating drafts list\n*/\n\n.tc-drafts-list {\n\tz-index: 2000;\n\tposition: fixed;\n\tfont-size: 0.8em;\n\tleft: 0;\n\tbottom: 0;\n}\n\n.tc-drafts-list a {\n\tmargin: 0 0.5em;\n\tpadding: 4px 4px;\n\tborder-top-left-radius: 4px;\n\tborder-top-right-radius: 4px;\n\tborder: 1px solid <<colour background>>;\n\tborder-bottom-none;\n\tbackground: <<colour dirty-indicator>>;\n\tcolor: <<colour background>>;\n\tfill: <<colour background>>;\n}\n\n.tc-drafts-list a:hover {\n\ttext-decoration: none;\n\tbackground: <<colour foreground>>;\n\tcolor: <<colour background>>;\n\tfill: <<colour background>>;\n}\n\n.tc-drafts-list a svg {\n\twidth: 1em;\n\theight: 1em;\n\tvertical-align: text-bottom;\n}\n\n/*\n** Control panel\n*/\n\n.tc-control-panel td {\n\tpadding: 4px;\n}\n\n.tc-control-panel table, .tc-control-panel table input, .tc-control-panel table textarea {\n\twidth: 100%;\n}\n\n.tc-plugin-info {\n\tdisplay: flex;\n\tborder: 1px solid <<colour muted-foreground>>;\n\tfill: <<colour muted-foreground>>;\n\tbackground-color: <<colour background>>;\n\tmargin: 0.5em 0 0.5em 0;\n\tpadding: 4px;\n    align-items: center;\n}\n\n.tc-plugin-info-sub-plugins .tc-plugin-info {\n    margin: 0.5em;\n\tbackground: <<colour background>>;\n}\n\n.tc-plugin-info-sub-plugin-indicator {\n\tmargin: -16px 1em 0 2em;\n}\n\n.tc-plugin-info-sub-plugin-indicator button {\n\tcolor: <<colour background>>;\n\tbackground: <<colour foreground>>;\n\tborder-radius: 8px;\n    padding: 2px 7px;\n    font-size: 0.75em;\n}\n\n.tc-plugin-info-sub-plugins .tc-plugin-info-dropdown {\n\tmargin-left: 1em;\n\tmargin-right: 1em;\n}\n\n.tc-plugin-info-disabled {\n\tbackground: -webkit-repeating-linear-gradient(45deg, #ff0, #ff0 10px, #eee 10px, #eee 20px);\n\tbackground: repeating-linear-gradient(45deg, #ff0, #ff0 10px, #eee 10px, #eee 20px);\n}\n\n.tc-plugin-info-disabled:hover {\n\tbackground: -webkit-repeating-linear-gradient(45deg, #aa0, #aa0 10px, #888 10px, #888 20px);\n\tbackground: repeating-linear-gradient(45deg, #aa0, #aa0 10px, #888 10px, #888 20px);\n}\n\na.tc-tiddlylink.tc-plugin-info:hover {\n\ttext-decoration: none;\n\tbackground-color: <<colour primary>>;\n\tcolor: <<colour background>>;\n\tfill: <<colour foreground>>;\n}\n\na.tc-tiddlylink.tc-plugin-info:hover .tc-plugin-info > .tc-plugin-info-chunk > svg {\n\tfill: <<colour foreground>>;\n}\n\n.tc-plugin-info-chunk {\n    margin: 2px;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-toggle {\n\tflex-grow: 0;\n\tflex-shrink: 0;\n\tline-height: 1;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-icon {\n\tflex-grow: 0;\n\tflex-shrink: 0;\n\tline-height: 1;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-description {\n\tflex-grow: 1;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-buttons {\n\tfont-size: 0.8em;\n\tline-height: 1.2;\n\tflex-grow: 0;\n\tflex-shrink: 0;\n    text-align: right;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-description h1 {\n\tfont-size: 1em;\n\tline-height: 1.2;\n\tmargin: 2px 0 2px 0;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-description h2 {\n\tfont-size: 0.8em;\n\tline-height: 1.2;\n\tmargin: 2px 0 2px 0;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-description div {\n\tfont-size: 0.7em;\n\tline-height: 1.2;\n\tmargin: 2px 0 2px 0;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-toggle img, .tc-plugin-info-chunk.tc-plugin-info-toggle svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\n.tc-plugin-info-chunk.tc-plugin-info-icon img, .tc-plugin-info-chunk.tc-plugin-info-icon svg {\n\twidth: 2em;\n\theight: 2em;\n}\n\n.tc-plugin-info-dropdown {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tbackground: <<colour background>>;\n\tmargin-top: -8px;\n}\n\n.tc-plugin-info-dropdown-message {\n\tbackground: <<colour message-background>>;\n\tpadding: 0.5em 1em 0.5em 1em;\n\tfont-weight: bold;\n\tfont-size: 0.8em;\n}\n\n.tc-plugin-info-dropdown-body {\n\tpadding: 1em 1em 0 1em;\n\tbackground: <<colour background>>;\n}\n\n.tc-plugin-info-sub-plugins {\n\tpadding: 0.5em;\n    margin: 0 1em 1em 1em;\n\tbackground: <<colour notification-background>>;\n}\n\n.tc-install-plugin {\n\tfont-weight: bold;\n\tbackground: green;\n\tcolor: white;\n\tfill: white;\n\tborder-radius: 4px;\n\tpadding: 3px;\n}\n\n.tc-install-plugin.tc-reinstall-downgrade {\n\tbackground: red;\n}\n\n.tc-install-plugin.tc-reinstall {\n\tbackground: blue;\n}\n\n.tc-install-plugin.tc-reinstall-upgrade {\n\tbackground: orange;\n}\n\n.tc-check-list {\n\tline-height: 2em;\n}\n\n.tc-check-list .tc-image-button {\n\theight: 1.5em;\n}\n\n/*\n** Message boxes\n*/\n\n.tc-message-box {\n\tborder: 1px solid <<colour message-border>>;\n\tbackground: <<colour message-background>>;\n\tpadding: 0px 21px 0px 21px;\n\tfont-size: 12px;\n\tline-height: 18px;\n\tcolor: <<colour message-foreground>>;\n}\n\n.tc-message-box svg {\n\twidth: 1em;\n\theight: 1em;\n    vertical-align: text-bottom;\n}\n\n/*\n** Pictures\n*/\n\n.tc-bordered-image {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tpadding: 5px;\n\tmargin: 5px;\n}\n\n/*\n** Floats\n*/\n\n.tc-float-right {\n\tfloat: right;\n}\n\n/*\n** Chooser\n*/\n\n.tc-chooser {\n\tborder-right: 1px solid <<colour table-header-background>>;\n\tborder-left: 1px solid <<colour table-header-background>>;\n}\n\n\n.tc-chooser-item {\n\tborder-bottom: 1px solid <<colour table-header-background>>;\n\tborder-top: 1px solid <<colour table-header-background>>;\n\tpadding: 2px 4px 2px 14px;\n}\n\n.tc-drop-down .tc-chooser-item {\n\tpadding: 2px;\n}\n\n.tc-chosen,\n.tc-chooser-item:hover {\n\tbackground-color: <<colour table-header-background>>;\n\tborder-color: <<colour table-footer-background>>;\n}\n\n.tc-chosen .tc-tiddlylink {\n\tcursor:default;\n}\n\n.tc-chooser-item .tc-tiddlylink {\n\tdisplay: block;\n\ttext-decoration: none;\n\tbackground-color: transparent;\n}\n\n.tc-chooser-item:hover .tc-tiddlylink:hover {\n\ttext-decoration: none;\n}\n\n.tc-drop-down .tc-chosen .tc-tiddlylink,\n.tc-drop-down .tc-chooser-item .tc-tiddlylink:hover {\n\tcolor: <<colour foreground>>;\n}\n\n.tc-chosen > .tc-tiddlylink:before {\n\tmargin-left: -10px;\n\tposition: relative;\n\tcontent: \"» \";\n}\n\n.tc-chooser-item svg,\n.tc-chooser-item img{\n\twidth: 1em;\n\theight: 1em;\n\tvertical-align: middle;\n}\n\n.tc-language-chooser .tc-image-button img {\n\twidth: 2em;\n\tvertical-align: -0.15em;\n}\n\n/*\n** Palette swatches\n*/\n\n.tc-swatches-horiz {\n}\n\n.tc-swatches-horiz .tc-swatch {\n\tdisplay: inline-block;\n}\n\n.tc-swatch {\n\twidth: 2em;\n\theight: 2em;\n\tmargin: 0.4em;\n\tborder: 1px solid #888;\n}\n\ninput.tc-palette-manager-colour-input {\n\twidth: 100%;\n\tpadding: 0;\n}\n\n/*\n** Table of contents\n*/\n\n.tc-sidebar-lists .tc-table-of-contents {\n\twhite-space: nowrap;\n}\n\n.tc-table-of-contents button {\n\tcolor: <<colour sidebar-foreground>>;\n}\n\n.tc-table-of-contents svg {\n\twidth: 0.7em;\n\theight: 0.7em;\n\tvertical-align: middle;\n\tfill: <<colour sidebar-foreground>>;\n}\n\n.tc-table-of-contents ol {\n\tlist-style-type: none;\n\tpadding-left: 0;\n}\n\n.tc-table-of-contents ol ol {\n\tpadding-left: 1em;\n}\n\n.tc-table-of-contents li {\n\tfont-size: 1.0em;\n\tfont-weight: bold;\n}\n\n.tc-table-of-contents li a {\n\tfont-weight: bold;\n}\n\n.tc-table-of-contents li li {\n\tfont-size: 0.95em;\n\tfont-weight: normal;\n\tline-height: 1.4;\n}\n\n.tc-table-of-contents li li a {\n\tfont-weight: normal;\n}\n\n.tc-table-of-contents li li li {\n\tfont-size: 0.95em;\n\tfont-weight: 200;\n\tline-height: 1.5;\n}\n\n.tc-table-of-contents li li li li {\n\tfont-size: 0.95em;\n\tfont-weight: 200;\n}\n\n.tc-tabbed-table-of-contents {\n\tdisplay: -webkit-flex;\n\tdisplay: flex;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents {\n\tz-index: 100;\n\tdisplay: inline-block;\n\tpadding-left: 1em;\n\tmax-width: 50%;\n\t-webkit-flex: 0 0 auto;\n\tflex: 0 0 auto;\n\tbackground: <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item > a,\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item-selected > a {\n\tdisplay: block;\n\tpadding: 0.12em 1em 0.12em 0.25em;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item > a {\n\tborder-top: 1px solid <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-background>>;\n\tborder-bottom: 1px solid <<colour tab-background>>;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item > a:hover {\n\ttext-decoration: none;\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n\tbackground: <<colour tab-border>>;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item-selected > a {\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n\tbackground: <<colour background>>;\n\tmargin-right: -1px;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item-selected > a:hover {\n\ttext-decoration: none;\n}\n\n.tc-tabbed-table-of-contents .tc-tabbed-table-of-contents-content {\n\tdisplay: inline-block;\n\tvertical-align: top;\n\tpadding-left: 1.5em;\n\tpadding-right: 1.5em;\n\tborder: 1px solid <<colour tab-border>>;\n\t-webkit-flex: 1 0 50%;\n\tflex: 1 0 50%;\n}\n\n/*\n** Dirty indicator\n*/\n\nbody.tc-dirty span.tc-dirty-indicator, body.tc-dirty span.tc-dirty-indicator svg {\n\tfill: <<colour dirty-indicator>>;\n\tcolor: <<colour dirty-indicator>>;\n}\n\n/*\n** File inputs\n*/\n\n.tc-file-input-wrapper {\n\tposition: relative;\n\toverflow: hidden;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n\n.tc-file-input-wrapper input[type=file] {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tfont-size: 999px;\n\tmax-width: 100%;\n\tmax-height: 100%;\n\tfilter: alpha(opacity=0);\n\topacity: 0;\n\toutline: none;\n\tbackground: white;\n\tcursor: pointer;\n\tdisplay: inline-block;\n}\n\n/*\n** Thumbnail macros\n*/\n\n.tc-thumbnail-wrapper {\n\tposition: relative;\n\tdisplay: inline-block;\n\tmargin: 6px;\n\tvertical-align: top;\n}\n\n.tc-thumbnail-right-wrapper {\n\tfloat:right;\n\tmargin: 0.5em 0 0.5em 0.5em;\n}\n\n.tc-thumbnail-image {\n\ttext-align: center;\n\toverflow: hidden;\n\tborder-radius: 3px;\n}\n\n.tc-thumbnail-image svg,\n.tc-thumbnail-image img {\n\tfilter: alpha(opacity=1);\n\topacity: 1;\n\tmin-width: 100%;\n\tmin-height: 100%;\n\tmax-width: 100%;\n}\n\n.tc-thumbnail-wrapper:hover .tc-thumbnail-image svg,\n.tc-thumbnail-wrapper:hover .tc-thumbnail-image img {\n\tfilter: alpha(opacity=0.8);\n\topacity: 0.8;\n}\n\n.tc-thumbnail-background {\n\tposition: absolute;\n\tborder-radius: 3px;\n}\n\n.tc-thumbnail-icon svg,\n.tc-thumbnail-icon img {\n\twidth: 3em;\n\theight: 3em;\n\t<<filter \"drop-shadow(2px 2px 4px rgba(0,0,0,0.3))\">>\n}\n\n.tc-thumbnail-wrapper:hover .tc-thumbnail-icon svg,\n.tc-thumbnail-wrapper:hover .tc-thumbnail-icon img {\n\tfill: #fff;\n\t<<filter \"drop-shadow(3px 3px 4px rgba(0,0,0,0.6))\">>\n}\n\n.tc-thumbnail-icon {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tdisplay: -webkit-flex;\n\t-webkit-align-items: center;\n\t-webkit-justify-content: center;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.tc-thumbnail-caption {\n\tposition: absolute;\n\tbackground-color: #777;\n\tcolor: #fff;\n\ttext-align: center;\n\tbottom: 0;\n\twidth: 100%;\n\tfilter: alpha(opacity=0.9);\n\topacity: 0.9;\n\tline-height: 1.4;\n\tborder-bottom-left-radius: 3px;\n\tborder-bottom-right-radius: 3px;\n}\n\n.tc-thumbnail-wrapper:hover .tc-thumbnail-caption {\n\tfilter: alpha(opacity=1);\n\topacity: 1;\n}\n\n/*\n** Diffs\n*/\n\n.tc-diff-equal {\n\tbackground-color: <<colour diff-equal-background>>;\n\tcolor: <<colour diff-equal-foreground>>;\n}\n\n.tc-diff-insert {\n\tbackground-color: <<colour diff-insert-background>>;\n\tcolor: <<colour diff-insert-foreground>>;\n}\n\n.tc-diff-delete {\n\tbackground-color: <<colour diff-delete-background>>;\n\tcolor: <<colour diff-delete-foreground>>;\n}\n\n.tc-diff-invisible {\n\tbackground-color: <<colour diff-invisible-background>>;\n\tcolor: <<colour diff-invisible-foreground>>;\n}\n\n.tc-diff-tiddlers th {\n\ttext-align: right;\n\tbackground: <<colour background>>;\n\tfont-weight: normal;\n\tfont-style: italic;\n}\n\n.tc-diff-tiddlers pre {\n    margin: 0;\n    padding: 0;\n    border: none;\n    background: none;\n}\n\n/*\n** Errors\n*/\n\n.tc-error {\n\tbackground: #f00;\n\tcolor: #fff;\n}\n\n/*\n** Tree macro\n*/\n\n.tc-tree div {\n    \tpadding-left: 14px;\n}\n\n.tc-tree ol {\n    \tlist-style-type: none;\n    \tpadding-left: 0;\n    \tmargin-top: 0;\n}\n\n.tc-tree ol ol {\n    \tpadding-left: 1em;    \n}\n\n.tc-tree button { \n    \tcolor: #acacac;\n}\n\n.tc-tree svg {\n     \tfill: #acacac;\n}\n\n.tc-tree span svg {\n    \twidth: 1em;\n    \theight: 1em;\n    \tvertical-align: baseline;\n}\n\n.tc-tree li span {\n    \tcolor: lightgray;\n}\n\nselect {\n        color: <<colour select-tag-foreground>>;\n        background: <<colour select-tag-background>>;\n}\n\n/*\n** Utility classes for SVG icons\n*/\n\n.tc-fill-background {\n\tfill: <<colour background>>;\n}"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize",
            "text": "15px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/bodylineheight": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/bodylineheight",
            "text": "22px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/fontsize": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/fontsize",
            "text": "14px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/lineheight": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/lineheight",
            "text": "20px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/storyleft": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/storyleft",
            "text": "0px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/storytop": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/storytop",
            "text": "0px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/storyright": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/storyright",
            "text": "770px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/storywidth": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/storywidth",
            "text": "770px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth",
            "text": "686px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint",
            "text": "960px"
        },
        "$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth": {
            "title": "$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth",
            "text": "350px"
        },
        "$:/themes/tiddlywiki/vanilla/options/stickytitles": {
            "title": "$:/themes/tiddlywiki/vanilla/options/stickytitles",
            "text": "no"
        },
        "$:/themes/tiddlywiki/vanilla/options/sidebarlayout": {
            "title": "$:/themes/tiddlywiki/vanilla/options/sidebarlayout",
            "text": "fixed-fluid"
        },
        "$:/themes/tiddlywiki/vanilla/options/codewrapping": {
            "title": "$:/themes/tiddlywiki/vanilla/options/codewrapping",
            "text": "pre-wrap"
        },
        "$:/themes/tiddlywiki/vanilla/reset": {
            "title": "$:/themes/tiddlywiki/vanilla/reset",
            "type": "text/plain",
            "text": "/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n   ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\nhtml {\n  line-height: 1.15; /* 1 */\n  -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/* Sections\n   ========================================================================== */\n\n/**\n * Remove the margin in all browsers.\n */\n\nbody {\n  margin: 0;\n}\n\n/**\n * Render the `main` element consistently in IE.\n */\n\nmain {\n  display: block;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n/* Grouping content\n   ========================================================================== */\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n  box-sizing: content-box; /* 1 */\n  height: 0; /* 1 */\n  overflow: visible; /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n  font-family: monospace, monospace; /* 1 */\n  font-size: 1em; /* 2 */\n}\n\n/* Text-level semantics\n   ========================================================================== */\n\n/**\n * Remove the gray background on active links in IE 10.\n */\n\na {\n  background-color: transparent;\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57-\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n  border-bottom: none; /* 1 */\n  text-decoration: underline; /* 2 */\n  text-decoration: underline dotted; /* 2 */\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n  font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n  font-family: monospace, monospace; /* 1 */\n  font-size: 1em; /* 2 */\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n  font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nsup {\n  top: -0.5em;\n}\n\n/* Embedded content\n   ========================================================================== */\n\n/**\n * Remove the border on images inside links in IE 10.\n */\n\nimg {\n  border-style: none;\n}\n\n/* Forms\n   ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers.\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  font-family: inherit; /* 1 */\n  font-size: 100%; /* 1 */\n  line-height: 1.15; /* 1 */\n  margin: 0; /* 2 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput { /* 1 */\n  overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect { /* 1 */\n  text-transform: none;\n}\n\n/**\n * Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n  -webkit-appearance: button;\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n  border-style: none;\n  padding: 0;\n}\n\n/**\n * Restore the focus styles unset by the previous rule.\n */\n\nbutton:-moz-focusring,\n[type=\"button\"]:-moz-focusring,\n[type=\"reset\"]:-moz-focusring,\n[type=\"submit\"]:-moz-focusring {\n  outline: 1px dotted ButtonText;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n  padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n *    `fieldset` elements in all browsers.\n */\n\nlegend {\n  box-sizing: border-box; /* 1 */\n  color: inherit; /* 2 */\n  display: table; /* 1 */\n  max-width: 100%; /* 1 */\n  padding: 0; /* 3 */\n  white-space: normal; /* 1 */\n}\n\n/**\n * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n  vertical-align: baseline;\n}\n\n/**\n * Remove the default vertical scrollbar in IE 10+.\n */\n\ntextarea {\n  overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10.\n * 2. Remove the padding in IE 10.\n */\n\n[type=\"checkbox\"],\n[type=\"radio\"] {\n  box-sizing: border-box; /* 1 */\n  padding: 0; /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type=\"search\"] {\n  -webkit-appearance: textfield; /* 1 */\n  outline-offset: -2px; /* 2 */\n}\n\n/**\n * Remove the inner padding in Chrome and Safari on macOS.\n */\n\n[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n  -webkit-appearance: button; /* 1 */\n  font: inherit; /* 2 */\n}\n\n/* Interactive\n   ========================================================================== */\n\n/*\n * Add the correct display in Edge, IE 10+, and Firefox.\n */\n\ndetails {\n  display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n  display: list-item;\n}\n\n/* Misc\n   ========================================================================== */\n\n/**\n * Add the correct display in IE 10+.\n */\n\ntemplate {\n  display: none;\n}\n\n/**\n * Add the correct display in IE 10.\n */\n\n[hidden] {\n  display: none;\n}\n"
        },
        "$:/themes/tiddlywiki/vanilla/settings/fontfamily": {
            "title": "$:/themes/tiddlywiki/vanilla/settings/fontfamily",
            "text": "-apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\""
        },
        "$:/themes/tiddlywiki/vanilla/settings/codefontfamily": {
            "title": "$:/themes/tiddlywiki/vanilla/settings/codefontfamily",
            "text": "\"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,Courier,monospace"
        },
        "$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment": {
            "title": "$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment",
            "text": "fixed"
        },
        "$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize": {
            "title": "$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize",
            "text": "auto"
        },
        "$:/themes/tiddlywiki/vanilla/sticky": {
            "title": "$:/themes/tiddlywiki/vanilla/sticky",
            "text": "<$reveal state=\"$:/themes/tiddlywiki/vanilla/options/stickytitles\" type=\"match\" text=\"yes\">\n``\n.tc-tiddler-title {\n\tposition: -webkit-sticky;\n\tposition: -moz-sticky;\n\tposition: -o-sticky;\n\tposition: -ms-sticky;\n\tposition: sticky;\n\ttop: 0px;\n\tbackground: ``<<colour tiddler-background>>``;\n\tz-index: 500;\n}\n\n``\n<$list filter=\"[range[100]]\">\n`.tc-story-river .tc-tiddler-frame:nth-child(100n+`<$text text=<<currentTiddler>>/>`) {\nz-index: `<$text text={{{ [[200]subtract<currentTiddler>] }}}/>`;\n}\n`\n</$list>\n</$reveal>\n"
        }
    }
}
pre
fluid-fixed
yes
* 8x 50Ah cells
** studs welded onto the battery terminals
** got them locally from someone who bought more than they needed from china
* [[Battery Management System (BMS)]]
** JBD 100A
* case
** 400x300x220mm Euro container with hinged lid
** cheaper, available locally: https://www.obi.de/aufbewahrungsboxen/eurobox-system-box-vollwand-40-x-30-x-22-cm-schwarz/p/6037568
** https://www.obi.de/aufbewahrungsboxen/eurobox-system-deckel-mit-scharnieren-fuer-box-40-x-30-cm-transparent/p/5954607
** https://www.tbs-online.de/de/de/Betriebsausst/Werkzeugaufbewahrung/TBS-Boxx%C2%AEen-System/TBS-Transportboxen/Transportbox-TBS-schwarz-mit-transparentem-Deckel-St%C3%BCckweise-oder-VPE-sid141681.html
** cheaper lid, container expensive: https://www.ebay.de/itm/223781388659
* additional stuff
** nickel coated busbars, had to drill additional holes for the studs
** nickel coated washer nuts with nylon stop rings
requirements:

* ~200Ah
* 12V
* 1,5kW inverter
* [[LiFePO4 (LFP)]] cells

bought:

* 4x 280Ah LFP cells
** should include busbars and screws
* 200A Daly 4s LFP BMS
* 1,5kW inverter
* battery monitor with 200A hall sensor and another one with 200A shunt
* 20A 14.6V charger

the cells took quite some time to arrive, and after testing 2 of the cells where of lower quality and i was only able to pull arround 250Ah of capacity. they where advertised als 280Ah, but thats not too bad.

i intent to use a 40x30cm euro container as case but the 22cm versions are a little to small, i need atleast 24cm height. the next standard height would be 27cm. i ordered a ED 43/27 from Auer packaging.

i may add an anderson connector to power DC-devices directly

i could order the charger with different connectors, i ordered it with an XT60 connector and ordered some XT60 connectors for the battery. panel-mount XT60 are rare and more expensive but I could 3D print a some panel-mount hardware later to mount the connector propperly

* https://www.thingiverse.com/search?q=xt60&type=things&sort=relevant&page=2

build

* to mount/secure the cells inside the box i needed a baseplate which i can screw inside the euro container, also the floor of the box is a bit narrower than the rest and i need a bit of height to propperly screw it in. i got a 36x26cm wood plate with 2cm thickness, plenty enough to clear the narrower part and enough to propperly screw into.
* i hat to make the edges round to fit the plate into the bottom of the container and i carved out tracks where 12mm zipties are flush with the wood, i drilled some holes to be able to pull zipties through
* i propperly sanded the whole plate to be smooth
* i test-fitted the battery cells, so i can adjust the zipties at the bottom, cut off the excess and fit the plate with the ties into the container
* the inverter i got fitts well next to the cells inside the box, i removed the side-plate with the mains sockets and power switch from the inverter, i removed the mains sockets and switch assembly from the plate.
* i meassured the switch assembly and the mains sockets and made holes in the side of the container in order to facilitate the sockets and the switch. i made sure the holes are not too small and they got a snugg fit, because they are clipped in and i don't want them to fall out. the sockets will get a 3d-printed shroud, which will sit inside the box and will prevent beeing able to touch the mains cables and connections, also the fit of the sockets will be better with them
* i also made a hole to mount a air grill for additional ventilation. i have fans with matching size i could mount there if needed
* i drilled holes every 5cm into the lower side of the box and angled them down to propperly drill into the wood base, then i screwed the wood-base to the container with 30*4mm wood screws with countersunk TORX head
* i got some foam rubber (moosgummi) to fit under the battery cells to protect them some more and dampen shocks and then fitted the cells
* i've got a bit of cardboard protecting the edges of the cells from the zip-ties and pulled the zip-ties so they had perfect fit arround the cells. i tied the cells as hard as i was able to with bare hands, they are mounted good and sturdy
* when i tried fitting the inverter, BMS and the hall sensor of the battery monitor, i was not able to fit the hall sensor with the cable next to the cells, so i decided to buy another battery monitor which uses a shunt for meassuring the current, the shunt is more narrow than the hall sensor and should fit a lot better
I've got a used 19" 6U rack-bag for 30€. It's really useful for my XR18 and additional stuff, so i don't have to connect everything up each time.

It has two "doors" with zippers for front and rear access and 19" rails in the front. The mounting depth of rack devices is just 36cm for this rack-bag, so a lot of things like 41cm depth rack drawers don't fit.

Other things that aren't as deep are often a lot more shallow and leave a lot of space unused.
So I wanted to add rack rails for the rear to mount stuff.
Also a 2U rack drawer for cable mics and cables and a multi-outlet power strip to connect everything.

wanted to get some used parts to save some money and i don't care about a bit of wear.
found a 2U 21cm mounting-depth rack drawer for around 30€ used, but i bought the power strip new because there were only few used one that i could find and they were more expensive.

Because the manufacturer build the rack pretty small the rack doesn't have a lot of space on the sides. So i had to get a power strip on which the cable doesn't come out of the side to not bend the cable a lot: https://www.thomann.de/de/varytec_power_distribution_panel_8x_sc.htm

Another problem that's caused by the smaller overall rack-width is that standard rackrails from adam hall or so are to wide. Also the rack uses M5 screws instead of M6 (M6 is common for 19" racks in europe)
I had to custom make rack rails.
I planned on bending the angled rails myself at the local workshop "werkstadtpirat:innen", but luckily they had perfect scrap metal lying around. The scrap was some old locking plate from a door. One side of the angle was 17mm which is perfect because the original rails are also 17mm on the mounting face.

I made plans with freecad.  i can't use the full 6U height, because of triangular pieces, inside the back in the corners, supporting the rack overall and making it sturdy. I didn't want to modify the rack to much and also didn't want to make the stability worse. So i decided to make it kinda a 5U rail but more like a 4U rail with 2x 0,5U on the top and bottom.
If i want to the 0.5U are enough to mount some plates or so in the bottom and top U and i also don't want to completely close of the back, so i can still get at all cables easily.

I cut pieces of the scrap material, marked and drilled all the holes and also tapped the holes for mounting rack devices. The original rails also have the mounting holes tapped for M5.
I got some screws and mounted the rails in the wood of the rack.

After Mounting the new rails i mounted my 2U drawer in the front and the power strip in the back behind the drawer. Then i wired everything up.

the scrap material was galvanized and the new rails are still silver, maybe someday i will paint them black, but right now it doesn't bother me, because they are in the back.
Also i'm thinking about mounting and wiring some of my wireless mics into the rack but i'm unsure which.
And i plan on putting some dampening material into the drawer to protect my cable mics. I've got some foam or maybe i use neoprene, felt or so.
Information:

* https://en.wikipedia.org/wiki/19-inch_rack
* https://de.wikipedia.org/wiki/Rack
* the [[Eurorack]] is based on the Eurocard PCBs which are based on the 19" standard, so you can mount Eurorack modules inside every 19" rack requiring only additional horizontal mountingrails
* https://en.wikipedia.org/wiki/Rack_unit

DIY stuff:

* https://colomar.com/Shavano/rackcase.html
* https://tombuildsstuff.blogspot.com/2014/02/diy-server-rack-plans.html
* https://diysynthcases.com/  - https://web.archive.org/web/20200919153954/http://diysynthcases.com/
* https://www.makeuseof.com/tag/build-diy-rack-case/
* https://blog.deadlycomputer.com/index.php/2006/09/17/458/

cases

* https://www.fischerelektronik.de/web_fischer/de_DE/Geh%C3%A4use/index.xhtml
* https://de.farnell.com/c/gehause-racks-schranke/racks-schranke/19-gehause
* https://www.bopla.de/gehaeusetechnik/produktkatalog-standardgehaeuse/aluminiumgehaeuse.html
* https://www.youtube.com/channel/UCSpFnDQr88xCZ80N-X7t0nQ - Coridor Crew
* https://www.youtube.com/channel/UCOKHwx1VCdgnxwbjyb9Iu1g - Blender Guru
* [[Easy Satisfying Animation in Blender (Blender Tutorial)|https://www.youtube.com/watch?v=6zcpOrg8Vqs]]
* mixamo
* VRChat
** https://docs.vrchat.com/docs/creating-your-first-avatar
** https://hello.vrchat.com/developer-faq
** uses unity
* https://teachingtechyt.github.io/calibration.html
* https://wiki.opensourceecology.de/Maker%27s_Friend
* https://www.opensourceecology.org/portfolio/3d-printer/
* https://de.wikipedia.org/wiki/Prusa_i3
** https://en.wikipedia.org/wiki/Prusa_i3
* https://deezmaker.com/products/bukobot-3d-printer/
* https://wiki.opensourceecology.de/3D-Drucker
* see [[open source CAD software]]

designs / styles

* H-Bot

stuff

* [[Autoleveling on 3D printers: 9 myths and 12 sensors tested!|https://www.youtube.com/watch?v=il9bNWn66BY]]
* https://wiki.opensourceecology.de/Maker%27s_Friend
** https://github.com/case06/MakersFriend
* https://digitaltechindia.com/images/4accoustic%20PDF.pdf page 68
* pa calculate app (rcf) -> Limiter berechnet
** 32db verstärkung hat die endstufe
** 0db an der endstufe einstellen
** -6db standard am input vom eq/dsp/etc.
Hi, I'm a Student and Software developer from Germany and very interrested in sustainable energy systems, sustainable transportation and sound reinforcement (PA).
I reguarly contribute to open (source/hardware/etc.) projects or start new projects and repair a lot of stuff.

human rights, LGBT* rights, better climate politics and digital (human) rights are very important to me, i fight against nazis, racism, the right and their tactics and missinformation.
i'm nonbinary and pansexual.
i think i'm a hacker of the traditional, not the (colloquial) criminal kind.
i like subcultures like goth, punk, solar-/lunarpunk and similar open minded subcultures.

This is my wiki where i collect informations/knowledge/links of topics i'm interrested in and documentation of my projects.
It is allways work-in-progress. Most of it is in english, some parts might be german or mixed though.
This wiki is just an interim solution until i find a better option.

I work with different Projects and Initiatives in Dresden.

Please Support me if you like my work and find my projects or contributions to other projects useful:

<a href='https://ko-fi.com/thorbijoern' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://cdn.ko-fi.com/cdn/kofi4.png?v=2' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
<a href="https://liberapay.com/Thorbijoern/donate" target='_blank'><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>

or support with stuff from my [[Wishlist]], Thanks.

the stuff i collect is used for projects which benefit people through being public/open, i lend them or they are used in political activism:

[[here you can find the equipment i got and i can lend some of it|my equipment]]

[[Ersatzteile die ich übrig habe bzw. Teile für Projekte]]

[[some stuff i can give away|(old) stuff i can give away]]

[[my github page|https://github.com/thorbijoern]] <img alt="GitHub followers" src="https://img.shields.io/github/followers/Thorbijoern?label=Follow&style=social">

about the wiki software i use here:

[[here you can find out how you can set up your own wiki like this|Setting up a Wiki like this]]
* https://en.wikipedia.org/wiki/Accessibility
* https://de.wikipedia.org/wiki/Barrierefreiheit
* https://en.wikipedia.org/wiki/Category:Assistive_technology
* see [[Computer Accessibility]]
* https://wheelmap.org
* https://raul.de/
* https://www.libravatar.org/
* https://shields.io/
to compare accumulator technologies the measures volume/Wh, cost/Wh and sustainability are important.

anderson powerpole and similar seem pretty good for high current applications

* https://wiki.opensourceecology.de/Open_Source_Ecology_Germany
* https://learn.libre.solar/system/battery.html

subarticles:

<<list-links "[all[current]tagging[]]">>
* [[Active rectifiers (1/2)|https://www.youtube.com/watch?v=VR456CsHYx4]]
* [[Active rectifiers (2/2)|https://www.youtube.com/watch?v=arvNukW-jeo]]
* [[The End of the Full Bridge Rectifier? (Sorry ElectroBOOM) Active Rectifier is here!|https://www.youtube.com/watch?v=S0j4xOuRzD4]]
* https://d3ward.github.io/toolz/src/adblock.html - testing
* ublock origin
** https://old.reddit.com/r/uBlockOrigin/
** https://andadinosaur.com/youtube-s-anti-adblock-and-ublock-origin
** https://files.enderman.ch/scripts/yt-antiadblocker.html
* Decentraleyes
* Facebook Container
* Privacy Badger
* https://twitter.com/nervtjeden
informations and common adc and dac chips

ADCs - analog (to) digital converters

* PCM1802
** 24 bit, 96 kHz, stereo
** https://www.ti.com/lit/ds/symlink/pcm1802.pdf
* PCM1808
** [[Altec Lansing Speaker will only play loud Static noise - Motherboard repair & BIG BOSS DANCING|https://www.youtube.com/watch?v=m7QjPZ4nzAc]]
** https://www.ti.com/lit/ds/symlink/pcm1808.pdf
* info
** [[ Understanding Analog to Digital Conversion |https://www.youtube.com/watch?v=_gZjBx9cdro]]
** [[ Delta-Sigma Analog to Digital Converters |https://www.youtube.com/watch?v=SFAS8nE4_ZM]]
*** [[ Delta Sigma ADCs, Part 2 |https://www.youtube.com/watch?v=mCWC0X2naY0]]
** [[ TSP #32 - Tutorial on the Theory, Design and Measurement of Delta-Sigma Analog to Digital Converters |https://www.youtube.com/watch?v=z9u-QTDAeaM]]

DACs - digital (to) analog converters

* PCM510xA - often PCM5102A
** 32 bit, 384 kHz, stereo
** https://www.ti.com/lit/ds/symlink/pcm5102a.pdf

used by behringer ultradrive:

* AKM AK5393VS - Enhanced Dual bit ΔΣ 96 kHz 24-bit ADC
* AKM AK5383VS - Enhanced Dual bit ΔΣ 96 kHz 24-bit ADC
* AKM AK4393VF - Advanced Multi-Bit 96kHz 24-Bit ΔΣ DAC 
* Polyimide/kapton tape - pretty themperature resistant
* T-7000, T-8000, B-7000 - multi purpose glue and display glue
* hylomar
AES/EBU is the most used name, AES3 is the standard.

used for digital transfer of audio data between to points over a single cable.
serial, unidirectional, selfsynchronising
audio can be stereo/two channels or mono 32-192kHz, 16-24Bit PCM.
cable can be balanced 110Ohm XLR, unbalanced BNC 75Ohm coax or twisted pair cable or optical fiber.

* AES-2id includes guidelines for using AES3
* MADI (AES10) and AES50 are digital protocols which can transport AES3
* AES42 is a standard for digital audio for microfones which builds upon AES3
* S/PDIF (IEC 60958) is a consumer grade variant build upon AES3
* AES47 transports AES3 over ATM (obsolete)

Hardware implementation:
using

* pulse transformers for isolation
* sample rate converters
** [[Cirrus Logic CS8420-CSZ - Digital Audio Sample Rate Converter|https://www.alldatasheet.com/datasheet-pdf/pdf/198989/CIRRUS/CS8420-CSZ.html]] - [[Behringer Ultradrive Pro DCX2496]]
* https://www.ti.com/audio-ic/interface/spdif-transceivers/products.html
* https://www.ti.com/audio-ic/interface/sample-rate-converters/products.html

links

* https://de.wikipedia.org/wiki/AES/EBU
* https://en.wikipedia.org/wiki/AES3
* https://tech.ebu.ch/docs/tech/tech3250.pdf
* https://tech.ebu.ch/docs/other/aes-ebu-eg.pdf
* https://www.nti-audio.com/Portals/0/data/en/NTi-Audio-AppNote-AES3-AES-EBU.pdf
* https://sound-au.com/project85.htm
I was searching for AKG HT80 wireless mics for my [[Fohhn EasyPort FP1 plus repair]] when i found a seller who had 2 WMS80 sets with HT80 mics and 2 sets with PT80 bodypacks. I initially just wanted one set for 35€, but he sold me all 4 sets for 40€ and i couldn't refuse.

* WMS80 is the series of the complete set
* SR80 is the receiver
* HT80 is the normal hand mic transmitter
* PT80 is the bodypack transmitter for instrument mics, headset mics or guitar pickups

some of the SR80's had broken solderjoints at the connectors, i just resoldered them.

much more work was removing the matte finish of the black plastic part of the housing. the matt finish started to peel and flake off and it was ugly and bad to the touch, so i decided it had to come off.
i probably don't have the best way, but a lot of anoying scubbing with soapy wather, a microfible cloth and rubbing with the fingers removed almost everything except for some spots left in creases and in letters on the back. but the bare plastic feels better than the old matte finish.
save aus FFF wiki - https://wiki.fridaysforfuture.is/wiki/Akku_PA-Anlage_/_Akku_Beschallungsanlage


<<<
diese Seite handelt mehr von schon bestehenden Systemen und bietet einen Überblick, für mehr technische Informationen zur Umsettung siehe [[Mobile Stromversorgung]]

PA-Anlagen (PA: Public Adress) bzw. Beschallungsanlagen nutzen meist Netzspannung (230V 50Hz) und werden bei mobiler Nutzung mit Notstromaggregaten betrieben. Da Notstromaggregate jedoch nicht umweltfreundlich sind, sind Akkus eine gute alternative.

Es gibt schon coole existierende Systeme:
* http://www.gruener-bereich.net/
* http://www.klarageist.com (sehr teuer)
* https://www.rockgegenrechts.com/?p=4864 [Fragen wie der stand ist?]
* http://www.sonnensystem.info/
* "Sonnensystem 2.0" vlt. bald auch in Dresden (Kollaboration von Tolerave e.V., Hertz Beben, Verkehrswende, FFF Dresden und weiteren)
[gerne weitere eintragen]

Wichtig ist auch die Betrachtung der [[Effiziente Beschallung von Menschenmengen|effizienz der gewählten Baschallungsweise]].

== Kauf fertiger Akku-Anlagen ==
Eine Möglichkeit ist die Anschaffung von Boxen mit integriertem Akku, wie z.B. Teufel Rockster, Sennheiser LSP 500 Pro (wenn man zu viel geld hat) oder kleinere.
Jedoch ist das nicht immer möglich bzw. nicht die billigste oder praktikabelste Wahl (vor allem bei größeren Anlagen), jedoch die einfachste Möglichkeit da nicht unbedingt tiefes technisches wissen benötigt ist.

== Akkubetrieb einer bestehenden Anlage ==

Wenn es schon eine bestehende Anlage gibt kann diese auch mit Akkus betrieben werden, näheres dazu in [[Mobile Stromversorgung]]. Dies ist mit einem Wechselrichter jedoch nicht die effizienteste Möglichkeit.
Hierbei ist eig. egal ob es sich um eine Anlage mit Aktivboxen (der Verstärker ist in die Boxen integriert) oder Passivboxen (der Verstärker ist extra) handelt, da beide für gewöhnlich normalen Netzstrom (230V 50Hz AC) verlangen.

== Bau einer Anlage die für den Akkubetrieb bestimmt ist ==
Die dritte Möglichkeit ist der Aufbau einer neuen Anlage, die gleich auf den Akkubetrieb ausgelegt ist. Diese Variante ist effizienter als Wechselrichter zu nutzen. Hierzu bietet sich eine Anlage mit Verstärkern/Endstufen an, die Gleichstrom zum Betrieb nutzen, dazu werden dann noch die passenden Passivboxen benötigt.
Man bekommt in vielen Elektronikläden Car-Hifi Anlagen, die für die 12V eines Autoakkus (Blei-Säure) ausgelegt sind. Dies ist zwar nicht unbedingt die professionellste und qualitativste Wahl, aber einfach zu kaufen.
Besser sind jedoch professionelle Endstufen die z.B. mit 48V als Eingangsspannung arbeiten (Sources?).
Es ist auch möglich die Passivboxen mit normalen Verstärkern am Stromnetz zu betreiben.

[[Kategorie:Wissen & Diskurs]][[Kategorie:Technik-IT Support]]

<<<
* https://en.wikipedia.org/wiki/Algorithmic_art
* https://en.wikipedia.org/wiki/Category:Algorithmic_art
* https://en.wikipedia.org/wiki/Category:Computer_art
** https://de.wikipedia.org/wiki/Kategorie:Computerkunst
* https://en.wikipedia.org/wiki/New_media_art

Lists

* https://alternativeto.net/list/5827/algorithmic-creation

Audio only

* SuperCollider
* https://github.com/sonic-pi-net/sonic-pi

Visual only

* https://tinkersynth.com/
* https://ptsjs.org/

Audio Visual

* Touch Designer - fucking expensive proprietary stuff - https://www.youtube.com/watch?v=waGzVes6PWY
** https://alternativeto.net/software/touchdesigner/?license=opensource
* Pure Data - https://puredata.info/
** https://alternativeto.net/software/pure-data/
** https://en.wikipedia.org/wiki/Pure_Data
** https://de.wikipedia.org/wiki/Pure_Data
** https://www.pd-tutorial.com/english/index.html
** https://github.com/sebpiq/WebPd
* https://www.bigfug.com/software/fugio/
* http://freeframe.sourceforge.net/
* [[Pixel Noise (Music from Images) - Computerphile|https://www.youtube.com/watch?v=c4cKlez0OCM]]
* [[Web Audio API, Web Midi API - Websites with advanced audio functionality]]
* https://charlie-roberts.com/gibber/ - https://github.com/charlieroberts

Programming langs/frameworks

* Processing - https://processing.org/
** https://en.wikipedia.org/wiki/Processing_(programming_language)
** https://de.wikipedia.org/wiki/Processing
** https://processing.org/reference/libraries/

stuff

* openFrameworks - https://openframeworks.cc/
** https://de.wikipedia.org/wiki/OpenFrameworks
** https://en.wikipedia.org/wiki/OpenFrameworks
* Cinder
* Processing - http://processing.org/
** https://de.wikipedia.org/wiki/Processing
** https://en.wikipedia.org/wiki/Processing_(programming_language)
* [[Coding Adventure: Ant and Slime Simulations|https://www.youtube.com/watch?v=X-iSQQgOd1A]]
* https://amicaldo.de/ fancy colorful interactivewater/smoke/turbulence animation stuff
** https://amicaldo.de/js/main-colors.js
* https://www.vitling.xyz/
** https://github.com/vitling/acid-banger
* https://www.youtube.com/watch?v=kzwT3wQWAHE
* [[EEVblog 1417 - Alternating Current AC Basics - Part 1|https://www.youtube.com/watch?v=rrPtvYYJ2-g]]
* [[EEVblog 1406 - DC Circuit Transients Fundamentals|https://www.youtube.com/watch?v=8nyNamrWcyE]]
* [[EEVblog 1397 - DC Voltage & Current Source Theory|https://www.youtube.com/watch?v=AQK7RyecVW0]]
* [[EEVblog 1401 - DC Power, Efficiency, & Maximum Power Transfer Theory|https://www.youtube.com/watch?v=fHoHYEZnVIg]]
GTC got some Alto TS315 active PA speakers in for repair which where damaged by a faulty mixing console.
The customer only stated they plugged them into a mixing console, they tested everything but they didn't work.
I immediately told them to call the owner and tell them not to use the mixing console anymore, it also has to be looked at.

First I tested the speakers myself with a known-good device and known good cables.
They have two separate inputs and one output per speaker. On one speaker both inputs are broken and on the other one one still functions kinda, but it's not symmetrical anymore and picks up interference from cellphones.

Then i unplugged everything and opened them up. I first focused on the input/control pcb. I unplugged and disassembled it from the back-plate to give it a visual inspection. I could pretty quickly see some obvious burnt components.
The damage is isolated to the input/volume control PCB directly after the XLR/Jack inputs it seems. The protection zener-diodes ZD1 through ZD8 are shorted and the small inductors L1 through L4 are damaged/burned.
The components certainly did their job in protecting from further damage, but need replacement.
The PCBs have markings "HB04212", "TS212 PRE" and "VER151029".

The small smd inductors are probably there to improve the signal in some way, they are completely burned up, except one lucky inductor in one of the speakers.
The zener diodes are for protection, to protect the inputs/opamps from high voltages. they are mostly meant for voltage spikes like esd or so, but in this case there probably was a pretty powerful DC voltage on the inputs. the zener diodes are between the signal lines and Vcc,GND and Vdd (depending on the circuit) and clamp the voltage to a level.
one zener which wasn't shorted measured 2.1V in reverse, maybe that's the zener voltage of them?

I did not yet try injecting a signal at other stages in the circuit, but one of the speakers had one input still kinda working and after the inductors and zener diodes are electrolytic capacitors. they should block DC and take some "force" out of harmful voltages by just blowing up. they still seemed fine, but might be also good to replace them.

I have contacted Alto about spare parts, but they only sell spae parts through their service partners / sellers. So I contacted Korn, a local store, about it. The people at Alto take their time answering the people at Korn, because Korn also had to inquire Alto, they obviously don't stock such seldom needed spare parts.

In the mean time i searched again for service manuals or schematics. I also searched for  info of similar devices from Alto and found a service manual or rather schematics for the Alto TS212S TS215S and TS218S. These are the subwoofers from the Previous versions of the TS series.

* https://elektrotanya.com/alto_ts212s_ts215s_ts218s_ver.1.0_sm_%5B2016%5D.pdf/download.html

* zener: MMSZ5242A
** "SE00243 - SMD zener diode-RS - 1/2W 12V MMSZ5242A(SOD123)/PANJIT"
** https://www.digikey.de/de/products/filter/dioden-zener-einzeln/287?s=N4IgTCBcDaILJwMoC0CsYAsYCCIC6ANCKlKAA5QCMRZFklADAwL7NA
** https://www.mouser.de/c/?q=MMSZ5242A&qty=16
* inductor:
** "CO00168 - SMD inductance-RS-ACT - 1000Ω±25% (BLM18RK102SN1D)"
** https://www.mouser.de/ProductDetail/Murata-Electronics/BLM18RK102SN1D
* https://www.digikey.de/de/products/detail/murata-electronics/BLM18RK102SN1D/1948333


After some back and forth with Korn and Korn trying several times to get an answer from Alto, i created another support ticked on the Alto homepage and informed them that Korn tried to get info for some time now. I didn't get any reply on that last ticket, but Korn had the information pretty quickly after that.

I messaged the owner about the price, but the owner had to ask the people who did the damage first, or so. That took some time. But after a while we finally had the go to order the replacement Boards from Korn. Delivery time for replacements is 3 Weeks or so.

After over a year of waiting and a lot of effort by Musikhaus Korn, Alto did not reply propperly and we were not able to get a replacement. The customer got his speakers back how we received them, no work was done.
* https://www.happareute.de
* https://www.fischerelektronik.de/web_fischer/de_DE/Geh%C3%A4use/index.xhtml
* https://www.bopla.de/gehaeusetechnik/produktkatalog-standardgehaeuse/aluminiumgehaeuse.html
* https://www.rose-systemtechnik.com/produkte/industriegehaeuse/standardgehaeuse/aluminiumgehaeuse/
https://www.hifiengine.com/manual_library/amcron/geodyne.shtml

i don't know if i will get this amp yet
* https://www.diyaudio.com/community/threads/adau1701-marries-tpa3251-low-cost-build.311908/
* https://www.3e-audio.com/dsp/adau1701-2in4out/
* https://www.hs-sound.de/TinySine-TSA1701-SET
* https://www.hs-sound.de/TinySine-TSA1701
* https://www.hs-sound.de/Verstaerker
* wondom
* https://hackaday.io/project/27375-adau144x-core-dsp-board
* https://ez.analog.com/dsp/
* ADSP
* https://www.analog.com/en/product-category/sigmadsp-audio-processors.html
* https://www.analog.com/en/parametricsearch/11321#/d=4458|4870|s3|s5
* https://www.analog.com/en/product-category/audio-signal-processors.html
* https://auverdion.de/aurora-dsp/
** https://auverdion.de/2021/04/06/firit-fir-filter-einfach-erstellt/
* https://freedsp.github.io/
* https://www.diyaudio.com/community/threads/freedsp-main-thread.285260/
* https://www.diyaudio.com/community/threads/freedsp-catamaran-a-b.381417/page-2
* http://realhdaudio.de/2018/04/27/realhdaudio-board-for-freedsp-adau1701/
* https://github.com/freeDSP/freeDSPx-AES-SPDIF-IN
* https://blog.hackster.io/the-open-source-freedsp-aurora-dsp-just-launched-on-kickstarter-96456813b405
* https://www.youtube.com/watch?v=8vDUtkF31B0
* https://oshwlab.com/imdbere/audiointerface
* http://www.hifi-forum.de/viewthread-71-13288-2.html
* https://github.com/freeDSP/freeDSP-aurora/issues/102
* https://www.youtube.com/watch?v=IxX0EGMtLJk
* https://hackaday.io/project/21119-pidsp
* http://realhdaudio.de/2018/04/27/realhdaudio-board-for-freedsp-adau1701/
* https://cyberpithilo.web.fc2.com/audio/freedsp/index.html
* https://wwwpub.zih.tu-dresden.de/~s5514549/projects.html
* https://www.diyaudio.com/community/threads/freedsp-aurora-dsp-with-8-i-os-usb-audio-s-p-dif-adat-bluetooth-and-wifi-contro.334055/
* https://github.com/freeDSP/freeDSP-aurora
* 
https://soundcertified.com/how-to-bridge-amp/
see also [[speaker / audio Dummy Load (Ersatzlast)]]

* https://geoffthegreygeek.com/understanding-amplifier-power/
* https://www.audioholics.com/audio-amplifier/basic-amplifier-measurement-techniques
* https://amplifier.cd/Tutorial/Power/output_power.htm
* https://amp-performance.de/3-messverfahren.html
* [[Klirrfaktor / THD]]
* https://andydoz.blogspot.com/2016/04/arduino-audio-wattmeter.html
* https://www.youtube.com/watch?v=hA12uYxHBXM
* [[Kiss Analog: Power supply design for audio amplifier|https://www.youtube.com/playlist?list=PLZ0_iMoMBSsl-da5T7z2BdEhNPWbYNgkT]]

* https://de.wikipedia.org/wiki/Equalizer
* https://en.wikipedia.org/wiki/Equalization_(audio)
* https://en.wikipedia.org/wiki/Electronic_filter
* https://de.wikipedia.org/wiki/Filter_(Elektrotechnik)
* most simple mixing consoles work with analog filters and EQs
* analog EQs often use opamps
* http://eq.perkaudio.net/
* https://en.wikipedia.org/wiki/Tone_control_circuit
* [[TSP #9 - Tutorial on Passive Filters, Data Transmission and Equalization|https://www.youtube.com/watch?v=MhWyAL2hKlk]]
* https://github.com/spantaleev/matrix-docker-ansible-deploy
* https://www.proaudio.de/de/tests/15877-api-500-modularsystem.html
* https://www.bonedo.de/artikel/einzelansicht/api-500-basics.html
* see [[Eurorack]]
* Gehaltsverhandlung Tipps
<<list-links "[all[current]tagging[]]">>

* https://en.wikipedia.org/wiki/Category:Video_art
* https://en.wikipedia.org/wiki/Category:Visual_effects
* https://en.wikipedia.org/wiki/Category:Computer_art
** https://de.wikipedia.org/wiki/Kategorie:Computerkunst
* [[audio visualisation]]
* [[Mark Benecke ������ Artensterben (MINTköln)|https://www.youtube.com/watch?v=Zk4Qw6YzhDg]]
* [[Mark Benecke ������ Messungen und Tatsachen zum Sterben der Arten (Vortrag)|https://www.youtube.com/watch?v=3ByO1gaxyHs]]
* [[Dr. Mark Benecke: Insektensterben|https://www.youtube.com/watch?v=A8qtdXFtyv8]]
* [[Mark Benecke ������ WGT (Wave Gotik Treffen) 2019: Artensterben|https://www.youtube.com/watch?v=g4sjn0LrVLA]]
* https://tonsky.me/blog/unicode/
* http://www.asciifacepalm.com/
* https://en.wikipedia.org/wiki/Radare2
* https://en.wikipedia.org/wiki/Ghidra
* smaller tools
** https://www.johannes-bauer.com/mcus/avrdisas/
** https://github.com/twinearthsoftware/AVRDisassembler
** some stuff on community.atmel.com
** https://github.com/vsergeev/vAVRdisasm
* https://stackoverflow.com/questions/5141177/atmel-avr-disassembler
<<list-links "[all[current]tagging[]]">>

* https://www.instructables.com/id/The-Monthly-Challenge-Audio-Hacks/
* https://www.instructables.com/id/Simple-Sound-Circuits/
* https://www.instructables.com/id/Audio/
* https://www.instructables.com/id/Introduction-to-Operational-Amplifiers/
* https://www.instructables.com/id/Arduino-Synthesizer/
* https://www.instructables.com/id/Arduino-Due-Guitar-ADC-Input-and-DAC-Output-Mixer/
* https://www.diyrecordingequipment.com/
<<list-links "[all[current]tagging[]]">>

* https://www.audioholics.com/audio-amplifier/amplifier-classes
* https://en.wikipedia.org/wiki/Power_amplifier_classes
* https://www.powersoft.com/en/products/amp-modules/d-cell-504
* https://www.crownaudio.com/how-much-amplifier-power
* [[Was steckt in der t.amp E800 PA Endstufe ?|https://www.youtube.com/watch?v=jb8HuZYCGyo]]
* https://amp-performance.de/allgem-zur-leistung-von-verstaerkern.html
* https://sound-au.com/articles.htm#ampl
* audio amplifiers are basically voltage amplifiers, the current is determined by Ohms Law and the resistance/impedance of the connected loudspeaker (Load)
* https://en.wikipedia.org/wiki/Amplifier#Power_amplifiers
* https://en.wikipedia.org/wiki/Power_amplifier_classes
* https://de.wikipedia.org/wiki/Verstärker_(Elektrotechnik)
** https://de.wikipedia.org/wiki/Audioverst%C3%A4rker
** https://de.wikipedia.org/wiki/Endstufe
* [[Advantages of Amplifier Bridged Mono Mode (Public)|https://www.youtube.com/watch?v=HYbvA1DOR9A]]
* https://sound-au.com/p-cat.htm#pwrhttps://www.learnabout-electronics.org/Amplifiers/amplifiers12.php
* https://www.learnabout-electronics.org/Amplifiers/amplifiers10.php
* https://www.learnabout-electronics.org/Amplifiers/amplifiers40.php
* https://www.learnabout-electronics.org/Amplifiers/amplifiers50.php
* https://sound-au.com/articles/amp-classes.htm
* [[Class A vs class AB vs class D... audio AMPLIFIER types, classes and topologies made SIMPLE!|https://www.youtube.com/watch?v=D73787fbWnc]]
* [[What are the Differences Between Class A, AB, and D Amplifiers?|https://www.youtube.com/watch?v=dKlVlYHAp3A]]
* [[Understanding Amplifier Class A & Class AB|https://www.youtube.com/watch?v=Aa8Yb4VIw8w]]
* [[TSP #23 - Tutorial on the Design and Characterization of Class-B and AB Amplifiers|https://www.youtube.com/watch?v=YuVqccvgNPM]]
* [[Amplifier Feedback - tomtektest|https://www.youtube.com/watch?v=mAisstb0n5Q&list=PL2u6aYAXZ0Z_XwKbYv2Fyc_CfiKW2PiUc]]
* [[ All You Need To Know About AMPLIFIERS To Fix Stuff - A Beginners Guide To Audio Amplifier Repair |https://www.youtube.com/watch?v=0oWBcTTeMNQ]]


class a

* [[20 Watt Class-A Power Amplifier Fail|https://www.youtube.com/watch?v=Kk0oDwR02Pg]]
* [[20 Watt Class A Amplifier - Bode Plot & THD|https://www.youtube.com/watch?v=D_b-i4VSjYc]]
* [[20 Watt Class A Amplifier - This is Why it Failed|https://www.youtube.com/watch?v=-VRcelNAcP0]]
* https://www.youtube.com/watch?v=GtFnkXar5JU


stuff

* https://www.youtube.com/watch?v=kmHd_hl1MGc
see also [[audio testing and measurement]]

ARTA

* DIY
* [[https://artalabs.hr/]]
* http://uibel.net/bauvor/bv_tutorials/arta/arta.html
* [[#ARTA #REW DIE BASIS - !!! Das Teil müsst ihr unbedingt nachbauen !!!|https://www.youtube.com/watch?v=qBhmLW72Qq8]]
* https://www.lautsprecherforum.eu/viewtopic.php?t=4794

Analog Discovery

* https://www.diyaudio.com/community/threads/audio-analyzer-for-digilent-analog-discovery.306499/
* https://forum.digilent.com/topic/1493-audio-analyzer-suite-for-analog-discovery/
* https://www.diyaudio.com/community/threads/analog-discovery-audio-analyzer-suite-video.376466/
* https://www.eevblog.com/forum/projects/analog-disovery-as-audio-analyzer/
* https://www.diyaudio.com/community/threads/audio-analyzer-for-digilent-analog-discovery.306499/page-2
* https://digilent.com/reference/add-ons/impedance-analyzer/start
* [[Audio Analyzer Suite Playlist|https://www.youtube.com/playlist?list=PLj1iPGXgbNf2otUxBjLh93bI31FuradPS]]
* [[Audio Analyzer & Dummy Load Using Analog Discovery 2 - 2019 Version|https://www.youtube.com/watch?v=1rOvdsxQVTY]]
* [[Audio Analyzer Suite / Analog Discovery 2 Review and Demo|https://www.youtube.com/watch?v=vZdL6jmCJvE]]

Klippel

* expensive
* see [[Klippel Production Analyser reverse enginering]]

Dayton DATS

* 200$
* https://www.daytonaudio.com/product/1650/dats-v3-computer-based-audio-component-test-system
* https://diyaudioprojects.com/Testeq/DATS/index.htm
* [[REVIEW - Dayton Audio DATS V3|https://www.youtube.com/watch?v=5FhZFpVMs00]]
* [[A Common "HORROR" Story + A Brand New Solution|https://www.youtube.com/watch?v=rexXJ2xc2ZQ]]

OSVA - open hardware

* https://www.diyaudio.com/community/threads/osva-open-source-versatile-analyzer.335005/
** https://github.com/OneAudio/OSVA

Clio Pocket

* [[LAUTSPRECHER MESSEN - CLIO Pocket 2.1 von Strassacker - Einrichtung & Kalibration|https://www.youtube.com/watch?v=1HtwI3TPxRE]]
* [[AKUSTIKMESSUNG - CLIO Pocket 2.1 von Strassacker - Akustische Messung & Funktionen|https://www.youtube.com/watch?v=EzC9iRW40qk]]

Audio Precision

* https://www.ap.com/audio-analyzers/
* https://www.ap.com/analyzers-accessories/accessories/

Rohde&Schwarz

* https://www.rohde-schwarz.com/de/produkte/messtechnik/audioanalysatoren_63675.html


stuff

* https://www.youtube.com/results?search_query=audio+analyzer
* https://hackaday.com/2021/06/02/know-audio-start-at-the-very-beginning/
* https://wiki.production-partner.de/allgemein/seitenverzeichnis-alle-themen-in-der-uebersicht/
* https://www.youtube.com/watch?v=Om_1IYsqPWg
Got an old audio cable tester for free because it was broken.

problems:

* it's missing one cinch/phono connector
* it was designed for 9V battery but someone bodged a 3V battery holder
* some screws for the case are missing


i tested it and the buzzer/single continuity tester works fine, but the wire tester doesn't work correctly.

i opened it up and noted/marked all the wire connections first. I want to clean the complete box, but in order to do so, i have to desolder all the connectors to get them out.

i cleaned the box and connectors.
While cleaning i also saw that the pcb has some liquid damage and some dried stuff still on it. I cleaned it off thoroughly with alcohol. One LED has to be resoldered because it's a bit corroded and one LED has a snapped pin. To repair the snapped of pin, i desoldered the part that remained in the pcb and used a piece of component-pin/wire from some other repair out of the scrap. i soldered the wire through the pcb and then soldered the LED pin to the wire.
I tested the function of all leds with the multimeter and they all work now.

I have some cinch/phono connectors lying around. But the Hole is to big to propperly mount the ones i got. I had the idea to maybe find a washer as spacer and i found a perfect one. I used two other wahsers and a screw to press-fit it into the case. Now i can propperly mount the cinch connector.

Before reassembly i reverse engineered the whole circuit and made a KiCAD schematic.

there are some improvements that would be nice, like a new battery compartment, but it works.

* https://en.wikipedia.org/wiki/List_of_open-source_codecs
* https://alternativeto.net/software/flac/
* https://en.wikipedia.org/wiki/Audio_codec
* https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Audio_codecs
* https://www.audioholics.com/audio-technologies/codecs
* https://de.wikipedia.org/wiki/Liste_von_Audio-Fachbegriffen
** https://de.wikipedia.org/wiki/Grenzfrequenz
** https://de.wikipedia.org/wiki/Bandbreite
* http://www.sengpielaudio.com/Tontechnikbegriffe.htm
* https://www.hifi-regler.de/lexikon/
* siehe [[Phasenwinkel, Phase, Schwingungen]]
* quarter wavelenth
* https://de.wikipedia.org/wiki/Schalldruckpegel
* https://de.wikipedia.org/wiki/Schalldruck
* https://de.wikipedia.org/wiki/Schallschnelle
* https://de.wikipedia.org/wiki/Schallkennimpedanz
* https://de.wikipedia.org/wiki/Schallintensit%C3%A4t
* https://de.wikipedia.org/wiki/Schallfluss
* https://de.wikipedia.org/wiki/Kategorie:Akustik
* https://webaudioapi.com/samples/frequency-response/
* https://webaudioapi.com/samples/filter/
* https://webaudiodemos.appspot.com/TouchPad/index.html
* https://developer.mozilla.org/en-US/docs/Web/API/BiquadFilterNode
* https://en.wikipedia.org/wiki/Q_factor
** https://de.wikipedia.org/wiki/G%C3%BCtefaktor
* https://en.wikipedia.org/wiki/Electronic_filter_topology#Biquad_filter_topology
* https://en.wikipedia.org/wiki/Digital_biquad_filter
* https://de.wikipedia.org/wiki/Tschebyscheff-Filter
* https://developer.mozilla.org/en-US/docs/Web/API/IIRFilterNode
* https://en.wikipedia.org/wiki/Infinite_impulse_response
** https://de.wikipedia.org/wiki/Filter_mit_unendlicher_Impulsantwort
* https://en.wikipedia.org/wiki/Digital_filter
** https://de.wikipedia.org/wiki/Digitales_Filter
* https://en.wikipedia.org/wiki/Finite_impulse_response
** https://de.wikipedia.org/wiki/Filter_mit_endlicher_Impulsantwort
* https://en.wikipedia.org/wiki/Category:Filter_theory
** https://de.wikipedia.org/wiki/Kategorie:Filter_(Elektrotechnik)
* https://en.wikipedia.org/wiki/Filter_design
* https://en.wikipedia.org/wiki/Equalization_(audio)
* https://en.wikipedia.org/wiki/Mason%27s_gain_formula#Digital_IIR_biquad_filter
* https://en.wikipedia.org/wiki/Electronic_filter_topology

* https://www.ti.com/design-resources/design-tools-simulation/filter-designer.html
* [[EEVblog #490 - Peak Detector Circuit|https://www.youtube.com/watch?v=jllsqRWhjGM]]
* [[TSP #9 - Tutorial on Passive Filters, Data Transmission and Equalization|https://www.youtube.com/watch?v=MhWyAL2hKlk]]
* [[active filters - tomtektest|https://www.youtube.com/watch?v=plgxcEg0aB8&list=PL2u6aYAXZ0Z8t-9s_OxGnaQXniQCUcf-7]]
* https://www.ti.com/audio-ic/overview.html
* https://www.coolaudio.com/
most external audio interfaces use USB, you should pay attention to the class compliance of the interface. if the manufacturer followed the USB specifications the interface should use the USB audio device class. devices following this are mostly marketed as "class compliant", but any interfaces not requiring drivers might be supported.

* https://en.wikipedia.org/wiki/Sound_card
** https://de.wikipedia.org/wiki/Soundkarte
* [[YT: RELOADED #BEHRINGER #SOUNDKARTE günstige Lösung ~ Reicht das kleine Audio Interface zum Messen?|https://www.youtube.com/watch?v=eUeGrMvYb2c]]
* https://www.alsa-project.org/wiki/Main_Page
** https://www.alsa-project.org/wiki/SoundcardTesting
** https://alsa.opensrc.org/
* https://source.android.com/devices/audio/usb
* https://noterepeat.com/articles/pc-troubleshooting/95-troubleshooting-class-compliant-usb-computer-peripherals
* https://hackaday.com/2022/05/24/the-stm32-makes-for-a-cheap-diy-usb-soundcard/

linux support of the interfaces i have:

* creative e-mu 0202
** seems to be supported, not fully tested yet
** https://www.alsa-project.org/wiki/Matrix:Module-emu10k1-fpga
** might have preamp issues
** no phantom power
* Tascam US-122L
** have not got it to work yet
** not class compliant
** not to be confused with the US-122
** https://www.alsa-project.org/wiki/Matrix:Module-usb-us122l
* Yamaha MG10 XU - not tested yet, should be class compliant
* steinberg UR22
** phantom power
** not supported, not class compliant
* iConnectAudio2+
** class compliant, working
** has some weird control/settings software that only runs on windows


open hardware

* https://github.com/erichVK5/PCM290x-USB-audio-interface
* https://openhw.blogspot.com/
* https://www.openmha.org/hardware/
** https://lac.linuxaudio.org/2018/pdf/35-paper.pdf
* https://blog.zynthian.org/2021/05/zynadac-v1-0-an-open-hardware-soundcard-for-zynthian/
* diyaudio.com
* http://www.sengpielaudio.com/index.html - Tontechnik
* https://www.acs.psu.edu/drussell/demos.html - Acoustics and Vibration Animations
* http://www.sengpielaudio.com/Berechnungen.htm
* http://www.openmusiclabs.com/index.html
* https://www.speakerplans.com/index.php?id=links
* https://www.youtube.com/c/SonicVisionTV1/playlists
* https://www.akustikdesign.at/grundlagen-der-akustik/
* https://de.wikibooks.org/wiki/Grundlagen_der_Akustik
* http://medi.uni-oldenburg.de/download/docs/lehre/pichl09/08_Blau.pdf
* https://de.wikibooks.org/wiki/Grundlagen_der_Akustik:_Physikalische_Grundlagen
* https://www.bonedo.de/artikel/einzelansicht/akustik-grundlagen.html
* https://circuitdigest.com/audio-circuits
* auna
* skytec
* electron
* MC crypt
* Rockwood
* https://www.epanorama.net/newepa/2021/04/17/xlr-over-cat-567/
* Tascam or yamaha DB25 cables
<<list-links "[all[current]tagging[]]">>

knowledge/guides/tutorials

* https://dobrian.github.io/cmp/index.html

lists

* https://github.com/topics/spectrum-analyzer
* https://github.com/topics/signal-processing
* https://github.com/topics/realtime-audio

software

* https://github.com/markjay4k/Audio-Spectrum-Analyzer-in-Python
* https://github.com/tyiannak/pyAudioAnalysis
** https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0144610
* https://github.com/scottlawsonbc/audio-reactive-led-strip
* http://ajaxsoundstudio.com/software/pyo/ - https://github.com/belangeo/pyo
* https://madmom.readthedocs.io/en/latest/ - https://github.com/CPJKU/madmom
* Somewhat crude THD+N calculator in Python: https://gist.github.com/endolith/246092
* https://github.com/endolith/waveform_analysis
* https://github.com/cournape/audiolab - https://cournape.github.io/audiolab/index.html
* https://www.scipy.org/
** https://www.scipy.org/getting-started.html
* https://stackoverflow.com/questions/42077247/calculating-thd-in-python

python

* https://soundcard.readthedocs.io/en/latest/
<<list-links "[all[current]tagging[]]">>
<<list-links "[all[current]tagging[]]">>

youtube channels about audio equipment repairs

* [[FeedbackLoop|https://www.youtube.com/channel/UCy8KVhry-wrEcHKcSb4BiMg/videos]]
* https://www.youtube.com/c/TheRadioShop/videos
* https://www.youtube.com/c/simonspiers/videos


stuff

* [[Altec Lansing Speaker will only play loud Static noise - Motherboard repair & BIG BOSS DANCING|https://www.youtube.com/watch?v=m7QjPZ4nzAc]]
* http://studiorepair.com/gallery/index.html

* DLNA/~UPnP

* VBAN - https://vb-audio.com/Voicemeeter/vban.htm
** [[VBAN Protocol Specification|https://vb-audio.com/Voicemeeter/VBANProtocol_Specifications.pdf]]
** https://github.com/quiniouben/vban - open source linux implementation

* https://duckduckgo.com/?q=linux+stream+wav+audio&t=ffab&ia=web
* [[RTP|https://en.wikipedia.org/wiki/Real-time_Transport_Protocol]], [[RTSP|https://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol]], [[RTCP|https://en.wikipedia.org/wiki/RTCP]]
* https://en.wikipedia.org/wiki/Audio_over_IP
* https://en.wikipedia.org/wiki/Comparison_of_audio_network_protocols

* Ethernet AVB
** https://www.linux-magazin.de/ausgaben/2013/11/avb/
** https://de.wikipedia.org/wiki/Audio/Video_Bridging
** https://en.wikipedia.org/wiki/Audio_Video_Bridging
** https://github.com/audioscience/Open-AVB
** http://avnu.github.io/OpenAvnu/

* [[AES: Audio Networking Resources|https://secure.aes.org/members/insidetrack/201810/]]
** AES50
** [[AES67-2018: AES standard for audio applications of networks - High-performance streaming audio-over-IP interoperability|https://www.aes.org/publications/standards/search.cfm?docID=96]]
* [[behringer ultranet]]

* https://trac.ffmpeg.org/wiki/StreamingGuide
* https://stackoverflow.com/questions/11644625/rtp-streaming-with-ffmpeg
* https://www.youtube.com/watch?v=ZXz-u1f-uw0
* https://www.linux.com/training-tutorials/weekend-project-using-pulseaudio-share-sound-across-all-your-computers/
* https://stackoverflow.com/questions/2795031/synchronizing-audio-over-a-network
* https://stmllr.net/blog/streaming-audio-with-mpd-and-icecast2-on-raspberry-pi/
* https://wiki.archlinux.org/index.php/Music_Player_Daemon/Tips_and_tricks#HTTP_streaming
* https://www.musicpd.org/doc/html/user.html#satellite
* https://wiki.archlinux.org/index.php/Icecast

* https://www.musicpd.org/
** https://wiki.ubuntuusers.de/MPD/
** https://wiki.archlinux.org/index.php/Music_Player_Daemon#Multi-MPD_setup
** https://en.wikipedia.org/wiki/List_of_Linux_audio_software#Music_Player_Daemon_based

* https://gstreamer.freedesktop.org/
** https://github.com/matthew1000/gstreamer-cheat-sheet
** https://arunraghavan.net/2016/11/gstreamer-and-synchronisation-made-easy/
** https://gstreamer.freedesktop.org/documentation/application-development/advanced/clocks.html?gi-language=c
** [[Synchronised multi-room multimedia playback and synchronised live media processing and mixing with G|https://www.youtube.com/watch?v=C7sH4TSc054]]
** https://archive.org/details/lca2020-Synchronised_Playback_with_GStreamer

* https://www.linux.com/topic/desktop/how-stream-audio-your-linux-pc-android/
* https://blog.michael.franzl.name/2013/11/25/audio-streaming/
* https://www.linuxquestions.org/questions/linux-software-2/linux-audio-streaming-server-4175441805/
* https://www.linux.com/topic/desktop/5-streaming-audio-players-linux/

* proprietary, professional:
** Dante
*** https://www.audinate.com/products/dante-enabled/audinate/audinate-dante-avio-aes3-ebu
*** https://www.audinate.com/products/devices/dante-avio
*** https://assets.audinate.com/wp-content/uploads/2022/03/Dante-AVIO-AES3-Marketing-Datasheet-03102022.pdf

* https://sonobus.net/

* https://jamulus.io/

* [[Digital vs Analog Audio - X32/M32 AES50, Routing Latency (Public)|https://www.youtube.com/watch?v=hSYXAV-rpOg]]

* https://www.eetimes.com/achieving-ultra-low-latency-digital-wireless-audio/
* https://www.techhive.com/article/583730/wisa-low-latency-wireless-multi-channel-audio-standard.html
* https://www.reddit.com/r/CommercialAV/comments/9me47n/lowest_possible_latency_wireless_audio_streaming/
* RT-WIFI
** https://ieeexplore.ieee.org/document/6728869
** https://arxiv.org/pdf/2203.10390.pdf
** https://link.springer.com/chapter/10.1007/978-3-030-31831-4_20
** https://ls12-www.cs.tu-dortmund.de/daes/media/documents/teaching/courses/rts/rt-wifi.pdf
** https://pdfs.semanticscholar.org/984b/d8f9d17e63e25e18cd01f232c9a2d2313740.pdf
** https://arxiv.org/abs/2203.10390
<<list-links "[all[current]tagging[]]">>


* https://en.wikipedia.org/wiki/Electrical_characteristics_of_dynamic_loudspeakers
* https://en.wikipedia.org/wiki/Audio_system_measurements
* https://www.youtube.com/watch?v=ninFs1HWcMs&list=PLupjt2J2x38fUAiUFobzyJwUvy_Uq8ToW
* [[YT: #BEHRINGER #SOUNDKARTE günstige Lösung ~ Reicht das kleine Audio Interface zum Messen?|https://www.youtube.com/watch?v=JsDxViPYhOc]]
* https://en.wikipedia.org/wiki/Smaart
** https://www.rationalacoustics.com/smaart/about-smaart/
* REW Room EQ Wizard
* Theremino
** [[WaveAnalyzer|https://www.theremino.com/en/downloads/uncategorized#waveanalyzer]]
** [[WaveGenerator|https://www.theremino.com/en/downloads/uncategorized#wavegenerator]]
** [[Audio Input with Vumeter|https://www.theremino.com/en/downloads/multimedia#audioinput]]
** [[AudioExamples (playing, various)|https://www.theremino.com/en/downloads/multimedia#audioexamples]]
** [[AudioAnalyzer|https://www.theremino.com/en/downloads/multimedia#audioanalyzer]]
** [[DAA – audio analyzer and oscilloscope|https://www.theremino.com/en/downloads/uncategorized#daa]]
* https://en.wikipedia.org/wiki/Category:Acoustic_measurement
* https://en.wikipedia.org/wiki/Category:Signal_processing
* https://en.wikipedia.org/wiki/Category:Time%E2%80%93frequency_analysis
* https://en.wikipedia.org/wiki/Category:Time_domain_analysis
* https://en.wikipedia.org/wiki/Impulse_response
* https://en.wikipedia.org/wiki/Waterfall_plot
* https://en.wikipedia.org/wiki/Loudspeaker_acoustics
* https://en.wikipedia.org/wiki/Loudspeaker_measurement
* https://en.wikipedia.org/wiki/Category:Sound_measurements
* https://en.wikipedia.org/wiki/Category:Acoustic_measurement
* http://spectrum3d.sourceforge.net/
* https://github.com/YongChingTee/spectrogram_gtk/
* https://octave.sourceforge.io/signal/function/specgram.html
* https://sourceforge.net/projects/ltfat/
* https://ltfat.github.io/
* https://www.nti-audio.com/en/support/know-how/lets-clear-up-some-things-about-sweeps
* https://www.audiocheck.net/index.php
* https://onlinetonegenerator.com/
* https://satsignal.eu/software/audio.html - freeware, but can be pretty easily implemented as open source
* https://theaudioprogrammer.com/signal-analysis-ii-linear-vs-logarithmic-sine-sweep/
* https://www.paulvdiyblogs.net/2017/10/setting-up-fft-measuring-system.html
* https://www.paulvdiyblogs.net/2015/05/simple-but-precisice-1khz-distortion.html
* https://www.hifi-selbstbau.de/grundlagen-mainmenu-35/softwaremesstechnik-mainmenu-66
* https://www.tolvan.com/index.php?page=/main/home.php
* https://sound-au.com/project93.htm
* https://sound-au.com/p-cat.htm#tst
* https://ltfat.org/
* https://sndtools.cs.princeton.edu/
* https://www.academia.edu/33571411/ESTABLISHING_THE_PERFORMANCE_OF_A_DIY_TAPPED_HORN_LOUDSPEAKER?f_ri=1381325
* https://www.academia.edu/33571535/ESTABLISHING_THE_PERFORMANCE_OF_A_DIY_TAPPED_HORN_SUBWOOFER?f_ri=1381325
* https://en.wikipedia.org/wiki/Category:Time%E2%80%93frequency_analysis
* https://en.wikipedia.org/wiki/Category:Acoustics_software
* https://www.merlijnvanveen.nl/en/calculators
* systune - expensive
** https://www.afmg.eu/en/afmg-systune
** https://paforum.de/forum/index.php?thread/136473-systune-vs-satlive-vs-smaart-di-rita-praxiserfahrungen-im-vergleich/
** https://paforum.de/forum/index.php?thread/84673-neue-software-systune-oder-smaart-7/
** https://www.mediterraneanacoustics.com/systune---professional-audio-measurement.html

* ''[[ Build A Sound System Tuning Rig For Under $250 |https://www.youtube.com/watch?v=uLMkjVaKNqY]]''
** ''[[Soundsystem]]''
** ''[[ How To Connect Your Sound System Tuning Rig And Take A Measurement|https://www.youtube.com/watch?v=8iwFjAmo8TM]]''
** ''[[ Open Sound Meter Fundamentals - Sound System Tuning Software Walkthrough For Beginners |https://www.youtube.com/watch?v=R36WHCI9j0k]]''
* [[ Stereo Club Anlage upgraden und mit Smaart einmessen - Auftrag Sound 17 |https://www.youtube.com/watch?v=CvRvy91wfsY]]
* [[Phasenwinkel, Phase, Schwingungen]]
** [[ELENDES GEZAPPEL - Phasenverlauf einfach erklärt #REW|https://www.youtube.com/watch?v=zYf8fzJcA7A]]

plots:

* 2d/3d spectrogram
* sound level meter (db SPL (peak))
* just the "normal" audio waveform

distortion (klirrfaktor)

* http://www.jobst-audio.de/tools-nuetzliches/klirrfaktor
* https://www.paulvdiyblogs.net/2015/05/simple-but-precisice-1khz-distortion.html


linux/open source

* https://www.linuxlinks.com/best-free-open-source-audio-analyzers/
* https://www.linuxcompatible.org/story/9-best-free-and-open-source-audio-analyzers/
* https://www.reddit.com/r/livesound/comments/fvfbo9/open_source_audio_analyzer/
* https://awesomeopensource.com/projects/audio/spectrum-analyzer
* https://github.com/topics/audio-analyzer
* https://friture.org/
* https://opensource.com/article/19/9/audio-processing-machine-learning-python
** https://pubmed.ncbi.nlm.nih.gov/26656189/
* https://www.opensourceagenda.com/projects/audio-spectrum-analyzer-in-python
* https://en.wikipedia.org/wiki/Comparison_of_free_software_for_audio#Audio_analysis
** https://en.wikipedia.org/wiki/BRP-PACU
** ~~https://en.wikipedia.org/wiki/Baudline~~ - not open source, but useful feature list
* https://sonicvisualiser.org/
** https://en.wikipedia.org/wiki/Sonic_Visualiser
* https://github.com/alexkay/spek
** https://web.archive.org/web/20210729045511/http://spek.cc/
** https://www.hecticgeek.com/spek-free-acoustic-spectrum-analyzer/
* https://sourceforge.net/projects/audmes/
* see [[open source spectrum analysis software]]
* https://opensoundmeter.com/en/
** https://github.com/psmokotnin/osm
** https://opensoundmeter.com/en/tools
*** https://github.com/psmokotnin/SubAlign
** ''[[ Open Sound Meter Fundamentals - Sound System Tuning Software Walkthrough For Beginners |https://www.youtube.com/watch?v=R36WHCI9j0k]]''


* SMD
** im-sg+ - Impedance meter / signal generator
** amm-1 - audio multi meter



amplifier bode plot

* [[30W Class A amplifier - finding max power Bode Plot with Omicron Lab|https://www.youtube.com/watch?v=qjWaGvhO-d8]]
* [[ ICEpower 125ASX2 Class D Amplifier - Bode Plot and THD measurement with GW Instek Oscilloscope |https://www.youtube.com/watch?v=WxZlFJ2j8YA]]
* [[ Class D Amplifier TPA 3255 Bode Plot with Omicron Lab Bode 100 |https://www.youtube.com/watch?v=UDx8ftvKU3A]]
* https://biniou.net/
* http://mrkrbrts.com/blog/
* https://github.com/projectM-visualizer/projectm
* https://en.wikipedia.org/wiki/MilkDrop
* https://en.wikipedia.org/wiki/Music_visualization
* https://en.wikipedia.org/wiki/Category:Music_visualization_software
* https://tytel.org/lissa/
* https://tytel.org/
* https://sndtools.cs.princeton.edu/
** https://designbynoble.wordpress.com/2008/06/02/sndpeek-open-source-audio-visualization/
* spectrum analyzers
* [[ELECTRONICOS FANTASTICOS!|https://www.youtube.com/channel/UCU85cqdRQh8HBpk94vbcS_g]]
* https://ccrma.stanford.edu/software/snd/ - https://en.wikipedia.org/wiki/Spectrogram
* http://spectrum3d.sourceforge.net/
* https://github.com/YongChingTee/spectrogram_gtk/
* https://octave.sourceforge.io/signal/function/specgram.html
* https://sourceforge.net/projects/ltfat/
* https://ltfat.github.io/
* https://en.wikipedia.org/wiki/Lissajous_curve
** https://de.wikipedia.org/wiki/Lissajous-Figur
* https://www.youtube.com/user/jerobeamfenderson1
* https://www.vitling.xyz/
* https://github.com/projectM-visualizer/projectm
* https://resolume.com/ - expensive
* https://en.wikipedia.org/wiki/Libvisual
* http://libvisual.org/
* https://www.conrad.com/p/voltcraft-slc-100-sound-level-calibrator-101291 - 115€
* https://www.thomann.de/de/digital_sound_8930b.htm - 75€
** https://www.conrad.com/p/pce-instruments-pce-sc-43-calibrator-2583836 - 131€
* https://www.peaktech.de/PeakTech-P-8010-Schallpegelkalibrator-94-dB-1-Pa-114-dB-10-Pa/P-8010 - ~120€
* one might find cheaper options directly from china, the ones above are anyways just rebranded

* [[Messsystem einfach kalibrieren mit Schallpegelkalibrator als Referenz|https://www.youtube.com/watch?v=Qut7LIH-G8s]]
* https://ufer-projekte.de/allmende/
* Kulturbüro vlt.?
* Stura (als Student*in)
* Rosenwerk/Konglomerat (haben unterhanderem diverse Werkzeug-sets die ausleihbar sind)
* Sukuma/XR - Beamer
* TechnikKollektivDD - Veranstaltungstechnik (Sound)
* [[my equipment]]
* https://www.bibo-dresden.de/de/bibliothek-der-dinge.php
* https://www.dresden.de/de/stadtraum/umwelt/abfall-stadtreinigung/entsorgung/gebrauchtwaren/ausleihen.php
Tools

* https://en.wikipedia.org/wiki/Comparison_of_backup_software
* https://en.wikipedia.org/wiki/List_of_backup_software
* https://www.bacula.org/
** https://de.wikipedia.org/wiki/Bacula
** https://wiki.ubuntuusers.de/Bacula/
* https://en.wikipedia.org/wiki/Proxmox_Backup_Server
** https://pbs.proxmox.com/wiki/index.php/Main_Page
* https://www.borgbackup.org/
** https://github.com/borgbackup/borg
* Attic
* https://restic.net/
* http://duplicity.nongnu.org/
** https://help.ubuntu.com/community/DuplicityBackupHowto
** http://duplicity.nongnu.org/duplicity.1.html
** https://wiki.gnome.org/Apps/DejaDup

information

* https://media.ccc.de/search/?q=backup
* https://www.howtogeek.com/346907/backups-vs.-redundancy-what%E2%80%99s-the-difference/
* see [[DIY FLOSS home NAS]]

commercial services:

* https://en.wikipedia.org/wiki/Backblaze - is said to be cheap and pretty good
** Backblaze B2
*** https://www.backblaze.com/b2/docs/quick_account.html
*** https://help.backblaze.com/hc/en-us/articles/217664628-How-does-Backblaze-support-Linux-Users-
*** Restic on linux: https://help.backblaze.com/hc/en-us/articles/115002880514-How-to-configure-Backblaze-B2-with-Restic-on-Linux
*** Duplicity on Linux:
**** https://help.backblaze.com/hc/en-us/articles/115001518354-How-to-configure-Backblaze-B2-with-Duplicity-on-Linux
**** https://www.loganmarchione.com/2017/07/backblaze-b2-backup-setup/
* https://duplicacy.com/guide.html - shared source, still proprietary
** https://github.com/gilbertchen/duplicacy


!!! docker backup


<<<
~WhiteKIBA, [23.03.21 15:30]
Du kannst halt docker volumes exportieren und dann sichern. Alternativ vermeidest du volumes und mountest die Pfade auf deinem lokalen Dateisystem was das grundsätzliche handling sehr vereinfacht

Wenn du die volumes exportierst wirst du dir ziemlich einen abbrechen die inkrementell zu sichern

Ich würde grundsätzlich empfehlen nur Dinge in volumes zu speichern die potentiell für den Betrieb nicht essentiell sind und für alles was sichernswerte Daten enthält volume mounts zu nutzen die auf dem lokalen Dateisystem liegen. Das macht Backups wesentlich angenehmer und falls man an den Dateien mal was manuell basteln muss muss man nicht erst nen temporären ordner starten in dem man die nötigen tools hat

<<<




!!! Backblaze B2 backup using duplicity

1. install

```
sudo apt update -y
sudo apt install -y duplicity
```
2. [[Setup GPG|https://www.loganmarchione.com/2015/12/a-brief-introduction-to-gpg/#generate-a-key-pair]]; backup the GPG keys and passphrases somewhere else

3. create script in a folder where you store your configs or other scripts

```
#!/bin/sh

# Backblaze B2 configuration variables
B2_ACCOUNT="AAA"
B2_KEY="BBB"
B2_BUCKET="CCC"
B2_DIR="backups"

# Local directory to backup
LOCAL_DIR="/var/lib/docker/volumes/"

# GPG key (last 8 characters)
ENC_KEY="EEEEEEEE"
SGN_KEY="FFFFFFFF"
export PASSPHRASE="GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG"
export SIGN_PASSPHRASE="HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH" 

# Remove files older than 90 days
duplicity \
 --sign-key $SGN_KEY --encrypt-key $ENC_KEY \
 remove-older-than 90D --force \
 b2://${B2_ACCOUNT}:${B2_KEY}@${B2_BUCKET}/${B2_DIR}

# Perform the backup, make a full backup if it's been over 30 days
duplicity \
 --sign-key $SGN_KEY --encrypt-key $ENC_KEY \
 --full-if-older-than 30D \
 ${LOCAL_DIR} b2://${B2_ACCOUNT}:${B2_KEY}@${B2_BUCKET}/${B2_DIR}

# Cleanup failures
duplicity \
 cleanup --force \
 --sign-key $SGN_KEY --encrypt-key $ENC_KEY \
 b2://${B2_ACCOUNT}:${B2_KEY}@${B2_BUCKET}/${B2_DIR}

# Show collection-status
duplicity collection-status \
 --sign-key $SGN_KEY --encrypt-key $ENC_KEY \
  b2://${B2_ACCOUNT}:${B2_KEY}@${B2_BUCKET}/${B2_DIR}

# Unset variables
unset B2_ACCOUNT
unset B2_KEY
unset B2_BUCKET
unset B2_DIR
unset LOCAL_DIR
unset ENC_KEY
unset SGN_KEY
unset PASSPHRASE
unset SIGN_PASSPHRASE
```
4. see [[systemd unit/timers]]


sources:

* https://help.backblaze.com/hc/en-us/articles/115001518354-How-to-configure-Backblaze-B2-with-Duplicity-on-Linux
* https://www.loganmarchione.com/2017/07/backblaze-b2-backup-setup/
* https://help.ubuntu.com/community/DuplicityBackupHowto
* http://duplicity.nongnu.org/duplicity.1.html
* https://shields.io/
* https://forthebadge.com/
* https://naereen.github.io/badges/
* https://github.com/Naereen/badges
* https://licensebuttons.net/
* https://github.com/ellerbrock/open-source-badges/
* https://github.com/bevacqua/awesome-badges
* in PA mostly [[XLR]] or sometimes TRS 6,3mm jack is used
* https://en.wikipedia.org/wiki/Balanced_audio
** https://de.wikipedia.org/wiki/Symmetrische_Signal%C3%BCbertragung
* https://en.wikipedia.org/wiki/DI_unit
** https://de.wikipedia.org/wiki/DI-Box
* https://en.wikipedia.org/wiki/Balun
** https://de.wikipedia.org/wiki/Balun
* [[Understanding Balanced Audio|https://www.youtube.com/watch?v=N1lJCL5OCxM]]
* https://www.deutschlandfunknova.de/beitrag/sonnenstrom-nutzen-ein-micro-solarkraftwerk-bauen
* https://www.heise.de/ratgeber/Balkonkraftwerke-Die-haeufigsten-Fragen-zu-Installation-etc-und-die-Antworten-7311273.html
i was tasked to repair two base hazer pro form hazebase, which didn't pump any fluid anymore after being used with water-diluted fog-fluid.

* [[Inside a theatrical haze machine.  (hazer)|https://www.youtube.com/watch?v=SR9p2tDPA_U]] - basically the same
* https://www.hazebaseamerica.com/base_hazer_pro.php
* https://web.archive.org/web/20180211092921/http://hazebase.com/product/basehazerpro/
* https://ulkapumps.com/collections/ulka-pump-nme-series?filter.p.m.custom.voltage=220V - probably the pump model-series

i removed the hazer from the transport-case and unscrewed the lid to measure and check components individually.

most hazers seem to have a blower, a fluid pump (Ulka, 230-240V 50Hz; NME series?) and an air pump, as well as the heater with vaporizer and control circuitry.
the fluid pump is a small vibrating piston pump working similar to a solenoid. it can also be found in coffee machines and similar.
the fluid and the air from the air pump get mixed right behind the fluid pump and moved through the vaporizer.

the blower and air pump were working fine and i could press some leftover fluid out of a piece of hose. the fluid droplets then got moved to the vaporizer by the air and vaporized into a bit of mist.
but the fluid pump wasn't working.

I tried measuring the power supply of the pump and also the pumps resistance with a multimeter. the pump has a built-in diode, so measuring the resistance is only possible in one polarity. The fluid pumps measured around 6MOhm.
I could not really measure a good power supply, so I suspected the AHQ3223 was to blame. The chip is a solid state relay and switches the power for the pump.
The air pump, fluid pump and some other stuff are on the same fuse, and it was fine. And between the grid power and the pump is nothing except the fuse and the chip controlled by the microcontroller. the microcontroller drives everything else just fine and we cannot replace it, doe to not having the firmware.
so we decided to order some AHQ3223 to try replacing those, but replacing them did nothing to get the pumps working again. So it could only be the pumps themself.

we ordered two replacement fluid pumps from hazebase, because they removed the model-stickers from the original manufacturer. the pump has some markings "NME A", but there is no NME "A" model, maybe the NME Type 4.
After installing the new pumps everything worked fine again. Then i also learned that the pumps are pulsed, so i could not have measured a good supply with the multimeter, it would have required a oscilloscope, but isolated with a isolation transformer or differential high voltage probe.

We obviously didn't use the old fluid again and did a ~10min test run, to also flush out all old fluid.

I took the old, seized fluid pumps home to try to revive them. I disassembled them, thoroughly flushed the internal pumping parts with distilled water and assembled the pumps again. I connected the pumps directly up to 230V 50Hz grid power and after a few seconds they vibrated themself loose and worked fine again. Maybe we keep them as spares.
later i also found some videos: https://www.youtube.com/results?search_query=ulka+pump
* helmholtz resonator
* LABHorn
** https://forums.prosoundweb.com/index.php?topic=76300.0
** https://www.eminence.com/speakers/speaker-detail/?model=LAB_12
** https://www.eminence.com/support/faq/ - "How do I avoid failures with my LAB12 subwoofer?"
* https://jhsaudio.com/design.html
* Leach's horn design equations
** "You state that the Kilomax 18 is not to be used in horn loaded enclosures. Is this because the cone is not rigid enough to withstand the extra pressure?" - https://www.eminence.com/support/faq/
* http://hornplans.free.fr/
* synergy and unity horns
** http://www.hificircuit.com/community/threads/index-of-diy-synergy-and-unity-horns.23/
* Basshörner: http://www.hifi-forum.de/viewthread-127-3337.html
* https://www.youtube.com/watch?v=jVpUe46yaUE
* ~~RCF kaltgeräte kabel 3m?~~
* vlt. neues 25m verlängerungskabel mit XLR dran?

* Mini PARs
** LED Linsen
** high power LED
** LED driver
** heatsink

* Hope Rack
** ~~DB15 conn~~
** kabel reparieren
** ~~DCX XLR-mod connectors sind da~~
** ~~dsp~~
** DCX hat wieder probleme

* [[thomann t.box MA120 MK2 active monitor speaker repair]]

* [[QSC PL1.8|QSC Powerlight 1.8 repair]] mosfets durch

* 250Ah LFP pack active balancer

* [[Fidek FPA-10A|Fidek FPA-10A repair]]
** netzkabel

* [[thomann the t.amp TSA1400|thomann the t.amp TSA1400 repair]]
** IR gp4063d
*** https://www.infineon.com/dgdl/Infineon-IRGP4063D-DataSheet-vNA-EN.pdf?fileId=5546d462533600a401535655ee0c2450
*** https://octopart.com/search?q=gp4063d&currency=USD&specs=0
*** https://www.digikey.de/de/products/detail/infineon-technologies/IRGP4063DPBF/1300610
*** https://www.digikey.de/de/products/filter/transistoren/igbts/einzelne-igbts/279?s=N4IgTCBcDaIOYAcAsAGAbAZgCYgLoF8g

* akku projekt


* SoSy DSPs

* Regal Addons

* diverse mischpulte und audio interfaces

* Lastenrad Lotte

* [[WSP BoXZY CNC]]
* [[Konglomerat wood CNC, buildbotics controller repair]]


wait

* reloop amp

* [[Carver PM-1.5|Carver PM-1.5 repair]]
**

* [[Eric NA9201|Eric NA9201 repair]]
**

new

* Arta Messbox
* amp dyno
* DIY Amps
* DIY lautsprecher


teile da

* QSC PL1.8
** reparieren
** testen

* Monstertruck
** reifen kleben
** verkaufen

doku

* kamera
* behringer monitor
** mov + ntc und sicherung + test
* 
* [[How dangerous are LiPo batteries? ~ Overcharge, Overdischarge, Short Circuit|https://www.youtube.com/watch?v=osfgkFyq7lA]]
* [[Li-Ion battery short circuit,overcharge,undervoltage EXPERIMENT|https://www.youtube.com/watch?v=bNNWbm681AI&t=43s]]
* [[Testing LCBs (Lithium Ceramic Batteries) ~ The Future of Battery Technology?|https://www.youtube.com/watch?v=kJXRyWQgOY4]]
there are programmable battery management systems which are more expensive, but there are also simpler ones which are only for specific battery technologies and for a specific number of cells in series / for a specific voltage.

a BMS does these important tasks:

* monitor cell voltage when chargin to prevent overcharging and overvoltage protection
* monitor cell voltage when discharging to prevent overdischarging
* balancing the cells when charging/discharging
* overcurrent protection, to protect the batteries from short circuits
* monitoring cell themp to prevent overheating (thermal cutout) (not as important in low power applications)
* some might have serial connections so you can use a microcontroller to read the voltage and some might have build-in visible charge readouts or you can set them to only charge or discharge to a specific percentage

some cell technologies might have special needs, e.g. LiFePO4 doesn't like beeing charged with themps under 0°C

all this is so the cells are protected, live longer and faults like thermal runaways are prevented

there are cheap bms boards from asia which should work perfectly fine fir smaller, low power applications, but with bigger high power projects you might need something better.

balancing?

* passive
** is the most common and simplest type of cell balancing
* active
** benefits?

open hardware BMS:

* https://openbms.net/
** http://scienceenvy.com/open-bms/
** https://github.com/Teslafly/OpenBMS
** https://hackaday.io/project/25512-open-bms
* https://hackaday.io/search?term=BMS
* https://libre.solar/devices/bms-overview
** https://wiki.opensourceecology.de/LibreSolar_BMS_%E2%80%93_Batterie_Management_System
** https://learn.libre.solar/system/bms.html
** https://electrodacus.com/
** [[Electrodacus -Open Source- Solar Battery Management System: Introduction and Setup|https://www.youtube.com/watch?v=eCspxDLZR9U]]
* https://github.com/EnnoidMe/ENNOID-BMS
* https://endless-sphere.com/forums/viewtopic.php?t=92952
* https://github.com/Teslafly/OpenBMS
* https://foxbms.org/
* https://github.com/Tom-evnut/TeslaBMS
** https://github.com/Tom-evnut/SimpBMS
* diyBMS
** https://github.com/stuartpittaway/diyBMSv4
** [[diyBMS Upgrade|https://www.youtube.com/watch?v=0iOya8RvJ_k]]
** [[DIYBMS - How to order and build it|https://www.youtube.com/watch?v=ErxDBzra15A]]


stuff

* [[BMS (Battery Management System) DIY or Buy - Properly protecting Li-Ion/Li-Po Battery Packs|https://www.youtube.com/watch?v=rT-1gvkFj60]]
* [[Small BMS Vs Large BMS|https://www.youtube.com/watch?v=0gmSMfeDpZ0]]
* https://en.wikipedia.org/wiki/Battery_management_system
* https://www.eevblog.com/forum/manufacture/smart-bms-design/msg3300940/#msg3300940
* reference designs
** https://www.ti.com/solution/battery-management-system-bms
** https://www.ti.com/applications/industrial/power-delivery/overview.html -> battery packs
** https://www.ti.com/solution/energy-storage-battery-packs-with-bms
* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:bms
* [[Homemade BMS - Balanced LiPo Charger Multiple Cells and Current Limit|https://www.youtube.com/watch?v=qRVEJjk5B_g]]
* https://mitxela.com/projects/lipocheck
* [[Lithium cell balancer reverse engineering with schematic|https://www.youtube.com/watch?v=kDjUQVwbmik]]


Proprietary BMS

* Daly BMS
** https://www.dalyelec.eu/ - reseller, not official
** Aliexpress/alibaba/ebay
** https://dalyelec.en.alibaba.com/
** https://diysolarforum.com/resources/daly-smart-bms-manual-and-documentation.48/
* https://www.energusps.com/shop/product/tiny-bms-s516-150a-750a-36

Jaibaida (JBD) / xiaoxiang

* https://diysolarforum.com/threads/jbd-xiaoxiang-bms-apps-list.29890/
* BYD
* CATL
* ~ThunderSky Winston
what i call "battery monitors" are different displays with microcontrollers meassuring different battery parameters (like voltage and current) in order to display those numbers and calculate the state of charge of batteries and battery packs.

you can get these as separate parts (like pretty cheap but useful ones from china) or use data from a (smart) BMS or inverter. most smart BMS cost more and come with a bluetooth adapter and better or worse apps, the protocol/data not being particularly open source... most inverters only have rudimentary outputs not sufficient... so additional battery monitors might be a cheap and easy way.

the voltage meassurement ist pretty straight forward, but there are different options for current meassurement:

* shunt
** internal for smaller currents
** external for high currents
* hall sensor (external)
(mainly meant for lithium battery packs)

* use wire that is rated for enough amps
* check your nickel strips if they can sustain the amperage without getting warm
** https://electric-skateboard.builders/t/how-much-current-can-nickel-strip-handle/43081/27
** https://endless-sphere.com/forums/viewtopic.php?f=14&t=68005
* use fuse wire or thermal fuses between a couple of cells in parallel to prevent to much dammage in case of a cell shorting
* use a [[BMS|Battery Management System (BMS)]] (might allready integrate some features)
* use a fuse on the output
** https://learn.libre.solar/system/wires_fuses.html
* use a thermal cutoff
** https://de.wikipedia.org/wiki/Temperatursicherung
** https://en.wikipedia.org/wiki/Thermal_cutoff
* [[How to Make Battery Cables the Right Way and the Easy Way|https://www.youtube.com/watch?v=XkMdlPsBxkc]]
* https://media.blackhat.com/bh-us-11/Miller/BH_US_11_Miller_Battery_Firmware_Public_WP.pdf
* [[Wanna make 18650 Battery Packs? WATCH THIS FIRST!|https://www.youtube.com/watch?v=f9hsqDr381o]]

stuff:

* https://help.orf.at/stories/3203081/
a battery pack consists of different parts

required:

* accumulator cells - the cells which actually store the energy and are connected in series or parallel to produce the desired capacity and voltage
* some good connector do make it detachable and changeable

recommended:

* [[Battery Management System (BMS)]] - continuously checks the battery status to prolong the life and ensure secure operation
* housing to protect the battery and other electronics as well as the connections and the user

optional:

* some display or readout to show the status and change

rack mounted

* https://www.youtube.com/watch?v=SYJ25izYSGc


stuff

* [[Creating my single biggest D.I.Y. battery with 2800 18650 cells recovered from used laptop batteries|https://www.youtube.com/watch?v=PenPYwa00CA]]
* [[High-Capacity Off-Grid Solar Generator (rev 4) -- Wiring Diagram, Parts List, Design Worksheet|https://www.youtube.com/watch?v=QZYAAatdlmc]]
* [[Complete LiFePO4 Solar Battery System Design|https://www.youtube.com/watch?v=_PgthByAYz4]]
* [[Simple DIY Powerwall using $1 LG 18650 eBay Cells|https://www.youtube.com/watch?v=g7V9XQ34chc]]
* [[DIY 400 Watt 12 volt Solar Power System Beginner Tutorial: Great for RV's and Vans! *Part 1*|https://www.youtube.com/watch?v=IRRKHYwB3Uo]]
* [[This Device could bring emergency power to Puerto Rico|https://www.youtube.com/watch?v=m04CXhoQ2jU]]
* [[DIY Inergy Kodiak Solar Generator|https://www.youtube.com/watch?v=ZDSOIN0egMo]]
* [[600,000mAh DIY Power Pack build|https://www.youtube.com/watch?v=bn0KtdrpoEM&t=139s]]
* [[How to Make the Ultimate 18650 Power Bank with Infinitely Expandable Capacity|https://www.youtube.com/watch?v=0jRsltIW8qM]]
* [[California Blackouts? build Instant Portable Powerwall - $500 ESS Rack Mount Battery Modules|https://www.youtube.com/watch?v=779yJ-cWcMk&t=966s]]
* [[DIY Laptop PowerBank (battery pack to charge your laptop on the go)|https://www.youtube.com/watch?v=ZQjazsiyr8s]]
* [[Huge BMW Lithium Battery, EV, Less Than $100/kwh|https://www.youtube.com/watch?v=GqyZ1dBaGQw]]
* [[Fortune LiFePO4 Battery Cells: I love them!|https://www.youtube.com/watch?v=buNxclZixuU]]
* [[$669 Ruixu LiFePO4 "LS" 100Ah Tear down|https://www.youtube.com/watch?v=YVIiHzra2kA]]
* https://www.youtube.com/watch?v=TsY9ov784-g
* https://www.youtube.com/watch?v=ewkj875qUmk
* https://batteryuniversity.com/learn/article/serial_and_parallel_battery_configurations
* [[EBike Battery Pack ~ DIY or Buy ~ Electric Bike Conversion (Part 2)|https://www.youtube.com/watch?v=b2sBhDxmPmA]]
* [[Make your own Li-Ion Battery Pack|https://www.youtube.com/watch?v=hwhqn4BmC2I]]
* [[DIY Lithium Battery - What could go wrong??|https://www.youtube.com/watch?v=KUmlCH7bTO8]]
* [[A very, very detailed video on how I built my battery pack for electric skateboard.|https://www.youtube.com/watch?v=7QjO90LG67g]]
* [[Building a 24V 72Ah Ammo Cannister Battery Pack|https://www.youtube.com/watch?v=np3EGmik1aU]]
* [[DIY 4000Wh 48V LiFePO4 Battery Toolbox Build, Start to Finish!|https://www.youtube.com/watch?v=JN7GK979Ck0]]
* [[Cheapest 48 volt LiFePO4 Battery, Pre-Built with BMS, Testing and Review, Gyll from Signature Solar|https://www.youtube.com/watch?v=SYJ25izYSGc]]
* [[Designing a Controller Board For the ES200G Scooter Batteries|https://www.youtube.com/watch?v=_5EJ8fxnttg]]
* [[Building a portable power station (1200w, USB-C and MORE!)|https://www.youtube.com/watch?v=adY-S8AH_Jc]]
* [[ My Power Bank Rivals Commercial Ones?! Super Fast! (DIY or Buy) |https://www.youtube.com/watch?v=_WI9Nwqvplo]]
* [[Lithium Batteries for Car Audio? Yinlong LTO Cells LTO66160H 8000 watt capable Battery Bank [4K]|https://www.youtube.com/watch?v=BYLCH33UWwU]]
* https://hackaday.com/2020/01/07/choosing-the-right-battery-for-your-electric-vehicle-build/
* [insert vids von Kurzgesagt]
* https://www.mein-grundeinkommen.de/ - leggit?
* zurrschienen
* ösenbefestigungsschiene
* https://www.thomann.de/de/flugzubehoer.html?pg=2&ls=25
* spanngurte, zurrgurte, expander
* Fittings
* Airlineschiene / airline rails
* "Stud Ring"
* [[Behindertenwerkstätten: Skrupellose Ausbeutung? - MrWissen2go EXKLUSIV|https://www.youtube.com/watch?v=4RC_ACfNIrI]]
* [[Behindertenwerkstatt als Sackgasse? - Panorama 3 - NDR|https://www.youtube.com/watch?v=BHnSJ53X1jE]]
* [[Abzocke in Behindertenwerkstätten? Lukas will den Mindestlohn - reporter|https://www.youtube.com/watch?v=t1b-KASKUXA]]
* ...
This article is not a complete guide and just gives an overview

* https://www.behringer.com/product.html?modelCode=P0B6H
** https://mediadl.musictribe.com/media/PLM/data/docs/P0B6H/DCX2496LE-DCX2496_QSG_WW.pdf
** https://mediadl.musictribe.com/media/sys_master/h84/h96/8849440243742.pdf
* https://www.thomann.de/de/behringer_dcx2496le_ultradrive.htm
* yt
** [[DSP Review: Behringer DCX2496 Ultradrive Pro|https://www.youtube.com/watch?v=MTgNDOqT8Mo]]
** [[Behringer DCX 2496 Ultradrive Pro - Lautsprechermanagementsystem|https://www.youtube.com/watch?v=xU1N5bbVb7g]]
** [[Mein Setup für Behringer DCX2496 Ultradrive Pro|https://www.youtube.com/watch?v=6-Q5YF1wZHs]]
** [[#DIGITAL #FREQUENZWEICHE DCX2496 - Grundsätzliche Funktionen bei Verwendung für HiFi-Boxen|https://www.youtube.com/watch?v=c2PUJX0vfeA]]
* https://www.stute-engineering.de/index.php/de/dcxserver - proprietary software

* wifi "upgrade"
** [[ANLEITUNG WLAN-fähige Behringer DCX2496 +Downloadlink +Anleitung +3D-Case|https://www.youtube.com/watch?v=YBlRMFletkc]]

* https://www.eserviceinfo.com/downloadsm/174419/.%20Various_DCX2496-FRONT-REVF.html


Repairs:

* [[Behringer Ultradrive Pro DCX2496 repair 1]]
* [[Behringer Ultradrive Pro DCX2496 repair 2 + XLR Mod]]
! Overview:

Date Code: 1105

original Firmware Version: 1.17

Hardware Revisions:

* Main Board: H
* I/O Board: H
* HID Board: E
* LCD Board: C

!! Chips / main components

"Main" Board

* Cirrus Logic CS8420-CSZ - [[Digital Audio Sample Rate Converter|https://www.alldatasheet.com/datasheet-pdf/pdf/198989/CIRRUS/CS8420-CSZ.html]]
* AKM AK5393VS - [[Enhanced Dual bit ΔΣ 96 kHz 24-bit ADC|https://pdf1.alldatasheet.com/datasheet-pdf/view/54969/AKM/AK5393-VS.html]]
* AKM AK5383VS - [[Enhanced Dual bit ΔΣ 96 kHz 24-bit ADC|https://pdf1.alldatasheet.com/datasheet-pdf/view/54967/AKM/AK5383VS.html]]
* 3x AKM AK4393VF - [[Advanced Multi-Bit 96kHz 24-Bit ΔΣ DAC |https://www.alldatasheet.com/datasheet-pdf/pdf/54943/AKM/AK4393VF.html]]
* 2x 7805 - linear Voltage Regulator
* 2x ISSI IC42s16100F-7Tl - [[512K Words x 16 Bits x 2 Banks 16Mb SDRAM|https://www.issi.com/WW/pdf/42-45S-VS16100F.pdf]]
* AMIC A29040B-70F - [[512K X 8 Bit CMOS 5.0 Volt-only, Uniform Sector Flash Memory|https://www.alldatasheet.com/datasheet-pdf/pdf/118487/AMICC/A29040B-70F.html]]
* Analog Devices ADSP-21065L - [[DSP Microcomputer|https://www.analog.com/media/en/technical-documentation/data-sheets/ADSP-21065L.pdf]]
* 3 different quarz oscillators
* 2x ISSI ic42s16100f-7tl - [[512K x 16 Bits x 2 Banks (16-MBit) Synchronous Dynamic RAM|https://www.alldatasheet.com/datasheet-pdf/pdf/146448/ICSI/IC42S16100.html]]
* Pulse Transformer - for AES/EBU (AES3)


I/O Board

* 6x JRC 4580 - [[dual opamp|https://www.alldatasheet.com/datasheet-pdf/pdf/1159324/HMSEMI/JRC4580.html]]
* 2x Bestar BT-5S - 5VDC - switching inputs between analog and AES/EBU

Power Supply

* 4N35 - [[General Purpose 6-Pin Phototransistors Optocouplers|https://www.alldatasheet.com/datasheet-pdf/pdf/542519/FAIRCHILD/4N35.html]]
* several diodes
* several transistors

LCD Board

* Avant SBN6400G - [[64-Common Driver for Dot-Matrix STN LCD|https://www.crystalfontz.com/controllers/Avant/SBN6400G/65]]

HID Board

* 2x TI TPIC6B273 - [[Power Logic Octal D-Type Latch|https://www.ti.com/lit/ds/symlink/tpic6b273.pdf]]
* TI SNx4HC244 - [[Octal Buffers and Line Drivers With 3-State Outputs|https://www.ti.com/lit/ds/symlink/sn74hc244.pdf]]
* 74hc574d - [[Octal D-type flip-flop; positive edge-trigger; 3-state|https://www.alldatasheet.com/datasheet-pdf/pdf/15644/PHILIPS/74HC574D.html]]



! Repairs

Problems:

* Fuse blown, maybe dead power supply
* Display somehow cloudy

!! Fuse blown / Power Supply

Fuse: T 1A H 250V

i had to buy new fuses. I checked the chips on the power supply if they are shorted and tested the transistors with the diode tester. i also checked some diodes for shorts. because i didn't find anything wrong i assembled the power supply back into the case and went on to check the voltages.

# +15V (Red)
# -15V (Blk)
# +9V (Blk)
# AGND (Blk)
# DGND (Blk)
# +5V (Blk)
# +3.3V (Blk)

Source: https://never.net/powersupply/PSInstallation.html

the voltages were all fine. as last step i checked if there are any obvious shorts on the Main-PCB. I only measured continuity between all the pins of the connector for the power supply. But apart from the two ground rails which are connected there is no short.
So i connected everything again and powered up the unit. It booted fine and there didn't seem to be any issue.

!! Fixing cloudy display

removing the front PCB with the display module soldered onto was a bitt challenging because it was held in by rubber strips which were glued to the aluminium case.

I carefully bent the metal tabs of the display-housing bac and lifted the housing. I then carefully separated the silicone-style conducting-pads from the pcb, because they were slightly sticking. I allways was very careful to not bent the thin ribbon cable to much or to tear it. I lifted and turned the display over to the left side. between the backlight and the LCD was some mineral-oil like substance. I carefully cleaned it away, first with tissue to get the bulk and then also with rubbing alcohol, acetone and a micro fibre cloth to get it completely clean. I also cleaned the zebra strips and the PCB connections with rubbing alcohol and acetone. After i was satisfied and there was no oil or dust left, i carefully assembled the display again and bent back the tabs of the display housing

Before reassembling i cleaned the leftover glue from the case and the rubber strips. But i had to add glue again to secure the PCB back into the case.

!! Other stuff

i later also did the input XLR mod, so the input xlr connectors are a locking type.

the unit had a problem with out6 being distorted and noisy, but that cleared itself it seems.
i got a DCX2496 for free because it is broken, it came from a student-run club/bar, it probably was pretty abused there and was switched on for a long time. the caps of the power supply are all swollen up and dead.
also i don't like that the inputs don't latch, cables can come loose, so i want to change the connectors to oneswith clips.

! Overview:

Date Code: 1209

original Firmware Version: 1.17

Hardware Revisions:

* Main Board: H
* I/O Board: H
* HID Board: ?
* LCD Board: ?
* Powersupply: F

!! Chips / main components

"Main" Board

~~* Cirrus Logic CS8420-CSZ - [[Digital Audio Sample Rate Converter|https://www.alldatasheet.com/datasheet-pdf/pdf/198989/CIRRUS/CS8420-CSZ.html]]
* AKM AK5393VS - [[Enhanced Dual bit ΔΣ 96 kHz 24-bit ADC|https://pdf1.alldatasheet.com/datasheet-pdf/view/54969/AKM/AK5393-VS.html]]
* AKM AK5383VS - [[Enhanced Dual bit ΔΣ 96 kHz 24-bit ADC|https://pdf1.alldatasheet.com/datasheet-pdf/view/54967/AKM/AK5383VS.html]]
* 3x AKM AK4393VF - [[Advanced Multi-Bit 96kHz 24-Bit ΔΣ DAC |https://www.alldatasheet.com/datasheet-pdf/pdf/54943/AKM/AK4393VF.html]]
* 2x 7805 - linear Voltage Regulator
* 2x ISSI IC42s16100F-7Tl - [[512K Words x 16 Bits x 2 Banks 16Mb SDRAM|https://www.issi.com/WW/pdf/42-45S-VS16100F.pdf]]
* AMIC A29040B-70F - [[512K X 8 Bit CMOS 5.0 Volt-only, Uniform Sector Flash Memory|https://www.alldatasheet.com/datasheet-pdf/pdf/118487/AMICC/A29040B-70F.html]]
* Analog Devices ADSP-21065L - [[DSP Microcomputer|https://www.analog.com/media/en/technical-documentation/data-sheets/ADSP-21065L.pdf]]
* 3 different quarz oscillators
* 2x ISSI ic42s16100f-7tl - [[512K x 16 Bits x 2 Banks (16-MBit) Synchronous Dynamic RAM|https://www.alldatasheet.com/datasheet-pdf/pdf/146448/ICSI/IC42S16100.html]]
* Pulse Transformer - for AES/EBU (AES3)~~


I/O Board

~~* 6x JRC 4580 - [[dual opamp|https://www.alldatasheet.com/datasheet-pdf/pdf/1159324/HMSEMI/JRC4580.html]]
* 2x Bestar BT-5S - 5VDC - switching inputs between analog and AES/EBU~~

Power Supply

~~* 4N35 - [[General Purpose 6-Pin Phototransistors Optocouplers|https://www.alldatasheet.com/datasheet-pdf/pdf/542519/FAIRCHILD/4N35.html]]
* several diodes
* several transistors~~

LCD Board

~~* Avant SBN6400G - [[64-Common Driver for Dot-Matrix STN LCD|https://www.crystalfontz.com/controllers/Avant/SBN6400G/65]]~~

HID Board

~~* 2x TI TPIC6B273 - [[Power Logic Octal D-Type Latch|https://www.ti.com/lit/ds/symlink/tpic6b273.pdf]]
* TI SNx4HC244 - [[Octal Buffers and Line Drivers With 3-State Outputs|https://www.ti.com/lit/ds/symlink/sn74hc244.pdf]]
* 74hc574d - [[Octal D-type flip-flop; positive edge-trigger; 3-state|https://www.alldatasheet.com/datasheet-pdf/pdf/15644/PHILIPS/74HC574D.html]]~~



! Repairs

Problems:

* noise
* LCD has really low contrast

After a short test to determine the problems i opened the DSP up and did a visual inspection. It was easily visible that 4 of the 7 caps on the low voltage side of the power supply were bulged.
These 4 caps are definitely dead and need replacement.
To make sure, i'm going to replace all 7 low voltage caps with good quality ones.

* 3x Decon SHL 16V 1000uF (105°C)
* 2x Decon SHL 16V 470uF (105°C)
** look ok, but i'll replace them anyways
* 2x Decon SHL 25V 470uF (105°C)

i bought fitting, quality caps from panasonic and nippon/europe chemicon as replacements, soldered them in and everything worked fine again.

! XLR Mod

i don't like that the inputs don't latch, cables can come loose, so i want to change the connectors to oneswith clips.

It looks like NC3FAH1 or NC3FAAH1 might fit. i bought 3 Neutrik NC3FAAH1.
the new connectors fit just as well as the original ones onto the pcb, though due to the latch one has to fiddle a bit to get them trough a shielding plate and the case. but nothing hard.
* possibly using https://www.bourns.com/pdfs/PTL.pdf ?
* https://www.alibaba.com/product-detail/60mm-Travel-Slide-potentiometer-SA6005-NJAOA_237776348.html?spm=a2700.shop_plgr.41413.15.740f6464q4eUgE
https://hackaday.com/2024/03/05/reverse-engineering-the-behringer-ultranet-protocol/
!! USB Player

* USB Player accepts WAV with 16-bit, 48kHz sample rate (not 44,1kHz!) PCM audio
* USB has to be FAT or FAT32 formated
* [[Behringer XR Mixer Pt 6, Playing music from a USB thumb drive|https://www.youtube.com/watch?v=BTCpIMOGfWw]]

!! XAir Edit on Linux (Fedora)

Running XAir Edit on Fedora is not easily possible because Fedora does not provide libcurl-gnutls (cURL Library compiled with gnutls support), the repos only include the normal ~OpenSSL version.

!! stuff

* [[X AIR How To: USB Recorder (X AIR EDIT) XR12 / XR16|https://www.youtube.com/watch?v=mdVcoD5HpAI]]
* [[X AIR How To: Auto Mixing in Depth|https://www.youtube.com/watch?v=FQrVHU0AClc]]
* https://behringerwiki.musictribe.com/index.php?title=OSC_Remote_Protocol
** see [[Open Sound Control (OSC) (protocol)]]
* https://github.com/search?q=x+air+mixer
** https://github.com/peterdikant/xair-remote - most updated
** https://redtide.github.io/wiki-x-air/en/effect_descriptions#wave-designer
* can be controlled via midi
** https://behringerwiki.musictribe.com/index.php?title=8._MIDI
** * see [[Midi]]
** [[Behringer X-Air XR-16 or XR-18 Digital Mixers MIDI Dongle Control|https://www.youtube.com/watch?v=G7fEYLSqpK8]]
** [[Behringer XR18 Midi Control|https://www.youtube.com/watch?v=Grwsr2vmRrQ]]
** http://blog.jessicat.me.uk/2019/05/midi-control-of-the-behringer-x32/
** https://www.pcdimmer.de/phpBB3/viewtopic.php?t=1455
** 
* [[X AIR How To: Side Chain Operation|https://www.youtube.com/watch?v=aVPHWw53hYs]]
* [[X AIR How To: Side Chain Triggering|https://www.youtube.com/watch?v=BsmzwRgxhiQ]]
* https://www.reddit.com/r/livesound/comments/nv4wxo/inserting_third_party_plugins_behringer_xr18_uad2/
* [[Behringer XAir Parallel Compression: Don't Make This Mistake!|https://www.youtube.com/watch?v=1BGxMdeu7fw]]
* [[X AIR How To: Using Compression (X AIR EDIT)|https://www.youtube.com/watch?v=uNvU672EDmk]]
* ''[[EFFECTS FX Ducking - MIDAS M32 MR18 + BEHRINGER X32 X-Air XR18 XR16 XR12 X18|https://www.youtube.com/watch?v=nG9GN_HcjVQ]]''
* https://codeblog.jonskeet.uk/2021/01/27/osc-mixer-control-in-c/
* https://codeblog.jonskeet.uk/2022/10/16/introduction-to-digimixer/
* controll with behringer xtouch


my todo:

* how to efficiently use the mix buses
Informations:

* Fullrange/Tops
* never Version: https://www.bell-store.de/p/bell-v3-400-speaker-system
* Woofer: 15" Fostex 15W400 (8 Ohm, 200W continuous, ferrit, OEM)
* Tweeter: 1" Fostex FD40 (8 Ohm, 20W continuous) Compression Driver with CD Horn
* Connection: Speakon
* Power: 400W (RMS?)
* Impedance: 8 Ohm

Symptoms: no Bass/mids, only high

Problem: Woofer burnt-out/blown

Woofer Information:

* 15" Fostex 15W400 (8 Ohm, 200W continuous, ferrit) is pretty much all you can get from the driver itself
* not found on manufacturer website
** https://www.fostexinternational.com/docs/speaker_components/discontinued_models.shtml
** https://www.fostexinternational.com/docs/speaker_components/compatibility.html
* best information i got: http://www.kogerer.ru/subj/fostex/fullrange.html#15w400 matching with http://www.eifl.co.jp/index/export/fostex/special%20use%20speaker%20units/special%20use%20speaker%20units.html
** impedance: 8 Ohm
** //f,,0,,// = 38Hz
** frequenzy response: //f,,0,,// - 5kHz
** sensitivity: 110.5dB/w (1m)
** Power: 200W
** //M,,0,,// = 67.8g
** //Q,,0,,// = 0.27
** effective radius: 16.2cm
** magnet weight: 1836g
** gross weight: 6.9kg
* some more but in japanese is here: http://ikakoo-g.sakura.ne.jp/IkakooGathering/Top/Guitar/2wayGuitarAmplifier/10w150.pdf
** maybe a 3 kHz crossover?

Woofer Replacement: Eminence Kappa?

the closest Kappa judging by the Thiele&Small Params would be the Kappalite 3015.


Tweeter information:

* https://www.bell-store.de/p/fostex-treiber-fd40
* FOSTEX OEM Produkt. Original Ersatzteil für ACR, NEXO, BELL und Systeme versch. US Hersteller.
* Abmessungen Durchmesser: 120mm
* 1" throat diameter
* Tiefe: 59.5mm
* Impedanz: 8Ω
* Power nom. w/network: 80W
* Freq. Range: 1,0 - 16kHz
* SPL: 104.5dB (+-2dB)
* Gewicht: 2400gr



The Kappalite 3015 was to expensive for the owner, so we decided on a the box Speaker 15-300/8-A as replacement.

https://www.thomann.de/de/the_box_speaker_153008a.htm

It's totally fine for his hobby DJ uses.

I have saved the defective woofer for me. Some day i might try to recone and recoil it.
* based on a electic car battery pack 
* build to a similar standard like high power generators

battery cells

* most electric cars use Li-Ion wich comes with some fire risk
* some cars use [[LiFePO4|LiFePO4 (LFP)]] cells which are much safer because they don't burn, they come with a bit less energy density though
* lead acid batteries are out of question because it would be to heavy for portability
* having Sodium-ion cells would be great, but the first manufacturers are just building production lines and ramping up production and it might take quite some time till these cells can be seen in cars or purchased by private people from sellers

Electronics

* inverter
** a propper, professionsl inverter with 10-25kW from companies like SMA
** 3 phase
** most of these inverters are string inverters with integrated MPPT functions for Solar panels, has to be checked if that is a problem or can be turned off as to not interfere with the battery/BMS
** probably also has some useful safety features, maybe a built in insulation monitor or other features which require less extra parts
** do they work well with changing loads and fluctuating power draw or are they only designed for constant loads?
* BMS
** is probably the best to use the bms designed for the packs we got, might come with the battery
** probably has an insulation monitor for the DC side built in, else one has to be added inside the DC breaker panel
* Charger
** is also best if we get the charger module from the same car as the batteries
** chraging from 230V home outlet or car charging station
** fast charge?
* breaker panels
** separate Panels for DC and AC
** should be waterproof and more accessible, like through doors in the enclosure
** 3 phase insulation monitor in the breaker panel for AC because then we don't have to worry about having a propper earth connection or earthing rod. with a regular RCD there has to be a propper impedance to earth or the FI will not trigger or trigger too late, disabling the security
*** https://en.wikipedia.org/wiki/Insulation_monitoring_device
*** https://de.wikipedia.org/wiki/Isolationsw%C3%A4chter
* communication/controll
** the BMS, charger, Inverter and other components might/should have serial communication like CAN Bus, modbus or RS232/RS485
** there should be a small controll panel giving data fom all important parts of the battery pack and inverter
** displaying power draw, voltages, charging state, errors and stuff
** depending on the featureset of other equipment (like the data the inverter provides) a shelly 3em or similar is useful for meassuring AC power
*** https://shop.shelly.cloud/shelly-3em-wifi-smart-home-automation
*** https://www.youtube.com/watch?v=RlSCe9xaUPE
* waterproof
** everything should be propperly waterproof or mounted inside the enclosure in a way it can't be reached by water
* cooling
** do we have to worry about cooling?

case/chassis

* maybe similar like medium size power generators with a metal frame and case
* size like an [[EPAL|EUR-pallet / Europoolpalette]] and with holes for transport with a Pallet-Jack or forklift
* wood chassis is probably not the best option
* aluminium for the side panels to save weight? steel for the base?
* the enclosure should be pretty good waterproof/splashproof
see [[big (portable) battery]] and [[fucking big portable battery]]


Todos:

* Inverter
* wiring
* case
* fuses/breakers and protection
** [[sicherheit/absicherung von mobilen stromerzeugern, invertern/wechselrichtern]]
* digital control
* elektroinstallation siehe [[elektronik / elektroinstallation]]
* zum Schluss: Abnahme der Anlage von Elektrofachkraft mit Instalationstester
** FI / Isometer prüfen
** https://www.bender.de/fachwissen/technologie/it-system/isolationswiderstaende-pruefen-messen-und-ueberwachen




* State of Charge
* Effizienz aufrechnen
* wechselrichter
** 3 einzelphasen
** oder so
* laden
** möglichkeit [[EV Ladestationen|open hardware EV charger (Ladestation)]] zu nutzen?
* spannung
* sicherung

* https://kaco-newenergy.com/de/produkte/Kategorie/hybrid-und-batterie-wechselrichter/
* https://de.enfsolar.com/directory/component/inverter?country=54&type2=o
* https://www.sma.de/produkte/hybrid-wechselrichter/sunny-tripower-smart-energy

* https://qelectrotech.org/





stuff

* Huawei hat u.A. 450V nominal - https://solar.huawei.com/de-DE/download?p=%2f-%2fmedia%2fSolar%2fattachment%2fpdf%2fde%2fdatasheet%2fLUNA2000-5-15-S0.pdf
* https://www.openbikesensor.org/
** https://twitter.com/OpenBikeSensor
* https://verschwoerhaus.de/tag/openbikesensor/
* wood
** https://de.wikipedia.org/wiki/Holz
** https://en.wikipedia.org/wiki/Wood
* [[Lignin]] and [[bio materials for fibers and fabric]] combined
* hemp
** https://en.wikipedia.org/wiki/Hemp
** https://de.wikipedia.org/wiki/Nutzhanf
** https://de.wikipedia.org/wiki/Hanffaser
* linen
** https://en.wikipedia.org/wiki/Linen
** https://de.wikipedia.org/wiki/Flachsfaser
* cotton
** https://de.wikipedia.org/wiki/Baumwollfaser
** https://en.wikipedia.org/wiki/Cotton
* general:
** https://de.wikipedia.org/wiki/Polymer
** https://en.wikipedia.org/wiki/Polymer
* https://de.wikipedia.org/wiki/Kategorie:Biopolymer
* [[Lignin]]
* https://en.wikipedia.org/wiki/Cellulose
** https://de.wikipedia.org/wiki/Cellulose
* https://de.wikipedia.org/wiki/Bio-basierter_Kunststoff
* https://en.wikipedia.org/wiki/Bioplastic
* https://wedocs.unep.org/bitstream/handle/20.500.11822/7468/-Biodegradable_Plastics_and_Marine_Litter_Misconceptions,_concerns_and_impacts_on_marine_environments-2015BiodegradablePlasticsAndMarineLitter.pdf.pdf
* https://hackaday.com/2023/01/06/myceliotronics-biodegradable-electronics-substrates-from-fungi/
* https://hackaday.com/tag/bioluminescence/
* https://www.glowee.com/
* https://www.treehugger.com/bioluminescent-fungi-mushrooms-that-glow-in-the-dark-4868794
goal is to get +V, 0V and -V
https://de.wikipedia.org/wiki/Spannungsquelle#Asymmetrische,_bipolare_und_symmetrische_Spannungsversorgungen

* from AC
** transformer with separate windings
*** just needs two full-bridge rectifiers and maybe regulators
** transformer with center tap
*** only 2 diodes needed for rectification
* from DC
** virtual ground - a voltage divider with resistors, unstable at non semmetric loads, maybe with capacitors
** virtual ground using a opamp as supply, more stable, but also not propperly done
** inverting charge pump
** smps?


* [[Negative Voltages are more important than you think! So here is how to make them! EB#52|https://www.youtube.com/watch?v=z5eB_2wjLTg]]
** https://tangentsoft.net/elec/vgrounds.html
** https://robu.in/what-is-dual-power-supply-circuit-construction-and-working/
** https://www.electronicsweekly.com/market-sectors/power/ten-best-ways-split-voltage-rail-2015-02/
** https://en.wikipedia.org/wiki/Charge_pump
* https://sound-au.com/project192.htm
* https://hackaday.com/2023/04/20/ask-hackaday-split-rail-op-amp-power-supply/
bldc motors can function as encoders and offer custom haptic feedback.

* https://www.youtube.com/results?search_query=bldc+encoder
*[[DIY haptic input knob: BLDC motor + round LCD|https://www.youtube.com/watch?v=ip641WmY4pA]]
** [[Building a haptic input knob from scratch!|https://www.youtube.com/watch?v=Q76dMggUH1M]]
* see [[ESC / BLDC motor driver / controller]]
* [[Festplattenmotor (BLDC) als Drehimpulsgeber / Encoder mit Atmega8 und DLG7137|https://www.youtube.com/watch?v=37tUzxodYGE]]
* [[HACKED!: Using an HDD Motor as a Rotary Encoder?!|https://www.youtube.com/watch?v=tjCJ3MlFt7g]]
* [[Magnetic Angle Sensor for BLDC Brushless DC Motor Replaces Optical Encoders with a Magnetic Encoder|https://www.youtube.com/watch?v=vuG8D7yX4m4]]
* [[SmartKnob on STM32 - Update|https://www.youtube.com/watch?v=MPMm7QWxUBM]] - channel has several videos on their own version of the haptic input knob
* gimbal BLDC motors with hollow axles allow for wires to be fed trough
* mini bldc motors could make for useful small encoders
** https://de.aliexpress.com/wholesale?catId=0&SearchText=mini+bldc
* [[ SmartKnob - BLDC + GC9a01 + ESP32 |https://www.youtube.com/watch?v=IfK-p96Ccdc]]
* [[ BLDC Motor: sensorless haptic control |https://www.youtube.com/watch?v=vJXnunhm1c4]]
* https://www.youtube.com/results?search_query=bldc+encoder
* https://duckduckgo.com/?t=ffab&q=bldc+encoder&ia=web
cheap bluetooth modules/adapters usually only support the most basic lossy compression

Modules

* BK8000 ?
* CSR64215 (Qualcomm aptX support, integrated DSP, pairing?)
* CSR8645
* https://www.qualcomm.com/products/bluetooth
* ...

linux

* https://www.collabora.com/news-and-blog/blog/2022/09/02/using-a-raspberry-pi-as-a-bluetooth-speaker-with-pipewire-wireplumber/

linux bluetooth audio issues:

* https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/227

stuff

* https://hackaday.com/2022/09/14/esp32-adds-bluetooth-to-an-ipod-nano/
* https://old.reddit.com/r/Android/comments/11t16lk/qualcomm_has_open_sourced_its_aptx_and_aptx_hd/
* Bluetooth LE audio
* https://hackaday.com/2017/01/30/reprogramming-bluetooth-headphones-for-great-justice/
* https://www.eetimes.com/achieving-ultra-low-latency-digital-wireless-audio/
HC-05

* see also [[Parkside PDM 300 C2/C3]]

HC-06

* https://forum.arduino.cc/t/solved-hc-06-bluetooth-module-and-at-commands/697344/6
* see also [[Parkside PDM 300 C2/C3]]

JDY-30/JDY-31

* http://www.ko4bb.com/getsimple/index.php?id=jdy-30jdy-31-bluetooth-modules
** http://www.ko4bb.com/getsimple/data/uploads/jdy-30/jdy-30-bluetooth-module.pdf
* android phone dev settings -> bluetooth debugging (recording) -> download via adb -> opening with wireshark
* nRF52840 can sniff BLE -> wireshark
** https://www.nordicsemi.com/Products/Development-tools/nrf-sniffer-for-bluetooth-le
* maybe ESP32?
* https://en.wikipedia.org/wiki/Comparison_of_boot_loaders
* syslinux
** https://de.wikipedia.org/wiki/SYSLINUX
** https://wiki.syslinux.org/wiki/index.php?title=The_Syslinux_Project
** https://en.wikipedia.org/wiki/SYSLINUX
* GRUB
** https://de.wikipedia.org/wiki/Grand_Unified_Bootloader
** https://en.wikipedia.org/wiki/GNU_GRUB
Telescope: Bresser "Electronic Digital Series" Refractor-Telescope with Meade Motors and Motor Controll


<<<
EDIT

maybe https://hackaday.com/2013/03/22/diy-pc-to-telescope-interface-cable/ is helpful
<<<


* Art.-Nr.: 46-25000
* F =700; D = 60
* Branding/Model:
** possibly sold as Meade ~TeleStar
*** https://www.cloudynights.com/uploads/monthly_10_2017/post-280480-0-74118000-1508460402.jpg
** but also sold with Bresser branding
** the tripod and mount is a Meade DS Gen 1
** the telescope body is made by Bresser
* Price:
** sold for around 80€ new
** there was a listing of a Bresser Branded one sold for 40€ used but with a lot or all of the components, none missing
* Missing:
** ~~Computer Cable and Software~~
** only one ocular/eyepiece (SN4mm), came with atleast 2
* Optional:
** Case, not allways included, there where sets with or without

Electronic controll

* the electronics seem to be the //#492 Dual-Motor Electronic Control System//
** remote
*** includes a mistery chip and a linear regulator chip as power source as well as some other components, no information about the computer connection there
** even though this remote does not support the computer connection it does send something via the serial connection
** logic levels seem to be 0V low and ~5.4V high
* but for the computer controll the //#493 Autostar Computer Control System// or just the //#495 Autostar Handbox// (if you allready got the motors ans stuff) is needed
* the whole system could be relatively easy reverse engineered, modified and controlled using microcontrollers, there is even good open source software like stellarium which supports controlling telescopes


Cable

* 4C4P western-modular Connector for the PC cable on the panel
* after searching: cost >20€ on ebay
* seems to be a pretty simple USB to UART/RS232 Adapter Cable (information deducted from the ebay listings)
** there are much cheaper options which only have other connections
** a cheaper adapter could be easily connected to a cheap cable with 4C4P connector
* ~~i bought a PL-2303HX based adapter which only supports 3.3V logiklevel, it didn't work, because the telescope controller has around 5-6V logiklevel
~~
Software

* Meade Autostar (requires the right remote)
** https://meade.com/support/auto.html
** https://www.meade.com/category/support/downloads/software/autostar-suite/
* if one builds something custom with microcontrollers the whole system could be controlled using stellarium or others
** https://en.wikipedia.org/wiki/ASCOM_(standard)
** https://www.ascom-standards.org/
** https://www.indilib.org/

Manual
* https://www.meade.com/pub/media/downloads/51/DS.pdf

Motors

* custom Servomotors with basic DC Motor and optical (IR) encoding discs
* chips
** some microchip branded microcontroller (18 pin)
** LM78L
* 2 other 8-pin mystery chips
<<list-links "[all[current]tagging[]]">>

* https://www.lautsprecherteile.de/
* bend plywood
** http://kolbrek.hornspeakersystems.info/index.php/horns/exponential-midrange-1
** https://www.wikihow.com/Bend-Plywood
** https://www.instructables.com/CC-Chair-How-to-Bend-Plywood/
** https://mathoplywood.com/how-to-bend-plywood-2-method-with-picture/
** https://www.hunker.com/13401539/how-to-soak-bend-plywood
* milling the shape into wood (can be a bit massive and heavy)
* 3D Printing, more viable for smaller (high frequency) horns
* making a mold out of wood or other materials and casting some resin or modelling with glassfiber and resin or so
* funding?
* local scrapyards (parts)
* local public transport company
* local university or technical schools
* local mechanics and garages
* local manufacturers of automotive (parts)
* local companies working with renewable energy-technology
* https://en.wikipedia.org/wiki/Kiepe_Electric
* https://www.zf.com/mobile/en/homepage/homepage.html
* https://www.caf.net/de/index.php
* https://www.ikarus.hu/
* https://www.electrobus.hu/city-pioneer
* https://www.crrcgc.cc/g7220.aspx
(Project idea: Erik from FFF DD)

taking an old bus and rebuilding it to electric or adding more electric capability to hybrid or trolleybus

getting the bus from a company or through crowdfunding?
mit firmen, vereinen, makerspaces, einrichtungen, behörden, etc. zusammen arbeiten...

* https://www.youtube.com/watch?v=Tto6bglCevA
* https://www.youtube.com/watch?v=MVXWGBgYj3M
* [[How Does a Tesla Motor Really Work?? EV West Drops Knowledge|https://www.youtube.com/watch?v=Ci5hK9bt6Jw]]
* [[Electric SuperCar|https://www.youtube.com/channel/UC-Uk13BnLTGAO5APsfuT9uw]]
* https://www.youtube.com/channel/UC8sR7IAMOHKV-S_oz3JH3qw
* [[Electric Vehicle World Tour|https://www.youtube.com/channel/UCHOCdckFdBEmTfR1qoW4Atg]]
* [[HOW IS IT MADE? Electric Vehicle Conversion (#EVWT)|https://www.youtube.com/watch?v=uibJV-EQOH4]]
* [[Build Your Own Electric Car|https://www.youtube.com/watch?v=BSA2fGTmqfw&list=PLmHss3DBZUilepzTmr-XAVwpRRCqMv7Ny]]
* [[Electric CAR Conversion! From GASOLINE to ELECTRIC car in ONE video!|https://www.youtube.com/watch?v=-5amE5HVy08]]
* https://ripower-elektrofahrzeuge.de/elektroauto-umbau-kosten/
* https://www.youtube.com/c/TTTesla/videos
* https://www.e-drive-solution.de/
* https://www.teslakaufen.com/
* https://www.youtube.com/watch?v=HnaeagbcV0E

Needed:

* vehicle to convert
** detailed technical information about the vehicle to convert
** trolleybus or hybrid bus allready have electric motor and a lot of stuff
* electric motor
** https://components101.com/articles/ev-traction-motor
* battery
** which type to use? LiFePO4? LTO?
** how does the co2 footprint charge off (amortisieren)
*** https://www.youtube.com/watch?v=HnaeagbcV0E
* motor controller/inverter
** https://openinverter.org/
* charging circuit
** via Pantografen (DVB) 
** via Induktion (BVG)  (effizienz?)
** via Starkstromleitung (DVB+BVG)
** https://openwb.de/main/ - open source wallbox/charger

where to get that?

problems:

* TÜV
** (in reply to openinverter i think) laut der webseite des Typen ist es durch den deutschen tüv gekommen (mit Opel Kadett chassis)
** muss nur den EMC test  bestehen wenn du ein vorhandes chassis verwendest

Open Source Cars
* Renault Twizy or Renault POM
** https://www.heise.de/make/meldung/Renault-POM-Open-Source-im-Auto-3599435.html
** das ist basically der Twizy. Auf der Webseite von OSVehicle (jetzt OpenMotors) sieht man dann Bilder vom Twizy ohne Verkleidung etc.:
https://www.openmotors.co/renaultpomsignup/


Misc:

* streetscooter von der post sind ja auch nice, nur leider hat die post keinen käufer gefunden und beendet das ganze - https://de.wikipedia.org/wiki/Streetscooter
* https://i.imgur.com/R9rnmXv.jpg?2
* Wie sinnvoll sind Elektro-Transporter? - http://feedproxy.google.com/~r/netbooknewsde/~3/XiHFRPCz-7Y/
* https://openinverter.org/wiki/Main_Page
* https://github.com/damienmaguire
* https://web.archive.org/web/20121105123653/http://www.powerguru.org/2012/07/02/dc-dc-converter-technologies-for-electrichybrid-electric-vehicles/
* http://opengarages.org/index.php/Main_Page
* streamdeck uses one big screen with some transparent button matrix over the top or so?
* https://hackaday.com/2022/10/17/poly-keyboard-has-screens-in-every-key/
* keys with integrated screen that one can buy commercially are very expensive and very limited in specs
* https://hackaday.com/2022/12/20/more-detail-on-that-fantastic-lego-oled-brick/
** small, simple microcontroller: rp2040 or some small and cheap risc-v one?
** 0,42"/0.49/0.69/0.91/0.96/1.3" oled screens
** custom mold for caps, switches
* https://hackaday.com/2023/09/26/single-button-keyboard-has-multiple-uses/
* [[EEVblog #859 - Bypass Capacitor Tutorial|https://www.youtube.com/watch?v=BcJ6UdDx1vg]]
* http://www.learningaboutelectronics.com/Articles/What-is-a-bypass-capacitor.html
* https://en.wikipedia.org/wiki/Decoupling_capacitor
* https://www.electronicshub.org/bypass-capacitor-tutorial/
* [[EEVblog #1085 - Bypass Capacitors Visualised!|https://www.youtube.com/watch?v=1xicZF9glH0]]
* [[Decoupling capacitors|https://www.youtube.com/watch?v=3rxKZWQk_DY]]
* https://www.analog.com/en/technical-articles/bypass-capacitor-and-coupling-capacitor-stabilizing-voltage-the-right-way.html
* https://components101.com/articles/decoupling-capacitor-vs-bypass-capacitors-working-and-applications
* https://www.renesas.com/us/en/document/apn/an1325-choosing-and-using-bypass-capacitors
* [[effects from coupling capacitors in audio circuits|https://www.youtube.com/watch?v=eF8e-FmtDh4]]
* [[What are the Decoupling capacitors? How to select Decoupling / Bypass capacitors? |https://www.youtube.com/watch?v=KKjHZpNMeik&list=PLbGlpmZLQWJdl4jvacyENiZ_3rQnJ9dLJ]]
* [[OP Amp PCB Layout: Grounding & Bypass (Mixed signals, grounding and bypass capacitors)|https://www.youtube.com/watch?v=a-FjxztpxBo]]
I've got a nice 50m cable drum from brennenstuhl, a good quality brand, but there is some damage on it.
after the first 9m there is roughly 1m with a couple of damaged spots. the remaining 40m are fine.
i think the best option is to cut out the damaged part and get a new pair or plug and socket to join the cable and have a 49m cable.
that's what i did in the end. the cable drum works fine again.
* [[50 Ohm & 75 Ohm - Woher kommen diese Werte und was ist eine Kabelimpedanz?|https://www.youtube.com/watch?v=YAyN75RxznA]]
* https://github.com/Tbruno25/canopy
** https://tbruno25.medium.com/car-hacking-faster-reverse-engineering-using-canopy-be1955843d57
** https://hackaday.com/2021/05/08/using-canopy-to-visualize-the-can-bus/
* https://github.com/zombieCraig/ICSim
* https://hackaday.com/tag/can/
* https://www.youtube.com/watch?v=H6OGESbr9yA
* [[Capacitors Explained - The basics how capacitors work working principle|https://www.youtube.com/watch?v=X4EUwTwZ110]]
* [[How to choose the right capacitor type for a circuit?! ~~ Film vs. Ceramic vs. Electrolytic|https://www.youtube.com/watch?v=2v8zBj7_sxg]]
* [[Why electrolytic capacitors are actually kinda shitty|https://www.youtube.com/watch?v=WytU5uj78-4]]
* [[Capacitor calculations - Basic calculations for capacitors in series and parallel|https://www.youtube.com/watch?v=ucEiEic-kZ4]]
* [[Capacitor Replacement Tutorial|https://www.youtube.com/watch?v=YCSNWi3UHf4]]
* [[Capacitor i-v equations|https://www.youtube.com/watch?v=EqlsSqET1kk]]
* see [[quality Electrolytic Capacitors]]
* [[EEVblog #486 - Does Current Flow Through A Capacitor?|https://www.youtube.com/watch?v=ppWBwZS4e7A]]
* https://caps.wiki/wiki/Capacitors
** https://caps.wiki/wiki/Category:Capacitors
** https://caps.wiki/wiki/Capacitor_Failure_Methods
* https://analyseameter.com/2015/09/capacitor-markings-symbols.html
* https://www.condoraudio.com/wp-content/uploads/Reviews/How-to-Choose-Replacement-Capacitors-and-Resistors.pdf
* https://eevblog.com/forum/chat/capacitor-brands/
* [[Kondensatortausch: Kritisch - das solltest Du wissen!|https://www.youtube.com/watch?v=TJtoKx5eGY8]]
* [[Capacitor calculations - Basic calculations for capacitors in series and parallel|https://www.youtube.com/watch?v=ucEiEic-kZ4]]
* [[bypass / decoupling capacitors]]
* https://www.digikey.de/de/resources/conversion-calculators/conversion-calculator-smd-capacitor-code
* https://www.youtube.com/watch?v=R9slJUqT6Ls

types

* supercaps - extra type, see below
* electrolytic
** [[quality Electrolytic Capacitors]]
** [[EEVblog #742 - Why Electrolytic Capacitors Are Connected In Parallel|https://www.youtube.com/watch?v=wwANKw36Mjw]]
** https://en.wikipedia.org/wiki/Electrolytic_capacitor#Electrical_characteristics
** https://forum.digikey.com/t/calculating-capacitor-esr-from-tan/2633
** for audio use cases where low noise is prefered low inductance is important
** for switching power supplies a low ESR is importat because of the high switching frequencies
* film
** https://en.wikipedia.org/wiki/Film_capacitor
** https://www.vishay.com/docs/26033/gentechinfofilm.pdf
** https://www.tdk-electronics.tdk.com/download/530754/480aeb04c789e45ef5bb9681513474ba/pdf-generaltechnicalinformation.pdf
** https://en.wikipedia.org/wiki/Film_capacitor#Characteristics_of_film_materials_for_film_capacitors
** https://eepower.com/capacitor-guide/types/film-capacitor/#
** https://components101.com/articles/different-types-of-film-capacitors-and-their-applications
** https://www.tdk-electronics.tdk.com/download/530780/7a11ce85afa1498543bf984153733752/pdf-markingandorderingcodesystem.pdf
* ceramic
** [[EEVblog #1037 - Solving Ceramic Capacitor Cracking|https://www.youtube.com/watch?v=QgKY5QWehME]]
** [[EEVblog #855 - Ceramic Capacitor Piezoelectric Effect|https://www.youtube.com/watch?v=F2gX-R1k7MM]]

~SuperCaps

* special caps with very high capacity compared to normal caps, not as high as batteries though
* charge/discharge rate is much higher than batteries
* inbetween caps and batteries

Powercaps

* marketing term, widely used in the car-hifi sector
* can be normals caps, supercaps or a combination of both
Caps

* [[ The TRUTH About Car Audio CAPACITORS! Testing a CHEAP 12v Capacitor VS IOXUS UltraCap Supercapacitor |https://youtu.be/L_JXo-7p_t8]] ?
* https://www.youtube.com/watch?v=_htSRg4m5V0
* https://www.youtube.com/watch?v=w_JpEo-dsDY


stuff

* https://bandaaudioparts.com/
* Eton amps
* https://de.wikipedia.org/wiki/Kategorie:Fahrzeugtechnik
* https://de.wikipedia.org/wiki/Kategorie:Fahrradtechnik
* https://de.wikipedia.org/wiki/Lenkkopfwinkel
* https://de.wikipedia.org/wiki/Fahrzeugbau
* https://de.wikipedia.org/wiki/Konstruieren_(Technik)
* https://de.wikipedia.org/wiki/Fahrzeugkonzept
* https://de.wikipedia.org/wiki/Fahrzeugtechnik
* https://de.wikipedia.org/wiki/Leiterrahmen
* https://de.wikipedia.org/wiki/Rohrrahmen
* https://en.wikipedia.org/wiki/Bicycle_frame
* https://en.wikipedia.org/wiki/Bicycle_frame
* https://en.wikipedia.org/wiki/Category:Bicycle_parts
* es gibt ein paar spezialisierte CAD programme für fahrradrahmen, aber eher nicht für anhänger
* [[carla cargo]]
<<list-links "[all[current]tagging[]]">>

* https://www.netzwelt.de/fotos/261-verrueckte-e-bikes-fahrrae.html
* https://www.werkstatt-lastenrad.de/index.php?title=Hauptseite
* https://www.cargobike.jetzt/blogroll/
* https://lastenrad-tuning.com/
* https://www.werkstatt-lastenrad.de/index.php?title=Bauanleitung_Carla_Cargo_Crowd
* https://pedalkreis.org/bauplaene/carlacargo/

older stuff

* https://ebike-news.de/carla-cargo-fahrradanhaenger-elektromotor/118132/
* https://mahler-net.eu/das-carla-cargo-projekt
* https://www.werkstatt-lastenrad.de/index.php?title=Datei:Carla_cargo_crowd_doku_fotostream_013.JPG
* https://www.startnext.com/carla/blog/beitrag/carla-cargo-summer-p33261.html
* https://www.pinterest.de/pin/793337290579685671/
bought an old used Carver PM-1.5 amp which does not seem to switch on fully. 
overall condition seems really good, no obvious bad components on first sight.

links

* https://en.audiofanzine.com/dual-channel-power-amp/carver/pm-1-5/
* https://www.hifiengine.com/manual_library/carver/pm-15.shtml
* https://www.manualslib.com/manual/703074/Carver-Pm-1-5.html
* https://paforum.de/forum/index.php?thread/27796-carver-pm-1-5-gute-endstufe/

Problems:

* does not switch on fully?
* missing case screws
* missing input ground/chassis ground jumper and screws
* dirty/dusty
* dust filter needs cleaning
* fan motor has probably never seen any oil

screws

the amp was made in the usa, so the screws are probably some really hard to get inch type but i can't find out the thread... some threads seem very damaged because maybe someone used the wrong screws, other threads seem to fit metric screws just fine.
I drilled out and recut the threads to the next metric size. now i just have to find good screws.
* https://de.makercase.com/#/
* https://festi.info/boxes.py/
* https://www.instructables.com/The-Ultimate-Guide-to-Laser-cut-Box-Generators/
* https://boxdesigner.connectionlab.org/
* https://makeabox.io/
* and more
cd and dvd players seem to have common problems that they stop playing disc after some time, only accept certain disks, don't accept discs at all or similar. These problems seem to be related to aging laser diodes, were the light output of the diodes drops after some years of use and it can't propperly read discs anymore.

maybe there is also some other buggy behavior that can be observed, like the controllers sometimes failing to eject the disks, but i don't have good data on that.

most times there are small potentiometers next to the laser diode assembly or on the pcbs or flatflex cables with hold power and data lines for the laser assembly. those pots set the current with which the laser diode is driven. they can be adjusted to give the diode more output again, but that also means more power which is dissipated in the diode and makes it age. but adjustments have to be done very carefully in order to not overpower and burn the laser diode, rendering it useless.
a good practice is to mark the factory setting of the potentiometers bevor going further. then trying to adjust them by very tiny amounts in either direction and testing for improvement.

i was not jet able to test these infos on cheap devices.

i don't jet know if it is possible or viable to replace laser diodes.

see also [[grease / oil for repairs]]

replacement parts

* https://www.ebay.de/str/audiovideoexperte - offers a lot of other laser-modules for many devices (germany)

i'm going to collect some links to tutorials here.


* https://en.wikipedia.org/wiki/List_of_battery_sizes
* https://www.youtube.com/watch?v=LqgP16JQ24I
* https://www.turn-on.de/tech/ratgeber/feststoff-graphen-und-co-kommt-eine-akku-revolution-512259
* https://www.energy-storage.news/
* https://www.mobilegeeks.de/news/akku-leer-graphen-batterie-liefert-unbegrenzt-strom/
* https://www.akku.net/magazin/der-akku-der-zukunft-wir-brauchen-mehr-energie/
* https://www.heise.de/hintergrund/Erste-Batterie-auf-Graphen-Basis-2403258.html
* https://www.androidauthority.com/graphene-batteries-explained-1070096/
* https://www.graphene-info.com/graphene-batteries
* https://batteryuniversity.com/
* https://www.technologyreview.com/topic/climate-change/battery-technology/
* https://www.forbes.com/sites/jamesconca/2019/08/26/energys-future-battery-and-storage-technologies/
* https://www.sciencedaily.com/news/matter_energy/batteries/
* [[flywheel (schwungrad)]]
* https://en.wikipedia.org/wiki/List_of_battery_types
* https://en.wikipedia.org/wiki/Category:Rechargeable_batteries
* https://www.energy.gov/sites/prod/files/2019/07/f65/Storage%20Cost%20and%20Performance%20Characterization%20Report_Final.pdf
* [[Are AA NiMH Batteries obsolete? Here is everything you need to know about them!|https://www.youtube.com/watch?v=5B1sX7p5xXI]]
* [[Battery Type Comparison -- Lead Acid VS NiMH VS Li-Ion VS LiPo|https://www.youtube.com/watch?v=LqgP16JQ24I]]
* [[https://de.wikipedia.org/wiki/Ladeverfahren#IU-Ladeverfahren_(CCCV)]]
* [[EEVblog #919 - How To Charge Li-Ion/LiPo Batteries With A Power Supply|https://www.youtube.com/watch?v=jNmlxBXEqW0]]
* [[EEVblog #176 - Lithium Ion/Polymer Battery Charging Tutorial|https://www.youtube.com/watch?v=A6mKd5_-abk]]
* [[Batteries & Charging|https://www.youtube.com/playlist?list=PLvOlSehNtuHtj5Ubhx7govoBfNkyUO4Pp]]
* https://en.wikipedia.org/wiki/Category:Battery_charging
* https://en.wikipedia.org/wiki/Power_Management_Bus
* for solar: [[MPPT|MPPT - Maximum Power Point Tracking]] charge controller
* [[DIY LiPo Supercharger! (Charge, Protect, 5V/12V Boost V2)|https://www.youtube.com/watch?v=6LxRnf6sQNQ]]

stuff

* https://github.com/twischer/ChargeMonitoring
* https://www.n-tv.de/technik/So-halten-Akkus-laenger-article22353002.html
you can get a lot of cheap amplifier boards online, they are pretty good if you know how to use them.
often thse are class-d amplifiers which are most-efficient (d doesn't mean digital).

you have to read the datasheets of the utilized ICs to get the accurate data you want/need.

often used chips:

* STMicroelectronics - https://www.st.com/en/audio-ics/class-d-audio-power-amplifiers.html#products
** TDA7498 (2*100W, stereo)
** TDA7498E? (2*160W, stereo) - https://www.st.com/en/audio-ics/tda7498e.html
* Texas Instruments - https://www.ti.com/audio-ic/amplifiers/overview.html
** TPA3116
** TPA3110 (2*15W, stereo) - https://www.ti.com/lit/ds/symlink/tpa3110d2.pdf
** https://www.ti.com/product/TPA3255
* Power Analog Micoelectronics
** PAM8610 (2*10W, stereo)
**

some chip manufacturers:

* https://www.nxp.com/products/audio-and-radio/audio-amplifiers
* https://www.ti.com/audio-ic/amplifiers/speaker-amplifiers/overview.html
* https://www.st.com/en/audio-ics/digital-audio-power-amplifiers.html#overview
* https://www.infineon.com/cms/en/product/power/class-d-audio-amplifier-ic/
* https://www.analog.com/en/products/audio-video/audio-amplifiers/class-d-audio-amplifiers.html

you can't really trust the product descriptions of the sellers, best is if you look up the used chip and read the official datasheet. most datasheets of amplifier chips have graphs where you can see which input voltage you need for the impedance and power of your speakers.

using 12V batteries and step-up converters you can supply them with the needed voltage.

you can supply small 3W amplifiers with 5V directly from a common powerbank


stuff

* [[ Besser als WONDOM? | Das TinySine Verstärker Board von HS-SOUND | #DIY |https://www.youtube.com/watch?v=oeZ3-hDS_7E]]
* [[ [#11] TDA7492 Amplifier Power & Stress Testing |https://www.youtube.com/watch?v=KDLmVlIuHQE]]
* [[Class D amplifier board reviews|https://www.youtube.com/playlist?list=PLHzOpLPsV6EGqHubNA-ODaCGmXr5sxYdI]]
see [[cheap "chinese" amplifier boards]]

* TZT / Wondom
* boards with Bp1048b2
** https://www.diyaudio.com/community/threads/mv-silicon-bp1048b2.398656/
** https://www.diyaudio.com/community/threads/true-wireless-stereo-tws-bluetooth-for-speakers.379643/page-6
** https://www.reddit.com/r/DSP/comments/104qffq/ive_found_a_weird_dsp_company_online/
* https://de.aliexpress.com/item/1005005022230492.html
* PCB marking* "JM IR_Cam_V5.1.2" and "20200622"
* ~1.4" screen ("FP-133HSP05A")
* 50-60€ version without battery or buttons
* just 5V micro usb for power
* AMG8833 sensor, 8x8 pixels
* GigaDevice GD32E230F4P6TR ARM Microcotroller
* small SOT-23-3 package, likely 3.3V LDO for the microcontroller or so
* small 4-pin header
* some smd passives


<<<
Spezifikationen:

* Material: Leiterplatte
* Temperaturgenauigkeit:
* Hochleistungsart mit hoher Verstärkung: typisch ± 2,5 ℃ ± 4,5 ℉
* Hochleistungstyp mit geringer Verstärkung: typisch ± 3,0 ± 5,4 ±
* Erkennungsentfernung beim Menschen: 7 m oder weniger (Referenzwert) 22.966 ft
* NETD:
** Typ. 0,05 ≤ 32,900 ≤ 1 Hz
** Typ. 0,16 ≤ 32,288 ≤ 10 Hz
* Betrachtungswinkel: typisch 60 °
* Spalt der optischen Achse: innerhalb der typischen ± 5,6 °
* Derzeitiger Verbrauch:
* Typisch 4,5 mA (normaler Modus)
* Typisch 0,2 mA (Schlafmodus)
* Typische 0,8 mA (Standby-Modus)
* Installationszeit:
* Typische 50 ms (Zeit, um die Kommunikation nach dem Setup zu aktivieren)
* Typische 15s (Zeit zur Stabilisierung der Ausgabe nach dem Setup)
* Pixelanzahl: 64 (vertikale 8 * horizontale 8-Matrix)
* Externe Schnittstelle: 1²C (schneller Modus)
* Bildrate: typisch 10 Bilder / Sek. Oder 1 Bild / Sek
* Betriebsart: Normal, Schlaf, Standby (10 Sek. Oder 60 Sek. Unterbrechung)
* Ausgabemodus: Temperaturausgang
* Berechnungsmodus: kein gleitender Durchschnitt oder zweimal gleitender Durchschnitt
* Temperaturausgangsauflösung: 0,25 ℃ / 32,45 ℉
* Nummer der Sensoradresse: 2 (1²C Slave-Adresse)
* Thermistorausgangstemperaturbereich: -20 80 ~ 80 ℃ (-4 ℉ ~ 176 ℉)
* Auflösung des Thermistorausgangs: 0,0625 ℃ / 32,1125 ℉
* Artikelgröße: 38 * 36 * 17 mm / 1,5 * 1,4 * 0,7 Zoll
* Artikelgewicht: 17 g
* Packungsgröße: 90 * 80 * 20 mm / 3,5 * 3,1 * 0,8 Zoll
* Verpackungsgewicht: 19 g 
<<<

stuff

* [[EW0001 - Panasonic Grid-EYE Thermal Image Sensor|https://www.youtube.com/watch?v=o_4K15vFM6s]]
* [[ Inside a cheap set of eBay digital calipers |https://www.youtube.com/watch?v=fKSSY1gzCEs]]
* [[How Does A Digital Caliper Work?|https://www.youtube.com/watch?v=u84BDCo22U4]]
* https://www.mdpi.com/2076-3417/8/12/2419
* https://www.grant-trebbin.com/2014/04/digital-calliper-teardown-and-repair.html
* https://www.mjt.me.uk/posts/digital-vernier-teardown/
* https://www.caliper2pc.de/schieblehre/typen/caliper_types.html
* https://www.electroschematics.com/digital-caliper/
* https://hackaday.com/2010/12/15/reading-a-digital-caliper-with-a-microcontroller/
* https://pcbheaven.com/exppages/Digital_Caliper_Protocol/
* https://www.sigrok.org/wiki/Protocol_decoder:Caliper
* https://www.robotroom.com/Caliper-Digital-Data-Port.html
* can be used as cheap DRO
* [[ Digital Caliper HACK/MOD from 150mm to 650mm |https://www.youtube.com/watch?v=JYnit_PSSMY]]
* [[ Caliper and Arduino i2c - measure 3D filament |https://www.youtube.com/watch?v=tTV52DihPTc]]
* [[ DIY Digital Caliper Data Plug |https://www.youtube.com/watch?v=34IsYgL4cMw]]
* https://www.youtube.com/results?search_query=diy+digital+caliper
* https://forum.allaboutcircuits.com/threads/grid-capacitance-linear-synchronous-sensor.158223/

maybe related

* https://www.ti.com/lit/an/snoa927a/snoa927a.pdf?ts=1692324948021
* https://ieeexplore.ieee.org/document/8980074/
* https://www.comsol.jp/forum/thread/attachment/124523/Planar_capacitive_sensors___designs-24313.pdf
using off the shelf power supplys like PC power supplies, power bricks and DC converter

i pretty much scrapped this project because i got a complete unit for the same price or even cheaper than i could have build a crude one from several DC converters and stuff.
got 6 cheap PAR56 for a steal because they all had water damage.
one of them worked, but only slightly. the others all didn't turn on.

the one working slightly seems to only needs a new dip switch because it has a bad connection and a few LEDs are out. it will function as reference.

for all remaining 5 PARs the fuses on the power supplies are blown. i have to check them individually.
i started disassebling all of them and checking the low voltage circuitry completely.
the power supplies output 8,5V or 9,5V (it's hard to read) and 26V according to the pcb markings. the working one outputs 8,5V and 26,3V, close enough.

so i checked all of them using my dual channel labbench power supply set to 8,5V and ~25V with current limiting enabled.
some of them also had bad dip switches and some dead LEDs but appart from that they seem to work fine.
have to check the DMX though, they might still have problems there.

after that i removed all of the power supplies and checked each one.
one of them looked pretty fine and all of the semiconducting components on the primary side checked good, it needed only a new fuse, had one lying arround. after replacing the fuse, i plugged it in carefully, without anything connected and the voltages meassured fine (9,3V and 26V).

i used the LED pcb with the most LEDs out as donor and fixed all of the other LED PCBs.
So we now have atleast 2 working PAR cans.

i checked all of the other 4 power supplies, 3 of them had blown up chips and transistors and all four had some burned resistors. all 4 need new T1A 250V 4mm fuses with leads.
componenta that had problems on all of them: uc3843an (power supply ASIC), 2sc945 (NPN), fta04n60d (mosfet), 1N4148 diode, small 1kOhm and 10k Ohm 5% resistors and bigger 1 ohm 5% 1W or so resistor.
one of them even had one of the 817 optocouplers (817cn) meassuring bad.

i have some salvaged small resistors i used a replacement, even had several salvaged 817c optocouplers, 1n4148 diodes and 2sc945 NPN. So i only need to order 4 new power supply chips, the mosfets and the 1w resistors.

i found the uc3843an power supply ICs from TI instead of on semi, but it should be a drop in replacement. for the Mosfet i had to find a different model, because digikey and ebay don't have the exact model but that's fine, found one that should match close enough.

i think i had one or two burned out red and blue LEDs, but around 10 burned out green ones. i think i also had to replace a lot of the green ones on the LED Bar.

i replaced all of the 10 position dip switches.

after replacing the obviously damaged components, i found one of the power supplies still had problems while testing, so i checked all components on it and found a 2.2Ohm 1/2W resistor that looked fine from the outside but was open circuit. luckily i also had some laying around that i also salvaged. after replacing it, the supply worked fine.

now i have 6 functioning cheapo LED PAR cans. light mixing is not the best, but good enough for some stuff.


i found a manual from a similar PAR can, that has the same modes and interface: https://www.bedienungsanleitu.ng/showtec/led-par-56-short-dmx/anleitung?p=9

control modes:

* auto mix
** switches 9+10
** switches 1-7 control the fading speed
* sound
** switch 10
** the sensitivity potentiometer controls the sound sensitivity
* manual
** switches 8+9+10
** red: 1&2
** green: 3&4
** blue: 5&6
** intensity: 00=0%; 10=25%; 01=50%; 11=100%
* DMX
** DMX address: switches 1-9 added together
** 1=1; 2=2; 3=4; 4=8; 5=16; 6=32; 7=64; 8=128; 9=256

many other models use an additional switch to switch between sound and auto mode or so.
this is just a cheap chinese device, nothing of value, but the simple trough hole circuitry makes reverse engineering easy. i think its a good starting point to understand mixing consoles.

problems:

* a lot of dust inside, cleaned it out
* blown electrolytic caps - replaced

other than these problems there was nothing wrong with it.

i replaced the thermal paste and it worked fine. Its a piece of cheap crap and sounds bad, but it works XD
many cheap ones are a ripoff and are just worse PWM charge controllers.

but there are also genuine ones

* [[Cheap(est?) Lithium MPPT Solar Charge Controller CN3722 - 12v Solar Shed|https://www.youtube.com/watch?v=liYZ5pYOZDE]]
* [[Another Cheap MPPT Charge Controller - CPT-LA10 - 12v Solar Shed|https://www.youtube.com/watch?v=1z5r3Yo6fmQ]]
* [[#142​ Solarenergie für den ESP8266, Arduino, etc. (mit deutschen Untertiteln)|https://www.youtube.com/watch?v=WdP4nVQX-j0]]
* [[#154​ Solar Charger for Microcontrollers|https://www.youtube.com/watch?v=dBx-g1dkdDQ]]
* [[#155​ The 5 Best Solar ChargerBoards for Arduino and ESP8266|https://www.youtube.com/watch?v=ttyKZnVzic4]]

i bought a cheap MPPT from ebay to use with a solar panel, it is based on the BQ24650

* https://www.ti.com/lit/ds/symlink/bq24650.pdf
* https://www.ti.com/product/BQ24650
* https://www.alldatasheet.com/datasheet-pdf/pdf/94809/TOSHIBA/TPC8107.html
* and two other unknown mosfets

i might need to make some adjustments

see also [[small cheap MPPT modules]]


ideas

* https://www.analog.com/en/products/lt8491.html#product-overview
* https://www.analog.com/en/products/lt8490.html#product-overview
* https://duckduckgo.com/?q=automatic+mppt+chip
* https://eevblog.com/forum/beginners/any-good-alternative-to-the-agilent-analog-discovery-2-that-i-should-know-about/
* https://www.allaboutcircuits.com/technical-articles/tool-review-analog-discovery-2-by-digilent/
* https://www.allaboutcircuits.com/news/analog-discovery-2-vs-other-pc-based-oscilloscopes-is-ad2-worth-the-hype/
* https://www.eevblog.com/forum/testgear/adalm2000-vs-analog-discovery-2/
* https://digilent.com/reference/test-and-measurement/start
* https://forum.digilent.com/topic/20482-alternative-to-analog-discovery-2/
* https://digilent.com/blog/red-pitaya-and-analog-discovery-2-how-do-they-compare/
* https://forum.allaboutcircuits.com/threads/analog-discovery-vs-mydaq.88688/
* https://knowm.org/a-review-of-usb-oscilloscopes-with-software-development-kits/
* https://sigrok.org/wiki/Supported_hardware#Mixed-signal_devices
* https://jamnopapa.blogspot.com/2017/04/makers.html

devices

* ADALM1000 - discontinued, was 32€, see ADALM2000
    ** https://wiki.analog.com/university/tools/m1k


* ADALM2000 - 170€ or so
    ** https://wiki.analog.com/university/tools/m2k
    ** https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/ADALM2000.html
    ** https://www.youtube.com/watch?v=bEg14JNpag8


* simpleFE
    ** https://www.geeky-gadgets.com/mixed-signal-frontend-29-01-2020/


* Red Pitaya
    ** https://redpitaya.com/
    ** https://en.wikipedia.org/wiki/Red_Pitaya_(hardware)
    ** 400$ for a impedance meassurement addon is just too much when the base version of the device costs around 400$
    ** https://www.ebay-kleinanzeigen.de/s-red-pitaya/k0


* ~OpenScope MZ - discontinued, see Analog Discovery
    ** https://github.com/Digilent/openscope-mz


* ~OpenLogger - discontinued, see Digital Discovery


* Analog Discovery 2
    ** https://digilent.com/reference/test-and-measurement/analog-discovery-2/start
    ** https://digilent.com/reference/test-and-measurement/start
    ** digikey seems to be cheap but doesn't have all addons


* Digital Discovery - only digital stuff
    ** https://digilent.com/reference/test-and-measurement/start


* Labrador - 50$
    ** https://news.ycombinator.com/item?id=20126760
    ** https://espotek.com/labrador/
    ** https://github.com/EspoTek/Labrador


* myDAQ
    ** https://www.ni.com/de-de/shop/hardware/products/mydaq-student-data-acquisition-device.html


* ScopeFun - Open Source/Hardware, 900$
    ** https://www.scopefun.com/
    ** https://www.crowdsupply.com/scopefun/open-source-instrumentation


* ThunderScope
    ** https://hackaday.io/project/180090-thunderscope
    ** https://www.hackster.io/news/thunderscope-the-open-source-software-defined-oscilloscope-is-coming-to-crowd-supply-220eb2e458fe


* Haasoscope - open source 120$
** https://www.crowdsupply.com/andy-haas/haasoscope


* EEZ Bench Box 3 - 470$+
** https://www.envox.eu/eez-bb3/
** https://www.crowdsupply.com/envox/eez-bb3


* bitscope?
** https://www.bitscope.com/
** https://sourceforge.net/projects/xoscope/

* ~JouleScope JS220 - Precision Energy Analyzer Scope
** [[ TSP #218 - JouleScope JS220 Precision Energy Analyzer Scope Review, Teardown & Experiments |https://www.youtube.com/watch?v=QLL3NgCIXQY]]
** [[ New Joulescope JS220 Better Specs Same Cost | Voltlog #433 |https://www.youtube.com/watch?v=wWetroEQoJw]]

* osci + multimeter
** [[ Ideales MESSGERÄT (nicht nur) für BEGINNER ������ MULTIMETER und OSZILLOSKOP in einem Gerät - OWON HDS |https://www.youtube.com/watch?v=uXhDyImpS9M]]

* Bode 100
** https://www.omicron-lab.com/products/vector-network-analysis/bode-100/#
* [[ A 110MHz Oscilloscope for under $70! Is It For Real And Is It Any Good? |https://www.youtube.com/watch?v=Jtc_01iH8tc]]
* https://www.youtube.com/watch?v=tASZaUEOdj0
* https://www.youtube.com/watch?v=5Aaq82dzRZI
433MHz

* https://www.youtube.com/watch?v=Sfx0v42rD40&pp=ygUMNDMzbWh6IHJhbmdl

nRF24

*

LoRa

*

stuff

* https://www.youtube.com/watch?v=nP6YuwNVoPU
* https://www.youtube.com/watch?v=vxF1N9asjts
* 
* https://chemrxiv.org/
* https://sinbosenaudio.com/
* https://china-sanway.com/
* https://aliexpress.com/store/5603107 - goldensoilaudio Store
* https://aliexpress.com/store/2184152 - Xinbaosheng Audio Equipment Store
* https://de.aliexpress.com/store/201473 - Audio workshop Store
general

* https://de.wikipedia.org/wiki/Schaltungssimulation
* https://en.wikipedia.org/wiki/Electronic_circuit_simulation
* https://www.mikrocontroller.net/articles/Schaltungssimulation

software



* Spice
** [[https://de.wikipedia.org/wiki/SPICE_(Software)]]
** https://en.wikipedia.org/wiki/SPICE#Open-source_successors
** https://hackaday.com/2016/02/26/adding-spice-to-your-workbench/
** https://hackaday.com/tag/spice/
** LTspice
*** https://de.wikipedia.org/wiki/LTspice
*** https://en.wikipedia.org/wiki/LTspice
*** https://www.analog.com/en/design-center/design-tools-and-calculators/ltspice-simulator.html
*** https://www.mikrocontroller.net/articles/LTspice
*** [[Fesz LTspice tutorials|https://www.youtube.com/playlist?list=PLT84nve2j1g_wgGcm0Bv3K4RSl2Jdjsey]]
** Ngspice - http://ngspice.sourceforge.net/index.html
*** https://en.wikipedia.org/wiki/Ngspice
*** included in KiCAD
** with KiCAD - 
*** https://mithatkonar.com/wiki/doku.php/kicad/kicad_spice_quick_guide
*** https://github.com/kicad-spice-library/KiCad-Spice-Library
** [[https://awesomeopensource.com/project/pepaslabs/LTSpice-parts?...]]

* other
** https://sourceforge.net/projects/circuitmod/
** https://en.wikipedia.org/wiki/List_of_free_electronics_circuit_simulators
** https://en.wikipedia.org/wiki/Comparison_of_EDA_software
** https://hackaday.com/2015/07/20/a-breadboard-in-a-browser/
*** https://lushprojects.com/circuitjs/
*** https://www.falstad.com/circuit/
*** https://www.falstad.com/circuit/circuitjs.html
*** https://www.falstad.com/afilter/
* https://en.wikipedia.org/wiki/GNU_Circuit_Analysis_Package


electromagnetics:

* http://openems.de/start/index.php
* [[SDG #245 Design of a 60W Synchronous LED driver and Current Density Modelling in PDN Analyzer|https://www.youtube.com/watch?v=5B6fNz9gk0U]]
* [[10 circuit design tips every designer must know|https://www.youtube.com/watch?v=FNLG_Y3QWVw]]
* [[My Top 10 PCB Design Tips|https://www.youtube.com/watch?v=kkc8BxL5Eo0]]
* [[15 Tips and Tricks for Using KiCad|https://www.youtube.com/watch?v=CgZ4WzhtxtY]]
* [[How To Make A Custom PCB From Design To Assembly|https://www.youtube.com/watch?v=JCmg-18BxTU]]
* [[EEVblog #1323 - PCB Layout Review & Analysis|https://www.youtube.com/watch?v=xhRhsCVF8mE]]
* [[EEVblog #1307 - TUTORIAL: PCB BOM Consolidation|https://www.youtube.com/watch?v=RwVzLOI4cmA]]
* [[EEVblog #1129 - Creating a Nice Readable Schematic|https://www.youtube.com/watch?v=R_Ud-FxUw0g]]
* [[EEVblog #244 - How To Lay Out A PCB - PSU Design Part 9|https://www.youtube.com/watch?v=2b1UdOmxVrw]]
* [[EEVblog #127 - PCB Design For Manufacture Tutorial - Part 1|https://www.youtube.com/watch?v=VXE_dh38HjU]]
** [[EEVblog #239 - PCB Design For Manufacture Part 2|https://www.youtube.com/watch?v=Uemr8xaxcw0]]
* [[Schematic Tips & Tricks - Phil's Lab #62|https://www.youtube.com/watch?v=ywBPm7TMpfk]]
* [[KiCAD PCB Design|https://www.youtube.com/watch?v=Ep4r-wD7PPs]]
* [[Techniques and Strategies for Building Electronic Circuits|https://www.youtube.com/watch?v=vq968AFgPhg]]
* https://components101.com/articles
* [[Chip Shortage - Top 5 Design Guidelines|https://www.youtube.com/watch?v=lTghYyXcQPs]]
* [[This credit card sized PCB can SAVE YOUR LIFE! (Shrinkify your projects with a 4 Layer PCB)|https://www.youtube.com/watch?v=sr_sm6VR9uc]]
* [[Phil's Lab: PCB Design|https://www.youtube.com/playlist?list=PLXSyc11qLa1b9VA7nw8-DiLRXVhZ2iUN2]]
** [[KiCad 6 STM32 PCB Design Full Tutorial - Phil's Lab #65|https://www.youtube.com/watch?v=aVUqaB0IMh4]]
** [[KiCad STM32 + USB + Buck Converter PCB Design and JLCPCB Assembly (Update) - Phil's Lab #11|https://www.youtube.com/watch?v=C7-8nUU6e3E]]
** [[KiCad STM32 Hardware Design - An Overview in 20 Minutes - Phil's Lab #15|https://www.youtube.com/watch?v=wLwKgMBWhpY]]
** [[How To Improve Your PCB Designs (Common Mistakes) - Phil's Lab #18|https://www.youtube.com/watch?v=IclJ9nbtYgI]]
** [[Critiquing My Own PCB Designs - Phil's Lab #43|https://www.youtube.com/watch?v=eQYJLRH4WPs]]
** [[High-Speed PCB Design Tips - Phil's Lab #25|https://www.youtube.com/watch?v=VRJI0X-6yTg]]
** [[How to design custom Footprints & Symbols in Kicad|https://www.youtube.com/watch?v=pV-4ElYoXYU]]
** [[Switching Regulator Component Selection & Sizing - Phil's Lab #71|https://www.youtube.com/watch?v=FqT_Ofd54fo]]
** [[Switching Regulator PCB Design - Phil's Lab #60|https://www.youtube.com/watch?v=AmfLhT5SntE]]
** [[Design Review - Schematic & PCB - Phil's Lab #70|https://www.youtube.com/watch?v=rIDl-V2G2yk]]
** [[Design Review (Spartan 7 FPGA) - Schematic & PCB - Phil's Lab #63|https://www.youtube.com/watch?v=au9hlIVZteE]]
** [[ESP32 + PCB Antenna Hardware Design Tutorial - Phil's Lab #90|https://www.youtube.com/watch?v=yxU_Kw2de08]]
** [[USB Hub Design Walkthrough - Phil's Lab #86|https://www.youtube.com/watch?v=iR2hYpq0KI0]]
** [[How To Learn PCB Design (My Thoughts, Journey, and Resources) - Phil's Lab #87|https://www.youtube.com/watch?v=aODkA2mrimQ]]
** [[Mixed-Signal Hardware/PCB Design Tips - Phil's Lab #88|https://www.youtube.com/watch?v=v6fTa6LRJLI]]
** [[Mini 6-Layer Mixed-Signal Hardware Design Walkthrough - Phil's Lab #78|https://www.youtube.com/watch?v=AxEL3eESL9I]]
* https://www.digikey.de/en/resources/online-conversion-calculators

RF

* [[KiCad STM32 + RF + USB Hardware Design - Phil's Lab #5|https://www.youtube.com/watch?v=14_jh3nLSsU]]
* [[Practical RF Hardware and PCB Design Tips - Phil's Lab #19|https://www.youtube.com/watch?v=_Hfzq1QES-Q]]
* [[Michael Ossmann: Simple RF Circuit Design|https://www.youtube.com/watch?v=TnRn3Kn_aXg]]
* https://din.one/site/cieco
 i think you don't have to study to do science, even though some did

* [[The Thought Emporium|https://www.youtube.com/c/thethoughtemporium/videos]]
* [[Tech Ingredients|https://www.youtube.com/user/TechIngredients]]
* [[Breaking Tabs|https://www.youtube.com/channel/UC06HVrkOL33D5lLnCPjr6NQ]]
* open source ecology
* https://en.wikipedia.org/wiki/Citizen_science
* https://de.wikipedia.org/wiki/Citizen_Science
* https://en.wikipedia.org/wiki/List_of_citizen_science_projects
* https://scistarter.org/
** https://en.wikipedia.org/wiki/SciStarter
* https://www.buergerschaffenwissen.de
** https://www.buergerschaffenwissen.de/citizen-science
* https://noise-planet.org/index.html
* https://publiclab.org/
* https://www.sweetwater.com/insync/quiescent-current/
* https://electronics.stackexchange.com/questions/220121/what-is-a-normal-quiescent-current-in-bjt-class-ab-amplifier
* https://www.learnabout-electronics.org/Amplifiers/amplifiers12.php
* https://hardwarebee.com/quiescent-current/
* [[Class AB Verstärker - RUHESTROM EINSTELLEN - genau erklärt - LECSON Quattra Teil 2|https://www.youtube.com/watch?v=75D7dWeqbdo]]
* https://www.learnabout-electronics.org/Amplifiers/amplifiers55.php
* https://www.learnabout-electronics.org/Amplifiers/amplifiers56.php
* https://sound-au.com/articles/class-g.htm
* [[Understanding Amplifier Class A & Class AB|https://www.youtube.com/watch?v=Aa8Yb4VIw8w]]
* [[TSP #23 - Tutorial on the Design and Characterization of Class-B and AB Amplifiers|https://www.youtube.com/watch?v=YuVqccvgNPM]]
* [[Transistor Amplifiers - tomtektest|https://www.youtube.com/watch?v=FG4obc9SkPE&list=PL2u6aYAXZ0Z8xIXAaWAZCrb-f9hOhJbU7]]
* https://de.wikipedia.org/wiki/Class-D-Verst%C3%A4rker
* https://en.wikipedia.org/wiki/Class-D_amplifier
* https://www.hackster.io/TapasBoard/raspberry-pi-based-audio-player-tapas-as-class-d-amplifier-22940d
* class d amps work very similar to some SMPS and inverters
* https://www.learnabout-electronics.org/Amplifiers/amplifiers56.php
* [[#FQC Class-D Verstärker ERKLÄRT - Power satt bei kleiner Baugrösse - Wie machen die das?|https://www.youtube.com/watch?v=sLQCoxlrqj8]]
* [[ [#12] Discrete Class-D Amplifier (PWM based) |https://www.youtube.com/watch?v=24sBtnnjK34]]
* [[ [#2] Designing A Discrete Closed-Loop Class-D Amplifier (Tutorial) |https://www.youtube.com/watch?v=7M2cWYeBmkc]]
* [[ [#18] Full digital Class-D amplifier with FPGA (by using a multibit sigma-delta noiseshaper) |https://www.youtube.com/watch?v=3Jd_ZyCZeGk]]
* [[ [#21] Self-oscillating Class-D amplifiers |https://www.youtube.com/watch?v=E2LPpjhGIYk]]
** https://www.youtube.com/watch?v=24sBtnnjK34&list=PLTNEB0-EzPlvu4CjLDSZcB0Vl9FHg2SAx
* [[ Class D amplifier basics for DIY audience designers part 1-6 |https://www.youtube.com/watch?v=5_NstNrT0xk]]
* [[ How Class D Amplifiers Work part 1 with EPC GaN FETs |https://www.youtube.com/watch?v=GCA3t67yOLc]]
* [[ The Class D audio amplifier - Basics (1/3) |https://www.youtube.com/watch?v=w1Rq1cxfNEk]]

hypex electronics

* https://www.diyclassd.com/
* https://www.hypex.nl/products/amplifier-families/
* https://en.wikipedia.org/wiki/Hypex_Electronics
* [[Lambda Labs KW18]]


stuff

* https://silentpcreview.com/two-amp-projects-8x100w-diy-h-k-770-restoration/
* https://www.ti.com/product/TPA3116D2
** https://www.ti.com/lit/ds/symlink/tpa3116d2.pdf
* https://hackaday.com/tag/clean-room/
* https://www.zmescience.com/science/poznan-mussel-water-plants-892524/
* https://en.wikipedia.org/wiki/Category:Solar_architecture - https://de.wikipedia.org/wiki/Kategorie:Solararchitektur
** https://en.wikipedia.org/wiki/Trombe_wall
*** https://de.wikipedia.org/wiki/Trombe-Wand
* https://de.wikipedia.org/wiki/Earthship
* https://en.wikipedia.org/wiki/Category:Solar_design
* https://en.wikipedia.org/wiki/Category:Sustainable_building
* https://en.wikipedia.org/wiki/List_of_pioneering_solar_buildings
* https://de.wikipedia.org/wiki/Kategorie:Energiesparendes_Bauen
* https://en.wikipedia.org/wiki/Air_conditioning#Other_techniques
* [[solar thermal]]
* [[Solar / renewable energy]]
* don't use sand
<<list-links "[all[current]tagging[]]">>

* https://lcamtuf.coredump.cx/gcnc/ - Guerrilla guide to CNC machining, mold making, and resin casting
* https://www.linuxcnc.org/
** https://en.wikipedia.org/wiki/LinuxCNC
** https://linuxcnc.org/docs/html/hal/tools.html
* https://de.wikipedia.org/wiki/Computerized_Numerical_Control
* https://en.wikipedia.org/wiki/Numerical_control
* https://www.linuxlinks.com/best-free-open-source-cnc-software/
* https://cncmachine.wiki/
* https://www.opensourceecology.org/portfolio/multimachine/
* https://www.opensourceecology.org/portfolio/cnc-circuit-mill/
* https://www.opensourceecology.org/portfolio/laser-cutter/
* https://www.opensourceecology.org/portfolio/cnc-torch-table/
* open tool changer designs?
** [[WP-DAKSH :: 3D Printed Tool Changer with 6 independent tools - First Look, Overview and Operation|https://www.youtube.com/watch?v=1WqDcpxC3-o]]
* https://wiki.opensourceecology.de/Portalfr%C3%A4se
* https://wiki.opensourceecology.de/Maker%27s_Mill
* https://wiki.opensourceecology.de/Bohrautomat
* [[ OPEN-CNC-Shield 2 Überblick - Anschlüsse - Module - Funktionen |https://www.youtube.com/watch?v=Jcu9nbrWOIc]]

open source controller

* https://smoothieware.org/
* https://buildbotics.com/

stuff

* [[The printer port isn't dead yet! part 3. new ball screw and 3d printed parts for test fit.|https://www.youtube.com/watch?v=K1yNw-DbM_0]]
* [[CNC Finale: Automatic Toolchanger Spindle Install & Testing|https://www.youtube.com/watch?v=vB_FvkllLPc]]
* https://wiki.opensourceecology.org/wiki/Category:Digital_Fabrication
Co²-neutralität ist schwierig... meist wird zumindest bei der herstellung der komponenten der systeme CO² poduziert... das kann man aber minimieren indem in der produktion auch CO² neutraler strom, also strom aus u.a. windkraft und solar, genutzt wird.

* Akkus
** die unterschiedlichen Technologien haben underschiedliche vor und nachteile was u.a. die rohstoffe, deren nachhaltigkeit und den energiebedarf bei der herstellung angeht
* Luftdruck
** speicherung der energie im druck eines gases (meist luft), welche dann kolben oder eine turbine antreiben kann und damit wieder nutzbar ist
* chemische träger
** Methan, Wasserstoff, (Bio-)Ethanol, Biotreibstoffe/Biokraftstoffe (Biodiesel, etc.)
** [[Why Don’t We Have Functional Biofuel Yet?|https://www.youtube.com/watch?v=LEepDbZqFmE]]
** [[Biokraftstoffe: Pro und Contra|https://www.youtube.com/watch?v=rzVIssYb06Y]]

brennstoffzell / fuel cell

* https://www.ose-germany.de/projekte/zac/
* [[Inductors Explained - The basics how inductors work working principle|https://www.youtube.com/watch?v=KSylo01n5FY]]
* [[Electronic Basics #12: Coils / Inductors (Part 1)|https://www.youtube.com/watch?v=kdrP9WbJIb8]]
* [[Electronic Basics #13: Coils / Inductors (Part 2) ~~ Reactance|https://www.youtube.com/watch?v=XCnI6ZOYKes]]
* [[How to choose the right coil type (inductor)?!|https://www.youtube.com/watch?v=hYOtx_2hYTU]]
* [[How INDUCTOR's work & How to make your own|https://www.youtube.com/watch?v=d-E12DlzGGc]]
* [[Inductance basics|https://www.youtube.com/watch?v=VSMGnmQApA0]]
* transformers
** [[Transformers 101: How They Work & How To Wire Them|https://www.youtube.com/watch?v=XMsb_qFy5sc]]
** [[How To: Rewind Microwave Oven Transformer, Trash To Treasure!|https://www.youtube.com/watch?v=I3fQjlInC44]]
** [[Is it easy to create your own Transformer? Everything you need to know about Transformers! -- EB#42|https://www.youtube.com/watch?v=2cxcP5lY7K4]]
* [[Inductor equations|https://www.youtube.com/watch?v=w1NR5sjsChI]]
* [[Inductor kickback 1 of 2|https://www.youtube.com/watch?v=YKKd5p4a5Lo]]
* important for meassuring coils/inductors: [[component testers / LRC / LC meter]]
* [[Electronics tutorial - Inductor saturation|https://www.youtube.com/watch?v=Tl_LH--5Ce8]]
* [[Electronics tutorial - Inductor magnetic field emissions|https://www.youtube.com/watch?v=ezspdaumu1w]]
* [[Electronics tutorial - Ferrite and Magnetic permeability|https://www.youtube.com/watch?v=-EqmJx4rJTc]]
* [[Electronics tutorial -TRANSFORMER construction and performance|https://www.youtube.com/watch?v=0XWzBeP5Rdc]]
* [[EMC tutorials - The FLUX BAND|https://www.youtube.com/watch?v=Vx00iKkWC3w]]
* [[ How Inductors Work |https://www.youtube.com/watch?v=PvIb2LtgmaU]]
* https://pad.hacc.space/
* ~BigBlueButton
* Jitsi
* https://etherpad.org/
* cryptpad
** https://cryptpad.digitalcourage.de/
* nuudel / framadate
** https://nuudel.digitalcourage.de/
** https://framagit.org/framasoft/framadate/framadate/wikis/home
* framasoft tools - https://framasoft.org/en/
* https://openslides.com/ - conferences/member meetings
* Moodle - more geared towards education
* https://github.com/getfireside/fireside - prototypefund, dead
lists

* https://www.cargobike.jetzt/lastenrad-hersteller/
* http://www.nutzrad.de/index.php?seite=kat

bikes

* https://www.christianiabikes.com/
* https://www.xtracycle.com/
* https://www.babboe.de/
* Larry vs. Harry
* Muli-Cycles
* Douze
* https://www.moghul-rikschas.de/
* Urban Arrow
* Cube
* Tern
* Bergamont
* Kettler
* Riese und Müller
* Gazelle
* Pfau-Tec
* Triobike
* Wike
* Yuba
* Hercules
* http://www.xyzcargo.com/ - some open hardware stuff but most is commercial
* https://www.vowag.de/
* https://www.radkutsche.de/
* https://cargocycle.de/
* Bakfiets Cangoo E-Groovy - Sonnensystem
* https://lademeister.bike/ - produced by a coop
* https://veload.org/
* https://www.velo-lab.de/lastenrad/leichtes-lastenrad
* [ Das ARGO Cargobike Kit macht aus deinem Fahrrad ein Long John Lastenrad - kann das funktionieren? |https://www.youtube.com/watch?v=Q4ySHXXjdes]]
* https://www.rytle.com/
* https://vhelio.org/ - open source, non-profit
** https://md.opensourceecology.de/s/VHelio-Review-Proposal#
** https://www.velomobilforum.de/forum/index.php?threads/vhelio-ein-open-source-projekt-solartadpole-fuer-zwei-personen.68220/
* ...

trailers

* https://www.carlacargo.de/
* https://www.fleximodal.fr/
* https://cargocycle.de/ they featured a big trailer on their social media
* https://www.hinterher.com/ - different sizes, even feature a big trailer for palettes in their news
* https://wicycle.com/de/
* https://instagrid.co/de/products/zero-387
* https://www.greenpack.de/der-greenpack-akku/ - claim to have some open hardware which is bullshit
* https://akkuenergiesysteme.de/
* atmel
* STM8
* STM32
* 8-Bit 8051-based NUVOTON chips
models

* PINECIL v2
** https://www.pine64.org/pinecil/
** https://eleshop.de/pinecil-smart-mini-tragbarer-lotkolben.html
* PTS100
** 
* PTS200
** TS and T12 tips
* T65 / Mini65
** 65W

* Miniware TS80P
** https://eleshop.de/ts80p.html
* Miniware TS100
* Miniware TS101
** https://eleshop.de/ts101-lotkolben.html
** 65W
** USB-C PD + barrel jack
* Fnirsi HS01
** https://eleshop.de/fnirsi-hs01-lotkolben.html
* GVDA
** 65W
** USB-C PD / barrel jack adapter

shops

* https://eleshop.de/lottechnik/lotstationen/alle-lotstationen.html
* https://pine64eu.com/product-category/devices/solderingirons/
* https://pine64.com/product-category/pinecil/?v=0446c16e2e66

tests / comparisons

* [[Best hobby soldering iron? Pinecil vs. Miniware, Hakko, Weller and Ersa|https://www.youtube.com/watch?v=R2sPDQeGlj8]]
* [[EEVblog 1543 - Mailbag FNIRSI HS-01 USB Portable Soldering Iron - YouTube|https://www.youtube.com/watch?v=Ia0C_X0ycFE]]
* [[FNIRSI intelligent soldering iron HS-01 - YouTube|https://www.youtube.com/watch?v=R0Z3QJrkXpI]]
* [[SDG #275 Pinecil V2 PINE64 Open Source Soldering Iron - Test with PCBs from JLCPCB - YouTube|https://www.youtube.com/watch?v=-TosWhPsru4]]
* [[TS101 Soldering Iron - Better than TS100? - YouTube|https://www.youtube.com/watch?v=IZiL0RK4E20]]
* [[ Miniware TS101 Smart Soldering Iron Test & Review. TS101 vs Pinecil |https://www.youtube.com/watch?v=XgzYn8qSlMc]]
* [[PTS200 Smart Soldering Iron - Virtually Indestructible! - YouTube|https://www.youtube.com/watch?v=Omu6aXXqMDk]]
* [[FNIRSI HS-01 Smart Soldering Iron Test And Review|https://www.youtube.com/watch?v=rSfzHMbBO4E]]
* [[$25 Pinecil Soldering Iron vs TS100 - YouTube|https://www.youtube.com/watch?v=eme_AUayLp8]]
* there are cheap component testers from china on ebay but they are most usefull for getting a sense of the type of some components, not all meassurements are really acurate
** [["transistor tester" (avr) component tester]]
* LRC meters are used for meassuring inductance (L), capacitance (C) and resistance (R)
** one meassuring true inductance, true capacitance, ESR and maybe Q factor is most useful, but there are meters specialized in ESR for example
** https://en.wikipedia.org/wiki/LCR_meter
** https://de.wikipedia.org/wiki/Wechselspannungsbr%C3%BCcke
** https://en.wikipedia.org/wiki/Q_meter
** https://hackaday.com/2021/03/22/build-it-yourself-lc-meter/
* https://electronoobs.com/eng_arduino_tut10.php - arduino Resistence meter
* https://electronoobs.com/eng_arduino_tut10_1.php - arduino Capacitance meter
** [[Arduino capacitane meter with LCD screen|https://www.youtube.com/watch?v=8yGbOlJ7ZWM]]
* https://electronoobs.com/eng_arduino_tut10_3.php - arduino Inductance meter
** [[Inductance meter with Arduino|https://www.youtube.com/watch?v=BGjV5vUvGPc]]
* https://www.qsl.net/dl2lux/pdf/lcmeter_dl.pdf
* https://hackaday.com/2021/03/22/build-it-yourself-lc-meter/
** https://hackaday.io/project/178081-build-an-lc-meter
** https://github.com/coreWeaver/LC-Meter
* [[EEVblog #1020 - Is A $7 LCR / Component Tester Any Good?|https://www.youtube.com/watch?v=7Br3L1B80ow]]
* [[Instrument Basics: LCR Meter - Workbench Wednesdays|https://www.youtube.com/watch?v=C3AVUHcOIOc]]
* [[SDG #019 Peak LCR45 LCR Meter Review and Teardown |https://www.youtube.com/watch?v=s29kMjpH8A4]]


ESR

* https://www.youtube.com/watch?v=ivVSq0IiZGo
* https://en.wikipedia.org/wiki/ESR_meter
* Peak atlas ESR70
** [[SDG #010 Peak Atlas ESR Meter - Review, Teardown and Analysis|https://www.youtube.com/watch?v=YR0-SQYmFhk]]
** [[Review: Peak Atlas ESR70 Capacitance and ESR meter|https://www.youtube.com/watch?v=LZ49GCnf0V4]]
** [[Peak Electronic Design ESR70 Gold Review - No.950|https://www.youtube.com/watch?v=FrhF-V0fsh8]]
* [[ESR70 & Blue ESR meters, comparison, features and differences|https://www.youtube.com/watch?v=fD-8Dppp03w]]


DIY

* [[DIY transformer/inductor tester|https://www.youtube.com/watch?v=QBbEYYWiBI8]]
* https://producerhive.com/music-production-recording-tips/vocal-compression-settings-cheat-sheet/
* https://www.academia.edu/38645745/Vocal_Compression_Cheatsheet
* https://www.playingwithgear.com/post/vocal-compression-cheat-sheet
* https://www.homebrewaudio.com/24868/using-audio-compressor-voice-over-jobs/
* using to much compression can sound bad, using none can result in the listeners ears hurting because sound got loud
* https://gist.github.com/scottburton11/3222152 - nice in depth
* [[Designing a simple audio compressor from scratch|https://www.youtube.com/watch?v=Wag-yTyAxPA]]
** https://www.youtube.com/watch?v=OMeKERW1E60

Limiter

* https://www.jobst-audio.de/tool/helfer/limiter-rechner
* "auftrag sound" on youtube uses a "powersoft limiter calculator" excel sheet or so
[[Computer accessibility|https://en.wikipedia.org/wiki/Computer_accessibility]] is important, so that all people can use software equally. In open source this is often neglected because not many people have disabilities and not many developers know people with disabilities and many don't have the time to also provide accessibility appart from fixing bugs and errors.

e.g. high-contrast support might be pretty easy, but screenreaders likely not so much

Maybe there are projects to make open source better in that regard?

i don't know if and which tools and guides/guidelines are good, but some sources like w3 or MDN are pretty trustworthy.

If you want to develop tools it's pretty much mandatory to be in constant consultation and tests with the people you develop that tool for, else your tools might be totaly useless because you don't know the needs of the people.

* [[example for telegram (german)|https://social.anoxinon.de/@jr/104120620545566933]]
* Screenreader
** https://de.wikipedia.org/wiki/Screenreader
** https://en.wikipedia.org/wiki/Screen_reader
* Web Accessibility
** https://www.w3.org/WAI/fundamentals/accessibility-intro/
** https://www.w3.org/WAI/standards-guidelines/wcag/
** https://www.ada.gov/pcatoolkit/chap5toolkit.htm
** https://webaccess.berkeley.edu/resources/tips/web-accessibility
** https://www.w3schools.com/html/html_accessibility.asp
** https://developer.mozilla.org/en-US/docs/Learn/Accessibility
** https://html.com/blog/25-website-accessibility-checker-tools/
** wordpress
*** https://make.wordpress.org/accessibility/2016/03/21/wordpress-goes-wcag/
*** https://wordpress.org/about/accessibility/
*** https://www.deque.com/blog/wordpress-accessibility/
* https://oskars.org/ - braille-keybord for smartphone
<<list-links "[all[current]tagging[]]">>

* https://github.com/prakhar1989/awesome-courses
* https://bios-pw.org/
cheap car hifi amp, 2x ~70W@4Ohms

high switching noise, probably dead electrolytic caps

* https://www.amp-performance.de/455-Concord-CA50-2.html
* https://www.plugsocketmuseum.nl/index.html - Digital Museum of Plugs and Sockets
* "stecker wasserdicht luftfahrt"
* cnlinko
** https://connector24.de/c/power-steckverbinder/lp-serie-power-stecker
** https://connector-distribution.com/eu/industrie/netzstecker/lp-serie-netzanschluss/lp-16-serie/m16-kunststoff/188/lp-16-power-netz-steckverbinder-m16-3-pol-maennchen-ip67-max.-400-v-10-a
problem: no audio output from the receiver

internals

* 13V 1A power supply
* fake screen for the frontpanel, device has fixed frequencies
* main board only has a small switching power supply ic: MC34063A; the rest is discrete
* 2 daughter boards (1 for each channel)
** KT0613 - main chip, UHF wireless mic receiver ASIC
*** http://www.ktmicro.com/?mnwx_61/154.html
** hk 24c02 - 2 kbit eprom for the wireless settings
** UTC4558 - dual opamp - https://www.alldatasheet.com/datasheet-pdf/pdf/1154494/YOUWANG/UTC4558.html
** 5V and 8V power supply
** 1117 5V v-reg


steps

* receiver detects signal from wireless mics
* i had one channel randomly working for a short time
* was able to inject a signal to the output of the daughter boards and got output, the rest of the circuitry seems to work fine
* some of the flimsy cables to the antennas or front panel already ripped of, I have to improve those. also the dc jack is crooked, i want to fix that too
* power supply to the daughter boards seems fine
* desoldered the daughter boards fully and checked them
** i think there is some short on the daughter boards, because components get pretty hot, was not able to identify them yet
* Q Light Controller+ - https://qlcplus.org/features.html
* Art-Net DMX - https://art-net.org.uk/ / ARTNet
* https://github.com/twischer/WLAN-IO
* DMX
* https://openthread.io/ - some IoT stuff
* https://benjamin.kuperberg.fr/chataigne/en
** https://hackaday.com/2023/01/06/chataigne-an-open-source-swiss-army-knife/
* https://ossia.io/

hardware

* WS2812B or WS2813 or so, adressable RGB LEDs, can be individually controlled
* milky plastic tubes with rgb LEDs and integrated dmx/wifi/etc. controller, maybe integrated rechargeable batteries?

proprietary stuff

* https://nanoleaf.me/en-EU/
* https://resolume.com/

stuff

* https://computer.rip/2022-11-23-enlightenment-and-lighting-controls.html
* capacitive touch
* Adafruit ANO Rotary Navigation Encoder
** https://www.adafruit.com/product/5221
** https://www.adafruit.com/product/5001
** Zippy Ano
* rgb encoder - encoder with transparent shaft and built in rgb led
* rubber keypads
** https://www.adafruit.com/product/1611
** https://www.adafruit.com/category/236
* slide otentiometers / fader with integrated LEDs
** https://www.bourns.com/pdfs/PTL.pdf
** https://www.alibaba.com/product-detail/60mm-Travel-Slide-potentiometer-SA6005-NJAOA_237776348.html?spm=a2700.shop_plgr.41413.15.740f6464q4eUgE
* display buttons
** https://hackaday.com/2020/12/17/adaptive-macro-pad-uses-tiny-oled-screens-as-keycaps/
** https://hackaday.io/project/176239-keybon-adaptive-macro-keyboard
** https://github.com/CoretechR/Keybon
** https://www.reddit.com/r/AskElectronics/comments/gz9meq/part_sleuthing_display_switches_lcdoled_push/
a list of cool people and projects i don't have a category for yet

* CCC - https://ccc.de
* https://www.tolerave.de
* https://coma-emerald.de/
* fefe - https://blog.fefe.de/
* https://www.youtube.com/user/wwwSatankade - Dr. Mark Benecke
* Linus Neumann
** https://linus-neumann.de/
** https://chaos.social/@linuzifer
** https://twitter.com/linuzifer
** https://github.com/Linuzifer
* sascha lobo
** https://de.wikipedia.org/wiki/Sascha_Lobo
* enno lenze
* https://de.wikipedia.org/wiki/Wolfgang_M._Schmitt
* https://www.ggultras.de/
* https://hassmelden.de/
* https://computertruhe.de/
* https://www.abgeordnetenwatch.de/
* open knowledge foundation
* https://www.wikimedia.de/unlock/
* https://opennext.eu/
* https://www.opensourceecology.org/ - US
** https://opensourceecology.de/ - germany
** http://www.opensourceecologie.org/ - france
* https://riseup.net/, https://www.systemli.org/index.html, https://disroot.org/, etc.
** https://www.systemli.org/friends/
** https://help.riseup.net/en/security/resources/radical-servers
* https://openculture.agency/start/
* https://www.appropedia.org/Welcome_to_Appropedia
* https://www.ose-germany.de/
* http://makers4humanity.org/
* https://wirbauenzukunft.de/
* https://www.offene-werkstaetten.org/
* https://fragdenstaat.de/
* https://www.abgeordnetenwatch.de/
* https://wechange.de/ or https://plattform-n.org/n/ / https://www.netzwerk-n.org/ might be useful for many initiatives, even though they don't have Cyber/data sovereignty
* https://www.hogesatzbau.de/
* https://digitalcourage.de
* okfn.de - open knowledge foundation deutschland
** https://prototypefund.de/
* https://repair.eu/
* https://fabcity.hamburg/ - nur scheiße das da die BW mit drin hängt
* https://freiheitsrechte.org/
** [[Logbuch:Freiheit|https://www.youtube.com/playlist?list=PLFvKRXhjAguwMBfh2nFWibm_U7rKsMkFz]]
* https://sea-watch.org/
* https://sea-shepherd.de/
* https://www.reporter-ohne-grenzen.de/
* https://so36.net/
* https://nadir.org/
* https://systemausfall.org/
* https://www.immerda.ch/
* https://www.autistici.org/
** https://www.autistici.org/links
** https://noblogs.org/
* https://www.ingenieure-ohne-grenzen.org/de
* https://www.aerzte-ohne-grenzen.de/
* https://sea-shepherd.de
* https://anstiftung.de/
* sea punks
* https://verschwoerhaus-bleibt.de
* https://anita-tilda-faber.org/
* FSFE, Mozilla Foundation, DPGA, Open Science Hardware Foundation
* https://www.youtube.com/watch?v=Gou2V33nByU
* https://de.wikipedia.org/wiki/Bunte_Republik_Neustadt
* https://de.wikipedia.org/wiki/Conch_Republic
* https://de.wikipedia.org/wiki/Freistadt_Christiania
* https://de.wikipedia.org/wiki/Gay_%26_Lesbian_Kingdom_of_the_Coral_Sea_Islands
* ~~https://de.wikipedia.org/wiki/Kliemannsland~~
** https://lmaafk.de/
* [[Pulse Tube Cryocooler - Part 1|https://www.youtube.com/watch?v=GjRoThMyNGA]]
* [[Pulse Tube Cryocooler - Part 2 (-75C)|https://www.youtube.com/watch?v=WOmjJFk8rl0]]
<<list-links "[all[current]tagging[]]">>
* https://en.wikipedia.org/wiki/Semiconductor_curve_tracer
* https://www.paulvdiyblogs.net/2021/03/building-curve-tracer-version-3.html
** https://www.paulvdiyblogs.net/2017/12/building-curve-tracer.html
* [[Curve & Signature Tracers - tomtektest|https://www.youtube.com/watch?v=ri1X2vl0h4I&list=PL2u6aYAXZ0Z-_VB8-WULtLuFJQfAEY0le]]
* https://ostechnix.com/how-to-create-a-custom-ubuntu-live-iso-image-with-cubic/
* https://www.techrepublic.com/article/how-to-create-a-custom-ubuntu-iso-with-cubic/
* https://itsubuntu.com/tools-create-custom-linux-os/
* https://fogproject.org/ - fog server
** https://schoolitexpert.com/network-tools/fog/306-install-fog-server
*** see also [[Open education, open learning, open university, open knowledge]]
* clonezille might have a feature
* https://holzmueller-sachsen.de/Konstruktionsvollholz ?
* https://www.ikea.com/de/de/planners/ivar-planner/
** https://www.hausbau-forum.de/threads/effektive-breitenmasse-ikea-ivar-nutzbar.21826/
* https://holzmueller-sachsen.de/OSB
* https://holzmueller-sachsen.de/Theaterlatten_Fichte ?
* https://holzmueller-sachsen.de/Glattkantbretter ?
* https://en.wikipedia.org/wiki/Cyber_sovereignty
* https://en.wikipedia.org/wiki/Network_sovereignty
* https://de.wikipedia.org/wiki/Digitale_Souver%C3%A4nit%C3%A4t
* Datensouveränität
* https://www.omnicalculator.com/sports/cycling-wattage
* https://wattscalculator.com/
* https://www.bergfreunde.eu/cycling-wattage-calculator/
!! Info

* 2x 400W RMS(?)
* the amp uses a primary-secondary design, where channel B contains parts of the circuitry for both channels

!!Problem:

Left channel was overheating, owner tried setting the bias current didn't really change the problem, owner tried swapping the channels for refurbished ones but no luck either.
The Amp was previously given to a repair shop that does not repair Amps and i don't quite know if anyone there has done something, because screws went missing there (it was still open from the owner).

the amp boards should have been fine, but when i switched it on something shorted.
i later found uppon inspection a spring washer like the one holding the power transistors to the heatsink. there was no washer missing so i suspect its leftover from the refurbishement. It shorted out one or several of the transistors, which are now dead. So the refurbished Channel A is dead now.

had to reverse engineer the Amp because there are no schematics. The refurbished Bords may be a newer version, they have some changes.

!! Comparison of the different Board Versions:

* Original Boards have Markings "PSA-3000-L", "06,06,K1'" and "PSA-3000-R", "07,28,K1'"
* refurbished Boards have markings "PSA-3000-L", "VER031117 and "PSA-3000-R", ""
* (L being Channel A and R being Channel B)
* the original Boards have better PCB quality than the refurbished ones: the main material is of better quality and the solder resist coating is much better
* the Parts BOM has changed a bit, but there are no obvious quality differences
* both channels of the refurbished PCBs have a GND connection which seems to be meant to connect the middle-potential between "+VCC" and "-VCC" of both channels, i'm not sure about the benefits
* small parts of the refurbished PCBs have small layout changed to make them more compact. the changes are pretty superficial and don't make the PCB footprint much smaller, i don't think it makes much difference in production.
* both channels have two thermistor-like parts, but one of them marked "R36" on the pcb is mounted to the power transistors on the refurbished versions. on the original versions it is just on the board. the part is "uei 090"
* the opamps are different. original version uses JRC NJM2068D; refurbished version uses TI NE5532P

a NJM13700 is used which is a pretty new part to me. it's part of the volume control circuitry.

* https://www.mouser.com/datasheet/2/294/NJM13600_NJM13700_E-346722.pdf
* https://en.wikipedia.org/wiki/Operational_transconductance_amplifier
* https://de.wikipedia.org/wiki/Transkonduktanzverst%C3%A4rker

Pots:

* quiescent current / DC offset?
* conducting angle?
* ?

!! What i did:

* clean the amp from dust and stuff, clean the Fan
* checking everything for obvious damaged/faulty parts or bad solder joints
* check connections of the trafo to the power PCB
* check power bridge rectifiers
* check trafo voltage output
** the transformer is wired to provide 2x 118V~
** rectified and smothed it might be a bit more
* some reverse engineering
* while comparing, inspecting and reverse engineering i found some small solder balls which i removed and i resoldered some parts which looked a bit poorly soldered
* change out the refurbished with the "old" Channel-Modules because refurbished channel A is blown
* snug up the screw holding the tranformer
* check all cabling for correctness and replug the cables
* check power cables for good connection
* connect Amp and hope it doesn't blow up
** it didn't blow up
* let it run some time in idle without audio playing
** both channels pretty similar in warmth to the touch
* test music
** sounds fine
* test idle/bias current
** pretty much all 0,5mV, one side on channel b it was 0,7mV but the pots are probably not fine enough that trying to change it would make it much better
* let it run some time with music at a lower level and meassure temps
** both channels pretty spot on 35°C

I don't really know what fixed the problem, but i can't replicate it, it works fine for me now.

as a last step i checked the output of both channels on the oscilloscope and compared them to see if there are any differences, maybe the pots have to be adjusted, but i found nothing.

!! repair of the shorted channel

As explained earlier one of the refurbished channels was shorted when i got it. The owner opted to repair the channel.

I checked if i could find any other parts on the pcb (apart from the power transistors) that might be damaged and compared the damaged channel a with the good channel b, but all seems fine.

I desoldered the power transistors and preamp transitors to check them one by one. 3 power transistors are dead, 2 completely shorted and one is something inbetween but also not good anymore.
The preamps seem fine, but its a good advice to change all transistors because their state is unknown and they might be pre-damaged and might easily fail later.

The Mission 900 uses 4x 2SC5200-O and 4x 2SA1943-O per channel, preamps are MJE15032G and MJE15033G.

its a nice coincidence that the [[Palladium 1200|DAP Palladium 1200 Vintage repair]] i also have for repair uses the same power transistors. the transistors are hard to get, but now it saves a bit of time for both.

Luckily i could get all parts after some time.

i cleaned the heatsink thoroughly. This amp is simpler to assemble again than the Palladium 1200. The PCB fits into a groove on the heatsink. I took each power transistor one by one, applied thermal paste on the back, slit the pins through the pcb to put them in the right place on the heatsink and screwed them down. i also applied thermal paste behind some diodes and bent them a bit so they touch the heatsink propperly. After everything was in place i checked once again that i didn't mix them up or so. Then I soldered every connection.

I pretty randomly checked some of the other semiconductors on both amp boards and found one broken diode on the R/B Channel PCB. The SMD diode "D4" was cracked and open circuit. I got some 1N4004 or 1N4007 from a small local shop, but they didn't have smd parts, so i got through-hole ones. To solder them to the PCB i bent the pins so the diode can be flat on the pcb and i removed some solder resist from the trace to have a bit more pad to solder to.

The damaged diode was just a ordinary low power rectifier diode for the 15V supply for the opamps and other circuitry.

Then I thoroughly tested every semiconductor part on both boards and compared the readings to check if i might have missed other damaged components. The passive components all seem fine too.

After i was pretty sure no other components are damaged i was pretty confident they won't blow up again when testing. The Amp still had the original modules mounted. I tested them again and checked the voltages for the opamps to compare it with the refurbished channels were i replaced a diode. pretty good +-15V.

I then changed the amp modules out to check the repaired ones.
They worked fine and didn't have any audible difference. They also didn't heat up excessive. The supply voltage for the opamps was also good. So they are successfully repaired.

The owner wanted me to change out the amp modules back to the original ones, so i did that.
* https://circuitsgeek.com/tutorials/class-ab-amplifier/
* https://www.tnt-audio.com/clinica/bias_e.html
* https://electronics.stackexchange.com/questions/324215/how-to-keep-the-bias-current-constant-in-class-ab-output-stage
* https://www.diyaudio.com/community/threads/optimum-class-ab-bias-current-again.297853/
* [[ Class A Class B or Class AB - How to set the bias current with Micro-Cap Tutorial |https://www.youtube.com/watch?v=jonOEyUftpM]]
* [[ TSP #23 - Tutorial on the Design and Characterization of Class-B and AB Amplifiers |https://www.youtube.com/watch?v=YuVqccvgNPM]]
* [[ TSP #15 - Tutorial on the Theory, Design and Characterization of a Single Transistor BJT Amplifier |https://www.youtube.com/watch?v=Y2ELwLrZrEM]]
* [[ Setting Bias on a Class AB Power Amp |https://www.youtube.com/watch?v=RnhkXjmvdu8]]
* https://www.electronics-tutorials.ws/amplifier/class-ab-amplifier.html
* https://www.edaboard.com/threads/need-help-with-understanding-the-biasing-of-a-class-ab-output-stage.300967/
* [[ Class-A Power at 8 and 4 ohms, THD and Bias w Temperature |https://www.youtube.com/watch?v=nY_STZ49UJs]]
* [[ Amplifier Theory |https://www.youtube.com/watch?v=c8sNM0Gq-PE]]
* [[ Push-Pull Pair - Class B, Class AB and Class A operation |https://www.youtube.com/watch?v=S7jrirsfkNw]]
* [[ Class AB Verstärker - RUHESTROM EINSTELLEN | genau erklärt | LECSON Quattra Teil 2 |https://www.youtube.com/watch?v=75D7dWeqbdo]]
* [[Transistor Amplifiers| https://www.youtube.com/watch?v=FG4obc9SkPE&list=PL2u6aYAXZ0Z8xIXAaWAZCrb-f9hOhJbU7
* [[ Understanding Amplifier Class A & Class AB |https://www.youtube.com/watch?v=Aa8Yb4VIw8w]]
* https://www.electronics-tutorials.ws/de/verstarker/verstaerker-der-klasse-ab.html
* https://electronics.stackexchange.com/questions/580849/how-to-bias-a-mosfet-class-ab-amp
* https://www.fairaudio.de/lexikon/verstaerker-klassifizierungen/
* [[ Spice simulation of the Class A amplifier |https://www.youtube.com/watch?v=fF9XzhJWYfk]]
!! DAP Palladium 1200 Vintage

Fuses of one Channel missing/Blown, one Channel is dead, other one has some charred resistors but seems fine otherwise.

the DAP Palladium 1200 Vintage uses a Class G design. It uses Mosfets controlled by a comparator to switch between two voltage rails from the linear supply/toroid transformer.

First task i did was some cleaning to get all of the old dust out.

One of the Channels was shorted, the other one had some very charred resistors which also charred the pcb and a film cap next by. I'm also replacing an electrolytic cap next to the resistors just to be sure, because electrolytic ones can quickly degrade.

It is hard to find out which power rating and type the original resistors had. I carefully scraped of the charred laquer on the old ones to see the construction and to guess the type. The type is Metal Oxide Film i guess, because it doesn't have wound wires and more like a metal film all around with cut in slots, also next to wire wound these are pretty mch the highest power resistors. I bought some of the highest value of that type that would still fit in small space were they belong. They ended up being 3W rated Yageo RSF3WSJT-73-10R. The caps are the Panasonic ECW-FD2W104J4 film cap and nichicon UPJ1E101MED1TD electrolytic, both should work fine.

see also [[resistors]]

The shorted channel will get a replacement of all the power transistors and of the preamp transistors. The Toshiba 2SA1943 and 2SC5200 still being manufactured, so one can still get them. It is Important to check the Suffix/hfe rating of them and buy the right ones. In audio the O-Rating seems to be most common for these complimentary pair. If your electronic parts distributor of choice lists them with additional suffixes they only indicate the way of packaging (e.g. tray/tablet or tube) and not the package/case of the device itself.

The preamp transistors 2SA1837/2SC4793 are not manufactured anymore and i could not find a source for original ones. But NTE Electronics manufactures clones/licenced alternatives(?) and i opted to buy these. The data in the datasheets is pretty identical.

Next Time i should try to check everything first, because i discovered more problems after i already placed a big order and hoped i had all replacement parts. I missed that on one channel some of the Mosfets were burned. Luckily i had some IRF640N laying around because i got them for cheap when the local conrad store closed.
The IRF640N are only slightly different, due to the N-suffix version using a newer manufacturing process/newer technology, but they pretty much seem to be drop in replacements as long as you don't mix and they are not used near their max. ratings [[[1]|https://forum.vcfed.org/index.php?threads/irf640-mosfet-and-irf640n-interchangeable.1226234/]] [[[2]|https://www.electronicspoint.com/forums/threads/irf640-vs-irf640n.272646/]].

semiconductors:

* 2SA1837 - replaceable with NTE2647
** https://pdf1.alldatasheet.com/datasheet-pdf/view/548281/TOSHIBA/2SA1837.html
** https://www.tme.eu/Document/fd9b9dc10947890cd2ff4b92959695e4/nte2647_48.pdf
* 2SC4793 - replaceable with NTE2648
** https://pdf1.alldatasheet.com/datasheet-pdf/view/549059/TOSHIBA/2SC4793.html
** https://www.tme.eu/Document/fd9b9dc10947890cd2ff4b92959695e4/nte2647_48.pdf
* 2SA1943-O - the O-suffix is very important
* 2SC5200-O - the O-suffix is very important
* IRF640 - replaceable with IRF640N
** [[old IRF640 datasheet from IRF|https://pdf1.alldatasheet.com/datasheet-pdf/view/68218/IRF/IRF640.html]]
** [[IRF640N datasheet from Infineon (IRF)|https://www.infineon.com/dgdl/Infineon-IRF640N-DataSheet-v01_01-EN.pdf?fileId=5546d462533600a4015355e7be9019ee]]
** Continuous Drain Current, Power Dissipation, Repetitive Avalanche Energy, Peak Diode Recovery and Themperature Range slightly higher
** Single Pulse Avalanche Energy lower


!! channel with charring

I started the repairs with the channel with the charred resistors. I had already desoldered the parts before. Because the PCB was charred and pretty much only carbon it had to be removed. It was not charred through and i didn't neet to repair traces, but i had to remove the charred fiberglass material with a small knive and a small grinding dremel bit. After removing all the black material i smothed everything with a fibreglass brush and cleaned it out with normal brushes. I got UV cured solder resist to coat and seal the fibreglass again.
Looks pretty good.

I fitted the replacement parts and soldered them. I soldered the resistors at a slight angle to maybe improve heat dissipation and move them a bit further from the pre-damaged PCB.
The caps i installed at slight angles away from the resistors so they hopefully won't get damaged again.

!! shorted channel


<<<
also je ein PNP und NPN leistungstranistor ist tot, komplett kurz... die vorverstärker und anderen leistungstrans scheinen noch ok zu sein, aber da ist es gut sicher zu gehen und die zu tauschen...
ansonsten habe ich auf dem kanal der durch war alle anderen silizium bauteile durchgetestet und die sind ok
<<<


i replaced the power transistors and preamps with new ones and measured everything thoroughly to check for other damaged components.

assembling the boards to the heatsink was a pain because there are power resistors on both sides of the heatsink and one has to somehow still get thermal paste in between.


!! 200Hz noise issue

<<<
die 200Hz sind bei dem Kanal wo ich nahe der Luftspule paar sachen getauscht hatte weil widerstände angeschmorrt waren... 
die luftspule ist ja am ausgang und da ist ein widerstand und ein Kondensator in serie zu 0V... so weit recht normal für Class AB denke ich
der Widerstand sind zwei parallel um die leistung zu erhöhen, beide waren stark angeschmorrt und haben den (folien) kondensator und die einen nahegelegenen elko angebrutzelt.
elkos vertragen hitze ja nicht gut und die marke ist eher noname, deswegen wollte ich es nicht drauf an kommen lassen, ich denke eher nicht das der neue von Nichicon das problem ist. aber der folienkondensator könnte vlt. damit zu tun haben? hab was davon gelesen das das RC-Glied am ausgang dazu führen kann das sich die endstufe aufschwingt wenn mit denen was nicht stimmt?
den folienkondensator habe ich getauscht weil der lack etwas angeschmorrt war, gegen einen panasonic mit selbem wert, ich weiß nur nicht ob die folien art die selbe ist.
die widerstände habe ich gegen 3W metall-oxid von Yageo getauscht, die alten sahen von der konstruktion unterm lack nach metal-oxid aus. ich hätte bei einem anderen händler noch welche mit 5W leistung bekommen, aus der selben Yageo serie, aber die hätten eh nur sehr knapp gepasst.
hab sogar das verschmorrte platinenmaterial sauber entfernt und mit neuem lötstoplack versiegelt

ich komme nur nicht drauf was die 200Hz erzeugt...

und ich kann keinen ruhestrom messen, was ich auch eigenartig finde.
die potentiometer um das einzustellen sind mit silikon festgeklebt, die haben sich seit der fabrik nicht bewegt und bei beiden kanälen messe ich nichts, weder bei dem der noch am originalsten ist (mit den 200Hz) noch bei dem mit komplett neuen Leistungstransistoren

hab mir heute eure Palladium 1200 nochmal angesehen, ich habe das 200Hz brummen durch vorsichtiges einstellen des arbeitpunktes in dem einen kanal weg bekommen.
aber ich kann keinen ruhestrom messen, dass verwirrt mich... ich habe aber einen test-header gefunden, den ich mir genauer ansehen werde wo der hin verbindet.
<<<

after repairing both channels, while testing, i had 200Hz noise on the channel with the charring.
i did not really figure out were it came from.
I suspected something with my replacement parts for the RC-filter at the output or the biasing of the amp. i think i adjusted TR6 a bit and that fixed it, but i'm unsure what i did, because i'm writing that down now a while later.

trimpot measurements:

TR4
102
A: 513-514
B: 508

TR5
102
A: 595-596
B: 645

TR6
101
A: 21,4
B: 17
(NTC trim)


! reverse engineering

see [[dap palladium 1200 class ab lern stuff]]

parts

* rectifier pcb
** 4x https://pdf1.alldatasheet.com/datasheet-pdf/view/111095/IRF/GBPC3504W.html
** 8x 10000uF 80V electrolytic caps 105°C

* channel pcb
** 2 x BYV72EW-200 https://pdf1.alldatasheet.com/datasheet-pdf/view/17522/PHILIPS/BYV72EW-200.html

i started reverse-engineering the amp channels, but later found a schematic: https://elektrotanya.com/dap_audio_palladium_p-1200_sch.pdf/download.html
* https://wiki.opensourceecology.de/TempCTRL
* [[diy weather station, air quality monitor, environmental data]]
* [[powerlogging / power meter / AC power analysis / energy monitor]]
Examples

* ~SpiegelMining https://media.ccc.de/v/33c3-7912-spiegelmining_reverse_engineering_von_spiegel-online
* ~BahnMining https://media.ccc.de/v/36c3-10652-bahnmining_-_punktlichkeit_ist_eine_zier

other links

* https://de.wikipedia.org/wiki/Data-Mining
* https://en.wikipedia.org/wiki/Data_mining
* https://de.wikipedia.org/wiki/Knowledge_Discovery_in_Databases
* https://en.wikipedia.org/wiki/Knowledge_extraction
* https://de.wikipedia.org/wiki/Data_Science
* https://en.wikipedia.org/wiki/Data_science

Data Mining is its own university course... i'll never be able to do that lol
* https://search.datasheetcatalog.net/
* https://www.alldatasheet.com/
* https://wiki.opensourceecology.de/DiVER/en
* https://en.wikipedia.org/wiki/Microgrid
* https://microgridknowledge.com/building-microgrids-current-pnnl/
* https://vbn.aau.dk/ws/files/308350938/DC_Microgrid_Protection_A_Comprehensive_Review.pdf
* https://hackaday.io/project/168223-dc-microgrid
* https://libre.solar/docs/nanogrid/
* https://learn.libre.solar/system/
* https://open-dc-grid.org/
* https://ieeexplore.ieee.org/document/7110892
* https://www.researchgate.net/project/The-DC-House-Project
* http://dchouse.calpoly.edu/ Goal: Develop a platform for residential and small scale DC electrical system using mainly renewable energy sources to provide access for electricity to people living in rural areas unreachable by the power grid. For further details, please see the DC House Project

connectors

* anderson sbe, powerpole?
* harting?
* euro DIN connector?
* [[EEVblog #49 - Decibels (dB's) for Engineers - A Tutorial|https://www.youtube.com/watch?v=mLMfUi2yVu8]]
* https://en.wikipedia.org/wiki/Decibel#Suffixes_and_reference_values
** https://en.wikipedia.org/wiki/DBFS
* https://de.wikipedia.org/wiki/Bel_(Einheit)
** https://de.wikipedia.org/wiki/DBFS
* https://www.learnabout-electronics.org/Amplifiers/amplifiers13.php
* [[DAS VERWIRRT EUCH NIE WIEDER - Die elektrischen Pegelangaben im Messfenster von REW erklärt - #REW|https://www.youtube.com/watch?v=k28diYoAp5c]]
* [[ Music: how loud is loud? |https://www.youtube.com/watch?v=zTEQmmG6TzE]]
* https://ea-dresden.site36.net/material/rund-um-die-demo/
* https://ea-dresden.site36.net/material/boese-post/
* https://ea-dresden.site36.net/material/und-da-kam-die-polizei/
* https://ea-dresden.site36.net/technik-1x1-fuer-aktionen-und-den-aktivistischen-alltag/
* https://ea-dresden.site36.net/material/spitzelei-und-datensammelwut/
ehemals aus fff wiki, wird bei gelegenheit mit neuem wissen überarbeitet

<<list-links "[all[current]tagging[]]">>
<<list-links "[all[current]tagging[]]">>

* http://sublinks.perkhorns.net/
* http://quarter-wave.com/Horns/BLH_Design_Article.pdf
* https://hackaday.com/2018/10/23/one-mans-quest-to-build-his-own-speakers/
* https://www.e-service-check.de/was-ist-die-dguv-v3-pruefung/
* https://publikationen.dguv.de/widgets/pdf/download/article/1052
* in germany it is required to regularly test electrical devices and to ensure their electrical safety
* VDE 07101
* https://github.com/devEmbedded/differential_probe
* https://hackaday.com/tag/differential-probe/
* https://hackaday.io/project/181065-modular-differential-probe
* https://github.com/paulvee/100MHz-Differential-Probe
* https://www.paulvdiyblogs.net/2017/10/differential-amplifier-probe-make-buy.html
* https://hackaday.io/project/169390-a-10x-100mhz-differential-probe/details
* https://github.com/wingel/diff-probe
* https://hackaday.com/2016/03/31/diy-active-sub-ghz-differential-scope-probe/

* [[EEVblog 1415 - Reverse Engineering the DP10007 Differential Probe|https://www.youtube.com/watch?v=GOk1BYKSsOI]]
** https://www.eevblog.com/product/hvp70/
** https://www.eevblog.com/2021/08/30/eevblog-1415-reverse-engineering-the-dp10007-differential-probe/
* https://www.tiepie.com/en/articles/differential-measurements
* https://www.tiepie.com/en/articles/measuring-a-power-outlet
* [[EEVblog #932 - How Does A HV Differential Probe Work?|https://www.youtube.com/watch?v=GOlgaEK2Hsk]]
* https://forum.mosfetkiller.de/viewtopic.php?t=63623

products

* https://www.micsig.com/Differential%20Probe04/
* https://www.micsig.com/Differential%20Probe01/ - new
* bk precision
* https://de.farnell.com/w/c/messtechnik/messleitungen-tastkopfe/spannungstastkopfe-frequenztastkopfe-fur-oszilloskope/prl/ergebnisse?tastkopf-funktion=differentiell&sort=P_PRICE
* https://www.picotech.com/accessories/active-differential-high-voltage
* https://digilent.com/reference/test-and-measurement/analog-discovery-2/start
* https://hackaday.com/2016/12/28/review-digilent-analog-discovery-2/
** https://learn.digilentinc.com/list?tag=analog-discovery
* [[Analog Discovery 2 Quick-Start Guide|https://www.youtube.com/watch?v=HUAy0J3XqaU&list=PLSTiCUiN_BoLtf_bWtNzhb3VUP-KDvv91]]
* https://www.arrow.com/en/research-and-events/articles/digilent-analog-discovery-2
* https://digilent.com/reference/test-and-measurement/analog-discovery-2/specifications
* https://digilent.com/reference/test-and-measurement/analog-discovery-2/reference-manual
* https://digilent.com/reference/test-and-measurement/analog-discovery-2/hardware-design-guide
* https://digilent.com/reference/software/waveforms/waveforms-3/start
* https://digilent.com/reference/test-and-measurement/analog-discovery-3/start

Addons

* https://digilent.com/reference/add-ons/start (not all addons listed and some are not for AD2)
* Audio Adapter
** 2x 3,5mm Jack connectors instead of BNC for the oscilloscope (2x mono or 1x stereo)
** https://digilent.com/reference/add-ons/audio-adapter/start
* Impedance Analyzer
** https://digilent.com/reference/add-ons/impedance-analyzer/start
** https://digilent.com/reference/test-and-measurement/guides/waveforms-impedance-analyzer?redirect=1
** https://digilent.com/reference/add-ons/impedance-analyzer/getting-started-guide
** https://digilent.com/reference/add-ons/impedance-analyzer/diy-speaker
** https://digilent.com/reference/add-ons/impedance-analyzer/reference-manual
* BNC Adapter
** https://digilent.com/reference/test-and-measurement/bnc-adapter-board/start

my usecases

* audio analyzer
** [[TheStuffMade Audio Analyzer Suite|https://www.youtube.com/watch?v=7yXUbU5bSGw&list=PLj1iPGXgbNf2otUxBjLh93bI31FuradPS]]
** https://www.diyaudio.com/community/threads/analog-discovery-audio-analyzer-suite-video.376466/
** [[Audio Analyzer Suite / Analog Discovery 2 Review and Demo|https://www.youtube.com/watch?v=vZdL6jmCJvE]]
** [[ Audio Analyzer & Dummy Load Using Analog Discovery 2 - 2019 Version |https://www.youtube.com/watch?v=1rOvdsxQVTY]]
*** [[ SBS Update - Audio Analyzer Suite - Analog Discovery 2 Mystery Solved!!! |https://www.youtube.com/watch?v=segL---cj9s]]
* speaker impedance analyzer
** impedance analyzer addon
** [[ Impedance Analyzer v1.4.0.0 Available for Download |https://www.youtube.com/watch?v=xRgviNyggNw]]
* upgrades for [[balanced signals / symmetrische signale]]?

stuff

* [[Analog discovery Experiments - tomtektest|https://www.youtube.com/watch?v=zr_k7HGLpPc&list=PL2u6aYAXZ0Z_Jwsr22nDtI3XA18DJcsIh]]
* [[Analog Discovery 2 Spectrum Analyzer Frequency Extension - tomtektest|https://www.youtube.com/watch?v=oz8d1r0cxu0&list=PL2u6aYAXZ0Z_51pfFgMaKcTxhHuj10ZgT]]
* [[Curve & Signature Tracers - tomtektest|https://www.youtube.com/watch?v=ri1X2vl0h4I&list=PL2u6aYAXZ0Z-_VB8-WULtLuFJQfAEY0le]]
* [[Art of Electronics Lab - tomtektest|https://www.youtube.com/watch?v=gmI22zJQZ5g&list=PL2u6aYAXZ0Z_VLDK7zHTmknZFUxJ6CW--]]
* [[TTT117 Analog Discovery THD v Rigol, Siglent |https://www.youtube.com/watch?v=dlF7UVp65WY]]
* [[Analog Discovery 2 - tomtektest|https://www.youtube.com/watch?v=CZiOuGBzA_0&list=PL2u6aYAXZ0Z8ECUU8I0jCohN_oGdC-L57]]
* [[Analog Discovery Projects - TheStuffMade|https://www.youtube.com/watch?v=cbXGzz3PC3Y&list=PLj1iPGXgbNf11SL1XVvDII3L6C4ZWhbyp
* http://designideas.cocolog-nifty.com/blog/analog_discovery/index.html
** http://designideas.cocolog-nifty.com/blog/zigbee/index.html
** http://designideas.cocolog-nifty.com/blog/122low_impedance_analyzer_for_analog_discovery/index.html
** http://designideas.cocolog-nifty.com/blog/2018/01/we-love-balan-1.html ?
* [[usb galvanic isolation]]
* https://ravenattic.com/2020/05/31/an-audio-frequency-response-tester/
* https://jamnopapa.blogspot.com/search/label/ANALOG%20DISCOVERY
* https://github.com/search?q=analog+discovery&type=Repositories

buying

* i compared different sellers and found digikey to be the cheapest overall and to have most of the addons, but it might be different for you
* https://octopart.com/search?q=Digilent+Analog+Discovery&currency=EUR&specs=0&sort=median_price_1000&sort-dir=asc&start=10




!! ~WaveForms

* Windows 64-bit:		https://mautic.digilentinc.com/asset/110:waveforms-windows-64-bit-download
* Windows 32-bit:		https://mautic.digilentinc.com/asset/108:waveforms-windows-32-bit-download
* Mac OS X:		https://mautic.digilentinc.com/asset/104:waveforms-mac-os-x-download
* Linux 64-bit .rpm:	https://mautic.digilentinc.com/asset/111:waveforms-linux-64-bit-rpm-download
* Linux 64-bit .deb:      https://mautic.digilentinc.com/asset/105:waveforms-linux-64-bit-deb-download
* Linux 32-bit .rpm:	https://mautic.digilentinc.com/asset/112:waveforms-linux-32-bit-rpm-download
* Linux 32-bit .deb:	https://mautic.digilentinc.com/asset/107:waveforms-linux-32-bit-deb-download
* Linux ARM-64-bit .rpm:	https://mautic.digilentinc.com/asset/113:waveforms-arm-64-bit-rpm-download
* Linux ARM-64-bit .deb:	https://mautic.digilentinc.com/asset/114:waveforms-arm-64-bit-deb-download
* Linux ARM-32-bit .rpm:	https://mautic.digilentinc.com/asset/109:waveforms-arm-32-bit-rpm-download
* Linux ARM-32-bit .deb:	https://mautic.digilentinc.com/asset/106:waveforms-arm-32-bit-deb-download
* ARM-32-bit .deb (Linux Mode):	https://mautic.digilentinc.com/asset/120:waveforms-adp3x50-arm-32-bit-deb-download



Adept2
======

* Linux 32-bit .deb:	https://mautic.digilentinc.com/asset/36:adept-download-linux-32-bit-deb-runtime
* Linux 32-bit .rpm:	https://mautic.digilentinc.com/asset/37:adept-download-linux-32-bit-rpm-runtime
* Linux 32-bit .tar.gz:	https://mautic.digilentinc.com/asset/38:adept-download-linux-32-bit-runtime-zip
* Linux 64-bit .deb:	https://mautic.digilentinc.com/asset/39:adept-download-linux-64-bit-deb-runtime
* Linux 64-bit .rpm:	https://mautic.digilentinc.com/asset/40:adept-download-linux-64-bit-rpm-runtime
* Linux 64-bit .tar.gz:	https://mautic.digilentinc.com/asset/41:adept-download-linux-64-bit-runtime-zip
* Linux ARM-64-bit .deb:	https://mautic.digilentinc.com/asset/115:adept-download-runtime-arm-64-bit-deb
* Linux ARM-64-bit .rpm:	https://mautic.digilentinc.com/asset/116:adept-download-runtime-arm-64-bit-rpm
* Linux ARM-Raspberry Pi:	https://mautic.digilentinc.com/asset/42:adept-download-runtime-arm-rasperry-pi
                
* small microcontroller-boards
* usb connector for programming or as USB device
* several GPIOs
* attiny85
* https://www.reichelt.de/digispark-mini-attiny85-usb-mit-stiftleiste-digispark-mini-p192128.html
* http://digistump.com/wiki/digispark

setup

* https://github.com/digistump/DigistumpArduino/
* http://digistump.com/wiki/digispark/tutorials/connecting
* https://forensicswiki.xyz/page/Main_Page
* https://media.ccc.de/search/?q=forensik
* https://de.wikipedia.org/wiki/IT-Forensik
* https://www.computer-forensik.org/tools/
* https://www.cleverfiles.com/howto/de/computer-forensic.html
* [[How NOT to Sample Audio! - Computerphile|https://www.youtube.com/watch?v=VQOdmckqNro]]
* [[How Digital Audio Works - Computerphile|https://www.youtube.com/watch?v=1RIA9U5oXro]]
* [[Digital Audio: The Basics|https://www.youtube.com/watch?v=9z5HOZ4C1KY]]
* [[Digital Audio: The Line Between Audiophiles and Audiofools|https://www.youtube.com/watch?v=IiZqYnd5g8M]]
* https://sound-au.com/p-cat.htm#dig
* https://hackaday.com/category/digital-audio-hacks/
* [[Digital vs Analog Audio - X32/M32 AES50, Routing Latency (Public)|https://www.youtube.com/watch?v=hSYXAV-rpOg]]
* [[ Understanding Jitter in Digital Audio: Measurements and Listening Tests |https://www.youtube.com/watch?v=TT9JL2yaIOA]]
* [[ Do USB Filters Make DACs Sound Better? |https://www.youtube.com/watch?v=RulAcLrnPkA]]

subarticles:

<<list-links "[all[current]tagging[]]">>
* AES-3 (AES/EBU) - https://de.wikipedia.org/wiki/AES/EBU
* https://de.wikipedia.org/wiki/TOSLINK
* https://de.wikipedia.org/wiki/Sony/Philips_Digital_Interface
* see also [[I²S]]
* needs receiver / DAC chips to be converted back to analog
* are there chips supporting both analog singal or digital AES/EBU input on the same input?
* https://www.learnabout-electronics.org/Digital/dig10.php
ehemals fff wiki - https://wiki.fridaysforfuture.is/wiki/Digitale_Nachhaltigkeit

<<<
Dieser Artikel soll aufzeigen wie man auch digital nachhaltig sein kann und Möglichkeiten auflisten.

Wichtig für digitale Nachhaltigkeit ist Free/Libre, Open Source Software (FLOSS; free as in freedom) und Achtung der Privatsphäre und Datensicherheit.

Siehe auch:
* [[Wikipedia:de:Digitale Nachhaltigkeit]] (sehr lesenswert)
* https://www.freie-messenger.de/einfuehrung/#digitale-nachhaltigkeit

[[Kategorie:Technik-IT Support]][[Kategorie:Aktionen & Aktivismus]][[Kategorie:Wissen & Diskurs]]

<<<
* https://en.wikipedia.org/wiki/Diode

zener

* [[EEVblog #908 - Zener Diodes|https://www.youtube.com/watch?v=O0ifJ4oVdG4]]
* https://www.digikey.de/en/maker/blogs/zener-diode-basic-operation-and-applications
* https://en.wikipedia.org/wiki/Zener_diode

schottky

* https://de.wikipedia.org/wiki/Schottky-Diode
* https://en.wikipedia.org/wiki/Schottky_diode
* https://en.wikipedia.org/wiki/Category:Disassemblers
* https://alternativeto.net/software/ida/
* https://en.wikipedia.org/wiki/Interactive_Disassembler
* https://en.wikipedia.org/wiki/Radare2
* https://en.wikipedia.org/wiki/Ghidra
* https://en.wikipedia.org/wiki/Decompiler
* https://en.wikipedia.org/wiki/Disassembler
* https://en.wikipedia.org/wiki/Category:Disassemblers
* https://en.wikipedia.org/wiki/Objdump


* https://en.wikipedia.org/wiki/Category:Java_decompilers
** https://en.wikipedia.org/wiki/JEB_decompiler
** https://en.wikipedia.org/wiki/JD_Decompiler
* Radare2
** https://www.radare.org/r/
** https://en.wikipedia.org/wiki/Radare2
* http://boomerang.sourceforge.net/
* IDA(Pro) - proprietary
** https://hex-rays.com/ida-pro/
** https://de.wikipedia.org/wiki/Interactive_Disassembler
** https://en.wikipedia.org/wiki/Interactive_Disassembler
* Ghidra
** https://www.ghidra-sre.org/
** https://en.wikipedia.org/wiki/Ghidra
** https://de.wikipedia.org/wiki/Ghidra
** https://github.com/NationalSecurityAgency/ghidra
* https://onlinedisassembler.com/odaweb/
see also [[PC troubleshooting tools]] and maybe [[digital / computer forensic]]

Tools:

* open-source (mostly linux)
** dd
*** if you're not experienced with dd it's very easy to fuck thins up, use gdiskdump which provides a GUI
**** https://helpdeskgeek.com/linux-tips/use-the-linux-%E2%80%98dd%E2%80%99-command-with-a-simple-gui/
**** https://ostechnix.com/kindd-a-graphical-frontend-to-dd-command/
*** https://wiki.ubuntuusers.de/dd/
*** https://unix.stackexchange.com/questions/180330/resuming-a-dd-of-an-entire-disk
** ddrescue (dd_rescue?)
*** https://wiki.ubuntuusers.de/gddrescue/
*** https://de.wikipedia.org/wiki/Ddrescue
*** https://www.030-datenrettung.de/datenrettung-linux-ddrescue-anleitung
*** https://www.gnu.org/software/ddrescue/
*** speed
**** https://superuser.com/questions/413650/is-there-any-way-to-speed-up-ddrescue
**** https://unix.stackexchange.com/questions/366901/faster-disk-recovery-ddrescue-running-slow
* https://www.pcwelt.de/ratgeber/dd-und-dd-rescue-Datenrettung-fuer-Windows-und-Linux-171679.html
** ~PhotoRec
*** https://www.cgsecurity.org/wiki/PhotoRec
*** https://de.wikipedia.org/wiki/PhotoRec
** Testdisk
*** https://www.cgsecurity.org/wiki/TestDisk
*** https://de.wikipedia.org/wiki/TestDisk
** GParted
** fsck
** linux live ISOs (for CD/USB)
*** http://www.datenrettung-etc.de/datenrettung-live-cd.htm (example for possible software)
*** see [[PC troubleshooting tools]]
*** https://distrowatch.com/search.php?category=Data+Rescue
** fdisk
*** https://de.wikipedia.org/wiki/Fdisk
*** https://wiki.ubuntuusers.de/fdisk/
** Fight Flash Fraud
*** https://fight-flash-fraud.readthedocs.io/en/stable/index.html
*** https://github.com/AltraMayor/f3

* proprietary/closed-source
** [[HDDSuperClone|http://www.sdcomputingservice.com/hddsuperclone]]
** diskpart (windows tool)
* https://www.heise.de/ct/artikel/c-t-Systeminfo-2859100.html
** https://www.heise.de/download/product/h2testw-50539

infos

* https://forensicswiki.xyz/page/Main_Page
* https://www.lifewire.com/what-are-read-and-write-speeds-2640236
* https://linuxhandbook.com/linux-list-disks/
* https://www.cyberciti.biz/faq/linux-getting-scsi-ide-harddisk-information/
* https://www.tecmint.com/check-linux-hard-disk-bad-sectors-bad-blocks/
* SMART
* https://media.ccc.de/search/?q=datenrettung
* https://www.tecmint.com/manage-ext2-ext3-and-ext4-health-in-linux/
* https://www.dedoimedo.com/computers/linux-data-recovery.html
* https://www.linux.com/training-tutorials/get-your-data-back-linux-based-data-recovery-tools/
* https://www.linux.com/news/recovering-linux-files-and-filesystems/
* https://www.ubuntupit.com/top-15-linux-data-recovery-tools-the-professionals-choice/
* https://www.techrepublic.com/blog/10-things/10-linux-rescue-tools-for-recovering-linux-windows-or-mac-machines/
* https://www.lifewire.com/free-data-recovery-software-tools-2622893
* https://itsfoss.com/recover-deleted-files-linux/
* https://www.fossmint.com/linux-rescue-recovery-tools/
* https://www.maketecheasier.com/recover-data-linux-tools/
* https://fossbytes.com/top-best-free-data-recovery-software-2016/
* https://www.hddzone.com/
* [[Connecting an LCD to our computer — 6502 part 4|https://www.youtube.com/watch?v=FY3zTUaykVo]]
* types
** LCD
** VFD
** OLED
* https://hackaday.com/blog/?s=display
* https://hackaday.com/2021/12/11/getting-familiar-with-round-displays/
* https://hackaday.com/2022/04/19/oled-display-kicks-knob-up-several-accurate-notches/
* https://hackaday.com/2022/05/24/character-vfd-becomes-spectrum-analyzer/
* [[ Making OLED Displays |https://www.youtube.com/watch?v=qg8pMUd-tSk]]
* [[ Build an electroluminescent glass panel display -- an Apollo DSKY |https://www.youtube.com/watch?v=Z2o_Sp2-aBo]]
Open hardware/DIY

* https://www.nutsvolts.com/magazine/article/build-a-basic-audio-distortion-analyzer
* https://www.reddit.com/r/diyaudio/comments/3wd5s6/diy_open_source_distortion_analyser_programmer/
* https://www.diyaudio.com/community/threads/diy-distortion-analyzer-analysis.1565/


stuff

* https://eevblog.com/forum/testgear/distortion-analyzer-suggestions/


proprietary:

* https://www.reddit.com/r/diyaudio/comments/3wd5s6/diy_open_source_distortion_analyser_programmer/
* https://hackaday.io/project/176072-diy-stream-deck-with-raspberry-pi-pideck
* https://stream-pi.com/
** https://github.com/stream-pi
* https://www.youtube.com/watch?v=obWFprWTRSs
* https://www.youtube.com/watch?v=ELgtjeJyFw8
* https://www.youtube.com/channel/UCSS99JShi8DD3sHgnB4FaCg
* https://www.youtube.com/watch?v=P8BWQBP4Vhk
* http://www.devtome.com/an_open_source_hi-fi_amplifier
* [[HiFi Elektronik Selbstbauprojekte: Do it yourself (DIY) Tipps|http://www.hifi-forum.de/viewforum-103.html]]

class d

* just use the [[cheap "chinese" amplifier boards]] or design your own.
* [[YT: IRS2092AMP-500W Class D Amplifier: The Real Watts|https://www.youtube.com/watch?v=jLkWVuYESss]]
* [[YT: How Class D Amplifiers Work part 1|https://www.youtube.com/watch?v=GCA3t67yOLc]]
* [[YT: DIY Class D Audio Amplifier|https://www.youtube.com/watch?v=3dQjIeYoIdM]]
* [[YT: Class D Amplifier Tutorial!|https://www.youtube.com/watch?v=O1UagNkcxi4]]
* https://www.allaboutcircuits.com/projects/how-to-build-a-class-d-power-amplifier/
* https://www.circuitstoday.com/class-d-power-amplifiers
* https://www.digikey.com/en/articles/simplify-portable-low-power-audio-circuit-design-class-d-amplifiers
* https://www.analog.com/en/analog-dialogue/articles/class-d-audio-amplifiers.html
* https://en.wikipedia.org/wiki/Class-D_amplifier
* https://spectrum.ieee.org/consumer-electronics/audiovideo/build-your-own-professionalgrade-audio-amp-on-the-sort-of-cheap
* https://www.cybernet.co.jp/beetech/product/designkit/pdf/Class_D/class_d_audio_amplifier.pdf
* using cheap "china" amplifiers with class d chips
** using them bridged or in parallel
** big step up converter as DC-powersupply
** big switchmode powersupply (schaltnetzteil) like for LEDs as AC-powersupply
* [[YT: How to make Class D sound better|https://www.youtube.com/watch?v=ixcgl3_Wwi4]]
* [[Class D Audio Amplifier --The design of a live audio Class D audio amplifier with greaterthan 90%efficiency and less than 1% distortion.|https://web.wpi.edu/Pubs/E-project/Available/E-project-041808-145643/unrestricted/report.pdf]]
* [[Class D Audio Amplifier Design Tutorial - IRF|http://www.irf.com/product-info/audio/classdtutorial.pdf]]
** [[Class D Amplifier Design Basics II - IRF|http://www.irf.com/product-info/audio/classdtutorial2.pdf]]
* [[Class D Audio Amplifiers - Theory and Design|https://sound-au.com/articles/pwm.htm]]
* http://hephaestusaudio.com/media/2009/12/How-to-Design-a-Class-D-Amplifier.pdf
* Reference designs
** [[Class D Audio Amplifier Reference Design - NXP|https://www.nxp.com/design/designs/class-d-audio-amplifier-reference-design:CLASS-D-AUDIO-AMPLIFIER]]
** https://www.ti.com/audio-ic/amplifiers/speaker-amplifiers/reference-designs.html#search?famid=3419
* https://www.diyclassd.com/
* http://exertion.pbworks.com/w/page/12085514/HBridge

Class A

* [[Building the simplest, best sounding, yet most inefficient Audio Amp! - Class A Audio Amp Tutorial|https://www.youtube.com/watch?v=7Pv-j_R3YP4]]
* https://www.circuitlib.com/index.php/tutorials/product/39-how-to-build-an-audio-mixer
* https://www.instructables.com/id/Making-an-Audio-Mixer/
* https://www.instructables.com/id/3-CHANNEL-AUDIO-MIXER-Integrated-With-an-FM-Radio-/
* https://www.instructables.com/id/Passive-Audio-Mixer-w-Channel-Volume-Control/
* https://www.instructables.com/id/Altoids-Tin-18-Stereo-Mixer/
* https://www.instructables.com/id/Silent-Rehearsal-Band-Matrix-Mixer/
* https://www.instructables.com/id/Passive-3-input-Stereo-Mixer/
* https://www.instructables.com/id/DIY-simple-audio-mixer/
* https://www.instructables.com/id/Altoids-tin-audio-mixer/
* https://www.instructables.com/id/DIY-Passive-Audio-Mixer/
* https://www.instructables.com/id/Active-Sound-Mixer/
* https://www.instructables.com/id/Audio-mixer/
* https://groupdiy.com/index.php?topic=62980.0
* https://makezine.com/2009/06/09/how-to-5-channel-sound-mixing-board/
* https://homerecording.com/bbs/general-discussions/studio-building-and-acoustic-treatment/diy-analog-mixing-console-180912/
* https://sound-au.com/project30a.htm
* https://www.gearslutz.com/board/so-much-gear-so-little-time/186712-building-your-own-mixing-console.html
* https://finegear.net/mixerblocks-2/
* https://www.engineersgarage.com/circuit_design/diy-circuit-design-audio-mixer/
* https://www.diystompboxes.com/smfforum/index.php?topic=104384.0
* https://www.reddit.com/r/diysound/comments/dai99l/diy_dual_audio_mixer_passive_or_active/
* [[Moritz Klein: DIY Mixer series|https://www.youtube.com/playlist?list=PLHeL0JWdJLvQUWK_poeQVAd3mvSTiE0uV]]
* https://hackaday.com/2023/02/15/how-to-build-jennys-budget-mixing-desk/
* https://www.youtube.com/watch?v=YCIcnFuRK7w
* some managed switch with QoS and other features for AES67, Dante, AVB or so (audio over IP in general)
* i'm mainly focused on open source protocols
* https://www.youtube.com/results?search_query=aes67
hooks - not easy to find

* carefully bending small angle plates or similar from the hardware store
* https://www.ortlieb.com/de_de/produkte/accessoires/ersatzteile ortlieb sells spare parts but they are expensive
* AES50 (ethernet pysical only) and/or AES67 (Ethernet & IP)
* with USB host capability? as XR18 interface?
* XR18 Ultranet?
* only some rate conversion, not DSP functions at first, basically just pushing PCM (I2S/AES3) streams arround
* maybe programmable preamps?
* https://upload.wikimedia.org/wikipedia/commons/archive/a/a2/20071013114114%21Bicycle-trailer-for-outdoor-trekking.jpg
** https://web.archive.org/web/20160126032556/http://www.bike-buggy.com/ger/
* https://de.wikipedia.org/wiki/Fahrradanh%C3%A4nger
* https://konglomerat.org/projekte/velozack.html
** https://konglomerat.org/_Resources/Persistent/57df904ee9f2a48b55d4e1aa805423a777cf675d/velozack_web%20%28BG%29-1200x800.jpg
* https://www.youtube.com/watch?v=AHdn8-ePKgM&list=PLsiRYfPtL8E-MCIBkW__UQq_s5ir0u4Li
* https://charrette.bike/
** https://hackaday.com/2023/01/02/a-bicycle-trailer-fit-for-heavy-haulage/
** [[google translate|https://charrette-bike.translate.goog/?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp]]
** carla-cargo-like design, completely open source (cern ohl-w v2 bzw. cc-by-sa)

stuff

* https://www.bosch-diy.com/de/de/all-about-diy/fahrradanhaenger-selber-bauen
* https://www.pedelecforum.de/forum/index.php?threads/fahrradanhaenger-wie-lang-sollte-der-sein.77281/
* https://mirkojavurek.wordpress.com/2015/05/31/fahrrad-lastenhanger-aus-holz/
* https://www.1-2-do.com/projekt/fahrrad-anhaenger/bauanleitung-selber-bauen/4002868
* https://www.spiegel.de/auto/aktuell/fahrradanhaenger-statt-lastenrad-der-hamburger-supertrailer-a-1206082.html
* http://fuzzcraft.com/flightcasediy.html
* https://www.instructables.com/Making-of-a-DIY-Flightcase/
* https://www.adamhall.com/shop/us-en/landingpage/flitecad/sArticle/
* https://grabcad.com/uasia.pipkin-2/models
* https://flightcase-teile.de/
using an [[SBC|single board computer (SBC)]], see [[backup]]

* OS: ~OpenMediaVault? (~FreeNAS and ZFS need way more RAM)
** ~TrueNAS?
** https://docs.nextcloud.com/server/16/admin_manual/installation/system_requirements.html
* SBC: Rock64 Pro? Odroid H1/H2?

software

* https://ownyourbits.com/nextcloudpi/
* freenas - https://www.freenas.org/
** https://de.wikipedia.org/wiki/FreeNAS
* https://www.openmediavault.org/
** https://de.wikipedia.org/wiki/OpenMediaVault
!! Case

!! Controller

see [[DMX]], [[microcontroller]]

WLED?

!! Driver

Constant Current

see [[LED Driver (constant current)]]

see [[LED]]

see [[transistors]]

there are cheap mosfet driver boards available on aliexpress and the likes, some even come with rgb led controllers

!! power supply / battery


!! Stuff

* [[EEVblog #928 - Jaycar DMX RGB LED Lights Teardown|https://www.youtube.com/watch?v=QqPJJLkm46U]]
* https://bikerglen.com/blog/homebrew-rgb-led-light/
* https://www.epanorama.net/newepa/2019/10/21/led-dmx-512-lamp-teardown/
* https://www.epanorama.net/newepa/2019/10/16/dmx-512-led-light-teardown/
* cheap LED pars can be bought from china for around 25-35€
* https://www.thomann.de/de/onlineexpert_topic_par_scheinwerfer.html
* https://gvmled.com/rgb-video-light/
* https://www.reddit.com/r/FastLED/comments/yw6xto/diy_rgbw_spotflood_light/
* https://www.reddit.com/r/WLED/comments/yw700i/diy_rgbw_spotflood_light/
* 3w leds
** https://cdn-shop.adafruit.com/product-files/2524/FD-9RGB-Y2.pdf
** https://www.adafruit.com/product/2530
** https://www.adafruit.com/product/5162
** https://www.reddit.com/r/WLED/comments/oiq8uc/best_led_floodlight_solution_for_trees/
* https://hackaday.com/2021/02/02/dvd-optics-power-this-scanning-laser-microscope/
* https://hackaday.com/?s=microscope
* https://hackaday.com/?s=scanning+microscope
* [[DIY Scanning Electron Microscope - Overview|https://www.youtube.com/watch?v=VdjYVF4a6iU]]
* [[Measuring Microns with a Pinhole (and laser|https://www.youtube.com/watch?v=9TYlQ4urcg8]]
* [[I made a scanning laser microscope|https://www.youtube.com/watch?v=9TYlQ4urcg8]]
* https://openflexure.org/
* https://wiki.opensourceecology.de/Uniscope
* https://hackaday.io/project/180044-stereo-ninja
* https://hackaday.com/2023/09/19/printed-upgrades-improve-cheap-digital-microscope/
* https://hackaday.com/2017/11/14/if-you-want-to-spend-on-a-microscope/


stuff

* https://www.nature.com/articles/d41586-023-03064-9
!! "classic", analog type

* off the shelf quality potentiometer
* miniature timing belt and gears
* DC motor
* touch input using additional wire?

!! digital, encoder kind

* [[bldc motor (as) encoder]] as underlying concept
* small bldc motor
** problem: needs (hall) sensors for feedback
* small timing belt and pulleys
* maybe could sense touch by sensing small movements
* or touch input could be done using a flexible wire as connection
* could provide force feedback
* linear glide bearings for smoth operation like in good quality pots
** "3mm lineare welle"
* timing belt as optical encoder?

* capacitive
** https://robocombo.blogspot.com/2010/12/using-tis-launchpad-to-interface.html
** https://www.posic.com/EN
** https://www.researchgate.net/publication/273394227_A_Capacitive_Rotary_Encoder_Based_on_Quadrature_Modulation_and_Demodulation
** https://blog.honzamrazek.cz/2017/07/rotational-encoders-on-the-cheap-the-capacitive-way/
*** https://hackaday.com/2017/11/17/diy-capacitive-rotational-encoder-on-the-cheap-with-fr4/
** https://ietresearch.onlinelibrary.wiley.com/doi/10.1049/iet-smt.2017.0376
** https://www.mdpi.com/1424-8220/19/14/3116/htm
** https://www.semanticscholar.org/paper/Prototyping-of-flexible-capacitive-encoder-with-Kimura-Gondo/a7879da5bacdac2d835aaa91829e5372b2fdc223
** https://www.semanticscholar.org/paper/Capacitive-Type-Flexible-Linear-Encoder-With-Slider-Kimura-Gondo/e452964477592e0b4c5d51b620d7d2e6c475db49
** https://www.ien.eu/article/linear-encoder-kit/
** https://www.yuriystoys.com/2013/07/MSP430-mixed-scale-dro.html
** https://blog.mbedded.ninja/electronics/circuit-design/capacitive-sensing/
*** https://www.iceinspace.com.au/forum/showthread.php?t=80356
** https://www.mikrocontroller.net/topic/462864
** https://www.mdpi.com/2076-3417/8/12/2419
** https://www.researchgate.net/publication/322479692_A_new_capacitive_rotary_encoder_based_on_analog_synchronous_demodulation

* optical
** https://www.yuriystoys.com/2014/07/diy-tachometer-for-your-mill-or-lathe.html
** https://benkrasnow.blogspot.com/2010/02/linear-position-tracking-with.html
** https://www.youtube.com/watch?v=BwOMmHc1kI4
** https://hackaday.com/2009/11/12/linear-optical-encoder/

* magnetic
** https://hackaday.com/2023/01/09/clever-mechanism-makes-a-linear-control-from-a-rotary-hall-sensor/


stuff

* https://en.wikipedia.org/wiki/Potentiometer#Contactless_potentiometer
* https://www.usdigital.com/blog/difference-between-optical-magnetic-and-capacitive-encoders
Steps:

# [[design the circuit and layout of the board|pcb design]]
# make/order the board
# solder the components

ways to make your own boards:

* etching the board with chemicals
* CNC/routing
* design the board and order pretty professional PCBs from companies
*

ordering boards (i don't endorse any of these services, i just list some, search for yourself):

* https://pcbshopper.com/
* JLCPCB
* https://www.pcbway.com/
* https://oshpark.com/
* https://www.seeedstudio.com/fusion_pcb.html
* https://aisler.net/
* https://www.mikrocontroller.net/articles/Platinenhersteller

guides:

* [[From Idea to Schematic to PCB - How to do it easily!|https://www.youtube.com/watch?v=35YuILUlfGs]]
* [[EEVblog #1129 - Creating a Nice Readable Schematic|https://www.youtube.com/watch?v=R_Ud-FxUw0g]]
* [[EEVblog #1327 - 3 Ways to FAIL at PCB Manufacture|https://www.youtube.com/watch?v=2AcpRCNhbsw]]
* [[PCB Design - Getting Started & Design Rules|https://www.youtube.com/watch?v=qCAUI4nm5_I]]
* [[Design your own Circuit Boards using Kicad Part 1 (FREE software)|https://www.youtube.com/watch?v=sEGyNfBuPig]]
* https://www.youtube.com/watch?v=qK8Iv3YeSzM
* https://www.youtube.com/watch?v=PfGJDiz7-TQ

stuff

* https://www.4pcb.com/trace-width-calculator.html
* https://www.4pcb.com/trace-width-calculator.html
* panelizing?
* [[EEVblog #1259 - PCB Manufacturing Options EXPLAINED|https://www.youtube.com/watch?v=mT2Vp3HcIP4]]
* [[EEVblog #939 - How Is A PCB Manufactured?|https://www.youtube.com/watch?v=rEB0pl8a5C0]]
* [[EEVblog #1323 - PCB Layout Review & Analysis|https://www.youtube.com/watch?v=xhRhsCVF8mE]]
* [[In einer riesigen Leiterplattenfabrik - in China|https://www.youtube.com/watch?v=ljOoGyCso8s]]
* [[In einer Leiterplattenlötfabrik - in China|https://www.youtube.com/watch?v=24ehoo6RX8w]]
* https://wiki.fablab-muenchen.de/display/L4DIY/LASER4DIY
* [[ Make A Circuit Board, At Home! |https://www.youtube.com/watch?v=1Y6mNqMU9z8]]

Soldering:

* [[How to do SMD Reflow Soldering properly! -- Hot Air VS Sand VS Reflow Oven|https://www.youtube.com/watch?v=DYrucIWig24]]
* [[ Platinen-Klein(st)serienproduktion: Löten von Commodore 64-Hardware im Lötbad #C64 #FaszinationC64 |https://www.youtube.com/watch?v=-8WtqGi_7lE]]
* [[DIY Radio Telescope Version 2: Wifi vision - Part 1|https://www.youtube.com/watch?v=o6WHhqDHSQ4]]
** [[Building a Camera That Can See Wifi - Part 3 SUCCESS!|https://www.youtube.com/watch?v=g3LT_b6K0Mc]]
* [[Tracking Satellites in Orbit - Part 1|https://www.youtube.com/watch?v=NsY76tI2Vus]]
* [[Building An Autonomous Satellite Tracker For Ham Radio, Part 1|https://www.youtube.com/watch?v=KiPubPpx9hQ]]
* [[DIY RADIOASTRONOMY|https://www.youtube.com/watch?v=6wBSBNDKOlc]]
* [[Satellites You Can Use For FREE! #teamtrees|https://www.youtube.com/watch?v=tbXBEd7PL9A]]
* [[Building a Giant 2m Corner Reflector Antenna For Less than $200 (For Goes-16, Pulsars and More!)|https://www.youtube.com/watch?v=tjvOyUsoh1c]]
* [[How to Pull Images from Satellites in Orbit (NOAA 15,18,19 and METEOR M2)|https://www.youtube.com/watch?v=cjClTnZ4Xh4]]
* [[How to Build a Radio Telescope (See Satellites 35,000km Away!)|https://www.youtube.com/watch?v=aeah3fFYlnA]]
* https://www.youtube.com/watch?v=Me3-dcMfEtM
* https://www.youtube.com/watch?v=qnP8-wJVAlI
* https://www.youtube.com/watch?v=f1rTZqJggSw
* https://www.youtube.com/watch?v=Er_NqsJUQ0o
* https://www.youtube.com/watch?v=DhbMnQt14_o
* https://www.youtube.com/watch?v=37D_k4KVV-Q
* https://www.youtube.com/watch?v=a0d-wT6YS4w
* https://www.youtube.com/watch?v=DKOWeuV1FWE
** https://www.youtube.com/watch?v=QnvircC22hU&t=4s
** https://www.youtube.com/watch?v=Uke98FWkrHg
* https://www.youtube.com/watch?v=37D_k4KVV-Q
* https://www.youtube.com/watch?v=r8hBvHMt9V0
* https://www.youtube.com/watch?v=kd14I2HRHCY


connecting

* https://www.artfox.net/wall-wash-light-d0108012.html
* https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fanzhee-light.ru%2Fimages%2Fproducts%2Fimport_files%2Faa%2Faad0b1f42af011eaaadec2aee2823aa1_62cd60fe735e11eaab11c2aee2823aa1.jpg&f=1&nofb=1&ipt=cbbf28b78b73822435830430edc2c207ff2cae527fdef1126f29a75c7382a875&ipo=images
** https://anzhee-light.ru/product/anzhee-pixel-tube-connector-a18-ball/
* https://ignispixel.com/product/ignis-pixel-staff
** https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fignispixel.com%2Ffiles%2Fproducts%2Fstaff-connector-pro3.x1200n.jpg&f=1&nofb=1&ipt=aa7081e05ebcf2d4a3e7b091891a55302fd18e9f544c2df949e3d6dffa43faf8&ipo=images
* just a hook?
* https://www.bresser.de/en/Photostudio/Tripods/BRESSER-JM-82-Spigot-Connector-with-2-Ball-Joints.html
* screw connectors with integrated barrel jacks?
* endkappen alu
** led stick wird durch gewindestab zentral zusammengehalten
** custom stahl doppel-mutter schraubt an gewindestab, schließt nahtlohs mit alu ab und bietet noch eine mutter für externe befestigungen
** anschauben/festziehen wie flex-scheiben-mutter
** schwierig noch stecker unterzubekommen -> stecker einfach an 3 seiten vom alu teil?
* diverses zubehör
** doppelgewinde mit nurling für zwei stäbe
** standfuß mit gewinde
** Öse mit Gewinde
* keywords
** quick connect spigot
** quick release connector
** (light) spigot connector
* https://www.canford.co.uk/Products/74-8588_RYCOTE-185803-PCS-SPIGOT-Quick-release-attach-connector-3-8-inch-PCS-Tip-16mm-spigot-fitting
* https://www.huss-licht-ton.de/product_info.php/en/Astera-AX1-PixelTube-Wireless-Outdoor-LED-Tube/info/26136.html
* coax power connectors?
* [[Sam Zeloof|https://www.youtube.com/channel/UC7E8-0Ou69hwScPW1_fQApA]]
** [[Semiconductor Fabrication Basics - Thin Film Processes, Doping, Photolithography, etc.|https://www.youtube.com/watch?v=qCSIGejNT4M]]
** https://users.ece.cmu.edu/~szeloof/
* [[Hackaday Supercon - Sam Zeloof Home Chip Fab: Silicon IC Fabrication in the Garage|https://www.youtube.com/watch?v=23fTB3hG5cA]]
* https://hackaday.com/2017/02/25/the-fab-lab-next-door-diy-semiconductors/
* [[Nano-scale images made with electrons (electron beam lithography)|https://www.youtube.com/watch?v=3KXkcFcjcfY]]
* https://github.com/bmurmann/Book-on-MOS-stages - Book repository "Analysis and Design of Elementary MOS Amplifier Stages"
Required

* [[Speakers (combined or separate)|speakers]]
** Tops (high range)
** mid range boxes
** Subwoofer (low range)
* [[audio amplifier(s)|audio amplifiers]]
* power source
* 

Optional

* audio crossover (passive or active/digital), DSP or similar (recommended)
* pure resistive mode
* later addon: reacive load (with inductors to make it more speaker-like)
* tests
** settable frequency and amplitude/volume
** pure sine for longer time (1kHz standard as default)
*** detect power dropoffs
**  peak power test mode (standard?)
**  automatically determine clipping

see [[speaker / audio Dummy Load (Ersatzlast)]]

* https://en.wikipedia.org/wiki/Audio_power
* [[Can we print EVERYTHING in a speaker? Trying Polymate3D's FD52 fully 3D printed driver!|https://www.youtube.com/watch?v=nux47f92pf4]]
* [[ Planar Speaker PCB - Homemade HiFi Headphones |https://www.youtube.com/watch?v=Wrizk-TqsGY]]
* https://www.instructables.com/id/TPA3118-Amplifier-and-Speaker/


you can learn a lot from teardowns and there are many people wo are great and contribute to the collective knowledge through sharing teardowns and repairs online, e.g. on youtube

* https://de.ifixit.com/Device/Speaker
* https://www.subwoofer-builder.com/
* https://www.youtube.com/user/HexiBase/videos
* https://www.youtube.com/watch?v=4_4tu4rAtgI
* http://www.sengpielaudio.com/ - tontechnik
* https://www.instructables.com/circuits/audio/projects/
* https://www.instructables.com/circuits/speakers/projects/
* http://www.jobst-audio.de/
* "Werkstatt der Lautsprechertechnik" - youtube
* https://www.speakerplans.com/
* https://www.speakerplans.com/index.php?id=links
* http://www.diysubwoofers.org/
* https://forum.speakerplans.com/forums.html
* https://www.diyaudio.com/
* https://www.epanorama.net/links/audiospeakers.html
* http://www.frugal-horn.com/
* http://education.lenardaudio.com/
* http://mh-audio.nl/Loudspeakers.html#top
* https://www.acoustic-design-magazin.de/
* https://en.wikipedia.org/wiki/Loudspeaker_enclosure
* http://www.lean-business.co.uk/speakerplans/
* https://www.electronics-notes.com/articles/audio-video/loudspeaker/speaker-enclosure-box.php
* https://www.dummies.com/consumer-electronics/home-theater/types-of-speaker-enclosures-sealed-and-ported/
* http://www.cieri.net/Documenti/Schemi/Altec%20-%20Loudspeaker%20Enclosure%20-%20Their%20Design%20and%20Use%20(circa%201975).pdf
* http://www.audiogurus.com/learn/news/speaker-cabinet-design-styles-techniques/2037
* https://hifi-selbstbau.de/grundlagen-mainmenu-35
* https://www.lautsprecherbau.de/grundlagen/theorie/gehaeusearten/10100,de
* http://www.lautsprecher-berlin.de/linkliste.html
* https://diyaudioprojects.com/Speakers/speakers.htm
* https://gearpatrol.com/2015/05/15/beginners-guide-to-speakers/
* https://www.audioholics.com/diy-audio/building-a-do-it-yourself-loudspeaker-design
* https://www.diyaudioandvideo.com/Tutorial/DesignBuildSpeakerBox/
* https://projekter.aau.dk/projekter/files/9878159/Advanced_Loudspeaker_Modelling_and_Crossover_Network_Optimization.pdf
* https://engineering.purdue.edu/ece103/LectureNotes/SRS_Speaker_and_Enclosure_Intro.pdf
* https://sound-au.com/articles.htm#loud
* https://www.youtube.com/c/jobstaudio/playlists

other stuff:

* https://www.cnet.com/news/how-to-stop-worrying-about-speaker-impedance/


the hard part is designing the speaker enclosure fitting to the speakers, [[speaker design software]]

needed:

* drivers
* wood
* punched plate (lochblech/gitter)
* input-plugs or terminals
* ...
* air quality
** https://www.tomshardware.com/news/raspberry-pi-air-pollution-monitor
** https://www.luft.sachsen.de/aktuelle-messwerte-15045.html
** https://www.umweltbundesamt.de/daten/luft/luftdaten
** https://projects.opennext.eu/@tiwaneewaag/open-holu
** [[DIY Air Quality Monitor - PM2.5, CO2, VOC, Ozone, Temp & Hum Arduino Meter|https://www.youtube.com/watch?v=esY_OtDLv7g]]
** [[Your home's air could be making you sick. Fight back!|https://www.youtube.com/watch?v=Cmr5VNALRAg]]
** [[SuperHouse #38: DIY air quality sensor part 1 - "Basic" version|https://www.youtube.com/watch?v=5FdTRIq6_mY]]
** https://hackaday.com/2022/08/30/lora-air-quality-monitor-raises-the-bar-on-diy-iot/
** CO2
** https://verschwoerhaus.de/tag/openfeinstaub/

* weather / air
** https://www.heise.de/make/artikel/Wettermessgeraet-fuer-OpenSenseMap-einrichten-2803135.html
** https://opensensemap.org/

* https://github.com/sensebox
* https://sensebox.de/
** https://www.buergerschaffenwissen.de/projekt/sensebox-die-kiste-mit-sinn
* https://www.heise.de/ratgeber/19-Umweltsensoren-fuer-Arduino-und-Raspberry-Pi-4312920.html

* could maybe even be used to get entropy for cryptography?

* noise
** https://www.researchgate.net/post/What-are-the-open-source-software-available-for-noise-pollution-modeling
** https://noise-planet.org/noisemodelling.html

* seismic data (earthquakes)
** https://openeew.com/

* radiation (geiger-counter)
** https://safecast.org/devices/bgeigie-nano/
** https://hackaday.com/2019/08/28/global-radiation-montoring-and-tracking-nuclear-disasters-at-home/

* light
** [[#322​ 12 Light Sensors Tested: Measuring Light with Microcontrollers (Arduino or ESP8266, ESP32)|https://www.youtube.com/watch?v=r6mof_5w0rU]]
* [[DIY Air Quality Sensor|https://www.youtube.com/playlist?list=PL8mjSseObLTkEzNIGXqip-_NtkfDJM-Kk]]

hardware

* si7021 themp and humidity sensor modules


projects

* https://hackaday.com/2018/06/05/smart-citizen-opens-eyes-and-ears-in-barcelona/
* https://fablabbcn.org/projects/smart-citizen
* https://hackaday.com/tag/environmental-monitoring/
* https://hackaday.com/2013/09/30/smart-citizen-arduino-compatible-and-packed-with-sensors/
galvanometers and their controllers are expensive

pps, points per second, is the meassure of how many individual dots an animation-laser can display

20kpps galvanometers can be found at ebay for 100€ and less, but mid-range is more like 45kpps and good ones have 60kpps+

ideas

* maybe using HDD parts?
** high speed BLDC/stepper motors
** the read/write arm is more or less a galvanometer in itself
* completely rotating mirrors or prisms to do xy-scanning? more like a laser printer

other projects


* https://hackaday.io/project/28573-laser-xy-scanner
* https://stanleyprojects.com/projects/laser/laserscanner has two (or more) versions
* https://web.archive.org/web/20201109030530/elm-chan.org/works/vlp/report_e.html - includes selfbuild galvanometers
** https://hackaday.com/2010/08/22/another-home-built-laser-projector/
* https://hackaday.com/tag/galvanometer/
** https://hackaday.com/2018/04/20/laser-projector-ditches-galvanometer-for-spinning-drum/
* https://hackaday.com/tag/projector/
* https://makezine.com/2012/01/04/homemade-full-color-hdtv-laser-projector/
* http://laser-tv.eu/
* https://people.ece.cornell.edu/land/courses/ece5760/FinalProjects/s2019/eam348_rbr76/eam348_rbr76/eam348_rbr76/index.html
* https://hackaday.com/2022/07/15/collaborative-effort-gets-laser-galvos-talking-g-code/
* https://hackaday.com/2022/11/02/laser-project-relies-on-steppers-rather-than-galvanometers/
* https://hackaday.com/2018/04/20/laser-projector-ditches-galvanometer-for-spinning-drum/
* https://hackaday.com/2017/08/29/boredom-lasers-projector/
* https://hackaday.com/2016/11/23/cheap-dual-mirror-laser-projector/
* https://hackaday.com/2011/11/10/rgb-laser-projector-is-a-jaw-dropping-build/
* https://hackaday.com/2014/09/20/vector-laser-projector-is-a-lesson-in-design-processes/
* [[Move Mirror with Magnets and Coils - Magnetic Actuator For Laser Machine|https://www.youtube.com/watch?v=lbkL_NNcL9Y]]
* https://hackaday.io/project/21933-prism-laser-scanner
Parts

* a webcam or digital camera of some sort
* linear diffraction grating (or old DVD for very simple/dirt cheap builds/uses)


stuff

* https://spectralworkbench.org/
* https://publiclab.org/wiki/spectrometry
* https://hackteria.org/wiki/DIY_NanoDrop
* [[Building a Nanodrop Style UV/Vis Spectrometer|https://www.youtube.com/watch?v=pIk8I10ZmYY]]
* https://www.theremino.com/en/downloads/automation#spectrometer
* https://physicsopenlab.org/2015/11/26/webcam-diffraction-grating-spectrometer/
* https://physicsopenlab.org/wp-content/uploads/2015/11/Spettrometro_ENG.pdf
* [[How to make a High Resolution Spectrometer|https://www.youtube.com/watch?v=DXkHjGL9CaA]]
* https://en.wikipedia.org/wiki/Optical_spectrometer
* https://hackaday.com/2019/02/09/spectrometer-is-inexpensive-and-capable/
* https://hackaday.com/tag/spectrometer/
* https://hackaday.com/tag/spectrophotometry/
* https://publiclab.org/notes/homechemist/08-24-2018/diy-high-resolution-spectrometer
* [[Building a DIY spectrometer|https://www.youtube.com/watch?v=p3MzQ1OF3lk]]
* https://www.navina.ch/workshop/spektroskop/index.html
** https://www.navina.ch/workshop/mini-spektroskop/index.html
* https://www.cs.cmu.edu/~zhuxj/astro/html/spectrometer.html
* https://github.com/leswright1977/PySpectrometer2
** https://hackaday.com/2022/10/29/pi-based-spectrometer-gets-an-upgrade/
** [[ DIY Raspberry Pi Spectrometer NEW SOFTWARE! |https://www.youtube.com/watch?v=SCp9T8NKfnM]]
** [[ How to build a DIY Raspberry Pi Spectrometer using a Picamera and Spectroscope. |https://www.youtube.com/watch?v=T_goVwwxKE4]]
** [[ How to build a DIY Raspberry Pi Spectrometer. Part 2, Software update and discussion on code|https://www.youtube.com/watch?v=dm3woVQp8Xc]]
<<list-links "[all[current]tagging[]]">>

* http://www.dmx512-online.com/whats_dmx512.html
* https://hackaday.com/2021/10/15/learn-dmx512-basics/
* https://de.wikipedia.org/wiki/DMX_(Lichttechnik)
** https://en.wikipedia.org/wiki/DMX512
* see also [[inter IC or inter device communication, networking]] for RS-485
* https://www.thomann.de/de/onlineexpert_topic_dmx.html
* https://www.thomann.de/de/onlineexpert_page_kabel_kabelarten.html - 4. Steuerkabel

other diy

* https://wiki-de.dmxcontrol-projects.org/index.php?title=Kategorie:Selbstbau-Projekte
* https://hackaday.com/blog/?s=DMX
* https://www.electroschematics.com/arduino-dmx-and-rgbw-par-led-spotlight/
* one can find cheap "DMX decoder" pcbs/modules/boards to directly control LED strips or lights
* https://www.youtube.com/watch?v=xc9Zmm6CCp4

hardware:

* XLR 5pin or 3pin connector see [[DMX Connector]]
* isolation using optocouplers or so
* MAX485 and the SN75176 RS-485 to serial transceiver
** or ADM483
** https://www.analog.com/en/products/adm2486.html
* [[microcontroller]]
* drivers for light and stuff

software

* https://www.qlcplus.org/ - active, really good
* https://www.pcdimmer.de/index.php - active
* https://sourceforge.net/projects/dmxdesk/ - abandoned
* https://sourceforge.net/projects/qlc/ - abandoned
* https://sourceforge.net/projects/lightsup/ - abandoned
* https://github.com/luksal/ESP32-DMX

stuff

* [[Inside a wireless DMX receiver|https://www.youtube.com/watch?v=CBUxwt6Vliw]]
* [[Inside the DMX-cat event-industry lighting tool|https://www.youtube.com/watch?v=aIVqrAzrgEg]]
* [[Inside a Showtec DB-1-4 DMX isolator, buffer, repeater.|https://www.youtube.com/watch?v=ajw5Dwtfd74]]
* https://en.wikipedia.org/wiki/Lighting_control_console
* [[SDG #048 DMX Controlled RGB Linear Light Strips|https://www.youtube.com/watch?v=bDFkVJ4jwTE]]
* https://www.epanorama.net/newepa/2021/03/15/dmx-512-control-board-dmx-192-repair/
* https://www.epanorama.net/newepa/2016/06/13/four-channel-dmx-512-light-dimmer/
* https://www.epanorama.net/newepa/2016/06/14/from-dmx-512-to-artnet/
* https://www.epanorama.net/newepa/2017/03/07/dmx-512-decoder-for-rgb-led/
* [[inside a cheap eBay 1 to 8 way DMX buffer.|https://www.youtube.com/watch?v=kq4nU--hUAI]]
* [[10W LED "blunty" moving head disco light teardown.|https://www.youtube.com/watch?v=i3dHP6ehGY0]]
* [[Inside the DMX version of the LED dome disco light.|https://www.youtube.com/watch?v=tZLf6gObNIk]]
* [[Teardown of a DMX controlled UV disco light.|https://www.youtube.com/watch?v=0bKzHjpYZUo]]
* [[DMX fire machine.|https://www.youtube.com/watch?v=-AzhhbOzTbI]]
* https://qlcplus.org/features.html
* [[Learning from other's mistakes|https://www.youtube.com/watch?v=fDP1OPlib2g]]
* [[https://www.youtube.com/shorts/Uy1H3s--Xw8]]
* https://www.youtube.com/watch?v=OngB0z3zVpc&pp=ygUJbHVtaWJvb3N0
devices might use 3pin XLR or 5pin XLR for DMX

receivers have female plugs, the inputs on DMX devices are male.

cheap option would be to have 3pin female on the wireless receivers and use 3pin male to 5pin female adapters:

* https://www.thomann.de/de/pro_snake_tpa_1003_mf5.htm
* https://www.thomann.de/de/stairville_dmxadapter_53_pol_wm.htm
* https://www.thomann.de/de/adj_dmx_adapter_cable_dmxt_3m5f.htm

how important is 110Ohm cable?
* [[DIY keychain DMX tester for lighting technicians.|https://www.youtube.com/watch?v=skwUNRp-Rrk]]
* [[Make Your Own DMX Signal Tester|https://www.youtube.com/watch?v=wLC3ojYHd70]]
* https://www.youtube.com/watch?v=9FRVcq_Uf2M
* https://www.youtube.com/watch?v=nrQUze0Q_yE
* https://www.instructables.com/Art-Net-Controlled-Winch/
* https://de.wikipedia.org/wiki/Fangvorrichtung
* https://de.aliexpress.com/w/wholesale-rc-auto-winde.html
* https://en.wikipedia.org/wiki/Fall_arrest
* retracting fall arrest
* https://www.the-scientist.com/news-opinion/scientists-reverse-engineer-mrna-sequence-of-moderna-vaccine-68640
* https://github.com/NAalytics/Assemblies-of-putative-SARS-CoV2-spike-encoding-mRNA-sequences-for-vaccines-BNT-162b2-and-mRNA-1273
* https://en.wikipedia.org/wiki/DNA
** https://de.wikipedia.org/wiki/Desoxyribonukleins%C3%A4ure
* https://en.wikipedia.org/wiki/RNA
** https://de.wikipedia.org/wiki/Ribonukleins%C3%A4ure
* https://www.youtube.com/watch?v=WFCvkkDSfIU
** https://www.youtube.com/watch?v=X_tYrnv_o6A
* https://berthub.eu/articles/posts/reverse-engineering-source-code-of-the-biontech-pfizer-vaccine/
* https://www.quad9.net/
<<list-links "[all[current]tagging[]]">>

* https://en.wikipedia.org/wiki/Dresden
* https://freiraumelbtal.wordpress.com/ - war mal was cooles aber leider tod
* https://dresden.network/ - mastodon
* https://www.piraten-dresden.de/daten-aller-kommunalen-grundstuecke-sind-frei/
** https://www.piraten-dresden.de/grundstuckkarte/
* https://www.radwatch-dresden.de
* https://de.wikipedia.org/wiki/Sachsenbad_Dresden
** https://sachsenbad.propieschen.de/
* https://www.dresden.de/de/rathaus/dienstleistungen/versammlungsuebersicht.php
* https://coloradio.org/
* https://blauefabrik.de/
* https://ratsinfo.dresden.de/info.asp
* stadtplan.dresden.de
* apps.dresden.de
* https://codimd.c3d2.de/vernetzung#
* https://t.me/VernetzungvonDresden
* https://www.wann-wieviele-wohin.de/
* propieschen.de
* rostiges-ross.de
* https://colouring.dresden.ioer.info/
* https://terminal.digital/

Förderungen

* https://kulturbuero-dresden.de/
** [[Kinder- und Jugend Büro|https://kijubdd.de/]]
** https://www.hor-dresden.de/
* https://www.aufwinddresden.de/foerderungen/
* Stadtbezirgsbeiräte und die Stadtteilfonds
** https://www.zukunftsstadt-dresden.de/projekte/b5/
* https://www.99funken.de/ - art lokales fundraising?

osint

* https://www.vvo-online.de/de/service/verkehrskameras/index.cshtml
* https://www.holz-rentsch.de/unser-sortiment/
** https://www.ihr-holzshop.de/
* AZ Elektronik: https://www.openstreetmap.org/node/9929580173
* https://www.hans-mueller-jun.de/ - metall-schrott abkaufen
* baumärkte:
** obi
** hornbach
** globus
* https://nytt-materialdepot.de
* https://materialvermittlung.org/
* https://fundus-dresden.jimdofree.com/
* "schloma" - https://www.pft-riesa.de/standorte/filiale-dresden.html
** https://www.openstreetmap.org/way/168345461
* [[free/open/cheap DSP]]
* [[#DIGITAL #FREQUENZWEICHE DCX2496 -- Grundsätzliche Funktionen bei Verwendung für HiFi-Boxen|https://www.youtube.com/watch?v=c2PUJX0vfeA]]
* https://xilica.com/
* https://www.xmos.ai/
* https://www.creative.com/oem/products.aspx
* some amp chips or bluetooth/etc. transceivers have integrated dsp functionality
** https://www.ti.com/product/TAS5825M
* https://dbxpro.com/
* https://theaudioprogrammer.com/
** https://theaudioprogrammer.com/category/digital-signal-processing/signal-analysis/
* [[audio filters (digital)]]
* analog devices
* https://www.youtube.com/results?search_query=jobst+audio+dsp+review
* some stuff can also be done with fpga's
* https://hackaday.com/2019/11/01/dsp-spreadsheet-frequency-mixing/
* https://en.wikipedia.org/wiki/Digital_signal_processing
* [[Phil's Lab: DSP|https://www.youtube.com/playlist?list=PLXSyc11qLa1ZCn0JCnaaXOWN6Z46rK9jd]] - implementation of digital filters and other dsp stuff
** [[Audio EQ Software Implementation (STM32) - Phil's Lab #89|https://www.youtube.com/watch?v=4o-_gUht_Xc]]


Manufacturers / commercial models

* Behringer
** [[Behringer Ultradrive Pro DCX2496]]
* Musicrown - cheap ones from china
** thomann the t.racks - rebrands
* dbx
* Xilica
* https://www.minidsp.com/


Chips used in other, commercial hardware:

* [[Analog Devices ADSP-21065L|https://www.analog.com/media/en/technical-documentation/data-sheets/ADSP-21065L.pdf]] - [[Behringer Ultradrive Pro DCX2496]]

implementation?

* Hardware
** [[AES/EBU, AES3]]

* Software
** [[Limiter]]
** crossover
** EQ
** ...

* mixed signal pcb design: [[circuit/pcb design and simulation]]

stuff

* http://96khz.org/htm/fpgamusicsynthesizercyclone4.htm
* https://www.musicdsp.org/en/latest/index.html
* https://dsp.stackexchange.com/questions/43907/normalizing-audio-waveforms-code-implementation-peak-rms
* https://www.diyaudio.com/community/threads/sensorless-dsp-cone-excursion-limiter.298248/
* https://ez.analog.com/dsp/sigmadsp/f/q-a/98429/sigma-dsp-compressor-level-readout
* https://dsp.stackexchange.com/questions/81189/modeling-analog-filters-for-software-implementation
* [[Phil's Lab - Audio Electronics Playlist|https://www.youtube.com/playlist?list=PLXSyc11qLa1ZGY3nD7to5eQGKGMREhNGl]]
* https://thesofproject.github.io/latest/index.html
** https://thesofproject.github.io/latest/platforms/index.html#supported-platforms
* https://blog.brixit.nl/building-a-digital-audio-mixer/
* [[Understanding Audio Dynamic Range / SNR (Part 1)|https://www.youtube.com/watch?v=D4qQJ82O4tY]]
TODO: move esc/motor controller stuff ti

* essentially just a [[ESC / BLDC motor driver / controller]] with some connections and features for external hardware and controlls
* most controllers include the controller and the motor driver in one package
* https://www.elecycles.com/blog/post/what-you-need-to-know-about-electric-bike-controller/

controller + driver

* cheap ones from china can be found on ebay, aliexpress/alibaba, bangood, etc., bmc-world.com also sells them
** some wiring diagrams:
*** https://www.elecycles.com/blog/post/what-you-need-to-know-about-electric-bike-controller/
*** https://ricardolevinsmorales.com/e-bike-controller-wiring-diagram/
** https://www.pedelecforum.de/wiki/doku.php?id=antriebsstrang:specialbike_lsdzs_com - some more information
* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:barmalcontroller
* the VESC can be easily used for bikes - open source
* https://www.pedelecforum.de/forum/index.php?threads/eigenbau-universalcontroller-250-1000w.45553/ - open source
* https://github.com/EBiCS/EBiCS_Hailong - open source
* https://www.pedelecforum.de/wiki/doku.php?id=e-motor:programmierbare_controller

fitting flipsky controllers (vesc)

* https://flipsky.net/collections/electronic-products/products/flipsky-75100-foc-75v-100a-single-esc-base-on-vesc-for-electric-skateboard-scooter-ebike-speed-controller
* https://flipsky.net/collections/electronic-products/products/flipsky-mini-fsesc6-7-pro-70a-base-on-vesc6-6-with-aluminum-anodized-heat-sink
* https://flipsky.net/collections/electronic-products/products/mini-fsesc4-20-50a-base-on-vesc-widely-used-in-eskateboard-escooter-ebike
* https://flipsky.net/collections/electronic-products/products/torque-esc-vesc-%C2%AE-bldc-electronic-speed-controller

open firmware for common controllers

* https://github.com/stancecoke/BMSBattery_S_controllers_firmware/wiki
** https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:open_source_firmware_fuer_sxxs_ktxx_-controller
* https://github.com/EBiCS/EBiCS_Firmware
** https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:open_source_firmware_fuer_lishui_-controller
* https://github.com/OpenSourceEBike/TSDZ2-Smart-EBike

stuff

* some support [[regenerative breaking (rekuperation)]]
* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:controller-reparaturanleitung
* https://www.pedelecforum.de/wiki/doku.php?id=tipps:start#controllerfunktion_reparatur

<<list-links "[all[current]tagging[]]">>


general

* https://www.pedelecforum.de/wiki/doku.php?id=start
** https://www.pedelecforum.de/wiki/doku.php?id=start&do=index
* https://circular.bike/
** https://blog.formf.de/2020/12/rc3/
** https://blog.formf.de/circular-bike/
* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:komponenten_eines_pedelecantriebes
* https://www.pedelecforum.de/wiki/doku.php?id=tipps:start
* https://hackaday.com/tag/electric-bicycle/
* https://hackaday.com/tag/electric-bike/

in some legislations (like the EU) the e-bike is only allowed to accelerate to a certain speed only with motor power. in the EU e-bikes are only allowed to accelerate up to 6km/h on motor power, for higher speeds the person driving the bike has to pedal and the motor is only assisting.
in the EU the max speed is 25km/h and the max allowed motor power is 250W.

electronics

* https://www.pedelecforum.de/wiki/doku.php?id=e-motor:start
* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:start
* [[motor|e-bike motor]]
* [[controller, motor driver|e-bike controller, motor driver]] 
* [[throttle control|e-bike throttle control]]
* [[PAS-Sensor|e-bike PAS-Sensor]]
* torque sensor (drehmomentsensor)
** only found in expensive bikes instead of the simpler PAS
** https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:drehmomentsensoren
* brake levers
** break levers can be bought or modified with switches or hall-sensors to signal the controller to switch of the motor, has to be supported by the controller
** https://www.pedelecforum.de/wiki/doku.php?id=tipps:start#bremshebelmotorabschaltung_mit_modifikationen 
* [[battery packs]]
** mostly normal Li-Ion battery packs
** mostly 36V or 48V nominal
** https://www.pedelecforum.de/wiki/doku.php?id=akku:start
* standards/normen
** EN15194?
* [[regenerative breaking (rekuperation)]]
* connectors
** Higo connectors
** Julet connectors
** JST SM (not whaterproof)
** and others
* https://hackaday.com/2020/01/07/choosing-the-right-battery-for-your-electric-vehicle-build/
* https://hackaday.com/2023/09/18/fast-charging-a-cargo-bike-from-an-electric-car-charger/

finding problems:

* https://www.pedelecforum.de/wiki/doku.php?id=antriebsstrang:specialbike_serviceinfos-lsdzs_com
* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:fehlersuche_beim_pedelec
* https://www.pedelecforum.de/wiki/doku.php?id=tipps:start#motor-_regler-_hallsensorprobleme

stuff

* https://hackaday.com/blog/page/4/?s=e%20bike
* [[Electronic Basics #18: DC & Brushless DC Motor + ESC|https://www.youtube.com/watch?v=UteZJ_7C4Mg]]
* [[ Convert Tricycle to Electric Power for $200 - including the Battery Pack. |https://www.youtube.com/watch?v=UoGbLtdpOO4]]
* https://emotion-technologies.de/e-bike-infos/lexikon/s-pedelec/
* https://de.wikipedia.org/wiki/Mofa#Deutschland_2
* https://de.wikipedia.org/wiki/E-Bike#Deutschland
* https://en.wikipedia.org/wiki/Pedelec
* they all seem to be 3-phase BLDC motors
** https://en.wikipedia.org/wiki/Brushless_DC_electric_motor
** https://de.wikipedia.org/wiki/B%C3%BCrstenloser_Gleichstrommotor
* the power of the motor also depends on the voltage of the system.
** 36V systems mostly have 250W motors, but 500W motors are allso available
** 48V systems have motors with 500W, 1kW or even more
* https://www.pedelecforum.de/wiki/doku.php?id=antriebsstrang:specialbike_suzhou-bafang-motor
* https://www.pedelecforum.de/wiki/doku.php?id=e-motor:start
* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:epacsim
* https://www.pedelecforum.de/wiki/doku.php?id=tipps:start#formeln_zur_berechnung_des_maximalen_anfahrdrehmoments_von_naben-_und_tretlagermotoren
Pedal Assist Sensor, used to detect pedaling of the driving person.

in some legislations (like the EU) the e-bike is only allowed to accelerate to a certain speed only with motor power. in the EU e-bikes are only allowed to accelerate up to 6km/h on motor power, for higher speeds the person driving the bike has to pedal and the motor is only assisting. this requires a PAS-Sensor

the PAS Sensor is composed of a small plate with embedded magnets, a Hall-Sensor and mounting hardware.
the Hall-Sensor is mounted on a fixed position on the frame next to one of the pedals, the plate is fixed to the axle of the pedals and spinns along with the pedals next to the sensor which picks up the magnetic fields of the embedded magnets.

mostly digital hall sensors are used.

pinout

* 5V - power supply for the hall sensor
* GND
* data - has to be pulled high

the data line of the hall-sensor has to be pulled high (with a 10k resistor to the 5V line) by the controller because the digital hall sensors pull the data line to ground.

* https://www.pedelecforum.de/wiki/doku.php?id=tipps:start#pas-sensorenfunktionsweise_und_tests
* https://www.pedelecforum.de/wiki/doku.php?id=tipps:start#sensorbefestigung_von_pedelec-sensor_und_magnetscheibe
mostly twist- or lever-style controlls used to controll the trottle and, to some extend, the speed. attached to the handlebars of the bike.

most throttle controls for e-bikes use an analog hall-sensor and a magnet

pinout for most analog types:

* 5V (often red) - power supply for the sensor
* GND (often black)
* data (some other color, sometimes white) - the analog readout of the hall-sensor
* alp 2d schlüssel
* https://www.key-code.com/en/shop/kl-alp9s-keyline-key-alp9s-alp9r-alp-2d-8938#attr=
* https://bz1.de/zylinderschluessel-standard-messing-klalp9-salp9-bo986-jmaalp2i-p-2028.html
* https://bz1.de/zylinderschluessel-standard-messing-klwr7-swei1-bo996k-jmawei1-p-2096.html
* https://bz1.de/zylinderschluessel-standard-messing-klalp4-salp4-bo1484-jmaalp1i-p-2026.html
* https://bz1.de/zylinderschluessel-standard-messing-klalp4s-salp4r-bo986-jmaalp1d-p-2027.html
* https://bz1.de/zylinderschluessel-standard-messing-klalp9s-salp9r-bo986kn-jmaalp2d-p-2029.html
* https://autokulcs.hu/lakaskulcsok/5139-silca-alp9r-10-errebi-ah8r-jma-alp-2d-orion-aph6l-keyline-alp9s-epueletkulcs-lakaskulcs-100005950033.html
* https://asel-shop.ch/search?type=product&options%5Bprefix%5D=last&options%5Bunavailable_products%5D=show&q=alpha
* https://asel-shop.ch/
* schlüssel ALP9s
* schlüsselrohlinge
** https://www.ebay.de/itm/114183802484
** https://www.ebay.de/itm/175713732027
** https://www.ebay.de/itm/175713732029
** https://www.ebay.de/itm/281081423147
* alp9 schlüssel
* keyline alp-2d
* https://www.besabvba.com/documents/catalog/alp-2d.xml?open=&lang=de
* https://ecatalogo.jma.es/de/alp-2d/854/
* keyline alp9s
* https://keyline-shop.de/product/alp9sk000/
* https://www.keyfirst.eu/de/flache-schraubenschluessel/cles-plates-acier-keyline-s-alp9r-j-alp-2d.html
* schlüssel profil alpha
* https://www.ebay.de/sch/i.html?campid=5338791379&kw=schl%C3%BCssel%20rohling%20alpha&mkcid=1&* * mkrid=707-53477-19255-0&toolid=20004
* https://www.ebay.de/itm/265091343762
* https://de.m.wikipedia.org/wiki/Schl%C3%BCssel
* profil alpha 4
* jma alp-2d
* https://www.jma.es/en/eshop/alp-2/pr-5829/
* https://ecatalogo.jma.es/en/alp-2/849/?imprimir=1
* https://ecatalogo.jma.es/en/alp-2d/850/?imprimir=1
* https://jma-uk.co.uk/alp-2d-jma-alp-2d-cylinder-key-blank-for-alphar
* https://ecatalogo.jma.es/de/alp-2d/854/
* alp-9 key dimensions
* https://www.keyfirst.eu/en/building-keys/flat-wrenches/alpha/
* https://www.mslocks.com/shop/alp9-key-blank/
* alpha key profile
* Errebi AH4R





* https://www.denver-locksmith.net/2017/03/rekey-car-door-lock-cost/
* https://lockanalyst.org/index.php/the-wafer-tumbler-design/
* https://www.drlock.com.au/store/lock-shop-locks-cabinet-furniture-locks-cam-locks-lock-focus-spare-parts-accessories-lock-focus-wafers-11351003
* https://digitalfires.com/rekeying/
* https://www.lsc.com.au/lock-focus-wafer-kit-a-kit-60-ser60
* https://home.howstuffworks.com/home-improvement/household-safety/lock-picking3.htm
* https://en.wikipedia.org/wiki/Wafer_tumbler_lock
* https://www.clksupplies.com/products/standard-wafer-keying-kit
* http://locksmithschool4u.com/lock_lessons/16-how-to-rekey-service-tubular-wafer-locks.html
* https://www.clksupplies.com/blogs/news/locksmithing-101-how-to-re-key-cam-locks-everything-you-need-to-know
* https://www.youtube.com/watch?v=f3zmnhJ3-IA
* https://www.youtube.com/watch?v=McQr0VACZpw
* https://lockwiki.com/index.php/Wafer
* https://lockwiki.com/index.php/Guide_to_Wafer_Lock_Reading
* https://www.keypicking.com/viewtopic.php?t=7654
* https://www.digital-kaos.co.uk/forums/showthread.php/586920-Car-lock-wafer-decoding
* https://lockpickingforensics.com/decoding.php
* https://www.youtube.com/watch?v=mySMWvOGmmo
* https://www.youtube.com/watch?v=FRZ2YXlZV-o
* https://doityourselflocksmithing.blogspot.com/2013/02/wafer-tumbler-lock.html
* https://www.locksmithledger.com/home/article/10756365/wafer-lock-key-fitting
* original keys are branded shanshan plastic but you can't find much with that on aliexpress


* aliexpress wafer plates: wafer reed lock plate 




zylinder:

* hailong lock
* bike battery lock
* yose power?
* Phylion
* unit pack power
* hailong
* Hailong lock key
* https://de.aliexpress.com/item/32975182610.html
* https://de.aliexpress.com/item/1005004712415873.html
* https://de.aliexpress.com/item/1005003752605005.html

!! further findings

so i originally bought HU49 wafers, maybe i get lucky. but those are bigger than the ones in the locks i got.

i later got a broken ebike battery with a lock in it that actually uses the HU49 wafers.

i also got honda motorbike key blanks which have the same profile.

since i had no luck with the wafers in the first try i bought 3 replacement locks for hailong batteries. 11mm ones, but the ones with the longer bar should be the same cylinder.
the 3 i got have 5 positions for wafers. I got lucky, that one of the locks has a very simple code and the simple keying matches with one of the other locks.
i can rekey the simple lock to match the other one using wafers from the old locks with missing keys. and then i can just modify the key myself.

i want to try find the right wafer size.
i had no luck finding dimensions for any of the wafers. other wafers that look similar: NSN14 (4), HYN11 (4), HY16 (5)
controller only, without motor driver

* using/spying on the serial connection of the display to log the data
** e.g. using an esp32/esp8266 and phyphox
** see [[protecting microcontroller inputs]]
* https://hackaday.com/2020/03/07/a-super-brain-for-an-e-bike/
** https://makestuff4.fun/pyec/#
** https://forum.micropython.org/viewtopic.php?f=5&t=7828
* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:forumscontroller
* https://github.com/thorlancaster/electric-bike-controller - seems to be meant to simultaneusly controll 2 motors (front&rear) on one bike
* https://www.youtube.com/watch?v=7wRX0unw5e4
!! EE Systems V-800

Problem (told from owners): no sound, just noise on one channel in stereo mode

I opened the amp up cleaned it a bit and checked if i could see any obvious problems. did a quick check if the channels might be shorted but found nothing, so i connected two speakers for testing and it worked fine. i could not find any issues.
But i think the transformer is pretty small for a 450W stereo Class AB amp.
<<<
Grundsätzlich würde ich sagen, Kauf dir nen 12" koax Lautsprecher mit 1,4er oder so in der Mitte, dann hast du eine Schallquelle was der Sprachverständlichkeit zu gute kommt. Trennfrequenz von tmt zu HT musst du auf den coax Anpassen, dann nen Recht großes BR Gehäuse mit großen Ports und 80-120hz Abstimmung um Recht viel Wirkungsgrad zu bekommen. Reicht für Sprache locker als standalone
<<<

* ported, bass reflex, see [[ports / vents]]
* abstimmung
** fullrange:
*** je nach größe des basstreiber 50-65hz
** tops:
*** eher bei 100-200Hz
ehemals fff wiki - https://wiki.fridaysforfuture.is/index.php?title=Effiziente_Beschallung_von_Menschenmengen


<<<


Dieser Artikel beschäftigt sich mit Ideen zur effizienten Beschallung von größeren Menschenansammlungen/-gruppen, wie z.B. auf Demonstrationen.

== Motivation ==
Lautsprecher und ihre Schallerzeugung sind ziemlich ineffizient. Da Schall sich außerhalb von Gebäuden (also im Freiraum) ziemlich ungehindert ausbreiten kann nimmt der Schallpegel etwas mehr als quadratisch mit der Entfernung ab [vlt. bisschen Wissenschaftlicher machen].
Aus diesem Grund sind große PA-/Beschallungsanlagen nicht sehr effizient.

Da Generatoren sehr dreckig sind und Photovoltaik und Akkus in größeren Maßstäben auch nicht mehr einfach zu handhaben sind, ist eine Betrachtung der Effizienz wichtig.
Auch ist die Effizienz von Akkus abhängig von der Häufigkeit/Dauer der Nutzung, da für die Produktion von Akkus meist viel Energie benötigt wird. Diese Energie und das dabei freigewordene CO2 muss sich erstmal amortisieren.

== keine, oder nur sehr geringe elektronische Beschallung ==
Wenn Musik vernachlässigbar ist, kann auch ohne Beschallung gearbeitet werden. Reden könnten über ein Megafon realisiert werden.
Eine Band könnte vlt. an einem Punkt der Demoroute stehen und die Leute unterhalten während sie vorbei laufen.
Jedoch funktioniert die Beschallung von vielen Menschen so nur sehr begrenzt und ist kaum möglich. Reden werden nicht von allen Teilnehmer*innen verstanden.

Im folgenden gibt es aber auch noch Ansätze den Leistungsbedarf der Verbraucher zu minimieren.

== Verbesserung der Effizienz von bestehenden Anlagen ==
Die Verstärker sind ein Punkt an dem man ansetzen kann um die Effizienz einer Anlage zu erhöhen. Es gibt verschiedene Klassen an Verstärkern, die indirekt Qualität und Effizienz beschreiben, da jede Klasse für eine bestimmte Methode der Verstärkung steht.
Klasse D (engl. Class-D) Verstärker sind sehr effizient, da sie nur eine geringe Verlustleistung besitzen.

siehe auch:
* [[Wikipedia:de:Klasse-D-Verstärker]]

[weitere Wege der Effizienzsteigerung?]

== Kompressionstreiber und Hörner, Druckkammerlautsprecher ==
Die Methode wie sie auch in Megafonen eingesetzt wird ist ziemlich effizient.
Hörner haben bei hohen Frequenzen auch noch eine geringe Größe, aber die Größe von den benötigten Hörnern steigt mit der tiefe der Frequenz. Große Hörner für Bässe sind logistisch schnell problematisch.
Musik ist teilweise eher schwierig zu realisieren (hat nicht viel Bass).

Arrays von Druckkammerlautsprechern können auch ohne großen stromaufwand beachtlich hohe akkustische Leistung bringen, wie das folgende (wenn auch für dreckige zwecke gedachte) system: https://www.youtube.com/watch?v=1P3FsLMKwJE

== Nutzung kleinerer, verteilter Anlagen bzw. einzelner Boxen ==
Die Nutzung von mehreren kleineren Anlagen, die auf einer Demo verteilt sind kann die Effizienz erhöhen, da durch jede Anlage ein gewisser Bereich effizienter abgedeckt werden kann, als die gesamte Demo von nur einer Anlage.
Man könnte sogar kleinere handelsübliche, tragbare Bluetooth-Lautsprecher über funk verbinden. Dies könnte aber auf Grund der Größe und Leistung der Lautsprecher auch wieder ineffizienter sein.
Man könnte jedoch kleine Empfänger an den Aux-Eingang anschließen.
Mehr dazu in [[Musikstreaming zwischen Lautis (Konzept)]].

== Line Arrays ==
siehe: [[Wikipedia:de:Line Array]]

sehr teuer (ca. 1-2k€ pro Stück)

Line Arrays sind spezielle Lautsprecher mit raffinierter Technik, die es erlaubt Musik und Sprache über weite Distanzen zu übertragen.
Jedoch sind Line Arrays sehr teuer und benötigen eine gewisse Höhe um auch Distanz zu erreichen, was logistische Probleme mit sich bringt.


[[Kategorie:Wissen & Diskurs]][[Kategorie:Technik-IT Support]]

<<<


* [[Best LRAD System!... For Your Money -- Tech Ingredients|https://www.youtube.com/watch?v=y7UZHEHhdek]]
* [[LRAD]]
* Große Demonstration beschallen: http://www.hifi-forum.de/viewthread-127-3333.html
* demo / kundgebung mobil beschallen: http://www.hifi-forum.de/viewthread-182-7070.html
* https://www.mikrocontroller.net/articles/Eisenwarenversender
* see [[mcmaster carr alternative for europe]]
* https://www.pft-riesa.de/standorte/filiale-dresden.html
** https://www.openstreetmap.org/way/168345461
* [[Eisenfeustel|https://www.eisenfeustel.de/kontakt/]] - bisschen fragwürdig drauf
* [[werkzeuge kliemann|http://www.werkzeuge-kliemann.de/produktuebersicht]]
* out of old, crashed EVs?
* dunno

knowledge:

* https://www.instructables.com/class/Large-Motors-Class/
* https://www.n-tv.de/auto/Motoren-in-Elektroautos-sind-nicht-gleich-article21970051.html
* https://www.youtube.com/user/mikeselectricstuff/videos
* [[#113 - E-Auto Ladetechnik - Steckertypen, Wallbox, CEE-Laden, Lademodi, Fakten - Alles Wichtige|https://www.youtube.com/watch?v=T3WUfSBW-kE]]
* [[Ultimate Beginners Guide to Using Electric Motors for Makers and DIY Projects; #068|https://www.youtube.com/watch?v=SrPHQh-M3pM]]
* [[What Electric Motors Can Be Used In A Go Kart or E Bike; Bench Testing and Recommended Sizing #61|https://www.youtube.com/watch?v=5QYyzVyWckw]]
* [[Common Problems With Making An Electric Go Kart or EBike and How I Resolved Them. #063|https://www.youtube.com/watch?v=we2PcBok0YQ]]
* [[5 Build Your Own Electric Car: DC Motor Basics|https://www.youtube.com/watch?v=UnLEy8p9Xu8]]
* [[Making a Motorised Go Cart with NO WELDER and simple tools #1 - Chassis/Engine|https://www.youtube.com/watch?v=vuRV-uXGy1w]]
* [[Easy Conversion of AC Washer Motor to 12VDC|https://www.youtube.com/watch?v=5XkBpn1GaJw]]
* [[CHAINSAW GO KART! - Part 1|https://www.youtube.com/watch?v=v_1UO1GTsg0]] - electric chainsaw?
* [[electric go kart 775 made at home and reverse|https://www.youtube.com/watch?v=ihJYRyV0TqY]]
* [[Build a 1000W Electric Gokart at Home - Electric car - Tutorial - Part 2|https://www.youtube.com/watch?v=DwNzn-_G5_M]]
* [[Make a Motorised Drift Trike with Basic Tools|https://www.youtube.com/watch?v=tMn8NqbCkDA]]
* [[Building an Electric Bike|https://www.youtube.com/watch?v=1pm1RtCuE3A]]
* [[How we made a DIY PVC / EMT Electric Go Kart (48V 2000W)|https://www.youtube.com/watch?v=oXubH4b0ing]]
* [[Electronic Basics #18: DC & Brushless DC Motor + ESC|https://www.youtube.com/watch?v=UteZJ_7C4Mg]]
* [[Does this old Induction Motor still work? -- How do Asynchronous Motors work? EB#46|https://www.youtube.com/watch?v=EzJsKWW-cDU]]
* [[How to Reuse Washing Machine Motors - (The Simple Way )|https://www.youtube.com/watch?v=tUQg2WiHpUY]]
* https://hackaday.com/2018/02/16/analyzing-hobby-motors-with-an-oscilloscope/
* https://www.heise.de/hintergrund/Grundlagen-Technik-im-Elektroauto-Arten-des-Drehstrom-Motors-7190363.html

for Cars and Trucks

* https://www.bosch-mobility-solutions.com/de/produkte-und-services/pkw-und-leichte-nutzfahrzeuge/antriebssysteme/elektroantrieb/
* https://www.n-tv.de/auto/Motoren-in-Elektroautos-sind-nicht-gleich-article21970051.html
* https://endless-sphere.com/forums/
* https://www.youtube.com/user/mikeselectricstuff/videos
* [[#113 - E-Auto Ladetechnik - Steckertypen, Wallbox, CEE-Laden, Lademodi, Fakten - Alles Wichtige|https://www.youtube.com/watch?v=T3WUfSBW-kE]]
* https://www.youtube.com/watch?v=sGYCWztsjZg
* [[Building the Brains of the HIGH VOLTAGE System - IT MOVES!!|https://www.youtube.com/watch?v=yS_jxAIPCPw]]
* [[EEVblog: Fundamentals Friday|https://www.youtube.com/playlist?list=PLvOlSehNtuHtWlH0UOZNtOn-FlFCn1GYw]]
* [[GreatScott!: Electronic Basics|https://www.youtube.com/playlist?list=PLAROrg3NQn7cyu01HpOv5BWo217XWBZu0]]
* https://en.khanacademy.org/science/electrical-engineering
* [[The Engineering Mindset: Electrical Engineering Basics|https://www.youtube.com/playlist?list=PLWv9VM947MKi_7yJ0_FCfzTBXpQU-Qd3K]]
* https://www.youtube.com/c/Afrotechmods/playlists
* [[Electrical engineering|https://www.youtube.com/playlist?list=PLSQl0a2vh4HCLqA-rhMi_Z_WnBkD3wUka]]
* [[Basic Electronics Part 1 - By Washington Technical College |https://www.youtube.com/watch?v=nb4ovfwqup8]]
* [[ Analog and Digital Signals |https://www.youtube.com/watch?v=_iPoDIxD_-0]]

components

* [[A simple guide to electronic components.|https://www.youtube.com/watch?v=6Maq5IyHSuc]]
* [[Essential Electronics Components that you will need for creating projects!|https://www.youtube.com/watch?v=u4md32GMX28]]
* see [[electronics parts/components]]

Impedance

* [[Electronic Basics #37: What is Impedance? (AC Resistance?)|https://www.youtube.com/watch?v=W2VwAL7-8-o]]
* [[Tutorial: Electrical impedance made easy - Part 1|https://www.youtube.com/watch?v=xyMH8wKK-Ag]]

(linear) voltage regulators

* [[#183​ How to select voltage regulators for small projects? (ESP8266, ESP32, Arduino)|https://www.youtube.com/watch?v=ffLU7PSuI5k]]

Tools

* [[Essential Tools that you will need for creating electronics projects!|https://www.youtube.com/watch?v=7-djg27lJyQ]]
* [[EEVblog #168 - How To Set Up An Electronics Lab|https://www.youtube.com/watch?v=R_PbjbRaO2E]]
* [[EEVblog #954 - How To Setup An Electronics Lab For $300|https://www.youtube.com/watch?v=HicV3Z6XLFA]]

AC Power

* [[Power Factor Explained - The basics what is power factor pf|https://www.youtube.com/watch?v=Tv_7XWf96gg]]
* [[Ground Neutral and Hot wires explained - electrical engineering grounding ground fault|https://www.youtube.com/watch?v=P-W42tk-fWc]]
* [[120V 240V Electricity explained - Split phase 3 wire electrician|https://www.youtube.com/watch?v=fJeRabV5hNU]]
* [[Why 3 Phase AC instead of Single Phase???|https://www.youtube.com/watch?v=quABfe4Ev3s]]
* [[Three Phase Electricity Basics and Calculations electrical engineering|https://www.youtube.com/watch?v=qthuFLNSrlg]]
* [[Electronic Basics #38: True, Reactive, Apparent & Deformed Power|https://www.youtube.com/watch?v=cxXmWZDwNEs]]
* [[Single Phase Electricity Explained - wiring diagram energy meter|https://www.youtube.com/watch?v=W0_1xRqT8uU]]
* https://www.learnabout-electronics.org/ac_theory/index.php

general

* https://www.allaboutcircuits.com/textbook/


stuff

* [[EEVblog #941 - Schmitt Trigger Tutorial |https://www.youtube.com/watch?v=Ht48vv0rQYk]]
* https://hackaday.com/tag/electronic-load/
** https://hackaday.com/2020/06/06/a-diy-electronic-load-with-a-twist/
** https://hackaday.com/2019/02/28/spot-this-diy-electronic-loads-gracefully-hidden-hacks/
** https://hackaday.com/2020/01/07/liquid-cooling-keeps-this-electronic-loads-mosfets-from-burning/
** https://hackaday.com/2017/02/28/beefy-100-amp-electronic-load-uses-two-mosfets/
* https://www.youtube.com/results?search_query=diy+electronic+load
** [[DIY Adjustable Constant Load (Current & Power) -- GreatScott!|https://www.youtube.com/watch?v=VwCHtwskzLA]]
** [[Analog Constant Load/Current Controller Circuit - Electronoobs|https://www.youtube.com/watch?v=88xuhR30-dY]]
** [[Homemade Digital Electronic Load - Multiple Modes -- Electronoobs|https://www.youtube.com/watch?v=3XEf05flC4Q]]
** [[EEVblog #102​ - DIY Constant Current Dummy Load for Power Supply and Battery Testing|https://www.youtube.com/watch?v=8xX2SVcItOA]]
** [[Quick and Powerful IGBT Electronic Load|https://www.youtube.com/watch?v=acAuW0IVXKw]]
** [[Voltlog #119​ - 150W Dummy Load Review|https://www.youtube.com/watch?v=_uNfyM8TJl8]]
* https://www.instructables.com/DIY-Adjustable-Electronic-DC-Load/
* http://www.kerrywong.com/2013/10/24/building-a-constant-currentconstant-power-electronic-load/
* https://www.codrey.com/electronic-circuits/simple-electronic-dc-load/
* [[180W Electronic DC Load is a Fun Gadget|https://www.youtube.com/watch?v=e5dJ80Bbtqg]]
* !!! [[EEVblog #102​ - DIY Constant Current Dummy Load for Power Supply and Battery Testing|https://www.youtube.com/watch?v=8xX2SVcItOA]]
* https://www.paulvdiyblogs.net/2015/08/dynamic-dc-power-load.html
* https://hackaday.com/2021/03/15/custom-dummy-load-with-data-logging/
* https://hackaday.com/2023/09/01/hackaday-prize-2023-10-kw-electronic-load/

smaller loads for small power supplies or batteries:

* https://syonyk.blogspot.com/2015/10/tec-02-ver-30-semiconductor-battery.html
** https://syonyk.blogspot.com/2018/01/tec-06-serial-battery-tester-review.html
*** https://syonyk.blogspot.com/2018/01/reverse-engineering-tec-06-serial.html
** https://syonyk.blogspot.com/2018/12/the-ebd-m05-battery-tester-195v-5a-30w.html

TEC-06 and EBD-M05 seem to be very good.
i bought the TEC-06 for now.
the ZB206 seems to be an older design and isn't sold a lot anymore.

* http://www.kolloquia.de/?p=477 - about the tec-06

* https://hackaday.com/2018/09/06/zpb30a1-electronic-load-gets-an-open-firmware/

* mouser
* [[digikey|https://www.digikey.de/]]
* https://www.arrow.com/
* farnell
** https://en.wikipedia.org/wiki/Premier_Farnell
** https://de.farnell.com/
** https://farnell.com/
** https://www.newark.com/
* [[conrad|https://www.conrad.de/]]
** https://www.voelkner.de/
** Wikipedia: "Seit 2008 gehört zur Conrad-Unternehmensfamilie auch die Nürnberger Re-In Retail International GmbH, die die Online-Shops voelkner.de,[8] digitalo.de und smdv.de betreibt.[9]"
* [[pollin|https://www.pollin.de/]]
* reichelt
* https://www.buerklin.com/
* https://www.we-online.com/web/en/wuerth_elektronik/start.php
* https://czh-labs.com/
* https://lcsc.com/
* makershop.de
* [[AZ-delivery|https://www.az-delivery.de/]]
* [[Eckstein|https://eckstein-shop.de/]]
* https://www.tme.eu/
* https://www.ttieurope.com/
* https://de.elv.com/
* https://www.pololu.com/
* https://www.distrelec.de/

other lists:

* https://www.mikrocontroller.net/articles/Lokale_Elektroniklieferanten
* https://www.mikrocontroller.net/articles/Elektronikversender
* https://www.mikrocontroller.net/articles/Standardbauelemente#Lieferanten
* https://caps.wiki/wiki/Distributors

tools

* https://octopart.com/
<<list-links "[all[current]tagging[]]">>

* https://www.digikey.com/en/maker
* https://www.digikey.de/reference-designs/en
* https://www.eevblog.com/forum/index.php
* https://en.khanacademy.org/science/electrical-engineering
* https://sound-au.com/articles.htm
* https://www.elektronik-kompendium.de/
* Wikipedia
* ~GreatScott!: [[Youtube|https://www.youtube.com/channel/UC6mIxFTvXkWQVEHPsEdflzQ]], [[Instructables|https://www.instructables.com/member/GreatScottLab/instructables/]]
* [[Proof Wood|https://www.youtube.com/channel/UCewU7vV-uVSVCO8Ai1vr6Kw]]
* https://www.youtube.com/c/EevblogDave/playlists
* https://www.youtube.com/user/Afrotechmods
* https://www.youtube.com/user/mikeselectricstuff/videos
* https://www.eevblog.com/wiki/index.php?title=Main_Page
* https://en.khanacademy.org/science/electrical-engineering
* https://www.allaboutcircuits.com/
* https://sound-au.com/articles.htm
* https://www.element14.com/community/welcome
* https://github.com/kitspace/awesome-electronics#readme
* [[Electrical engineering|https://www.youtube.com/playlist?list=PLSQl0a2vh4HCLqA-rhMi_Z_WnBkD3wUka]]
* https://www.electrodragon.com/w/Main_Page
* https://www.youtube.com/c/VoltLog/videos
* https://www.youtube.com/c/TheDefpom/videos
* https://www.youtube.com/hashtag/electronicscreators
* https://eng.libretexts.org/Bookshelves/Electrical_Engineering
<<list-links "[all[current]tagging[]]">>
* https://wiki2.rossmanngroup.com/index.php?title=Main_Page
* https://repair.eu/
* https://www.youtube.com/channel/UCwru3qQ5uCj94QkfMoXw-jQ/channels
* https://www.eserviceinfo.com/
* https://elektrotanya.com/
* https://www.hifiengine.com/manual-library.shtml
* https://www.repair.wiki/w/Repair_Wiki
* https://caps.wiki/wiki/Main_Page
** https://hackaday.com/2022/02/24/caps-wiki-place-for-you-to-share-your-repair-notes/
* https://hackaday.com/category/repair-hacks/
* https://www.youtube.com/user/rossmanngroup/playlists
* https://vinafix.com/ - PC/notebook board schematics and service information
* https://www.youtube.com/c/ActuallyHardcoreOverclocking/playlists - motherboard/gpu knowledge
* [[Kondensatortausch: Kritisch - das solltest Du wissen!|https://www.youtube.com/watch?v=TJtoKx5eGY8]]
* [[Pure Electronics Repair. Learn Methodical Fault Finding Techniques / Methods To Fix Almost Anything|https://www.youtube.com/watch?v=wkAp5x3Z_gc]]
* https://www.s-manuals.com/
* https://www.youtube.com/c/NorthridgeFix
* https://www.youtube.com/user/rossmanngroup
* https://www.youtube.com/c/EevblogDave
* https://www.youtube.com/@LearnElectronicsRepair
** [[More METHODICAL Fault Finding, Samsung LED Monitor Is Faulty & We Have No Schematics. Can We Fix It?|https://www.youtube.com/watch?v=yJnDOG02f1Y]]
** [[The Art Of Methodical Fault Finding - A Practical Example|https://www.youtube.com/watch?v=3vP0YEsBeE4]]
** [Pure Electronics Repair. Learn Methodical Fault Finding Techniques / Methods To Fix Almost Anything|https://www.youtube.com/watch?v=wkAp5x3Z_gc]]
** [[How a PSU With Too LOW Voltage Can Kill Your Electronics Devices! HOW A Buck Converter Works!|https://www.youtube.com/watch?v=KAJbetbyK8Q]]
* https://www.youtube.com/@KrisFixGermany
* https://xdevs.com/fix/
* https://www.youtube.com/@ActuallyHardcoreOverclocking - some in-depth knowledge in pc components
* https://www.youtube.com/@Tronicsfix
* https://elektrotanya.com/content/useful-sites-hasznos-oldalak
* http://studiorepair.com/gallery/index.html
* https://www.youtube.com/watch?v=DWCcWczwfL4
* https://www.youtube.com/watch?v=D7HOE6G97CU
* https://www.allaboutcircuits.com/textbook/direct-current/chpt-3/importance-electrical-safety/
* https://sound-au.com/articles.htm#safl
* see [[Schutzschaltungen / Sicherungen]]
* https://www.instructables.com/Work-safely-with-high-voltage/
* https://de.wikipedia.org/wiki/Kleinspannung
* electronic devices either use a save voltage which is not harmful to humans (and animals) or have to be propperly grounded/earthed or well insulated and shielded so nobody can somehow touch voltage carying components
* fuses are important
* https://www.leifiphysik.de/elektrizitaetslehre/elektrische-grundgroessen/ausblick/stromsicherheit
* https://caps.wiki/wiki/Mains_Power
* [[ground wire explained|https://www.youtube.com/watch?v=JBpQ9Fodz_Q]]
got some amasan T12 from stannol because it got recommended in some audio forums.


thermal conductive foil/tape

i got recommended keratherm 86/60, i don't have much experience with other products

* https://www.kerafol.com/en/thermal-management/produkte-produktuebersicht/kerathermsupr-sup-waermeleitfolien

stuff

* https://www.fischerelektronik.de/web_fischer/de_DE/K%C3%BChlk%C3%B6rper/index.xhtml
* https://www.allaboutcircuits.com/tools/heat-sink-calculator/
* https://www.avnet.com/wps/portal/abacus/resources/article/calculating-led-heatsinks/
* https://www.heatsinkcalculator.com/

LED

* https://www.ledsupply.com/blog/why-you-need-an-led-heat-sink/
* https://www.avnet.com/wps/portal/abacus/resources/article/calculating-led-heatsinks/
* https://www.led-professional.com/resources-1/articles/choosing-the-appropriate-heatsink-for-an-application-by-fischer-elektronik
* https://www.simscale.com/blog/led-heat-dissipation/
* https://en.wikipedia.org/wiki/Thermal_management_of_high-power_LEDs
* https://www.digikey.com/en/articles/led-heat-dissipation-and-lowering-thermal-resistance-of-led-lighting-substrates

thermal paste / compount

* https://www.youtube.com/watch?v=8RJ-vLLwDPU
* https://www.youtube.com/watch?v=WJnrMNCahxc
* https://www.youtube.com/watch?v=8MOTMq9g8Nk
* https://www.youtube.com/watch?v=Glfak2B9J5U
* https://www.youtube.com/watch?v=RMl79Z6_EJA
* https://www.youtube.com/watch?v=75AhrTQWs70
* 
<<list-links "[all[current]tagging[]]">>

stuff

* [[SDG #011 Peak Atlas DCA75 Pro Semiconductor Analyser|https://www.youtube.com/watch?v=CnkdtJRYbXg]]
* [[youtube: Der Elektriker|https://www.youtube.com/channel/UCuaX2rlIYVD5TWMh574Hmiw]] - https://der-elektriker.org/
* https://www.youtube.com/c/ElektroM
* https://www.youtube.com/watch?v=LPP7VMCDZzo
* [[youtube: Elektrotechnik24|https://www.youtube.com/channel/UCnFjB-iXhFTIBHJ5rndwuSw]]
* [[Alles nur freiwillig?! Die Wahrheit über VDE-Normen - Infos zur DIN-VDE|https://www.youtube.com/watch?v=ogEuoywZD_M]]
* https://www.youtube.com/c/EevblogDave/videos
* [[How to do Electrical Wiring properly! (more or less....) GERMAN STYLE!|https://www.youtube.com/watch?v=83Mdnc7FyVY]]
* https://www.ewl-instakit.de/elektroinstallation/
* [[Germans do the PERFECT Electrical Wiring! (Be my Judge)|https://www.youtube.com/watch?v=wsJONukJlLI]]

* Verbinder/Stecker/Buchsen
** [[Welche Klemme brauchst du? Alle Infos zu Leiterarten und Klemmverbindungen aus der Elektrotechnik|https://www.youtube.com/watch?v=adQdTOYEJQE]]
** [[Schuko-Stecker (Schutzkontaktstecker) anbringen|https://www.youtube.com/watch?v=fabjZdANxAw]]
** [[Wago Klemmen - richtige Verwendung/Einsatz|https://www.youtube.com/watch?v=aQsAmU87yr4]]
** [[Wago Klemmen - Typen - Verwendung - Installation|https://www.youtube.com/watch?v=nziW1bnsTsY]]
** [[400V CEE - Steckdose / Kraftstromsteckdose anschließen (Drehstrom)|https://www.youtube.com/watch?v=r7DEw-sLYXQ]]
** [[Crimpen von Aderendhülsen - Hülse auf Litze crimpen / Quetschen / pressen|https://www.youtube.com/watch?v=inwXYxWu7MY]]
** [[400V CEE Verlängerungsleitung erstellen / Verlängerungskabel herstellen / anschließen|https://www.youtube.com/watch?v=iMETpYoP5ek]]
** [[Steckertypen für 230V - Welcher Stecker ist für welches Gerät? - (Schuko, Euro, Kontur, CEE)|https://www.youtube.com/watch?v=2h4bHGYyg5s]]
** [[Connectors are more important than you might think! So which one is the best? (Experiment)|https://www.youtube.com/watch?v=KE3CjZ0BUFo]]
* [[ Klemmdose schnell, sauber und ordentlich verdrahten. Praxis Tipps vom Elektromeister zur Abzweigdose |https://www.youtube.com/watch?v=LPP7VMCDZzo]]

* Kabel-/Leiterarten
** [[Welche Klemme brauchst du? Alle Infos zu Leiterarten und Klemmverbindungen aus der Elektrotechnik|https://www.youtube.com/watch?v=adQdTOYEJQE]]
** [[Typenbezeichnungen von Kabeln/Leitungen - Bedeutung der Buchstaben und Zahlen (NYM-J 3x1,5)|https://www.youtube.com/watch?v=CaVSfSpBkxQ]]
** [[Aderfarben - Bedeutung der einzelnen Leiterfarben|https://www.youtube.com/watch?v=qLy1GRlJuYU]]
** [[Crimpen von Aderendhülsen - Hülse auf Litze crimpen / Quetschen / pressen|https://www.youtube.com/watch?v=inwXYxWu7MY]]
** [[Gefahr durch Steckdosenleiste ?! - Alle wichtigen Infos zu Mehrfachsteckdosen und Sicherheitsrisiken|https://www.youtube.com/watch?v=Qj2OmajRgN8]]

* Netzsysteme / Netzformen
** [[Alle Netzsysteme / Netzformen ausführlich erklärt TT- / IT- / TN-S / TN-C-S-System im Vergleich|https://www.youtube.com/watch?v=pfBbaj9WcBM]]
** [[6.1.3.9 Alle Netzsysteme im Vergleich|https://www.youtube.com/watch?v=W11lDZQ5EgY]]
*** [[6.1.3.8 Das IT-Netzsystem|https://www.youtube.com/watch?v=ob9qqiSnCe4]]
*** [[6.1.4.8 Automatische Abschaltung im IT Netz|https://www.youtube.com/watch?v=-fwnpns1e7o]]
** [[IT-System / Grundprinzip / Netzsysteme / Elektrotechnik / Elektroniker|https://www.youtube.com/watch?v=3_1Yl175ipg]]
* [[Ground Rod Explained|https://www.youtube.com/watch?v=C0iOzmJKOg8]]

* anderes
** [[IP-Code (Schutzart) - Bedeutung der Ziffern (z.B. IP45)|https://www.youtube.com/watch?v=PV32mXhfLbU]]
** [[Schutzklasse 1, 2 und 3 - Unterschied / Bedeutung|https://www.youtube.com/watch?v=hPeVqBTA2Ic]]
** [[Abzweigdose installieren und verdrahten|https://www.youtube.com/watch?v=rdV9bZbl8eQ]]
** [[Funktion und Aufbau - Schütz (und Relais)|https://www.youtube.com/watch?v=J23hzDMcZyw]]
*** [[Schützschaltung - Selbsthaltung|https://www.youtube.com/watch?v=h-6lCR5wY_M]]
*** [[Schützschaltung - Verriegelung von Schützen (Schützverriegelung)|https://www.youtube.com/watch?v=zvRunG2bcLw]]


* https://qelectrotech.org/
* https://learn.libre.solar/development/firmware_frameworks.html
* see [[microcontroller]]
* see [[Real Time Operating System (RTOS)]]
* see [[inter IC or inter device communication, networking]]
* see [[single board computer (SBC)]]


stuff

* https://wokwi.com/
optical linear encoders

* like used in printers
* https://hackaday.com/2009/11/12/linear-optical-encoder/
* www.pyroelectro.com/tutorials/simple_motor_encoder/index.html
* [[ DIY Linear Encoder Slider knob test0 |https://www.youtube.com/watch?v=BwOMmHc1kI4]]
* one can buy some of the encoder strips pretty cheaply

magnetic linear encoders

* with hall sensors?

capacitive/inductive linear encoders

* https://commons.wikimedia.org/wiki/File:Digital_caliper_capacitive_linear_encoder_on_bottom_of_slider.jpg
* https://www.engineerlive.com/content/evaluation-kits-miniature-inductive-encoders

rotary encoder

* https://www.paulvdiyblogs.net/2016/11/demistifying-rotary-encoders-some-more.html
* https://www.paulvdiyblogs.net/2015/12/rotary-encoders-raspberry-pi.html
* https://www.paulvdiyblogs.net/2015/12/demistifying-rotary-encoders.html
* https://en.wikipedia.org/wiki/Rotary_encoder
* https://blog.honzamrazek.cz/2017/07/rotational-encoders-on-the-cheap-the-capacitive-way/
** https://hackaday.com/2017/11/17/diy-capacitive-rotational-encoder-on-the-cheap-with-fr4/
* https://hackaday.io/project/178005-magnetic-rotary-encoder
** https://hackaday.com/2021/03/05/magnetic-angle-sensor-mods-make-encoder-better-for-blasting/
* https://hackaday.com/2021/11/10/3d-printed-absolute-encoder-is-absolutely-wonderful/
Problem:

* very high distortion + noise
listen

* https://opensource.com/tools/enterprise-resource-planning
* related: https://en.wikipedia.org/wiki/Category:Free_business_software
** https://en.wikipedia.org/wiki/Category:Free_ERP_software
** https://en.wikipedia.org/wiki/Category:Free_accounting_software
** https://en.wikipedia.org/wiki/Category:Free_e-commerce_software
** https://en.wikipedia.org/wiki/List_of_ERP_software_packages
* https://geekflare.com/de/open-source-erp-software/
* https://omr.com/de/reviews/contenthub/open-source-erp
* https://softwareconnect.com/erp/open-source/
* https://www.softwaretestinghelp.com/best-erp-software-systems/
* https://www.erpfocus.com/erp-product-comparison.html
* https://www.tryton.org/

software

* https://www.synerpy.de/cm/
* https://metasfresh.com/
* OpenZ
** licence?
** https://sourceforge.net/projects/openz/
** https://openz.de/
* https://ofbiz.apache.org/
* https://www.dolibarr.org/
* https://erpnext.com/
* https://www.odoo.com/de_DE
* https://axelor.com/


ebay / ebay-kleinanzeigen CRM/ERP? bzw. softmware mit ebay integration?


inventory management

* https://partkeepr.org/
** https://github.com/partkeepr/PartKeepr
* https://alternativeto.net/feature/inventory-management/?license=opensource
* Silicon devices
** Sanken 2SC4495
** Sanken 2SD2083
** Sanken 2SB1383
** 3x [[MB10FTR "BRIDGE RECT 1PHASE 1KV 500MA MBF"|https://www.digikey.de/product-detail/de/smc-diode-solutions/MB10FTR/1655-1817-1-ND/7244845]]
** 10x (oder so) [["DIODE GEN PURP 1KV 1A SMA"|https://www.digikey.de/product-detail/de/smc-diode-solutions/S1MTR/1655-1506-1-ND/6022951]]
** 19x BAS20 smd diodes
** 3 oder 4x [[1n4007 Diode|https://www.conrad.de/de/p/vishay-standarddiode-1n4007-e3-54-do-204al-1000-v-1-a-564849.html]]
** 2x LM3886T
* diverse sicherungen
** 4x [["FUSE BRD MNT 1A 250VAC/63VDC RAD"|https://www.digikey.de/product-detail/de/bel-fuse-inc/RSTA-1-BULK/507-1856-ND/4968133]]
* diverse elektronik componenten aller art
* 14V Glühlampen, ca. 5mm durchmesser

* 2x DIN rail mounted Relais Controller with STM32F030F4P6 + ADM2587E RS-485 Transeiver used in a solar installation of a building for remote controll of the battery banks
* different buck/boost converters
* [[Moxa DE-304 "NPort Server Lite"|reverse engineering of Moxa DE-304 "NPort Server Lite"]]
* https://www.moxa.com/en/products/industrial-edge-connectivity/multiport-serial-boards/pcie-upci-pci-serial-cards/cp-104el-a-series
* 2x Hutschiene
* 3x C16 Sicherungsautomat
* 3x B10 Sicherungsautomat
* 400V C2 Doppel-Sicherungsautomat
* 20A Schütz (2 Schließer, 2 Öffner)
* 230V LED Strahler (Bewegungsmelder kaputt und abgebaut)
* diverse Schuko-Steckdosen
* kleiner sicherungskasten
* 2x Klippel Production Analyzer - allerdings ohne Software und co, müsste reverse engineered werden
* often made for RC Vehicles, but also used in other vehicles like Scooters and E-Bikes
* for bigger stuff see [[
* [[LearnMore#3 - The ESCs - Brushless Motors - All Theory You Need To Know About ESCs|https://www.youtube.com/watch?v=erppWLMzw8I]]
* [[Make your own ESC -- BLDC Motor Driver (Part 1)|https://www.youtube.com/watch?v=W9IHEqlGG1s]]
* [[Make your own ESC -- BLDC Motor Driver (Part 2)|https://www.youtube.com/watch?v=NXkLydhRvS0]]
* [[Make your own Sensored ESC -- Electric Bike Conversion (Part 1)|https://www.youtube.com/watch?v=YV-ee8wA5lI]]
* [[Best BLDC Controller: ODrive vs MIT Mini Cheetah vs Moteus (MJBots)|https://www.youtube.com/watch?v=Wb1gsJ4K4pM]]
* https://open-bldc.org/wiki/Open-BLDC
* [[I followed a YouTube Electronics Video and Regret it! (Debunking a 500k video)|https://www.youtube.com/watch?v=SykfLBLP3xI]]
* [[ESC Hardware Design (1/2) - Phil's Lab #66|https://www.youtube.com/watch?v=dJjxcjJOlN0]]
* [[Brushless Motor - How they work BLDC ESC PWM|https://www.youtube.com/watch?v=yiD5nCfmbV0]]


VESC - Vedder ESC - open hardware

** https://vesc-project.com/
** https://vesc-project.com/Hardware
** https://vedder.se/2015/01/vesc-open-source-esc/
** [[VESC (Best Open Source ESC) -- DIY or Buy|https://www.youtube.com/watch?v=SPoMvuRxwFw]]
* https://vesc-project.com/forum/6 - third party hardware

Electronoobs open hardware esc

* https://electronoobs.io/tutorial/1# - open source arduinos ESC
** https://hackaday.com/2019/05/15/an-open-source-esc-for-brushless-motors/
** https://www.open-electronics.org/arduino-sensorless-electronic-speed-controller/
** [[DIY Sensored ESC - full tutorial|https://www.youtube.com/watch?v=G9PHqN9vmVI]]
** [[My ARDUINO ESC - Better update version 3?|https://www.youtube.com/watch?v=-ymTE-Nivzw]]
** [[ESC electronic speed controller with arduino ALL EXPLAINED|https://www.youtube.com/watch?v=8LXPcJD6hEA]]

other electronoobs foc esc

* [[FOC Driver Controller PCB - Slow Brushless Control|https://www.youtube.com/watch?v=zSdetJsSeNw]]

Cheap FOCer (VESC redesign with TO-220 mosfets) - open hardware

* old (V1)
** https://github.com/shamansystems/Cheap-FOCer
** https://endless-sphere.com/forums/viewtopic.php?f=7&t=97699
** https://vesc-project.com/node/706
* current (V2)
** https://github.com/shamansystems/Cheap-FOCer-2
** https://vesc-project.com/Hardware
** https://forum.esk8.news/t/cheap-focer-2-open-source-low-cost-vesc-6-based-esc-v0-9-release-beta-testing-ongoing
* Little FOCer
** https://forum.esk8.news/t/little-focer-84v-5kw-vesc-based-controller/50110
* different modules
** https://forum.esk8.news/t/some-new-focers-84v-vesc-6-based-controllers/1513 - old thread
* in development (V3)
** https://forum.esk8.news/t/cheap-focer-3-open-source-low-cost-vesc-6-based-esc-in-development/67432/48

cheap chinese controller

* https://de.aliexpress.com/item/4001142532908.html
* speed input and speed output
* using them with a cheap controller might be useful to make cheap ebike motor controllers
* FOC versions available?


commercial

* https://flipsky.net/collections/electronic-products - Flipsky VESC or ODrive clones from china

* ODrive
** https://odriverobotics.com/
** https://flipsky.net/collections/od-drive
** https://github.com/odriverobotics/ODrive

* https://vesc-project.com/Hardware

stuff

* https://hackaday.com/2015/10/01/open-source-esc-developed-for-longboard-commute/
* small bike-motor controller/inverter (kt36zwst-xfc06d2?)
** 3 phase, normal 10s Li-Ion battery supply (~30-42V, 36V nominal)
** trottle controll connection (just a potentiometer with 5V supply
** PAS (pedal sensor)  connection
** 3 sense lines for hall sensors mounted inside the motor, supplied with ~5V
** maybe a display connection?
** STM8S105
** 6x STP110N7F6 (2 for each phase) in an H-Bridge
*** https://www.st.com/en/power-transistors/stp110n7f6.html
* https://oscarliang.com/esc-firmware-protocols/
* [[regenerative breaking (rekuperation)]]
* [[What is FOC? (Field Oriented Control) And why you should use it! -- BLDC Motor|https://www.youtube.com/watch?v=Nhy6g9wGHow]]
* https://www.youtube.com/watch?v=Y16kbAK3vaU
* https://hackaday.com/2022/07/04/moteus-open-source-bldc-controller-gets-major-upgrade/
* https://hackaday.com/2021/07/07/simplefoc-demystifies-precision-bldc-motor-control/
* https://hackaday.com/tag/bldc-controller/
* https://hackaday.com/tag/bldc/
* [[My open source Arduino ESC - BEMF zero-cross|https://www.youtube.com/watch?v=VdkloigaxZo]]
* [[How to control a BLDC with an Arduino|https://www.youtube.com/watch?v=qOzE5F5vFGs]]
* [[Arduino DC Motor mit MOSFET H-Brücke steuern - Einstellbare Drehrichtung & Geschwindigkeit|https://www.youtube.com/watch?v=13bCzydTz8I]]
* https://forum.esk8.news/t/escs-based-on-the-vesc/60389
* https://community.simplefoc.com/t/linear-bldc-using-simplefoc/139
** https://github.com/Juanduino/THE-DIMMER_M4SDRV_V1
* https://github.com/Juanduino/Beefy-BLDC-3phase-Powerstage-T4
* [[Field Oriented Control of Permanent Magnet Motors|https://www.youtube.com/watch?v=cdiZUszYLiA]]
* https://hackaday.com/2021/02/08/hands-on-the-risc-v-esp32-c3-will-be-your-new-esp8266/
* https://hackaday.com/2023/09/07/how-small-can-the-esp32-get/


stuff

* https://www.youtube.com/watch?v=m6njN9Y7PF0
* https://www.youtube.com/watch?v=yxU_Kw2de08
* https://www.youtube.com/watch?v=hJSBTFsOnoA
* https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
* https://hackaday.io/project/164477-esp32-guitar-shield
* also see [[ESP32 high-quality audio transmitter]]
* https://hackaday.io/project/162628-audio-delay-and-vox-using-esp32
* https://hackaday.io/project/18294-esp32-audio-recorder
* https://hackaday.io/project/170710-esp32-tnc-and-audio-relay-for-hfvhf-packet-radio
* https://hackaday.io/project/165919-yummydsp
* https://hackaday.io/project/165365-eurorack-audio-synthesis-platform
* https://hackaday.io/project/171475-diy-sw-mw-sdr-radio-with-esp32-and-si5351
* https://hackaday.io/project/20160-super-pure
* https://hackaday.io/project/170911-ctag-tbd-open-source-eurorack-synthesizer-module
* https://hackaday.io/project/46280-muffsy-stereo-relay-input-selector
* https://hackaday.io/project/171566-wifi-balanced-audio-volume-control
* https://hackaday.io/project/167081-linki
* https://hackaday.io/project/166867-esp32-i2s-slm - sound level meter
* https://www.youtube.com/watch?v=afBSpobG6Zo
* https://hackaday.com/2015/06/06/esp8266-as-a-networked-mp3-decoder/
* https://www.hackster.io/janost/audio-hacking-on-the-esp8266-fa9464
* ''[[ #419 ESP32 Audio Tutorial with lots of examples |https://www.youtube.com/watch?v=a936wNgtcRA]]''
* https://espressif-docs.readthedocs-hosted.com/projects/espressif-esp-iot-solution/en/latest/usb/usb_stream.html
* https://www.aksevenfour.com/picoaudio.html
* https://hackaday.com/2019/10/06/professional-audio-on-an-esp32/
arduino setup:

* installing arduino IDE
* `pip install pyserial`
* https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/boards_manager.md
* aditionally for esp8266: https://arduino-esp8266.readthedocs.io/en/latest/installing.html#boards-manager

esp-idf setup:

*
* https://learn.sparkfun.com/tutorials/using-artnet-dmx-and-the-esp32-to-drive-pixels/all
* https://learn.sparkfun.com/tutorials/sparkfun-esp32-dmx-to-led-shield/all
* https://reference.arduino.cc/reference/en/libraries/esp_dmx/
** https://registry.platformio.org/libraries/someweisguy/esp_dmx
** https://github.com/someweisguy/esp_dmx
* https://www.reddit.com/r/WLED/comments/13yk6e1/dmx_output/
* https://github.com/Rickgg/ESP-Dmx
* https://github.com/harryprayiv/ESP32-DMX
* https://forum.arduino.cc/t/dmx-mit-dem-esp32/953023
* https://wled.discourse.group/t/dmx-out/3483
* https://github.com/mtongnz/espDMX
* https://esp32.com/viewtopic.php?t=15599
* https://esp32.com/viewtopic.php?t=33699
* https://www.digikey.de/en/maker/projects/sparkfun-esp32-dmx-to-led-shield/560d33ea7da84cfa9f015f338762a8e8
* https://www.tindie.com/products/inpublic/esp32-2-universe-dmx-breakout-board/
* https://github.com/claudeheintz/LXESP32DMX
* https://github.com/cansik/esp-dmx-max485
* https://github.com/jostlowe/Pico-DMX
* https://github.com/tinic/ESP32_ArtNetNode
* https://github.com/rstephan/ArtnetWifi
* https://github.com/chaosloth/Connotron_DMX_Gateway
* https://forum.dmxcontrol-projects.org/index.php?thread/14159-artnet-addressing-to-output-dmx-universes-on-esp32-dmx-modules/
* https://www.instructables.com/ESP8266-Artnet-to-DMX/
* https://forum.arduino.cc/t/help-dmx-signal-via-esp32-wifi-and-artnet/1063143
* https://www.instructables.com/ESP8266-Artnet-to-DMX/
Intro:

* [[Building a Digital Music Player with I2S?! What is I2S! EB#45|https://www.youtube.com/watch?v=qNLvoSQCx60]]
* [[Coding a Sound Driver on the ESP32 ULP|https://www.youtube.com/watch?v=6PGrsZmYAJ0]]
* [[AM Radio Transmitter on ESP32|https://www.youtube.com/watch?v=lRXHd3HNzEo]]
* [[#195 DIY Internet Radio using an ESP32 (Arduino IDE)|https://www.youtube.com/watch?v=hz65vfvbXMs]]
* https://www.edn.com/common-inter-ic-digital-interfaces-for-audio-data-transfer/

Parts:

* [[Wemos D32 Pro (ESP32-WROVER)|https://www.wemos.cc/en/latest/d32/d32_pro.html]]
** you can also use other devboards, i liked this one
* PCM5102A Board (32-bit, 384 kHz Stereo DAC) - [[Datasheet|https://www.ti.com/lit/ds/symlink/pcm5102a.pdf]]
** Pins required
*** VCC - 5V Supply, not needed if you supply 3.3V directly (there is a voltage regulator stepping it down to 3.3V)
*** 3.3V - 3.3V supply, not needed if you supply 5V on VCC
*** GND - Ground
*** SCL / SCK - System clock input
*** BCK - Audio data bit clock input
*** DIN - Data/Digital In - Audio data input
*** LCK / LRC / LRCK / WS - Audio data word clock input
** Pins optional on some boards (have pre-bridged jumpers)
*** FLT - Filter select: Normal latency(Low) / Low latency (High)
*** DMP / DEMP - De-emphasis controlfor 44.1-kHz sampling rate: Off (Low) / On (High)
*** FMT - Audio format selection: I2S (Low) / Left-justified (High)
*** XMT / XSMT - Soft mute control: Soft mute (Low) / soft un-mute (High)
* PCM1808 Board (24-Bit, 96-kHz Stereo ADC) - [[Datasheet|https://www.ti.com/lit/ds/symlink/pcm1808.pdf]] - [[product page|https://www.ti.com/product/PCM1808]]

information on PCM:

* https://homedjstudio.com/audio-bitrates-formats/
* https://wiki.multimedia.cx/?title=PCM

Wiring:

* PCM5102A
** Vcc or 3.3.V - pretty obvious
** Ground - pretty obvious
** SCL -> Ground
** BCK -> e.g. GPIO26
** DIN -> e.g. GPIO25
** LCK -> e.g. GPIO22
** FLT -> Ground?
** DMP -> Ground?
** FMT -> Ground
** XMT -> connected to 3.3V through 10kOhm resistor (might be switchable with Ground, to soft-mute/soft-unmute the resceiver)

the ADCs and DACs of the ESP32 are not that great for audio (12bit ADCs [[(Source)|https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html]], 8bit DACs [[(Source)|https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/dac.html]], (stuff in de: [[[1]|http://esp32-server.de/adc/]], [[[2]|https://ckblog2016.net/2018/03/03/esp32-adc-dac/]])), so i'll use I²C.

high-quality examples of the esp-idf library using I2S and audio streaming:

* https://github.com/espressif/esp-idf/tree/master/examples/peripherals/i2s - sending tones
* https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/classic_bt/a2dp_source - bluetooth a2dp sender
* https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/classic_bt/a2dp_sink - bluetooth a2dp receiver

Getting started:

* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html
* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/establish-serial-connection.html
* https://github.com/espressif/esp-idf/tree/7d75213674b4572f90c68162ad6fe9b16dae65ad/examples/bluetooth/bluedroid/classic_bt/a2dp_sink
* https://github.com/esp32vn/esp32-a2dp-sink
* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/bluetooth/esp_a2dp.html
* https://esp32.com/viewtopic.php?t=2159

some existing esp32 or esp8266 audio streaming projects:

* https://hackaday.io/project/93838-esp32-bluetooth-a2dp-src
* https://hackaday.io/project/166122-esp32-as-bt-receiver-with-dsp-capabilities
* https://hackaday.io/project/18294-esp32-audio-recorder
* https://hackaday.io/project/168354-esp32-based-internet-radio-and-bluetooth-speaker
* https://hackaday.io/project/49280-wirelessstandalone-headset-audio-device
* https://hackaday.io/project/167081-linki
* https://github.com/geeksville/Micro-RTSP
* https://esp32.com/viewtopic.php?t=131
* https://www.toptal.com/embedded/esp32-audio-sampling
* https://hackaday.com/2019/10/06/professional-audio-on-an-esp32/
* https://github.com/vedranMv/Ka-Radio32
* https://github.com/chunter1/ESP8266_WLAN_speaker
* https://www.esp8266.com/viewtopic.php?t=13285
* https://www.reddit.com/r/esp8266/comments/4rm7po/audio_streaming_with_esp8266/
* https://hackaday.com/2016/07/15/baby-monitor-rebuild-is-also-esp8266-audio-streaming-how-to/
* https://www.hackster.io/tliero/wifi-doorbell-with-esp32-and-dfplayer-1fa367
* https://www.esp32.com/viewtopic.php?t=4261
* https://www.esp32.com/viewtopic.php?t=4683
* https://www.hackster.io/julianfschroeter/stream-your-audio-on-the-esp32-2e4661
* https://github.com/thinpv/wifi-speaker
* https://github.com/smurf0969/ESP32_ESP8266_WiFi_Speaker_OLED
* https://hackaday.com/2022/09/14/esp32-adds-bluetooth-to-an-ipod-nano/
* ''[[ [#10] DIY DSP Bluetooth Speaker with ESP32 |https://www.youtube.com/watch?v=_nCOluMHfGI]]''

streaming the audio

* https://duckduckgo.com/?q=esp32+stream+WAV&t=ffab&ia=web
* WAV files use PCM just like I²S
* [[Audio streaming]]
* RTP/RTSP (+RTCP)
* https://www.esp8266.com/viewtopic.php?t=6640
* https://www.3cx.de/voip-sip/rtp/
* https://de.wikipedia.org/wiki/Real-Time_Transport_Protocol
* https://www.elektronik-kompendium.de/sites/net/1106071.htm

Libraries:

* https://github.com/espressif/esp-adf
** https://docs.espressif.com/projects/esp-adf/en/latest/get-started/index.html#
* https://github.com/earlephilhower/ESP8266Audio

I²S Interfaces:

* Both I2C periherals are fully routable via the GPIO matrix, so you should be able to connect your codec to any GPIO pin (that is output-capable, for pins where you want to output a signal) [[(Source)|https://esp32.com/viewtopic.php?t=357]]
* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2s.html
* i2s debug
** https://esp32.com/viewtopic.php?t=8234
** https://www.i2c-bus.org/i2c-primer/common-problems/
** https://www.microforum.cc/blogs/entry/42-the-problems-of-i2c-common-problems-and-errors-with-using-i2c/
** https://hackaday.com/2016/07/19/what-could-go-wrong-i2c-edition/
https://github.com/meetri/esp32-i2s-audio-test/tree/master/components/minmax

increasing signal range

* ESP32 has 18 to 20.5dBm transmission power https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf#21
* you can get bigger antennas with higher gain, like 10dBi, but you need to get an ESP32 module with a U.FL (I-PEX MHF, IPAX, IPX, AMC or UMCC) connector
* not all esp32 modules with an U.FL connector have the connector actually connected, so check before with the seller
* you might be able to calculate the range with tools like: https://www.rfwireless-world.com/calculators/WLAN-range-calculator.html
* you can get RF amplifier modules from alibaba or similar shop platforms, but they might be illegal were you live
only esp32 have this option, esp8266/esp8285 do not support it

ws2812 protocol

* https://www.arrow.com/en/research-and-events/articles/protocol-for-the-ws2812b-programmable-led

different rmt drivers

* https://lib.rs/crates/ws2812-esp32-rmt-driver
* https://github.com/codemee/esp32_rmt_pwm
* https://github.com/bertmelis/esp32WS2811
* https://github.com/espressif/esp-idf/blob/master/examples/peripherals/rmt/led_strip/README.md

library stuff

* https://docs.micropython.org/en/latest/esp32/quickref.html#rmt
** https://docs.micropython.org/en/latest/library/esp32.html#esp32-rmt
* https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf - chapter 15
* https://github.com/espressif/esp-idf/blob/master/docs/en/api-reference/peripherals/rmt.rst
* https://pycom.github.io/pydocs/tutorials/all/rmt.html
** https://pycom.github.io/pydocs/firmwareapi/pycom/machine/rmt.html
* https://esp-cpp.github.io/espp/rmt.html
* https://docs.espressif.com/projects/arduino-esp32/en/latest/api/rmt.html
* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/rmt.html#rmt-encoder
** https://espressif-docs.readthedocs-hosted.com/projects/esp-faq/en/latest/software-framework/peripherals/rmt.html

parse/read/sample

* https://esp32.com/viewtopic.php?t=27561
* https://github.com/kimeckert/ESP32-RMT-Rx-raw
* https://stackoverflow.com/questions/56127996/how-to-receive-long-data-frame-by-esp32-rmt-ringbuffer

send & read

* https://github.com/ExploreEmbedded/ESP32_RMT
* https://hackaday.io/project/177672-esp32-rmt-peripheral-for-radio-remote-control
* https://github.com/espressif/esp-idf/tree/release/v5.0/examples/peripherals/rmt/onewire
* https://github.com/espressif/esp-idf/tree/master/examples/peripherals/rmt/ir_nec_transceiver

stuff

* https://esp32.com/viewtopic.php?t=26659
* https://esp32.com/viewtopic.php?t=296
* https://duckduckgo.com/?q=esp32+rmt+receiver
* https://esphome.io/components/light/esp32_rmt_led_strip.html

* https://en.wikipedia.org/wiki/EUR-pallet
* https://de.wikipedia.org/wiki/Europoolpalette
* https://de.wikipedia.org/wiki/Kleinladungstr%C3%A4ger
* https://en.wikipedia.org/wiki/Euro_container
* https://www.auer-packaging.com/de/de/Stapelbeh%C3%A4lter.html
* many cargobikes and many bike trailers adopt the footprint of euro boxes
* https://www.surplus-systems.de/ - bad website, amazon shop not found?
* alutec
* verschiedene baumärkte abklappern
* https://www.utzgroup.de/
* https://www.ifco.com/de/unsere-produkte/
* https://wibo-group.com/
* https://www.alutec.net/produkte/kunststoffbehaelter/
* https://www.keeeper.com/produktwelt/storage/euro-boxen/ - stupid proprietary dimensions that probably don't fit normal euro containers
** https://www.keeeper.com/produkt/bruno-eco/
* https://www.tbs-online.de/de/de/Betriebsausst/Werkzeugaufbewahrung/TBS-Boxx%C2%AEen-System/TBS-Transportboxen/Transportbox-TBS-schwarz-mit-transparentem-Deckel-St%C3%BCckweise-oder-VPE-sid141681.html#
the idea was to design a shelve made of stacked euro boxes for storing smaller items. each box having a cutout but with an optional panel to close the box for transport.
i had the idea of a normal [[19" Rack|19" Rack, cases]] build inside a box the size of a standard [[euro container|euro container / Eurokiste / Kleinladungsträger]]. it's supposed to house normal 19" rack equipment, mainly for PA purposes, but be in a different format for easy transportation with cargobike and maybe house an inverter or other stuff.

* equipment depth (of the fist page of amps at thomann) is up to 480mm, not accompanying connectors... so a lot of 19" equipment is to big... eurorack or 10" rack equipment fits better inside 600x400cm
* https://en.wikipedia.org/wiki/Eurorack
* Construction: http://www.doepfer.de/a100_man/a100m_e.htm
* the Eurorack is based on the [[Eurocard|https://en.wikipedia.org/wiki/Eurocard_(printed_circuit_board)]], which is based on the [[19" Rack|19" Rack, cases]] standard, so you can mount Eurorack modules inside every 19" rack requiring only additional horizontal mountingrails
* https://en.wikipedia.org/wiki/Horizontal_pitch
* see [[API 500 System]]

* "eurorack rail" on ebay
* thoman has https://www.thomann.de/de/behringer_eurorack_rack.htm
** its to expensive for me, the main parts can be picked up from ebay for cheaper an i can manufacture my own eurorack rail/rack in a local workshop
* https://de.wikipedia.org/wiki/Baugruppentr%C3%A4ger
* https://www.graylands.ca/the-compound/recording/interface/event-echo-gina20-audio-interface/
* https://www.pinterest.de/pin/event-echo-gina-24-bit-sound-card--373306256591690000/
* https://en.audiofanzine.com/pci-isa-rack-soundcard/echo/Gina/
* the soundcard is missing, only the connection-box is still there
* instead of the Event Echo card i've got a blackmagick soundcard but it's probably not compatible
wie kann man lokale events/veranstaltungen/termine/demos zu gewissen themen (z.b. nachhaltigkeit/umwelt/klima) am besten automatisch aggregieren?

https://gruenesbrett.net/ - sehr manuell

bei zukunftstadt war was ähnliches

Probleme:

* viele verschiedene plattformen/kanäle als quellen (asoziale medien (twitter, facebook und co), verschiedene webseiten, ...)
* bisher in telegram kanälen und webseite (grünes brett) manuell gelöst

Ideen:

* Netzwerk n: nein, da müssten sich alle anmelden, es soll ein öffentlicher kalender werden
** fragwürdige plattform, wechange? kommerziell?
** schlechte usability
* activity pub als basis sonst ist es auch nur inkompatibel
* https://www.linux-magazin.de/ausgaben/2014/01/bitparade/
* APIs der platformen nutzen
* webseiten parsen
* platform anbieten, eigene seite zum eintragen (manuell ist doof)
* APIs einbauen in webseiten? CalDav, WebCal, [[iCal|https://en.wikipedia.org/wiki/ICalendar]]?
** könnte dann von orgas/inis selbst geadded, vom admin approved werden und wäre ziemlich simpel
* wenn alles automatisch gesammelt wird ist das automatische senden/publishing auf verschiedenen kanälen ziemlich einfach
* https://github.com/fsr/propaganda
* https://www.quora.com/Are-there-any-good-websites-that-provide-social-media-aggregation-cloud-email-content-and-search-aggregation-in-one-platform
* https://xylusthemes.com/plugins/wp-event-aggregator/
* https://www.quora.com/How-can-I-aggregate-relevant-local-events-from-Meetup-Facebook-LinkedIn-independent-websites-etc-into-one-calendar-without-manual-searching-for-and-entering-in-content?share=1
* https://en.wikipedia.org/wiki/Semantic_Web#Challenges
* https://www.zukunftsstadt-dresden.de/projekte/a18/
** https://www.zukunftsstadt-dresden.de/projekte/h7/
Vorwissen

* https://de.m.wikipedia.org/wiki/L%C3%B6schmittel
* https://de.m.wikipedia.org/wiki/Brandklasse
* https://de.m.wikipedia.org/wiki/L%C3%B6schpulver#D-L%C3%B6schpulver

Infos

* https://de.wikipedia.org/wiki/Lithium-Ionen-Akkumulator#Gefahren_beim_Umgang_mit_Lithium-Ionen-Akkus
* Metallbrandpulver wird von diversen Firmen explizit für Lithium akkus vermarktet, ist aber nicht zwingend, denn in den akkus kommt eig. kein handelsübliches lithium vor. Wichtiger ist es auf die Elektrolyten und den Kunststoff zu achten. (https://www.dguv.de/medien/fb-holzundmetall/sachgebiete/fahrzeug/elektromobilitaet/faq_elekro.pdf)
* https://lifehacker.com/how-to-extinguish-a-battery-fire-1822040010
* https://resources.impactfireservices.com/how-do-you-put-out-lithium-ion-battery-fire
* https://electronics.stackexchange.com/questions/223245/what-type-of-fire-extinguisher-do-i-need-for-lithium-polymer-batteries
* https://help.orf.at/stories/3203081/

Löschversuche bzw. Tests

* Playlist von Feuerwehr.at: https://www.youtube.com/watch?v=4FNs0jLW1vw&list=PL9WXJsXjnOjmN_N_pzqziZr_YP5tUe4ws
* https://www.youtube.com/watch?v=4ybZMzA-SX8 (maybe biased, hersteller von metalllöschpulver)

Feuersichere Behältnisse
* metallboxen?
paar F-Droid App Empfehlungen von bekannten zusammengetragen (habe ich noch nicht alle getestet)

* Alarmio - schicker Wecker
* Amaze - Dateimanager
* ~AntennaPod - Podcasts hören
* ~BatteryBot Pro - Batterietool
* Document Viewer - PDF Viewer
* ~FairEmail - Mailclient
* statt fairmail lohnt sich auch K9 Mail
* ~FitoTrack - Fittnesstracking nur per Sensoren und GPS
* ~ImagePipe - Macht Bilder vor dem Teilen kleiner und entfernt EXIF-Daten
* OSMand+ - Offlinenavigation, Karten sind detailierter als Google Maps (siehe Zoo)
* ~NewPipe - Youtube ohne Werbung mit Bildschirm aus und Download als Video oder Audio (Bedienung gewöhnungsbedürftig, aber lohnt sich!)
** kann neben youtube auch soundcloud und bandcamp (beide cool für musik) und framatube/peertube
* Nextcloud - Nextcloud Client (wenn mensch eine nextcloud hat)
* Nextcloud Notes - wenn man die Notes App nutzt
* QKSMS - SMS App mit export, import, zeitversetztes senden etc...
* ~RadioDroid - Internetradio
* Schlichte Galerie Pro - (Simple Gallery) finde ich bequemer zu bedienen als die Originale
* ~SecScanQR - QR Code Scanner
* Syncthing-Fork - Syncthing
* Zapp - deutsche ÖR Mediatheken Videos gucken und downloaden und so
* VLC app ist auch nicht schlecht
* mpv - für manche vlt. angenehmer als vlc zu nutzen
* "Jeden Tag ein Set" ist was für freunde der elektronischen musik, super in verbindung mit newpipe
* keepassdx ist auch praktisch
* adaway
* https://molly.im/ - Molly ist ein signal Fork der einige Features die entfernt wurden noch beinhaltet.
* https://f-droid.org/en/packages/app.organicmaps/ - kennt wohl viele gute wege, u.a auch viele schleichwege für radfahrer
* https://f-droid.org/packages/org.secuso.privacyfriendlyweather/
<<list-links "[all[current]tagging[]]">>

* https://de.wikipedia.org/wiki/Fahrrad
** https://de.wikipedia.org/wiki/Fahrrad#Konstruktion
* https://de.wikipedia.org/wiki/Kategorie:Fahrradbauteil

stuff with bicycles

* https://www.stadtradeln.de/
* https://de.wikipedia.org/wiki/Fahrradfreundliche_Kommune
* https://de.wikipedia.org/wiki/Fahrradklimatest
* https://de.wikipedia.org/wiki/Fahrradstadt
* https://de.wikipedia.org/wiki/Copenhagenize_Index#Rangliste
* ADFC
* [[Building an Electric Bike|https://www.youtube.com/watch?v=1pm1RtCuE3A]]
* https://hackaday.com/?s=bike
* https://dein-lastenrad.de
* http://www.nutzrad.de/?seite=kat

* https://www.wired.com/2010/12/diy-cargo-bike-mods/
*http://www.copenhagencyclechic.com/2016/12/diy-cargo-bike-whats-that-like.html
* [[Electric Bike Conversion (Part 3) ~ Final Assembly & Test Ride|https://www.youtube.com/watch?v=ALU8j7BTXnI]]
* https://www.radwatch-dresden.de
* https://mitxela.com/projects/qr_stem
* https://verschwoerhaus.de/tag/fahrrad/


Reifen und co

* https://www.schwalbe.com/technik-faq/
* https://www.youtube.com/watch?v=zCrs7bFOg_s - Felgenband
* https://de.wikipedia.org/wiki/Fahrradbereifung#Reifen-_und_Felgengr%C3%B6%C3%9Fen
* https://de.wikipedia.org/wiki/Fahrradfelge#Gr%C3%B6%C3%9Fen
* https://www.fahrradmonteur.de/Formelsammlung#Reifen-_und_Laufradgr%C3%B6%C3%9Fen
* https://www.fahrradmonteur.de/Fahrradreifen_und_-schl%C3%A4uche
* https://www.fahrradmonteur.de/Reifengr%C3%B6%C3%9Fen
* https://www.schwalbe.com/schlauchsuche/
* https://www.radforum.de/threads/3027865-hilfe-bei-der-richtigen-fahrradschlauch-wahl - die nummer gibt bei schwalbe die dicke des gummis und damit auch die dehnbarkeit an
* https://www.schwalbe.com/Marathon-Plus-11100770
* https://www.schwalbe.com/files/schwalbe/userupload/Images/FAQ/Felgenband.pdf
* https://www.schwalbe.com/files/schwalbe/userupload/Images/FAQ/reifen_felgen_2020/Reifen_Felgenkombinationen_2020-06_DE.pdf
* https://www.radforum.de/threads/385626-felgenband-breite-herausfinden-ohne-reifen-zu-demontieren
* https://www.velonerd.cc/
*


material

* bike24.de
* fahrrad.de?
* https://www.grofa.com/de/


elektronik

* SON dynamos, kabel ?
* shimano dynamos
hier geht es erstmal nicht um ein-achsige, - spurige, -rädrige fahrradanhänger.

* Hochdeichsel
** Kugelkopf-Anhängerkupplung, an sattelstütze oder gepäckträger
** haerry (z.b. carla cargo)
* Tiefdeichsel (kupplung an hinterradnarbe)
** Kreuzgelenk
** Blue Bird
** Weber
** Chariot
** Burley



stuff

* https://www.hinterher.com/News.php paar designs november 2018 rum
* http://fahrradkino.org/
* https://fahrradkino-chemnitz.de/
* https://oekotrainer.de/ (Leipzig)

components:

* bike-stands
* generators attached to stands with a friction wheel or so
* generator MPPT (maximum power point tracker)
* battery (with charge controller) as buffer
* inverter

stuff

* https://hackaday.com/2015/05/10/a-pedal-powered-cinema/
* https://media.ccc.de/v/rc3-channels-2020-97-aktiv-werden-fr-faire-elektronik-
I got myself a used Fairphone 3+ as replacement for my old Nexus 5.

some android stuff for Fairphone 3:

* if you want to use TWRP: fairphone/fairphone3.html
* MicroG-LineageOS:
** https://download.lineage.microg.org/FP3/
** 
* https://www.youtube.com/watch?v=FglBi4-ddcE
* https://hackaday.com/2022/02/05/how-to-spot-a-fake-op-amp/
* https://en.wikipedia.org/wiki/Fast_Fourier_transform
* https://de.wikipedia.org/wiki/Schnelle_Fourier-Transformation
* [[ Understanding FFT in Audio Measurements |https://www.youtube.com/watch?v=bqGjh67x7IU]]
* [[But what is the Fourier Transform? A visual introduction.|https://www.youtube.com/watch?v=spUNpyF58BY]]

uses

* [[open source spectrum analysis software]]
* [[frequency response / spectrum analysis / Measurements]]
* [[frequency response webapp]]

inverse/reverse

* https://de.wikipedia.org/wiki/IFFT
* mastodon - https://joinmastodon.org/
** https://schwarzerpfeil.de/2020/12/08/mastodon-guide-leitfaden/
** https://dresden.network/ - for people local to dresden
** https://moa.party/
* GNU Social - https://gnu.io/social/
* Diaspora
* https://pleroma.social/
* ~ActivityPub - a great protocol commonly used
* https://join-lemmy.org/
<<<
for f in *.mp3; do ffmpeg -i "$f" "$(basename $f).wav"; done
<<<

* https://askubuntu.com/questions/919788/convert-mp3-file-to-wav-using-the-command-line
* https://wiki.ubuntuusers.de/FFmpeg/
info

* https://www.manualslib.de/manual/270789/Fidek-Fpa-10A.html
* http://www.hifi-forum.de/themen/produkte/fidek/fpa-10-a
* https://paforum.de/forum/index.php?thread/115950-verst%C3%A4rker-fidek-fpa-10a/
* kingsman
* https://www.instructables.com/
* https://hackaday.com/
* https://hackaday.io/
* https://de.oho.wiki/wiki/Home
* https://en.wikipedia.org/wiki/List_of_open-source_hardware_projects
* https://en.wikipedia.org/wiki/Open-source_hardware#Find_open-source_hardware_products
* https://wikifactory.com/discover/topics
* https://www.open-electronics.org/
* ~~https://en.oho.wiki/wiki/Home~~ - not really useful, a lot of crap... its a kind of search engine but totally unmoderated and its scraping a lot of bad, not open projects, tutorials and "life hacks"
* https://www.hackster.io/ - having to log in to actually view projects is shit and excludes people
* https://github.com/sindresorhus/awesome#hardware
* https://certification.oshwa.org/directory.html
* https://www.openhardware.io/explore
* https://en.wikipedia.org/wiki/List_of_open-source_hardware_projects
* https://www.appropedia.org/Welcome_to_Appropedia

other 

* https://wiki.fablab-muenchen.de/pages/viewpage.action?pageId=688954
* github
* gitlab
* https://alternativeto.net/
* https://github.com/topics/awesome
* https://github.com/sindresorhus/awesome
** https://github.com/sindresorhus/awesome#related
* https://awesomeopensource.com/
* https://www.fosshub.com/ ?
* https://osdn.net/ ?
* https://opentoolchain.org/tools/
* searching patents
** https://alternativeto.net/software/patent-monk/
* long searching
*  [[Understanding the Finite Element Method|https://www.youtube.com/watch?v=GHjopp47vvQ]]
* [[ Understanding Failure Theories (Tresca, von Mises etc...) |https://www.youtube.com/watch?v=xkbQnBAOFEg]]
* https://github.com/tankywoo/simiki
* https://docs.readthedocs.io/en/stable/index.html
* using a normal static site generator for wiki/documentation like tasks probably needs a lot of setup and special templates

sadly pretty dynamic:

~~* gollum
** https://github.com/gollum/gollum
** https://en.wikipedia.org/wiki/Gollum_Wiki
** https://de.wikipedia.org/wiki/Gollum_Wiki
* dokuwiki
** https://www.dokuwiki.org/dokuwiki
** https://de.wikipedia.org/wiki/DokuWiki
* ~MoinMoin
** https://en.wikipedia.org/wiki/MoinMoin~~

lists:

* https://en.wikipedia.org/wiki/List_of_wiki_software#Hosted-only_software
* https://en.wikipedia.org/wiki/Comparison_of_wiki_software
* https://www.wikimatrix.org/search

more like notes / knowledge bases

* ~~https://obsidian.md/~~ closed source
* https://foambubble.github.io/foam/
* https://zettelkasten.de/introduction/
* https://www.zettlr.com/
* https://de.wikipedia.org/wiki/Brennstoffzelle
* https://en.wikipedia.org/wiki/Fuel_cell
* https://de.wikipedia.org/wiki/Elektrolyseur
* https://en.wikipedia.org/wiki/Electrolysis_of_water
** https://en.wikipedia.org/wiki/Polymer_electrolyte_membrane_electrolysis
* "open source" fuel cell car
** the company does't do open designs anymore it seems, the 40 fires foundations website which hosted parts of the open designs isn't awailable any more (only the archived version can still be found)... the drivetrain and electronics don't seem to have been open anyways
** https://en.wikipedia.org/wiki/Riversimple_Urban_Car
** https://web.archive.org/web/2020*/40fires.org
* ein komplettes system besteht aus Elektrolyseur -> Kompressor -> spezieller Wasserstofftank -> Brennstoffzelle und zusätzlich oft einem Akku oder Supercaps als puffer
* https://wiki.opensourceecology.org/wiki/Microbial_Fuel_Cells
* toyota reportedly opened their patents (~5600) around fuel cells and fuel cell cars, but i don't know how to find them and how open these patents really are

development software:

* https://www.sciencedirect.com/science/article/abs/pii/S0010465515003872
* https://openfuelcell.sourceforge.io/
* http://www.openfcst.mece.ualberta.ca/
I got a used, waterproof flourescent tube-style LED lamp that would not turn on. It would be great to have it for [[Werkstadtpirat:innen]].

I checked the fuse of the LED driver and it was open/blown. Then i checked the bridge recktifier and it was shorted on all pins.
I had the same parts left over from other projects, a small through-hole T2A Fuse and a MB10F bridge rectifier. It seems this type of rectifier is common, but also prone to be faulty (but that might just be a bias)
I changed the parts out, reassembled the lamp and tested it. The lamp is working fine again.
not a battery by the definition, stores energy as kinetic energy in a spinning disc, can be connected to a generator/motor to store and retrieve energy. has to spin with high speeds to be most efficient, hard to manufacture, has to be very balanced for the used speeds. in professional installation often suspended by magnetic bearings and in a vacuum not loose as little energy as possible.

* https://en.wikipedia.org/wiki/Flywheel_energy_storage
** https://de.wikipedia.org/wiki/Schwungradspeicherung
** https://diysolarforum.com/threads/flywheel-energy-storage.9384/
* https://www.youtube.com/watch?v=gahKxbwUcYw
* [[How To Make a Cheap Fog Machine 10 Times More Powerful|https://www.youtube.com/watch?v=AxEL3eESL9I]]
* "nebelfluid feuerwehr extra"
!! Problems:

* missing wireless microphone AKG WMS80 HT80
* accoustic foam disintegrates, needs replacement
* lead-acid battery is pretty dead
** 12V 3.4Ah(/20h) (Panasonic LC-R123R4PG)
** dampening foam used so the battery doesn't rattle turned into sticky sludge - needs annoying removal
** maybe replace with lifepo4 instead of lead-acid?
* heat sink pads and thermal paste need replacement
* drops out at high volume -> probably just the dead battery and dropping out due to low voltage or the amp chip running into protect mode due to low voltage or insufficient heat sinking

!! Documentation:

* https://www.akg.com/on/demandware.static/-/Sites-masterCatalog_Harman/default/dw17dccf51/pdfs/WMS80_manual.pdf
* https://www.manualslib.com/products/Fohhn-Easyport-Fp1-Plus-6033799.html
** https://www.manualslib.de/manual/16309/Fohhn-Easyport-Fp-1-Plus.html?page=3#manual

!! Internals:

Parts

* AKG WMS80 SR80 PCB
* FP1 main PCB "FP1 412 100 / 9907
* input/output pcb
* woofer 8 Ohms
* motorola piezo tweeter

Chips

* main pcb
** TDA1560Q - 40W (@8Ohm) class-H/B/AB power amplifier
** KA7815 - 1A voltage regulator
*** https://www.alldatasheet.com/datasheet-pdf/pdf/19229/PHILIPS/TDA1560Q.html
** mc33079n - low noise quad opamp
** TL072CN - low-noise jfet dual opamp
** TL074CN - low noise jfet quad opamp
** TL071CN - low noise jfet single opamp
** CA3140E -  4.5MHz, BiMOS Operational Amplifier with MOSFET Input/Bipolar Output 
** NE5534P - low noise opamp
** BUZ11 - n-channel mosfet
** BD237 - npn power transistor
** 6 smaller transistors
*** C546B
** 4 1n4007 diodes


medium speed 10A 250V sand filled 20x5mm fuse

!! Repairs

!!! new AKG HT80 Mic

searched and found a used AKG WMS80 set with HT80 Mic, i ended up buying all 4 sets of WMS80 for just 5€ more than one set from the seller. read more here: [[AKG WMS80 Sets repair]]

!!! front acoustic foam replacement

* removed old acoustic foam
* removed Fohhn logo from foam
** was placed 2cm from the bottom of the mesh
* removed glue leftovers from the mesh
* the foam is a bit curved so it is ~7mm thick at the left and right edges and 1,5cm in the middle, but i've got a perfectly fine leftover 12mm thick foam piece from a friend and i don't care enough about the foam.



!!! lead-acid battery replacement

original battery:

* 12V 3.4Ah (/20h)
* Panasonic LC-R123R4PG
* sealed lead-acid
* lasts for 6-12h (speech/music)
* 135x67x60?mm (body without connectors)
* https://www.pro-akkus.de/panasonic-lc-r123r4pg-12v-3-4ah-blei-akku-agm-batterie-vds-zulassung

options

* just replace with new sealed lead-acid with same dimensions
* replace with ~LiFePO4 battery, maybe with higher capacity

i checked if there are empty cases available to assemble your own lithium batteries or if there are prebuild ones available in the right size. But the closest matching size is 150x65x96cm which is to big.
It seems the original is a special size. I don't want to buy a new lead-acid battery even if that is the easiest option.

I decided to open the old battery, gut its contents and reuse the case for ~LiFePO4 cells.
The internal dimensions are: ~ 115x60x45mm
I tried finding new cells but it's challenging. The common battery sizes 18650, 32650, 32700, 26700, 32113, 33140, 60200, 46160

pouch:

* 136 x 82 x 11 mm

at the end i decided not to use the old case and make a new battery pack with 26650 cells. i tried fitting a 4s3p pack in the box to get more than 3x the original capacity, but there were screws in the way, so a 4s2p it is. its still more than 2x the capacity.

i've got a gne-3s4s100a-f 4s BMS which i got with the cells for my 100Ah battery. it was a good size for this task here and i used it. it has a separate charging port, which i don't use, but i hope that is no issue.

https://www.justinmind.com/blog/awesome-lorem-ipsum-alternatives/
https://nietzsche-ipsum.com



Right superiority suicide aversion philosophy ideal merciful snare pious eternal-return chaos against joy. Abstract hatred decieve burying superiority joy god decieve virtues evil deceptions good ultimate selfish. Aversion decrepit passion free mountains mountains play. Justice good ocean noble superiority depths good aversion moral sea ultimate aversion abstract law. Justice aversion love grandeur overcome prejudice hope decieve. Salvation sea marvelous contradict revaluation society. Virtues salvation grandeur faithful noble enlightenment disgust mountains moral noble horror.

Revaluation noble inexpedient will convictions zarathustra gains truth mountains madness mountains. Salvation philosophy endless disgust hatred suicide morality value convictions zarathustra hope. War will fearful selfish truth ocean ubermensch against god endless ultimate. Selfish joy moral burying chaos pious hope endless law zarathustra ubermensch victorious overcome superiority. Philosophy faith fearful eternal-return pious sea war faithful. Will spirit good insofar enlightenment inexpedient intentions abstract oneself holiest mountains sexuality selfish.

God overcome grandeur enlightenment abstract. Abstract decieve philosophy spirit of ocean holiest endless holiest sexuality. Deceptions law ocean contradict society christianity morality pious society passion will. Ascetic free ultimate horror disgust horror philosophy morality eternal-return ocean faith law. Derive law society selfish eternal-return snare battle against sea truth convictions intentions. Snare grandeur of victorious fearful noble disgust. Hope love.
* [[How FPGAs work, and why you'll buy one|https://www.embeddedrelated.com/showarticle/195.php]]?

cheap devboards / modules

* 

stuff

* [[Design Review (Spartan 7 FPGA) - Schematic & PCB - Phil's Lab #63|https://www.youtube.com/watch?v=au9hlIVZteE]]
* Hardware
* Software
* Knowledge/Education
* Data
* etc.

''Free as in Freedom''

* https://en.wikipedia.org/wiki/Free_content
* https://opensourceecology.de/
* https://wiki.opensourceecology.org/wiki/Main_Page
* http://emlab.utep.edu/opensource.htm
* https://en.wikipedia.org/wiki/Category:Free_culture_movement
* https://en.wikipedia.org/wiki/Business_models_for_open-source_software
* https://freedomdefined.org/Definition

* https://search.creativecommons.org/
* https://unsplash.com/license
* https://publicdomainvectors.org/
* https://openclipart.org/ ~~(a bit wonky since redesign)~~ fixed
* https://iconduck.com/
* https://freesvg.org/
* https://publicdomainvectors.org/
* https://www.svgrepo.com/vectors/
* https://openverse.org/ - also audio
(free as in freedom)

* https://freedsp.cc - https://github.com/freeDSP

c-dsp von minidsp?

cheap eq or dsp boards from china? there are some using the ADAU1701 (like freedsp) or called "audio processor"

* https://www.thomann.de/de/the_t.racks_dsp_4x4_mini.htm
** seems to be made by http://en.musicrown-audio.com/index.html

there are some open source/diy dsp projects, e.g. on hackaday

https://hackaday.io/project/166122-esp32-as-bt-receiver-with-dsp-capabilities
Stereo DAC with 32-bit, 384kHz PCM

* http://store3.sure-electronics.com/adau1701-audio-digital-signal-processor-kernel-board
** one can find these from different chinese sellers on pretty much every platform... there are also other designs with adau140x or other chips
* https://auverdion.de/produkt/aurora-dsp/
* the ESP32 has some DSP capabilities, take a look at [[esp32 audio projects]]
** https://hackaday.io/project/166122-esp32-as-bt-receiver-with-dsp-capabilities
* Tutorial: ~LowBudget 4Kanal ~SureDSP mit DIY-Anteil fürs Autoradio: http://www.hifi-forum.de/viewthread-123-2308.html
* Qualcom has Bluetooth audio ~SoCs with integrated DSP
* https://www.diymobileaudio.com/threads/diy-custom-audio-dsp-like-minidsp.107968/
* https://ohdsp.weebly.com/
* https://www.xmos.ai/xcore-200/

programming:

* proprietary graphical programming languages
* C++
* https://soul-lang.github.io/SOUL/docs/SOUL_V1_Release.html

Stuff:

* https://t.me/javaebooks/162
* [[FAUST: Functional programming language for real-time DSP and synthesis|http://faust.grame.fr/about/]]
* [[Assessing the Ada Language for Audio Applications|http://www.electronicdesign.com/embedded-revolution/assessing-ada-language-audio-applications]]
* [[Web Audio DSP Playground|https://acarabott.github.io/audio-dsp-playground/]]
* https://ccrma.stanford.edu/~jos/pasp/
* [[Web DSP audio editor|https://dsp.audio/editor/]]
* [[How FPGAs work, and why you'll buy one|https://www.embeddedrelated.com/showarticle/195.php]]?
* [[DSP Spreadsheet: Frequency Mixing|https://hackaday.com/2019/11/01/dsp-spreadsheet-frequency-mixing/]]
* [[DSP Spreadsheet: IQ Diagrams|https://hackaday.com/2019/11/15/dsp-spreadsheet-iq-diagrams/]]
* https://hackaday.io/project/454-dsp-in-verilog-when-it-needs-to-be-fast
* [[AudioGridder   DSP servers using general purpose networks and computers|https://github.com/apohl79/audiogridder]]
* [[Ask HN: Learning DSP witha software development background?|https://news.ycombinator.com/item?id=22955914]]
pretty much the standard in open source cad software

tipps:

* use the pre/development version from github

collection of useful stuff:

* https://wiki.freecadweb.org/Expressions/de / https://wiki.freecadweb.org/Expressions
* you can put values into spreadsheets inside of FreeCAD, define the spreadsheet cells as variables and then use these variables in expressions all over your project for example to define meassurements and dimensions
** https://wiki.freecadweb.org/Expressions#Reference_To_CAD-Data
* https://wiki.freecadweb.org/Manual:Using_spreadsheets
** https://wiki.freecadweb.org/Spreadsheet_Workbench
* https://grabcad.com/library/freecad-example-of-variables-and-equations-1#!
* https://wiki.freecadweb.org/Python_console
** https://wiki.freecadweb.org/FreeCAD_Scripting_Basics

* https://wiki.freecadweb.org/Assembly
* https://wiki.freecadweb.org/External_workbenches
** https://wiki.freecadweb.org/External_workbench_list
*** https://wiki.freecadweb.org/Lattice2_Workbench
* https://framagit.org/FrViPofm/Bike3D
* https://wiki.freecadweb.org/FEM_Tutorial_Python
* https://www.youtube.com/c/flowwiescorner/videos
* https://wiki.freecadweb.org/ExplodedAssembly_Workbench


stuff

* https://www.youtube.com/watch?v=CnKsPq3NxE4
* https://teknoclothing.com/
* https://www.bbsr.bund.de/BBSR/DE/veroeffentlichungen/sonderveroeffentlichungen/2016/freiraum-fibel-dl.pdf;jsessionid=C47D9B47E2EDB4665AC898D65A2604C4.live11294?__blob=publicationFile&v=3 - "Frei Raum Fiebel"
** https://coma-emerald.de/freiraum-fibel-dl.pdf - if the above is not accessible anymore
* https://coma-emerald.de/
* https://mwk.baden-wuerttemberg.de/de/kunst-kultur/kulturfoerderung/freiraeume/
* [[DIYRM: Basic REW Frequency Response Measurements....|https://www.youtube.com/watch?v=RW5v9KM8fwA]]
* uses [[Fast Fourier Transform (FFT)]]
* [[frequency response webapp]]

# create noise/frequency sweep, output that to speakers
# record a mic that captures the response from the speaker
# analyze the recorded audio using [[Fast Fourier Transform (FFT)]] and display a frequency response graph

* [[Spectrum Analyzers - tomtektest|https://www.youtube.com/watch?v=9PumAvTzTUs&list=PL2u6aYAXZ0Z9Q6H6WBcb1y3bCo0-sc4XF]]
* [[ Using a Spectrum Analyzer for Audio Work - BG082 |https://www.youtube.com/watch?v=PjlIKVnKe8I]]
* [[ Understanding Audio Frequency Response & Psychoacoustics |https://www.youtube.com/watch?v=TwGd0aMn1wE]]
* [[ DIYRM: Basic REW Frequency Response Measurements.... |https://www.youtube.com/watch?v=RW5v9KM8fwA]]
* [[ High-resolution Speaker Frequency Response & Distortion Measurements and Why We Need Them |https://www.youtube.com/watch?v=vGjA5oT_mTk]]
* [[ Everything You Need to Know About Frequency Response for Audio Gear! |https://www.youtube.com/watch?v=NJJcjNqpytk]]
* https://www.youtube.com/watch?v=n2SipY6E-CI
goal is to build a small webapp that is able to make frequency response meassurements using the [[Web Audio API|Web Audio API, Web Midi API - Websites with advanced audio functionality]] and the Canvas.

!! TODO:

* sound generation
** include different noise
** make frequency sweep better + settings
** simple oscilator with settings
* visualisations
** frequency domain settings
** frequency domain over a recording as one graph
** time domain (waveform)
** spectrogram
* make it look nicer
** tabs for visualizations and other features
** help tab with descriptions
* 

!! info:

see [[frequency response / spectrum analysis/Measurements]]

* create noise/frequency sweep, output that to speakers
** noise
*** https://noisehack.com/generate-noise-web-audio-api/
*** https://github.com/zacharydenton/noise.js
*** https://github.com/search?q=web+audio+noise
** frequency sweep
*** https://teropa.info/blog/2016/08/10/frequency-and-pitch.html
*** [[OscillatorNode|https://developer.mozilla.org/en-US/docs/Web/API/OscillatorNode]]
**** [[OscillatorNode.frequency|https://developer.mozilla.org/en-US/docs/Web/API/OscillatorNode/frequency]] - [[AudioParam|https://developer.mozilla.org/en-US/docs/Web/API/AudioParam]]
***** [[AudioParam.linearRampToValueAtTime()|https://developer.mozilla.org/en-US/docs/Web/API/AudioParam/linearRampToValueAtTime]]
* record a mic that captures the response from the speaker
** [[MediaDevices|https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices]]
*** [[getUserMedia|https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia]]
** [[AudioBuffer|https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer]]
** [[MediaStreamTrackAudioSourceNode|https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrackAudioSourceNode]]
** [[MediaStreamAudioSourceNode|https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamAudioSourceNode]]
* analyze the recorded audio and display a frequency response graph with canvas
** [[AnalyserNode|https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode]] doing [[Fast Fourier Transform (FFT)]]
* [[web design]]
* spectrogram
** https://github.com/borismus/spectrogram
*** https://academo.org/demos/spectrum-analyzer/
* waveform
** https://academo.org/demos/virtual-oscilloscope/
* https://dead-beef.github.io/webaudio-spectrum-analyser/#/
* info box
** https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Practical_positioning_examples#a_sliding_hidden_panel

!! useful examples/guides

* https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Using_Web_Audio_API
* https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Advanced_techniques
* https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API
* https://webaudioapi.com/samples/frequency-response/
* https://github.com/hughsk/web-audio-analyser
* https://github.com/sepans/webaudio-analyzer
* https://github.com/hvianna/audioMotion.js
* https://github.com/mdn/violent-theremin - frequency sweep
* https://github.com/mdn/web-dictaphone - record (and playback)
* https://github.com/mdn/voice-change-o-matic - record and visualize, simple basis
* https://github.com/mdn/webaudio-examples/tree/master/audio-buffer - buffer & white noise
** https://mdn.github.io/webaudio-examples/audio-buffer/
* https://github.com/mdn/webaudio-examples/tree/master/audio-analyser
** https://mdn.github.io/webaudio-examples/audio-analyser/

!! progressive web app stuff:

* manifest.webapp and install-button like in MDN examples
* https://developer.mozilla.org/en-US/docs/Web/Manifest#browser_compatibility

!! rants

why tf does `<button>` behave like a f* `<input type="submit">`?!? WHY?!? why doesn't it just do nothing like an `<input type="button">`?!? why does one have to do `<button type="button">` for it to work like the name implies?! wasted quite some time on that...
* https://de.wikipedia.org/wiki/Fahrradanh%C3%A4nger#Ma%C3%9Fe,_Masse_und_Reifen

** Abmessungen (§ 32 StVZO Absatz 1–4)
** Breite allgemein: 2,55 m
** Höhe: 4 m
** Länge allgemein: 12 m
** Fahrrad und Anhänger zusammen: 18 t
** und wenn der anhänger 3,5t nicht überschreitet müssen wir mit achslast auch nichts beachten... lass mal bauen XD
* lastenanhänger können praktischer sein als lastenräder, da sie als einzelnes kompakter sind und die nutzung ist modularer... also man kann auch ohne rumfahren wenn man nichts transportieren muss

*Pedelec-Norm und co: beschränkung auf max. 6km/h ohne treten (u.a. anfahrhilfe, handwagen) max. 25km/h mit tretenund 250W dauerleistung des motors.
** Motor-Leistung: https://www.kfztech.de/kfztechnik/motor/steuerung/leistungsformel.htm (http://www.hv-engineering.de/pdf/pdf_anleitungen/TechnischeAnleitungNr7.pdf?)


Ideen/Ziele:

* mindestbreite der ladefläche von einer Europalette längs (80cm breit, 120cm lang), besser zwei Europaletten quer (120 breit, 160cm lang) (https://de.wikipedia.org/wiki/Europoolpalette#/media/Datei:Plan_palette-europe.svg)
* Radwegbreite: https://de.wikipedia.org/wiki/Radverkehrsanlage#Benutzungspflichtige_Radverkehrsanlagen
* 2-3m hohe aufbauten müssen möglich sein, am besten bis 4m
* ~~möglichst aus Holz?,~~ stahl, aluminium ist nicht wirklich nachhaltig
* relativ simpler kasten-artiger bau
* reifen unter der ladefläche, damit die nicht im weg sind und damit man schon eine gewisse grund höhe hat.
* XYZ Cargo Truck als inspiration http://www.xyzcargo.com/cycles/
** http://www.xyzcargo.com/wp-content/uploads/2018/02/0-Ma%C3%9Fe-XYZ-CARGO-TRUCK-measurements-2-wide-4-web.jpg
* another commercial bike: https://www.vowag.de/
* breite
** Carla Cargo
*** Ladefläche: 1650 x 650 mm
*** breite: 970 mm
** Radkutsche Musketier breite: 1066 mm
** xyz cargo fourwheeler 100cm, truck 120cm
* fahrradstreifen/fahrradwege breite
** https://de.wikipedia.org/wiki/Radfahrstreifen
** https://www.stvo2go.de/schutzstreifen-breite/
** https://de.wikipedia.org/wiki/Radverkehrsanlage
** https://www.adac.de/rund-ums-fahrzeug/zweirad/fahrrad-ebike-pedelec/tests/radwegbreiten/
* über 120cm gesammbreite des gespanns, also eurokistenbreite ist aktuell wohl nicht sinnvoll

Kraft die beim beschleunigen eines bestimmten gewichtes mit fahrradreifen gebraucht wird?
wie viel gewicht kann man mit einem fahrrad und einem 250W motor in angemessener zeit zu einer angemessenen geschwindigkeit beschleunigen und halten? wie ist das mit steigungen? wie viel selbst treten?

* reibungskraft berechnen? reibungszahl von fahrradreifen/gummi? rollwiederstand/rollverlust
** https://www.leifiphysik.de/mechanik/reibung-und-fortbewegung/ausblick/reibungskraefte-beim-fahrradfahren
** https://www.leifiphysik.de/mechanik/reibung-und-fortbewegung/ausblick/reifen-aus-gummi-ein-kompliziertes-reibungsproblem
* drehmoment
** https://www.wolfgang-frank.eu/drehmoment.php
** https://de.wikipedia.org/wiki/Drehmoment
** https://www.youtube.com/watch?v=1yQtfZ99U8I
** https://www.lehrerfreund.de/technik/1s/fahrrad-kraefte-und-drehmomente/4013
** https://www.helpster.de/drehmoment-berechnen-so-geht-es-richtig_50444
* https://www.schwalbe.com/technik-faq/rollwiderstand/

wie ist dauerleistung definiert? darf man einen stärkeren motor wählen, der aber nur zum anfahren mit mehr als 250W betrieben wird?


FEM/FEA vom Rahmen des Lastenrades bzw. anhängers machen

Metall

* https://de.wikipedia.org/wiki/Stahlrohr
* https://de.wikipedia.org/wiki/Stahlsorte
* https://de.wikipedia.org/wiki/Baustahl
* https://de.wikipedia.org/wiki/Kategorie:Baustahl
* https://de.wikipedia.org/wiki/Kategorie:Stahl


weitere Inspiration:

* https://www.freie-lastenradl.de/cb_item/bernd-lastenrad-buehne/
** https://twitter.com/ThomasMichels15/status/1518605504670539776
* https://www.veloconcerts.com/
** https://www.bremen.de/leben-in-bremen/fahrradstadt/bike-it-stage
** https://www.wfb-bremen.de/de/page/news/76492
** https://www.berliner-philharmoniker.de/education/uebersicht/unterwegs-in-berlin-in-der-welt/velostage/
* https://www.klassikradio.de/magazin/news/musik-auf-dem-fahrrad-die-buehne-fuer-strassenmusik
* https://twitter.com/KochGa/status/1498247267379208192
* https://www.werkstatt-lastenrad.de/index.php?title=Hauptseite
** https://www.werkstatt-lastenrad.de/index.php?title=Lastenrad_vom_Projekt_Nordgarten_in_N%C3%BCrnberg
** https://www.werkstatt-lastenrad.de/index.php?title=Dokumentation#SAM_der_Werkbox3_in_M.C3.BCnchen
** https://www.nicojungel.net/space.html
* https://www.heise.de/news/Pimp-my-Bike-Kostenfreie-Bauanleitung-fuer-den-TrudeTrailer-Lasten-Anhaenger-7135874.html
* https://www.greencity.de/wp-content/uploads/Lastenradb%C3%BChne_M%C3%BCnchow_10-1200x800.jpg
* https://twitter.com/KochGa/status/1498247267379208192/photo/1
* https://www.permies.com/t/51729/bicycle/Dale-heavy-duty-cargo-trailer
* https://cargocycle.de/
* https://donkeytrailers.com/3-wiel-fietskarren/7-xxl3d-big-mammut-240x80
* https://www.werkstatt-lastenrad.de/index.php?title=Dokumentation#SAM_der_Werkbox3_in_M%C3%BCnchen
* https://www.werkstatt-lastenrad.de/index.php?title=Bau_eines_Heckladers_mit_dem_einleuchtend_e.V.
* https://www.nicojungel.net/space.html

* https://baumeister.eu/produkte/elektrischer-palettenwagen
* https://www.hinterher.com/blog/unsere-hausbank-ein-starker-partner-3e4dt-pz3zx-bl79y
* https://www.fleximodal.fr/de_DE/bicylift
ich habe einen kleinen 3MW wechselrichter gefunden lol:
https://www.sma.de/produkte/solar-wechselrichter/sunny-central-2200-2475-2500-ev-2750-ev-3000-ev.html

https://www.sma.de/produkte/solar-wechselrichter/sunny-tripower-15000tl-20000tl-25000tl.html
die kleine version davon + e-auto akku (+ gabelhubwagen zum transport)
sind wir bei voller leistung mit 5h dabei?

https://www.sma.de/produkte/solar-wechselrichter.html

wenn ich mich nicht irre... man wäre nicht mal schrecklich größer oder schwerer als ein dieselaggregat

e-auto akku 20-25k€, zumindest für Tesla akkus auf einer seite
inverter 2,5k€ (bis 25kW) z.B. SMA STP Sunny Tripower 25000 TL-30
ca. 400-550kg
gabelhubwagen: ~300€
palette: 15€

85kWh/15kW/h = ~5,7h

befreundeter elektrotechniker zum abnehmen oder so?
feuerschutz?

data about the tesla model s battery:

* https://teslatap.com/undocumented/
* https://www.quora.com/How-much-voltage-and-amperage-do-Tesla-battery-packs-have?share=1
* https://en.wikipedia.org/wiki/Tesla_Model_S#Battery
* https://teslamotorsclub.com/tmc/threads/model-s-battery-voltage.22341/


links:

* https://www.youtube.com/watch?v=PVnQ87Fvsk4
* https://www.secondlife-evbatteries.com/
* https://de.wikipedia.org/wiki/Crowdfunding
* https://en.wikipedia.org/wiki/Crowdfunding
* https://en.wikipedia.org/wiki/Category:Crowdfunding
* https://en.wikipedia.org/wiki/Business_models_for_open-source_software
* https://en.wikipedia.org/wiki/Comparison_of_crowdfunding_services
* https://shields.io/category/funding


platforms

* open
** https://liberapay.com/
** https://github.com/cloudpatron/cloudpatron
** https://opencollective.com/
** more tailored to software:
*** https://www.bountysource.com/
*** http://gitpay.me/
*** https://gitcom.org/
*** http://www.freedomsponsors.org/
* proprietary
** Kofi - https://ko-fi.com/
** Patreon
** Flattr

general

* https://prototypefund.de/
* https://www.opentech.fund/
** https://en.wikipedia.org/wiki/Open_Technology_Fund
* hans sauer preis
* Rosa-Lux
* anstiftung
* https://www.bewegungsstiftung.de/antrag-stellen.html
* amadeu-antonio-stiftung


local

* https://quartiermeister.org/de/projektfoerderung/
* https://kijubdd.de/
* https://kulturbuero-sachsen.de/
* https://www.dresden.de/de/kultur/kulturfoerderung/kulturfoerderung.php
* https://www.hor-dresden.de/
** https://www.hor-dresden.de/fokus-foerderung-2022/
*** https://www.hor-dresden.de/fokus-foerderung-2022-kurzportraits/
* https://www.wfs-foerderportal.de 
* Sächsischer Förderpreis für Demokratie
* SAB - Weltoffenes Sachsen - https://www.sab.sachsen.de/
* dresden LHP
shroom power!

* https://en.wikipedia.org/wiki/Radiotrophic_fungus
* [[Stephen Axford: How fungi changed my view of the world|https://www.youtube.com/watch?v=KYunPJQWZ1o]]
* mushroom and fungi could replace concrete or other building material
* plastics alternative (for example for packaging like styrofoam)
* important part of ecosystems, recyclers
* seemingly endles amound of different species
* https://en.wikipedia.org/wiki/Fungus
** https://de.wikipedia.org/wiki/Pilze
* [[This mushroom brick could replace concrete|https://www.youtube.com/watch?v=Pp7pSlwIlLA]]
* mycelium leather
* https://de.wikipedia.org/wiki/Elektrochemisches_Abtragen
* https://wikifactory.com/+dronecoria
** https://wikifactory.com/@aeracoop/dronecoria
* https://wikifactory.com/@luzleanne/community-composter
* https://wikifactory.com/@till-w/diy-micro-biogas-systems
* [["automatic" gardening]]
* https://farmos.org/
* http://www.geda-project.org/
* http://wiki.geda-project.org/geda:faq#what_is_geda_gaf_and_how_does_it_relate_to_geda
* [[https://de.wikipedia.org/wiki/GEDA_(Software)]]
generelle punkte zum "jugendbudget"

* ich frag mich wie diese "Jugend-Jury" zusammengesetzt wurde und entscheidet... eine unabhängig gewählte jury wäre da zielführend, aber es gibt auch ministerien, die lieber menschen einsetzen, die eine bestimmte meinung vertreten...
** ähnlich wie Michael Kretschmer's Klimakonferenz...
* ich habe auch sehr oft den eindruck das solche aktionen der regierung wieder nur irgendwelcher pseudo kram ist... die sachen die sinnvoll sind, sind alle nichts neues... umsetzen will sie die regierung aber eh nicht... lieber mehr geld in lufthansa und co, sowie in bewaffnung, abschottung und überwachung stecken statt in umwelt und soziales...
* die "handlungsfelder" sind sehr verwoben und ich habe auch bedenken, dass sie bei der jugendstrategie zu getrennt und einzeln betrachtet werden... viele punkte haben mit vielem zu tun, das große ganze ist da auch wichtig und man muss thematische verbindungen betrachten...
** die kriminalität in einem bereich bekämpft man halt vlt. besser damit das man jugendarbeit macht und die bildung stärkt, sodass jugendliche nicht mehr in gangs gehen oder auch austreten, bessere bildung und damit arbeit bekommen... das dauert länger, aber ist sinnvoller und nachhaltiger als viel geld in polizei und überwachung zu stecken und sich straßenschlachten zu liefern...


ich habe jetzt viele themen die in den handlungsfeldern angesprochen wurden tangiert und meine ideen aufgeschrieben, keine ahnung ob das sinnvoll und zielführend war in eine richtung wie es bei dieser "jugendstrategie" vom ministerium gewollt ist...


''Transparenz''

transparenz fehlt in unserer demokratie an vielen stellen, obwohl transparenz extrem wichtig ist für eine gute demokratie. es bedarf transparenz, damit jede person nachvollziehen kann warum bestimmte politiker, ministerien, ausschüsse und co entscheidungen treffen. besonders die verschiedenen arten von lobbyismus ("moderne korruption), vor allem aus der industrie, sind für eine gute demokratie gefährlich, weil nicht mehr die bevölkerung die macht hat sondern die firma mit den besten empfängen in brüssel und co.
es muss transparent gemacht werden mit welchen firmen und lobby-gruppen sich politiker treffen.
es gibt immer wieder fälle von studien und andere untersuchungen die eig. etwas ganz anderes empfehlen als die politik umsetzt, weil diese zurückgehalten werden. viele dokumente, die wichtig für die allgemeinheit sind werden auch mit fragwürdigen praxen wie dem "zensurheberrecht" zurückgehalten wo sich gruppen wie fragdenstaat wehren, damit mehr transparenz herrscht.
die resultierende nachvollziehbarkeit würde es dann verringern, dass leute teilweise aufgebracht sind.

''Open Source software, Open Hardware, offene standards und Open Knowledge''

open source software kann extrem viel geld sparen, z.B. indem eine verwaltungssoftware gemeinsam entwickelt werden kann, einzelne bundesländer nur paar kleinere spezielle sachen ändern müssen, aber die software insgesammt in allen bundesländern eingesetzt werden kann, ohne das jedes bundesland komplett eigene software entwickeln muss. (als beispiel)
außerdem können andere länder so auch an software teilhaben und eine Konferenzsoftware, wie ~BigBlueButton kann auch in anderen ländern den unterricht während corona möglich machen obwohl die nie die mittel hätten so was zu entwickeln.
mit der geeigneten kombination aus offener software und mit kompetentem hosting wäre es möglich gewesen für alle klassen konferenzen anzubieten ohne das man auf teure, proprietäre dienste zurückgreifen muss, weil die lösungen wie lernsax zusammen brechen.
ähnlich geht das auch mit open hardware, offene hardware hat anfangs die verbreitung von heimcomputern extrem beschleunigt und das rasante wachstum des internets wäre nie ohne open source software und offene standards möglich gewesen.
in deutschland (und europa) sind viele standards, also DIN, VDE und co leider geschlossen, wo man oft viel geld bezahlen muss um die dukumente zu bekommen... das mach es leuten schwer, die z.b. open hardware entwickeln wollen die den strengen deutschen (sicherheits) standards entspricht.
open knowledge ist auch sehr wichtig, das ist im grunde die basis von open source und open hardware. offenes wissen, offener, kostenloser zugang zu wissen für alle. viele wissenschaftliche arbeit wird durch steuern finanziert, bleibt aber verschlossen und landet bei einzelnen firmen. auch wissenschaftliche journals sind da ein problem, auch für studenten und doktoranden, viele wissenschaftliche arbeiten werden dort veröffentlicht, aber der zugang dazu kostet viel geld.

diese zwei sachen ermöglichen erstmal viel denke ich.
von da aus kann man dann weiteres machen.

* ein punkt ist z.b. die verringerung des wahlalters. viele jugendliche würden gerne mehr in der politik zu sagen haben und sind nicht unmündiger als die ältesten unserer gesellschaft die auch wählen dürfen.
* jugendparlamente, die ernsthaft auf diversen ebenen, also regional, landes und vlt. bundesebene und sogar europaebene angehört werden, könnten auch sehr viel zur demokratie beitragen.
* auch bestimmte parlamente und zusammenkünfte zu bestimmten themen wie z.B. dem klimawandel könnten sehr interessant sein. es gibt allgemein das gefühl das die politik keine politik für die normale gesellschaft macht sondern nur für konzerne... politiker müssen mehr mit den menschen reden, ihnen zuhören. politiker sind meist älter und tun die jugend wenn es um umwelt oder themen wie axel voss' artikel geht gerne als naiv und unwissend ab (oder sogar als bots), das ist ignorant und trägt zur politikverdrossenheit der jugend bei
* bezüglich der umwelt und dem klima müsste man schauen die industrie mehr in die mangel zu nehmen und auch unser wirtschaftssystem neudenken... unendliches kapitalistisches wachstum funktioniert nicht auf einem endlichen planeten, wachstum vom gemeinwohl oder ähnliche ideen sollten wieder mehr betrachtet werden... unsere "soziale" marktwirtschaft könnte eh sozialer werden.
* wenn man jugend und allgemein auch andere eher benachteiligte gruppen einbinden will (vielfalt und teilhabe) kommt man nicht um (jugend-)sozialarbeit und die vielen gemeinnützigen vereine drum rum, die diverse teile unserer gesellschaft über lange zeit mit einem mindestbudged am laufen gehalten haben... sie ermöglichen manchen menschen erst die teilhabe an der gesellschaft, erwecken interesse an politik und anderen themen... statt wegen corona all denen die mittel noch mehr oder komplett zu streichen, sollte man ihnen noch mehr unter die arme greifen... untersuchungen rund um die welt haben gezeigt, dass sozialarbeit mit vergleichsweise weniger mittel so viel mehr bringt als immer mehr geld in polizei und co zu stecken.
* viele dieser sachen können auch super zusammen arbeiten, indem z.B. jugendsozialarbeit möglichkeiten bekommt umwelt- und klimaproblematiken mit den jugendlichen zu behandeln und es möglichkeiten gibt das jugendliche eigene lösungsideen erforschen und umsetzen können (siehe hierfür auch die MINT thematik die stellenweise sehr forciert wird, obwohl nicht alle wirklich bock drauf haben)
* vereine und einrichtungen die in der sozialarbeit tätig sind, sind auch wichtige orte der freizeit und wichtige freiräume, in denen man von schul-/lern- oder arbeitsstress entfliehen kann. es werden möglichkeiten geboten die mensch nicht unbedingt zuhause hat und allgemein ist man unter gesellschaft. das ist auch wichtig für psychische gesundheit (siehe auch weiter unten).
* die meisten jugendlichen haben ein fahrrad und fahrrad ist ein guter weg um zur schule zu kommen, aber oft ist das nicht wirklich schön, weil fahrradwege in den meisten gebieten deutschland schlecht ausgebaut sind und es auch regelmäßig unfälle gibt. (querzug zwischen klima/umwelt und gesundheit, sowie mobilität) kostenloser ÖPNV wäre auch eine nice sache.

* bezüglich digitales: viele jugendliche sind kompetenter im umgang mit den digitalen medien als ihre lehrer*innen, es gibt zu wenige sinnvolle weiterbildungen für lehrer*innen. aber auch fehlt die infrastruktur in schulen für guten unterricht... viele lehrer*innen fordern von schülern und schülerinnen das smartphones benutzt werden um etwas nachzuschlagen um die offline mittel wie bücher zu erweitern... viele schüler*innen haben auch ein smartphone, aber bei ärmeren familien kann es zum problem werden das kein geld da ist für große flatrates mit viel datenvolumen. es soll viel geld in die digitalisierung der schulen gesteckt werden, aber oft an den falschen stellen. offenes WLAN ist an Universitäten schon ein standard, warum nicht dieses netz auf schulen ausweiten? bei schulen muss man nicht einen ganzen campus abdecken, sondern meist nur einzelne gebäude. gleichzeitig gäbe es auch kein problem mehr, dass der Beamer-trolley erstmal mit einem LAN-Kabel angeschlossen werden muss, aber das LAN-Kabel wegen unvorsichtiger benutzung mal wieder kaputt ist und deswegen nichts läuft. (abgesehen davon das LAN kabel nicht für solchen einsatz gedacht sind)
* ein großer kritikpunkt ist auch übervorsichtiger jugendschutz im internet... es ist sinnvoll wenn bestimmte altersgruppen von bestimmten inhalten fern gehalten werden, aber jeder jugendliche hat früher oder später "illegal" auf den "ich bin 18+"-Button gedrückt und pornos angesehen... ich denke das ist nicht sonderlich schädlich und in gewisser weise sinnvoll für die sexuelle aufklärung. groß brittanien macht es vor, dort wird mit kanonen auf spatzen geschossen indem man mit dem ausweiß bestätigen soll das man alt genug ist... anderes thema: auch bei den artikeln die u.a. axel voss entsprungen sind ist einiger mist gemacht worden bei dem man nicht auf die "digital natives" gehört hat... daraus kommt halt auch frust und politikverdrossenheit bei der jugend...
* sexualität und geschlecht sind neben der kultur große felder in denen es viele vorurteile und viel diskriminierung gibt... das ist auch ein thema bei dem eine große schnittmenge zwischen jugendarbeit, vielfalt&teilhabe, bildung, freiräume.
* Hate Speech und Mobbing -> jugendsozialarbeit anyone?
* "Verdichtung und Beschleunigung des Alltags, Leistungsdruck und Selbstoptimierung" sind große probleme unserer (kapitalistischen) gesellschaft... viele psychische probleme unter denen ein großteil der bevölkerung leidet sind darauf zurück zu führen... 
* worüber viele lehrer und schüler auch klagen sind immer vollere lehrpläne mit immer mehr themen obwohl selten alte themen raus genommen werden
* bei dem punkt Teilhabe bin ich auch bei https://de.wikipedia.org/wiki/Soziales_Modell_von_Behinderung, dass die gesellschaft teilweise die menschen selbst behindert und das abgebaut werden muss... das geht nur gemeinsam... es gibt z.B. projekte von karten auf denen problematische stellen und wege für menschen eingezeichnet werden, die beim gehen beeinträchtigt sind. die müssen natürlich gefüllt werden von menschen die wissen worauf mensch achten muss... einerseits hilft das den menschen die stellen (oft mit umwegen) zu meiden, andererseits kann man dann sehr genau aufzeigen wo es noch arbeit für z.B. Kommunen gibt.
* https://de.wikipedia.org/wiki/Gemeinwohl-%C3%96konomie
* https://web.ecogood.org/de/
* https://utopia.de/ratgeber/gemeinwohl-oekonomie/
geschlecht ist nicht nur binar, also männlich und weiblich (schwarz und weiß)... geschlecht ist ein unendliches spektrum wo es dazwischen und außerhalb männlich und weiblich alles gibt und geschlecht ist nicht unbedingt fest.

* https://www.antidiskriminierungsstelle.de/DE/ThemenUndForschung/Geschlecht/Themenjahr_2015/Trans/trans_node.html
* https://media.ccc.de/v/36c3-143--hello-i-m-your-edge-case-or-no-seriously-how-do-you-ask-people-for-their-gender-on-the-internet-#t=959

* https://github.com/issyl0/pan
* https://github.com/spacekookie/gay

* https://xenia-linux-site.glitch.me/
** https://twitter.com/cathodegaytube/status/1197227512075411456
** https://twitter.com/cathodegaytube/status/1269405917700710400
* generators use fossil fuels and the exaust is pretty dirty, they polute the environment and constribute to global warming
* [[Hybrid Drone Generator|https://www.youtube.com/watch?v=1yB49G756OI]]
* [[Which Motor Type is the Best Generator? - DC, BLDC or Stepper? (Experiment)|https://www.youtube.com/watch?v=cJ_vDA7xsGs]]
* [[How to rewind a BLDC Motor (as a Generator)|https://www.youtube.com/watch?v=KZ4cylB114E]]
* [[HACKED!: Turning an Induction Motor into a Generator?!|https://www.youtube.com/watch?v=05qJM-zZ4ng]]
* some generators can be converted to be powered by gas like propane and there are a few gas powered generators on the marged, but they are very expensive.
* [[generator vs battery pack]]
* https://de.wikipedia.org/wiki/Stromerzeugungsaggregat
* https://en.wikipedia.org/wiki/Emergency_power_system
* https://en.wikipedia.org/wiki/Engine-generator
* https://blog.arduino.cc/2023/09/20/turning-an-old-car-into-a-powerful-generator/

(diy) inverter generator:

* inverter generators are more efficient because they don't produce the 230V directly but have a intermediary voltage and an inverter boosts the voltage up and produces the mains sinewave. the motor can run on lower speeds depending on the power consumption on the load and only if more power is consumed it ramps up, thus being more efficient, reducing fuel consumption and exhaust. normal generators have a fixed speed they run on.
* inverter generators are more expensive but they also often run much quieter than normal ones
* https://thegeneratorplace.com/how-to-build-an-inverter-generator-diy-your-emergency-power-source/
* https://permies.com/t/59981/DIY-Inverter-Generator
* https://extremehowto.com/inverter-generators-for-diyers-and-more/
* 
* https://www.youtube.com/@jcondon1
* https://www.youtube.com/watch?v=bvMG37wesNs
[[generators|generator]] vs. [[battery packs|accumulator - battery - rechargeable energy storage]]

there are 2 main reasons that people choose generators over batteries:

* cost: lithium (Li-Ion, LiPo or LiFePO4) cells  are pretty expensive
* runtime: you can only pull a certain amount of power from a battery for a certain amount of time until it is fully discharged, generators can run indefinetely as long as you have fuel

i think these reasons are not very good or they are only scratching the surface. there are also a few other factors i will discuss later on.

runtime: i think indefinite runtime is only required in few big and special cases, like emergency power for impontant infrastructure, and in most cases you only need a limited amount of power anyways.

cost: if you compare battery packs to generators you might look at the cheapest ones at your local hardware store. but that is a bad comparison, because these cheap generators are build to a very low quality to be so cheap and they output a poor power quality and sinewave. a battery with a pure sinewave inverter (which are only slightly more expensive than modified sine ones) outputs a good sinewave. good quality generators are much more expensive than the cheap ones.

other factors:

* weight
* cost of fuel or recharging
* environmental impact

the honda EU inverter series starts at ~1.500€ (EU 20i or EU 22i)


stuff

* [[Building a DIY Off-Grid Power System (vs. Ecoflow )|https://www.youtube.com/watch?v=U6UOyM9ovxA]]
* https://de.wikipedia.org/wiki/Europ%C3%A4ische_Genossenschaft
* Wohnungsgenossenschaften sind nice
* Energiegenossenschaften scheinen nice
* Genossenschaftsbanken erscheinen nice
** man muss aber leider aufpassen das diese banken keine esotherischen und schwurbel themen unterstützen, das ist ein großes problem dabei...
* https://www.genossenschaftsverband.de/
* https://en.wikipedia.org/wiki/Cooperative
* https://media.ccc.de/v/rc3-578923-wie_gruende_ich_eine_genossenschaft
* https://de.wikipedia.org/wiki/Genossenschaft
* https://tricargo.de/genossenschaft/
if you have a Nextcloud account with otp enabled you have to create an app password in your accounts security settings in order to use gnome's online accounts feature to connect to the nextcloud.
* https://de.deree.com.tw/lcr-meter.htm
** https://de.deree.com.tw/de-5000-lcr-meter.html
*** ~100€ einzeln, ~130€ kleines set
*** sigrok (serial) support, but needs IR-USB adapter
*** https://sigrok.org/wiki/DER_EE_DE-5000

* MASTECH MS5308
** sigrok (serial)
** really ugly

* Peaktech 2165 / Extech 380193 / Voltcraft 4080
** old
** sigrok (serial)
** https://www.ebay-kleinanzeigen.de/s-anzeige/lcr-4080-voltcraft/1834539328-168-7608
** https://www.ebay-kleinanzeigen.de/s-anzeige/lcr-4080-voltcraft/1834539328-168-7608

* ~PeakTech 2170 / Voltcraft LCR300
** sigrok (USB)
** https://www.conrad.de/de/p/voltcraft-lcr-300-komponententester-digital-cat-i-anzeige-counts-20000-103677.html

* Voltcraft
** ~~LCR100~~
*** no esr
*** https://www.conrad.de/de/p/voltcraft-lcr-100-komponententester-101392.html
** LCR400
*** https://www.conrad.de/de/p/voltcraft-lcr-400-komponententester-digital-cat-i-anzeige-counts-20000-1301292.html

* UNI-T 
** UT612
*** sigrok (USB)
*** https://www.uni-trend.com/meters/html/product/tyyq/ComponentTesting/UT610_LCR_Meters/UT612.html

* Peak Electronics
** ~~LCR40~~ -> ~~LCR45~~
*** no esr
** ESR60
*** 0-20Ohms ESR
** ESR70 - 102-110€
*** ESR in circuit
*** 0-40Ohms ESR
*** Speaker for audible feed back

* GW Instek?

* BK Precision
** BK890C
*** serial

* RS PRO
*** RS-9935 - 225€

* ET43x - china noname

* MESR-100 - useless

* https://www.ebay-kleinanzeigen.de/s-anzeige/cmt-417-lcr-handmessgeraet/1932730264-168-8085




stuff

* https://sigrok.org/wiki/Category:LCR_meter
* https://sigrok.org/wiki/Supported_hardware#LCR_meters
* [[#623 UNI-T UT612 LCR Meter Teardown And Review - how does it compare with the DER DE-5000 LCR ?|https://www.youtube.com/watch?v=abqVErJVVp0]]
* [[Instrument Basics: LCR Meter - Workbench Wednesdays|https://www.youtube.com/watch?v=C3AVUHcOIOc]]
* [[Messen mit dem LCR Meter DE 5000 Teil 1|https://www.youtube.com/watch?v=Qb3EWRCp4kM]]
** [[Messen mit dem LCR Meter DE 5000 Teil 2|https://www.youtube.com/watch?v=TxI5uW3U4zU]]
* [[Understanding LCR Meters|https://www.youtube.com/watch?v=vi9t5gdog7Q]]
* [[Wann ist der serielle Widerstand eines Elko zu hoch?|https://www.youtube.com/watch?v=HqmgQprPjYg]]
* [[Basics zum LCR-Meter & ESR bei Kondensatoren|https://www.youtube.com/watch?v=nWUv0OskLjA]]
* [[EEVblog #115 - Extech 380193 LCR Meter Review|https://www.youtube.com/watch?v=zEA5MfllPdg]]
* [[EEVblog #137 - BK Precision 879B Handheld LCR Meter Review|https://www.youtube.com/watch?v=H4TP0i917Ro]]
* [[EEVblog #365 - ESR Meter Bad Cap Monitor Repair|https://www.youtube.com/watch?v=72sJ5Infuu0]]
* [[Measuring Capacitance and ESR - Workbench Wednesdays|https://www.youtube.com/watch?v=H9_CDPD4sh0]]
* [[LCR and Transistor Tester Comparison|https://www.youtube.com/watch?v=BK7gnJavW28]]
* [[Hantek TO11 1832C LCR Meter Review & Teardown - Voltlog #303|https://www.youtube.com/watch?v=PTiKKWl6dfs]]
* [[Applent AT825 LCR meter review & teardown|https://www.youtube.com/watch?v=JzHZFcVofUg]]
* [[Low Cost LCR meter Shoot Out - Hantek 1833C, CEM, DER DE-5000, East Tester ET-433, Peak Atlas LCR45|https://www.youtube.com/watch?v=6_6KMnD4f0E]]
* [[#172 DER EE DE-5000, Silicon Chip ESR Meter MkII, MESR-100, MK-328, ESR meter comparison|https://www.youtube.com/watch?v=80sZUPwCnR8]]
* [[ESR meter kit build|https://www.youtube.com/watch?v=LQbvk8G_p1s]]
* https://www.eevblog.com/forum/testgear/der-ee-de-5000-unboxing-and-teardown/
* https://sigrok.org/wiki/Supported_hardware#LCR_meters
* https://eleshop.eu/test-measure/lcr-meter.html
* https://www.reichelt.com/ch/de/induktivitaets-kapazitaetsmesser-c4060.html
* [[#83 LCR's meter D, Q, Phi, ESR what is it all about demonstrated on DER EE DE-5000|https://www.youtube.com/watch?v=ivVSq0IiZGo]]
* [[EEVblog #229 - IET DE-5000 LCR Meter Teardown|https://www.youtube.com/watch?v=ji-UT7HJm0Q]]
* [[#89 Kenwood TS-850 for maintenance and ESR lab talk|https://www.youtube.com/watch?v=qQJVwZ_ImSk]]
* [[#154 PART 1: Is the ESR of an electrolytic capacitor able to tell the health of it?|https://www.youtube.com/watch?v=l2K9j2KGzDY]]
* [[EEVblog #137 - BK Precision 879B Handheld LCR Meter Review|https://www.youtube.com/watch?v=H4TP0i917Ro]]
* [[EEVblog #234 - Agilent U1733C LCR Meter Teardown|https://www.youtube.com/watch?v=Mp0n-Gu0aKk]]
* [[EEVblog 1474 - Can You Measure Capacitors IN Circuit?|https://www.youtube.com/watch?v=Uds-wLoaZmA]]
* [[EEVblog 1473 - How Your LCR Meter Works|https://www.youtube.com/watch?v=D9J-AmCcf4U]]
* [[EEVBlog LCR Meter Reviews|https://www.youtube.com/playlist?list=PL195AB0E12CE8BB8F]]
* https://eleshop.de/messtechnik/lcr-meter.html
* https://caps.wiki/wiki/Measuring_Capacitance_and_ESR

different:

* [[#91 Electrolytic capacitors and its LEAKAGE current and how to test|https://www.youtube.com/watch?v=2HUxuRcPR4M]]
* [[Which Capacitor Tester Should I Buy?|https://www.youtube.com/watch?v=lLQThhf3Brc]]
* [[Invention Release! Carlson LV Capacitor Leakage Tester.|https://www.youtube.com/watch?v=LhovRIM5xAo]]
* [[#76 Tutorial: Why do electrolytic capacitors fail so often|https://www.youtube.com/watch?v=OH6U2SKQaOw]]
!! grease

there are a lot of discussions (and confusion) and few decisive answers on forums about what grease to use for gears, plastic parts and linear ways in CD/DVD players.

some examples

* silicone grease
* lithium grease
* ptfe (teflon) grease

some manufacturers sell mixtures and that might be why some people had problems with one or the other. i bought a universal silicone grease without any additives, it is food grade and can also be used for o-rings in coffee machines or similar. because silicone is pretty chemically inert i think its not going to react with any plastic parts and the manufacturer also states is is unreactive with plastics.

other people report having had problems with ptfe or lithium greases, i think the lithium additives might be culprit. but to find the right answers one basically has to be a materials scientist, because every grease type behaves differently and ptfe or lithium might react with one plasic type but not with others.

don't use grease with brass (slide) bushings like in some DC motors or so, these bearings are somewhat spongy and are infused with oil. if they ran dry one maybe could use some oils to get them going again but don't use grease.

https://www.oks-germany.com/en/products/oks-1110-multi-silicone-grease/
* https://www.nledshop.com/products/
** https://www.nledshop.com/miscproducts/ - level shifter, differential spi, dmx/rs485 isolator
*** https://github.com/NLED/dmx-isolation-v1a
** https://www.nledshop.com/16bitlamp/
** https://www.nledshop.com/fourchan/
** https://www.nledshop.com/4chandmx/
* https://www.ulrichradig.de/home/index.php/dmx
* https://www.led-genial.de/

dmx to pixel

* https://www.nledshop.com/pixelmicro
* https://www.ebay.com/itm/133304110552

some more 

* https://leds-and-more.de/
* https://www.zedfy.shop/
* https://shop.led-studien.de/en/pixel-dmx
* https://shop.dmx4all.de/de/
* [[Leadership From A Dancing Guy|https://www.youtube.com/watch?v=hO8MwBZl-Vc]]
* [[Philip Schlaffer|https://www.youtube.com/channel/UCCcFnVUHZDKDUkghDspBKdQ]] beschreibt in einigen videos auch gruppendynamiken
* eingekaufter schrott bzw. aufbereitete verkaufs-geräte gehören in ein ERP/WWS
* Kundengeräte gehören in ein ticketsystem
* timetracking für kosten.

siehe [[ticket system / help desk / CRM]] und [[ERP / WWS, inventory management]]
* http://gtkgraph.sourceforge.net/ - abandoned, only GTK+ 2.0 it seems
* matplotlib
* gnuplot
* https://gitlab.com/john_t/giraffe-toolkit
* http://nongnu.org/gsequencer/api/3.7.11/libags-gui/AgsCartesian.html - [[[1]|https://www.reddit.com/r/GTK/comments/kgsofe/comment/ggklvf6/]]
* https://github.com/lcallarec/live-chart
* Dash?
* https://www.reddit.com/r/gnome/comments/jiht1a/graphs_and_data_visualization_in_gtk/
* https://github.com/lundmar/gtkchart

examples

* https://gitlab.gnome.org/GNOME/gnome-power-manager
* https://wiki.gnome.org/Apps/SystemMonitor
* https://htrb.github.io/ngraph-gtk/
** https://github.com/htrb/ngraph-gtk
habe fürs Sonnensystem paar günstige speakons bei thomann bestellt um die zu vergleichen, weil die Neutrik NL4FX nicht mehr wirklich verfügbar sind.

die blauen seetronic sind vom anschließen sehr ähnlich wie die NL4FX, aber ich finde die schrauben nicht gut, die halten bei beiden, seetronic und neutrik nicht so viel aus.
die blauen sind aber auch gefühlt etwas schwerer, was einen wertigeren eindruck macht, aber das bedeutet ja nichts.

die komplett schwarzen sind gefühlt etwas leichter, aber auch ca. 4mm kürzer. ich mag die schrauben mehr, die scheinen besser zu halten. die schrauben sind zwar dünner, aber die köpfe bleiben besser intakt.

ich glaube ich mag die verriegelung bei beiden von seetronic besser als die von den NL4FX, weil ich denke das man da besseren grip hat um die wieder zu entriegeln.

ich habe kabelendhülsen verwendet und dadurch war es bei beiden etwas knapp die kabel rein zu bekommen, ich glaube das ist bei NL4FX aber auch so. und ich habe bei beiden auch den kabelschutz der schon vorinstalliert ist drin gelassen, wenn man den rausnimmt ist das sicher auch einfacher.
bei den blauen musste ich die schrauben komplett raus nehmen, dann ging das reinschieben recht einfach, bei den schwarzen war es etwas schwerer, aber ich konnte die schrauben etwas drin lassen.

mir gefallen die schwarzen mehr, ich finde es immer mist wenn die schrauben schnell kaputt gehen.
schweißen / weld

* mostly TIG (WIG)
* aluminium bronze / silicon bronze 
* [[ Can You Weld Cast Iron?? |https://www.youtube.com/watch?v=usRMtTFKpmI]]
* [[Always learning: Brazing Cast Iron|https://www.youtube.com/watch?v=ZV6O8LIiW6w]]
* [[TIG Welding/Brazing Cast Iron Vise|https://www.youtube.com/watch?v=xQN_yz-4Hhg]]
* [[ Welding and Cast Iron Block Repair |https://www.youtube.com/watch?v=iyAykUm_Ykg]]
* [[ TIG Brazing a Repair on a Cast Iron Wilton Vise |https://www.youtube.com/watch?v=nUPFJVcDNLU]]
* silica/silicone bronze lot?
* wig mit nickel ist auch möglich wohl
* https://www.youtube.com/watch?v=VF-npEsJuE4&list=PL5uzLI8cqfnG62r4hDsGiGRobiVFBy8iM

braze

* [[ Braze Repair on a Broken Casting Part 1 |https://www.youtube.com/watch?v=wN3-4rN0n4E]]
* [[ Always learning: Brazing Cast Iron |https://www.youtube.com/watch?v=ZV6O8LIiW6w]]
* [[ Brazing Broken Cast Iron: Repairing a Stanley 55 Plane |https://www.youtube.com/watch?v=TyUE7uyQOW8]]
* [[ Norton Power Feed Gearbox Repair Part 1: Brazing |https://www.youtube.com/watch?v=ck8IepSvQyU]]
* ist es gusseisen, guss alu, guss stahl?
** graues gusseisen?
** weißes gusseisen?
** nodular/malluable?
* thermische ausdehnung
** komplettes Bauteil vorwärmen
** ca. 200°C?
* brass/messing lot
* flux auf kompatibilität achten
* werkstück einkerben (bevel)
important part of power electrtonics... used in (class-d) (audio-)amplifiers, inverters, motor controllers, [[switched mode power supply (SMPS)]], ...

* https://en.wikipedia.org/wiki/H-bridge
* https://de.wikipedia.org/wiki/Vierquadrantensteller
* buzzword used by politicians and intelligence agencies to sound good, but its fucking stupid what they mean
* https://ptrace.fefe.de/Hackback/
* https://www.kuketz-blog.de/hackback-zurueckhacken-ist-keine-loesung-sondern-riskanter-bloedsinn/
hacking means to extend the functionality of something, a device (hardware) or some software, in a creative way. contrary to the popular understanding hacking is not just maliscious breaking into computers/servers/IT-systems and stealing data or similar.

* [[https://de.wikipedia.org/wiki/Kategorie:Hacken_(Hardwareszene)]]
* https://github.com/Hack-with-Github/Awesome-Hacking
* Vernünftige Klimapolitik, auf die Wissenschaft hören!
* sichere migrationsrouten, förderung privater seenotrettung
* Lobbyismus transparent machen (Lobbyregister)
* Mitgliedsstaaten hart für die untergrabung von menschenrechtlichen und demokratischen grundsätzen bestrafen, darunter:
** gewaltenteilung
** pressefreiheit
* banken verstaatlichen
* Steueroasen unterbinden bzw. eine generelle, eu-weite steuer festlegen, steuern außnahmslos von allen unternehmen eintreiben, die geschäffte in der EU führen
* Internetgiganten kontrollieren, steuern eintreiben, monopole verhindern
* mehr völkerverbund statt wirtschaftsverbund
* Artikel 13 streichen
* vermögen gleicher/mehr verteilen, reiche wesentlich mehr besteuern
* genderpaygap schließen
* transparenz der ponlitische organe, ihres budgets/ausgaben/einnahmen und der entscheidungsfindung
* Vernünftige Klimapolitik, auf die Wissenschaft hören!
* Rechte strukturen in Bundeswehr und Polizei aufspüren und zerschlagen, rechtsextreme entlassen
* alternative zum Verfassungsschutz
* Subunternehmen-Werksvertrag Strukturen in vielen industrien verbieten und auflösen
** mindestlohn durchsetzen (am besten auch auf EU ebene)
** wohnungssittuation drastisch verbessern
** arbeitsschutz durchsetzen
** firmen kontrollieren
** betroffene industrien (u.A.): pflege, landwirtschaft, lebensmittel (fleischindustrie), zulieferdienste, etc.
* Lobbyismus transparent machen (Lobbyregister)
* open source fördern
* föderalismus stellenweise vereinheitlichen
** schulsystem
* vermögen gleicher/mehr verteilen, reiche wesentlich mehr besteuern - https://www.spiegel.de/wirtschaft/soziales/vermoegen-in-deutschland-viel-ungleicher-verteilt-als-bisher-angenommen-a-67e29ab7-2894-460d-92e9-53132437422e
* genderpaygap schließen
* transparenz der politische organe, ihres budgets/ausgaben/einnahmen und der entscheidungsfindung
* soziale ungleichheit abbauen
** https://www.youtube.com/watch?v=NfBSQ0Sbtwo
** [[bedingungsloses Grundeinkommen]]
* https://sound-au.com/manufacture.htm
* https://www.radwatch-dresden.de
* https://www.backblaze.com/blog/what-smart-stats-indicate-hard-drive-failures/
* https://www.backblaze.com/blog/hard-drive-smart-stats/
* [[Intro to Hardware Reversing: Finding a UART and getting a shell|https://www.youtube.com/watch?v=ZmZuKA-Rst0]]
* [[Philippe Laulheret - Intro to Hardware Hacking - DEF CON 27 Conference|https://www.youtube.com/watch?v=HuCbr2588-w]]
* [[Samy Kamkar's Crash Course in How to Be a Hardware Hacker|https://www.youtube.com/watch?v=tlwXmNnXeSY]]
* see also [[serial connection stuff]]
* [[Hacker's Guide to UART Root Shells|https://www.youtube.com/watch?v=01mw0oTHwxg]]

* [[Phil's Lab - Audio Electronics Playlist|https://www.youtube.com/playlist?list=PLXSyc11qLa1ZGY3nD7to5eQGKGMREhNGl]]
* [[Design Review (Buck + STM32 +Peripherals) - Phil's Lab #81|https://www.youtube.com/watch?v=eZnyBt2LVoc]]
* [[FPGA + PCIe Hardware Accelerator Design Walkthrough (DDR3, M.2, ..) - Phil's Lab #82|https://www.youtube.com/watch?v=8bw80LiCl7g]]

* https://www.digikey.de/en/resources/online-conversion-calculators

aethetics

* [[Aesthetic PCB Design Tips - Phil's Lab #84|https://www.youtube.com/watch?v=D2UaRPkRExw]]
the HK990 is a quite beefy HIFI AMP with 150W at 8Ohms and 300W at 4Ohms. It has two separate PCBs with chunky heatsinks for the channels and main power supply, two big toroidial transformers for each channel and an additional small supply for the logic and input boards. [[additional information|https://www.cnet.com/products/harman-kardon-hk-990-amplifier-series/]]

the one i got had problems with the right channel getting pretty hot even when not in use. the proplem is probably that the idling voltage is not adjusted, but that should be an easy fix. I quickly found a service manual [[here|https://www.eserviceinfo.com/downloadsm/40753/HARMAN-KARDON_HK990.html]] and [[here|https://www.eserviceinfo.com/downloadsm/47031/Harman/Kardon_HK990.html]], they describe the amp adjustment and it seems pretty easy.

* https://www.eserviceinfo.com/downloadsm/225516/Harman%20Kardon_HK-990%20&%20230.html

i started with opening the amp, removed the top of the case and then the side panels. i like the small cutouts they made on either of the side panels for the adjustment potentiometer, but there is no way to propperly reach the testpoints to meassure the idling voltage. it would've been very helpful to provide additional cutouts for those, but without them one has to pretty much disassemble the whole amp and take out both PCBs of the channels to reach them. the fact that there is no easy access for the testpoints is a big designflaw in my oppinion.

while disassembling i noticed that someone must have worked on this amp before, the wires supplying power to one of the amp board weren't cable tied, also the two amp boards looked slightly different, they had some different komponents on them. uppon closer inspection after i completely removed both amp boards from the amp i could see, that the boards have different revisions. one is an original revision 0 board and the other is revision 2. they seem pretty similar appart from some components from other manufacturers, with other coloring, but they all got the same values except for two resistors. they seem to have changed the resistors R96 and R97 (2.4kOhms 5%) from 2W ones to 3W ones. the original 2W resistors look a bit toasty and discoloured, they are probably a bit on the edge with their spec, so the 3W ceramic/cement ones from the newer revision will help with that.
Also while inspecting the boards i found a missing SMD part from one of the edges. It was ripped of the solderpads and the soldermask had a scratch in it. Because i was very careful while disassembling and i could not find that SMD part anywhere on my workbench i figgured it was probably the person before me. either way the solder pads are not damaged and it was pretty easy to find in the part labeled D8 in the service manual, it's a BAS20 diode. Because I allready wanted to order other parts from a distributor, i decided to search for matching resistors and the diode. I found the diode and i found 5W resistors. 5W is even more than the 3W replacements from the 2nd revision, but it shouldn't hurt.

after i recieved the parts i soldered the BAS20 Diode with a hot air soldering station and replaced the 2.4kOhm resistors with the higher power ones with a normal soldering station. I also had some small an thin heat-resistant insulators lying arround which i uses as insulators and spacers for the leads of the new resistors, because the higher power ones don't fit as well.

after soldering i connected testleads to the test pads 4 and 8 on the amp boards to do the AMP Iding Adjustment like descriped in the serivce manual. i carefully fitted the amp boards back into the case and connected all wires. after 5 minutes (or a bit more) of warm up time i adjusted the R53 labeled potentiometer so the voltage between the test points meassures +38mV on my multimeter.
I reapeated the adjustments several times with a couple of minutes in between, because the voltage would still drift a bit after adjusting.
You need to find a bit of a sweet spot, because it is always drifting a bit more after your adjustment, so it is best to adjust a bit less and let it settle out to 38mV.

as last step i assembled the whole amp and ziptied a couple of wires again.
* [[ Custom Tools - Brazing & Welding |https://www.youtube.com/watch?v=PCGBISlVKMM]]
* [[ Silver Brazing Tips |https://www.youtube.com/watch?v=no-OWfC5-RY]]
* https://www.sonderlote.de/

* [[gusseisen schweißen/hartlöten]]
* https://media.ccc.de/v/eh19-111-die-zwiebelfreunde-riseup-durchsuchungen
* https://media.ccc.de/v/np14-20-it_durchsuchungen
* https://media.ccc.de/v/35c3-10018-verhalten_bei_hausdurchsuchungen
* https://media.ccc.de/v/23C3-1346-de-sie_haben_das_recht_zu_schweigen
** https://media.ccc.de/v/c4.openchaos.2018.09.sie-haben-das-recht-zu-schweigen
* https://shop.digitalcourage.de/kategorie/digitalcourage-und-ccc-aufkleber/hausdurchsuchung-was-tun.html
* [[Hausdurchsuchung: 8 Tipps, wie du dich verhalten solltest! - Nutzerfrage XXL RA Christian Solmecke|https://www.youtube.com/watch?v=1_nODUMlwrc]]
* https://www.theverge.com/2019/11/7/20943377/chinese-hi-fi-audio-chifi-fiio-hifiman-tin-audio
* https://homebrewheadphones.com/3d-printed-bluetooth-headphones/
** https://hackaday.com/2022/08/05/build-your-own-3d-printed-bluetooth-headphones/
* [[Why Heat Pumps are Immensely Important Right Now|https://www.youtube.com/watch?v=MFEHFsO-XSI]]
* [[Heat Pumps Explained - How Heat Pumps Work HVAC|https://www.youtube.com/watch?v=QykwWs3L1W8]]
* are open source diy heatpumps possible?
* https://www.youtube.com/watch?v=m2mFhj9Uj6g
** https://efahrer.chip.de/news/heimwerker-bastelt-sich-waermepumpenheizung-jetzt-lacht-er-ueber-die-monatskosten_107708?utm_source=pocket-newtab-global-de-DE
* https://www.youtube.com/watch?v=BvI7A3NmY08
** https://efahrer.chip.de/news/genialer-hack-junger-ingenieur-bastelt-sich-waermepumpe-aus-klimaanlage_106898
* [[WIEDERBELEBUNG - Reparatur eines englischen Vollverstärkers Teil 1 - LECSON Quattra|https://www.youtube.com/watch?v=EZ3PkeIm0CQ]]
* [[Yamaha Receiver CR 600. Kein Signal am Lautsprecherausgang. Teil 1 Die Fehlersuche|https://www.youtube.com/watch?v=pc_8xZ1GUxM]]

! Denon dra-201sa

* symptom: water damage, amplifier goes into protect after switching on
* problem: one channel of the power stage is completely dead/fried
* manual
** https://www.eserviceinfo.com/downloadsm/95618/DENON_dra201sa.html
** https://www.manualslib.com/manual/1036642/Denon-Dra-201sa.html?page=37#manual
* ''service manual''
** https://www.eserviceinfo.com/downloadsm/70212/Denon_DRA-201SA.html
* parts on ebay are very expensive, bought at digikey
* dead chips/parts
** [[2SC4495 - NPN 50V 3A 40MHz 25W|https://www.semicon.sanken-ele.co.jp/sk_content/2sc4495_ds_en.pdf]]
** [[2SD2083 - NPN - Darlington 120V 25A 20MHz 120W|https://www.semicon.sanken-ele.co.jp/sk_content/2sd2083_ds_en.pdf]]
** [[2SB1383 - PNP - Darlington 120V 25A 50MHz 120W|https://www.semicon.sanken-ele.co.jp/sk_content/2sb1383_ds_en.pdf]]
** 1SR35-400A(T93X) replaced by 1N4007
** MTZJ2.7A T77 replaced by BZX79C2V7
* steps
** changing the main amplification chips didn't work, there is a problem somewhere else
** tracing out the signal path
*** [[LC72720N - Single-Chip RDS Signal-Processing System LSI; decoding the radio signal|https://www.alldatasheet.com/datasheet-pdf/pdf/127988/SANYO/LC72720N.html]], just one of the inputs, connected to the radio receiver module
*** [[TC9273N - Analog Switch Array IC, selecting the inputs|https://www.alldatasheet.com/datasheet-pdf/pdf/32129/TOSHIBA/TC9273N.html]]
*** [[TC9184AP - Electronic Tone (treble/bass) Control, over serial|https://www.alldatasheet.com/datasheet-pdf/pdf/32110/TOSHIBA/TC9184AP.html]]
*** [[tc9459f -  Electronic Volume Control, controled using serial|https://www.alldatasheet.com/datasheet-pdf/pdf/85187/TOSHIBA/TC9459F.html]]
** when checking the connections of the main power transistors of the broken channel i got a short between the base of the preamplifier and the output
** found two shorted diodes: D510 (diode 1SR35-400A(T93X)) and ZD502 (zeener diode MTZJ2.7A T77)
** ordered replacement diodes, could not find originals but found good matching alternatives BZX79C2V7 for ZD502 and 1N4007 for D510
** i replaced the diodes and soldered some bodge-wires for a blown track
** finaly i adjusted both output channels and played musik for some time as test. all fine and working again

! Pioneer X-HM20-S

* symptom: did not allways switch on when pressing the button, later didn't switch on at all. remote didn't work
* problem: dead (bulged/dried out) smoothing caps on the power supply part for the logic
* parts
** 2x 1000uF 16V caps see [[quality Electrolytic Capacitors]]
* repair:
** replaced the caps with new ones. the amp turns on again and even the remote works again.

! Sony str-db840

* manuals
** https://www.sony.de/electronics/support/audio-components-receivers-amplifiers/str-db840/manuals
* service manual:
** https://www.eserviceinfo.com/downloadsm/36003/sony_sony%20str-db840.html ?
** https://www.eserviceinfo.com/downloadsm/52362/Sony_STR-DB840%20%26%20STR-DB940.html

repairs

* searched some new fitting screws for the case
general information

* [[Off-grid Solar Buyer's Guide: DC Wire and Connectors|https://www.youtube.com/watch?v=Mb0LQ19DEaI]]

cables

* battery cables as used in cars (batteriekabel, fahrzeugleitung)
** pure copper! cheap cables might be aluminium or only copper-coated aluminium and have poor performance (higher resistance and bigger fire-risk)
* welding cables (schweißkabel)
** much more flexible than standard copper cables with the same performance
* [[How to Select and Purchase Battery Inverter Cables Part1|https://www.youtube.com/watch?v=p1bnHu14SMs]]
* [[How to Select and Purchase Battery Inverter Cables Part2|https://www.youtube.com/watch?v=YCUpMJEn2Zw]]
* [[Electric Cable & Fuse Sizing - Camper Van Conversion Series|https://www.youtube.com/watch?v=koFg6oFs0RU]]
* AWG (the american inch-based standard wire sizes) can me easily converted using 'calculators' or charts found online, but the sizes don't match exactly
* if you are unsure which size to use better use a size higher to be safer
* [[What WIRE GAUGE SIZE for amplifier install? How to calculate!|https://www.youtube.com/watch?v=u4E0ui8yeI8]]

cable terminals / copper lugs

* some people diy them
** https://www.youtube.com/watch?v=_saiwmG9zEc
** https://www.youtube.com/watch?v=CccZY6vnpo4
** https://www.youtube.com/watch?v=DVjzv_UUmE4
** https://www.youtube.com/watch?v=uNKfDVAtI_A
* soldering or crimping
** i don't quite know which is better, but in professional environments crimping seems to be prefered, because the cold welding might be better and it's faster... there are many different ways of crimping though...
** solding should only be used for amplications where there is no stress on the cable and crimping is prefered...
** i've seen videos where they crimp and then solder as additional meassure, but that seems overkill and might even have contra-productive effects
** soldering
*** https://www.youtube.com/watch?v=UMeGCQa-oCI
** crimping
*** there are a number of different tools, vice-like tools, Boltcutter-type crimpers, hydraulic crimpers and even powered and automatic ones
*** [[The PROPER WAY to Crimp Heavy Gauge Battery Cables|https://www.youtube.com/watch?v=-n7XW4Q8oXY]]
*** [[Crimping marine battery cable terminal lugs (the proper way)|https://www.youtube.com/watch?v=bvQ5qMTy_os]]
*** [[How to Crimp Large Gauge Wires (Battery Cable Lug, Ferrules & Ring Terminals) - AnthonyJ350|https://www.youtube.com/watch?v=ca37WnL6Oxo]]
*** [[How To Make Your Own Battery Terminals - The Ultimate Guide|https://www.youtube.com/watch?v=PqOa2d8v8Tw]]
*** [[How to Make Battery Cables the Right Way and the Easy Way|https://www.youtube.com/watch?v=XkMdlPsBxkc]]
*** [[How to Crimp Various Electrical Wires: Beginner and Expert Tutorial|https://www.youtube.com/watch?v=dTYyMwbSK7I]]

connectors

* XT30, XT60, XT90, XT150
* EC5, EC3
* MT30, MT60, MT90 / AS120
* TRX/Traxxas
* T-Plug/Deans connector
* Anderson
** SB50, SB175, SB350
** Powerpole
* din battery connector ("ravioli", "forklift") - hard to disconnect
* connectors used for welding equimpent
* [[ My favourite industrial connector (Ceeform). |https://www.youtube.com/watch?v=feCZs9YpH3M]]

bus bars

* [[Busbar Comparison Guide|https://www.youtube.com/watch?v=vziEq_3OlcU]]

der Mikrofonständer nutzt 1m Holzstäbe mit 2cm durchmesser, einstellbar soll der ständer über eine klemme sein. die klemme verbindet einen senkrechten stab, der im fuß steckt und einen angewinkelten stab, über die klemme kann die höhe und der der winkel eingestellt werden. die klemme besteht aus 4 backen, einer sterngriff-schraube und einer einschlagmutter.

die mikrofonklemme wird an ein 1/2" innengewinde Rohr-endstück geschraubt. das Rohr endstück kann auf einen der 2cm Holzstäbe geschraubt werden.
warum 1/2"? siehe [[https://www.gewinde-normen.de/zoll-rohr.html]]

mikrofonklemmen haben eigenartiges zollgewinde, üblich sind:

* 5/8 Zoll, 27 Gewindegänge pro Zoll, [[Unified Thread Standard|https://de.wikipedia.org/wiki/Unified_Thread_Standard]];
* 3/8 Zoll, 16 Gewindegänge pro Zoll, [[Whitworth-Gewinde|https://de.wikipedia.org/wiki/Whitworth-Gewinde]].

siehe [[Wikipedia: Mikrofonsänder|https://de.wikipedia.org/wiki/Mikrofonst%C3%A4nder]] und [[https://www.gewinde-normen.de/en/unified-coarse-thread.html]].

das 3/8" Gewinde fand ich besser für diese anwendung, weil ich Schrauben einfacher finden konnte.

der fuß besteht aus einem 1m holzstab, der in 3 gleich lange (ca. 33cm) stücke gesägt wurde und im 120° abstand an der basis verschraubt sind und ausgeklappt ca. 15° nach unten neigen, ein gutes dreibein.
<<list-links "[all[current]tagging[]]">>
''examples''

* http://www.foeoen.de/katalog/34.html - used by EG
* https://www.youtube.com/watch?v=DeCb93lhjhg - Realhorns Soundsystem

''ideas:''

* (semi) professional horn system like above
* janky but functioning horn system with cheap horn speakers (from china?), modular system
** horns mounted on modules which can be put in circles, half circles or quarters
** can be mounted on a normal speaker stand, or on other pole-type objects, even the rear of a lorry/truck
** active, amplifier on board? (simpler setup?, 3 cables) or passive and dedicated amp-box (1 cable per module)?
* using coax compression drivers?
* how low can compression drivers go? is bass possible?
* folded bass horn, druckkammerlautsprecher, folded horn
* amplifier?
* [[DSP|free/open/cheap DSP]]?
* http://www.hifi-forum.de/viewthread-127-3333.html
* http://www.hifi-forum.de/viewthread-182-7070.html
tops - fullrange

subwoofer - bass

* w-bins - low-mid
** https://perkhorns.wordpress.com/horns/w-bin/
* folded
** https://perkhorns.wordpress.com/horns/folded/
* tapped
** https://perkhorns.wordpress.com/horns/tapped/
** othorn https://www.diyaudio.com/forums/subwoofers/193418-othorn-tapped-horn.html
* front loaded
** https://perkhorns.wordpress.com/horns/frontloaded/
''Drivers:''

* BMS
** http://www.bmsspeakers.com/index.php?id=coaxial_neodymium_compression
*** http://www.bmsspeakers.com/index.php?id=4592nd_specification
* https://bcspeakers.com/en/products/coaxials-hf - https://audioxpress.com/article/test-bench-b-c-speakers-dcx464-high-power-coaxial-compression-driver-and-horn
* https://www.chinafuturesound.com/pd02x/
* https://www.alibaba.com/product-detail/high-and-mid-frequency-coaxial-speaker_62293114206.html?spm=a2700.galleryofferlist.0.0.5f176a9bp67kPX
* high-power compression driver - https://www.alibaba.com/product-detail/high-end-2-x-3-5_60803377720.html
* Celestion Axi2050 - https://celestion.com/product/174/axi2050/
* https://www.alibaba.com/product-detail/Coaxial-speaker-drivers-mid-range-and_1600083367885.html?spm=a2700.galleryofferlist.0.0.a68044a37oGHWn
* https://www.alibaba.com/product-detail/top-quality-2-x-3-5_1600062410369.html?spm=a2700.details.deiletai6.2.367821c2vEsrjO
* https://ethercalc.net/zolmj2uvumzm


''berechnung:''

* http://www.hornlautsprecher.de/helfer_kontur.htm - exponential horn?
* http://www.flo-horns.de/10Schritte/10Schritte.htm
* [[HIFI Forum: Wie berechne ich ein Horn 'zu fuss'...|http://www.hifi-forum.de/viewthread-104-5294.html]]
* [[HIFI Forum: HornTop - wie Mittelton Horn berechnen|http://www.hifi-forum.de/viewthread-267-890.html]]
* http://education.lenardaudio.com/en/07_horns.html
** http://education.lenardaudio.com/en/07_horns_2.html
** http://education.lenardaudio.com/en/07_horns_3.html
* https://www.ralf-he.de/horn-berechnung/
* AJHorn - http://www.aj-systems.de/index.htm - expensive, useless demo

"factors:"

* most stuff/informations is/are useless, it's not that easy
* impedance matching - matching the acoustic impedance the compression driver can move to the acoustic impedance of the air
* 1/4 (quarter) wavelength rule

how compression drivers are build:

*

''science and praxis (stuff)''

* [[World's Largest Horn Shatters Glass|https://www.youtube.com/watch?v=pFEB0chiuJA]]
** "World's Largest" is pretty clickbaity but still good channel
* [[How a horn amplifies sound (hint: Impedance matching)|https://www.youtube.com/watch?v=vcSc16tnVqk]]
* [[3-way horn speaker, DIY Bass horn|https://www.youtube.com/watch?v=Kr-sf6rwcXo]]
* [[Midrange Exponential Horn with 5" driver - 200Hz to 1600Hz +/-3dB - 103dB|https://www.youtube.com/watch?v=ecVXEFb0mXY]]
* https://www2.spsc.tugraz.at/www-archive/downloads/PA_MAURER_Basshornlautsprechersystem.pdf
* https://www.acoustic-design-magazin.de/grundlagen/gehaeusearten/hoerner/
* https://www.limmerhorns.de/%C3%BCbersicht/
* https://www.hifi-studio.de/ratgeber/smith-horn/
* https://www.youtube.com/watch?v=z3Mg68FAKic
* http://www.jobst-audio.de/public-address/h-serie/122-jh-sat212h
* Limmer horns - https://www.limmerhorns.de/
* http://kolbrek.hornspeakersystems.info/index.php/horns/exponential-midrange-1
* https://eurshdaily.blogspot.com/2011/08/power-up-bass-cannon.html
* https://www.academia.edu/33571411/ESTABLISHING_THE_PERFORMANCE_OF_A_DIY_TAPPED_HORN_LOUDSPEAKER?f_ri=1381325
* https://www.academia.edu/33571535/ESTABLISHING_THE_PERFORMANCE_OF_A_DIY_TAPPED_HORN_SUBWOOFER?f_ri=1381325
''Basics:''

* ein [[Horn|https://de.wikipedia.org/wiki/Horn_(Lautsprecher)]] ist ein [[Impedanzwandler|https://de.wikipedia.org/wiki/Impedanzwandler#Schall]] (bzw. Impedanztransformator), es passt die Möglichkeit des Treibers Luft zu bewegen an die Impedanz (hemmung) der Luft sich nicht zu bewegen an.
* "Mit der Querschnittsfläche des Schallkanals ändert sich die Wellenimpedanz, man spricht von einem Impedanztransformator."
* Hörner "transformieren den Schalldruck sehr effektiv in [[Schallschnelle|https://de.wikipedia.org/wiki/Schallschnelle]], um die Lautstärke deutlich anzuheben." - siehe https://de.wikipedia.org/wiki/Wellenwiderstand#Akustische_Wellen_bei_variablem_Querschnitt
* ''der Kompressionstreiber kann also einen hohen Druck erzeugen und durch das Horn wird dieser Schalldruck an die Luft gekoppelt und zu Schallschnelle, also schnelle Luftbewegung, gewandelt.''
* [[Akustische Impedanz|https://de.wikipedia.org/wiki/Akustische_Impedanz]] übersicht zu den drei Arten der Impedanz in der Akustik
** [[30-Second Physics: Acoustic Impedance|https://www.youtube.com/watch?v=9u2agHbvdHI]]
** [[Intro to Acoustics - 1.3 - Specific Impedance|https://www.youtube.com/watch?v=0Yxx1KypsvU]]
** [[12 Acoustic Impedance: Lecture by Dr. Eric Blackwell on History and Physics|https://www.youtube.com/watch?v=yPjFzF-8dlk]]
** https://newt.phys.unsw.edu.au/jw/z.html
** https://acousticstoday.org/7-the-world-through-sound-acoustic-impedance/#
** https://www.britannica.com/science/sound-physics/Impedance
** https://public.ostfalia.de/~harrieha/vl/mathe/2/arbeitsblaetter/impedanzv2.pdf
* https://physik.cosmos-indirekt.de/Physik-Schule/Akustische_Impedanz
* der Treiber kann eine Wellenimpedanz leisten?
* die Luft besitzt eine [[Schallkennimpedanz|https://de.wikipedia.org/wiki/Schallkennimpedanz]] bzw. einen [[Wellenwiderstand|https://de.wikipedia.org/wiki/Wellenwiderstand#Akustische_Wellen_im_Freiraum_(Schallwellen)]].
** Verhältnis von Schalldruck p zu Schallschnelle v: //__Z,,F,,__ = __p__/__v__// (komplex, hängen von Frequenz ab, [[Nahfeld|https://de.wikipedia.org/wiki/Nahfeld_und_Fernfeld_(Akustik)]])
** im [[Fernfeld|https://de.wikipedia.org/wiki/Nahfeld_und_Fernfeld_(Akustik)]]: //Z,,F,, = p / v = I / v^^2^^ = p^^2^^ / I = ρ * c//
*** [[Schallitensität|https://de.wikipedia.org/wiki/Schallintensit%C3%A4t]] //I//
*** [[Schallgeschwindigkeit|https://de.wikipedia.org/wiki/Schallgeschwindigkeit]] //c// in dem Medium (343,2 m/s (1236 km/h) in trockener Luft bei 20°C)
*** [[Dichte|https://de.wikipedia.org/wiki/Dichte]] //ρ// des Mediums ([[1,293 kg/m³ bei Luft|https://de.wikipedia.org/wiki/Luftdichte]])
** //Z,,F,,// = 413,5 kg / (m^^2^^ * s) bei 20 °C in Luft
* ein Horn ist auch ein Wellenleiter, weil Wellen fokusiert werden und sich nicht ungehindert ausbreiten können.
* https://de.wikipedia.org/wiki/Akustischer_Strahlungswiderstand



<<<
Thorbijoern
[Antwort auf ~RedNoise]
naja bei den tops noch nicht so extrem... so ein 300Hz horn ist nach meinen ersten berechnungen "nur" 35,4cm lang
bei den bässen hätte es dann viel mehr länge

~RedNoise
[Antwort auf Thorbijoern]
Brauchst aber auch nen Öffnungswinkel, sonst hast ne transmissionline
<<<



Wichtige/Interessante Hornformen

* [[Exponentialhörner|https://de.wikipedia.org/wiki/Horn_(Lautsprecher)#Exponentialhorn]] bzw. [[Exponentialtrichter|https://de.wikipedia.org/wiki/Exponentialtrichter]] sind wohl die einfachsten Hörner
** //A(x) = A,,h,, * e^^kx^^// beschreibt die Querschnittsfläche
*** //A,,h,,// Flächenquerschnitt des Trichterhalses
*** //k// Trichterkonstante bzw. Öffnungsmaß des Trichters
*** //A(x)// Flächenquerschnitt des Trichters im Abstand //x// vom Trichterhals
** //k = (f,,g,, * 4π) / c//
*** f,,g,, ist die angestrebte untere Grenzfrequenz des Horns
* Multicell Hörner bestehen aus einer Anordnung (Array) kleinerer Hörner, die an einen Treiber koppeln, die kleinen einzel-Hörner sind auf keine Horn-form festgelegt und können konisch, exponential oder anders geformt sein.

professional stuff

* [[Hornresp: Front Loaded Bass Horn Basics....|https://www.youtube.com/watch?v=D_yDGPH83XQ]]

"theory:"

* https://en.wikipedia.org/wiki/Horn_loudspeaker
* [[https://de.wikipedia.org/wiki/Horn_(Lautsprecher)]]
* [[https://commons.wikimedia.org/wiki/Category:Horns_(loudspeakers)]]
* https://www.itwissen.info/Hornlautsprecher-exponential-horn.html
* http://www.cieri.net/Documenti/Schemi/Altec%20-%20Loudspeaker%20Enclosure%20-%20Their%20Design%20and%20Use%20(circa%201975).pdf
* https://www.lautsprecherbau.de/grundlagen/theorie/gehaeusearten/10100,de
* http://www.excelsior-audio.com/Publications/QTWaveguide/QTWaveguide_WhitePaper.pdf
* https://jhsaudio.com/design.html
* ''https://www.grc.com/acoustics/An-Introduction-to-Horn-Theory.pdf''
* http://www.quarter-wave.com/Horns/Horn_Physics.pdf
* http://mh-audio.nl/Calculators/GExpohorn.asp
* [[Acoustics students design 3D printed horn loudspeakers|https://www.youtube.com/watch?v=vhHGBKulIgo]]
* [[Vibro-Acoustic 3D simulation of a compression driver with horn|https://www.youtube.com/watch?v=shudEyfrgXo]]
* http://www.hornlautsprecher.de/
* https://www.professional-system.de/basics/hornlautsprecher-basics/
* Wie berechne ich ein Horn 'zu fuss'...: http://www.hifi-forum.de/viewthread-104-5294.html
* http://education.lenardaudio.com/en/17_cinema_5.html
* Frontloaded Horn selbst bauen: http://www.hifi-forum.de/viewthread-104-17993.html
* https://zoneofthefree.blogspot.com/2010/10/got-horn.html
* https://en.wikipedia.org/wiki/Horn_Massive
* http://education.lenardaudio.com/en/07_horns.html
* https://www.youtube.com/watch?v=vcSc16tnVqk
* https://www.hifi-studio.de/ratgeber/smith-horn/
* en
** https://en.wikipedia.org/wiki/Impedance_matching#Acoustics
** https://en.wikipedia.org/wiki/Compression_driver
** https://en.wikipedia.org/wiki/Horn_loudspeaker
** https://en.wikipedia.org/wiki/Horn_(acoustic)#Horn_loudspeakers
** https://en.wikipedia.org/wiki/Acoustic_impedance
* http://mysite.du.edu/~jcalvert/tech/speak.htm
* http://www.vias.org/crowhurstba/crowhurst_basic_audio_vol1_049.html
* http://www.geocities.ws/la1zka/hifi/Hornexperiments/Midhorn.html
* "finite element method constant directivity" search
** [[Applying the Finite Element Method for ModellingLoudspeaker Waveguide Directivity|https://core.ac.uk/download/pdf/80702224.pdf]]
* https://www.prosoundtraining.com/2010/05/24/understanding-horn-directivity-control/
* https://darklanternforowen.wordpress.com/2014/04/13/tractrix-midrange-horn/
* https://www.slideshare.net/BertChenin/exponential-horn
* http://www.quarter-wave.com/Horns/Horn_Theory.html
* http://exertion.pbworks.com/w/page/86321986/Horns#
* http://www.victor-victrola.com/Fundamentals%20of%20Horns.htm
* http://www.victor-victrola.com/Victrola%20Horns.htm
* https://www.grc.com/acoustics/an-introduction-to-horn-theory.pdf
* https://education.lenardaudio.com/en/07_horns.html
* https://education.lenardaudio.com/en/07_horns_2.html
* https://education.lenardaudio.com/en/07_horns_3.html
* http://www.flo-horns.de/10Schritte/10Schritte.htm
* http://wp.volvotreter.de/dl-section/articles/
* BEM / FEM
** https://de.wikipedia.org/wiki/Randelementmethode
* https://en.wikipedia.org/wiki/Waveguide_(acoustics)
* https://blog.sciencemuseum.org.uk/in-search-of-perfect-sound-introducing-britains-largest-horn-loudspeaker/
* https://www.diyaudio.com/forums/multi-way/212513-spreadsheet-design-own-synergy-simple-conical-horns.html
* https://spot.colorado.edu/~pricej/downloads/AcousticWaveguides.pdf
* https://www.researchgate.net/search/publication?q=waveguides
* https://www.aes.org/e-lib/browse.cfm?elib=6997
* https://sound-au.com/articles/waveguides1.htm
* https://www.pispeakers.com/contents.html
** https://www.pispeakers.com/Pi_Speakers_Info.pdf
* https://www.reddit.com/r/audiophile/comments/5mcto0/what_is_a_waveguide_and_why_should_i_care_so_much/
* https://www.sweetwater.com/insync/constant-directivity/
* https://www.acousticfrontiers.com/201435speaker-off-axis-controlled-directivity-speakers/
* https://www.youtube.com/watch?v=r9-m17IPOco
* https://www.sciencedirect.com/topics/physics-and-astronomy/waveguides
* https://www.youtube.com/watch?v=Fmwu6AKPpBI
* https://asa.scitation.org/doi/abs/10.1121/1.2933071
** https://sci-hub.se/10.1121/1.2933071
* https://www.physicsclassroom.com/class/sound
* https://spot.colorado.edu/~pricej/downloads/AcousticWaveguides.pdf


''horn geometry''

* exponential (relatively easy)
* constant directivity (CD, about mid-easy)
** https://www.itwissen.info/CD-constant-directory-horn.html
** https://www.sweetwater.com/insync/constant-directivity/
* multicell (complex)
* exponential and CD horns are often used and are also made by BMS or B&C
** http://www.hifi-forum.de/viewthread-182-6160.html
** https://web.archive.org/web/20181213115304/http://www.bassreflex.de/Bauformen/Hornlautsprecher/CD_Horn/cd_horn.html
* https://www.araihorn.com/p/horn-design.html
* https://audioxpress.com/files/attachment/2705 - article    on      constant directivity  horn   design
** https://audioxpress.com/files/attachment/2720
* http://www.gedlee.com/Papers/What%20is%20a%20Waveguide.pdf
* https://web.archive.org/web/20180331074232/https://lockergnome.com/2011/09/09/how-do-waveguide-speakers-work/
* http://www.audioheritage.org/vbulletin/showthread.php?12751-Horn-Waveguide-Contour-Comparisons

scientific papers:

* https://asa.scitation.org/doi/full/10.1121/10.0001037
* https://www.comsol.com/paper/simulation-of-horn-driver-response-by-direct-combination-of-cd-frequency-respons-28561
* https://www.nature.com/articles/s41598-017-17511-x - Acoustic Waveguide Eigenmode Solver Based on a Staggered-Grid Finite-Difference Method
* ''https://www.comsol.com/blogs/simulating-nonlinear-sound-propagation-in-an-acoustic-horn/''
* https://www.yumpu.com/en/document/view/11706528/horn-physics-quarter-wavelength-loudspeaker-design
* https://www.grc.com/acoustics/an-introduction-to-horn-theory.pdf
* ''dinsdale et.al.''
** ''https://volvotreter.de/downloads/Dinsdale_Horns_1.pdf''
** ''https://volvotreter.de/downloads/Dinsdale_Horns_2.pdf''
** ''https://www.volvotreter.de/downloads/Dinsdale_Horns_3.pdf''
* https://www.akustikforschung.de/wp-content/uploads/publications/98/sarradj_schallfuehrung_hupen_daga98.pdf
* https://www.comsol.de/paper/download/290161/cinanni_abstract.pdf
* '' https://www.quarter-wave.com/Horns/Horn_Physics.pdf''
* https://www.diva-portal.org/smash/get/diva2:683355/FULLTEXT01.pdf
* http://lib.tkk.fi/Dipl/2010/urn100200.pdf
* https://www.youtube.com/watch?v=shudEyfrgXo
* high mid horntops
* https://de.wikipedia.org/wiki/Phase-Plug
* https://www.speakerplans.com/index.php?id=mt102
* https://www.speakerplans.com/index.php?id=mt122
* https://paforum.de/forum/index.php?thread/118869-low-boudget-horntop/
* http://hornplans.free.fr/
** http://hornplans.free.fr/mt130.html
** http://hornplans.free.fr/mt122.html
** http://hornplans.free.fr/mt121tda.html
** http://hornplans.free.fr/mt102.html
** http://hornplans.free.fr/f12cwh.html - i like those coax style builds
* synergy and unity horns
** http://www.hificircuit.com/community/threads/index-of-diy-synergy-and-unity-horns.23/
* pa mitteltonhorn diy: http://www.hifi-forum.de/viewthread-127-3361.html
* https://www.audiocircle.com/index.php?topic=112246.0
** http://www.bd-design.nl/forum/index.php?id=17095
* https://www.speakerhardware.com/jack-1x15-comp-horn-driver-kit.php
* https://uberspace.de/
* https://www.hetzner.com/
* https://www.netcup.de/
* github pages, gitlab pages (static site)
* readthedocs (documentation for open source projects)
* https://riseup.net/, https://www.systemli.org/index.html, https://disroot.org/, etc.
* https://ssl.greensta.de/
* https://homebrewserver.club/

easy self-hosting tools

* https://freedombone.net/
* https://www.freedombox.org/
* https://yunohost.org/#/
* https://ownyourbits.com/nextcloudpi/
* https://github.com/CherryKitten/CharjaBox - Ansible based Homeserver setup using Docker
* https://geek-cookbook.funkypenguin.co.nz/ 
* https://mailcow.email/
* https://github.com/khuedoan/homelab
** https://homelab.khuedoan.com/

stuff

* [[CC2tv #286 Eigener Server leicht gemacht|https://www.youtube.com/watch?v=JI5xPDA4Te0]]
* https://github.com/topics/self-hosted
* https://github.com/topics/selfhosting
* https://github.com/jackyzy823/fxa-selfhosting - Selfhosting your own Firefox Accounts (FxA)!
* https://lempstack.com/
* https://github.com/awesome-selfhosted/awesome-selfhosted
* [[#295​ Raspberry Pi Server based on Docker, with VPN, Dropbox backup, Influx, Grafana, etc: IOTstack|https://www.youtube.com/watch?v=a6mjt8tWUws]]
* [[#362​ Wireguard and NextCloud on a Raspberry Pi = Marvelous (Docker, IOTstack)|https://www.youtube.com/watch?v=7Pe-Cv0tnLs]]

professional

* https://checkmk.com/
** https://de.wikipedia.org/wiki/Checkmk
** https://en.wikipedia.org/wiki/Check_MK
* https://de.wikipedia.org/wiki/Icinga
* https://de.wikipedia.org/wiki/Grafana
* https://de.wikipedia.org/wiki/Prometheus_(Software)

ideas

* https://github.com/spantaleev/matrix-docker-ansible-deploy
* gitlab-ci->ansible->docker->matrix/etc.
* https://http.cat/
* https://en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol
** https://de.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol
bei den Werkstadtpirat:innen gibts eine alte Huhnholz Bohrmaschine, die etwas aufmerksamkeit braucht.
Die bohrmaschine wurde von anderen leuten zu einer Fräse modifiziert (wohl bevor sie zu den Werkstadtpirat:innen kam). 


* [[Finally Replacing That NOISY Bearing! - Variable Speed Milling Machine|https://www.youtube.com/watch?v=Puwd0-nLflQ]]
* https://de.wikipedia.org/wiki/W%C3%A4lzlager

Kugellager:

* ungefähr 20 47 14 lager
* skf wäre nice, aber viele fakes
* bei schloma kaufen?
* neue mit anliegender gummidichtung, das die resistenter gegen dreck sind
* SKF 6204-2RSH

Keilwelle:

* https://de.wikipedia.org/wiki/Keilwelle
* 16mm außen
* 10,6mm innen

Riemenscheibe:

* hat brüche/abplatzer
* gusseisen oder so
* hartlöten mit messing/bronze oder so
* wieder sauber drehen

Verbindung Keilwelle-Riemenscheibe

* ausgeschlagen?

Pinole

* https://de.wikipedia.org/wiki/Pinole
* läuft in bronze gleitlager/buchse

Werkzeugaufnahme

* Pinole hat MK$
* Spannfutter aktuell MK3
* reduzierstück MK4 zu MK3 (gekürzt)
* Mitnehmer von Keilwelle geht durch Hauptspindel und ist in MK3 geschraubt
* Werkzeug wechseln einfach durch Riemenscheibe und Spannfutter drehen/festhalten
* moves water using the energy of the water itself, not requiring energy input from other sources, but might be wasteful in regions with not much water
* https://de.wikipedia.org/wiki/Hydraulischer_Widder
* https://en.wikipedia.org/wiki/Hydraulic_ram
* https://www.youtube.com/watch?v=zFdyqTGx32A
* https://www.youtube.com/results?search_query=ram+pump

other

* https://de.wikipedia.org/wiki/Lambachpumpe
* https://en.wikipedia.org/wiki/Plunger_pump
** https://de.wikipedia.org/wiki/Plungerpumpe
* https://en.wikipedia.org/wiki/Piston_pump
** https://de.wikipedia.org/wiki/Hubkolbenpumpe
* https://de.wikipedia.org/wiki/I%C2%B2S
* https://en.wikipedia.org/wiki/I%C2%B2S
* https://de.wikipedia.org/wiki/Puls-Code-Modulation
* [[Building a Digital Music Player with I2S?! What is I2S! EB#45|https://www.youtube.com/watch?v=qNLvoSQCx60]]
"""
Ikarus 280.94T GVM (trolleybus)

length: 16.5 m
weight (full load): 23850 kg
seats: 35
standing places: 110

Motor: Ganz TK 110 K (DC Motor)
constant motor power: 196 kW
auxiliary motor (hydraulics) output: 12kW
acceleration: 1.3 m/s²
deceleration with rheostatic brake: 1.2 m/s²
deceleration with pneumatic brake: 5 m/s²

power grid voltage: 600V

the Motor speed is controlled using [[PWM|https://en.wikipedia.org/wiki/Pulse-width_modulation]] 
"""

Information Sources:

* ~~http://www.villamosok.hu/troli/index.html~~
* http://villamosok.hu/troli/ik-280-gvm/index.html
** English: http://villamosok.hu/troli/ik-280-gvm/e_index.html
** [[translation using google translate|https://translate.google.de/translate?sl=auto&u=http%3A%2F%2Fvillamosok.hu%2Ftroli%2Fik-280-gvm%2Findex.html]]
** the hungarian version goes into greater detail how the chopper works

possible modernisations:

* replacing the analog computer with a digital one
* using IGBTs instead of Thyristors for switching
** IGBTs are also used in modern inverters for electric cars (https://openinverter.org/]
* using a new motor, maybe synchronos AC motor with inverter circuit, old dc motor might be inefficient

Hardware vendors:

* https://www.kiepe.knorr-bremse.com/service_komponenten/vkproduktordner.2009-02-10.5149940469/vkproduktordner.2008-05-19.5586801525
* https://www.zf.com/products/en/buses/productfinder/driveline.html?filterLang=en
* absorbers/acoustic panels
* difusors

stuff

* https://hackaday.com/2021/03/15/theres-a-fungus-among-us-that-absorbs-sound-and-does-much-more/
* DIY ISP
* LoRa Mesh
** [[#337 LoRa Mesh Communication without Infrastructure: The Meshtastic Project (ESP32, BLE, GPS)|https://www.youtube.com/watch?v=TY6m6fS8bxU]]
** https://tinygs.com/
*** https://github.com/G4lile0/tinyGS
*** [[How to receive and track LoRa Satellites (TinyGS). Incl. innovative ideas for your projects|https://www.youtube.com/watch?v=ltJQjqm5bKA]]
* Briar (uses WIFI or Bluetooth if no internet is available)
* see also [[open and secure communication]]
* https://www.heise.de/hintergrund/The-Things-Network-Daten-mit-LoRaWAN-ueber-grosse-Entfernungen-senden-4172560.html
* mesh wifi
* using OpenWRT, LibreCMC, OPNsense, or similar

* https://freifunk.net/
** https://freifunkstattangst.de/

<<<
[Weitergeleitet aus Hacker News]
Winning back the Internet by building our own (Score: 100+ in 16 hours)

Link: https://readhacker.news/s/4AcTu
Comments: https://readhacker.news/c/4AcTu
<<<

* https://osmocom.org/projects
* https://www.youtube.com/watch?v=65r_1TzJXaQ
* animated leds
* hexapod / steward platform (3dof / 4dof)
* very black internal walls
** vantablack - stupid expensive
** black X.0 - expensive
** musou black - expensive
** black acrylic with coal mixed? activated coal?
** https://www.youtube.com/watch?v=Xr1AiExSAnU
* https://www.instructables.com/Warping-Infinity-Mirror/
* https://www.treehugger.com/
* https://www.lowtechmagazine.com/
* https://www.notechmagazine.com/
* http://www.humanpowerplant.be/
* https://www.lowtechmagazine.com/low-tech-solutions.html
* https://utopia.de/
* http://flood.firetree.net/
* http://www.n55.dk/MANUALS/manuals.html
* https://pedalkreis.org/low-tech/links/
* https://www.appropedia.org/Welcome_to_Appropedia
* https://www.ose-germany.de/
* https://publiclab.org/
* https://www.youtube.com/user/GREENPOWERSCIENCE
<<list-links "[all[current]tagging[]]">>

i don't have a good category for it, so i'll just tag it with kinda matching topics
(the informations here are very country-specific and not real legal advise)

germany:

* if you use an existing frame of a car and you don't do big modifications to that it seems that you only have to do EMC checks at TÜV
** https://www.tuv.com/world/en/electromagnetic-compatibility-%28emc%29.html
see [[serial connection stuff]]

* https://en.wikipedia.org/wiki/List_of_network_buses
* CANBus
* I²C / [[I²S]]
** https://hackaday.com/tag/i2c/
** https://hackaday.io/project/178271-i2c-master-mode-emulator
*** https://hackaday.com/2021/03/23/diy-i2c-tester/
*** https://github.com/dilshan/i2c-test-terminal
* https://github.com/twischer/esp-link
* [[Victron Energy communication protocols (VE.Direct, VE.Bus, VE.Can)]]
* serial ultrasound communication
** using build-in speakers and microphones to transfer data between devices without disturbing users
** https://www.anfractuosity.com/projects/ultrasound-networking/
** can also be used for side-channel and other attacks
* RS-458
** https://de.wikipedia.org/wiki/EIA-485
** https://en.wikipedia.org/wiki/RS-485
** https://hackaday.com/2022/04/05/hacker-dictionary-rs-485-will-go-the-distance/
* https://de.wikipedia.org/wiki/EIA-422
* https://de.wikipedia.org/wiki/Modbus
* https://en.wikipedia.org/wiki/UEXT
* https://libre.solar/thingset/
** https://libre.solar/thingset/1b_existing_solutions.html
** https://libre.solar/thingset/1b_existing_solutions.html#protocols
* https://learn.libre.solar/development/communication.html
* [[Reliable data transmission|https://www.youtube.com/watch?v=eq5YpKHXJDM]]

stuff

* https://www.digikey.com/en/articles/mcu-serial-interfaces-can-link-a-broad-set-of-peripherals
* see also [[protecting microcontroller inputs]]
* https://de.wikipedia.org/wiki/Occupy
** https://de.wikipedia.org/wiki/Occupy_Wall_Street
** https://de.wikipedia.org/wiki/Occupy_Germany
* https://de.wikipedia.org/wiki/Hambacher_Forst
* https://en.wikipedia.org/wiki/2019%E2%80%9320_Hong_Kong_protests
** https://www.youtube.com/watch?v=V0iytr0qM90
* https://pen.gg/
* https://politicalbeauty.de/
* https://www.youtube.com/watch?v=2zgMsWS91LU
* see [[LRAD]] for protection
* i'm pretty sceptical when it comes to IoT, most commercial devices are badly secured and solve problems nobody has
* i'm more into [[diy weather station, air quality monitor, environmental data]]
* if you get your power from [[Solar / renewable energy]] systems it might be very important and useful to monitor your energy yield and usage with [[powerlogging / power meter / AC power analysis / energy monitor]]
* https://openthread.io/
* [[EEVblog #1132 - The 3 Cent Microcontroller!|https://www.youtube.com/watch?v=VYhAGnsnO7w]]
** [[EEVblog #1306 (1 of 5): 3 Cent Micro - Open Source Programmer|https://www.youtube.com/watch?v=4fvFLSeDc4M]]
* [[This component can control tons of circuits! Digital Potentiometer Guide! EB#51|https://www.youtube.com/watch?v=uezoQ5fkixY]]
see also [[switched mode power supply (SMPS)]] and [[power electronics (Leistungselektronik)]]

* https://duckduckgo.com/?q=Inverter+design

!! inverters can be defined by

* the produced waveform
** square wave - just a coarse square wave with two steps, only suited for low-sensitivity applications, pretty seldom, not suitable for most applications
** modified sine wave - very coarse stepped rectangular waveform (thre steps: zero, + full power, zero and - full power); not the best for all appliances
** sine wave - finer stepped wave wich is not perfect but much closer to a real sine wave; should work with all appliances just fine; often work with (S)PWM similar to a Class-D audio Amp(?)
* type/input voltages
** "normal" solar inverter
*** using low DC voltages like 12V, 24V or 48V as input
** microinverters - meant to be used for single solar panels with 100W or more - https://en.wikipedia.org/wiki/Solar_micro-inverter
*** also include a Boost-stage with MPPT
*** nanoinverters - meant for small solar panels or single photovoltaic cells
** string or bigger inverters with other namings
*** often have input voltages from 300V to 400V
*** are often grid-tie
*** they are meant to be used on large arrays of solar panels connected in series (and parallel) and supply power directly to the mains grid
*** mostly comprised of the mains-switching h-bridge
* output phases
** single phase
** three-phase
* additional features appart from converting DC to AC (some features overlap)
** integrated charger - just an integrated charger for the connected batteries
** grid-tie - can feed the standard electrical grid and works alongside the grid or other inverters
** some kind of UPS (Uninteruptible Power Supply) functions
*** inverters with integrated chargers which charge the battery when there is power on the grid, but switch on in case there is an outage
*** netzvorangschaltung
** included MPPT - solar panals can be directly connected to the inverter featuring an [[MPPT - Maximum Power Point Tracking]] charge controller

!! general information:

* https://de.wikipedia.org/wiki/Wechselrichter
* https://en.wikipedia.org/wiki/Power_inverter
* https://de.wikipedia.org/wiki/Solarwechselrichter
* https://en.wikipedia.org/wiki/Solar_inverter
* https://www.lifewire.com/what-is-a-car-power-inverter-534721
* https://openei.org/wiki/Definition:Inverter
* https://en.wikipedia.org/wiki/Category:Inverters
* [[YTPower Inverters Explained - How do they work working principle IGBT|https://www.youtube.com/watch?v=iIqhAX0I7lI]]
* TEP
** https://www.theengineeringprojects.com/2012/11/basics-of-inverters-with-topology.html
** https://www.theengineeringprojects.com/2012/11/major-components-of-inverters.html
** https://www.theengineeringprojects.com/2014/12/introduction-multilevel-inverters.html
** https://www.theengineeringprojects.com/2012/11/pure-sine-wave-inter-design-with-code.html
** https://www.theengineeringprojects.com/2012/11/modified-sine-wave-design-with-code.html
* https://www.eevblog.com/forum/beginners/asking-for-resources-on-power-electronics-inverters-and-chargers/msg3306904/#msg3306904
* https://www.elprocus.com/what-is-an-inverter-types-circuit-diagram-applications/

!! circuit designs:

# switching the DC and using a transformer for stepping up - most basic/simple design, but finding high power transformers can be hard, due to the transformer working with 50/60Hz not the most efficient (around 80%)
# "transformerless"; using a step-up/boost circuit stepping up the DC Voltage and then switching the higher DC to produce the AC - uses smaller transformers in the boost circuit, more efficient due to the boost circuit using kHz frequencies, needs more filtering to filter the high freuencies
# z-source?
* a common method of achieving a pretty good sine wave is sPWM, there are prebuild spwm driver modules which can be bought for a few euros at ebay, but there are similar projects using uC's like Arduinos for the SPWM and these can be easily modified to have more functions
** https://github.com/MartinStokroos/openMicroInverter
** EGS002 boards with EG8010 Single Phase Sinus inverter ASIC and mosfet drivers
*** https://www.lz2gl.com/data/power-inverter-3kw/eg8010_datasheet_en.pdf
** https://github.com/Irev-Dev/Arduino-Atmel-sPWM
* there are some special designs wich are meant to funktion in both directions, DC to AC and AC to DC. the gaol seems to simplify design and reduce component count and maybe also the losses can be reduced...
** [[2-kW isolated bidirectional DC-DC converter reference design for UPS|https://www.youtube.com/watch?v=CYb6ZJCIyOs]]
*** https://www.ti.com/solution/single-phase-online-ups



!! security

* galvanic isolated: good practice when using such high voltages, no shorts when devices of the low-voltage and high-voltage side get connected or so (like cheap inverters for the car and some device connected to the aux in of the car radio), no loop currents (on some cheap designs the N is connected to + or - on the low-voltage side)



!! "transformerless" inverter design

input -> caps -> push-pull converter -> big caps -> h-bridge switched by 50Hz sPWM -> filtering

* stepping up the DC Voltage
** should be galvanicly isolated (see "security")
** the design depends on the required power
** push/pull-converter (Flusswandler) very common
*** see [[push-pull converter (DC-DC converter)]]
** EMV problems?, noise?
** efficiency?
** Fluss- und Sperrwandler. Und davon dann, Eintakt, Gegentakt und Mehrtakt/Mehrphasig
** converts the 12/24/48V into 350V DC + reserve
** for 230V RMS a peak voltage of around 325V is needed
*** 
* switching the higher DC to produce the AC
** using an H-Bridge
*** H5 design by SMA is a modification of the standard h-bridge
* basicaly includes 2 [[h-bridge]]s for switching, one switches a transformer rapidly for stepping up, one switches the 50Hz SPWM sine wave
** basically just powerful Class-D amps designed to only produce a 50Hz sinewave

https://sound-au.com/articles/inverters.htm


parts

* mosfets - general choice for switching
** SIC-MOSFETs are a good choice but expensive (might hurt more when they blow up)
* igbt's are useful above 100V (maybe for the mains-producing h-bridge)




!! some diy: (needs ordering)

* https://hackaday.io/search?term=inverter
* [[Example of three-level PWM single phase power inverter design (full-bridge)|http://postreh.com/vmichal/papers/three-level-PWM-power-inverter.pdf]]
* https://openenergymonitor.org/
* https://www.electronics-lab.com/open-inverter-an-open-source-micro-solar-inverter/
* https://sustburbia.blogspot.com/2015/10/openinverter-open-source-micro-solar.html?m=1 - https://sustburbia.blogspot.com/2015/10/open-inverter-part-6-thinking-allowed.html?m=1
* https://www.opensourceecology.org/call-out-for-inverter-project/
* https://wiki.opensourceecology.org/wiki/Inverter
* http://arduino42.com/
* https://github.com/gadgets-on-github/solar-inverter
* https://github.com/MartinStokroos/openMicroInverter
* maybe similar to [[motor controller / motor inverter]]
* https://github.com/SDI-SoftwareDefinedInverter/TAPAS/
* https://github.com/gonzojive/solar
* https://github.com/transistorgrab/OSSI - not finished, but explains a lot of the parts
* https://sourceforge.net/projects/os-si/
* https://github.com/tvixen/4KW-230V-Inverter
* https://github.com/texane/power_inverter
* https://github.com/PV-Log/Open-Photovoltaic-Inverter-Database
* https://github.com/pohsu/MIT-Pico-Grid
* https://github.com/jaw0/littlebox-power-inverter
* https://github.com/ThingEngineer/ReactorForge/wiki/ReactorForge-Hybrid-Driver
* https://github.com/cyysu/Inverter
* https://github.com/hildogjr/easyinverter
* https://github.com/hussamaldean/sPWM-ATMEL
* https://github.com/narongk/Arduino-Inverter-3-Phase
* https://github.com/kelvingakuo/Power-Electronics
* https://github.com/revyakin/avr-inverter-drive
* https://github.com/Jeet1994/MATLAB-SIMULATION-FOR-PWM-INVERTERS-IN-POWER-ELECTRONICS
* https://github.com/jpmatsci/INVERTER
* https://github.com/sibyjackgrove/SolarPV-DER-simulation-utility
* https://github.com/dfantonio/Single-Phase-Inverter-with-STM32F411
* https://github.com/Levitrevisan/STM32_Inverter
* https://github.com/charlieshao5189/Inverter_STM32/blob/master/README.md
* https://github.com/CREST-APV/InverterModelling
* https://github.com/atick-faisal/sPWM-Sine-Wave-Inverter-Arduino
* https://github.com/oOflowOo/inverter
* https://github.com/rusmanr/inverter
* https://github.com/Narendra-Walawalkar/Inverter
* https://github.com/mswati/inverter
* https://github.com/jerkey/inverter
* [[Does it suck? Chinese DIY Pure Sine Wave Inverter - Sinusoidal PWM (SPWM) Tutorial|https://www.youtube.com/watch?v=Dn2PFebi2ww]]
* https://sustburbia.blogspot.com/2016/01/open-inverter-part-8-general-purpose.html
* [[How to convert a Modified /Square wave inverter to Pure Sine|https://www.youtube.com/watch?v=GIsgjr0CU6Q]]
* https://sustburbia.blogspot.com/2016/01/open-inverter-part-8-general-purpose.html - a series of blog posts building some inverter it seems?

projects

* https://github.com/twischer/SineWaveGen - ?
* https://github.com/transistorgrab/OSSI - still in development but great docs
** ~~https://sourceforge.net/projects/os-si/~~ - old repo, moved to github
* http://www.arduino42.com/ - micro inverter design?
** https://github.com/gadgets-on-github/solar-inverter

stuff

* https://ieeexplore.ieee.org/document/7530373
* http://www.jetir.org/papers/JETIR1612001.pdf
* https://www.sciencedirect.com/science/article/abs/pii/S0038092X19301999
* https://www.edaboard.com/threads/bridge-inverter.395431/

* https://en.m.wikipedia.org/wiki/Little_Box_Challenge
* https://en.m.wikipedia.org/wiki/Solar_micro-inverter
* https://github.com/opengd/solar-sis
* https://github.com/www1374094/Three_Phase_Inverter_Base_dsp28335
* https://github.com/meltaxa/solariot
* https://github.com/slkakad?
* https://github.com/mitxela/phase-locked-inverter
* https://github.com/soldernerd/InverterControllerSoftware
* https://github.com/revyakin/acid
* https://github.com/motion55/SPWM.X
* https://github.com/slkakad/sine-PWM-
*https://www.ti.com/lit/an/slaa602a/slaa602a.pdf
* http://arduino42.com/intro.shtml does not output 240VAC
* [[YT: Electronic Basics #28: IGBT and when to use them|https://www.youtube.com/watch?v=RxRJW09A_XA]]
* [[YT: MOSFET BJT or IGBT - Brief comparison Basic components #004|https://www.youtube.com/watch?v=VlMdSCI29A0]]
* [[YT: Variable Frequency Drives Explained - VFD Basics IGBT inverter|https://www.youtube.com/watch?v=yEPe7RDtkgo]]
* [[Variable Frequency Driver | Variable Inverter|https://www.youtube.com/watch?v=FElPFGyNI3k]]
* [[Cheap 2000W Pure Sine Inverter Review and Teardown|https://www.youtube.com/watch?v=oLHQnnZSysQ]]
* https://circuitdigest.com/tutorial/three-phase-inverter-circuit-diagram-120-degree-and-180-degree-conduction-mode
* https://circuitdigest.com/tutorial/different-types-of-inverters
* https://www.digikey.de/reference-designs/en/ac-dc-and-dc-dc-conversion/dc-ac-inverter/2334
* https://www.digikey.de/reference-designs/en/ac-dc-and-dc-dc-conversion/dc-ac-inverter/539
* https://hackaday.com/tag/little-box-challenge/
** https://www.semanticscholar.org/topic/Little-Box-Challenge/2694125
** https://en.wikipedia.org/wiki/Little_Box_Challenge
* https://www.ti.com/reference-designs/index.html#search?keyword=inverter
* http://www.elkraft.ntnu.no/eno/Papers2008/Schimpf-norpie08.pdf
* https://web.archive.org/web/20131203011311/http://cms.uni-kassel.de/unicms/fileadmin/bilder/FB16/KDEE/PDF/Poster/DC_DC_AC.pdf
* https://www.solarchoice.net.au/blog/conventional-and-transformerless-inverters/
* https://ieeexplore.ieee.org/document/8684241
* https://de.wikipedia.org/wiki/H5-Topologie
* https://ieeexplore.ieee.org/search/searchresult.jsp?queryText=inverter&highlight=true&returnFacets=ALL&returnType=SEARCH&matchPubs=true&openAccess=true
* https://www.researchgate.net/publication/316456154_Grid_Connected_Inverter_Design_Guide
* https://www.digikey.de/reference-designs/de/ac-dc-and-dc-dc-conversion/dc-ac-inverter/539
* [[LE6_4a DC/AC Wandler - Dreiphasiger Wechselrichter|https://www.youtube.com/watch?v=rONYs_10mE8]]
* reference designs
** UPS designs might be a useful source of information and data
*** https://www.ti.com/solution/single-phase-online-ups
*** https://www.ti.com/solution/single-phase-offline-UPS
*** https://www.ti.com/solution/three-phase-ups
* https://www.ti.com/solution/string-inverter
* https://www.ti.com/solution/micro-inverter
* https://www.ti.com/solution/central-inverter
* teardowns - might give some information, might also be examples for good or bad design
** https://www.youtube.com/watch?v=P4JAYeKo1Z4
** https://www.eevblog.com/forum/other-blog-specific/teardown-of-the-flamezum-2000w-psw-inverter/


* [[Why are these Danfoss SOLAR Inverters So Inexpensive?|https://www.youtube.com/watch?v=mYQ3QQoeGsk]]
* https://www.youtube.com/watch?v=x-_PD2OzXuY
* https://www.microchip.com/design-centers/intelligent-power/applications/solar
* [https://www.akamaiuniversity.us/PJST8_1_4.pdf - Characterizations and Performance of a Solid-State Inverter and its  Applications in Photovoltaics  ?
* https://web.wpi.edu/Pubs/E-project/Available/E-project-042507-092653/unrestricted/MQP_D_1_2.pdf - DC/AC Pure Sine Wave Inverter

* https://www.hackster.io/alainstas/ltspice-inverter-simulation-with-thermal-effects-dadf6a
*https://www.hackster.io/dialog-semiconductor/design-and-implementation-of-a-single-phase-inverter-805dde
* https://www.hackster.io/philippedc/arduino-dc-12-24v-to-ac-230v-380v-3-phases-inverter-afe5e1

* https://en.wikipedia.org/wiki/Intelligent_hybrid_inverter
* [[Synchronverter]]
* [[ EEVblog 1518 - Hoymiles Solar Microinverter TEARDOWN |https://www.youtube.com/watch?v=_H4IP_iEzWw]]

* https://de.ifixit.com/Antworten/Ansehen/399577/Is+wood-paper+ESD+safe
* https://electronics.stackexchange.com/questions/93293/wood-workbench-as-esd-protection
* https://desco.blog/2014/09/29/paper-in-the-esd-protected-area/
* https://murraypercival.wordpress.com/2014/10/28/is-paper-safe-at-an-esd-workstation/
* 
isolation monitors are important as replacements for RCDs in applications where propper earthing of high-voltage installations is not possible (e.g. in mobile applications)

* https://de.wikipedia.org/wiki/Isolationsw%C3%A4chter
* https://en.wikipedia.org/wiki/Insulation_monitoring_device
* https://github.com/Tom-evnut/SimpISO
* https://www.ti.com/tool/TIDA-01513
* Bender IR 125Y-4 "isometer"
* [[ #151 - Versuchsaufbau mit PV-Isometer und Siemens LOGO SPS - Gerät aus Werksreparatur weiterhin o.F. |https://www.youtube.com/watch?v=FB01ZQn2V1c]]
* https://www.bsi.bund.de/DE/Home/home_node.html
* https://restoreprivacy.com/
* https://prism-break.org/
* https://www.privacytools.io/
* https://riseup.net/, https://www.systemli.org/index.html, https://disroot.org/, etc.
* https://www.eff.org/
** https://panopticlick.eff.org/
** https://www.eff.org/pages/tools
* https://thatoneprivacysite.net/
* https://droid-break.info/
* https://www.securemessagingapps.com/ - https://www.freie-messenger.de/
* https://www.reddit.com/r/privacy/
* https://securitycheckli.st/ - more mainstreamy
* https://webkay.robinlinus.com/
* https://forensicswiki.xyz/page/Main_Page
* https://digitalcourage.de/digitale-selbstverteidigung
* https://www.thinkprivacy.ch/
* https://degoogle.jmoore.dev/
* https://www.etebase.com/
* https://github.com/Lissy93/personal-security-checklist
* https://www.kuketz-blog.de/empfehlungsecke/
* https://github.com/pluja/awesome-privacy
* https://sec.hpi.de/ilc/search
* https://github.com/sbilly/awesome-security
* https://github.com/danielmiessler/SecLists
* https://www.hackthissite.org/
* https://torproject.org/
** https://snowflake.torproject.org/
* ansible
* jenkins
* https://saltproject.io/
** https://docs.saltproject.io/en/latest/
** https://docs.saltproject.io/salt/user-guide/en/latest/topics/overview.html
* [[EEVblog #499 - What is JTAG and Boundary Scan?|https://www.youtube.com/watch?v=TlWlLeC5BUs]]
* [[#03 - How To Find The JTAG Interface - Hardware Hacking Tutorial|https://www.youtube.com/watch?v=_FSM_10JXsM]]
* [[POLITIKANALYSE #10 - Kapitalismuskrise|https://www.youtube.com/watch?v=3XvCu0h9H54]]
* [[Hatte Karl Marx doch recht?|https://www.youtube.com/watch?v=6at-PpIv3fU]]
* [[Gregor Gysi über die Vorteile des Kapitalismus...|https://www.youtube.com/watch?v=NsmgqAxq4RI]]
* [[Klima vs. Kapitalismus – Brauchen wir einen Systemwandel?|https://www.youtube.com/watch?v=EOUovAzR2fg]]
* https://www.finanzwende.de/
* https://de.wikipedia.org/wiki/Gerhard_Schick
* siehe [[Genossenschaften]]
* https://sound-au.com/manufacture.htm

* [[Launchpad -- DIY or Buy -- Keyboard Matrix & MIDI Tutorial|https://www.youtube.com/watch?v=wyKStRyez5Y]]
* https://hackaday.com/2019/05/17/diy-button-matrix-lights-up-and-speaks-i2c/
** http://www.technoblogy.com/show?1YJO
* by wiring each column and each row in series you can minimize the needed inputs on a microcontroller
* small capacitors might be used to debounce, can be done in software too
* common problems described here: https://en.wikipedia.org/wiki/Computer_keyboard#Control_processor
* https://en.wikipedia.org/wiki/Keyboard_matrix_circuit
* https://learn.adafruit.com/mini-untztrument-3d-printed-midi-controller
** https://www.adafruit.com/product/1611
** https://www.adafruit.com/product/1616
** https://learn.adafruit.com/adafruit-trellis-diy-open-source-led-keypad/overview
** https://learn.adafruit.com/untztrument-trellis-midi-instrument
** https://www.synthtopia.com/content/2014/08/02/diy-arduino-native-midi-controller-the-mini-oontz/
** https://www.state-of-the-art.io/projects/matrix-midi-controller/
* DIY
** https://www.instructables.com/DIY-6-Button-Silicone-Rubber-Keypad/
** https://www.instructables.com/Make-Conductive-Rubber-Transparent-stylus-iPodiP/
** https://hackaday.com/2020/02/03/acrylic-mold-makes-for-professional-looking-silicone-keyboards/
** https://hackaday.com/2019/04/03/the-repair-and-refurbishment-of-silicone-keyboards/
* https://hackaday.com/2021/06/09/improved-technique-for-resistive-divider-keypads/
* https://hackaday.com/2020/12/17/adaptive-macro-pad-uses-tiny-oled-screens-as-keycaps/
** https://hackaday.io/project/176239-keybon-adaptive-macro-keyboard
** https://github.com/CoretechR/Keybon
* https://hackaday.com/2019/09/03/a-pocket-qwerty-for-arduino-and-more/
* https://hackaday.com/2019/09/03/a-pocket-qwerty-for-arduino-and-more/
wafer lock - Scheibenschloss/Plättchenschloss

* https://nl.m.wikipedia.org/wiki/Plaatjescilinderslot
* https://en.m.wikipedia.org/wiki/Wafer_tumbler_lock
* https://lockwiki.com/index.php/Wafer

stuff

* cam lock?
* https://de.wikipedia.org/wiki/Schl%C3%BCssel#Heutige_Schl%C3%BCssel:_Sonderformen_und_Varianten
* https://en.wikipedia.org/wiki/Lock_and_key
* https://www.art-of-lockpicking.com/types-of-locks/
* https://de.m.wikipedia.org/wiki/Schloss_(Technik)
* https://de.m.wikipedia.org/wiki/Sicherheitsschloss
*https://www.kicad.org/
* https://forum.kicad.info/t/tutorial-how-to-make-a-footprint-in-kicad-5-1-x-from-scratch/11092
* https://kicad.github.io/symbols/
* https://kicad.github.io/footprints/
* https://github.com/Digi-Key/digikey-kicad-library
* https://forum.digikey.com/t/importing-the-digi-key-kicad-library-into-kicad-5-0-0/4075
* https://kicad.org/help/getting-started/
* https://kicad.org/help/tutorials/
** [[KiCAD Quick-Start Tutorial|https://www.youtube.com/watch?v=zK3rDhJqMu0]]
* https://kicad.org/made-with-kicad/
* https://kicad.org/external-tools/
** https://github.com/xesscorp/KiCost
* https://www.baldengineer.com/custom-kicad-schematic-symbol.html
* https://hackaday.com/2021/08/03/tool-generates-interactive-pcb-diagrams-from-kicad/

eagle to kicad

* https://hackaday.com/2023/07/01/importing-eagle-projects-into-kicad-7-and-how-to-fix-them/
i've got two units of these really expensive devices from an electronics recycling place.
both have stickers "cleared for scrapping" but they look pretty great from the outside, some other gear i've seen from the recycling place looks much worse because it got thrown around.

!! general information

* https://klippel.de/products/qc-system/analyzer-hardware/pa-production-analyzer.html
* Case says Revision 1.1 (2006?)
* Main PCB says Revision 1.3
* Serial # 1307 and 1329
* missing powersupply, but seems to need 12V 24W
* power supply plug seems to be male 5-pin DIN connector with screw-locking (IEC 60130-9)
** [[like this one|https://www.voelkner.de/products/151288/Lumberg-SV-50-DIN-Rundsteckverbinder-Stecker-gerade-Polzahl-num-5-Silber-1St..html]]
** pin 1 GND
** pin 2 NC
** pin 3 ?
** pin 4 -12V
** pin 5 +12V
* #1307 has a USB-B card option build in
** PCB states "Phase Replacement Rev. 1.2.1
* fuses between poweramp input and speaker outputs are fine, but:
** #1307 has 5A Fuses fitted instead of the sticker stating 15A fuses
** #1329 has 15A fuses
* firewire doesn't seem to have ever been used
* "Digital I/O" looks like DB25 RS232 serial
* one of both has no feet, the other is missing one feet
* judging from the stickers about the fuses i have the default versions, see: https://www.klippel.de/fileadmin/klippel/Bilder/Our_Products/QC_System/PDF/Klippel_QC_Hardware%20Selection%20Guide%20PA.pdf

!! Internals

yet to come
* https://www.amplifier.cd/Tutorial/Klirrfaktor/Klirrfaktor.htm
* https://de.wikipedia.org/wiki/Klirrfaktor
*https://en.wikipedia.org/wiki/Total_harmonic_distortion#Definitions_and_examples
* Klirrfaktor Messen: http://www.hifi-forum.de/viewthread-136-391.html
* Somewhat crude THD+N calculator in Python: https://gist.github.com/endolith/246092
* https://github.com/endolith/waveform_analysis
* https://stackoverflow.com/questions/42077247/calculating-thd-in-python
* 400W RMS
* Fullrange design
* 4 Ohm
* they weigh 65kg each, atleast to what i found online, but i can tell you that they are fucking heavy.
* 2x 15" Electrovoice EVM-15L woofer
* 2x Renkus-Heinz comresssion drivers
** the compression drivers are most likely the first thing to burn out when the speakers are driven with to much power
** some people have replaced the Renkus-Heinzcompression drivers with RCF ND1710MT3
** a person i know has Nano 410 and replaced the RH with JBL 2426H
* H/W/D: 110/60/50 cm

they are heavy, like really heavy. You need atleast two people to transport them.
They feature two 15" woofers and a quite big high frequency horn with two compression drivers joined by a Y-part going into the horn.
possibly 3-way crossover so that the 15" drivers have different dedicated frequency ranges?
at least the compression drivers might be made by Renkus Heinz, but maybe also the woofers or the whole cabinet is made by Renkus Heinz.

The Klotz Nano 800 have NL4 Speakons but they use 2 of those lines for the Sense signals from the Speakers. To not run into problems you need all 4 wires connected to the Speakers and the Controller-Interface.

the smaller version is the Klotz Nano 400/410 and may be used with a Nano Bass 500 or Nano 1000 subwoofer or as a lower power fullrange.
The Nano 400 seems to originally have a 1" Compression driver Rhenkus Heinz SSD1800) and two 15" woofer (Electrovoice EVM-15L), total power of 300W by 35kg.
The Nano Bass 500 might be originally fitted with a 18" RCF-L18 woofer being able to consume 900W at 40kg.
The Nano 410 is the Touring version and the Nano 400 are the installation version.

The original 15" EV Drivers of the first versions only had 200W each. I got told the Rhenkus Heinz compression drivers are pretty low quality / have bad sound. One can replace them with JBL 2426H, which has a bit more power and better sound.


Klotz Micro PA (by Zebra) is also interesting: 2-Way or 3-Way Horntops and different bass horns (like w-bins, and other).

links with some data:

* https://gearsource.com/product/klotz-nano-800-loudspeaker-with-1kw/
* https://used-stage-equipment.com/ad-473180-Klotz+Nano+800+Lautsprecher+je+1kW+mit+RCF+und+Electro+Voice
* https://paforum.de/forum/index.php?thread/48031-klotz-nano-800-oder-dynacord-fe-15-3/
* https://www.manualslib.com/manual/169588/Electro-Voice-Pro-Line-Evm-15l.html
* https://paforum.de/forum/index.php?thread/65602-klotz-nano-pa-system/
* https://gebrauchte-veranstaltungstechnik.de/ad-447370-Klotz+Nano+800+Lautsprecher+je+1kW+mit+RCF+und+Electro+Voice
* https://paforum.de/forum/index.php?thread/89343-klotz-nano-400-1000/
* https://paforum.de/forum/index.php?thread/137912-ht-systems-klotz-pa/
* https://paforum.de/forum/index.php?thread/49670-klotz-controler-rpc-2/
Informations

* 2x 600W RMS @ 4 Ohm
* 21 kg
* 3.460.- DM new
* 1,8kVA transformer
* 2U rackmount
* Power transistors: Sanken 2SC3264 and 2SA1295
* power preamps/drivers: Sanken 2SC3263 and 2SA1294
* originally made by spanish company "aeq" but rebranded as Klotz it seems
** namely aeq 1201 and [[aeq 901|https://en.audiofanzine.com/dual-channel-power-amp/aeq/901/]] amps
** more obvious with this newer? design: https://www.diy-hifi-forum.eu/forum/showthread.php?9385-Klotz-PA1200-Reanimierung
* http://www.roehrenklingklang.de/LightNEasy.php?page=Klotz
** https://web.archive.org/web/20200208190259/http://www.roehrenklingklang.de/LightNEasy.php?page=Klotz
* [put more information here]

common problems:

* pins of LEDs break
** because the standoffs have very small holes and are very unflexible. the pins are under stress by vibrations because the LEDs are so far from the PCB. new LEDs are required and new, better standoffs with wider, oval holes for the LEDs pins
** i describe the same repair below
** same problem described here: https://paforum.de/forum/index.php?thread/32070-schaltplan-f%C3%BCr-klotz-pa-1200/&postID=294032#post294032
* a set of two 3k3 Ohms power resistors per channel burning out might also be a common problem
** https://paforum.de/forum/index.php?thread/32070-schaltplan-f%C3%BCr-klotz-pa-1200/&postID=290391#post290391

it seems that there were multible versions of these amps. i believe the one i got is an older version which uses normal 3mm LEDs in a vertical layout, but there are also pictures online which show a version with square LEDs in horizontal arangement.
i've also seen ones on pictures with "SAAVS - made by Klotz" branding.

smaller versions of these amps, like the P-A900 basically have the same PCB layout. in some forum messages i could find that the PCBs have even have 1200 written on them even though they are the 900 version.
the differences are mainly in the power transistors being a smaller number and the main capacitors being of a smaller size.
The 900 has an output of "only" 2x 450W @4Ohms


some sources:

* https://paforum.de/forum/index.php?thread/32070-schaltplan-f%C3%BCr-klotz-pa-1200/
* http://www.hifi-forum.de/bild/klotz-pa-1200_1060911.html
* https://www.diy-hifi-forum.eu/forum/showthread.php?9385-Klotz-PA1200-Reanimierung


!! Repair

''Problem: most of the LEDs were broken/not lighting up anymore, even the power LEDs even though the amp was working fine.''

The Problem is that the Pins of most LEDs broke. The LEDs are soldered to a small board which is mounted with some space behind the front panel. The LEDs are put through some standoffs/spacers and are soldered to the board. The spacers are aproximately 16mm in length which is quite long. The Pins of the LEDs all broke at the solder joints or at the plastic lense-body of the LED from vibration and stress. The standoffs have pretty narrow holes which likely is also a bad design choice. A better option would have been to solder the LEDs directly to the PCB, not to rely on the long pins and to use lightpipes instead, but changing it up now would be more hastle i think.
I decided to buy all new LEDs (not the original ones, but all colors from the same series of the same manufacturer) and 15,90mm long standoffs with more spacious oval holes which should reduce stress. Also i'm going to use small daps of elastic glue onto the standoffs and LEDs to maybe reduce vibrations but the Spacers are also from PVC which should be more elastic than the old ones. the front plate also features holes which are like countersunk for the LEDs which lasted the longest, i will countersink all holes to maybe reduce stress.

The LEDs of the dB output-display are driven by the [[LM3915N Dot/Bar Display Driver]] ([[Datasheet|https://media.digikey.com/pdf/Data%20Sheets/Texas%20Instruments%20PDFs/LM3915.pdf]]) which is a quite interresting chip also for DIY stuff.
!! Information

* Model: RPC/2-1
* Version: NA810
* version for NANO 800 speakers
** it seems only the program boards are different and depending
* no sub-bass functionality
* 1U rackmount

the PCBs inside the controller all have "Klotz" written on them, but entries in online forums state that the controller is made by Renkus-Heinz.

 * https://en.wikipedia.org/wiki/Renkus-Heinz
* https://renkus-heinz.com/

i could not find equipment that is similar to the controller in their "legacy" products page.

One function of the controller is to protect the drivers in the speaker cabinet, as to not supply them with too much power and have them go up in smoke. But the Controller also can get the most out of the Drivers to drive the speakers in the optimal way somehow.

namely automatic EQ and Limiter.
the Controller might also automatically detect if and which speakers are connected and have an automatic sctive crossover funktion when the speakers are used alongside subwoofers.

the Controller i got to repair only has the main functionality of being able to "process" two channels (stereo), the subwoofer/sub-bass parts are left out and there are only a cover for the hole of the connector in the back and some dummy LEDs which are not connected in the front. I'm unshure if a system including the sub-bass functionality would only like a 2.1 system because the sub-bass has just one DA-15 interface

The controller has a DA-15 socket (D-subminiature) for each Channel with all the inputs and outputs.
The audio input comes, along with the sense lines from the Speakers and the transformer isolated sense signal from the power send to the speakers into the Controller through the DA-15 connector. Directly out of the DA-15 plug comes the XLR Audio output which can be directly plugged into the AMP.

The Controller works completely using analog circuitry. Opamps are present as different DIP packages, but everything else is discrete.
There is a Power Supply PCB with a small toroidial transformer, some filtering and Linear regulators as well as the two "Main Board Fullrange" with each havin a "Fullrange Processing Card" daughterboard.
The space for the sub-bass processing is pretty empty because this is the fullrange version, but board has to be more narrow than the fullrange boards.

descriptions about the interface see below.

!! Repair

''Problem: The controller does not work and the "Aktive" LEDs remain off when switched on''

The LEDs are different from the ones used in the amp, they are 90° angled ones whith different spacers and the other LEDs work just fine. I could not test the LEDs yet, but they probably aren't faulty.

I decided to change a couple of capacitors on the Power Supply board, these probably aren't the problem because the voltages seem fine enough, but is doesn't hurt. The Class Y input Filter caps are visibly puffed up and probbably don't do the job anymore, the Class X Filter Cap looks fine but is old too. I'll change all of them with new ones from Kemet.
Also there are a couple of aluminium electrolytic caps which are know for their limited lifetime.
One of the bigger smoothing caps after the rectifiers looks slightly puffed up and all of the aluminium electrolytics are only 85°C rated. Most of them are near the Heat sink of the linear regulators wich only gets a little bit of passive convection cooling. The two 1A LDO linear regulators probably don't produce much heat, but i'll change all to new Rubycon caps rated at 105°C.

As predicted the caps on the power supply weren't the issue, the controller still doesn't propperly turn on.

The Processing boards use a lot of film capacitors which look like Epcos/TDK ~SilverCap Series which is uncoated/without case. I don't know much about film caps and what to look out for, but 2 or 3 of these caps look cracked and none of them have labeling wether they are 5% or 10% tolerance or so. Also i don't know if the production date of the controller was before Epcos started producing the ~SilverCap series or if other manufacturers had similar products. The trademark seems to be registered sinse 2002 or so. Epcos ended production of the Silvercap series in late 2020.

I could get some caps that looked pretty much the same like in the device, but i'm not sure if they are the same. I'm not sure which type of film capacitor would be a good replacement for these. If they are bad. see [[capacitors]]

I have to do further testing and reverse engineering to find the problem. I started reverse engineering the Power Supply module, there are a couple of transistors which switch a line going to all the boards but i don't know what they do.

!! Power supply

Semiconductors used:

* full bridge rectifier packages with little marking
* 2x LM2940CT-12
** 12V 1A fixed voltage low dropout linear voltage regulator
** [[Datasheet|https://pdf1.alldatasheet.com/datasheet-pdf/view/8856/NSC/LM2940CT-12.html]]
* BC140
** medium power silicon NPN transistor (marked "MEV BC 140")
** V,,CBO,,=80V; V,,CEO,,=40V; TO-39 Package
** still in production by many different manufacturers
* 3x C547B
** NPN general purpose transistor
** [[Datasheet|https://pdf1.alldatasheet.com/datasheet-pdf/view/16106/PHILIPS/C547B.html]]
** Philips datasheet from 2004 could match with production date and stuff
* 1N4148
**signal diode
** https://en.wikipedia.org/wiki/1N4148_signal_diode

...

!! Main Board

semiconductors used:

* CA3086
** general purpose NPN transistor array
** [[datasheet|https://pdf1.alldatasheet.com/datasheet-pdf/view/97179/INTERSIL/CA3086.html]]
* LM393 (LM393P)
** differential comparator
** [[datasheet|https://pdf1.alldatasheet.com/datasheet-pdf/view/27227/TI/LM393P.html]]

capacitors

* Epcos/TDK ~SilverCap Series or other uncoated film caps
* Roedenstein (ROE) EKU Series bipolar electrolytic capacitors
** could not find a datasheet since ROE was bought by vishay  a long time ago
** EK series ist polar and EKU series bipolar, derived from small shops selling remnants and from forum pots, also the EKU case is missing markings
** the case is wine red / ruby colored and bakelid, the bottom is filled with a yellow resin
** the case might crack which renderes the caps broken
* there are also a few orange tantalum electrolytic caps marked 1 35V maybe 1uF
** if they are bad they are likely to burn
* and some different common ceramic caps

!! Programm Card

The processing boards are smaller daughterboards which are mounted to the main boards with standoffs and connected with a normal header bar. The Boards i got have 3 stickers each. A sticker for (presumably) the serial number "#0043" and "#0044", stickers for a manufacturing date "3/92" (might be 3rd quarter of 1992) and a sticker reading "NA 800" indicating they are meant for the Nano 800 Speakers.

semiconductors used:

* 2x LM837 (LM837N)
** Low Noise Quad Opamp, by National Semi
** [[Datasheet|https://www.alldatasheet.com/datasheet-pdf/pdf/9059/NSC/LM837N.html]]
* TL074CN
** Low-Noise JFET-Input Opamp by TI
** [[old Datasheet|https://www.alldatasheet.com/datasheet-pdf/pdf/206612/TI/TL074CN.html]], [[new Datasheet|https://www.alldatasheet.com/datasheet-pdf/pdf/1333096/TI/TL074CN.html]]
* 3x RC4227 (RC4227FN)
** dual precission Opamp
** [[Datasheet|https://www.datasheetarchive.com/pdf/download.php?id=f780ec1a175ae45cb9109c3867b50abd1e61ae&type=M&term=RC4227]]

! Interface

the controller requires an Interface, which is just a small 1U rackmount Enclosure with no active circuitry inside, it does not need an extra power connection.
It features the nessesarry cabling on the backside for connecting to the amp and the Controller.
in the front are Speakon connectors for each channel and 2 for the sub-bass (which aren't used in this system) as well as XLR Connectors for input and one which is wired in parallel with the input as throu.
the connectors are soldered to a PCB inside the controller and for each speakon connector/amplifier output is a transformer.
i have not looked at it much, but the input signal goes directly to the DA-15 cable and the cables connecting to the amp go directly to the speakon.
The transformers have multible windings and might step down the voltage? they at least isolate the amp and controller.
On the end of the DA-15 Cable, directly at the DA-15 connector there is a small XLR cable going to the amps inputs.
The NL4 Speakon Outputs have the power form the amp and two sense lines connected.

!!! Wiring

Interface

DA-15 - Channel A/B


```
====  ===================  ==========
Pins  Description          Wire Color
====  ===================  ==========
1     Transformer sec. -   black
2     cable shield         unisolated
3     sense - (voltage?)   black
4     speaker sense +      blue
5     audio in -           black
6     nc		   -
7     nc     		   -
8     audio out +          red
9     Transformer sec. +   white
10    speaker sense -      black
11    sense + (voltage?)   green
12    audio in gnd/mass    unisolated
13    audio in +           red
14    audio out gnd/mass   unisolated
15    audio out -          blue
```

* audio out is the processed signal from the controller and goes through a microphone cable to the XLR of the amp.
* for each amp output a power resistor 25W 0.1 ohm 1%
* the speaker sense is implemented in the crossover of the speakers, a complete 4-wire NL4 speakon cable is needed for it to work
** FAGOR FB1506L
*** https://www.ebay.de/itm/373994826963
*** https://www.ebay.de/itm/325451685308
*** alternative? - https://pdf1.alldatasheet.com/datasheet-pdf/view/98984/ETC/FB1506L.html
** Kabel?



* https://www.diy-hifi-forum.eu/forum/showthread.php?3450-Verst%C3%A4rker-Absichern-welche-Feinsicherung
* 2x 250W @ ?Ohm
* http://www.kmt-sound.de/museum/museum.htm


brückengleichrichter + angeschmolzene kabel getauscht und platine sauber gemacht


~T4,2A fuses


<<<
also die carver die ich habe kann wohl 2x 600W auf 4 Ohm (2x 450W auf 8Ohm; stimmt das?) und hat eine träge 6,25A Sicherung, aber das ding ist irgendwie bisschen magic.

zu der KMT N500 finde ich nicht viel, hat aber wohl 2x 250W RMS
2x T6,3A pro kanal

die DAP palladium 1200 vintage hat F15A sicherung und 2x600W@4ohm / 2x400W@8Ohm
2x F10A pro kanal

wenn ich nach der DAP rechnung von den kanälen aus gehe KMT vlt. so T4,2A sicherung auf der primärseite?

wenn ich aber von der leistung der primär-sicherung ausgehe, dann sinds bei der DAP 15A*230V=3450W ~= 3*1200W
und bei der KMT wäre es vielleicht eher 2 x 500W = 1000W; 1000W/230V=4,35A würde da vlt. nur mal 2 statt mal 3 nehmen weil Träge sicherungen statt flinke?
4A klingt bei 500W vernünftiger als 9A

und nochmal anders ins verhältnis gesetzt:
1200W/15A=80
500W/80=6,25A
dann nochmal bisschen A weg, weil träge und nicht flink und wir sind auch wieder bei 4-5A sicherung

fidek fpa-10a
t10a primär vs je 2x t15a sekundär
2x 450w@8 / 2x 720w@4

da würden ~T4,2A primär für die KMT wirklich passen denke ich
<<<
the local makerspace Konglomerat (konglomerat.org) has a big wood CNC which is sadly out of order due to the controller having issues.

the controller is the open source buildbotics controller. it was send in to the us to the people who designed it, but it came back with still the same issues.

buildbotics controller

* https://buildbotics.com/docs/
** https://buildbotics.com/main-board/
** https://buildbotics.com/manual-v1-0-2/
* designed using [[gEDA]]
* https://github.com/buildbotics/bbctrl-pcb
* https://www.ti.com/product/de-de/DRV8711
** https://www.ti.com/lit/ds/symlink/drv8711.pdf
** https://www.digikey.de/de/products/result?s=N4IgTCBcDaICICUBqAOA7ARgyAugXyA



https://www.ti.com/product/DRV8711
https://www.pololu.com/product/3730

done:

* vor ort mit 24V labornetzteil auf factory default getestet - probleme immernoch



todo:

* links durchsehen
* caps checken
* passives checken
* mosfets checken
* traces checken
* grounds checken
* output der treiber/mosfets im oszi ansehen
* register und daten der treiber checken


"stepper driver problems"

 * https://www.brainy-bits.com/post/stepper-driver-stops-working-what-happened-and-why
 * https://www.st.com/resource/en/application_note/an460-stepper-motor-drive-considerations-common-problems--solutions-stmicroelectronics.pdf
* http://www.ostermann-net.de/electronic/sm_problems.pdf
* https://www.youtube.com/watch?v=UejSUgvbUgE
* https://arduino.stackexchange.com/questions/74841/stepper-motor-is-not-working-with-a4988-board
* https://www.steppermotors.net/stepper-motor-and-stepper-driver-troubleshooting
* https://forum.arduino.cc/t/problems-with-stepper-motor-driver-dm542t-version-4-0/960903
* https://eevblog.com/forum/projects/tb6600-stepper-driver-problems/
* https://blog.orientalmotor.com/troubleshooting-basics-stepper-motors
* https://www.ato.com/stepper-motor-troubleshooting
* https://reprap.org/wiki/Stepper_motor_driver
* https://learn.adafruit.com/all-about-stepper-motors/driving-a-stepper
* https://www.brainy-bits.com/post/stepper-driver-stops-working-what-happened-and-why
* https://www.reddit.com/r/Reprap/comments/l2wulu/has_my_stepper_driver_gone_bad/
* https://electronics.stackexchange.com/questions/559790/drv8825-stepper-driver-burning-up
* https://all3dp.com/2/what-s-a-stepper-motor-driver-why-do-i-need-it/
* https://3dsolved.com/3d-printers-stepper-motor-not-working-lets-fix-it/
* https://forum.pololu.com/t/stepper-motor-driver-36v4-4-units-all-burn/18644
* https://lastminuteengineers.com/drv8825-stepper-motor-driver-arduino-tutorial/
* https://www.brainy-bits.com/post/stepper-driver-stops-working-what-happened-and-why
* https://www.youtube.com/watch?v=jXCziYZx_ME
* https://www.youtube.com/watch?v=-l0cgNBeYu4
* https://www.youtube.com/watch?v=bkqoKWP4Oy4
* https://www.youtube.com/watch?v=UejSUgvbUgE
* https://www.youtube.com/watch?v=3R2sExPyiok
* https://www.youtube.com/watch?v=2sVxz7FX3QM


!!schematics

the design is completely opensource, but they don't simply provide schematics, one has to "build" them yourself using the sources. for that you need to use geda (https://www.geda-project.org/).
geda isn't really available on fedora it seems, so i quickly set up a basic debian VM in hopes i can get it to work there.
i installed pcb from the gEDA project, gerv and had to install lepton-eda for lepton-schematic. also you need build-essential installed for make (includes other stuff to, so you can also only install make, but you do you)
clone the repo to your machine: `git clone https://github.com/buildbotics/bbctrl-pcb.git`
then i ran `make schematics` and after that i ran the following command to export all schematics as a pdf:


```
lepton-cli export -f pdf -o buildbotics_schematics.pdf -p iso_a4 -l auto -c *.sch
```

stuff

* https://packages.debian.org/bookworm/electronics-pcb
* https://lepton-eda.github.io/lepton-manual.html/lepton_002dcli-export.html
* https://github.com/buildbotics/step-test
* [[Der Fall Amthor: Wie korrupt ist der Bundestag? - DIE DA OBEN!|https://www.youtube.com/watch?v=hOSGYo18T9Y]]
* Lobbyregister!
* [[Tranzparenz|Transparency]]
* https://www.abgeordnetenwatch.de/
got a broken Koukaam NETIO-230C smart power socket, its just a box with a IEC power in and 4 IEC power outs. it can be controlled manually through buttons or via ethernet or RS232.

internally its basically just a small smps, an Asix AX11005 microcontroller and 4 relays.

* Manual: https://www.manualslib.de/manual/299067/Koukaam-Netio-230C.html
* [[Asix AX11005 datasheet|https://pdf1.alldatasheet.com/datasheet-pdf/view/216363/ASIX/AX11005.html]]
** main feature is the integrated fast ethernet interface
* [[Sipex SP3232EE|https://pdf1.alldatasheet.com/datasheet-pdf/view/157037/SIPEX/SP3232EEA.html]] rs232 transceiver IC

i opened the device, took the pcb out and started with a visual inspection, i could not see any signs of problems.
so i assembled it partially again, plugged it in and switched it on. the smps made an audible high pitched sqeaking noise, that should not happen.

Its a bit odd that the smps is on a small daughter board, but the manufacturer probably needed a different power supply design and didn't want to redesign everything.
the smps is probably 12V and just low power, because such a device doesn't need much and the relays work with 12V and some caps near the smps are rated for 16V.

i tried measuring voltage on the smps, but without luck, the smps is probably dead or maybe there is a short. I could not measure an obvious short, but the integrated signal buzzer sometimes sounds continuously after switching it on, maybe just some glitch to so small voltages on switch on or so.

i decided to try powering it with my lab bench power supply, setting it to 12V and 1A max current. soldered a test cable to the PCB and it worked, the box booted and i could switch the relays.
the first LED was constantly red, but the manual states that's just the missing ethernet connection.

so the problem is the power supply. i desoldered it and under the small daughter board i could see the previous design. it looks like they originally planned on using a small print transformer and bridge rectifier for the job. but i wanna try salvaging the existing smps.

i also inspected the smps board visually, but nothing out of the ordinary. i tested the elektrolytic caps with my ESR70 and i can't measure the output capacitors, either they are faulty or i have to desolder them to measure them. so i desoldered them and tested them out of circuit, they were meassuring very high, i replaced the caps with good one out of my salvaged parts collection and soldered the smps PCB back onto the main board.

the following test was successful, the box booted successfully and i could switch the power outlets without problems.

there is another version with dual RS232, were the second RS232 port can be used to forward the commands to another netio-230 box, to control multible boxes with one serial line.
The DB9 connector is missing on the C Version, but you can just solder it yourself if needed i don't yet know if another firmware is needed, but the passive components for the second connection are there.
* Free HK - Proteste
** https://www.youtube.com/watch?v=32KTKXZZ-BI
* botschaften an gebäude projezieren
** https://netzpolitik.org/2019/wir-haben-da-mal-einen-geburtstagswunsch-aufs-kanzleramt-projiziert/
** Greenpeace, etc.
* https://pen.gg/
* https://politicalbeauty.de/
* moss/lichen (moos/flechten) graffiti
* [[Simulation of a Nuclear Blast in a Major City|https://www.youtube.com/watch?v=Z3RzNEzJyzo]]
* [[Death Count in a Nuclear War - The Shadow Peace, ep 1|https://www.youtube.com/watch?v=bIAF7kBbGKk]]
* Weapon exports fuel wars


<<list-links "[all[current]tagging[]]">>
* https://www.skf.com/de/products/rolling-bearings/roller-bearings/tapered-roller-bearings
** SKF ist qualitätshersteller, gibts aber auch viele fakes auf dem markt
** https://www.skf.com/de/products/rolling-bearings/roller-bearings/tapered-roller-bearings/single-row-tapered-roller-bearings
** https://www.skf.com/de/products/rolling-bearings/roller-bearings/tapered-roller-bearings/single-row-tapered-roller-bearings/bearing-data
** https://www.skf.com/de/products/rolling-bearings/roller-bearings/tapered-roller-bearings/single-row-tapered-roller-bearings/bearing-designations
** https://www.skf.com/de/products/rolling-bearings/principles-of-rolling-bearing-selection
** https://www.skf.com/de/products/rolling-bearings/principles-of-rolling-bearing-selection/general-bearing-knowledge/bearing-basics/standardized-boundary-dimensions
* https://www.schaeffler.com/remotemedien/media/_shared_media/08_media_library/01_publications/schaeffler_2/tpi/downloads_8/tpi_245_de_en.pdf
** https://www.schaeffler.de/de/produkte-und-loesungen/industrie/produktportfolio/waelzlager_gleitlager/kegelrollenlager/
* normen
** din iso 355
** din 720?
*** https://de.scribd.com/document/392821709/DIN-720-Kegelrollenlager
*** https://imgv2-1-f.scribdassets.com/img/document/392821709/original/775a4ec4cc/1595892409?v=1
*** https://imgv2-2-f.scribdassets.com/img/document/392821709/original/775a4ec4cc/1588190597?v=1
* https://de.wikipedia.org/wiki/W%C3%A4lzlager#Kegelrollenlager_(DIN_720,_ISO_355)
siehe auch [[nachhaltige/coole Initiativen in Dresden]]

wäre cool wenn sich leute zusammen tun und eine https://joinmobilizon.org/de/ instanz für dresden hosten würden. wie z.B. https://fomobremen.info/

* http://www.mukke-hilft.de/index.htm + https://spielraeume-dresden.de/
* https://blauefabrik.de/
* https://netzwerk-kultur-dresden.de/
** https://netzwerk-kultur-dresden.de/mitglieder/
* https://t.me/mittwochsdisko
* https://t.me/palaispalett
* https://t.me/objektkleina
* https://t.me/azconni
* https://t.me/VernetzungvonDresden/69
* https://www.startnext.com/kashaysalon
* rösslstube
* https://hanse3.de/
* https://www.rauze.de/ - mehr oder weniger inaktiv
* http://zope6.free.de/terminal - wird auch nicht mehr wirklich geupdated
* https://ticker.c3d2.de/ - scheint sich die daten automatisch zu ziehen
** https://gitea.c3d2.de/astro/ticker - sourcecode
** https://www.dresden-science-calendar.de/calendar/de
** https://www.medienkulturzentrum.de/angebote/kursprogramm-2/
** https://dresden-kulturstadt.de/ksdd_events/
* https://terminal.digital/

anderes:

https://www.bandbuero-chemnitz.de/
Hasomed ist eine firma, die eine extrem geschlossene software (Elefant) anbietet ohne überhaubt eine vernünftige eigenständige installation zu ermöglichen, da nur minimale infos bereitgestellt werden... die software ist ein zusammengestückelter haufen der scheinbar nie ein refactoring oder einen rebuild bekommen hat... schlechtes softwaredesign und kaum benutzerfreundlich...
hasomed zwingt die therapeut*innen den teuren service mit einer schlechten hotline zu bezahlen... denn anders kann man es kaum neu installieren... abgesehen davon, dass hasomed es nicht für nötig hält breaking changes wie das supportende von betriebssystemen anzukündigen oder dazu zu informieren...
Bei dem umzug euf einen neuen PC wird so z.B. empfohlen statt die software richtig neu zu installieren das komplette installationsverzeichnis zu kopieren.

die KV zwingt alle Therapeut*innen diese schlechte software zu nutzen und zwingt damit alle dazu diesen "service" zu bezahlen. im grunde ist es korruption, da nur von der KV zugelassene software (elefant) erlaub bzw. nutzbar ist und die KV sich immer neues ausdenkt damit hasomed auch immer neue updates raus bringen kann.
* https://www.pollin.de/p/quatpower-labornetzgeraet-ln-3003xiii-2x-0-30-v-0-3-a-5-v-3-a-351563
* [[cheap diy switchmode lab bench power supply (smps)]]

diy

* [[ Build a Small Dual Rail Linear Bench Power Supply. |https://www.youtube.com/watch?v=jBtNH1EbU8M]]
** [[ Bench Power Supply Testing, Homemade vs. Korad KA3005 vs. LongWei LW-K3010D |https://www.youtube.com/watch?v=RdT-xWC4h4k]]
Lab.Gruppen are mainly known for their professional high power amplifiers

* https://en.wikipedia.org/wiki/Lab.gruppen
* https://www.labgruppen.com/

there are a couple of companies selling rebranded/clones which are cheaper, but not allways as good as original, many selling the Fp10000q

* Sinbosen might be not as good - https://sinbosenaudio.com/
** "zu schwaches pcb weshalb die railvoltage irgendwie hoch katapultiert weil ne Leiterbahn abfackelt, das resultiert in einem schönen Feuerwerk"
** newer generations might be better
** "Aktuell haben die doch eher Probleme bei den endstufen Modulen soweit ich weiß"
* Sanway - https://www.china-sanway.com/
* PL Audio (Sanway) - https://pl-audio.de/
** from germany
** rebranded Sanway builds, other frontplate
* Gisen Audio
* Tulun


other

* [[LAB GRUPPEN CLONES FROM CHINA REVIEW|https://www.youtube.com/watch?v=1uej7HLzSk0]]
* https://de.wikipedia.org/wiki/Polyharnstoffe
* Tuff Cab
* warnex
* PU lack?
* https://en.wikipedia.org/wiki/LADSPA
* https://en.wikipedia.org/wiki/LV2
* https://en.wikipedia.org/wiki/Disposable_Soft_Synth_Interface ?
https://www.lambda-labs.com/de/produkte/kw-18

contrary to their advertising they have not designed and produced the amp fully in house.

the amp channels/modules are designed and manufactured by hypecs electronics, they are the UcD2k Boards

* https://www.hypex.nl/support/discontinued-products/ucd2k

they are marked with OEM, but from a bit of looking i could not find differences using the product pictures.

i didn't see the power supplies, but they also might be designed by hypex

these amps seem to be susceptible to surges/over voltage from generators. people i know had one blow up on them.
* primär mit landschafen
* bisschen hier erklärt:
** https://www.youtube.com/watch?v=v99yCU7e6PI
Idee

* großes modulares Akkupack mit Wechselrichter
* mehrere akku module und einzelnes Wechselrichter-modul mit schaltkasten und  kontrollelektronik



Zugehörig:

<<list-links "[all[current]tagging[]]">>



!! Bis zum Inverter

Zellen

daten

* triathlon tb 10508-v1
* https://www.triathlon-batterien.de/produkte/lithium-ionen-batterien
* https://www.triathlon-batterien.de/fileadmin/daten/02_Produkte/Lithium-Ionen-Batterien/Lithium-Ionen-Blockbatterie/Download/DE/2022_03_23_Lithium_Ionen_Blockbatterie_D_TBG.pdf
* 24-28,4V pro zelle (25,6V)
* 104Ah
* gebrauchte (eig. B-Ware)  24V 100AH LFP akkupacks von z.B. gabelstaplern
* jedes akkupack hat integriertes BMS mit CANbus support

Verschaltung

* 48V [[Kleinspannungs|https://de.wikipedia.org/wiki/Kleinspannung#Sicherheitskleinspannung_(SELV)]] (Sicherheitskleinspannung) system


Module

* 2 Zellen pro Modul in serie
* 48V @ 105Ah
* ~50kg, wäre noch zu zweit tragbar
* Sicherung (DC) für jedes Modul

Stecker

* industrie hochstrom steckverbinder
* mit datenkontakten für canbus und co
* am besten wasserfest
* Gabelstaplerstecker - aus dem bereich sind die akkus ja eh
** Anderson Stecker?
*** daten/hilfskontakte?
** DIN / Euro Battery Connector/Steckverbinder
*** 80A version sollte reichen, ansonsten gibts noch 160A+
*** Rema "DIN" Stecker
**** https://www.remagroup.com/steckverbinder/
*** https://www.andersonpower.com/us/en/resources/EBCResourcesPage.html
* Harting?
** harting alternativen?
*** https://paforum.de/forum/index.php?thread/25313-harting-und-alternativen/
*** https://www.amphenol-industrial.de/de/heavy-mate-Schwere-Rechtecksteckverbinder
*** https://www.tme.eu/de/katalog/hdc-steckverbinder_113616/
** https://www.harting.com/DE/de/produkte-loesungen
*** https://www.harting.com/DE/de/industrie-steckverbinder-han#Han%C2%AE-Baureihen
** https://www.thomann.de/at/10-pol_multipin_stecker.html
*** https://www.thomann.de/at/harting_09330102601.htm
* mehrere stecker?
* 


Kabel

* Schweißkabel?


!! Inverter Box

* korrekte absicherung erde/FI/isolationswächter
* Bender Isometer am AC out
* zusätzliche steuerung?
* freie software mit support für die schnittstellen des/der hersteller?
** Modbus/RS485 protokolle
** Ethernet/Wlan (IP)

* ausgänge CEE 32A, CEE 16A (drehstrom und wohnwagen) und schuko
* monitoring auf allen phasen
** entweder integriert in dem inverter oder extra energiemessgerät/drehstromzähler
*** je nach inverter hersteller bieten die auch solche geräte mit integration an (scheiß proprietärer vendor lock in)
** voltmeter
** frequenzmessung
** strommessung vlt. mit stromwandlern (current transformer)
*** https://de.wikipedia.org/wiki/Stromwandler
* Notaus schalter?
* can bus?
** scheint nicht offen dokumentiert
** vlt. nachfragen?
** mit zubehör sniffen und reverse engineeren?
*** wo bekommt man zubehör?
** ein defektes akkupack demontieren und reverse engineeren?



!! Modul Kisten

* Module haben Eurokisten Format oder normales Flightcase format
* Module stapelbar
* transport wahlweise auf Palette mit Gabelhubwagen oder auf rollbrettern
* oder haben alle module Rollen?


!! Laden

* Photovoltaikanlage
** Trennschalter vor dem anschluss
** trennschalter mit physischem lockout für stecker?
* IEC 62196 Typ 2 für laden von ladesäule?
** bräuchte vermutlich einen mikrocontroller zum kommunizieren und co
** https://de.wikipedia.org/wiki/Ladestation_(Elektrofahrrad)




Zubehör

* Stromverteiler/Stromwürfel/"Stromschildkröte"/Bau(strom)verteiler/verteilersteckdosen wasserdicht
* diverse stromkabel
* rollbretter?
* gabelhubwagen?
* kisten für zubehör

info

* https://de.wikipedia.org/wiki/CEE-Stromverteilung


stuff

* [[ Budget DIY Ecoflow Delta Pro! More power for less money |https://www.youtube.com/watch?v=fdeZz4QvxG0]]
* [[fucking big portable battery]]
* [[Big mobile Battery Project]]
* [[big (portable) battery]]
* https://de.wikipedia.org/wiki/EnergyBus
* https://de.wikipedia.org/wiki/OCPP
* https://de.wikipedia.org/wiki/ISO_15118
Förderung

* https://www.cargobike.jetzt/tipps/cargobike-kaufpraemien/

* bund
** ~~https://www.bafa.de/DE/Energie/Energieeffizienz/Kleinserien_Klimaschutzprodukte/Schwerlastenfahrraeder/schwerlastenfahrraeder_node.html~~
** https://www.bafa.de/DE/Energie/Energieeffizienz/E-Lastenfahrrad/e-lastenfahrrad_node.html
** https://www.bmuv.de/pressemitteilung/neue-bmu-foerderung-fuer-e-lastenraeder-und-mikro-depots-sorgt-fuer-sauberere-luft-und-mehr-klimaschutz/
* sachsen
** https://www.lasuv.sachsen.de/foerderung-lastenfahrraeder-pedelecs-4581.html
* https://www.fahrrad-xxl.de/beratung/lastenfahrrad/foerderung/
Grundlage

* Palette
** Paletti
** Kunststoff-Palette als Basis?
** Palette austauschbar bzw. nur geklemmt-verbunden?
* aus alt-Fahrrad Resten
* Alu-vierkant Rohre/Extrusionen wie XYZ Cargo Spaceframe oder ~VeloZack
* Alu Maschienenbau-Extrusionen

Verbinden:

* Schweißen
* Hartlöten
* Schrauben
** Stahl Rundrohre mit Einschlagkralle/Spannkralle (star nut) verbinden?
*** verbindung ist vermutlich nicht außreichend stark
** Alu/Stahl Vierkandrohre wie ~VeloZack oder XYZ-Cargo Spaceframe verbinden
*** mit Holz-inlay verstärken
see [[speaker plan lists]], [[speaker plans/designs]] and [[popular speaker plans / speaker copies / selfbuild speaker designs]]

!! 12" / 10" Tops oder so

leistungsstark

!! Akkubox(en)

besser als [[soundboks|Soundboks Internals (Teardown)]].

!! Horntops

3 wege wäre am besten, aber 2 wege ist vlt. einfacher

* https://www.jobst-audio.de/public-address/h-serie/122-jh-sat212h
* "cube" horntob clones?
** the box pro achat 112
** Dynacord FX12-PRO
** 4acoustics FCS-1712
* the box pro achat 208h clones?
* https://www.bs-tek.de/lautsprecher/fullrangelautsprecher/t0826/


!! (Horn)Bässe

* Tham15
* Cubo15
* tw audio b15 nachbau
* seeburg S115H?
* https://www.bs-tek.de/bausaetze/subwoofer/bs-18bph/

am sinnvollsten wäre wohl 15" oder eher 18" Bassreflex oder BR-Horn hybrid

schauen was gebraucht in die richtung zu finden ist

oder vlt. selbst bauen in richtung Cubo15 oder Cubo18... oder so

oder richtung:

* https://www.voice-acoustic.de/produkte/einzelkomponenten/paveosub-118.html#technische-daten
* https://proaudio-technology.com/en/product/vs18-subwoofer/

holz:

* https://www.holz-rentsch.de/unser-sortiment/platten/multiplex-platten/mn_22292
** https://www.ihr-holzshop.de/multiplex-holzplatte-birke-bb/bb-laengsfurniert?number=03-005-02-100-00033
* https://www.hornbach.de/shop/Multiplexplatte-Birke-BB-WG-1250x2500x18-mm-Zuschnitt-online-reservierbar/5084835/artikel.html
* https://www.bs-tek.de/
* https://www.jobst-audio.de/index.html
** https://www.jobst-audioshop.de/
(i don't know how these speakers are actually called but there's different names stated on the speakers and on the web)

Information:

* Fullrange/Tops
* Combination of one passive and one active Box with additional Output for the passive one
* Power: 500W RMS
* Impedance: 8 Ohm
* Connections: Speakon
* Woofer: 15" (8 Ohm, Neodymium)
** seems to be an Eminence Kappalite 3015? [[(Specs)|https://www.eminence.com/speakers/speaker-detail/?model=Kappalite_3015]]
* Tweeter: 1" Compression Driver
** original seems to be the BMS 4524 (25W, 8 Ohm) [[(Specs)|http://www.bmsspeakers.com/index.php?id=4524_specification]]
* https://www.bonedo.de/artikel/einzelansicht/ld-systems-stinger-series-ldeb-152-und-ldeb-152a/4.html

! 1st Repair

Symptoms: no high frequencies in the active box; amplifier cuts out with second, passive box connected

Problems: Tweeter burnt-out/blown; amplifier transistors might need to be replaced

These Speakers allready have seen much use... the owner fixed some bad soldering... but they where probably allready repaired before he got them... the passive one got an Eminence PSD2002-8 (8 Ohm, 80W) (Specs: [[Site|https://www.eminence.com/speakers/driver-detail/?model=PSD2002]]; [[PDF|https://www.eminence.com/pdf/PSD2002.pdf]]) with a CD Horn, the active got a BMS with a strange radial/exponential? horn. The passive Speaker is also missing the internal supports for the compression driver and only got vents where the active one atleast got a bit of reflex ports.
The Eminence PSD2002-8 doesn't sound as good as the BMS4524, it's not as crisp (due to the lower sensitivity).

These Speakers where pretty cheap, but use quality hardware, like a Bang&Olufsen amp. The boxes are a bit cobbled together and reflect the pricepoint more...
for example the passive crossovers are pretty different in both boxes

The BMS 4524 (25W, 8 Ohm) seems to be the original Tweeter

Solution: replacing the Diaphragm (can be bought separately); Problem: suppliers are rare and the best one let us wait 2 weeks just to refund us because they didn't have it in stock anymore.

Owners of the speakers decided to buy a new BMS 4524 and test the speakers... the tests went great and the amp seems fine too, no problems... now we wait for another BMS 4524 to replace the Eminence PSD2002-8.

i secured the big inductor for the woofer some more to the circuit board of the crossover, because it was broken before and was still not propperly secured. i just used a zip-tie which fit through 2 of 4 small holes left over from small broken pecks of the plastic inductor-carrier.

! 2nd Repair

Problems:

* woofer in the passive box without sound (probably the crossover again)
* compression driver in the active speaker is burned out again

repair:

the first repair was pretty easy, because only the big inductor in series with the woofer on the crossover was broken again. the zip-tie i used through the existing holes was to weak.
I carefully drilled these holes bigger and deburred them. then i used two zip-ties which are also bigger to secure the inductor again to the pcb. i hope these are able to withstand the rough handling. lastly i soldered the cable wich ripped out and tested continuity.

the burned out tweeter is a bigger problem though, because a new BMS 4524 is 80€+ again. The diaphragm is also available as replacement for around 40€ which is way cheaper... but the problem is, why does the tweeter blow at all?
i believe the owners do not use the speakers poorly, but i don't know if one can trust the passive crossovers used in both speakers... so I decided to reverse engineer the crossovers...
more info: [[passive crossover]]

adam hall ist BMS distributor in deutschland, jedoch haben die nur einen B2B shop: https://www.adamhall.com/shop/de-de/lautsprecherbau/hf-treiber-hoerner/1971/4524-l
* [[Battery Desulfation Demonstration Start to Finish - Part 1/2|https://www.youtube.com/watch?v=NcH-TwXJPmU]]
* [[How to PROPERLY Recover and Recondition a Sulfated Battery|https://www.youtube.com/watch?v=6x-JfckAt20]]
* ~40% DOD
* https://www.autobatterienbilliger.de/
* https://www.hoppecke.com/de/produkte/
my goals:

* should not be synthetic or atleast completely recyclable
* not animal-based, mostly plant based
* as biodegradeable as possible
* as sustainable as possible
* good properties for durable collars and bracelets
* no PVC, no petrol/oil based ingedients

lists/informations:

* https://www.leder-info.de/index.php/Veganes_Leder
* https://www.leder-info.de/index.php/Bioleder
* https://en.wikipedia.org/wiki/Artificial_leather
* https://www.peta.de/veganes-leder
* https://de.wikipedia.org/wiki/Kunstleder
* https://www.lifegate.com/people/lifestyle/muskin-leather-mushrooms
* https://www.vocativ.com/281599/vegan-leather-isnt-as-ethical-as-you-think/
* https://de.wikipedia.org/wiki/Kunstleder
* https://www.avesu.de/infocenter/vegane-alternativen.html
* https://www.vegan.co.at/veganes-leder/
* https://www.lederzentrum.de/wiki/index.php/Kunstleder

products:

* without synthetics
** Pilzleder
*** Kombucha
*** MuSkin
** Kakteenleder
** Kork
** Hanf/Hemp
* with synthetics
** https://en.wikipedia.org/wiki/Pi%C3%B1atex
** Paper-leather ~SnapPap - paper based, similar texture and strength
** recylced/upcycled rubber


there's also recycled leather using ground-up old leather and synthetics...

but most leathers don't seem to fit... seems like i have to still use nylon and/or neopren
* https://www.circuitbread.com/ee-faq/the-forward-voltages-of-different-leds
* [[LED Circuit Design - How to design LED circuits|https://www.youtube.com/watch?v=7d4ymjU9NqM]]
* [[LED Driver Basics and Its Circuit Design|https://www.apogeeweb.net/article/78.html]]
* https://www.ledsupply.com/blog/understanding-led-drivers/
* [[Building DIY LED lights|https://www.youtube.com/watch?v=Y06VHj1GvLI]]
* [[DIY Studio Lights - How to Build Your Own!|https://www.youtube.com/watch?v=DhbMnQt14_o]]
* [[Electronic Basics #8: Everything about LEDs and current limiting resistors|https://www.youtube.com/watch?v=Qlayua3yjuE]]
* [[KNOW HOW: LED lighting - Constant current LED drivers and series wiring.|https://www.youtube.com/watch?v=_YnZmQLOfA4]]
* [[LED Basics|https://www.youtube.com/watch?v=Yo6JI_bzUzo]]
* https://www.ledsupply.com/blog/what-you-need-to-know-about-leds/
* [[How to Turn an LED On|https://www.youtube.com/watch?v=zGsQbOjXeEs]]
* [[LED Driver (constant current)]]


controller for non-adressable LED strips or high power LEDs:

* [[ESP32 WLED Driver Board With USB Type-C Power Delivery - Voltlog #419|https://www.youtube.com/watch?v=jdCKJ26Zyw4]]
* https://grabcad.com/library/led-driver/details?folder_id=81610
* https://www.instructables.com/Easy-CAT4101-LED-Driver/
* https://www.instructables.com/Universal-High-Power-LED-Driver-with-3D-printable-/
* https://github.com/TeraHz/I2C-LED-Driver
* https://www.designnews.com/more-efficient-lighting-effective-led-driver-using-8-bit-mcu
* [[High Power Three-Channel LED Driver|https://www.youtube.com/watch?v=HkGtAK-_4ZM]]
* [[LED Powering Methods & How to Choose a Driver: CONSTANT VOLTAGE vs CONSTANT CURRENT (DIY BASICS)|https://www.youtube.com/watch?v=HSMUtYotx98]]
* [[EEVblog #392 - 555 LED PWM Hack|https://www.youtube.com/watch?v=OXsu29K_Ap4]]
* [[SDG #014 Designing a Constant Current DC-DC LED Driver - Part 1|https://www.youtube.com/watch?v=JOqSCbm9G0c]]
* [[SDG #246 Testing and Analysis of a dimmable high power 60W Synchronous LED driver|https://www.youtube.com/watch?v=VRHlG-_ypSU]]
* [[SDG #245 Design of a 60W Synchronous LED driver and Current Density Modelling in PDN Analyzer|https://www.youtube.com/watch?v=5B6fNz9gk0U]]
* [[High Power LED Tutorial #1 - How to Drive 1W and 3W LEDs from 12 Volts|https://www.youtube.com/watch?v=piET0Biqo0I]]
* [[High Power LED Tutorial #2 - How to Drive 5W & 10W COB LEDs from 12V|https://www.youtube.com/watch?v=Hboo3ZpNMPA]]
* [[Constant current source and laser / LED driver tutorial|https://www.youtube.com/watch?v=iuMngik0GR8]]
* [[How to Drive High Power LEDs With A DC-DC Adjustable Step-Down Module|https://www.youtube.com/watch?v=rDkP97-BHXI]]
* [[LED Tutorial: Light a 100W LED from 12V - Simple & Cheap|https://www.youtube.com/watch?v=8WjYmuUcvXo]]
* [[SDG #184 Build and Test of a 2.4A Constant Current Buck Regulator based on LM3409 LED Driver|https://www.youtube.com/watch?v=XFXVJ_Ijhjk]]

stuff

* [[Testing Power Supplies for LED Projects|https://www.youtube.com/watch?v=3Q28rSUzTp4]]
* [[SDG #014 Designing a Constant Current DC-DC LED Driver - Part 1|https://www.youtube.com/watch?v=JOqSCbm9G0c]]
** https://sdgelectronics.co.uk/led-circuits/designing-a-constant-current-led-driver-part-1/
* https://sdgelectronics.co.uk/led-circuits/designing-a-constant-current-led-driver-part-2/
* [[High Power LED Tutorial #2 - How to Drive 5W & 10W COB LEDs from 12V|https://www.youtube.com/watch?v=Hboo3ZpNMPA]]
* [[High Power LED Tutorial #1 - How to Drive 1W and 3W LEDs from 12 Volts|https://www.youtube.com/watch?v=piET0Biqo0I]]
* [[SDG #262 DIY High quality 20 W/m 90CRI LED strip with Cree LEDs|https://www.youtube.com/watch?v=Hf3CHTn1Lsg]]
* [[SDG #051 Driving RGB LEDs with 1 Constant Current Driver|https://www.youtube.com/watch?v=WSpkLsp_9_o]]
* [[SDG #100 - High Efficiency Constant Current 1W and 3W LED Driver - Lighting Controller Part 5|https://www.youtube.com/watch?v=gI8CK8zyRnM]]
* https://www.youtube.com/results?search_query=sdg+constant+current
* [[ How Addressable RGB LEDs are Made |https://www.youtube.com/watch?v=pMjhJ9kcaU4]]


tools

* [[ LED tester and comparison device |https://www.youtube.com/watch?v=A2c2JMWm5u0]]
* 360° Röhren
* verschiedene LED neon profile ausprobieren
* simple sticks mit LED neon streifen und alu profilen
* baustellen lampe mit WS2812 ringen/scheibe?

* led neon tube / led neon rohr/röhre/seil
* led neon streifen
* WS2811 WS2812B WS2813 WS2814 Ws2815
* SK6812
* https://de.aliexpress.com/item/1005005573206856.html - magic color
* led cob adressierbar
* https://de.aliexpress.com/item/1005004512744767.html
* RGB - 3 channels
* cold-white + amber + UV - 6 channels
* led strip verbinder bzw. verbindungen
* https://de.aliexpress.com/item/1005005627123008.html
* SK2812 WWA - https://de.aliexpress.com/item/1005001883751605.html
* WS2814 haben auch weiß?
* RGBWYV - xW chips
** https://de.aliexpress.com/item/32950854541.html
** https://de.aliexpress.com/item/4001119764668.html
* rgbwauv strip
* LED PAR Motherboard / mainboard led par licht
* lumiboost
* https://hackaday.com/category/led-hacks/
* https://hackaday.com/2012/08/14/how-to-design-your-own-led-driver/
* https://www.youtube.com/watch?v=QUtj9Dk9TVQ
* open source led boost
** https://oshwlab.com/enfoldit.dafonso/cc-led-boost-driver
** https://github.com/issus/150WLEDDriver_LT3756-2
** https://www.hackster.io/dymonxd/diy-grow-led-light-designing-a-better-sun-1adec1
* https://www.ti.com/lit/an/snva282b/snva282b.pdf
* https://www.ti.com/lit/pdf/slyt490
* https://www.ti.com/lit/SLVA419
* https://www.microchip.com/en-us/product/HV9910B
* https://www.youtube.com/watch?v=qlMtakaa7u8



stuff

* https://github.com/topics/boost-converter


* https://hackaday.com/blog/?s=ws2812
* https://hackaday.com/2019/05/07/lots-of-blinky-esp32-drives-20000-ws2812-leds/
* https://hackaday.com/category/led-hacks/
* https://hackaday.com/tag/rgb-led-matrix/
* https://hackaday.com/tag/led-matrix/
* https://hackaday.com/tag/rgb-led/
* https://hackaday.com/2019/03/26/can-you-live-without-the-ws2812/
* https://hackaday.com/2022/02/27/teaching-you-everything-you-might-have-missed-about-addressable-leds/
** ''https://www.derunledlights.com/the-difference-between-addressable-rgb-led-strip-ws2811-ws2812b-ws2813-ws2815-sk6812-sk9822/''
* https://hackaday.com/2014/02/02/rewriting-ws2812-driver-libraries-for-optimization/
* https://www.youtube.com/watch?v=Njzl4qC9_rY
* https://www.youtube.com/watch?v=nEdBhFB4Mpc
* led neon rope
* https://blog.ja-ke.tech/2019/06/02/neopixel-performance.html
* [[SDG #265 Easy Constant Current LED Driver with the AL5809|https://www.youtube.com/watch?v=4e4LAlr2hs8]]
* [[SDG #199 Aquarium Light Controller PCB and MQTT on the ESP32|https://www.youtube.com/watch?v=T5-nprH9-WE]]
I got two broken LED ceiling lamps, with one the LED driver was dead on arrival because the diode bridge shorted, with the other one the constant current LED driver has died.

!! shorted diode bridge

diodes were shorted, a track went up in smoke and the fuse was blown... ordered replacement parts and replaced the diodes and the fuse. I "reconstructed" the track with some thin insulated solid core wire.
it also looked like there was a emi suppression capacitor but it just wasn't populated and didn't burn.

after that i checked everything, to prevent another short and i connected it up and it worked.

!! not revivable led driver

i couldn't figure the problem out. the driver is pretty minimal but the chip is probably dead and it's not possible to find a real replacement.

the original has DC 150mA, 70-140V output (no load <= 150V)

the lamp has 5  PCBs with 6 LEDs each, all LEDs and modules in series. so 14V to 28V per PCB. each module requiring around 18V (~3V per LED).
max. 750mA if all PCBs are parallel.
the 150mA are reached at around 19,3V

as replacement i've ordered a 20W Driver that outputs 21-38V at 600mA. That doesn't drive the LEDs at full power, but that prolonges the life of the LEDs. They got pretty hot at 150mA.
I had to rewire the whole lamp so all modules are in parallel, but it works.
https://www.trilux-twenty3.com/fileadmin/PDFs/Produktdatenblaetter/DE/2350/2350_7374240_Datasheet_DE.pdf
* 16x16 ws2812b matrix penels can be found at aliexpress from 13€
* 8x8 or 8x32 is also pretty common
* adafruit has some, but they are more expensive
* there are also some with other leds and active circuitry but driving them is completely different

stuff

* [[ Driving hub75 LED panels. (including free test software)|https://www.youtube.com/watch?v=_dB1w99AwGE]]
* [[Inside the Project MC2 video purse. (Actual video wall panel!) |https://www.youtube.com/watch?v=CyLCwa2mneY]]
* https://github.com/2dom/PxMatrix
** https://www.arduino.cc/reference/en/libraries/pxmatrix-led-matrix-library/
** [[ PxMatrix on ESP32 driving 64x64 RGB LED matrix |https://www.youtube.com/watch?v=Kw1oYAoJP4s]]
* https://github.com/adafruit/Adafruit-GFX-Library
** https://learn.adafruit.com/adafruit-gfx-graphics-library/overview
* https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA
* https://www.youtube.com/watch?v=mF9df4QYprU
* https://www.youtube.com/watch?v=QUtj9Dk9TVQ
* https://www.youtube.com/watch?v=yzRHAdS9FLY
* https://www.youtube.com/watch?v=m4H2ftpWheU
* https://www.youtube.com/watch?v=FK7j8IgtUX0
* https://www.youtube.com/watch?v=PiaS8zfuBHo
* https://www.youtube.com/watch?v=NaAsBxi2Evs
* https://www.youtube.com/watch?v=6i8kzqvh94E
* https://www.youtube.com/watch?v=bu308tAqyIw
* https://www.youtube.com/watch?v=q1DxovtleYA
* https://www.youtube.com/watch?v=Zn_M8plmWfo
* https://www.youtube.com/watch?v=espfESarDkc
* https://www.youtube.com/watch?v=xSwoM3M24W8
netbook with a weird old Atom N270, i686 instruction set, not much power, 2GB RAM... enough to use for playing audio

!! setup

i first wanted to try out different OS (the i686/i386 images) from a multiboot usb, could only get Linux Mint to boot into live system but it didn't boot after installation, then tried again with debian 10.8.0 i386 netinstall and it worked.

i installed debian with XFCE4, followed the instructions for the bcm4312 wifi adapter here: https://wiki.debian.org/bcm43xx

installed some software:


```
apt update
apt install vlc ffmpeg pavumeter clementine python3-pip
pip3 install tidal-dl --upgrade
```

customized the xfce panels a bit

the official [[Behringer XAir (XR12/XR18)]] Software is only compiled for arm and x86 or so and therefor doesn't run on this i686 system. have to find alternatives

!! audio interfaces

* see [[audio interface / soundcard]]
* included ones seem to work fine
* creative e-mu 0202 - seems to be supported, not fully tested yet
** https://www.alsa-project.org/wiki/Matrix:Module-emu10k1-fpga
* Tascam US-122L - doesn't work yet
** not to be confused with the US-122
** https://www.alsa-project.org/wiki/Matrix:Module-usb-us122l
* Yamaha MG10 XU - not tested yet, should be class compliant

!! MTP support

debian and xfce didn't come with MTP support for transfering file to and from my smartphone out of the box. my device showed up with lsusb. i made sure that libmtp ist installed and it's the latest available version, then i installed mtp-tools and checked with mtp-detect if the device gets detected. mtp-detect detected the device and printed out a lot of information, everything fine, so i had to check further. installed gmtp, it needs some time to load, but works... it's just not as practical as the file manager thunar. i then found that i need gvfs-backends and gvfs-fuse for the mtp support in thunar: `apt install gvfs-backends gvfs-fuse`
I got a used Yoga Tablet 2 and wanted to use it as Linux Tablet/Convertible. The best part is that i got it with the matching bluetooth keyboard.

* Data: https://www.notebookcheck.net/Lenovo-Yoga-2-1051F.138465.0.html

!! Install

only a USB OTG adapter is needed so you can connect a USB stick and maybe a keyboard.
Kreata a boot USB-stick with the image you want and connect it with the USB OTG adapter, the installation doesn't differ from any other PC.

The first problem that i encountered was the Welcome/Start Window on the first boot of the freshly installed OS. Gnome uses 200% scaling by default and some applications or windows are not compatible, so some Text or Inputs might be off-screen. Thats also the case for that first window, you cant press the button to start the account creation. But that is easily solved using a USB keyboard. Just connect the Keyboard to the USB-OTG-Adapter and press enter. The button which is off-screen is convieniently pre-selected (because its the only input element on the page).
Then you can carry on the initial setup the normal way.

!! Drivers

Everything pretty much works out of the box because the device is a couple of years old and Linux has catched up.
WIFI, Battery Indicator, Sleep/Suspend and Screen Brightness work. Bluetooth seems to work mostly out of the box, but connecting the Keyboard does not work.

!!! setting up bluetooth drivers

The chip used in the yoga tablet 2 seems to be a weird UART connected one, so it will not show up with `lsusb` or `lspci`.
The Chip is a Broadcom BCM43241 and if you check dmesg (`dmesg | egrep -i "blue|firm"`) you can see that brcmfmac can't find the BCM4324B3.hcd Firmware/Patch File.

The following list contains Links that helped me. Sadly it's not as easy as installing the `broadcom-bt-firmware` package from rpmfusion nonfree-tainted because the required device is not supported by the package maintainer, but it's not much complicated.
Either you download the cab archive from microsoft like provided in the github issue and extract the file or you just download the single file from the daduke-blog.
Assuming the last digits of the filename is some version number the `BCM4324B3_*************.0161.hcd` is the most recent i could find and the file from the Blog and exctacted from the microsoft.archive are the same.
so


```
sudo cp BCM4324B3_002.004.006.0130.0161.hcd /lib/firmware/brcm/BCM4324B3.hcd 
```

and a reboot is needed an you should be able to pair the keyboard.

* https://daduke.org/linux/yoga.html
* https://github.com/winterheart/broadcom-bt-firmware/issues/6
* https://pcsupport.lenovo.com/de/en/products/tablets/yoga-series/yoga-tablet-2-1051/solutions/ht102593-bluetooth-keyboard-pairing-method-yoga-tablet-2-1050-2-1051-2-1371
this is just a small guide on how licences work in most legislations to help people not familiar with it understand the matter, it can be quite confusing. i'm not a lawyer an these informations might be inaccurate or wrong, it is just a mirror of what i understood during working with different works.

if you create something by yourself, say a drawing, photograph, pice of code/software, Design, etc, it is your property and you own the copyright.

except if you got paid for creating it, say in a company you're working for, it is most likely that you don't own the rights, your employer does. that is also a topic for artists in different fandoms, some have agreements, basic licences, along with the commissions that the artist still has copyright.

if you have copyright on something only you are allowed to copy it and distribute copies.

but if you are kind and want everyone to be able to use something you can't make agreements with everyone, you need something better:

* public domain - public domain means everyone is free to do whatever they want with some work, everybody/nobody has copyright. in some legislations works automatically enter the public domain after some time e.g. x years after the death of the author; in some legislations public domain can be a problem though, because they don't have that concept, so many advise on using [[Creative Commons Zero|https://creativecommons.org/publicdomain/zero/1.0/]] a public domain licence providing a better legal framework
* Licences - there are many licences with different features and for different uses, but some are also pretty universal
** Open Source Software - licences specially tailored to software, there is a broad range of options
** Open (Source) Hardware Licences - licences specially tailored to hardware, open hardware licences are more scarce, see [[Open Hardware Licences]]
** artistic licences tailored for art, drawings, photographs and such

some licences:

* https://creativecommons.org/
* MIT
* BSD
* GNU GPL, LGPL
* SIL Open Font License (OFL)

tools for choosing:

* https://choosealicense.com/
* https://creativecommons.org/choose/

stuff

* https://hackaday.com/2022/07/29/why-fedora-decided-to-give-cc0-licensed-code-the-boot/
** https://fedoraproject.org/wiki/Licensing:Main#Bad_Licenses
where to buy?
https://www.solarpaneltalk.com/forum/off-grid-solar/batteries-energy-storage/general-batteries/19671-best-places-to-buy-lifepo4-batteries
where to buy in germany?

* CALB cells cheap, a bit less energy density but usually good quality
** CALB = China Aviation Lithium Battery, but CALB seems to have developed to be the general term for a specific build-type
* GBS cell?
* >90% DOD
* https://de.wikipedia.org/wiki/Lithium-Eisenphosphat-Akkumulator
* https://en.wikipedia.org/wiki/Lithium_iron_phosphate_battery
* most need low themp chargin protection

testing

* [[Is it Time to Replace your Batteries? Here is how you can find out!|https://www.youtube.com/watch?v=VApJ_oaZAk0]]

types / designs/constructions

* aluminium case, often wrapped in blue foil
** often the cheapest, often used in automative applications (cars/trucks/busses)
* CALB-style, more smooth and rounded plastic case
* plastic case with channels like Winston/~ThunderSky

chemistries:

* ~LiFeYPO4 - added Yttrium enables charging at themperatures <0°C
* ~LiFePO4
** degrades when charged <0°C, should be a few degrees above 0 to safely charge, BMS should have low temp protection, some battery packs might contain added heaters controlled by the BMS
** only Winston/~ThunderSky produce them(?)


stuff

* https://basen.en.alibaba.com/index.html?spm=a2700.shop_plgr.88.12
* https://www.youtube.com/watch?v=2I-QdZFQqP8
<<list-links "[all[current]tagging[]]">>


stuff

* https://www.diychristmas.org/wiki/index.php?title=Special:AllPages
* https://wiki-de.dmxcontrol-projects.org/index.php?title=Kategorie:Selbstbau-Projekte
* https://en.wikipedia.org/wiki/Lignin
* https://de.wikipedia.org/wiki/Lignin
* [[bio polymer|bio polymers]]
* can be used for [[bio composite materials]]
* may be used as anolyte (electrolyte for the anode) for [[(redox) flow battery]]s
** https://doi.org/10.1021/acssuschemeng.8b00221
* [[Flüssiges Holz soll Plastik ersetzen - Galileo - ProSieben|https://www.youtube.com/watch?v=NZWCUOSf77Y]]
* [[Kunststoff aus Holz - Unser Land - BR Fernsehen|https://www.youtube.com/watch?v=1YW51MC3LBQ]]
* https://www.ndr.de/nachrichten/info/Der-Umwelt-zuliebe-Bioplastik-aus-Lignin,bioplastik106.html
* https://link.springer.com/article/10.1023/A:1021070006895 - Recent Industrial Applications of Lignin: A Sustainable Alternative to Nonrenewable Materials
* [[Die Sendung mit der Maus - Holzkunststoff|https://www.youtube.com/watch?v=eELodhjYF4o]]
* https://www.wdrmaus.de/filme/sachgeschichten/holzkunststoff.php5
* [[wood bike]]
* https://en.wikipedia.org/wiki/Line_array
* https://de.wikipedia.org/wiki/Line_Array
* http://www.burton-manor.co.uk/index.php/legacy
* https://forum.speakerplans.com/line-array-projects_topic27433.html
* https://forum.speakerplans.com/diy-compact-line-array_topic15820.html
* https://www.youtube.com/user/wwwAUDIOFANATICit/videos
* https://www.youtube.com/watch?v=zFnbY0f2998
* http://www.hifi-forum.de/viewthread-127-3354.html
* http://linearray.perkhorns.net/
* http://enclosures.perkhorns.net/
* https://www.academia.edu/32222727/Designing_and_Deploying_Line_Arrays_Line_Array_Architecture
* https://www.soundonsound.com/techniques/line-arrays-explained
* [[Line Array vs Point Source vs Human Hearing|https://www.youtube.com/watch?v=ytII-BY3EAo]]
* https://www.paulvdiyblogs.net/2017/07/my-new-power-supply.html
* https://www.paulvdiyblogs.net/2016/10/building-bench-tracking-dual-voltage.html
* https://sound-au.com/power-supplies.htm
* https://hackaday.com/2022/04/05/a-simple-linear-power-supply-done-well/
* https://hackaday.com/2019/02/09/power-supply-design-for-clean-jazz-amps/
* https://web.archive.org/web/20201112023448/https://sound-au.com/power-supplies.htm
* [[SDG #212 Why you don't need 10000+ uF on your voltage regulator output|https://www.youtube.com/watch?v=qosClvn9GqU]]
* https://www.learnabout-electronics.org/PSU/psu10.php - Power Supply Basics
* https://www.learnabout-electronics.org/PSU/psu20.php - Regulated Power Supply
es gibt nicht "die Antifa", Antifa steht für Anti-Faschismus, wird aber auch synonym für "die antifaschistische Aktion" benutzt, jedoch ist das nicht eine zusammenhängende gruppen, sondern viele ziemlich lose organisierte gruppen, die u.U. für bestimmte sachen zusammen arbeiten aber oft ihr eigenes ding machen.

Oft lehnen leute die gewalt "Der Antifa" ab und tun so als ob Antifa als gesammtes gewalttätig wäre... das ist aber nur ein kleiner teil, der durch die medien sehr stark dargestellt wird... der größte teil ist friedlich, zerstört kein Eigentum und greift auch keine Menschen an. Es gibt auch in der Antifa genug menschen die gewalt kategorisch ablehnen, mindestens so viele wie die, die gewalt anwenden.

Desweiteren unterscheiden linksradikale sehr zwischen den verschiedenen arten von gewalt. Es gibt so auch menschen in der linken szene, die neonazis bei einem gegenprotest nicht mal übertöhnen würden, weil si das schon als gewalt gegenüber den neonazis auffassen....

Im gegensatz zu den rechtsextremisten herscht nicht so eine starke vernetzung und zusammenarbeit. bei rechtsextremen gibt es die sogar zwischen ländern: e.g. deutsche rechtsextremisten die Separatisten in der Ukraine im Krieg "besuchen".


interessant:

* unter motorradclubs verstehen die meisten nur rockerclubs die sich als Outlaws im kriminellen bereich aufhalten, aber es gibt auch z.B. Kuhle Wampe https://www.kuhle-wampe.de/kuhle-wampe/was-wir-machen/
* [[Antifa: Alles Terroristen? - Kevin Kühnert & Tilman Kuban|https://www.youtube.com/watch?v=SA9DvABezmg]]
* [[Gewalt & Bedrohung gegen AfD-Politiker|https://www.youtube.com/watch?v=xg0ejl1f07c]]
* [[Leipzig: Polizei und linke Szene - unversöhnlich?|https://www.youtube.com/watch?v=Sjf-nioBK0I]]


paar quellen um vlt. zu verstehen wie sich journalisten mit der linken szene auseinander setzen. nicht alles ist schlecht, nicht alles ist gut, die szene ist halt nicht gerade einfach zu verstehen...

* [[Antifa: Was wollen Linksradikale? I reporter|https://www.youtube.com/watch?v=S3ziFuR49MQ]]


stuff

* https://riotaward1312.wordpress.com/
* https://www.linux.com/training-tutorials/linux-filesystem-explained/
* countles distributions, some with very special usecases and target, packaged with different combinations of software
* https://distrowatch.com
* https://mywiki.wooledge.org/BashPitfalls
* https://itsfoss.com/tux-trivia/
* https://xenia-linux-site.glitch.me/
** https://twitter.com/cathodegaytube/status/1197227512075411456
** https://twitter.com/cathodegaytube/status/1269405917700710400

setting keyboard layout on debian based systems:

```
sudo dpkg-reconfigure keyboard-configuration
```



in depth learning linux:

* https://wiki.gentoo.org/wiki/Handbook:AMD64
* https://itsfoss.com/compile-linux-kernel/ - A Guide to Compiling the Linux Kernel All By Yourself
* https://pipewire.org/
** "replaces"/is an alternative to pulseaudio and jack: pw comes with jack and pulseaudio compatible interfaces and should support all jack and pulseaudio applications. it should not be installed alongside jack or pulseaudio or you will have problems
** https://github.com/mikeroyal/PipeWire-Guide
** https://wiki.archlinux.org/title/PipeWire
* alsa
* pulseaudio
* jack
** https://linuxaudio.github.io/libremusicproduction/html/articles/demystifying-jack-%E2%80%93-beginners-guide-getting-started-jack.html
* [[Why I switched to Linux for Audio/Music Production|https://www.youtube.com/watch?v=5lMS2yoIrrI]]
** [[Linux Music Production|https://www.youtube.com/playlist?list=PL-49ES0c-XKkbm2wwyEH6E82R7VPy5_zd]]
* https://wiki.ubuntuusers.de/Soundsystem/#Soundserver
* ''https://ubuntuforums.org/showthread.php?t=205449 - Comprehensive Sound Problem Solutions Guide''
* https://alternativeto.net/software/qpwgraph/about/
* https://alternativeto.net/software/pulsemeeter/about/
* http://sox.sourceforge.net/Docs/Features
* https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Modules/#module-sine
** `pactl load-module module-sine frequency=440; read; pactl unload-module module-sine` (stops on keypress)
* ffmpeg
** https://ffmpeg.org/ffmpeg-filters.html#sine
*** https://superuser.com/questions/724391/how-to-generate-a-sine-wave-with-ffmpeg
** https://www.ffmpeg.org/ffmpeg-devices.html#lavfi
** https://ffmpeg.org/ffmpeg-filters.html#Audio-Sources
*** https://ffmpeg.org/ffmpeg-filters.html#anoisesrc - several noises
*** https://ffmpeg.org/ffmpeg-filters.html#aevalsrc - takes arbitrary mathematical expressions
** https://stackoverflow.com/questions/11831214/how-to-run-ffplay-as-a-window-less-process/53295994#53295994
* Audacity
* online tools
** https://onlinetonegenerator.com/
* https://linux.die.net/man/1/speaker-test - generates pink noise and sine waves
* 

programming:

* https://stackoverflow.com/questions/732699/how-is-audio-represented-with-numbers-in-computers/36510894#36510894 - minimalist c example
* alsa
** https://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2pcm_8c-example.html
* https://medium.com/@olehc/lets-write-a-simple-sine-wave-generator-with-c-and-juce-c8ab42d1f54f
* https://stackoverflow.com/questions/8299303/generating-sine-wave-sound-in-python

sources:
* https://stackoverflow.com/questions/5109038/linux-sine-wave-audio-generator
https://openprinting.github.io/cups/
* http://localhost:631/


HP

* https://fedoraproject.org/wiki/Printing/HPLIP
* https://www.openprinting.org/printer/HP/HP-DeskJet_840C
* https://forum.ubuntuusers.de/topic/hp-deskjet-840c-installieren/2/#post-5479542
* Buying a Linux-ready laptop | Opensource.com https://opensource.com/article/19/7/linux-laptop
* see also [[open computer firmware]]


Companies:

* Clevo
** Tuxedo Computers
** https://www.schenker-tech.de/
* Thinkpad
* https://system76.com/
* https://mntre.com/media/reform_md/2020-05-12-mnt-reform-german-press-release.html
* https://www.pine64.org/
* https://frame.work/
** see https://www.youtube.com/watch?v=IMZp8ErTTuk and the pinned comment

<<<
https://clevo-computer.com/de/notebooks-konfigurator/nach-anwendung/geschaefts-und-bueroloesungen/2059/clevo-n141cu-intel-core-10th-comet-lake-metallgehaeuse-intel-uhd-graphics-620-thunderbolt-3?c=1422

der zumbeispiel ist so modular wie es nur geht und der hersteller hat auch als prinzip die ersatzteile günstig anzubieten für lange zeit

clevo ist so ein No Brand hersteller oder wie das heißt und wird auch durch Schenker tech oder tuxedo rebrandet

ja weil es halt no brand hersteller ist also hört man eher von tuxedo oder sowas

ich selber habe noch keinen davon aber habe sehr viele test angesehen und war auch mal in taiwan beim hersteller schauen

von den testergebnissen her sind die ganz gut und auch günstig

bei clevo deutschland sollte man meist auf den niedrigsten preis kommen

https://www.schenker-tech.de/

die nutzen auch clevo basis und verkaufen auch bei cyberport

wenn ich mir heute einen neuen laptop kaufen müsste, würde ich den wählen CLEVO L141CU / TUXEDO InfinityBook S 14 v5 / SCHENKER VIA 14

und bei notebookcheck findest du auch viele detailierte berichte

ging eher darum das es noch hersteller gibt die sehr modulare notebooks herstellen und deren strategie ist auch lange und günstig ersatzteile anzubieten

ja oder tuxedo nimt clevo als basis, iwe man es sieht

tuxedo verkauft nur linux laptops auf clevo basis, wenn da linux schlecht läuft wäre das nicht gut

die laptops aus dem shop clevo deutschland sind auch bei tuxedo verfügbar
<<<

<<list-links "[all[current]tagging[]]">>
cell voltage: 3.6/3.7 V

Xs means the number (X) of cells in series, which influences the voltage

3s or 4s are used for 12V cells, but LiFePO4 might be a better choice.

lithium batteries are pretty expensive, but have a low volume/Wh.

optaining lithium and other rare materials used in these batteries is a hard thing and a problem for the environment and people and not as sustainable. also the manufacturing of lithium batteries uses a lot of energy and produces a lot of CO2.


* https://www.elektronik-kompendium.de/sites/bau/0810281.htm


* https://de.wikipedia.org/wiki/NMC-Akkumulator
*can display logarithmic voltage levels ind 3dB steps
* [[Datasheet|https://media.digikey.com/pdf/Data%20Sheets/Texas%20Instruments%20PDFs/LM3915.pdf]] or on [[alldatasheet|https://pdf1.alldatasheet.com/datasheet-pdf/view/558235/TI/LM3915N-1.html]]
* some links
** https://tronixstuff.com/2013/12/09/tutorial-lm3915-logarithmic-dotbar-display-driver-ic/
** https://www.homemade-circuits.com/lm3915-ic-datasheet-pinout-application-circuits/
** 
* LM3914 can display linear voltage ranges
** https://tronixstuff.com/2013/09/14/tutorial-lm3914-dotbar-display-driver-ic/
Verschaltung

* 15s: 360-426V (384V 38,4kWh)
* 20s: 480-568V (512V 51,2Wh)
** 10x 48V Module

Steckverbinder

* berührungssicher
* wasserfest
* powelock komplett overkill
* E-Auto Stecker
** IEC 62196 Typ 2 bzw. CCS
*** https://en.wikipedia.org/wiki/Combined_Charging_System
*** https://de.wikipedia.org/wiki/Combined_Charging_System
** https://de.wikipedia.org/wiki/North_American_Charging_Standard - kompakt aber lang
** https://de.wikipedia.org/wiki/CHAdeMO
* IEC 60309 (CEE) 8h grau - 2L+PE >250V DC
** https://de.wikipedia.org/wiki/IEC_60309
** im standard, aber nicht einfach käuflich scheinbar
* Harting
** Modular - https://www.harting.com/sites/default/files/2021-03/Han_06_Han-Modular_de.pdf
*** https://b2b.harting.com/ebusiness/de/Industrie-Steckverbinder-Hansup-sup-Einsaetze-Han-Modularsup-sup-der-modulare-Steckverbinder/40889?search=false&showProducts=1&q=:code-asc:inProductListAllowed:true:507:%25E2%2580%258C+40+A:507:%25E2%2580%258C+70+A&sort=integer7172-desc&page=0
*** https://b2b.harting.com/ebusiness/de/Han-70A-axial-module-male-6-16mm/09140022641?newPDP=true
*** https://b2b.harting.com/ebusiness/de/Han-70A-axial-module-male-14-22-mm/09140022642?newPDP=true
*** https://b2b.harting.com/ebusiness/de/Han-CD-module-crimp-male/09140073001?newPDP=true
*** https://b2b.harting.com/ebusiness/de/Han-CD-module-crimp-female/09140073101?newPDP=true
*** https://b2b.harting.com/ebusiness/de/Han-CC-Protected-module-crimp-female/09140043141?newPDP=true
*** https://b2b.harting.com/ebusiness/de/Han-CC-Protected-module-crimp-male/09140043041?newPDP=true
*** https://b2b.harting.com/ebusiness/de/Industrie-Steckverbinder-Hansup-sup-Gehaeuse-Han-Modularsup-sup-Twin-kompaktes-Metallgehaeuse-fuer-zwei-Module/380525?detail=true&sewConfig=false
*** https://b2b.harting.com/ebusiness/de/Industrie-Steckverbinder-Hansup-sup-Gehaeuse-Han-Modularsup-sup-Compact-kompaktes-Metallgehaeuse-fuer-ein-Modul/380524?detail=true&sewConfig=false
** Han-Com - teuer
*** https://b2b.harting.com/ebusiness/de/Han-K4-4-F-6-16mm-beruehrsicher/09380082701?newPDP=true
*** https://b2b.harting.com/ebusiness/de/Han-K4-4-M-6-16mm-beruehrsicher/09380082601?newPDP=true

Wichtige Punkte

* Vorteil: niedrige Ströme
* Nachteil: Hochvoltakku, dangerous
* Steckverbinder müssen Berührungssicher sein
* unter spannung erst wenn alles verbunden und ein handshake ausgeführt wurde
** würde extra elektronik für jedes Modul und ein Gleichstromschütz pro Modul benötigen
* 60V DC-Schütze müssten reichen, braucht keine 600V DC-Schütze
* Isolationswächter am DC Input vom Inverter - Verbunden mit Sicherheits-Handshake
* rfm95w modules
* ESP microcontrollers
* RFM69cw/RFM69hcw modules
see [[reverse engineering of electric cargo bike electronics]]

!! Steckverbinder

- DT / Deutsch
- JST Typ-JWPF-VSLE

those are great, but i chose the more common style of waterproof car plugs

[[connectors]]

!! Bremsen

- hydraulik steckverbinder? - gibts eher nicht in der größe denke ich und lohnt sich nicht, die bremse ist recht einfach abmontierbar

!! Schlüssel

* [[ebike akku schlüssel]]

!! sonstiges

*Rohrendkappen/Rohrstopfen
* [[The best low power display? E-Paper Tutorial|https://www.youtube.com/watch?v=kAmnU5Y96MA]]
* "kinetic" switches
** [[I thought this was going to be a fake kinetic switch|https://www.youtube.com/watch?v=qZ0Z18CcTzI]]
** [[Inside a kinetic self-powering remote switch|https://www.youtube.com/watch?v=9Pw7U0XFgUM]]
* https://pedalkreis.org/low-tech/
* http://konvivialetechnologien.blogsport.de/worum-gehts-hier/
* konviviale Technik
* https://www.lowtechmagazine.com/
** https://solar.lowtechmagazine.com/ (solar-powered version)
* https://www.notechmagazine.com/
* http://www.n55.dk/MANUALS/manuals.html
* https://pedalkreis.org/low-tech/links/
* https://wiki.opensourceecology.de/Open_Source_Ecology_Germany
* https://kante.info/uber-uns/angepasste-technik/
* https://www.latelierpaysan.org/Who-we-are
* https://kante.info/download-bereich/diverse-bauanleitungen/
* https://homebrewserver.club/low-tech-website-howto.html
* http://lowtechlab.org
* https://www.soundlazer.com/how-to-make-an-lrad-with-arduino/
* https://www.soundlazer.com/lrad-sound/
* https://www.soundlazer.com/how-does-a-long-range-acoustic-device-lrad-work-teardown/
* https://makezine.com/2006/03/06/how-lrad-works/
* https://science.howstuffworks.com/lrad.htm
* https://www.youtube.com/watch?v=y7UZHEHhdek - Best LRAD System!... For Your Money
* https://www.youtube.com/watch?v=Gi3WBwR8yeo - LRAD vs "Volunteers" - Field Test


lrad /sound protection

* https://lifehacker.com/how-to-build-a-diy-sound-cannon-shield-1844014455
* https://docs.google.com/document/d/1rnaSvs_WMYmlymEBa2R8fFxBu4apEjH4uX9lRcib1ZM/edit
* https://www.youtube.com/watch?v=3sqIvak-4Ek - LRADs and Sound Cannons Are NOT Safe. Here's How To Minimize Their Effects.
* [[DEFEATING LRAD|https://www.youtube.com/watch?v=CXKTBQBugIA]]
* [[LTspice tutorial - Measuring Impedance (part 1/2) |https://www.youtube.com/watch?v=l0f6c3AkTvA]]
* [[FesZ Electronics: LTspice tutorial|https://www.youtube.com/playlist?list=PLT84nve2j1g_wgGcm0Bv3K4RSl2Jdjsey]]
got this usb midi(?) controller for free because it was broken.

i first opened it for cleaning and visual inspection. the case of the Micro-USB connector was slightly bent, but bending it back was easy. found a slightly ripped flat flex cable, repairing them is not easily possible, but i just wired a bodge cable from PCB to PCB.


!! reverse engineering

Main pcb

* nuvoton microcontroller
* LM358
* two unpopulated headers, one 4-pin maybe for programming/debugging

"function board"

* 2x HCF4051BE - [["SINGLE 8-CHANNEL ANALOG MULTIPLEXER/DEMULTIPLEXER"|https://www.alldatasheet.com/datasheet-pdf/pdf/243225/STMICROELECTRONICS/HCF4051BE.html]]

keyboard pcb doesn't have interesting semis, just diodes and the big button matrix has no components, just those graphite connection pads.


i checked with amidi: the keyboard works out of the box with midi, so do the potentiometer and the big button matrix

the smaller controll buttons don't use midi it seems, i don't know how to test them yet.

lsusb output:


```
us 003 Device 004: ID 0763:2037 M-Audio Axiom A.I.R. Mini32
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x0763 M-Audio
  idProduct          0x2037 
  bcdDevice            1.40
  iManufacturer           1 M-Audio
  iProduct                2 Axiom A.I.R. Mini32
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0085
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower               64mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0 
      iInterface              0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength       0x0009
        bInCollection           1
        baInterfaceNr(0)        1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         1 Audio
      bInterfaceSubClass      3 MIDI Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      MIDIStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength       0x0061
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               1 Embedded
        bJackID                 1
        iJack                  14 
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               2 External
        bJackID                 2
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               1 Embedded
        bJackID                 3
        iJack                  15 
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               2 External
        bJackID                 4
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               1 Embedded
        bJackID                 9
        bNrInputPins            1
        baSourceID( 0)          2
        BaSourcePin( 0)         1
        iJack                  14 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               2 External
        bJackID                10
        bNrInputPins            1
        baSourceID( 0)          1
        BaSourcePin( 0)         1
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               1 Embedded
        bJackID                11
        bNrInputPins            1
        baSourceID( 0)          4
        BaSourcePin( 0)         1
        iJack                  15 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               2 External
        bJackID                12
        bNrInputPins            1
        baSourceID( 0)          3
        BaSourcePin( 0)         1
        iJack                   0 
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 6
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         2
          baAssocJackID( 0)       9
          baAssocJackID( 1)      11
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 6
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         2
          baAssocJackID( 0)       1
          baAssocJackID( 1)       3
```
* https://hackaday.com/2022/10/27/m-2-for-hackers-expand-your-laptop/
* https://hackaday.com/2022/11/03/m-2-for-hackers-connectors/
* https://caps.wiki/wiki/Mains_Power
see [[open workshops, hackerspaces, fablabs]]

* Rosenwerk / Konglomerat - https://konglomerat.org/
** Werkstadtpiraten - https://www.werkstadtpiraterei.de/
* https://turmlabor.de/
* Repair Cafe
** [[Im Repair-Café kaputte Speaker, Tablet oder Plattenspieler selbst reparieren – lohnt sich das?|https://www.youtube.com/watch?v=Ye41FRTy7yU]]
if you have a project or idea and want to make it open hardware there are some ideas you can follow to make it as much open as possible:

this guide is a draft for noting my ideas on the topic... some legal stuff (see the parts about licences and the Part libraries) might be wrong, i'm not a lawyer.

related to the OSEG Open Hardware Standards DIN SPEC 3105

* use open source software, so everyone has access to the software
** [[open source CAD software]] like FreeCAD
** [[open source graphics software]]
** and open EDA software like KiCAD for PCBs
* file types wich are good to use
** FreeCAD files - easily editable
** KiCAD's filetypes
** STEP - as transport to other software, supported by all other CAD software, not easily editable
*** simple, standardised parts such as bolts and fasteners, nuts, washers and similar small hardware can be kept only as step because they don't need to be editable
** STL - as transport for 3D-prints, supported by all slicers/printers
** SVG - for 2D designs/drawings
** PDF - as 2nd version of 2D drawings in SVG
** OpenSCAD - more specialized, steep learning curve, not as supported
* Licences and crediting
** each project should include a licence file detailing the Licence it is under
** see [[Licences and Licencing]]
** see [[Open Hardware Licences]]
** see [[problems with non-commercial licences]]
** list the tools/addons you used (also good as documentation or other users)
** check and note the licences of parts from CAD Part Libraries and catalogues (see below)
* Documentation
** each project should atleast include a Readme file
** document which tools/addons you used to design the project (also good for crediting the work of others)
* CAD Part Libraries and catalogues
** can drastically speed up the design, aid with tedious tasks
** you have to check the licences of the parts, can be sometimes dificult...
** FreeCAD examples:
*** 3DfindIT - proprietary service providing 3D files from manufacturers, can help with design but i don't think the files are allowed to be part of the design due to being IP of the manufacturers; might be compatible with the CERN licence though; reverse engineering of the design from the files might be possible and legal?
*** Fasteners Workbench - seems to be a clever way: standards are defined in the code and the parts are dynamically generated, not requiring a licence for each part
*** BOLTS (BOLTSFC) - uses public domain or CC0 for parts and some parts get dynamically generated by code; maintainer made a good writeup about the issues: https://www.bolts-library.org/en/docs/0.3/document/general/licensing.html
*** Parts Library - it seems there are plans to integrate it into freecad per default, but there are no hints about the licence in the repo or the wiki... i opened a github issue: https://github.com/FreeCAD/FreeCAD-library/issues/295
*** Symbols Library uses CC-BY 3.0 for every svg symbol
** i currently only use BOLTS and Fasteners Workbench
http://www.loudspeakerdatabase.com/

a work in progress list

* AA Craaft/https://www.solton-acoustic.de/
* Avantone
* [[B&C Speakers|https://bcspeakers.com/en]]
* Beyma
* BMS
* Celestion
* [[Ciare|https://www.ciare.com/en/products-2/]]
* dB Technologies
* [[Eighteensound|https://www.eighteensound.it/en/products]]
* ~ElectroVoice
* [[Eminence|https://www.eminence.com/]]
* [[FaitalPro|https://faitalpro.com/en/index.php]]
* Fane
* FBT
* Fostex
* http://www.hcdesignaudio.com/hcdesingtesting/
* JBL
* [[Jensen|https://sica.it/jensen/]] - part of Sica, for E-Guittar/-Bass Cabinets
* http://www.lavocespeakers.com/
* Limmerhorns - only horns
* Mackie
* Monacor
* https://www.oberton.com/en/
* http://www.paudiothailand.com/pac/
** http://p-audio.co.uk/ ?
* Peavey
* [[Precision Devices|https://www.precision-devices.com/]]
* Radian
* [[RCF|https://www.lautsprecherteile.de/pa-chassis/lt.speakers/]]
* [[Sica|https://sica.it/sica/]]
* Turbosound
* Visaton
* Yamaha

cheap rebranded? stuff

* https://www.lautsprecherteile.de/pa-chassis/lt.speakers/
* https://www.lautsprecherteile.de/pa-chassis/master-audio/?p=1
* https://www.lautsprecherteile.de/pa-chassis/sonitus-audio/
* https://www.thomann.de/de/the_box_lautsprecher_komponenten.html
* https://www.thomann.de/de/the_box_pro_lautsprecher_komponenten.html
* https://www.pedelecforum.de/wiki/doku.php?id=sonstige_interessante_links:openandromaps
* https://umap.openstreetmap.fr/de
* https://www.pedelecforum.de/wiki/doku.php?id=sonstige_interessante_links:openandromaps
Matrix ist dezentraler verschlüsselter Messenger (Chatanwendung).
Matrix ist vor allem der Name von dem Netzwerkprotokoll.

Oft wird es mit Slack verglichen, weil es etwas an Slack abgelehnt ist.

Matrix ist Ende-zu-Ende verschlüsselt, aber im Gegensatz zu z.B. XMPP hat man im Grunde keine Kontaktpunkte mit den technischen Punkten, was es einfacher für nicht-technische Nutzer:innen machen soll.
Matrix

Neben Chats gibts aber auch ~VoIP (Sprach- und Videotelefonie) Funktionen, man kann Bots nutzen und es gibt auch Funktionen fürs relativ einfache Bridgen zwischen anderen Messengern wie z.B. zu XMPP oder Telegram.

* [[matrix.org/|https://matrix.org/]]
* [[joinmatrix.org/|https://joinmatrix.org/]] - einfachere Einführung
* [[joinmatrix.org/guide/#get-started|https://joinmatrix.org/guide/#get-started]]
* [[matrix.org/docs/guides/introduction|https://matrix.org/docs/guides/introduction]] - etwas technischere Einführung


! Clients

Clients gibt es viele verschiedene.

Am beliebtesten/verbreitetsten bzw. vermutlich auch am aktuellsten was die Funktionen von Matrix angeht ist [[Element|https://element.io/]] (früher Riot genannt).
Element gibts als Smartphone Apps, Webapp im Browser und Desktop App.

Es gibt aber auch andere Clients die zumindest alle die grundlegenden Chatfunktionen unterstützen (z.b. Clients fürs Linux Terminal)

* [[element.io/|https://element.io/]] - beliebtester Client
* [[matrix.org/clients/|https://matrix.org/clients/]] - Liste anderer beliebter Clients
* [[matrix.org/docs/projects/try-matrix-now/|https://matrix.org/docs/projects/try-matrix-now/]] - noch eine Liste
* [[matrix.org/docs/projects/clients-matrix|https://matrix.org/docs/projects/clients-matrix]] - lange, ausführliche Liste an Clients.
* https://matrix.org/clients-matrix/ - Vergleich


! Heimserver/Homeserver

Ihr könnt euch einen Server wählen auf dem ihr euch registrieren möchtet.
Die Server können alle untereinander Kommunizieren.

Es gibt den [[matrix.org|https://matrix.org]] Server von den Hauptentwicklern. Es ist nicht der Sinn hinter Matrix das alle auf dem selben Server sind, aber viele verwenden den [[matrix.org|https://matrix.org]] Server. Ich rate vom dem Server ab.

Ich selbst bin bei https://tchncs.de/matrix betrieben von einem Nossener.

Neben der Mastodon-Instanz dresden.network gibts auch https://chat.dresden.network/. Der Server bietet sich vlt. an für Dresdener und Dresdener Initiativen.

Mitglieder der TU können auch den Matrix Server der TU nutzen solange Sie studieren oder in der TU arbeiten. Gehostet wird der Server vom ZIH und ist mit dem normalen TU ZIH Login nutzbar. [[matrix.tu-dresden.de/|https://matrix.tu-dresden.de/]]

in einer solidarischen (linken) IT Gruppe in der ich auf Matrix bin sind folgende noch beliebt:

* systemli.org
* activism.international
* livingutopia.org
* systemausfall.org
* rebellieren.jetzt
* enteig.net

Aber nicht alle Server bieten eine offene Registrierung.

Weitere Listen:

* [[joinmatrix.org/servers/|https://joinmatrix.org/servers/]] - lange Liste an öffentlichen servern
* https://tatsumoto-ren.github.io/blog/list-of-matrix-servers.html - andere Liste mit einigen Servern


! Konto erstellen

Nicht alle Server sind öffentlich für die Registrierung freigeschaltet. Man braucht bei manchen Logins von den Organisationen z.B. wie beim TU Server.
Aber es gibt auch viele öffentliche mit freier Anmeldung.

Ein Konto erstellen ist vermutlich am einfachsten am PC mit dem Webclient, aber sollte auch in den Apps möglich sein.
Falls der Server den ihr nutzen wollt selbst keinen Webclient hostet könnt ihr https://app.element.io/ nutzen.

Beim Registrieren solltet ihr sicherstellen das ihr euch wirklich auf dem Server registriert auf dem ihr landen wollt.
Im Webclient ist da ganz oben im Dialog zum Account erstellen ein Feld wo die Adresse von dem Server sein muss den Ihr nutzen wollt.

Wenn ihr euch registriert gebt ihr einn Benutzernamen an, der ist einzigartig und kann später nicht geändert werden. Der Benutzername dient auch dazu das andere Matrix Nutzern euch zu kontaktieren können.
Eure komplette ID besteht aus eurem persönlichen Benutzernamen und der Server Adresse, z.B. @mustermann:tchncs.de.

Es gibt aber noch einen Anzeigenamen den ihr nach dem Anmelden frei wählen und Ändern könnt.
Wenn Ihr bei der Registrierung eine Mail angebt dann müsst ihr zum Abschluss noch die Mail Adresse bestätigen.

Beim Erstellen vom Konto müssen natürlich auch Passwörter erstellt werden. Zudem kommt dazu, dass man sich die Verschlüsselungskeys sichern sollte (Anleitungen siehe unter dem Absatz).
Am besten nutzt ihr einen Passwortmanager dafür.

* [[joinmatrix.org/guide/#set-up-key-backup|https://joinmatrix.org/guide/#set-up-key-backup]] - Text Anleitung (englisch)
* https://www.ubuntubuzz.com/2021/01/element-made-easy-setup-security-phrase-and-key.html - grafische Anleitung (englisch)

! Gruppen

Wenn man mehrere Gruppen für z.B. einen Verein oder eine Initiative nutzt können die in Spaces organisiert sein. Dann sind die Gruppen und die Mitglieder des Space übersichtlicher aufrufbar.
* https://www.mikrocontroller.net/articles/MC34063
* datasheets
** https://www.ti.com/product/MC34063A
** https://www.onsemi.com/pdf/datasheet/mc34063a-d.pdf
** https://www.st.com/resource/en/datasheet/mc34063ec.pdf
* https://www.youtube.com/watch?v=qX6ZLLvBvNU
see [[Eisenwaren]]

this is specifically not normal diy or hardware stores.

* freight forwarders?
* Radionics ? [[[#]|https://www.reddit.com/r/DIY/comments/bgjte/comment/c0mnze9/]]
* http://www.maplin.co.uk/ + http://www.farnell.com/ + http://uk.rs-online.com/web/ + http://www.screwfix.com/ ? [[[#]|https://www.reddit.com/r/DIY/comments/bgjte/comment/c0mo85a/]]
* Reid Supply?, http://www.misumi-europe.com/start.aspx, http://www.wdsltd.co.uk/ - [[[#]|https://www.reddit.com/r/engineering/comments/1v6szd/comment/cepa9yy/]]
* Misumi [[[#]|https://www.reddit.com/r/engineering/comments/1v6szd/comment/cepctk6/]]
* http://www.maedler.de/ - [[[#]|https://www.reddit.com/r/engineering/comments/1v6szd/comment/cepcpce/]]
* http://www.ondrives.com/ - [[[#]|https://www.reddit.com/r/engineering/comments/1v6szd/comment/cepaehj/]]
* http://wueko.wuerth.com/ - [[[#]|https://www.reddit.com/r/AskEngineers/comments/hmq73/comment/c1wmnis/]]
* https://www.raptorsupplies.com/ ?
* https://www.kippwerk.de/de/de/Home.html ?
* rs components, screwfix, metal supermarket, wickes [[[#]|https://www.reddit.com/r/Machinists/comments/4cv7mv/comment/d1loo5s/]]
* https://us.misumi-ec.com/worldwide/
** https://de.misumi-ec.com/#

stuff

* https://hackaday.com/2017/09/13/noobs-guide-to-mcmaster-carr/
milli ohm meter needed for accurately meassuring low resistances

* https://www.paulvdiyblogs.net/2016/09/building-milli-ohm-meter.html
* [[DER TRICK bei kleinen Widerständen - 4-Draht Messung 'old School'|https://www.youtube.com/watch?v=57d4iacjFos]]
* see [[multimeter]]
* [[#321​ 7 Sensors tested: Measuring Current with Microcontrollers (Arduino, ESP32, ESP8266)|https://www.youtube.com/watch?v=cG8moaufmQs]]
* [[#347​ Measuring Mains Voltage, Current, and Power for Home Automation|https://www.youtube.com/watch?v=Vb9-pbLdsfQ]]
* shunt resistor
** accurate low resistance resistor, using ohms law to calculate the voltage from the meassured voltage
** [[What is a SHUNT? (Used to measure Current) + How to make a DIY version|https://www.youtube.com/watch?v=_3GPaFuqrxs]]
** [[How to Make a Shunt Current Sense Resistor|https://www.youtube.com/watch?v=j4u8fl31sgQ]]
** using shunts
*** [[DIY Arduino power/energy meter|https://www.youtube.com/watch?v=_PKQdEUam6Y]]
*** [[Arduino based current meter with i2c LCD screen|https://www.youtube.com/watch?v=mcDITdXGZDc]]
** INA219 - very popular
*** [[10 Minute Arduino Project - INA219 Current Sensor|https://www.youtube.com/watch?v=PZ7imiIIf_k]]
*** [[Make your own Power Meter/Logger|https://www.youtube.com/watch?v=lrugreN2K4w]]
*** [[15 Minute Arduino Project: OLED Ammeter INA219|https://www.youtube.com/watch?v=8ikyp4lu45M]]
**** [[Arduino Ammeter (with OLED) Converted to Wattmeter|https://www.youtube.com/watch?v=zvcTUMBGO24]]
** MAX4080
** INA169
** INA226
** INA3321
* hall sensors
** meassure current contactles, have high ranges, not accurate for low currents
** https://en.wikipedia.org/wiki/Current_clamp
** https://de.wikipedia.org/wiki/Zangenstrommesser
** ACS712
** ACS758
** WCS1800
* very small currents
** [[#84 Measuring small currents (incl. building of an amplifier and the µCurrent Gold)|https://www.youtube.com/watch?v=CdnxCIEklH4]]
** [[#245​ Deep-Sleep Current: Which is better? µCurrent or CurrentRanger? (ESP32, ESP8266)|https://www.youtube.com/watch?v=HmXfyLyN38c]]
* [[Ammeter for Workshop Battery (powers the lights)|https://www.youtube.com/watch?v=KEv0pnp9eCM]]
* [[300 Volt, 100 Amp Meter for Solar Panel|https://www.youtube.com/watch?v=Yuna7CgLK7k]]
* https://en.wikipedia.org/wiki/Current_sensing
* https://components101.com/article/comparison-between-shunt-hall-and-ic-based-current-sensing-designs
* [[About Current Probes and Transformers|https://www.youtube.com/watch?v=YWFONrIy110]]
* https://www.wikihow.com/Measure-Inductance
* https://www.daycounter.com/Articles/How-To-Measure-Inductance.phtml
* https://www.testandmeasurementtips.com/how-to-measure-inductance/
* https://meettechniek.info/passive/inductance.html
* https://www.instructables.com/Measuring-Inductance-With-a-Multimeter-and-a-Resis/
* https://circuitdigest.com/electronic-circuits/how-to-measure-inductance-or-capacitance-using-oscilloscope
* [[EEVblog 1465 - Your Multimeter Can Measure Inductors|https://www.youtube.com/watch?v=UrS5ezesA9s]]
* see [[multimeter]]
* [[#340​ How good are the ADCs inside Arduinos, ESP8266, and ESP32? And extenal ADCs (ADS1115) - how to meassure voltage|https://www.youtube.com/watch?v=UAJMLTzrM9Q]]
* [[#347​ Measuring Mains Voltage, Current, and Power for Home Automation|https://www.youtube.com/watch?v=Vb9-pbLdsfQ]]
* [[Open Source 8.5 Digit Voltmeter from CERN: Build and Test|https://www.youtube.com/watch?v=D28uSzCs7-k]]
* [[#10 Tutorial: Make the Arduino Analog Readings more precise|https://www.youtube.com/watch?v=xI_qU2auVx8]]
* [[Maximizing Arduino’s ADC Resolution and Accuracy Part 1|https://www.youtube.com/watch?v=obJkS2DT7vE]]
* [[Playing with: the Arduino Secret Voltmeter|https://www.youtube.com/watch?v=G6dvDgCOyqk]]
* [[300 Volt, 100 Amp Meter for Solar Panel|https://www.youtube.com/watch?v=Yuna7CgLK7k]]
* there are a lot of cheap voltmeters available ona ebay and co
** [[Julian's Electronics Postbag: #139​ - LED Voltmeters and Cables|https://www.youtube.com/watch?v=hJ114ClEKKQ]]
* https://www.tomshardware.com/news/raspberry-pi-pico-voltmeter-project
* https://techzeero.com/arduino-tutorials/measure-voltage-with-arduino/
* https://startingelectronics.org/articles/arduino/measuring-voltage-with-arduino/
* https://www.instructables.com/Voltage-Measurement-Using-Arduino/
* https://simple-circuit.com/measure-ac-voltage-arduino-ac-voltmeter/
* https://www.paulvdiyblogs.net/2016/09/building-6-digit-digital-milli-voltmeter.html
* https://der-newstest.de/
i bought a used Speaka ER-66S Megaphone with claimed 25W Power.
uses 8x Size C 1.5V batteries, so 12V (DC).
the megaphone also has marking saying "transistor megaphone" and "UM-2", it's obviously produced in china but i don't know if there are different versions with different internals sold under the same speaka model.

i reverse engineered the circuit of the one i got (not jet online)

* http://www.szczkjgs.com/ - manufacturer/seller of the amplifier board and the amplifier chip
* CS8622
** 24 W / 14 V / 4 Ω
** ESOP-16
*** amplifier chip is SO-Package with Exposed heat-sink pad on the bottom (which is also the main ground)
**** https://de.wikipedia.org/wiki/SO-Bauform
**** https://en.wikipedia.org/wiki/Small_outline_integrated_circuit
** 6,5 V - 18,5 V
** Geeignet für Blei-Säure Batteriestablautsprecher 25 W Mono Class D Audio-Leistungsverstärker-IC
** https://rtccn4awrjpnvp7r35un3ijr2a--www-szczkjgs-com.translate.goog/products_3674.htm
** https://www.alldatasheet.com/datasheet-pdf/pdf/1143314/YONGFUKANG/CS8622E.html

horn

* folded horn design
* 21,7cm mouth
* ''TODO''
Megaphones

just buy cheap loudhailers/megaphones from china (aliexpress/alibaba/banggood/taobao) and modify them?

monacor hardware is overpriced... Thomann sells their TM25 for way less (or you get them from china) and it's only missing the barrel-jack and the car adaptor, you can easy add that yourself.
the TM25 is pretty heavy ('cause of the driver) compared to similar ones e.g. from Speaka.

bigger megaphones like the TM-35 or TM-45 from Monacor are harder to find from china

* https://monacor-webshop.de/monacor/beschallungstechnik/megafone.html

there are rechargeable battery packs for megaphones, but i can't find them separately, they also have the charging circuit included which uses up a lot of space missing for electric capacity.
a 3d printed enclosure, and 6 either 18650 (common) cells or 21700 cells (more uncommon) (2p 3s configuration) with a small 3s BMS board would do the trick well.
6 26500/25500 cells (uncommon) could also work but height-wise it might be tricky.
would 4s work with the used amplifiers? 4s would be a bit thicky due to the space.

i can't find the megaphone parts separately....

* https://www.soundlazer.com/how-does-a-long-range-acoustic-device-lrad-work-teardown/

[[megaphone reverse engineering]]
* Lautsprecher
** 2x RCF Art 310A - ~350W RMS, aktiv
** 2x Reloop RSP-10 - 100W RMS, 8 Ohm
*** https://www.reloop.com/reloop-rsp-10
** Speaka ER-66S - 25W Megafon
** 2x [[TOA SC-35L Horn Speakers|TOA SC-35L Horn Speakers and Amplifier design]]
** [[Voice Systems Contact CX MK2|Voice Systems Contact CX MK2 repaired]]
** [[Fohhn EasyPort FP1 plus|Fohhn EasyPort FP1 plus repair]] - small battery powered speaker


* Verstärker
** [[KMT N500|KMT N500 repair]]
** günstige car hifi amps
*** Sinuslive 504 - 4x 50W@4Ohm (wahrscheinlich; bridging possible to 2x100W@8Ohm für RSP-10
*** Condor MB 5 - 2x TA8210AH, 4x 20W@4Ohm ("200W")
*** [[Renkforce EQ/Amp - 4x 22W|repair of Renkforce EQ/Amp]]
** [["Hollywood" Mischverstärker - super billiger Schrott, aber war geschenkt und ist gut zum basics lernen|cheap mixing amp repair, reverse engineering]]


* LFP Akku 12V 250Ah mit 1,5kW Inverter
* LFP Akku 12V 100Ah mit 1kW Inverter
* Boxenstative 2x normal, 2x 4m Kurbelstative mit Schrägstellern, DIY Holz-Mikrostativ, 3x normales Galgen-Mikrostativ, Stativ ohne Galgen
* Racktasche


* Mikros
** Shure PGA58
** Sennheiser XS1 (Kabel)
** thomann billigmikro (t.bone MB55)
** 2x t.bone MB75 Instrumentenmikros
** 2x beyerdynamic Opus300 und SDM 369 (Funk)
*** https://www.manualslib.com/manual/765816/Beyerdynamic-Opus-300.html
** beyerdynamic Opus600 und TS 600 Headset-Mikro (Funk)
** [[Superlux ECM999|https://www.thomann.de/de/superlux_ecm999.htm]] - Messmikrofon
** 4x AKG WMS80 Funkmikros
*** 2x HT80 Handmikro
*** 2x PT80 Bodypacks mit mini XLR für Headset Mic, Intrumenten Mics oder Gitarren Pickups
** Red Beat Audio Kabelmikro


* Digitalmixer-Setup
** GL.iNet GL-MT300N-V2 "Mango" als WLAN AP/Router
** Behringer XAir XR18
*** ethernet verbindung zu Router, da wlan karte vom mixer zu schlecht und anfällig
** Netbook
*** Clementine (fernsteuerbar) oder VLC
*** Debian mit xfce mit ~PulseAudio und Jack
** Tablet
** XR18 und Clementine sind über die Smartphone Apps steuerbar
** oder einfach flac library aufm handy


* analog-Mischpulte
** kleines no-name
** Conrad "Sound Craft" SA-100 - alter Stereo DJ-Mixer
** [[the t.mix micromix 2 usb|https://www.thomann.de/de/the_t.mix_micromix_2_usb.htm]] - sehr kleines Mischpult, Betrieb von 5V USB, Integriertes Interface, brauch noch chinch-xlr adapter
** Alto ZMX862
** behringer xenyx 302 usb - 5V USB power, usb audio interface.


* Interfaces
** E-MU 0202
** Tascam US-122L
** Line6 UX2

* DSP
** thomann DSP 4x4 Mini
** [[Behringer Ultradrive Pro DCX2496|Behringer Ultradrive Pro DCX2496 repair 2 + XLR Mod]]

* Effekte und co
** dbx 266XL compressor, gate

* Aufnahmegeräte
** Tascam DR-05

* diverse XLR Kabel, Adapterkabel, Stromkabel

!! Bedarf reperatur:

* Behringer DJ Mixer
* mittleres no-name analog Mischpult
* 2. Behringer DJ mixer - 18V AC netzteil fehlt, lohnt sich nicht
* [[Tascam US-428 - 7,5VAC 1A Netzteil fehlt - Mischpult/DAW-Controller/Audio-interface|Tascam US-428 repair / Power Supply build]]
* [[Eric NA9201 amp|Eric NA9201 repair]]
* 2x Klippel Production Analyser - gehen wohl noch aber ohne software und zubehör
* 3 alte HK Actor (u.a. AT 115A Bass und AT 112 Tops/Fullrange) aktivmodule
* [[günstiger car hifi amp - Concord CA50-2 ("100W RMS"); 2x ~70W@4Ohms|Concord CA50.2 repair]]
* [[Fidek FPA-10A|Fidek FPA-10A repair]]
* [[QSC Powerlight 1.8|QSC Powerlight 1.8 repair]]
* Laney BC30 Gitarren Amp - Potis müssen getauscht werden
* Behringer Intelligate - ungetestet
* Better SM-3090 V - analog dj mixer, ungetestet
* DOD SR835 - billiges analoges crossover
* [[steinberg UR22]]
** [[Peavey PV8 USB - 8 Kanal mit USB Interface|Peavey PV8 USB 8-Channel Mixing Console repaired]] - still has issues with a couple of channels
<<list-links "[all[current]tagging[]]">>

stuff

* https://www.youtube.com/@MachiningandMicrowaves
* https://hackaday.com/2023/01/27/cut-your-own-gears-with-this-diy-machine/
* https://de.wikipedia.org/wiki/Stahlsorte
* http://www.metalltechnik-lexikon.de/
* https://wiki.fablab-muenchen.de/display/FABMX/Project+FabMX
* https://www.247tailorsteel.com/de
Metall schneiden

* [[Igor Welder: Metall schneiden Playlist|https://www.youtube.com/playlist?list=PL5uzLI8cqfnEM07zjlh9d9LW1aaLtxZsb]]
* https://www.youtube.com/playlist?list=PLk8S90fhT-EgJKloQqSxYjOZKQvY1BZOH
* https://www.youtube.com/playlist?list=PLk8S90fhT-EhtjyIaQftgv2rA17M7eWrE

Verbindungstechnik

* https://de.wikipedia.org/wiki/Verbindungstechnik
* https://www.konstruktionsatlas.de/verbindungstechnik/schraube_gewinde_mutter/schraubensicherung.shtml#



diy (tube) bender

* [[The Rollenator! (Ring Roller Build)|https://www.youtube.com/watch?v=uNn6q0TXdDM]]
* [[Making an Inset Bench Metal Folder/Brake|https://www.youtube.com/watch?v=Ggy1DHwAh_0]]
* [[ Rohrbieger im Test |https://www.youtube.com/watch?v=VF-npEsJuE4]]
* https://www.youtube.com/watch?v=NzXecCoQWgg


tap wrench - windeisen

* https://www.youtube.com/watch?v=ZTmjdvg_Td8
* https://www.youtube.com/watch?v=AHoHNt1NOZs
* https://www.youtube.com/watch?v=22av6LcDVSY

collet blocks

https://www.youtube.com/watch?v=pUR7A1oxHg4

see [[Eisenwaren]], [[mcmaster carr alternative for europe]]


vice / clamps

* [[Easy Low Profile Side Clamps For The Milling Machine|https://www.youtube.com/watch?v=Dw27hDPZ-6E]]
* [[Two Piece Machine Vise Build|https://www.youtube.com/watch?v=9UGY8iJH_aY]]


rotary broach - profilräumen

* can be bought for around 40-60€ from china
* räumstempel, räumdorn, taumelwerkzeug, räumwerkzeug, pressstempel
* https://www.zuern-tools.de/images/PDF/Kataloge/162_Zuern_Raeumhalter_Katalog.pdf
* [[ (Taumeln) Sechskant CNC Fräsen|https://www.youtube.com/watch?v=S2_yxnOKgfM]]
* [[So stößt man einen Innensechskant/Inbus! - derIMechaniker|https://www.youtube.com/watch?v=coOiVpL7SNQ]]
* [[Innensechskantherstellung auf einer Drehmaschine|https://www.youtube.com/watch?v=Odhz69ymbBM]]
* [[Making A Rotary Broach - Cutting Hex Sided Holes (DIY)|https://www.youtube.com/watch?v=_AYEFjbGaL4]]
* [[Rotary Broaching The Night Away|https://www.youtube.com/watch?v=GWyHJVOxKK4]]
* [[Rotary Broach: Captain's Log, Supplemental|https://www.youtube.com/watch?v=4-3gPWl6wfU]]
* [[Square Holes!|https://www.youtube.com/watch?v=DgB1psCFC7o]]
* [[How to Drill Square Holes!|https://www.youtube.com/watch?v=M3Ul-s9_MA0]]
* [[Square Holes - 5 Methods To Make Them in Metal|https://www.youtube.com/watch?v=ASz-Ayo6-xM]]


classic broach - räumnadel - Räumen

* https://de.wikipedia.org/wiki/R%C3%A4umnadel


stuff 

* https://de.wikipedia.org/wiki/Ausspindler
* [[ Making gear cutters in the home workshop using Eureka tool |https://www.youtube.com/watch?v=70IbyKLO_iI]]
* https://www.youtube.com/watch?v=Q-XOM4E4RZQ
* https://www.youtube.com/watch?v=fWYzpK34KD4
* https://de.wikipedia.org/wiki/L%C3%BCnette_(Drehen)


metal

* tool steel, high speed steel - werkzeugstahl, drehlinge, drehstahl

Fertigungstechnik

* https://de.wikipedia.org/wiki/Kategorie:Fertigungstechnik
** https://de.wikipedia.org/wiki/Kategorie:Fertigungstechnik_nach_Verfahren
*** https://de.wikipedia.org/wiki/Kategorie:Trennen
**** https://de.wikipedia.org/wiki/Kategorie:Zerspanen
***** https://de.wikipedia.org/wiki/Kategorie:Zerspanungswerkzeug
****** https://de.wikipedia.org/wiki/Zerspanungswerkzeug
***** https://de.wikipedia.org/wiki/Kategorie:Spanen_mit_geometrisch_bestimmter_Schneide
****** https://de.wikipedia.org/wiki/R%C3%A4umen
****** https://de.wikipedia.org/wiki/R%C3%A4umwerkzeug
****** drehen, fräsen, ...
* http://www.matthiashertel.de/Technologien/technologien.html
* https://www.industrie-schweiz.ch/html/industrie_lexikon.html



stuff

* [[ Making a MASSIVE Fly Cutter - INHERITANCE MACHINING |https://www.youtube.com/watch?v=pWy76xDfTQE]]
* [[ Internal Splines (and Hexes Too)|https://www.youtube.com/watch?v=y3L1SyEd7EY]]
* https://www.youtube.com/watch?v=7ngNtK9tKME


mist cooling

* https://www.youtube.com/watch?v=nZ4D8rxJe_A
* https://www.youtube.com/watch?v=14VVActEH0M
* https://www.youtube.com/watch?v=hbj68jwO0iw
* https://www.youtube.com/watch?v=F6SAgnhWkxE
* https://www.youtube.com/results?search_query=cheap+mist+cooling


feuerfestigkeit

* silica fiber - silikat fasern platten/matten
* feuerfeste isolierung?
the pieso is constantly beeping on almost every setting and there is a warning singn in the display when the fuses are installed.

* https://de.rs-online.com/web/p/multimeter/4505240
** https://docs.rs-online.com/49dd/0900766b80204cc7.pdf
* https://www.transcat.com/media/pdf/30xr_meterman.pdf
* https://res.cloudinary.com/iwh/image/upload/q_auto,g_center/assets/1/26/Documents/Wavetek/30xr_manual.pdf
* https://de.ifixit.com/Device/Multimeter
* https://www.circuitspecialists.com/blog/dmm-troubleshooting-repair/
* https://www.youtube.com/watch?v=YM--cxT6X3k
* https://www.youtube.com/watch?v=-9kNSR4ozT4
* https://www.youtube.com/watch?v=tMh3nFYaI_Q
needed/used for many kinds of projects/devices

see [[embedded device development]]

* Arduino
** Adafruit and other compatible

* PIC
** old industry standard, many compatible chips still on the marked, but outdated
** basic programming is pretty easy due to the simple architecture, but it's processing power and capabilities are pretty limited

* STM32
** cheap, pretty powerful (more than arduino)
** new industry standard
** debugging using ~OpenOCD and gdb
** https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill.html
** [[Easy & Powerful Arduino Alternative? STM32 Beginner's Guide|https://www.youtube.com/watch?v=EaZuKRSvwdo]]
** https://stm32world.com/wiki/
** [[Phil's Lab: STM32 Firmware|https://www.youtube.com/playlist?list=PLXSyc11qLa1a4Tqbz228dPZfMrs-KRpzA]]
*** [[STM32 DMA and FreeRTOS Tutorial - Phil's Lab #14|https://www.youtube.com/watch?v=OyVemnshlQQ]]

* ESP8266 & ESP32
** http://esp8266.net/ - overview
** https://www.esp8266.com/ - forum
** https://web.archive.org/web/20220702032606/http://esp32.net/ - overview (original currently offline)
** https://esp32.com/ - forum
** there are ESP32 Models with Risc-V cores
** https://learnesp32.com/ ? 
** https://esp32io.com/
** https://en.wikipedia.org/wiki/ESP8266
** https://en.wikipedia.org/wiki/ESP32

* MSP430/ähnliche von TI

* Raspberry Pi Pico
** https://www.raspberrypi.com/products/rp2040/
** https://www.raspberrypi.com/products/raspberry-pi-pico/
** https://www.raspberrypi.com/news/raspberry-pi-pico-w-your-6-iot-platform/
** [[Challenger RP2040 Wi-Fi: A better Raspberry Pi Pico W than the Raspberry Pi Pico W?|https://www.youtube.com/watch?v=eNjvjc0sMNE]]
** [[Raspberry Pi Pico Clone with 16MB Flash, USB-C, Neopixel, and More!|https://www.youtube.com/watch?v=EChO4o4Z9v8]]

* Teensy
** https://www.pjrc.com/store/teensy41.html
** https://www.youtube.com/watch?v=jDihQXEuhzI
* [[RISC-V]]

* pine64
** https://www.pine64.org/pinenut/

* Risc-V
** https://www.sifive.com/cores/
** Bouffalo BL-602
** Bouffalo BL-706 - Pinecil V2
** GD32VF103TB - Pinecil V1
** https://wiki.pine64.org/wiki/Ox64
** [[ EEVblog 1524 - The 10 CENT RISC V Processor! CH32V003 |https://www.youtube.com/watch?v=L9Wrv7nW-S8]]


see [[single board computer (SBC)]] if more power/capabilities are needed

on low power/current uCs

* https://www.rs-online.com/designspark/which-low-power-mcu-is-really-the-lowest-power
* https://www.mouser.com/applications/low_power_choosing_mcu/
* https://electronics.stackexchange.com/questions/90602/parameters-to-compare-microcontrollers-for-low-power-consumption
* STM32 are also marketed as low power?
** https://www.st.com/en/microcontrollers-microprocessors/stm32-ultra-low-power-mcus.html
* https://www.analog.com/en/products/processors-microcontrollers/microcontrollers/ultra-low-power-microcontrollers.html

languages/frameworks

* ~MicroPython (pretty slow?)
* Rust Embedded (many things not stable or crates don't exist jet)
* C/C++ (oldschool)
* Arduino (C++)
* see [[Real Time Operating System (RTOS)]]


stuff

* https://www.youtube.com/watch?v=UAJMLTzrM9Q
* see [[inter IC or inter device communication, networking]]
* https://components101.com/article/difference-between-8-bit-16-bit-and-32-bit-microcontrollers
stm32

* [[YetAnotherElectronicsChannel: STM32 Audio DSP|https://www.youtube.com/playlist?list=PLTNEB0-EzPluXh0d_5zRprbgRfgkrYxfO]]
* [[ [#23] FFT Spectrum Analysis - Audio DSP On STM32 (24 Bit / 48 kHz) |https://www.youtube.com/watch?v=3WF4CGKoMas]]
* [[ [#13] FIR Filters - Audio DSP On STM32 (24 Bit / 48 kHz) |https://www.youtube.com/watch?v=n9Cy1xkEf1E]]
* [[easier in practice: Digital Signal Processing on the STM32G4|https://www.youtube.com/playlist?list=PLwa4R2HaZEqihzreDJynbcYGlc-mXn7F2]]
** [[ STM32G4 & Real Time DSP: Part 1 Introduction to the STM32 Family and STM32G4 |https://www.youtube.com/watch?v=SVT7n7hSzJU]]
** [[ STM32G4 & Real Time DSP: Part 2 Blinky Tutorial, Digital Functions, and Debugging. |https://www.youtube.com/watch?v=SVT7n7hSzJU]]
* [[ STM32 DSP CMSIS library: FIR filter in one line (2022 new method) |https://www.youtube.com/watch?v=jqCpaleqfls]]
* [[Phil’s Lab: DSP|https://www.youtube.com/playlist?list=PLXSyc11qLa1ZCn0JCnaaXOWN6Z46rK9jd]]

esp32

* [[ [#10] DIY DSP Bluetooth Speaker with ESP32 |https://www.youtube.com/watch?v=_nCOluMHfGI]]

general

* [[ Running DSP Algorithms on Arm Cortex M Processors |https://www.youtube.com/watch?v=PKdwQwBIv48]]
for hacking (i.e. extending the functionality) of devices, like cheap tools/parts from china or other things, it is quite often required to take a look on or modify the firmware of microcontrollers. this article focuses on [[common microcontrollers]]

disassembling from binary to assembly is pretty easy, but decompiling to higher languages is harder

* https://onlinedisassembler.com/odaweb/
* https://www.break-ic.com/Disassembler_software_mcu_reverse_engineer.htm
* https://www.break-ic.com/microprocessor-read/Dcc_binary_decompiler.htm
* see [[disassembling / decompiling]]
* https://www.break-ic.com/


STM32 (ARM)

* https://medium.com/techmaker/reverse-engineering-stm32-firmware-578d53e79b3 - Reverse engineering STM32 firmware with radare2
* https://github.com/Codewaves/mdisasm - Basic disassembler for Cortex M0/M3 (from binary to assembly
* https://stackoverflow.com/questions/59802528/stm32-decompiler
* https://reverseengineering.stackexchange.com/questions/17099/entry-point-for-stm32-firmware
* https://stackoverflow.com/questions/13468766/arm-disassembly
* https://wrongbaud.github.io/posts/writing-a-ghidra-loader/
* https://www.eevblog.com/forum/microcontrollers/arm-v7-disassembler-opensource-free-windows/

STM8

* https://github.com/baruch/STM8_reverse_engineering_aid
* https://hackaday.io/project/4381-stm-reverse-engineering-aid

Atmel AVR (Arduino)

* https://www.nongnu.org/avrdude/
* https://stackoverflow.com/questions/5141177/atmel-avr-disassembler
* https://community.atmel.com/projects/simple-avr-disassembler
* https://github.com/vsergeev/vAVRdisasm
* https://www.johannes-bauer.com/mcus/avrdisas/
* https://community.atmel.com/projects/reavr
* 

reading direct flash

* [[Extracting Firmware from Embedded Devices (SPI NOR Flash)|https://www.youtube.com/watch?v=nruUuDalNR0]]
info

* ''https://www.best-microcontroller-projects.com/digital-i-o.html''
* https://maker.pro/arduino/tutorial/how-to-extend-the-number-of-io-lines-on-an-arduino - decoder, shift register, encoder
* https://arduino.stackexchange.com/questions/21536/expanding-analog-inputs-to-the-arduino
* https://raspberrypi.stackexchange.com/questions/120049/how-to-extend-more-io-from-a-raspberry-pi-board
* https://resources.altium.com/p/how-expand-input-and-output-microcontroller
* https://www.digikey.com/en/articles/solve-microcontroller-io-expansion-problems-applying-external-devices


options

* shift registers
** TI 74HC595 / SN74HC595N - 8-bit shift register
** serial to parallel - for outputs
** parallel to serial - for inputs
** 75HC165 - 8 bit parallel in and serial out
** [[Controlling a BIG LED Matrix?! How Shift Registers work! -- EB#39|https://www.youtube.com/watch?v=Degt4HUzWXY]]
** [[74HC595 & 74HC165 Shift Registers with Arduino|https://www.youtube.com/watch?v=Ys2fu4NINrA]]


* multiplexers
** 74HC4067 - 16 channel analog multiplexer/demultiplexer
** 74HC4051- 8-channel analog multiplexer/demultiplexer
** TCA9548A - 8 channel I2C multiplexer/switch
*** https://randomnerdtutorials.com/tca9548a-i2c-multiplexer-esp32-esp8266-arduino/
** there are also UART multiplexer
** CD4051/CD4051B - 8-Channel Analog Multiplexer/Demultiplexer with Logic-Level Conversion
*** https://www.ti.com/lit/ds/symlink/cd4051b.pdf
** HCF4051 - single 8-channel analog multiplexer/demultiplexer
*** https://www.st.com/resource/en/datasheet/hcf4051.pdf
*** like used in [[M-Audio Axiom Air Mini 32|M-Audio Axiom Air Mini 32 controller repair, reverse engineering]]


* io expanders
** PCF8574 - Remote 8-Bit I/O Expander for I2C Bus
*** https://circuitsgeek.com/guides-and-how-to/expand-arduinos-io-interfacing-pcf8574-with-arduino/
*** https://www.picmicrolab.com/pcf8574-i2c-8-bit-io-expander/
*** https://www.mischianti.org/2019/01/02/pcf8574-i2c-digital-i-o-expander-fast-easy-usage/
*** http://www.esp32learning.com/code/esp32-and-pcf8575-i-o-expander-example.php
** PCF8591 I2C 8-bit A/D and D/A converter
*** https://www.picmicrolab.com/pcf8591-i2c-8-bit-ad-and-da-converter/
** I2C port expanders add digital ports, 8 or 16 (ports) at a time. You can also get I2C ADCs and DACs, many of them considerably superior to those in the Arduino itself
** MCP23017 - 16-bit, general purpose parallel I/O expansion for I2C bus
*** https://www.instructables.com/Extra-IO-Pins-For-Your-Arduino-Uno/
*** https://www.kickstarter.com/projects/mantaspats/64-i-o-arduino-shield
*** https://www.raspberrypi-spy.co.uk/2013/07/how-to-use-a-mcp23017-i2c-port-expander-with-the-raspberry-pi-part-1/
*** https://tutorials-raspberrypi.de/raspberry-pi-gpios-erweitern-mittels-i2c-port-expander/
*** https://www.instructables.com/Adding-an-MCP23017-IO-Extender-to-Arduino-or-ESP82/
** MCP23016
*** https://www.mattbrill.com/2017/01/06/mcp23016-mcp23017/
*** https://picaxeforum.co.uk/threads/say-no-to-mcp23016-yes-to-mccp23017.3231/
*** https://www.instructables.com/IO-Expander-for-ESP32-ESP8266-and-Arduino/
** MCP23018
*** https://piers.rocks/i2c/mcp23016/mcp23017/gpio/2018/09/11/differences-between-mcp23017-and-mcp23018.html
** MCP23S17 - 16-bit, general purpose parallel I/O expansion for SPI
*** https://www.instructables.com/Raspberry-Pi-Port-Expander/
*** https://electrosome.com/expanding-io-ports-of-pic-microcontroller/
** MCP3208 12-Bit, 100kSPS, 8-Channel ADC with SPI
** MCP23008 - 8-bit, general purpose parallel I/O expansion for I2C bus


using I2C is the most common option, SPI is much faster but not always needed

spi - multiplexing the chip select

* https://stackoverflow.com/questions/55172478/where-is-the-spi-multiplexer-of-my-dreams
* https://electronics.stackexchange.com/questions/545065/ic-to-use-for-multiplexing-spi-chip-select
* https://electronics.stackexchange.com/questions/121249/how-to-put-a-74hc165-on-an-spi-bus?rq=1
<<list-links "[all[current]tagging[]]">>


* https://www.youtube.com/watch?v=ts-JqEVzvDo
*https://www.youtube.com/watch?v=LoQu3XXIayc
* https://sound-au.com/p-cat.htm#mic
* https://hackaday.io/project/185762-mems-based-iepe-powered-instrumentation-microphone
* https://www.shure.com/en-US/performance-production/louder/faq-whats-the-difference-between-the-sm58-and-the-beta58a

* [[EEVBlog: Microphone Technology & Design|https://www.youtube.com/playlist?list=PLvOlSehNtuHv98KUcud260yJBRQngBKiw]]
** [[EEVblog #602 - Introduction to Microphones|https://www.youtube.com/watch?v=ihAG6cMpUlY]]
** [[EEVblog #605 - Fig.8 & Cardioid Microphone Patterns|https://www.youtube.com/watch?v=_rTAqO7xz8U]]
** [[EEVblog #608 - Condenser & Electret Microphone Construction|https://www.youtube.com/watch?v=yKOH0DyRWRU]]
** [[EEVblog #609 - Condenser Microphone Design Tutorial|https://www.youtube.com/watch?v=WTJhIVIGvSU]]
** [[EEVblog #611 - Electret Microphone Design|https://www.youtube.com/watch?v=UhG83WS51q8]]

in search for a better mic for my uses i asked a few people if they could recommend mics that are forgiving with unexperienced people that hold it to far from the mouth, but still with good feedback rejection. i was advised against the pretty much industra standard Shure SM58 because it drops off quickly when to far from the mouth, and they said the Shure PGA58 is a relatively cheap but pretty rugged choice.
* connection
* https://www.midi.org/categories-new/MIDI%20Connections
** over cable
*** 5-pin DIN
*** TRS Jack
** over network
*** RTP-midi - https://en.wikipedia.org/wiki/RTP-MIDI
*** https://www.midi.org/midi-articles/rtp-midi-or-midi-over-networks
*** https://www.midi.org/midi-articles/categories/rtp-midi
** bluetooth wireless
* Web Midi API see [[Web Audio API, Web Midi API - Websites with advanced audio functionality]]
* it is very simple to diy midi controllers with microcontrollers, potentiometers, buttons and stuff
** https://github.com/btrepp/usbd-midi - rust midi library for STM32
** arduinos can be used too
*** https://www.arduino.cc/en/Reference/MIDIUSB
*** https://github.com/lathoub/Arduino-USBMIDI
*** many "arduino midi controller" videos and tutorials
** https://www.pjrc.com/teensy/td_midi.html
* [[Open Source modular DJ-Controller]]
* https://willwillems.com/posts/midi-mki-build-log.html
* http://midi.org
* https://www.youtube.com/c/mitxela/videos
* https://hackaday.com/2021/03/22/midi-all-the-things-hack-chat/
* [[MIDI & Digital Music Making - Computerphile|https://www.youtube.com/watch?v=imY4EpxjyMY]]
* [[WHAT IS MIDI|https://www.youtube.com/watch?v=SUUxmJ84dnI]]
* https://en.wikipedia.org/wiki/MIDI
** https://de.wikipedia.org/wiki/Musical_Instrument_Digital_Interface
* python
** https://mido.readthedocs.io/en/latest/
** https://github.com/cyberrumor/midi-abstraction
** https://spotlightkid.github.io/python-rtmidi/
*** https://github.com/SpotlightKid/python-rtmidi
* see also [[Open Sound Control (OSC) (protocol)]]
* [[SUPER SIMPLE MIDI KEYBOARD DIY HOW TO|https://www.youtube.com/watch?v=wY1SRehZ9hM]]
* https://mitxela.com/projects/midi_over_bluetooth
* https://mitxela.com/projects/silly_synth
* https://github.com/snefs/webmidi
* https://wiki.linuxaudio.org/apps/midi_apps
* https://wiki.ubuntuusers.de/MIDI/
* amidi - dump midi information
** https://www.geeksforgeeks.org/amidi-command-in-linux-with-examples/
** https://linux.die.net/man/1/amidi
* https://learn.adafruit.com/web-ble-midi
* https://wiki.linuxaudio.org/apps/categories/midi_software

midi projects

* https://www.tomshardware.com/news/raspberry-pi-4-midi-sequencer
** [[It Plays Music! - Sequencer Build #2 - RPiMidiSC|https://www.youtube.com/watch?v=J1saOJOZrQc]]
** https://github.com/Niiisse/RPiMidiSC
* [[Build A Simple MIDI Interface / Scamp3 / MIDI Theremin|https://www.youtube.com/watch?v=MPhZMkZ1KjQ]]
some miscelaneous stuff

<<list-links "[all[current]tagging[]]">>
* [[SDG #011 Peak Atlas DCA75 Pro Semiconductor Analyser|https://www.youtube.com/watch?v=CnkdtJRYbXg]]
<<list-links "[all[current]tagging[]]">>

* https://en.wikipedia.org/wiki/Category:Signal_processing
* https://en.wikipedia.org/wiki/Category:Time_domain_analysis
* https://en.wikipedia.org/wiki/Signal_processing
* https://en.wikipedia.org/wiki/Infinite_impulse_response
* https://theaudioprogrammer.com/signal-analysis-ii-linear-vs-logarithmic-sine-sweep/
* https://theaudioprogrammer.com/
** https://theaudioprogrammer.com/category/digital-signal-processing/signal-analysis/
* http://dsp.perkaudio.net/
* [[TSP #9 - Tutorial on Passive Filters, Data Transmission and Equalization|https://www.youtube.com/watch?v=MhWyAL2hKlk]]
* https://www.thomann.de/de/onlineexpert_topic_kleinmixer.html
* https://www.bonedo.de/artikel/einzelansicht/alle-audio-mischpulte-verstehen-und-benutzen.html
* https://www.soundandrecording.de/tutorials/basis-wissen-mischpulte-aufbaufunktionenkonzepte/
* https://www.bonedo.de/artikel/einzelansicht/mastersektion-eines-mischpults-begreifen-und-verwenden.html
* https://www.thomann.de/de/onlineexpert_page_kleinmixer_kleines_mixer_glossar.html
* https://de.wikipedia.org/wiki/Mischpult
* [[Designing professional audio mixers for every scenario - TI|https://www.ti.com/lit/wp/spry322/spry322.pdf]]
* [[Professional audio mixer/control surface  - TI|https://www.ti.com/solution/professional-audio-mixer-control-surface]]
* [[deej - Arduino Volume Mixer|https://www.youtube.com/watch?v=9WqwH4tebzI]] (just for pc)
* http://digital.perkaudio.net/
* https://sound-au.com/p-cat.htm#mix
* https://www.flickr.com/photos/60782207@N08/8462967504
save aus dem FFF wiki - https://wiki.fridaysforfuture.is/wiki/Mobile_Stromversorgung

<<<

Bei diesem Artikel handelt es sich um eine Sammlung von Wissen/Methoden/etc. über die Möglichkeiten für eine mobile Stromversorgung, z.B. für PA Anlagen (Musik-/Beschallungsanlagen).
Einen Überblick über den Akkubetrieb von PA-Anlagen bietet der Artikel [[Akku PA-Anlage / Akku Beschallungsanlage]].

== Stromerzeugungsaggregat ==
Stromerzeugungsaggregate (Notstromaggregate, "Generatoren") sind offensichtlich mist, da sie einen Verbrennungsmotor nutzen, (kleinere Leistungen) Benzin, Gas (Methan, Propan etc.) oder (größere Leistungen) Diesel verbrennen und damit u.A. CO2 produzieren.

Dabei gibt es im Grunde zwei Arten, traditionelle und Inverter.

=== "traditionelles" Stromerzeugungsaggregat ===
Ein normales Notstromaggregat besteht im Grunde nur aus einem Motor und einem Generator.
Der Motor dreht sich mit einer Konstanten Drehzahl, damit der Generator die 230V 50Hz Wechselspannung erzeugen kann, verbraucht dadurch aber auch bei geringem Stromverbrauch eine konstante Menge an Treibstoff.

Normale Aggregate erzeugen meist eine nicht so schöne Sinuswelle.

=== Inverter Stromerzeugungsaggregat ===
Diese Aggregate besitzen ebenfalls einen Motor und einen Generator, jedoch zusätzlich einen Inverter.
Der Motor dreht sich unterschiedlich schnell, abhängig von der Leistung die die el. Verbraucher benötigen. Der Generator erzeugt dadurch unterschiedliche Spannungen, aber durch den Inverter werden diese zu 230V 50Hz gewandelt.
Dadurch, dass der Motor unterschiedlich schnell dreht verbraucht er unterschiedlich Treibstoff und ist somit effizienter.
Außerdem produzieren Inverter Notstromaggregate eine schönere Sinuswelle.
Diese Aggregate sind jedoch teurer.

=== nachhaltigere Möglichkeiten Stromerzeugungsaggregate zu betreiben ===
Es gibt Generatoren, welche mit Gas (Erdgas, Propan-/Butangas (Autogas/LPG)) betrieben werden können, diese sind aber selten und teurer. Es gibt aber
wohl Umrüst-Sets zu kaufen, mit denen man Benzin-Generatoren umbauen kann (ähnlich dem Umrüsten von Autos auf Autogas).
Neben der Umrüstung auf Gas ist auch die Nutzung von Benzin- und Diesel-artigen Biokraftstoffen (z.B. Biodiesel), welche aus Pflanzen gewonnen werden und daher neutraler sind, eine Alternative.
Etwas ähnliches gibt es bei der https://biofabrik.com/, bei der Plastik und Altöl wiederverwertet werden.

== Photovoltaik ==
Für kleinere Verbraucher (also eher geringe Leistungen) können auch Solarpanele eine gute mobile Stromversorgung sein, zusammen mit Akkus können sie die Laufzeit dieser noch erhöhen. Solarpanele eignen sich für den direkten Betrieb von Verbrauchern die geringere Leistungen benötigen oder in Verbindung mit Akkus für größere Leistungen. Solarpanele erzeugen jedoch auch nur Gleichstrom.

https://de.indymedia.org/2007/08/190087.shtml

== Akku ==

Da Akkus elektrische Energie speichern können, eignen sie sich vielseitig um el. Verbraucher mit Strom zu versorgen.
Wenn die Akkus mit Ökostrom geladen werden geschieht die Versorgung auch im Grunde CO2 neutral.

Jedoch ist die Herstellung von Akkus keineswegs CO2 neutral und ihre  Effizienz abhängig von der Häufigkeit/Dauer der Nutzung. Für die Produktion von Akkus wird meist viel Energie benötigt. Diese Energie und das dabei freigewordene CO2 muss sich erstmal amortisieren.

Es gibt verschiedene Typen an Akkus.
Um Verbraucher zu betreiben kann man direkt Gleichspannung nutzen oder benötigt einen Wechselrichter.

Es gibt fertige große Akkus für professionelle, industrielle Anwendungen, wie USVs, aber die kann man nicht leihen und sind sehr teuer in der Anschaffung. Auch ist die logistische Handhabung von diesen eher schwierig, da sie für einen stationären Gebrauch gedacht sind.

siehe auch: [[Wikipedia:Akkumulator]]

=== Typen/Technologien von Akkus ===
Es gibt verschiedenste Akku-Technologien mit unterschiedlicher Haltbarkeit und anderen Vor- und Nachteilen.
[Liste von Akku-Typen]
https://ethercalc.org/370rcajuc0vi

[Wikipedia:Nickel-Cadmium-Akkumulator] dürfen nicht mehr verkauft werden und von ihnen ist aufgrund des hochgiftigen Cadmiums, sowie aufgrund des Memory-Effektes abzuraten.

* [[Wikipedia:Lithium-Ionen-Akkumulator]]
* [[Wikipedia:Lithium-Eisenphosphat-Akkumulator]]
* [[Wikipedia:Lithium-Polymer-Akkumulator]]
* Hanfakkus - https://thisblowsmymind.com/hemp-batteries-are-even-more-powerful-than-lithium-and-graphene-new-study-shows/
* Lithium-Titanat - [[Wikipedia:Lithiumtitanat-Akkumulator]]
die zyklen die die akkus durchhalten und preis/(pro)zyklus

möglichst ohne Kobalt [Warum?]


https://www.golem.de/news/akkutechnik-in-zukunft-kommen-akkus-mit-weniger-seltenen-rohstoffen-aus-2002-146190.html


Die meiste Elektronik geht von Bleiakkus als Standard aus, weswegen bei anderen Akku-Technologien u.U. die Spannungsbereiche nicht passen, hier eine Übersicht.

{| class="wikitable"
|-
! Akku-Typ !! Spannung entladen (in V) !! Spannung geladen (in V) !! Ladespannung (in V)
|-
| Bleiakku || 10,5/10,8 || 13,8? || 14,4
|-
| 3S Li-Ion (LiCoO2) || 9 || 10,8 || 12,6
|-
| 4S Li-Ion (LiCoO2) || 12 || 14,4 || 16,8
|-
| Wechselrichter-Abschaltung || 10,2 (Unterspannung) || 10,8 (drohende Unterspannung) || 15,5 (Überspannung)
|}

siehe auch:
* [[Wikipedia:Bleiakkumulator]]

=== Laden und Entladen der Akkus ===
Akkus muss man natürlich laden, bevor man sie nutzen kann, dafür benötigt man u.U. spezielle Ladegeräte.
Verschiedene Akkus verhalten sich unterschiedlich beim entladen, z.B. wenn es um die Kapazität geht.
Deswegen muss man unterschiedliches beachten:
* Blei-Säure: damit Blei-Säure Akkus lange halten sollten diese nur bis 50% ihrer Kapazität entladen werden, damit das eingehalten wird ist die Anschaffung eines Akkuwächters sinnvoll.
* Lithium*: Lithium* Akkus bestehen meist aus mehreren Zellen, diese Zellen können durch ihre unterschiedlichen internen Widerstände unterschiedliche Ladestände aufweisen, was problematisch ist. Deswegen muss man sie balancen, bei einfachen Anlagen reicht ein Balancing am Anfang und regelmäßiges überprüfen, aber generell empfiehlt sich der Einbau eines BMS. Damit Lithium* Akkus noch länger halten kann man sie immer nur bis 90% laden und 10% entladen, dies kann man u.U. im BMS einstellen. Das BMS überwacht auch die Temperatur des Akkus und deaktiviert wenn der Akku zu heiß wird. Manche Lithium*-Akkus benötigen spezielle BMS wegen unterschiedlicher Spannungen und Funktionen.
* Speziell bei LiFePO4: LiFePO4 dürfen unter keinen Umständen bei Themperaturen um den gefrierpunkt geladen werden, da diese dann beschädigt werden, dafür empfiehlt sich ein BMS oder ein extra Bauteil, welches bei niedrigen Temperaturen die Stromzufuhr unterbricht. [schauen was genau, ob auch bei entladen]

Akkus sollten vor Tiefentladung geschützt werden, siehe [[Wikipedia:Tiefentladung]].

=== Versorgung von Verbrauchern ===

==== DC Direktversorgung ====
Viele Verbraucher werden mit Gleichspannung (DC) (z.B. 3V, 5V, 12V, 48V) betrieben.
(Beispiele wären USB Geräte, Handys, Laptops, Car-Hifi Verstärker, etc.)

Sie können Netzteile besitzen, welche die Netz-Wechselspannung in Gleichspannung umwandeln.

Verbraucher ohne extra Netzteil (direkter Gleichspannungs-Eingang) oder mit externen Netzteilen (wenn man das Netzteil weg lässt und den direkten Eingang nutzt) lassen sich am einfachsten betreiben.

Verbraucher mit eingebautem Netzteil können modifiziert werden oder benötigen einen Wechselrichter (siehe unten).
Da die Umwandlung in Wechselspannung und wieder zurück zu Gleichspannung Verluste birgt ist es effizienter Verbraucher direkt mit Gleichspannung zu betreiben.

==== Wechselrichter ====
Wenn die Verbraucher eine Wechselspannung (normalerweise 230V 50Hz) benötigen, z.B. normale Aktivboxen, dann benötigt man einen Wechselrichter (Inverter), der die Gleichspannung (DC) in Wechselspannung (AC) umwandelt.

Die meisten Wechselrichter arbeiten mit Spannungsbereichen um 12V oder 48V als Eingangsspannung.

Es gibt zwei Arten von Wechselrichtern:
; Modifizierte Sinuswelle (modified sine wave)
: Diese Inverter geben ''keine'' richtige Sinuswelle ab, sondern die Spannung ist Stufenförmig. Sie sind verbreiteter und günstiger, aber nicht alle el. Verbraucher kommen mit der Wellenform zurecht.
; reine Sinuswelle (pure sine wave)
: Pure sine Inverter geben eine nahezu richtige Sinuswelle aus. Sie sind teurer, aber es sollten alle Verbraucher problemlos funktionieren.

[Bilder der Wellenformen]

Zusätzlich zu diesen zwei Arten gibt es noch Wechselrichter welche Zusatzfunktionen integriert haben. Manche haben direkt ein Ladegerät/Laderegler integriert um die Akkus von Solarpanelen zu laden. Manche Wechselrichter besitzen eine Netzvorangschaltung (NVS), mit der sie wie eine USV (Unterbrechungsfreiestromversorgung) funktionieren. Bei der NVS wird ein eingehender Wechselstrom (230V 50Hz) nur durchgeschleift, außer dieser wird unterbrochen, dann fungiert das Gerät als normaler Wechselrichter und zieht Strom aus Akkus. Und sogenannte "Grid Tie Inverter" synchronisieren sich zur Wechselspannung vom Netz oder von anderen Invertern und können so eine größere Leistung bereitstellen.

===== Beispiel für ein Akkusystem mit Wechselrichter =====
* Zeit t in s (Sekunden), h (Stunden)
* Spannung U in V (Volt)
* Stromstärke I in A (Ampere)
* el. Leistung P = U·I in W (Watt)
* el. Energie Eel. = U·I·t = P·t in Ws, Wh, J (Joule)

z.B. Anlage mit 1500W, soll 3h laufen, 12V Akku, Wechselrichter braucht 20% mehr wegen Umwandlungmund Verlusten.

''[diese Beispiel-Berechnung geht von Maximalwerten aus, die nur mit Rosa-Rauschen erreicht werden, auch wenn man Musik spielt sind die Leistungswerte meist geringer, erst recht wenn man nur Sprache hat.]''

erstmal brauchen wir einen wechselrichter mit min. 1,5kW Leistung.

1500W·120%=1800W

1500W Ausgang, 1800W Eingang

1800W/12V = 150A

1800W·3h = 5400Wh

5400Wh/12V = 150A·3h = 450Ah

Wir brauchen einen 450Ah Akku um die Anlage für 3h zu betreiben.

== Superkondensatoren ==
siehe auch [[Wikipedia:Superkondensator]]

Superkondensatoren sind spezielle Kondensatoren, mit großer Kapazität. Superkondensatoren haben im Vergleich mit Akkumulatoren zwar eine viel geringere Energiedichte, aber eine viel höhere Leistungsdichte. Eingesetzt werden sie z.B. in hybrid Bussen.


[[Kategorie:Wissen & Diskurs]][[Kategorie:Technik-IT Support]]

<<<

<<list-links "[all[current]tagging[]]">>

* https://grabcad.com/oleksandr.stepanenko-1/models
* [[KINEMATICS - Introducing a new highly modular motion system (This is not CGI)|https://www.youtube.com/watch?v=MvEpi4FDhuI]]
* https://wiki.opensourceecology.de/Universal_Prototyping_Kit
** https://wiki.opensourceecology.de/Upklib
** https://wiki.opensourceecology.de/Kategorie:OSEG_-_UniPro-Baukasten
* http://www.contraptor.org/
* http://gatonero.wikidot.com/
* [[3D Printing Optomechanical Components|https://www.youtube.com/watch?v=NfjQO9_9C1U]]
* [[Let's build a TBot cartesian motion platform|https://www.youtube.com/watch?v=Ww2grGsl3Dk]]
* http://corexy.com/
* https://www.werkstatt-lastenrad.de/index.php?title=XYZ-Spaceframe-Vehicles
** http://www.n55.dk/MANUALS/SPACEFRAMEVEHICLES/spaceframevehicles.html
* https://openbuilds.com/
** not really open, atleast not open hardware, but good documentation
** parts can be bought from aliexpress for much cheaper
** 
General

* http://www.werkstatt-lastenrad.de/index.php?title=Hauptseite
* https://de.wikipedia.org/wiki/E-Bike
* Legal
** Pedelec-Norm
** [[StVZO|https://www.gesetze-im-internet.de/stvzo_2012/]]
** https://dejure.org/gesetze/StVG/1.html
** http://pdeleuw.de/fahrrad/anhaenger-fakten.html
* https://de.oho.wiki/wiki/Kategorie:Fahrradanh%C3%A4nger
* https://konglomerat.org/projekte/velozack.html
* https://rostiges-ross.de/angebot/kursangebote/#lastenrad

Carla Cargo

* commercial: https://www.carlacargo.de/
* http://www.werkstatt-lastenrad.de/index.php?title=Bauanleitung_Carla_Cargo_Crowd
* http://www.werkstatt-lastenrad.de/index.php?title=Carla_Cargo_Crowd_Klone
* https://pedalkreis.org/konstruktionen/carlacargo/
* https://grabcad.com/library/carla-cargo-crowd-1#!
* [[Bicycle Trailer Carla Cargo Crowd, Blueprints, Open Source Hardware, DIY - Part I|https://www.youtube.com/watch?v=ydK5dYZHsvk]]

https://charrette.bike/

* https://hackaday.com/2023/01/02/a-bicycle-trailer-fit-for-heavy-haulage/
* [[google translate|https://charrette-bike.translate.goog/?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp]]
* carla-cargo-like design, completely open source (cern ohl-w v2 bzw. cc-by-sa)

xyz spaceframe - like

* http://www.n55.dk/MANUALS/SPACEFRAMEVEHICLES/spaceframevehicles.html
** maybe one can find others xyz spaceframe designs online?
* different designs by https://wicycle.com/productlist
** should be easy to copy - https://wicycle.com/products/bike-trailers/heavy-duty-flatbed
* https://www.werkstatt-lastenrad.de/index.php?title=XYZ-Spaceframe-Vehicles

different

* https://www.instructables.com/id/Simple-No-Weld-Bike-Trailer/
* https://www.instructables.com/id/Gregs-Electric-Powered-Bicycle-Trailer/
* https://de.oho.wiki/wiki/Do_it_yourself_Fahrradanh%C3%A4nger_2

commercial, inspiration

* http://rollouttrailers.com/
* https://www.kickstarter.com/projects/946696900/brouhaha-bicycle-trailer/description
* https://www.bikesatwork.com/bike-trailers/features

components that are harder to design:

* overrun brake (auflaufbremse)
* trailer hitch/coupling
** has to move/rotate pretty freely horizontally (around the Z axis)
** but also needs to allow for some movement in the other axis and some rotation around the other axis
General

* http://www.werkstatt-lastenrad.de/index.php?title=Hauptseite
* https://pedalkreis.org/konstruktionen/
* https://de.wikipedia.org/wiki/E-Bike
* Legal
** Pedelec-Norm
** [[StVZO|https://www.gesetze-im-internet.de/stvzo_2012/]]
** https://dejure.org/gesetze/StVG/1.html
* https://de.oho.wiki/wiki/Kategorie:Fahrr%C3%A4der

xyz spaceframe

* http://www.xyzcargo.com/cycles/ - http://www.xyzcargo.com/de/raeder/ - semi-commercial
** https://github.com/FreeCutter/XYZ_ONESEATER
** https://github.com/bmsleight/xyx-spaceframe-openscad
** https://de.oho.wiki/wiki/XYZ_EINSITZER
** http://www.n55.dk/MANUALS/SPACEFRAMEVEHICLES/DIY.pdf
** https://taz.de/Transportfahrrad-zum-Selberbauen/!5087985/
* http://www.n55.dk/MANUALS/SPACEFRAMEVEHICLES/spaceframevehicles.html
** maybe one can find others xyz spaceframe designs online?
* https://projects.opennext.eu/@xyz-cargo-add-ons/xyz-cargo-add-ons
* https://www.werkstatt-lastenrad.de/index.php?title=XYZ-Spaceframe-Vehicles

stuff

* [[Wie man ein Fahrrad baut - SWR Handwerkskunst|https://www.youtube.com/watch?v=ZUK7SKumutQ]]
* https://hackaday.com/2023/08/28/making-an-injection-mold-for-yourself/
* https://www.youtube.com/watch?v=82KKr3jGxU8
* https://www.youtube.com/watch?v=WhWyN0wKkR4
* https://www.youtube.com/watch?v=h_QD1ff3wJk
* https://www.youtube.com/watch?v=WCEvjRdkjrU
* https://www.youtube.com/watch?v=2CIcvB72dmk
* https://www.youtube.com/watch?v=pfkIcKx1dnQ
* https://www.youtube.com/watch?v=XlRK_SMWX7Y
* https://www.youtube.com/watch?v=Mjlwc4x3GKE
* https://www.youtube.com/watch?v=HYGBH33dnsc
people i know have got a roughed up monacore megaphone which doesn't really work anymore.
It's a pretty good model, pretty loud, but this one has seen some use.

* model is a TM-35
* powered by 8x 1.5V c-size alkaline batteries or 12V 3A using a typical DC jack (but the cable for that is missing or was optional)
* has a typical handpiece with mic, push-to-talk switch and volume potentiometer, wired with spiral cable
* has an integrated siren, activated with a switch on the handle
* m8 (13mm long) insert for mounting or so


!! the issues and my fixes:

1. i'm told the main problem is a corroded battery contact due to a battery leaking in the past.
i removed the problematic contact completely from the case. they have a hex head, a round recess below that and then M2? threads for normal cimp ring connectors.
someone already cleaned the corroded contact superficially with a screwdriver or so, but in doing so gouged some pretty deep groves in the cheap contact screws. By removing the contact fully i could clean the contact completely. Then i used a drill to spin the contact an used fine sand paper and scotch brite to get the contact surface more even and flat. its not perfect, but much better.

2. there is a broken plastic eyelet for the carrying strap.
its pretty conveniently placed and one might find a metal eyelet as replacement that can be screwed in place.
but i was not yet able to find a suitable one.
the other side has a metal eyelet.

3. The megaphone also just looks like shit due to sticker residue, gaffer/painters tape glue residue and other dirt.
i removed all the remaining tape.
then i was able to scrub off all of the glue residue with ethanol.

4. I know of prior problems due to broken wires inside the handpiece/mic.
there was tape holding the cable kink protection together. i carefully removed it and also removed the glue leftovers with alcohol.
the kink protection is split and also generally pretty cracked and desintigrating so it needs replacement. i could just fix it temporary with heat shrink tube, but that's not good. i got some new, different size kink protectors, the inside diameter is approx. 5,5 - 6,0 mm. they are a bit snug but i don't think that's bad.

5. After opening the handpiece i could see the damage done by previous repair attempts: the wires that were already repaired once had really bad solder joins and the microswitch got butchered. the plastic got melted pretty bad and the contacts shifted. it still kinda works but not really good i think.
i bought a replacement.
also the spiral wire was not secured into the strain relief, but that is an easy fix after fixing the kink protection.

6. most tape was used to hold the battery compartment closed, because the latch doesn't latch.
the problem is a missing o-ring that would function as spacer, but without it there is to much play and the latch can simply slip of.
i got a new 120mm diameter and 3mm thick o-ring. A bit bigger would probably also fit, but 3mm is fine. smaller would be too small though.

!! a bit reverse engineering:

the compression driver has no information printed on the back, but i did not disassemble the megaphone fully.

the amplifier board is a pretty simple, discrete design. maybe class ab?
it uses 2 TIP41C NPN power transistors and uses a center tapped transformer to drive the compression driver.
was opened, possibly has problems

data/features

* 8 mic/line inputs (screw terminals)
* 8 line outputs (screw terminals)
* 6 presets
* controll over Network (RJ45 Ethernet, IP) - for pc control
* RS485 in&out - for remote or pc control
* 4 switch inputs (for additional presets) and switch outputs
* usb-b input - for pc control
* EQ, feedback supression, mic preamps

links

* https://marani-proaudio.com/
* https://www.monacor.com/media/FLE/DRM880LAN_880WP.pdf
* https://www.huss-licht-ton.de/product_info.php/Monacor-DRM-880LAN-Digital-Matrix-Router/info/17967.html
* https://www.manualslib.de/manual/87626/Stageline-Drm-880Lan.html
* https://www.monacor.com/media/FLE/CA2019-EN@E48.pdf

!! chips/devices

general

* JRC 4580 - opamps
* 1x winbond w79e632a40pl - 8 bit microcontroller
* takamisawa A9W-K - relay - https://pdf1.alldatasheet.com/datasheet-pdf/view/343449/FUJITSU/A-9W-K.html
* Marani M716 - custom/proprietary DSP chip - https://www.marani-proaudio.com/public/DPA440A_4448QRT-M716.pdf
* flash chip for M716
* 1x 74hc125d
* 1x 74hc573d
* 1x 74hc57d
* 2x 74hc14d - hex inverting schmitt triggers
* ft24c2??
* 2x 3.3 LDO's
* 1x LM2596-adj
* pcf8563 - RTC

ethernet

* 1x crystallan cs8900a-cq3z - isa-bus ethernet controller
* 1x stm8s20x - 8 bit microcontroller

inputs

* 8x 2sc1815 - audio amplifier transistor (on inputs)
* 4x akm AK5385B - 4bit, 192kHz sampling 2ch A/D converter - https://pdf1.alldatasheet.com/datasheet-pdf/view/136849/AKM/AK5385BVF.html
* 8x that 1512 - mic preamp - https://thatcorp.com/datashts/THAT_1510-1512_Datasheet.pdf

outputs

* 1x akm ak4358vq - 192kHz 24-Bit 8ch DAC - https://pdf1.alldatasheet.com/datasheet-pdf/view/92559/AKM/AK4358VQ.html

rs485 / serial

* ch340t
* sp485ee


!! notes

mic/line inputs

* clearly laid out and separated
* each got 2sc1815, that1512, A9W-K relay and 4580 opamp and one channel of one
* each A/D converter got an LED, possibly for "Analog Input Overflow Detect" (Clip)

line outputs

* clearly laid out and separated
* 2x 4850, 1x A9W-K relay

switch inputs

each got a resistor, and 2 protection diodes, go directly to 74hc573d it seems

switch outputs

* each got a A9W-K relay, flyback diode and smd transistor for driving

other

* 1 additional A9W-K relay, maybe phantom power?
see [[diy motor faders / potentiometer / encoders]]

* https://www.youtube.com/results?search_query=motor+fader
* https://groupdiy.com/threads/motorized-fader.2899/

sourcing

* ALPS is THE brand, but very expensive
* https://de.aliexpress.com/item/32906456269.html
* https://www.ebay.de/itm/254712111755
* https://www.ebay.de/itm/185293627969
* https://www.thomann.de/de/mixer_zubehoer.html?feature-590%5B%5D=Fader&feature-590%5B%5D=Motorised%20Fader&gk=PAMIZU&filter=true
* Yamaha Fader LS9 and Behringer X-Touch Motor-Fader MF100T look very similar
* https://www.adafruit.com/product/5466
** in datasheet: sm10001nka0x-ha1, sm10002nkb0x-ha2, sm10002nka1x-hw1
** looks like faders from Soundwell Electronic Products Guangdong Co., Ltd.
* https://soundwell.en.alibaba.com/index.html
* https://www.alibaba.com/product-detail/high-quality-wholesale-winele-100mm-60mm_1600232722496.html
* http://www.taiwanalpha.com/en/products/48
* Bourns

using

* https://tttapa.github.io/Pages/Arduino/Control-Theory/Motor-Fader/
* [[Custom Fader Board Project|https://www.youtube.com/watch?v=F_ABZ2ELtX0]]
* https://blog.codyhazelwood.me/motorized-faders-and-the-arduino/
* https://hackaday.io/project/189565-motorized-sequencer
<<list-links "[all[current]tagging[]]">>

* https://hackaday.com/tag/motor-controller/
* https://github.com/jsphuebner/inverter-hardware
* https://www.patreon.com/openinverter
* https://m.youtube.com/watch?v=47UbqTG6Cfo
* https://github.com/damienmaguire/Inverter
* https://github.com/dimecho/Open-Inverter-Dashboard
* https://openinverter.org/docs/index.html%3Fen_home,3.html
* https://github.com/SDI-SoftwareDefinedInverter/TAPAS/
* https://github.com/osannolik/MotCtrl
* https://github.com/tumanako
* https://github.com/damienmaguire/Nissan-Leaf-Inverter-Controller
* https://github.com/damienmaguire/Prius-Gen3-Inverter
* https://github.com/xxJian/STM32_Based_SVPWM
* https://github.com/tomdebree/Volt-Inverter
* https://github.com/hakansrc/mlv_inv
* https://github.com/hildogjr/easyinverter
* https://github.com/damienmaguire/Lexus-GS450H-Inverter-Controller
* https://github.com/TUMFTM/Reliability_Models_of_Inverters
* https://github.com/sajtostaller89/Szakdoga_Ctrl_Software
* https://github.com/L-Orsi/Three-Phase-Inverter-PWM-Generator?
* https://github.com/damienmaguire/Prius-Gen-2-Inverter
* http://www.powerdesigns.ca/
* https://hackaday.io/project/27421-ev-powershield
* https://www.ti.com/solution/hev-ev-inverter-motor-control
* http://eet.etec.wwu.edu/ahmanna/project/docs/Prodject%20description.pdf - Open Source 100kW Electric Vehicle Controller/Inverter
* https://www.hackster.io/eformula/formula-sae-electric-quad-inverter-593f40
the type of controller depends on the type of the motor

DC Motor

* simple PWM based controll
* [[Motor speed controller tutorial - PWM how to build|https://www.youtube.com/watch?v=UPTU6nYSaMo]]

BLDC motors

* [[ESC / BLDC motor driver / controller]]

AC Motors

* [[motor controller / motor inverter]]
* https://en.wikipedia.org/wiki/Maximum_power_point_tracking
* https://hackaday.io/search?term=mppt
* https://github.com/search?q=mppt
* https://de.wikipedia.org/wiki/Maximum_Power_Point_Tracking
* https://libre.solar/hardware/cc-overview.html
** https://learn.libre.solar/system/charge_controller.html
* https://www.instructables.com/ARDUINO-SOLAR-CHARGE-CONTROLLER-Version-30/
* type of power optimizer: https://en.wikipedia.org/wiki/Power_optimizer
* [[MPPT Solar Charger Prototype - 12V Lead-Acid Battery - Bulk Absorption Float|https://www.youtube.com/watch?v=28WZRZiZuS4]]
* https://github.com/twischer/MPPTCharger - MPPT Charge Controller for ESP8266
* https://github.com/twischer/MPPTCharger
* reference designs
** https://www.ti.com/solution/solar-power-optimizer
** https://www.ti.com/solution/solar-charge-controller
* [[Cheap(est?) Lithium MPPT Solar Charge Controller CN3722 - 12v Solar Shed|https://www.youtube.com/watch?v=liYZ5pYOZDE]]
* [[#142​ Solarenergie für den ESP8266, Arduino, etc. (mit deutschen Untertiteln)|https://www.youtube.com/watch?v=WdP4nVQX-j0]]
* [[#154​ Solar Charger for Microcontrollers|https://www.youtube.com/watch?v=dBx-g1dkdDQ]]
* [[#155​ The 5 Best Solar ChargerBoards for Arduino and ESP8266|https://www.youtube.com/watch?v=ttyKZnVzic4]]
* [[Another Cheap MPPT Charge Controller - CPT-LA10 - 12v Solar Shed|https://www.youtube.com/watch?v=1z5r3Yo6fmQ]]
* [[Solar Battery Charger (LiPo/Li-Ion) -- DIY or Buy|https://www.youtube.com/watch?v=kEttqWJrdww]]
* [[Cheap 3s Lithium Solar Charging & Balancing Module|https://www.youtube.com/watch?v=vDb6JDr-F-c]]
* [[Julian's Postbag: #48 - MPPT Solar Buck Regulator LED Display|https://www.youtube.com/watch?v=GlnjyFnFiR0]]
* [[Revisiting MuPPeT|https://www.youtube.com/watch?v=R1E5RDWQCMU]]
* [[DIY 1kW Arduino MPPT Solar Charge Controller (WiFi ESP32)|https://www.youtube.com/watch?v=ShXNJM6uHLM]]
* https://github.com/LucyJenkins/MPPT-Raspberry-pi-Pico-Shield
* https://github.com/Ralim/OpenMPPT
* https://github.com/elektra42/freifunk-open-mppt
* see also [[PC troubleshooting tools]]
* https://www.ventoy.net/en/index.html
** https://github.com/ventoy/Ventoy
* https://www.pendrivelinux.com/yumi-multiboot-usb-creator/
* https://github.com/mbusb/multibootusb
* see [[measuring voltage]]
* see [[measuring current]]
* see [[component testers / LRC / LC meter]]
* [[EEVblog #853​ - How A Multimeter Works|https://www.youtube.com/watch?v=yuCXsT3_WRE]]
* [[EEVblog #373 - Multimeter Input Protection Tutorial|https://www.youtube.com/watch?v=zUhnGp5vh60]]
* [[EEVblog #1067 - Analog vs Digital Multimeters!|https://www.youtube.com/watch?v=HHALK0sv1Y0]]
* [[EEVblog #929 - Designing A Better Multimeter|https://www.youtube.com/watch?v=jx0dryLmUEQ]]
* [[300 Volt, 100 Amp Meter for Solar Panel|https://www.youtube.com/watch?v=Yuna7CgLK7k]]
* [[Arduino Ammeter (with OLED) Converted to Wattmeter|https://www.youtube.com/watch?v=zvcTUMBGO24]]
* [[Easy Current & Voltage Measurements w/Arduino and LTC2945|https://www.youtube.com/watch?v=PVj4k0R9s4E]]
* INA226 - voltage (0-36V, 16bit), current and power, I2C, SMBus
** https://www.ti.com/product/INA226
* https://hackaday.com/2020/08/02/a-diy-6-5-digit-multimeter-is-a-lesson-in-clever-circuitry/
https://www.mumble.info/
https://wiki.mumble.info/wiki/3rd_Party_Applications

Mumble in the web:
https://github.com/Johni0702/mumble-web
https://voice.johni0702.de/?address=voice.johni0702.de&port=443/demo

* can only use port 80 or 443 (better use 443), so mumble also needs to listen on port 443 or you redirect it ([[Websockets|https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications]])
see:

* [[Recording Audio]]
* [[digital audio]]
** [[Open Source Audio Software]]
** [[Midi]]
** [[LADSPA, LV2 - Open Source VST alternative]]
** [[algorithmic / generative / computer art]]

* https://de.wikipedia.org/wiki/Tracker_(Musik)
* https://swiki.hfbk-hamburg.de/MusicTechnology/
* https://en.wikipedia.org/wiki/Category:Algorave
* https://en.wikipedia.org/wiki/Algorave
* https://en.wikipedia.org/wiki/Category:Audio_programming_languages
** ~SuperCollider
*** https://www.youtube.com/results?search_query=supercollider
*** https://www.youtube.com/results?search_query=supercollider&page&utm_source=opensearch
* https://en.wikipedia.org/wiki/Software_effect_processor
* https://github.com/sonic-pi-net/sonic-pi
* https://github.com/webprofusion/OpenAudio

sounds

* https://twitter.com/lincnotfound/status/1381418322776973312
* https://www.youtube.com/watch?v=v3O9vNi-dkA
* [[Marti Fischer feat. Make A Move - Der Gang|https://www.youtube.com/watch?v=XjOAA18z9uw]]
* https://de.wikipedia.org/wiki/Moscow_Death_Brigade
* The Prodigy
* [[https://en.wikipedia.org/wiki/Ministry_(band)]]
* Ling Ling (freetaxler)
** https://soundcloud.com/freetaxler/ling-ling-vs-enko-through-the-wormhole
* Enko
**  https://soundcloud.com/enkosound/enko-vs-ling-ling-sugarshock
* Multiplan Collective
* Cult Collective
** https://cult-collective.bandcamp.com/music
** https://cult-collective.com/artists/
* https://soundcloud.com/npma44
* reine wäsche
** http://twitch.tv/reinewaesche
** https://www.youtube.com/watch?v=t1ptI-yi5Pk
** http://reinewaesche.de/
* https://soundcloud.com/pangaea-dresden
* https://de.wikipedia.org/wiki/Kategorie:Schwarze_Szene
** https://de.wikipedia.org/wiki/Die_Schwarze_Szene_im_Spannungsfeld_rechter_Ideologien
** https://de.wikipedia.org/wiki/Kategorie:Gothic
** https://de.wikipedia.org/wiki/Kategorie:Dark_Wave
* Knorkator
* Grimmige Gabi - https://soundcloud.com/user-168030047/tracks
* https://soundcloud.com/cyanit
* https://www.youtube.com/watch?v=7LiRuluQP20
** https://mjut.me/
* https://soundcloud.com/search?q=tolerave
* https://soundcloud.com/synthieverrueckt/popular-tracks
* https://soundcloud.com/analog-tecne-model
* https://soundcloud.com/hesed-atm/popular-tracks
* https://soundcloud.com/chantalcyberrise/popular-tracks

stuff to try out:

* https://de.wikipedia.org/wiki/M%E2%80%99era_Luna_Festival
see [[Audio streaming]]

* raspberry pi oder ähnliches
** linux
** 
* audio out
** pcm5102 - habe ich noch rumliegen
** pcm5122
** https://www.ti.com/lit/ds/symlink/pcm5242.pdf - would be nice
** https://www.raspberrypi.com/products/dac-pro/
*** https://www.raspberrypi.com/documentation/accessories/audio.html#raspberry-pi-dac-pro
** https://www.hifiberry.com/shop/boards/hifiberry-dac2-pro-xlr/

weiteres

* https://sonobus.net/
* https://jamulus.io/
* [[ High Fidelity Audio on a VHF Amateur Radio Repeater - (NSFW) |https://www.youtube.com/watch?v=lwVgrxgyU3E]]

funk

* https://de.wikipedia.org/wiki/M17_(Amateurfunk)
* MMDVM
** https://github.com/g4klx/MMDVM
** https://mmdvm.com/
* https://en.wikipedia.org/wiki/Digital_mobile_radio
* DAB?
* https://m17project.org/get-started/software
* https://wiki.m17project.org/hotspot_mmdvm
* https://github.com/g4klx/MMDVM
* https://www.rowetel.com/wordpress/?page_id=452
* https://en.wikipedia.org/wiki/Spectral_efficiency#Comparison_table
* https://en.wikipedia.org/wiki/List_of_interface_bit_rates
* https://en.wikipedia.org/wiki/Comparison_of_wireless_data_standards
* https://en.wikipedia.org/wiki/Digital_radio
* WIFI?
** low-latency / low jitter
** wifi-direct (p2p)
** wifi broadcast
* [[wireless microphone hacking / reprogramming]]?




https://wiki.fridaysforfuture.is/index.php?title=Musikstreaming_zwischen_Lautis_(Konzept)

wenn die latenz nicht so kritisch ist geht streaming über Internet, z.B. über tools wie Mumble, ganz gut.

für niedrigere Latenzen braucht es andere funklösungen die integrierter sind.

professionelle/proprietäre funkstrecken sind sehr teuer (200+€) und haben reichweiten von <100m (Bühnengröße).

* https://www.thomann.de/de/drahtlose_audiouebertragungssysteme.html?oa=prd

WLAN könnte eine gute lösung sein:

* WLAN netzwerk und audio streaming darin
** mit mumble: nicht die beste idee, konvertierung und komprimierung steigert die latenz enorm
** VBAN: proprietary shit
** direkter stream, z.B. mit linux tools (Beispiele?) ist da viel besser
* [[ESP32 high-quality audio transmitter]]
* https://www.youtube.com/watch?v=ZXz-u1f-uw0

* https://www.eetimes.com/achieving-ultra-low-latency-digital-wireless-audio/
* https://www.techhive.com/article/583730/wisa-low-latency-wireless-multi-channel-audio-standard.html
* https://www.reddit.com/r/CommercialAV/comments/9me47n/lowest_possible_latency_wireless_audio_streaming/
* RT-WIFI
** https://ieeexplore.ieee.org/document/6728869
** https://arxiv.org/pdf/2203.10390.pdf
** https://link.springer.com/chapter/10.1007/978-3-030-31831-4_20
** https://ls12-www.cs.tu-dortmund.de/daes/media/documents/teaching/courses/rts/rt-wifi.pdf
** https://pdfs.semanticscholar.org/984b/d8f9d17e63e25e18cd01f232c9a2d2313740.pdf
** https://arxiv.org/abs/2203.10390


save aus FFF wiki - https://wiki.fridaysforfuture.is/wiki/Musikstreaming_zwischen_Lautis_(Konzept)

<<<

Für größere Städte, mit größeren Demonstrationen mag es interessant sein mehrere Lautis zu nutzen um die komplette Demonstration zu erreichen, da mehrere kleine Anlagen effizienter sein können als eine große.
Jedoch ist es dabei nicht (einfach) möglich auf allen Lautis die selbe Musik zu spielen oder die reden gleichzeitig zu haben.

Ziel dieses Artikels soll die Sammlung von Informationen zu einem Konzept für den Bau von Funkmodulen sein.
Mit Diesen Funkmodulen soll es möglich sein die Musik in guter Qualität und ohne hohe Verzögerungen zwischen Lautis zu streamen.

Funkübertragung
* analog
** in Masse wohl billiger
* digital
** Bluetooth
*** nicht mehr als 100m
*** Bluetooth Mesh wäre Option
** WLAN
*** mit der 100mW Begrenzung der Funkleistung ist man auf ca. 300m unidirektional im Freien begrenzt
*** bessere Antennen, vor allem mit Richtwirkung können da was raus holen
*** Verstärker sind aus legalen Gründen eher nicht empfohlen
** mit Smartphone (Mumble) <ref>https://wiki.systemli.org/howto/mumble_fuer_redebeitraege_auf_demos</ref>

==In der Praxis==

Es gibt Städte wie Potsdam, in denen wir mehrere Übertragungstechniken regelmäßig anwenden und unsere Erfahrungen hier mit euch teilen wollen. Bei Fragen könnt ihr uns jederzeit per E-Mail kontaktieren (potsdam @ fridaysforfuture punkt unsere domain).

===Analoge Funkübertragung===

Für die mobile Funkübertragung gibt es fertige Techniken, die sich in der Veranstaltungstechnik finden, eigentlich dienen sie wie Funkmikrofone der Übertragung auf kurze Strecken auf der Bühne. In der Praxis haben wir mit solchen Systemen aber auch schon Funkübertragung über bis zu 250m realisiert. Mit professionellem Antennenequipment (Richtfunktechnik) lässt sich dies auch noch erweitern, aber ein großes Problem sind Störfaktoren. Insbesondere um Häuserecken hilft auch die beste Antenne kaum etwas.

Unsere Sets bestehen meist aus einem Taschensender (meist  mit 2xAA-Akkus betrieben) und einem stationären Empfänger auf dem nächsten Lastenrad. Ein günstiges Setup, mit dem wir angefangen haben, ist das [https://www.thomann.de/de/the_t.bone_free_solo_pt_823_mhz.htm free solo PT], das wir als Versandrückläufer erworben haben. Dies gibt es in verschiedenen Frequenzbereichen (Achtung: besorgt unbedingt solche, die von 823-832, 863-865 und / oder im 1.8GHz-Bereich funken, andernfalls können Lizenzen für die Frequenznutzung anfallen. Wenn ihr euch hier unsicher seid, fragt sicherheitshalber nach!). Auch wenn das für unsere Zwecke ein guter Start war, das System hat auch Macken. So hat unser Empfänger beim ersten Versuch nicht funktioniert und wir mussten es tauschen. Insgesamt ist das wohl eine sehr "billige" und keine hochwertige Lösung - aber mindestens so viel solltet ihr investieren, darunter wird es nur noch schlimmer!
Wir sind inzwischen bei Funkstrecken der Firma Sennheiser gelandet, die wir gebraucht erworben haben, damit ist die Qualität deutlich besser.

Um das Setup zu nutzen, speist ihr Sound von einem Lauti oder Lastenrad in den Funksender, stellt dort die Verstärkung runter (für Instrumentenabnahme ist diese meist erhöht, z. B. auf 9dB. Stellt diese auf 0 oder noch weniger). Stellt dann am Empfänger unbedingt den "Squelch" runter. Diese Einstellung besagt, dass bei schlechtem Empfang sich der Empfänger stummstellt und lieber Aussetzer in Kauf nimmt, als lästige Störgeräusche. Experimentiert hier gerne rum, aber unsere Erfahrung ist, dass gelegentliches Rauschen bei ständiger Übertragung deutlich besser ankommt als abgehakte Musik.

Wenn ihr hier weitergehen wollt, könnt ihr auch bessere Funksender kaufen, schaut dazu nach sogenannten IEM-Sendern (in-Ear-Monitoring, diese senden einen Audiostream). An diese könnt ihr u. a. bessere Antennen anschließen, z. B. mit Richtwirkung. Da es hier aber schnell teuer wird und ihr natürlich auch darauf achten müsst, dass eure Anlage kompatibel bleibt, empfehlen wir hier Absprache mit Menschen, die Erfahrung in dieser Richtung haben, z. B. euren lokalen Veranstaltungsverleih.

===Digitale Übertragung über Mobilfunk===

Ein weiteres sehr vielversprechendes Konzept, das auch ohne hohe Investitionen in Funktechnik auskommt und dabei deutlich flexibler ist, weil man z. B. auch mit großem Abstand oder sogar an zwei Standorten in der Stadt funken kann, ist eine Funkverbindung über Mobilfunk (am besten LTE oder 5G falls verfügbar). Wir haben das in Potsdam zuerst während der Coronapandemie eingesetzt, um zwei getrennte Veranstaltungen zusammenzuschalten und dabei sogar Gespräche bei der Moderation 

Wir haben dafür die Software [https://mumble.info Mumble] eingesetzt. Unser Setup funktioniert so: 
* Es gibt einen zentralen Webserver, der installiert werden muss. Ihr könnt hier entweder einen eigenen installieren oder einen aus der öffentlichen Liste wählen. (PS: [[Infra4future]] stellt auch einen Mumble-Server zur Verfügung.)
* Alle Geräte verbinden sich mit diesem Server und tretem einem gemeinsamen Audiochannel bei
* Ein Gerät überträgt das Audio von einem Lastenrad in die Cloud. Am besten nehmt ihr hier einen Laptop, dort gibt es viel mehr Einstellungen und man behält auch leichter den Überblick, was man dort einstellt.
* Alle weiteren Geräte an den anderen Lautsprechern (auch hier gerne Laptops, Smartphones reichen aber (App-Empfehlung: Mumla)) verbinden sich, stellen sich stumm und geben den Ton aus.

Die Übertragung ist nun unabhängig von Hindernissen zwischen den Lastenrädern oder Lautsprechern wie Gebäudeecken, hohe Abstände etc, aber ihr seid nun auf den Mobilfunk angewiesen. Gerade da, wo ihr euch nicht bewegt und Sichtlinie habt, ist eine analoge Funkverbindung deutlich stabiler als der Weg über Mobilfunknetze.

====Internet====
Damit das also funktioniert, braucht es für jeden Lautsprecher oder jedes Lauti-Rad eine Internetanbindung. Dafür könnt ihr z. B. Hotspots per Smartphone aufmachen, LTE-Router nutzen (gibt es ja manchmal als Heimrouter dort, wo kein DSL verfügbar ist), euch Internetsticks kaufen oder ähnliches.

Wir haben bei Discountern mehrere SIM-Karten gekauft und können bei diesen dann Tagesflats aktivieren (z. B. 5€ für 24 Stunden). Ihr könnt natürlich auch einfach eure bestehenden Smartphones nehmen, das ist deutlich günstiger - bei uns möchte aber meist niemand sein Smartphone für ein paar Stunden aus der Hand legen, man könnte ja etwas verpassen (und mein eigenes ist leider zu alt für stabiles Internet ...).

====Setup====
Damit das Streaming über Mumble gut funktioniert, haben wir folgende Einstellungen für gut empfunden:

Wir empfehlen in allen Fällen eine Bitrate von etwa 48kbps. Das ist sehr wenig, reicht aber für Sprache und die meiste Musik ganz gut aus. Ihr könnt gerne herumprobieren, was bei euch im Netz stabil funktioniert. Beachtet bitte, dass einige Einstellungen '''nur im Desktop-Client''' verfügbar sind. Außerdem betreffen die Sendeeinstellungen nur das jeweilige Gerät. Das hat den Vorteil, dass ihr zentral am Sendegerät einstellen könnt mit welcher Qualität übertragen wird, aber dadurch können die, die vielleicht die schlechte Übertragung hören, nichts mehr umstellen. Testet das unbedingt gemeinsam aus.

Nachfolgend zwei Setup-Möglichkeiten zur Übersicht:

Die Übertragung (UDP/TCP) gibt an, mit welchem Netzwerkprotokoll die Daten übertragen werden. Bei UDP ist es nicht schlimm, wenn ein Paket fehlt, das wird dann einfach ignoriert und fehlt. Das führt zu dem bekannten Robotersound // Aussetzen, was ihr vielleicht von Telefonkonferenzen kennt. Bei TCP wird bei schlechter Verbindung darauf gewartet, dass ein Paket kommt. Dann hält alles kurz an und lädt (wie bei einem Videoplayer) und macht dann aber ohne Verluste weiter. Dadurch entsteht bei Livestreams aber eine immer größer werdende Verzögerung.

Die Einstellung "Audio pro Paket" gibt an, wie viele Audiodaten in jedem Paket übertragen werden. Bei UDP ist ein kleiner Wert interessant, weil dann bei einem verlorenen Paket weniger am Stück fehlt. Die kleinste Einstellung ist daher hier günstig. Da weniger Audio pro Paket im Umkehrschluss auch mehr Pakete pro Audio bedeutet, braucht man hier mehr Netzwerkbandbreite, weil die kleinere Stückelung mehr zusätzlichen Kommunikationsbedarf hervorruft. Bei TCP, wo auf jeden Fall auf ein Paket gewartet wird, sollte der Wert daher möglichst hoch gewählt werden, da die kleine Einstellung kaum Mehrwert bringt.

{| class="wikitable"
|-
! Ziel !! Geringe Verzögerung !! Einzustellen an
|-
| Übertragung: || UDP (Standard) || Empfänger (Sender optional, ausprobieren!)
|-
| Audio pro Paket || 10ms || nur Sender
|-
| Bitrate || 48kbit || nur Sender
|}

Hält die Verzögerung meist unter einer Sekunde, aber bei schlechter Verbindung hört man Aussetzer sofort. Bei großer Paketgröße (60ms) versteht man kaum etwas, weil ganze Teile von Worten fehlen, wenn man das runterstellt (10ms) und Teile der Sprache verloren gehen, bleibt die Verständlichkeit gewährt - aber man merkt es

{| class="wikitable"
|-
! Ziel !! Gute Qualität !! Einzustellen an
|-
| Übertragung: || TCP (Umstellen!) || Empfänger (Sender optional, ausprobieren!)
|-
| Audio pro Paket || 60ms || nur Sender
|-
| Bitrate || 48kbit || nur Sender
|}

Hält die Verbindung aufrecht, bei kurzen Aussetzern stockt es, geht dann aber flüssig weiter (ohne Robotersound). Dabei wird die Verzögerung aber immer größer und kann bis zu 15 Sekunden betragen. Manchmal spricht der Client dann einige Sekunden weiter, was natürlich Teile der Sprache zerstört - insgesamt merkt man eine kurzzeitig schlechte Verbindung aber gar nicht, wenn schnell genug wieder genug Durchsatz da ist. Da zu empfehlen, wo die Lautsprecher nicht gegenseitig hörbar sind. Wenn sie in Hörweite sind, sorgt die Verzögerung schnell für Verwirrung.

====Perspektivisch====
In mittlerer Zukunft können sich interessierte mal ansehen, ob man mit diesen weiteren Apps für das Mumble-System stabilere Anlagen bauen kann, die z. B. auch einfach zu nutzen sind (etwa nur ein Gerät, was man einschaltet und mit dem Internet verbindet, statt viele Clients einzurichten).
[https://wiki.mumble.info/wiki/3rd_Party_Applications Drittanbieter-Anwendungen für Mumble]

[Kategorie:Wissen & Diskurs][Kategorie:Technik-IT Support]

<<<
kann auch kram verleihen

Audio

* PA Technik
* E-MU 0202 - USB Audio-Interface
* Tascam US-122L - USB Audio/Midi-Interface (kein Windows support mehr)
* Conrad "Sound Craft" SA-100 - alter analoger Stereo DJ-Mixer
* Speaka ER-66S - 25W Megafon
* La Mancha Zafiro C - Akustikgitarre
* kleine, schrottige 80W Stereo-Anlage mit Akku die an den gepäckträger vom Fahrrad gehangen werden kann (Verstärker mit Bluetooth)
* Harman/Kardon HK990
* JVC R-K100 Stereo Receiver
* Tascam US-428 - 7,5VAC 1A Netzteil fehlt - Mischpult/DAW-Controller/Audio-interface
* Philips SBC ME570 - electret microphone
* 2x Klippel Production Analyzer - allerdings ohne Software und co, müsste reverse engineered werden
* Soundwave Stereo Integrated Amplifier A-900 + Stereo Graphic Equalizer/Spectrum Analyzer Q-900
* Fußschalter mit 6,3mm klinke

Elektronik

* Peak Electronic Design ESR70 - ESR meter
** https://www.peakelec.co.uk/acatalog/esr70-capacitor-esr-meter.html
** with crocodile clips, needle probes and SMD tweezers
* günstiges 1-Kanal Oszilloskop
* Multimeter
* Rework-Station mit Heißluft
* 2x günstige Lötstation
* billiger simpler lötkolben ohne themperatursteuerung
* Voltcraft VC-521 - AC/DC Stromzange
* imax B6AC - Akku-Ladegerät mit Balancer
* Ladegerät für Smartphone Akkus von diversen Marken/Modellen
* TEC-06 - kleine Elektronische Last
* diverse Usb - UART/TTL Adapter
* unitec PM-12 - Energiekosten-Messgerät
** DREWAG Kunden (Dresden) können die bei der DREWAG ausleihen
** diverse bibliotheken verleihen http://no-energy.de/
* bus pirate - universelles serial capturing, debugging tool, programmer
* Crimpzangen für diverse normale Aderendhülsen, Kabelschuhe und diverse JST Stecker
* Crimpzange 10-300mm² (hydraulisch) - Crimpzange für Kabelschuhe/etc. von großen durchmessern
* Punktschweißgerät - für akku/batteriezellen
* Sammlung an Elektronik komponenten
* PL2303HX USB zu TTL RS232 konverter
* FT232BL/CH340G USB to Serial/TTL 

diverses, Computer kram

* 5 verschiedene Monitore/Fernseher
* DVD-Spieler - ein normaler, ein tragbarer
* diverse Computer
** Raspberry Pi 3B
* diverses Werkzeug, darunter viele Schraubendreher
* 2 WLAN-Repeater
* 2 Fritzbox 7362 SL
* USB Joystick
* Nintendo Wii
* GL.iNet GL-MT300N-V2 "Mango"
** https://docs.gl-inet.com/en/3/release_notes/gl-mt300n-v2/

generelles Werkzeug

* standard kram wie Zangen, Schraubendreher, Schraubenbits, darunter ein set spezial und sicherheitsbits
* Akku-Schrauber/Bohrer
* einige Metall und Holz Bohrer
* Körner, Senkbohrer, Stufenbohrer, Kegelbohrer, Fräsbohrer, Trockenbau schraubvorsatz, entrgrater
* Bügelsäge für Metall oder andere sägeblätter
* Laubsäge
* Dremel
* Lochzange und Ösen-/Druckknopf Zange
* günstiges Gewindeschneidset
* günstige Messschieber

geplant:

* Akku-Schrauber/Bohrer - müssen repariert werden
*günstiger E-Bass - muss repariert werden
* Lautsprecher Ersatzlast
draft

components

* DSL/cable modem
** shitty, probbaly provided by ISP
** routerfreiheit, ich kann ein kabelmodem wählen das ich möchte
** am besten ein stromsparendes gerät
* router
** running ~OpenWRT, ~LibreCMC, OPNsense, or similar
** with some VPN capability (~OpenVPN, Wireguard, etc.)
** https://www.youtube.com/watch?v=TPHwomummP8
* small "server"
** probably some sbc or mini pc
*** HDMI, other interfaces and LEDs or so turned off to save power
** thought about combining router and server to save power, but results in much more expensive router and is not as easy to use and manage; power savings are small or none
** with fileserver (nextcloud, syncthing or so)
** https://github.com/awesome-selfhosted/awesome-selfhosted
** see [[hosting]]
** https://www.etesync.com/
* some pc's/laptops/smartphones for "consumption"
* someone i know uses an APU2C4 with opnsense and a Draytek VDSL2+
* NAS, see [[DIY FLOSS home NAS]]
* https://www.sensorsiot.org/wireguard-and-nextcloud/

stuff

* https://www.draytek.de/vigor165.html
<<list-links "[all[current]tagging[]]">>

* several random, low power Computers and Laptops
* Raspberry Pi 3?
* (new) Schenker VIA 15 Pro

notes on how i set up my personal computers

"""
OS: Fedora Workstation or Debian
DE: GNOME
"""

* drive encryption
* ~KeepassXC and Gnome Keyring
* some accounts (Mail, Nextcloud) added to Gnome Accounts
* TOR Browser
* sudo dnf groupinstall "Development Tools" "Development Libraries" "Editors" "C-Entwicklungswerkzeuge und -Bibliotheken"
* sudo dnf install vim tmux

list installed software and gnome extensions?

* https://ownyourbits.com
* also see [[my network setup]] & [[hosting]]

maybe make some post-install setup script?

* https://github.com/snwh/fedora-post-install
* https://github.com/David-Else/fedora-ultimate-setup-script
* https://github.com/ChrisTitusTech/fedora-setup
* https://github.com/jwpowell/fedora-setup
* https://forum.electronicwerkstatt.de/phpBB/Projekte_im_Selbstbau/nabendynamo_z_diode_als_ueberspannungsschutz_wie-t96528f34_bs0.html
* https://de.wikipedia.org/wiki/Nabendynamo
* https://www.fairphone.com/
** https://wiki.lineageos.org/devices/FP3
*https://utopia.de/bestenlisten/fair-handy-faires-smartphone-liste/
* https://www.shiftphones.com/ - hat scheinbar mängel
* https://www.pine64.org/
** https://netzpolitik.org/2020/freie-smartphones-ist-das-pinephone-alltagstauglich/
* Purism - got havily criticiced by the community; they where/are copying and rebranding open source software, adding proprietary features and sell it as subscription service
meine ideen zum aufbau bzw. zur erweiterung einer nachhaltigen parallelgesellschaft neben dem kapitalismus. eine gesellschaft die nachhaltigkeit aktiv (vor-)lebt und aufzeigt das es möglich ist komplett nachhaltig zu leben, die nachhaltige revolution selbst in die hand nehmen und selbst umsetzen. als beispiel dresden

* [[Solarpunk]]-stil
* unkommerzielle projekte
* open source
* Repair-Cafes, Makerspaces
** [[maker, lab, repair, etc. spaces in dresden]]
** [[open workshops, hackerspaces, fablabs]]
** [[repairs]]
** 
** ...
* möglichst viel vehrkehr und transport mit ÖPNV und Fahrrad
** Verkehrswende Hacken - media.ccc.de
** gut ausgebauter, möglichst nachhaltiger ÖPNV
** Fahrräder, Leih Fahrräder, Leih Lastenfahrräder
** offene Fahrrad-werkstätten
** günstige Mietautos und Transporter
* kleine, nachhaltige läden
** quergedacht-stadtplan
** https://kartevonmorgen.org/
* "Müll" aus dem kapitalismus abgreifen und reparieren
* öffentliche (Stadt-)Gärten
** Gärten auf Tempelhofer Feld in Berlin
** Gartennetzwerk Dresden
** vertical gardening?
** aquaponics?
* bildungs- und informationsangebote
** für privatpersonen
** für behörden
* sharing is caring - depot.social
** https://en.wikipedia.org/wiki/Sharing_economy
* verschenken platform
* http://materialvermittlung.org/
* https://coma-emerald.de/%C3%B6kologische%20Stadtteilzentren.html
* Cradle to Cradle (C2C)
** https://de.wikipedia.org/wiki/Cradle_to_Cradle
** https://en.wikipedia.org/wiki/Cradle-to-cradle_design
* https://www.remap-berlin.de/
* "circular economy"
* https://www.dekringwinkel.be/
* https://buynothingproject.org/about/


weiteres:

* analysen dazu welche punkte in der stadt man durch ÖPNV + kurzen fußweg in geringer zeit absolvieren kann und welche nicht?
* wie wird das ganze finanziert, wie finanziere ich mich? ich bin träumer, sammle wissen und mache, ich bin kein kapitalist
* https://youtu.be/WGtRyESsCqc
* https://de.wikipedia.org/wiki/Cradle_to_Cradle
siehe auch [[Kultur Dresden]]

* https://ufer-projekte.de/
* https://quergedacht-dresden.de/
* https://gruenesbrett.net/
* https://sukuma.net/
** https://umundu.de/
* https://www.offene-werkstaetten.org
* https://www.reparatur-initiativen.de/
* https://www.reparatur-initiativen.de/reparatur-termine/?keyword=Dresden
* https://anstiftung.de/selbermachen/reparatur-initiativen
* https://foodsharing.de/
* [[https://adfc-dresden.de/76 -fahrradselbsthilfewerkstätten]]
* C3D2 - Chaos Computer Club Dresden - https://www.c3d2.de/
* Rosenwerk
** Konglomerat- https://konglomerat.org
** Werk-Stadtpiraten e.V. - https://www.werkstadtpiraterei.de/ - http://werkstadtpiraten.blogsport.de
** Näh.Werk - http://www.naehwerk.org
** Werk.Stadt.Laden.http://www.werkstadtladen.de
** ~FabLabDD - http://www.fablabdd.de
** http://materialvermittlung.org/
** Solidarische Landwirtschaft (~SoLaWi) (Abholstation des ~LebensWurzeln e.V., des Schellehof und deinHof)
* https://mangelwirtschaft.org/
** https://www.syndikat.org/mangelwirtschaft/

* Garten Netzwerk Dresden - https://www.dresden-pflanzbar.de/
* Freifunk Dresden - https://www.freifunk-dresden.de
* Offene Werkstatt des Männernetzerks Dresden (fragwürdig?) - https://mnw-dd.de/offene-werkstatt.html
* Kreative Werkstatt Dresden e.V. - http://www.kreative-werkstatt.de/ (dezent kaputte webseite)
* Drehwerk - töpferwerkstatt - https://drehwerk.wordpress.com/
* Fabmobil - http://www.fabmobil.org
* Hackerspace Turmlabor (Technische Sammlungen) - http://www.turmlabor.de
* Holzhilfe - http://www.holzhilfe.de
* Rad i.O- - http://www.rad-i-o.org, https://www.stura.tu-dresden.de/radio
* Radschlag - http://www.radschlag-dresden.de/
* rostiges Ross - https://www.rostiges-ross.de
* SLUB Makerspace - http://www.slub-dresden.de/service/arbeitsplaetze-arbeitsraeume/makerspace/
* JKS offene Werkstätten
** Keramik - https://jks-dresden.de/programm/kurse-workshops-offene-werkstaetten/
** Malerei/Grafik - https://jks-dresden.de/programm/kurse-workshops-offene-werkstaetten/malerei-grafik/
** Kunsthandwerk - https://www.jks-dresden.de/programm/kurse-workshops-offene-werkstaetten/kunsthandwerk/
** Musik - https://www.jks-dresden.de/programm/kurse-workshops-offene-werkstaetten/musik/

* Repair Café - https://repaircafe.fueralle.org/
* Hopis/Neustadtpiraten Cyberflausch
* Frieda & Friedrich - kostenloser lastenradverleih - https://friedafriedrich.de/
* (phase 4 - videothek)
* ~~saek - sächsischer ausbildungs und erprobungskanal~~
* https://www.medienkulturzentrum.de/
* https://www.datenkollektiv.net/
* https://rave-base.de/cms/
* https://zentralwerk.de/
** https://zentralwerk.de/programm/offene-fahrradwerkstatt/
* coole musik-gruppen
** https://obt.world/
** https://tekno.party/
* https://coloradio.org/
* http://zope6.free.de/terminal


weitere:

* https://asonet.pads.ccc.de/vernetzung (veraltet)
* https://codimd.c3d2.de/vernetzung
<<list-links "[all[current]tagging[]]">>

* [[Coding Adventure: Simulating an Ecosystem|https://www.youtube.com/watch?v=r_It_X7v-1E]]
* https://fahrradbus.com/
* https://www.freie-lastenradl.de/cb_item/bernd-lastenrad-buehne/
** https://x.com/ThomasMichels15/status/1518605504670539776
* Bicco Bike Bus
* Beerbikes
* siehe auch [[nachhaltige/coole Initiativen in Dresden]]
* https://brn-buero.de/
* Tolerave (mit der Tolerade)
* C3D2
* [[AZ Conni|https://www.azconni.de/]]
* Zentralwerk
* Rosenwerk / Konglomerat
** Werkstattpiraten
* Rad i.O und Rostiges Ross
* https://kulturbuero-dresden.de/
** [[Kinder- und Jugend Büro|https://kijubdd.de/]]
** https://www.hor-dresden.de/
* https://rave-base.de/
* Wagenplatz "Schotter und Gleise" - schotterundgleise.blogsport.de
* https://gerede-dresden.de/index.php
* Jugendarbeit, Streetwork, Treberhilfe
* https://www.naus-dresden.org/
* https://weltoffenesdresden.com/
* https://konglomerat.org/freunde-foerderer.html
* https://evibes.org/de/
* https://and.notraces.net/
* https://www.polizeiklasse.org/
* https://seebruecke.org/mach-mit/deutschland/sachsen/dresden
* https://twitter.com/hopedresden
* https://www.opensourceecology.org/portfolio/nickel-iron-battery/
ich mag autos eig. nicht so, aber gibt paar niedliche elektro transporter die sicher voll praktisch sind für einiges

* https://de.wikipedia.org/wiki/Streetscooter
* Wie sinnvoll sind Elektro-Transporter? - http://feedproxy.google.com/~r/netbooknewsde/~3/XiHFRPCz-7Y/
* https://www.autohaus-dresden.de/tropos/tropos-able/aufbauvarianten/pritsche.html
specific artificial "colored" noise can be useful when testing and meassuring audio equipment, but there is also unwanted noise from bad grounding, bad filtering e.g. in the power supply or similar:

* [[Inside an audio isolator transformer module.|https://www.youtube.com/watch?v=fV_hsFK1MnA]]
* [[How to remove buzzing/noise from a cheap Bluetooth Music Receiver? (Experiment)|https://www.youtube.com/watch?v=n_b_0BWP0mI]]
* [[How to solve EMC problems! -- The mystery of the buzzing speaker|https://www.youtube.com/watch?v=zvkfWfbQ4KA]]
* [[Brummschleifen verstehen und beseitigen.|https://www.youtube.com/watch?v=CN7kMoQn5Cs]]
i got this device because nobody at GTC had the knowledge to repair it and it was sitting untouched in a shelf for month. I took it on me to try to fix it, becaus it belong to coloradio, a great local crowdfunded community radio.

problem: at first the player can play CDs fine on both decks at first, but after some warm-up time (~15min) one of the decks starts to malfunction. it does not accept CDs and it is very buggy when you try to eject the disk, it fails on most tries to register.

see [[CD and DVD player repair]] for some info.

i found a fitting CD Laser Assembly on ebay which was advertised as new by a commercial seller and agreed with coloradio to try replacing the laser assembly of the malfunctioning player deck with the new one.

* https://www.ebay.de/itm/144404738337 - listing of the replacement part
* https://www.ebay.de/str/audiovideoexperte - sellers page, offers a lot of other laser-modules for many devices

the seller provided a great guide together with the laser assembly, because most of them seem to have a solder bridge for ESD protection of the laser diode.
replacing the laser assembly was a bit finnicky, but i managed it.

The ways of the new laser assembly had not much grease on them, so i decided to buy some silicone grease. The first seller shipped silicone oil which was unusable and not propperly packed and leaked, it was returned. I then bought a smaller tube of silicone grease from another seller. I ablied small amounts of grease with a toothpick to some ways on the laser assembly and some other parts, like the gears.

The new laser assembly worked fine when i tested it for a while (1h or a bit more). the people from coloradio also told me it's working great for them again.
* [[Sollte man Obdachlosen Geld geben?|https://www.youtube.com/watch?v=WtPPrhrsSgk]]
* Treberhilfe
i got 2 old DJ mixers and might be able to repair them. One would be great to get working for the Band Room of a local Kids and Youth Club.

!! Behringer DX500

* quite an old model it seems
* manual: http://www.behringer-vintage.com/Anleitungen/DX500_GER_V1.2_JUL2000.pdf
* power supply (transformer) missing: 2x 19V AC with gx12-3 connector
** but can be powered from 2x 19V DC as well
* fader cap missing
* two faders are noisy/drop out and might need cleaning or are damaged?
* the audio record function is pretty noisy, but thats not as big of a problem.

the mixer goes for ~20€ on ebay-kleinanzeigen. a cheap transformer/power supply would cost around 15€ + the gx12-3 connector and the missing fader cap. i decided it's not really worth repairing and more useful for salvaging components.

!! Behringer DJX700

* goes for about 60-70€ on ebay-kleinanzeigen

the channel 2 is not working correctly; the led bar graph shows the volume before the channel 2 volume fader accurately; it seems somewhere between the led graph and the master section both, the left and right signal get lost.

(service) manuals / schematics

* https://www.behringer.com/product.html?modelCode=P0165
* https://www.electronica-pt.com/esquema/audio/behringer-audio/behringer-djx700-rev-b-16042/
* https://www.electronica-pt.com/esquema/audio/behringer-audio/behringer-djx700-professional-mixer-dj-schematic-16024/
* https://www.hifiengine.com/manual_library/behringer/djx700.shtml

chips

* TL074C - 4 channel opamps
* jrc 4580 - dual opamps
* cd4051BM - single 8 channel analog multiplexer/demultiplexer
* CD4052BCM - dual 4 channel analog multiplexer/demultiplexer
* ...

with help of the schematics i was able to narrow down the problems with channel 2 to the fader, it controls the volume going to the main/master section.
because other faders were also noisy or had dropouts i decided to desolder and clean them.
pretty much all faders were a bit dirty. the master/main put fader worked fine again after cleaning. The fader of channel 1 still has some problems.
the fader for channel 2 had very corroded slide contacts, i tried to clean it, but it only got a bit better. only a bit of one of the stereo signals gets through, just enough to hear it.
so fader 2 needs a changeout and maybe changing other faders is also a good option...

the faders are alpha (taiwanese company) A100KX2 45mm fader

digikey didn't seem to have fader that look similar

https://www.mouser.de/c/passive-components/potentiometers-trimmers-rheostats/slide-potentiometers/?resistance=100%20kOhms&travel=45%20mm%7C~60%20mm

https://www.alphapotentiometers.net/Slide%20Pots/html/slide_pots.html

Behringer/Musictribe have a community page and a form were one can ask if spare parts are available: https://community.musictribe.com/pages/create-new-ticket?type=spareparts&brand=Behringer

i contacted behringer through their form, but they apparently can't sell the replacement parts directly due to supply chain issues. they have pointed me to their service partners (https://www.behringer.com/buy.html?type=POS).
but they atleast gave me the information that the part number is CT10-00159-000.

the first service center already responded and they don't have the part in storage and ordering it would take a long time. I'm hoping the other german service center has a more positive answer.

the other german service center has the parts in storage, but they want 38€ for two faders and shipping. thats not really worth it for a 60€ device.

https://de.aliexpress.com/item/4000178368210.html ~~these faders might fit?~~ they aren't expensive - they don't fit, the sellers on aliexpress meassure the complete length of the part and not the fader travel.

http://www.taiwanalpha.com/en/products/48 - RA45D2F-211, RA45D2LF-211, RA45Q2F-211

have found some faders that should match on aliexpress but they are quite expensive, i saved them in a list for now.

!! omnitronic PM-322 P

broken input selection switch and probably other problems, not really worth much time
* https://hackaday.com/2022/02/05/how-to-spot-a-fake-op-amp/
* see [[widely used/common or standard electronic parts and components ("jellybean")]]
* https://www.learnabout-electronics.org/Amplifiers/amplifiers60.php
* [[EEVblog #600 - OpAmps Tutorial - What is an Operational Amplifier?|https://www.youtube.com/watch?v=7FYHt5XviKc]]
* [[Electronic Basics #21: OpAmp (Operational Amplifier)|https://www.youtube.com/watch?v=kqCV-HGJc6A]]
*[[How Op Amps Work - The Learning Circuit|https://www.youtube.com/watch?v=kbVqTMy8HMg]]
* [[Explore Working Applications of 8 Different Op-Amp Circuits - DC To Daylight|https://www.youtube.com/watch?v=aR9ILhbG4AE]]
 * [[ EEVblog #479 - Opamp Input Bias Current |https://www.youtube.com/watch?v=TxBJb-Z0XFI]]
* [[ Op Amp Theory and Design - Phil's Lab #53 |https://www.youtube.com/watch?v=Jexhr5NIHog]]
* [[ Op-Amps - Using Operational Amplifiers |https://www.youtube.com/watch?v=_HHxV-7alwE]]
* [[ How To TEST OP AMPS Using A Multimeter vs Op-Amp Tester Project Single Dual |https://www.youtube.com/watch?v=cGRPBV-_ZQc]]
* [[OP Amp PCB Layout: Grounding & Bypass (Mixed signals, grounding and bypass capacitors)|https://www.youtube.com/watch?v=a-FjxztpxBo]]
* https://hackaday.com/2014/07/05/the-disintegrated-op-amp/
a kind of event calendar for the local community and it's open, diverse and colorful culture and society

example dresden: buntes dresden?

Ideas/Problems:

* event Aggregation from different platforms
** Websites (with different backends: static, wordpress, typo3, etc.)
** Social Media (facebook, twitter, instagram)
** directly creating an event on the platform?
* spreading the event
** to social media
* using Activity Pub?
* calendar

the Solution? ''Mobilizon from Framasoft!''

* https://framablog.org/2019/10/15/mobilizon-lifting-the-veil-on-the-beta-release/
* https://framablog.org/2019/12/18/federating-mobilizon-one-more-step-towards-de-facebooked-events/
* https://joinmobilizon.org/en/
* https://framagit.org/framasoft/mobilizon
Messenger

* [[Matrix|https://matrix.org/]]
** https://element.io/features
** https://fluffychat.im/de/
** https://matrix.org/bots/
** https://matrix.org/docs/guides/
* XMPP
* Briar
* Jami?
* Tox?
* https://www.freie-messenger.de/
* https://de.wikipedia.org/wiki/Liste_von_mobilen_Instant-Messengern
* https://www.orcas.de/whatsapp-facebook-skype-telegram-signal-threema-wire-viber-hangouts-icq-jabber-simsme-hoccer-yooyuu-discord-vergleich/
* https://www.kuketz-blog.de/die-verrueckte-welt-der-messenger-messenger-teil1/
* https://www.kuketz-blog.de/empfehlungsecke/#messenger
* https://www.messenger-matrix.de/
** https://www.messenger-matrix.de/messenger-matrix.html
* signal is meh
** https://www.spektrum.de/news/mythos-signal-licht-und-schatten-beim-nicht-kommerziellen-messenger/2190072

Voice/Video communication

* Mumble
* Jitsi
* ~BigBlueButton

stuff

* https://fm4.orf.at/stories/3000611/
* https://keybase.io/?
* https://opensource.com/article/19/8/open-audio-kit-developer
* [[Experimenting with electrically generated music?! -- DIY Guitar Effects board!|https://www.youtube.com/watch?v=K9HTMol7hds]]
* https://opensource.com/article/18/2/open-source-audio-visual-production-tools
* https://www.zdnet.com/article/so-long-sonos-meet-the-open-source-audio-system-that-will-never-die/
* https://opensource.com/article/19/6/hardware-music
* https://freedsp.github.io/ and see [[free/open/cheap DSP]]
* https://www.coreboot.org/
** https://de.wikipedia.org/wiki/Coreboot
** https://en.wikipedia.org/wiki/Coreboot
* https://libreboot.org/
** https://de.wikipedia.org/wiki/Libreboot
** https://en.wikipedia.org/wiki/Libreboot
* https://de.wikipedia.org/wiki/OpenBIOS
* [[bootloader (open source)]]
* https://en.wikipedia.org/wiki/Category:Free_BIOS_implementations
see also [[Open Knowledge / Open Science / Open Access]]

```
"Wie CCC-Urgesteine gegen Teams und Zoom kämpfen''

Ein Verein aus dem Umfeld des CCC zeigt in Berlin, wie sich Schulen mit Open Source digitalisieren lassen. Schüler, Eltern und Lehrer sind begeistert.

Während in der Bundesliga wieder der Ball rollt und Restaurants und Cafés geöffnet haben, ist der Schulbetrieb in Deutschland immer noch alles andere als normal. Umso wichtiger wäre es für Lehrer, Schüler und Eltern, den normalen Unterricht mit Hilfe von digitalen Werkzeugen vorübergehend ersetzen zu können. Wie das funktionieren kann, ohne die Angebote der großen Digitalkonzerne nutzen zu müssen, zeigt eine Kooperation zwischen dem Verein Cyber4Edu und einer Grundschule in Berlin. Mit der Open-Source-Plattform Big Blue Button und eigenen Servern hat sich der Fernunterricht deutlich verbessert.

Es ist ein bisschen wie bei Asterix und Obelix: 
Während die ganze Welt in der Coronakrise die Videokonferenzsysteme von Microsoft (Teams/Skype), Cisco (Webex) oder Zoom verwendet, versucht ein kleiner Verein in Berlin, sich dem Trend entgegenzustellen. Auf dem Chaos Communication Congress Ende 2019 in Leipzig (36C3) stellte CCC-Mitglied Michael Merz in einer Session die Ziele seiner Initiative erstmals vor: nachhaltig gute Software, Lernmaterialien und Hardware für Schulen. Die Coronakrise und die damit verbundenen Schulschließungen ließen den Bedarf an solchen Lösungen plötzlich stark ansteigen.

Nachhaltig gute Software, Lernmaterialien und Hardware für Schulen:
https://events.ccc.de/congress/2019/wiki/index.php/Session:Cyber4EDU

Weiter auf:
https://www.golem.de/news/big-blue-button-wie-ccc-urgesteine-gegen-teams-und-zoom-kaempfen-2005-148560.html

#CCC #Cyber4EDU #OpenSource #Teams #Zoom
������@cRyPtHoN_INFOSEC_DE
```

* https://www.open.ac.uk/
* https://www.open.edu/openlearn/
* https://ec.europa.eu/jrc/sites/jrcsh/files/20170328_openeduframework_centred_video_support.pdf
* https://ocw.mit.edu/index.htm
* https://openlearning.mit.edu/
* https://oyc.yale.edu/
* https://en.wikipedia.org/wiki/OpenCourseWare
* https://www.youtube.com/c/OUlearn
* https://www.hoou.de/
* https://khanacademy.org/
** https://de.wikipedia.org/wiki/Khan_Academy
* https://www.edx.org/
* https://archive.org/projects/
* https://www.open.edu/openlearn/
* https://libretexts.org/
** https://eng.libretexts.org/

open source education software

* https://apps.kde.org/education

stuff

* https://bigbluebutton.org/
* https://moodle.com/
* https://netzpolitik.org/2020/ganz-nach-bedarf/ (german)
* https://lerntools.org/app/#/main-index

IT infrastructure for schools (and maybe public authorities):

* in germany the used hardware is often overpriced... a raspberrypi mounted to the back of a monitor would do the trick in many authorities, primary/elementary schools, maybe even in grammar schools
* munich wants to use more open source (again)
* OS: linux 
** https://news.softpedia.com/news/zorin-os-makes-it-easy-to-deploy-linux-powered-computers-in-schools-businesses-528887.shtml
** https://www.linuxmuster.net/
* there are great ~ActiveDirectory alternatives for linux like ~OpenLDAP, Samba, Apache Directory, Univention Corporate Server
** https://softwarerecs.stackexchange.com/questions/7388/more-reliable-alternative-to-samba-on-linux-speed-is-most-important
** https://www.topbestalternatives.com/samba/
** https://www.linuxquestions.org/questions/linux-newbie-8/samba-alternatives-697025/
** https://alternativeto.net/software/samba/?license=opensource
* https://schoolitexpert.com/network-tools/fog/306-install-fog-server
** https://fogproject.org/
** [[custom linux iso's / images]]
* https://en.wikipedia.org/wiki/Open-source_hardware
** https://en.wikipedia.org/wiki/Open-source_hardware#Find_open-source_hardware_products
* https://de.wikipedia.org/wiki/Open-Source-Hardware
* see also [[Open Hardware Licences]]
* https://en.wikipedia.org/wiki/List_of_open-source_hardware_projects
* https://en.wikipedia.org/wiki/Category:Open-source_hardware
* https://de.wikipedia.org/wiki/Open_Hardware_Repository
* https://en.oho.wiki/wiki/Home
* https://wiki.opensourceecology.de/Open_Source_Ecology_Germany
* https://www.opensourceecology.org/
* https://www.youtube.com/c/OpenTechLab
* https://din.one/display/OSH/OSH+Academy
* https://gitlab.com/osh-academy/osh-basics
* https://hardware.forum-open.de/

Standards for open hardware

* https://blog.wikimedia.de/2020/10/01/opennext-erster-din-standard-fuer-offene-hardware/
* DIN SPEC 3105
** https://din.one/pages/viewpage.action?pageId=36603167
*** https://din.one/pages/viewpage.action?pageId=36603169
*** https://din.one/pages/viewpage.action?pageId=36603181
* https://gitlab.com/OSEGermany/OHS/

stuff:

* https://www.scopefun.com/ - Oscilloscope, Arbitrary Waveform Generator, Spectrum Analyzer, Logic Analyzer, Digital Pattern Generator
* https://en.wikipedia.org/wiki/Open_Compute_Project
* https://en.wikipedia.org/wiki/List_of_open-source_computing_hardware
* https://www.opensourceimaging.org/
* https://mntre.com/media/reform_md/2020-05-12-mnt-reform-german-press-release.html
* https://www.pine64.org/
* https://www.eevblog.com/forum/oshw/
* https://openhardware.science/
* https://opentoolchain.org/
* http://en.qi-hardware.com/wiki/Laoban_Soundsystem information is pretty useless because docs are severely lacking
** https://makezine.com/article/maker-news/open-source-plans-for-large-scale-s/
** https://openclipart.org/detail/25782/laoban-loudspeaker
* [[Sonnensystem]]
* https://www.creative-technologies.de/projects/mimabox/
* https://bicycles.stackexchange.com/questions/2881/are-there-open-source-bikes
* http://en.openbike.org/wiki/Main_Page
* http://www.jetrike.com/
* https://www.treehugger.com/build-your-own-bamboo-bike-diy-kit-4854952
* https://www.roden.com.ar/
* https://wikifactory.com/@sentidosdi/duetta-bicycle-to-share
* https://en.oho.wiki/wiki/Category:Bicycles
* https://www.werkstatt-lastenrad.de/index.php?title=Hauptseite
* https://de.wikipedia.org/wiki/Kategorie:Fahrradtyp

thoughts

* it might be not cheap enough to build your own bike, except special designs appart from the normal bike
* but you can easily extend the functionality
* https://framagit.org/FrViPofm/Bike3D

cargobike

* https://www.treehugger.com/buid-your-own-open-source-cargo-bike-or-buy-it-xyz-cycle-4857433
* informations (DE): https://www.cargobike.jetzt/
* https://grabcad.com/library/open-source-cargo-bike-1
* http://www.xyzcargo.com/
** https://www.open-electronics.org/xyz-cargo-is-a-modular-bike-based-on-open-source-framework-n55/
** https://projects.opennext.eu/@xyz-cargo-add-ons/xyz-cargo-add-ons
** the framework, one bike (maybe?) and some addons are open source, but not much else
** https://www.werkstatt-lastenrad.de/index.php?title=XYZ-Spaceframe-Vehicles
* https://www.treehugger.com/bike-cargo-chapter-extended-frame-bikes-4855336
* https://www.roden.com.ar/
* https://en.oho.wiki/wiki/Tricycle_cargo_bike
* https://en.oho.wiki/wiki/Long_Andre_cargo_bike
* https://de.wikipedia.org/wiki/Long_John
* https://openstructures.net/apps/a196 - non-commercial licence, so not open

bike trailer

* https://www.treehugger.com/bicycle-cargo-chapter-bike-trailers-4858166
* https://www.roden.com.ar/
* https://konglomerat.org/projekte/velozack.html

ebike

* https://hackaday.com/2020/02/23/an-open-source-ebike/
* https://github.com/OpenSource-EBike-firmware
* https://electricbikeblog.com/open-source-ebike-project/
* https://www.eco-ebike.com/collections/tsdz2-open-source-firmware-osf-products

bike computers and other tools:

* https://hackaday.io/project/1887-open-bicycle-computer
* https://hackaday.io/project/165685-aurora-bike-compass
* https://www.treehugger.com/bicycle-cargo-chapter-racks-and-bags-4857512

bike sharing

* https://opensourcebikeshare.com/what
* https://media.ccc.de/v/36c3-10881-verkehrswende_selber_hacken
* https://hackaday.com/2023/01/06/developing-an-open-source-bike-computer/
* https://apertus.org/
* https://www.openmotors.co/
** https://www.openmotors.co/renaultpomsignup/ - renault twizy base
** https://elinux.org/OSVehicle
** https://en.wikipedia.org/wiki/OSVehicle_Tabby
** https://en.wikipedia.org/wiki/Category:Open_hardware_vehicles
* https://en.wikipedia.org/wiki/Open-source_car
* https://en.wikipedia.org/wiki/OScar
** https://www.heise.de/hintergrund/Das-offenste-aller-Autos-278081.html
** https://www.itmagazine.ch/artikel/16783/Auf_dem_Weg_zum_Open-Source-Auto.html
* https://en.wikipedia.org/wiki/Category:Open_hardware_vehicles
* https://evnerds.com/ev-album/your-e-motorcycle/open-hardware-e-moto/ - motorbike
* http://techgenix.com/software-hardware-self-driving-cars/
* http://openxcplatform.com/
* https://openwb.de/main/ - open source wallbox/charger
* https://en.wikipedia.org/wiki/OpenEVSE

general information:

* https://www.youtube.com/user/mikeselectricstuff/videos
* [[#113 - E-Auto Ladetechnik - Steckertypen, Wallbox, CEE-Laden, Lademodi, Fakten - Alles Wichtige|https://www.youtube.com/watch?v=T3WUfSBW-kE]]
* [[EEVblog 1437 - Zappi 7kW Electric Car Charger TEARDOWN + EXPERIMENT|https://www.youtube.com/watch?v=DwuZJHk5JV8]]

* https://de.wikipedia.org/wiki/Ladestation_(Elektrofahrzeug)#Lades%C3%A4ulen
* https://de.wikipedia.org/wiki/IEC_62196_Typ_2
* https://en.wikipedia.org/wiki/IEC_61851
* https://de.wikipedia.org/wiki/Combined_Charging_System
* es gibt typ 2 zu schuko oder typ 2 zu CEE adapter zu kaufen
* https://hackaday.com/2023/09/18/fast-charging-a-cargo-bike-from-an-electric-car-charger/
my plans / ideas

* modular designs
* drawer rack for Kistenberg NORS16
* drawer rack for Euro crates
** with screw in-nuts so it could be reconfigured for different crate heights?
** https://www.auer-packaging.com/de/de/Eurobeh%C3%A4lter-geschlossen/EG-4312-HG.html
*** https://www.auer-packaging.com/pdf/drawings/eg_4312_tech.pdf
* modular shelf system
** my ceiling height is 256cm
** the minimum ceiling height for some rooms in germany is 2,20m for rooms classified as rooms for living the minimum height ranges from 2,30m to 2,50m.
** with my existing shelves 625mm width is enough for 2 crates 30cm wide

other projects:

* Opendesk (opendesk.cc) is not open anymore (non-commercial is not open source/hardware!)
** https://en.wikipedia.org/wiki/Opendesk
** https://github.com/timrolls/Opendesk
** https://3dwarehouse.sketchup.com/by/opendesk
** https://github.com/opendesk/design-playground
** https://github.com/abetusk/dev/tree/release/projects/maslowcnc/opendesk
* https://en.wikipedia.org/wiki/OpenStructures - a lot of it is non-commercial, so not open
** https://openstructures.net/objects
** design is very industrial, but not often very practical; but good for inspiration and ideas

stuff

* https://hackaday.com/2022/11/04/adjusting-shelves-like-its-1899/ - great old craft
* https://hackaday.com/tag/shelf/
* https://hackaday.com/tag/shelving/
* https://hackaday.com/tag/furniture/
* https://www.openfunk.co/pages/re-mix
* https://en.wikipedia.org/wiki/Open_Hardware_License
* https://en.wikipedia.org/wiki/TAPR_Open_Hardware_License
* https://de.wikipedia.org/wiki/CERN_Open_Hardware_Licence
** https://en.wikipedia.org/wiki/CERN_Open_Hardware_Licence
** https://ohwr.org/project/cernohl
* http://www.inmojo.com/licenses/
* https://opensource.com/law/15/2/intro-open-hardware-licensing
* see [[problems with non-commercial licences]]
* see [[Licences and Licencing]]
* https://software.development.fabcity.hamburg/osh-license-discussion/ - comparison of the CERN OH Licences
* https://certification.oshwa.org/
* [[Legal Aspects of Open Source Hardware|https://youtu.be/s7bcnAN6Lz0]]
* https://de.wikipedia.org/wiki/Regal_(M%C3%B6belst%C3%BCck)
** https://de.wikipedia.org/wiki/Kategorie:Lagertechnik
* https://www.diydata.com/carpentry/shelving/shelf-materials.php
* https://en.wikipedia.org/wiki/Shelf_(storage)
** https://www.doityourself.com/stry/h2buildshelves
* using [[Wood (Holz)]]
* [[Finite Element Method / Finite Element Analysis]]


standard dimensions of boards?

* https://puuinfo.fi/puutieto/schnittholz/standardmasse-staerken-breiten-laengen/?lang=de


hornbach,~~ toom~~, obi, globus
* https://okfn.org/ - ~OpenKnowledge Foundation
* https://www.unesco.org/en/open-science/toolkit

see also [[Open education, open learning, open university]]

* https://scholar.google.de/ - can be used to get an overview of scientific publications
* https://www.doi.org/ - the DOI found on google schoolar can also be searched on other sites:
* https://scihub.wikicn.top/
* https://sci-hub.se/
** https://de.wikipedia.org/wiki/Sci-Hub
** https://en.wikipedia.org/wiki/Sci-Hub
* http://libgen.rs/ - more books
* ~~https://www.researchgate.net/~~
* https://en.wikipedia.org/wiki/Category:Scholarly_communication
* https://en.wikipedia.org/wiki/Category:Science_websites
* https://de.wikipedia.org/wiki/Kategorie:Wissenschaftskommunikation
* https://blogs.ub.tu-berlin.de/publizieren/2016/08/artikel-bei-researchgate-und-co-hochladen-welcher-verlag-erlaubt-was-und-wie-open-access-ist-das-eigentlich/
* https://osc.universityofcalifornia.edu/2015/12/a-social-networking-site-is-not-an-open-access-repository/
* https://arxiv.org
**  https://de.wikipedia.org/wiki/ArXiv
** https://en.wikipedia.org/wiki/ArXiv
* https://en.wikipedia.org/wiki/Category:Open_science
* https://en.wikipedia.org/wiki/Category:Open-access_archives
* https://en.wikipedia.org/wiki/Category:Eprint_archives
* https://en.wikipedia.org/wiki/List_of_academic_publishers_by_preprint_policy
* https://en.wikipedia.org/wiki/List_of_academic_databases_and_search_engines
* https://en.wikipedia.org/wiki/Open-access_repository
* https://de.wikipedia.org/wiki/Kategorie:Open_Access
* https://en.wikipedia.org/wiki/List_of_preprint_repositories
* https://de.wikipedia.org/wiki/Kategorie:Dokumentenserver
* https://de.wikipedia.org/wiki/Offene_Wissenschaft
* https://de.wikipedia.org/wiki/Fachdatenbank
* https://de.wikipedia.org/wiki/ViXra
* https://arxiv.org/
* https://blogs.ub.tu-berlin.de/publizieren/2016/08/artikel-bei-researchgate-und-co-hochladen-welcher-verlag-erlaubt-was-und-wie-open-access-ist-das-eigentlich/
* https://de.wikipedia.org/wiki/Researchgate
* https://github.com/micahwalterstudio/awesome-openaccess

* https://wiki.opensourceecology.de/OpenScience

* https://www.semanticscholar.org/
specialized:

* [[Open Sound Lab]]

parts:

* [[open hardware furniture]]
* [[cheap multi-device lab measurement/test devices/equipment]]
* [[open lab instrumentation, meassuring / testing equipment]]
* [[tools]]

stuff

* https://en.wikipedia.org/wiki/Open-Source_Lab_(book)
** https://www.appropedia.org/Open-source_Lab
** https://www.instructables.com/contest/buildmylab/?show=PRIZES
my idea is do build modules based on the eurocard standard, similar to eurorack modules, ("Systemgehäuse") which can be freely aranged and combined and can be mounted in different types of tabletop housings or racks.

* each module has a specific purpose
* modules communicate via a bus
* everything is open source and open hardware
* there are modules for controlling other modules, displaying data or for connecting to a PC or other devices
* a module could provide a description on the type of data
* simple display-modules could just provide the option to diplay the data in real-time, but other display-modules with more options could display graphs bases on the data type definitions of other modules
* interfacing with a computer can easily be used for datalogging and piping the data in other applications, e.g. for heavier real-time analysis

lab software (open source)

* http://xoscope.sourceforge.net/
* https://sigrok.org/
* https://myopenlab.org/inicio/ - dead it seems
** https://sourceforge.net/projects/myopenlab3/
* https://github.com/MyLibreLab/MyLibreLab - fork of ~MyOpenLab
* https://www.theremino.com/
* https://alternativeto.net/software/labview/ - ~LabView is a kind-of standard but proprietary
** https://de.wikipedia.org/wiki/LabVIEW
** https://en.wikipedia.org/wiki/LabVIEW
* see also [[scientific software]]


Tools:

open hardware (and software)

* https://www.eevblog.com/forum/oshw/open-source-oscilloscope/
* https://www.lab-nation.com/ - design files not accessible anymore?
* https://github.com/drandyhaas/Haasoscope
* https://hackaday.com/2020/05/07/open-source-2-ghz-oscilloscope-probe/
* https://osciprime.com/index.php?p=project
* https://hackaday.io/project/165964-60mhz-bandwidth-250msps-probe-scope
* https://baylibre.com/acme/
* https://physicsopenlab.org/
* https://www.theremino.com/
* https://physicsopenlab.org/low-cost-diy-scientific-equipment/
* https://pslab.io/ - Pocket Science Lab, includes 4-Ch Osci, Voltmeter, I²C for sensors
* https://open-ephys.org/showcase-overview

only open software

* https://www.redpitaya.com/ - Osci, signal generator, logic analyzer, LCR Meter
* https://openhantek.org/ - Software for Hantek and compatible (Voltcraft/Darkwire/Protek/Acetech) USB digital signal oscilloscopes
* https://github.com/ardyesp/DLO-138
* digilent ~OpenScope MZ /~OpenLogger - discontinued
** https://reference.digilentinc.com/reference/instrumentation/openscope-mz/start


open?

* miniware - http://www.miniware.com.cn/products/
** Digital tweezers
** mini oscilloscopes
** logic analyzers
* https://www.earthpeopletechnology.com/digital_storage_oscilloscope_dso_100m
** https://www.tindie.com/products/Earth_People_Technology/open-source-digital-storage-oscilloscope-4-ch/

stuff

* https://hackaday.com/tag/laboratory/
* https://hackaday.com/tag/lab/
* https://hackaday.com/tag/laboratory-equipment/
* https://en.wikipedia.org/wiki/Open_Sound_Control
** https://de.wikipedia.org/wiki/Open_Sound_Control
* see also [[Midi]]
* https://github.com/fabb/SynOSCopy/wiki
* http://opensoundcontrol.org/
** https://www.cnmat.berkeley.edu/OpenSoundControl
* https://www.linuxjournal.com/content/introduction-osc
* https://behringerwiki.musictribe.com/index.php?title=OSC_Remote_Protocol
* ''https://github.com/amir-arad/awesome-osc''
* https://opensoundcontrol.stanford.edu/index.html

devices i use which support it: [[Behringer XAir (XR12/XR18)]]

python:

* https://python-osc.readthedocs.io/en/latest/
** https://github.com/attwad/python-osc
** https://pypi.org/project/python-osc/
* https://github.com/peterdikant/xair-remote

other

* https://github.com/automata/osc-web
* https://github.com/colinbdclark/osc.js/

extension: OSCQuery

* https://github.com/Vidvox/OSCQueryProposal
* https://vdmx.vidvox.net/blog/oscquery
** https://docs.vidvox.net/vdmx_oscquery.html ?
* https://github.com/benkuper/Unity-OSCQuery
* https://forum.openframeworks.cc/t/ofxoscquery-addon/30341
https://github.com/Thorbijoern/OpenSoundLab

collecting information there

stuff to meassure speakers and similar

overview:

* https://en.wikipedia.org/wiki/Audio_system_measurements
* [[Anechoic Chamber - DIY Sound Absorption Panels|https://www.youtube.com/watch?v=fqodnHxRJ7c]]

stuff:

* impedance meassurement
** https://de.wikihow.com/Die-Impedanz-von-Lautsprechern-messen
** http://www.hifi-forum.de/viewthread-43-76.html
** https://www.likehifi.de/doityourself/die-impedanz-und-ihre-bedeutung-im-hi-fi-bereich/
** http://www.audio-software.de/lautsprecher_impedanzmessung.html
** https://www.wikihow.com/Measure-Speaker-Impedance
** https://www.quora.com/How-do-you-measure-the-impedance-of-a-speaker?share=1
** https://www.lifewire.com/speaker-impedance-3134705
** https://wiki.analog.com/university/courses/electronics/electronics-lab-speaker
** https://www.stereofactor.com/speaker-impedance-calculator/
** https://www.stereophile.com/content/measuring-loudspeakers-part-one-page-6
* SPL meassurement (frequengang, frequenzy response)
** https://praxistipps.chip.de/frequenzgang-messen-so-gehts_47590
* THD
* Output Power
* https://www.stereophile.com/content/measuring-loudspeakers-part-one-page-6

other labs

* https://soundlab.cs.princeton.edu/
evaluation (wip) on how easy it is to build a whole professional sound system as open source/hardware as possible currently

software will be easiest to make completely open, hardware has to rely on proprietary chips and parts

power supply

* working with mains power is dangerous
* linear power supplies are pretty easy and easily scaleable
* smps are more complex and not as easy, smaller smps designs can be easily found, but it is hard when higher power is required
* using existing, commercial powersupplies
* powering from battery might be viable

amplifiers

* dedicated amplifier ASICs simplify development, but are more proprietary and limited in power
* developping discrete amplifier circuits is harder but more open and scalable

dsp

* [[free/open/cheap DSP]]
* programming can probably be done completely open source
* some risc-v chips might even include open dsp functionality?

speakers

* there are some popular designs that get shared and DIY'ed, more or less open, often are pretty poorly documented in fomr of threads in some forum
* there is a lack of good quality guides and information on designing speakers from the ground up
* there is a lack of open source software to design speakers

controll/communication

* some standards, more or less open
* planetarium and visualisation software
** stellarium
** https://celestia.space/
** https://edu.kde.org/kstars/
** https://www.openspaceproject.com/
* device controll
** https://www.ascom-standards.org/
*** [[https://en.wikipedia.org/wiki/ASCOM_(standard)]]
** https://www.indilib.org/
* https://pikonic.com/
** https://wikifactory.com/+elektrictube/pikon-telescope
* "lucky imaging", image stacking and postprocessing software
** https://www.autostakkert.com/wp/download/ - only freeware
** https://github.com/fedhere/luckyMe
** https://github.com/GreatAttractor/stackistry
** http://deepskystacker.free.fr/german/index.html - only freeware
*** https://foto-download.heise.de/df1905/html/p31672.htm
** https://free-astro.org/index.php?title=Siril
* guides
** https://www.astropix.com/html/i_astrop/Planetary_Imaging.html
** https://eyeofthetelescope.com/opensource-astrophotography/
** https://fixthephoto.com/best-astrophotography-software.html
** https://www.ossblog.org/open-source-astronomy-software/
** https://fedoramagazine.org/astrophotography-with-fedora-astronomy-lab-setting-up/
* https://fits.gsfc.nasa.gov/
** https://en.wikipedia.org/wiki/FITS
* https://openastrotech.com/
* radio telescopes
** https://blog.adafruit.com/2019/01/22/open-source-radio-telescopes-opensource-astronomy/
** https://www.opensourceradiotelescopes.org/
* https://free-astro.org/index.php?title=Main_Page
* https://awesomeopensource.com/projects/astronomy
* https://www.astropy.org/
* https://hackaday.com/2021/03/12/diy-telescope-courtesy-of-ikea/

stuff

* [[The Man Who Hunts Spy Satellites|https://www.youtube.com/watch?v=1Vm7N5D5sg0]]
* https://james.darpinian.com/satellites/
Lists:

* https://opensource.com/article/18/2/open-source-audio-visual-production-tools
* http://djemberecords.com/software.html
* https://midination.com/free-music-production-software/
* https://opensource.com/life/16/2/5-music-making-tools
* https://de.wikipedia.org/wiki/Kategorie:Freie_Musiksoftware
* https://de.wikipedia.org/wiki/Kategorie:Freie_Audiosoftware
* https://en.wikipedia.org/wiki/Category:Audio_programming_languages
* https://en.wikipedia.org/wiki/Category:Free_audio_software
* https://en.wikipedia.org/wiki/Category:Free_music_software
* https://jackaudio.org/applications/
* https://en.wikipedia.org/wiki/Comparison_of_free_software_for_audio
* https://wiki.audacityteam.org/wiki/Other_Open_Source_Audio_and_Audio-Visual_Applications
* https://wiki.debian.org/Multimedia
** https://wiki.debian.org/Sound?action=show&redirect=CategorySound
* https://wiki.archlinux.org/index.php/Category:Multimedia
** https://wiki.archlinux.org/index.php/Category:Audio
* https://linuxaudio.org/resources.html
* https://wiki.linuxaudio.org/wiki/plug-ins


Software:

* JACK - https://jackaudio.org/
** https://en.wikipedia.org/wiki/JACK_Audio_Connection_Kit
* ~PulseAudio
* ~PipeWire
** https://hackaday.com/2021/06/23/pipewire-the-newest-audio-kid-on-the-linux-block/
* Audacity - Recording, others https://www.audacityteam.org/
** https://www.audacityteam.org/download/plug-ins/
* Hydrogen - drum sequencer - https://hydrogen-music.org/
* Ardour - DAW - https://ardour.org/
** https://www.linuxfromscratch.org/hints/downloads/files/ardour.txt
* LMMS - DAW - https://lmms.io/
* Mixxx - DJ mixer - https://www.mixxx.org/
* VCV Rack - Eurorack Simulator - https://vcvrack.com/
* Giada - DJ DAW? - https://www.giadamusic.com/
* Surge - Synthesizer - https://surge-synthesizer.github.io/
* Orca - esoteric programming lang. - https://100r.co/site/orca.html
* ~SuperCollider - ? - https://supercollider.github.io/
* Marabu - Tracker - https://github.com/hundredrabbits/Marabu - https://hundredrabbits.itch.io/marabu
* Soundbox - tracker - https://github.com/mbitsnbites/soundbox
* Pilot - Synth - https://hundredrabbits.itch.io/pilot
* QTractor - https://qtractor.sourceforge.io/
** https://opensource.com/article/17/6/qtractor-audio
** https://en.wikipedia.org/wiki/Qtractor
* https://tytel.org/helm/
* https://www.gnu.org/software/cursynth/
* https://rosegardenmusic.com/
** https://en.wikipedia.org/wiki/Rosegarden
* [[LADSPA, LV2 - Open Source VST alternative]]
* https://github.com/sonic-pi-net/sonic-pi
* https://soundlab.cs.princeton.edu/software/
** http://marsyas.info/
*** https://github.com/marsyas/marsyas
** https://sndtools.cs.princeton.edu/
** https://taps.cs.princeton.edu/
* https://lsp-plug.in/

Open source operating systems with audio (/multimedia) tools preinstalled: 

* https://distrowatch.com/search.php?&category=Multimedia
* https://www.heise.de/news/Kurz-ausprobiert-die-Distribution-AV-Linux-2021-05-fuer-Multimedia-Enthusiasten-6061335.html
* https://ubuntustudio.org/
* https://labs.fedoraproject.org/de/jam/

Other

* https://opensource.com/article/17/8/linux-guitar-amp
* https://opensource.com/tags/audio-and-music
* https://opensource.com/tags/multimedia-makers
* might help with linux audio problems: https://www.ubuntugeek.com/latencytop-measuring-and-fixing-linux-latency.html
goal is to potentially reverse engineer (hardware and firmware) of different cheap battery monitors and reverse engineer the communication interfaces and data from some smart BMS and some inverters to develop a universal battery monitor platform.
see [[OSC Android App]], [[Behringer XAir (XR12/XR18)]] and [[Open Sound Control (OSC) (protocol)]]

* https://codeblog.jonskeet.uk/2021/01/27/osc-mixer-control-in-c/
* https://codeblog.jonskeet.uk/2022/10/16/introduction-to-digimixer/
robots inspired by nature

opencat

* https://www.hackster.io/petoi/opencat-845129
* https://github.com/PetoiCamp/OpenCat

opendog

* https://www.youtube.com/watch?v=ten2T1Pq_z8

MIT cheetah and mini cheetah

* https://biomimetics.mit.edu/
* https://robots.ieee.org/robots/minicheetah/
* https://news.mit.edu/2019/mit-mini-cheetah-first-four-legged-robot-to-backflip-0304
* chinese manufacturers sell the motors relatively cheap
* https://www.youtube.com/watch?v=ecSQZlNda6g
* https://www.youtube.com/watch?v=Mhxz2Bj2RXA
* [[Backflipping MIT Mini Cheetah|https://www.youtube.com/watch?v=Mhxz2Bj2RXA]]
* [[Testing 9 New Mini Cheetahs|https://www.youtube.com/watch?v=G6fMV1UPzkg]]

SpotMicro

* https://spotmicroai.readthedocs.io/en/latest/
* https://www.thingiverse.com/thing:3445283
* https://github.com/mike4192/spotMicro
* https://www.personalrobots.biz/spotmicro-is-an-open-source-robotic-dog/
* FreeCAD - pretty much the open source standard
* https://www.sculpteo.com/blog/2018/03/21/top-13-of-the-best-open-source-cad-software/
* https://openjscad.org/
** https://github.com/jscad/OpenJSCAD.org
* https://solvespace.com/index.pl
* https://www.salome-platform.org/
* see also [[Simulators]]
* https://opensource.com/alternatives/autocad
* https://dev.opencascade.org/ - just a lib
** https://github.com/tpaviot/oce
** also the core of freecad 
** https://wiki.freecadweb.org/OpenCASCADE
* https://github.com/zalo/CascadeStudio - https://zalo.github.io/CascadeStudio/
* using blender for CAD
** [[#rC3​ Blender-Construction|https://www.youtube.com/watch?v=7krUF5GGclI]]
** https://wiki.opensourceecology.de/Blender_CAD_Addons
* [[https://en.wikipedia.org/wiki/Novena_(computing_platform)]]
* many [[single board computer (SBC)]] are
* http://projects.haskell.org/diagrams/
* Dia - https://gitlab.gnome.org/GNOME/dia
* diagrams.net
* ~PlantUML
* https://kroki.io/
DSP (as open as possible) with enough in/outputs and an interface for a microcontroller/raspberry pi or so.
raspberrypi with wifi, bluetooth (and LAN?), app

see [[free/open/cheap DSP]]

freedsp aurora?


like Soundcraft Ui1X or Behringer X Air XR1X

* big DSPs with network interfaces for controlling
* most are controlled using proprietary and closed-source apps
* the used protocols would be interesting
* if there are apps from different manufacturers and they can be used interchangeably, there might be a good change for atleast open and standardized protocols
* some even have webinterfaces
* could maybe be controlled using midi? (simple but powerful, often used in the audio professions)
* midi over network (over IP/TCP?) could be a thing?
* raspi zero w or raspi with ethernet (or similar SBC), small webserver, big DSP
* no real realtime audio streaming to the DSP
* Behringer XAir maybe has some Xilica chip
** xilica x-touch is an app very similar to the beringer app, even gets listed in the play store results

stuff:

* https://www.diyaudio.com/forums/digital-line-level/286543-diy-digital-mixer.html
* [[Take Apart Behringer X32 & Midas M32 (Public)|https://www.youtube.com/watch?v=Oms2ypKaSPo]]
* [[Behringer XAir (XR12/XR18)]]
* GIMP
** https://github.com/Diolinux/PhotoGIMP - making gimp a bit more like photoshop
* Krita - https://krita.org/
* https://osgameclones.com/
* https://supertuxkart.net/Main_Page
* https://reprap.org/wiki/InkJet
* https://www.appropedia.org/Open_source_Inkjet_printers
* DNA printer? https://www.ncbi.nlm.nih.gov/pmc/articles/PMC507883/
* https://makezine.com/2011/06/01/diy-open-source-inkjet-printer/
* https://ytec3d.com/hp45-inkjet-printhead/
* https://www.eevblog.com/forum/chat/end-the-monopoly-we-need-open-source-inkjet-printers/
* https://hackaday.io/page/6176-why-is-there-no-open-source-firmware-for-laser-or-inkjet-printers
* https://homofaciens.de/technics-machines-cnc-v3-1_en.htm
* https://reprap.org/forum/read.php?153,52959
* https://www.reprap.org/wiki/Scratchbuilt_Piezo_Printhead
* https://hackaday.io/project/167446-diy-inkjet-printer
* https://www.thingiverse.com/thing:8542
* https://www.kickstarter.com/projects/nicholasclewis/inkshield-an-open-source-inkjet-shield-for-arduino
* https://computer.howstuffworks.com/inkjet-printer.htm
* https://www.youtube.com/watch?v=AHX6tHdQGiQ

thoughts

* it might be cheaper to buy a black and white laser printer, buy cheap toner cartridges or how to get rid of the excess of toner powder when refilling or such stuff... but thats not really the point here
* printheads are really hard to manufacture and pretty much not viable for open source purposes, so refillable inkjet cartridges with included printheads seem to be the best option for open source printers...
* maybe it is also possible to write own firmware for printers
* https://www.epson.de/for-home/ecotank maybe good?
* https://www.newegg.com/p/0WX-0006-00042
* ~TinEye - reverse image search
* google reverse image search
* https://de.wikipedia.org/wiki/Open_Source_Intelligence
* https://en.wikipedia.org/wiki/Open-source_intelligence
* [[telegram scraping for good (osint)]]
* https://sector035.nl/articles
a DJ-Controller is a device that mimics turntables, it's basically just a input and controll device for humans, all of the work is done on PC.

it's basically just a bunch of encoders with optical feedback (LEDs).

see [[universal Midi/OSC/DAW controller]]

the controller interfaces with the pc via:

* USB HID - is a clusterfuck
* Midi (over USB) - is pretty nice i think, very universal

and most controllers also inlcude an audio interface out of convenience, so the user doesn't need a separate one, but that is optional.

it would be nice to build an open source design which is modular, so you can mix and match a dj-mixer, several turntables and a launchpad for example.

examples (commercial, proprietary)

* palette controller / https://monogramcc.com/ - very modular
* 

ideas:

* there are several microcontrollers (arduino, esp) which can be USB input devices, and also Midi devices/controllers over usb
** see [[Midi]]
* need to find the right encoders for the job
** encoders for the jogwheels
** encoders for the other knobs
** https://de.wikipedia.org/wiki/Inkrementalgeber
** https://lastminuteengineers.com/rotary-encoder-arduino-tutorial/
** https://www.mikrocontroller.net/articles/Drehgeber
** ''[[bldc motor (as) encoder]] !!!''
* feedback is pretty easy with LED rings arround the encoders (adafruit neo-pixel style)
* need to find a nice, open interface through which the single devices can be connected (maybe chaining midi?)
* has to be compatible and supported by open source mixing software like https://www.mixxx.org/
* https://www.denondj.com/sc5000m%20prime-sc5000mprimexus - might also use BLDC motors for feedback and encoders

reverse engineering and modifying existing (outdated) controllers

* https://djtechtools.com/2020/02/09/kontrol-s1-djdoubleyou-sawed-a-deck-off-a-kontrol-s4-to-make-a-new-diy-controller/
* https://willwillems.com/projects/s1.html
* https://github.com/NickolasBoyer/KontrolS1
* https://s1.willwillems.com/
* https://forum.djtechtools.com/showthread.php?t=96697

* https://clementine-player.org/
* https://amarok.kde.org/
* https://www.videolan.org/
Suites

* https://calligra.org/ - Calligra Suite by the KDE community
* Libre Office - more modern fork of Open Office
* Apache Open Office
* OnlyOffice
* Collabora Office

Tools

* https://languagetool.org/
* [[The Index Pick and Place Can Build Itself|https://www.youtube.com/watch?v=DrwvorYolqU]]
** https://github.com/index-machines/index
* https://openpnp.org/
** https://github.com/openpnp/openpnp
** [[Pick and Place Machine Openpnp tray feeders|https://www.youtube.com/watch?v=xqJdxL_PCIQ]]
* [[Stephen Hawes: Pick and Place|https://www.youtube.com/playlist?list=PLIeJXmcg1baLBz3x0nCDqkYpKs2IWGHk4]]
** https://github.com/opulo-inc/lumenpnp
* https://www.pfsense.org/
* https://vyos.io/
* https://opnsense.org/
* https://alternativeto.net/software/vyos/?license=opensource
* OpenWRT
* IPFire
* https://en.wikipedia.org/wiki/List_of_router_and_firewall_distributions
* https://buttplug.io/
** https://github.com/buttplugio/
** https://www.golem.de/news/buttplug-io-open-source-projekt-fuer-sexspielzeug-wird-stabil-2012-153083.html
* http://dildo-generator.com/
** https://github.com/IkarosKappler/extrusiongen
* https://www.comingle.io/
** https://www.core77.com/posts/28903/in-the-details-building-an-open-source-multivibrating-dildo-28221

stuff

* https://en.wikipedia.org/wiki/Teledildonics
* https://en.wikipedia.org/wiki/Metafetish
* https://www.metafetish.com/
* https://buttplug.io/
* https://iostindex.com/
* https://nonpolynomial.com/blog/
* https://intiface.com/
a solar generator describes a portable device with the most important features of a small Photovoltaic system:

* battery with BMS
** often some type of lithium battery
* charge controller
** for charging the battery using solar cells
** [[MPPT (Maximum Power Point Tracking) charge controller]]
** [[PWM charge controller]]
* DC outputs
** plain DC outputs (often 5V and 12V) to drive devices directly from DC
* inverter
** to supply devices with power which don't run on the DC outputs (easily)
* charger with mains input
** to charge the battery from mains power, might be faster than solar

stuff

* https://diysolarforum.com/threads/lets-build-an-open-source-solar-generator.16388/
* https://www.opensourceecology.org/solar-power-generator-update/
* https://www.ose-germany.de/projekte/libresolarbox/
* https://wiki.opensourceecology.de/SolarBox
* https://sunzilla.de/ - seem dead, but is documented
** https://web.archive.org/web/20171014012534/https://sunzilla.de/
** https://opensource.com/life/16/7/sunzilla
** https://makezine.com/2015/11/30/this-open-source-diy-solar-generator-unfolds-like-a-flower/
** https://www.instructables.com/Pop-up-Solar-Generator-SunZilla-30/
** https://www.youtube.com/watch?v=-4g0_a48vyg
* https://gitlab.fabcity.hamburg/hardware/interfacer-osh-build-workshops/libre-solar-box-360wh
** 
* see [[Fast Fourier Transform (FFT)]]

lists

* https://github.com/topics/spectrum-analyzer
* https://github.com/topics/signal-processing
* https://jackaudio.org/applications/ under "Metering and Analysis"

software

* http://friture.org/
* https://github.com/markjay4k/Audio-Spectrum-Analyzer-in-Python
* https://sourceforge.net/projects/audmes/ - AUDio MEasurement System
* https://github.com/maqifrnswa/scimpy
* [[frequency response webapp]]

web software/tools

* https://github.com/wayou/HTML5_Audio_Visualizer
* https://audiomotion.me/ - https://github.com/hvianna/audioMotion.js
* https://wayou.github.io/audio-visualizer-with-controls/ - https://github.com/wayou/audio-visualizer-with-controls
* Inkscape - https://inkscape.org/
* Karbon - https://calligra.org/karbon/ - part of the Calligra Suite
* libre office draw - https://www.libreoffice.org/discover/draw/
* https://skencil.org/ - seems to not be under active development
* https://github.com/SVG-Edit/svgedit - web/browser based
* https://hundredrabbits.itch.io/dotgrid
* http://sk1project.net/
* https://ballpoint.io/  - web/browser based
* http://webchemy.org/ - web/browser based
* PGF/TikZ
* https://github.com/RazrFalcon/svgcleaner-gui - only svg minifier
* Synfig Studio - https://www.synfig.org/
* https://www.pencil2d.org/
* https://opentoonz.github.io/e/
** https://morevnaproject.org/opentoonz/
* https://maurycyliebner.github.io/
* http://www.maefloresta.com/
* https://glaxnimate.mattbas.org/
* https://www.vpaint.org/
* https://github.com/va3c/viewer
* https://github.com/gdsestimating/three-dxf
* https://openjscad.org/
* https://github.com/donmccurdy/three-gltf-viewer
* https://github.com/omrips/viewstl
** https://www.viewstl.com/
* https://github.com/acgessler/open3mod
** https://acgessler.github.io/open3mod/
other

* https://threejs.org/ - good lib to make viewers with
* [[SVG, Canvas and WebGL - advanced graphics on websites]]
* https://remodel.dk
* https://opensource.org/osforbusiness
* https://www.de.digital/DIGITAL/Redaktion/DE/Digital-Gipfel/Video/2020/20201130-digital-gipfel-forum-a-tag1-1135-neue-geschaeftsmodelle.html
* https://opencircularity.info/talks/
* https://en.wikipedia.org/wiki/Business_models_for_open-source_software
* https://wiki.fablab-muenchen.de/display/FABMX/Open+Hardware+Business+Models

Software:

* Proxmox (and maybe redhat): offering professional support, trainings and enterprise repos
* Nextcloud: offering managed hosting and support
* offering additional paid features (more frowned uppon)
* just running on funding / donations

Hardware:

* selling the allready completely assembled piece
* selling kits for people wanting to DIY
* just running on funding / donations
* Prusa
* 
* https://github.com/FOSSASystems
* https://github.com/nasa-jpl/open-source-rover
* https://hackaday.com/2018/11/26/designing-space-rated-pcbs/
* https://tinygs.com/
** https://github.com/G4lile0/tinyGS
** [[How to receive and track LoRa Satellites (TinyGS). Incl. innovative ideas for your projects|https://www.youtube.com/watch?v=ltJQjqm5bKA]]
* https://github.com/Thorbijoern/OpenSpaceMining
* https://www.youtube.com/results?search_query=asteroid+mining
* https://www.youtube.com/watch?v=Gih8R-f_KMo
* https://www.youtube.com/watch?v=NtQkz0aRDe8

* maybe getting ideas from the open source satellite community?
general info

* https://en.wikipedia.org/wiki/VJing
* https://de.wikipedia.org/wiki/Kategorie:Lichtkunst
* https://de.wikipedia.org/wiki/Kategorie:Videokunst
* https://de.wikipedia.org/wiki/Projektionsmapping
** https://en.wikipedia.org/wiki/Projection_mapping
* see also [[Open Sound Control (OSC) (protocol)]]
* https://www.thedmxwiki.com/Welcome
* https://linux4vjs.net/
** https://linux4vjs.net/VJ%20Tool%20Types/linux-distribution/
* https://limeartgroup.com/the-mega-list-of-vj-software-and-tools/
* https://blogs.fsfe.org/samtuke/?p=245
* http://www.thedmxwiki.com/
* https://de.wikipedia.org/wiki/Kategorie:Lichtf%C3%BChrung
* https://de.wikipedia.org/wiki/Veranstaltungsbeleuchtung
* https://en.wikipedia.org/wiki/Category:Stage_lighting
** https://en.wikipedia.org/wiki/Lighting_control_console
** https://en.wikipedia.org/wiki/Lighting_control_system
* https://hackaday.com/tag/vj/


DMX

* https://de.wikipedia.org/wiki/DMX_(Lichttechnik)
** https://en.wikipedia.org/wiki/DMX512
** https://www.theater-technisch-lab.nl/dmxdu.htm
** https://wiki.production-partner.de/licht/steuersignale-der-lichttechnik/
** https://www.soundlight.de/techtips/dmx512/dmx512.htm
** https://wiki.production-partner.de/licht/lichtsteuerung-mit-dmx-512/


RDM

* https://en.wikipedia.org/wiki/RDM_(lighting)


ACN

*https://en.wikipedia.org/wiki/Architecture_for_Control_Networks


Artnet

* https://en.wikipedia.org/wiki/Art-Net
* https://awesomeopensource.com/projects/artnet
* https://github.com/OpenLightingProject/libartnet
*https://github.com/topics/artnet


light controll software

* https://mikacousin.github.io/olc/
* https://qlcplus.org/
* https://www.openlighting.org/
** https://www.openlighting.org/openlightingproject/projects/
** https://opendmx.net/index.php/Open_Lighting_Project
** https://wiki.openlighting.org/index.php/Open_Lighting_Project
** https://opendmx.net/index.php/Open_Lighting_Architecture
* https://xlights.org/
** https://www.nutcracker123.com/wk/index.php/Main_Page
* https://github.com/neophob/PixelController
** https://www.ledstyles.de/index.php?thread/17655-open-source-led-matrix-steuerung-pixelcontroller/&pageNo=1
* lists:
** https://dmxking.com/control-software
** https://opendmx.net/index.php/Category:Controllers
* https://benjamin.kuperberg.fr/chataigne/en
** https://hackaday.com/2023/01/06/chataigne-an-open-source-swiss-army-knife/
* https://ossia.io/


video/projection mapping/mixing software

* https://github.com/salsaman/LiVES
** https://en.wikipedia.org/wiki/LiVES
* https://sat-metalab.gitlab.io/splash/en/
* https://veejayhq.github.io/
** https://en.wikipedia.org/wiki/Veejay_(software)
* https://en.wikipedia.org/wiki/FreeJ ?
** https://www.dyne.org/software/freej/
* https://sourceforge.net/projects/openvjj/ ?
* https://mapmapteam.github.io/
* https://sourceforge.net/projects/glmixer/ - discontinued
* https://brunoherbelin.github.io/vimix/
* https://www.opensourceimaging.org/project/structured-light-3d-scanner/
* https://pocketvj.com/ - video projection platform
** https://projection-mapping.org/pocketvj-open-source-raspberry-pi-projection-mapping-tool/
** https://github.com/magdesign/PocketVJ-CP-v3
** https://hackaday.com/tag/projection-mapping/
* https://hackaday.com/2018/09/16/raspberry-pi-projection-mapping-crash-course/


led mapping

* https://github.com/bertspaan/led-strip-mapper
* https://github.com/vivedo/ledmapper
* https://hackaday.com/2022/03/23/finally-a-mapping-tool-for-addressable-led-strings/
* https://opensourcelibs.com/lib/lightwork
* https://www.reddit.com/r/led/comments/eqlq9q/software_for_mapping_leds_open_source/
* https://alltd.org/led-mapping-gpu-pipelines-with-lucas-morgan-2/
* https://github.com/neophob/PixelController
** https://www.ledstyles.de/index.php?thread/17655-open-source-led-matrix-steuerung-pixelcontroller/&pageNo=1
* https://github.com/techtim/ofxLedMapper
* https://github.com/hzeller/rpi-rgb-led-matrix
** https://github.com/hzeller/rpi-matrix-pixelpusher
* https://github.com/Gerfunky/TinyPixelMapper
* https://github.com/PWRFLcreative/Lightwork
* https://github.com/albert-ka/openLedMapper
* https://github.com/aaknitt/pixel_mapper
* https://hackaday.com/2017/12/21/bringing-a-christmas-lights-show-inside/


tools

* https://gitlab.com/tobi08151405/open-artnet-visualizer
* https://www.orangepi-dmx.org/
** https://github.com/vanvught/rpidmx512
* https://github.com/cbdevnet/midimonster


stuff

* http://en.qi-hardware.com/wiki/Milkymist_One
* https://hackaday.com/2015/12/30/must-have-overkill-christmas-tree-lights/
* https://hackaday.com/tag/video-projection/


proprietary controller stuff

* http://avldiy.cn/
* https://www.anyma.ch/research/udmx/


windows:

* https://www.dmxcontrol.de/ - freeware
* https://www.pcdimmer.de/ - open source
** https://de.wikipedia.org/wiki/PC_DIMMER
* http://www.freestylerdmx.be/ - freeware
* http://www.live-leds.de/
* https://www.offene-werkstaetten.org/
* https://wiki.hackerspaces.org
* https://www.ose-germany.de/projekte/openecolab-de/
* open bike workshops
* https://openecolab.de/
* https://coma-emerald.de/%C3%B6kologische%20Stadtteilzentren.html
* https://fabcity.github.io/
* https://fablabbcn.org/
* https://www.fablabs.io/
<<list-links "[all[current]tagging[]]">>

* [[Making DIY Lenses with Epoxy|https://www.youtube.com/watch?v=mfAGivG9Koc]]
* [[DIY Laser Lithography: Micron resolution|https://www.youtube.com/watch?v=XJ9w7DjI_Bc]]
* [[3D Printing Optomechanical Components|https://www.youtube.com/watch?v=NfjQO9_9C1U]]
* 



* https://phydemo.app/ray-optics/simulator/
** https://github.com/ricktu288/ray-optics
open source App with buttons, sliders, knobs, etc. to send data to devices supporting the [[Open Sound Control (OSC) Protocol|Open Sound Control (OSC) (protocol)]].

maybe with user-defineable layout of buttons and so on

similar app:

* https://f-droid.org/de/packages/org.sensors2.osc/
** https://github.com/SensorApps/Sensors2OSC
** https://sensors2.org/osc/
* https://f-droid.org/de/packages/org.sensors2.pd/

other open source apps use mostly kotlin, some still use java:

* https://github.com/mwarning/trigger
* https://github.com/thundernest/k-9
* https://github.com/SimpleMobileTools

other options:

* https://dzone.com/articles/android-development-options
<<list-links "[all[current]tagging[]]">>

audio

* [[Oscilloscopes For Audio Bench Work and Testing - 101 Series - Blueglow Electronics|https://www.youtube.com/watch?v=CoaI9lJsNgA&list=PLo7DGF0CxJGlrr7QxJydGYW1k8VwRCc4m]]

!! safety

* [[EEVblog #279 - How NOT To Blow Up Your Oscilloscope!|https://www.youtube.com/watch?v=xaELqAo4kkQ]]
* [[Everything you need to know when buying/using an Oscilloscope! EB#49|https://www.youtube.com/watch?v=d58GzhXKKG8]]
* see [[differential oscilloscope probe]]
* see [[Trenntransformator]]

other

* [[see signal / logic analysis tools]]
* pc soundcards can be used as crude oscilloscopes, but they only have a very limited capability and can be easily destroid when connecting to to high voltages
** https://makezine.com/projects/sound-card-oscilloscope/
** https://hackaday.com/2014/05/27/an-audio-based-usb-oscilloscope-and-signal-generator-for-20/
** http://www.zeitnitz.de/Christian/scope_en
* https://hackaday.com/2018/08/06/review-a-20-mhz-pocket-scope-for-not-a-lot/
* https://hackaday.com/2016/01/27/a-tale-of-two-sub-100-oscilloscopes/
* hantek
** https://github.com/doctormord/OpenBuudai
** https://openhantek.org
*** https://github.com/OpenHantek/openhantek
** https://www.eevblog.com/forum/oshw/opensource-oscilloscope-with-tabletphone-display-based-on-hantek-6022be/
* cheap chinese scopes
** https://github.com/ardyesp/DLO-138
** [[ How good can a new $60 oscilloscope actually be? (Hantek 6022BE Review) |https://www.youtube.com/watch?v=8ts5J09Y7Gc]]
* https://www.crowdsupply.com/andy-haas/haasoscope
* https://hackaday.io/project/167292-8-ghz-sampling-oscilloscope
* https://www.tindie.com/products/Earth_People_Technology/open-source-digital-storage-oscilloscope-4-ch/

* [[EEVBlog: Oscilloscope Tutorials|https://www.youtube.com/watch?v=DMXiD3dKYJc&list=PLvOlSehNtuHsCTtj-T_vkpTTbBXW4sB51]]
** [[EEVblog #279 - How NOT To Blow Up Your Oscilloscope!|https://www.youtube.com/watch?v=xaELqAo4kkQ]]
** [[EEVblog #926 - Introduction To The Oscilloscope|https://www.youtube.com/watch?v=Iq4QlfH-oqk]]

* [[EEVBlog: Oscilloscope Probing|https://www.youtube.com/watch?v=OiAmER1OJh4&list=PLvOlSehNtuHvIDfW3x2p4BY6l4RYgfBJE]]
* [[OSCILLOSCOPE Training|https://www.youtube.com/playlist?list=PLRiUZePMxwAyzlHMj9on4KlTsUaGJt4ue]]

* [[EEVblog #1260 - $70 100MHz Oscilloscope?|https://www.youtube.com/watch?v=SIH48bIUU00]]
* [[EEVblog #1317 - $140 2CH 100MHz Fnirsi Tablet Oscilloscope Review|https://www.youtube.com/watch?v=5iwtDwJlbWk]]
* [[ 4/12 This $57 portable oscilloscope has a really cool feature (ZEEWEII DSO1511G review) |https://www.youtube.com/watch?v=Uqrel5fQpK4]]

open source oscis

* https://www.scopefun.com/
** https://hackaday.com/2016/10/06/open-design-oscilloscope-could-be-almost-free/
* https://hackaday.io/project/165964-60mhz-bandwidth-250msps-probe-scope
* https://opensource.com/life/14/6/diy-open-source-oscilloscope
* https://www.eevblog.com/forum/testgear/a-high-performance-open-source-oscilloscope-development-log-future-ideas/
* https://hackaday.io/project/167292-8-ghz-sampling-oscilloscope
* http://openhantek.org/ - just open source software for proprietary devices
* https://www.tindie.com/products/Earth_People_Technology/open-source-digital-storage-oscilloscope-4-ch/
* https://hackaday.com/2023/09/26/13-scope-and-logic-analyzer-hits-18-msps/

probes

* [[EEVblog #1367​ - 5 Types of Oscilloscope Passive Probes COMPARED|https://www.youtube.com/watch?v=rzo4Ntxqu1E]]
* [[EEVblog #1368​ - Active Oscilloscope Probes COMPARED (Part 2)|https://www.youtube.com/watch?v=WlSb8hdFtTY]]
* [[EEVblog #1178​ - Build a $10 DIY EMC Probe|https://www.youtube.com/watch?v=2xy3Hm1_ZqI]]
** [[EEVblog #1188​ - $10 DIY EMC Probe using Scope FFT|https://www.youtube.com/watch?v=nImoQcoqkuQ]]


stuff

* https://github.com/florentbr/OWON-VDS1022
* https://www.sainsmart.com/collections/oscilloscopes
* [[Owon HDS3102M-N Handheld Scope review|https://www.youtube.com/watch?v=6td9kVKWGFw]]
* https://www.micsig.com/product5/
* https://www.youtube.com/results?search_query=kiss+analog+oscilloscope
* [[EEVblog #1317 - $140 2CH 100MHz Fnirsi Tablet Oscilloscope Review|https://www.youtube.com/watch?v=5iwtDwJlbWk]] 
* https://micsig.com/
* https://www.picotech.com/ - pico scope
* https://hackaday.com/tag/oscilloscope/

diy

* https://hackaday.com/2023/02/27/diy-stm32-scope-is-simple-cheap-and-featureful/
* https://www.micsig.com/ACP1000/
* https://www.micsig.com/current%20probe/
* https://www.micsig.com/RCP500/
* https://www.picotech.com/accessories/current-probes
* https://www.eevblog.com/product/cp2100b/
* [[EEVblog 1413 - Oscilloscope Current Probe TEARDOWN + DEMO|https://www.youtube.com/watch?v=suf3VWqs5zw]]
* https://hackaday.com/2020/02/10/recreating-fast-oscilloscopes-is-a-slow-process/
* https://hackaday.com/2018/08/06/review-a-20-mhz-pocket-scope-for-not-a-lot/
open source

* https://hackaday.com/2020/05/07/open-source-2-ghz-oscilloscope-probe/
* https://xellers.wordpress.com/electronics/1ghz-active-differential-probe/
* [[Probe Master vs Competitor Multimeter Test Leads|https://www.youtube.com/watch?v=i4IvB90jZxs]]
* [[100x High Voltage Oscilloscope Probe Test and Experiments (P4250)|https://www.youtube.com/watch?v=c6DsvD5jDgc]]
* https://github.com/jivoi/awesome-osint
* https://github.com/tracelabs/awesome-osint
* https://oslint.org/community/index.php?resources/awesome-list-of-osint-tools.2/
* https://github.com/lorien/awesome-osint
* [[OSINT At Home - Tutorials on Digital Research, Verification and Open Source Investigations|https://www.youtube.com/playlist?list=PLrFPX1Vfqk3ehZKSFeb9pVIHqxqrNW8Sy]]
** [[OSINT At Home #9 – My Top 4 Free Satellite Imagery Sources|https://www.youtube.com/watch?v=OONjbRAR-TM99]]

Dresden:

* https://www.vvo-online.de/de/service/verkehrskameras/index.cshtml
* https://wiki.thevillage.chat/
* https://listed.to/@lenowac
** https://github.com/lenowac/wiki
* https://sourceforge.net/projects/vslm/ - Virtual Sound Level Meter for analyzing calibrated sound files
* https://sourceforge.net/projects/sofacoustics/ - Spatially Oriented Format for Acoustics
* https://sourceforge.net/projects/expsuite/ - software framework for applications to perform psychoacoustical experiments
* https://sourceforge.net/projects/rt60calculator/ - Audio reverberation time calculation
* https://sourceforge.net/projects/pamguide/ - An analysis tool in MATLAB and R for acoustic habitat characterisation
* https://sourceforge.net/projects/jbj/ - A digital signal processing lab intended for educational purpose
* https://sourceforge.net/projects/dsp-lab/ - Digital Signal Processing Simulation
* https://sourceforge.net/projects/tdsapplication/ - A little helpful application for digital signal processing learning
* https://sourceforge.net/projects/rtcmix-pd/ - RTcmix music language as PureData external
* http://spek.cc/ - Acoustic Spectrum Analyser, helps to analyse your audio files by showing their spectrogram
* [[ Let's Talk Oxy Acetylene |https://www.youtube.com/watch?v=-uPAjIOkLVA]]
* [[ The Full Guide to Oxy Fuel Cutting |https://www.youtube.com/watch?v=gXuMDxYeqZ4]]
* [[ Oxy-Acetylene Cutting - Shake Hands With Danger! |https://www.youtube.com/watch?v=oKhhWGhBkYo]]
<<list-links "[all[current]tagging[]]">>

* [[EEVblog #354 - CityRail PA Amp Teardown|https://www.youtube.com/watch?v=NsOfgvbZQo0]]
* [[Ibiza 800W Amplifier repair - Dead. No Power|https://www.youtube.com/watch?v=qJxtu1kStLU]]
* [[BASIC 400 Powered Active PA Speaker - Blows Fuses, But Why?|https://www.youtube.com/watch?v=T0AoI-QFj_k]]
* [[Faulty 200W rms Amplified Active Speaker? NO WAY! It's all lies lies and DAMN LIES!!|https://www.youtube.com/watch?v=dI6w_-o69CA]]
<<list-links "[all[current]tagging[]]">>
* https://www.jobst-audio.de/selbstbautut/181-howto_lautsprecherbau1
* special joins not allways needed...
* https://www.youtube.com/watch?v=8vFGrNjT4P4
* https://www.youtube.com/watch?v=N149xC5DYl8
* https://www.youtube.com/watch?v=gtzogtcsLgQ
* https://www.youtube.com/watch?v=Uno5mXKoNyU
* MDF is often used for hifi speakers, it's more heavy than plywood and therefore not recommended for PA speakers
* some people build speakers from OSB but it is not considered good/professional
* PA speakers are build from 12, 15, 18mm or thicker birch plywood (multiplex) which is pretty light and gives good strength
* https://www.speakerplans.com/index.php?id=guide
* http://www.dancetech.com/aa_dt_new/pa/PA.cfm
* http://www.dancetech.com/index.cfm?loading=pa
* http://www.jobst-audio.de/
* https://en.wikipedia.org/wiki/Public_address_system

in wie weit kann man das design von "Hifi" lautsprechern auf PA boxen übertragen?
man findet halt zu heimlautsprechern viel mehr und die designs sind im groben ja nicht viel anders... muss man vlt. was beachten da PA ja eig. für viel größere räume bzw. für freiluft ist?

Hifi hat nen anderen Abstrahlwinkel und ne andere Abstimmung

Pa wird meistens eher im nutzbass abgestimmt (45hz Rum) und Hifi tiefer

Pa kann gerne Mal ne Überhöhung im Bass haben, Hifi soll linear sein

Frequenzweichen müssen halt wesentlich stärker dimensioniert werden als bei hifi
speakers using modulated ultrasound to produce highly directional sound.

do they have good bass?

* https://www.soundlazer.com/
* https://en.wikipedia.org/wiki/Sound_from_ultrasound
* https://www.instructables.com/id/Ultrasonic-Sound-Gun-Parametric-Speaker/
* https://github.com/NiklasFauth/ParametricSpeaker
https://twitter.com/atc1441/status/1583738148286132225


<<<
These days LIDL offers the PDM 300 C3 Multimeter for 15€ again������

The special part about it is that is offers a convenient UART 2400 baud TX line which spits out the current measurements!

Fully reversed and neat tools available here:
https://mikrocontroller.net/articles/Multi

Its very simple to add Bleutooth to the 15€ Multimeter!
Just bridge the 5V converter so the HC-06 module runs on the 3V from the Multimeter and set it to 2400 baud

On my one its just a bridge between these two points, but there could be different revisions, so make sure to bridge the 5V rail with the 3.3V rail on the module
<<<

https://www.mikrocontroller.net/articles/Multimeter_PDM-300-C2_Analyse

I made the error to install the bluetooth module into the multimeter before setting the baud and name

HC-05 config:

* https://www.instructables.com/AT-command-mode-of-HC-05-Bluetooth-module/
* https://www.instructables.com/How-to-Change-the-Name-of-HC-06-Bluetooth-Module/
* https://www.instructables.com/Bluetooth-AT-Commands-Settings-HC05-HC06/


HC-06 config

everything is mixed up and confusing... i had problems talking to the module because i was using the AT command to check. I tested all standard baud rates, different parity, different stopbits and i tried \r, \n, \r\n and \n\r.

nothing worked correctly... with baud 9600, 8bits data, no flow control, no parity, 1 stopbit i was atleast able to set the name, but nothing else. The ``AT`` command does not reply ``OK`` and it seems to do nothing with other commands too.
I was able to send and receive data with the app ~SerialTest (https://f-droid.org/packages/priv.wh201906.serialtest/).

ultimate help was the following: https://forum.arduino.cc/t/solved-hc-06-bluetooth-module-and-at-commands/697344/6

* HC-05 and HC-06 have different command sets
* HC-05 wants \r\n
* HC-06 dosn't want \r\n, it instead works with timeouts

now i also get why AT+NAME works, because the rest of the command is arbitrary data for the name.

to the default settings you need for HC-06 are:

* baud: 9600
* data: 8 bits
* flow control: none
* parity: none
* stop bit: 1
* line termination: none

the AT-commands are the following:

* ``AT``
** reply: ``OK``
* ``AT+NAME<name>``
** substitute ``<name>`` with the name you want to set
** reply: ``OKsetname``
* ``AT+BAUD<nr>``
** substitute ``<nr>`` with the number of the baud setting
** nr. 2 is for 2400 baud
** reply: ``OK<baudrate>``
* ``AT+VERSION``
** reply: ``OKlinvor1.x``


what i set:

* ``AT+NAMEDMM-PDM-300``
** sets "DMM-PDM-300" as name for Digital MultiMeter PDM-300 as Name
* ``AT+BAUD2``
** sets the baud to 2400


now i just need software for it.


other tips:

* https://twitter.com/basti_uhl/status/1585316132654751745

Portsdown test equipment suite?
<<list-links "[all[current]tagging[]]">>

stuff

* https://hackaday.com/2023/01/05/excuse-me-your-tie-is-unzipped/
* [[Does a DIY Audio Crossover make sense? How passive filters work! -- EB#41|https://www.youtube.com/watch?v=1wzUqVFyQ7o]]
* [[BASICS 1 - Frequenzweiche. Grober Überblick wozu eine Frequenzweiche benutzt wird.|https://www.youtube.com/watch?v=IhcUqJwvaY8]]
* [[BASICS 4 - Frequenzweiche. Die Spule - Funktionsweise|https://www.youtube.com/watch?v=QWCHrI8bnUE]]
* [[BASICS 3 - Frequenzweiche. Der Kondensator - Aufbau und Funktionsweise|https://www.youtube.com/watch?v=EyXzoZQNIr8]]
* [[Wie ist eine Lautsprecher Frequenzweiche aufgebaut?|https://www.youtube.com/watch?v=o95Pu3sC8hQ]]
* [[https://de.wikipedia.org/wiki/Frequenzweiche_(Lautsprecher)]]
* https://de.wikipedia.org/wiki/Hochpass
* https://de.wikipedia.org/wiki/Tiefpass
* [[Passive Crossover Design Part 1: Tweeters|https://youtu.be/kUrxAU7f78c]]
* https://celestion.com/blog/build-this-passive-crossovers/
* https://en.wikipedia.org/wiki/Audio_crossover
** [[https://de.wikipedia.org/wiki/Frequenzweiche_(Lautsprecher)]]

components:

* see [[electronics parts/components]] and [[electronic basics]]
* inductors
* high power resistors
* capacitors
** Foil capacitor
** bipolar electrolytic capacitors
*** optional: https://www.edaboard.de/threads/bipolaren-elko-durch-zwei-gepolte-ersetzen.11145007/ but not prefered
* protection
** PTC elements
*** as resetting/recovering fuses or
*** as resistors whose resistance rises with higher power
*** https://en.wikipedia.org/wiki/Temperature_coefficient#Positive_temperature_coefficient_of_resistance
**** https://de.wikipedia.org/wiki/Kaltleiter
*** https://www.elektronik-kompendium.de/sites/bau/0111051.htm
*** https://de.wikipedia.org/wiki/Selbstr%C3%BCckstellende_Sicherung
** incandescent lamps
*** https://en.wikipedia.org/wiki/Incandescent_light_bulb#Electrical_characteristics
**** https://de.wikipedia.org/wiki/Gl%C3%BChlampe
** fuses

calculators / simulation tools:

* https://www.micka.de/en/2weg_en.php
* http://www.jobst-audio.de/tools-frequenzweiche/frequenzweiche
** http://www.jobst-audio.de/tools-frequenzweiche/zobel-glied
** http://www.jobst-audio.de/tools-frequenzweiche/saugkreis
** http://www.jobst-audio.de/tools-frequenzweiche/l-pad
** http://www.jobst-audio.de/tools-frequenzweiche/sperrkreis
* https://www.falstad.com/afilter/
** https://www.falstad.com/circuit/

zobel glied / Boucherot-Schaltung

* https://de.wikipedia.org/wiki/Resonanztransformator
* https://en.wikipedia.org/wiki/Zobel_network
* https://en.wikipedia.org/wiki/Boucherot_cell
* https://www.elektroniktutor.de/analogtechnik/zobel.html

r-c glied

* https://www.spektrum.de/lexikon/physik/rc-glied/12164
* https://de.wikipedia.org/wiki/RC-Glied

stuff

* [[EINFACH erklärt - Sperr- und Saugkreise für Frequenzweichen|https://www.youtube.com/watch?v=siKi__ZUpf8]]
*many small bluetooth speakers use them to improve bass
* functions basically in the same way bass reflex ports do, but require much less space
* https://www.bluetooth-lautsprecher-infos.de/artikel/passive-radiatoren-bei-bluetooth-lautsprechern-demonstration
* https://en.wikipedia.org/wiki/Passive_radiator_(speaker)
* http://audiojudgement.com/passive-radiator-speaker-design/
* https://www.subwoofer-builder.com/passive.htm
* http://mh-audio.nl/Calculators/PassiveRadiator.html
* https://celestion.com/speakerworld/cabinetdesigns/


diy passive radiators?

* using off-the-shelf speaker suspensions? (sicken)
* making own out of silicone?
* Keepass and its derivatives/compatible siblings
** ~KeepassXC
** ~KeepassDX (Android)
* Bitwarden
** https://github.com/bitwarden/mobile/issues/6#issuecomment-584002060


stuff

* https://www.theverge.com/22285499/password-manager-lastpass-free-bitwarden-zoho
* https://keepassxc.org/docs/#faq-yubikey-2fa
* https://pages.nist.gov/800-63-FAQ/#q-b05
* https://www.bsi.bund.de/DE/Themen/Verbraucherinnen-und-Verbraucher/Informationen-und-Empfehlungen/Cyber-Sicherheitsempfehlungen/Accountschutz/Sichere-Passwoerter-erstellen/Umgang-mit-Passwoertern/umgang-mit-passwoertern_node.html
* https://www.bsi.bund.de/DE/Themen/Verbraucherinnen-und-Verbraucher/Informationen-und-Empfehlungen/Cyber-Sicherheitsempfehlungen/Accountschutz/Sichere-Passwoerter-erstellen/sichere-passwoerter-erstellen_node.html
* https://www.heise.de/security/meldung/Passwoerter-BSI-verabschiedet-sich-vom-praeventiven-Passwort-Wechsel-4652481.html
* https://hackaday.com/2023/01/03/the-problem-with-passwords/
<<list-links "[all[current]tagging[]]">>
* https://www.hirensbootcd.org/
* https://www.knopper.net/knoppix-info/index-en.html
* ~MediCat USB - https://gbatemp.net/threads/medicat-usb-a-multiboot-linux-usb-for-pc-repair.361577/
* https://www.ultimatebootcd.com/
** still gets updates but not much further development
** https://sourceforge.net/projects/ubcd/ (dead here)
* https://partedmagic.com/
** https://de.wikipedia.org/wiki/Parted_Magic
* gparted
** gparted live
* https://wiki.syslinux.org/wiki/index.php?title=Hdt_(Hardware_Detection_Tool)
* https://alternativeto.net/software/ultimate-boot-cd/about/
* see also [[Disk / drive (HDD/SSD/Flash) Rescue]]
* https://www.linux.com/news/hardware-diagnostics-open-source-tools/
* lists
** https://www.lifewire.com/free-memory-test-programs-2626178
** https://www.lifewire.com/free-hard-drive-testing-programs-2626183
** https://www.lifewire.com/free-data-destruction-software-programs-2626174
** https://www.lifewire.com/free-bootable-antivirus-tools-2625785
* ~~https://www.memtest.org/~~
* https://grml.org/

writing images/isos to usb-stick/etc.

* https://www.pendrivelinux.com/universal-usb-installer-easy-as-1-2-3/
* https://unetbootin.github.io/
* see also [[multiboot usb tools]]
* https://rufus.ie/
* fedora media writer
!! pcb design basics

* on paper
* using software like
** KiCAD
** https://librepcb.org/
** https://en.wikipedia.org/wiki/Comparison_of_EDA_software
** https://fritzing.org/ was a nice easy tool for beginners but they started to have a mandatory "donation" as download-barrier which is not nice
* tools
** https://www.snapeda.com/ (not suitable for open source)
** ultralibrarian (not suitable for open source)
* [[EEVblog #1129 - Creating a Nice Readable Schematic|https://www.youtube.com/watch?v=R_Ud-FxUw0g]]
* [[Introduction to Basic Concepts in PCB Design|https://www.youtube.com/watch?v=ESnDQl7ZM5o]]
* https://libre.solar/docs/pcb_layout/

stuff 

* https://www.youtube.com/watch?v=R_Ud-FxUw0g
* https://components101.com/articles
* https://pinouts.org/

noise reduction



stuff

* https://electronics.stackexchange.com/questions/25308/what-do-the-pcb-markings-mean
see [[soldering, pcb repair, electronics cleaning supplies]]

* http://www.cryo-sonic.com/
** https://hackaday.com/2014/11/13/extreme-repair-of-a-burnt-pcb/
* [[PCB solder pad repair & corrosion clean up - The epoxy method|https://www.youtube.com/watch?v=vx50YtEC2S8]]
* [[EEVblog #682 - Ness D16X Alarm Panel Repair|https://www.youtube.com/watch?v=h6D4MMWjrmM|]]
* https://www.youtube.com/c/NorthridgeFix
* https://elektrotanya.com/peavey_pv8_mixer_sch.pdf/download.html
** older or newer version

Problem:

* doesn't work anymore after wire broke at the power supply and wire got bodge-repaired
* small transistor seems to be burnt
** Marking "B1241", seems to be 2SB1241
** has 3 different current gain options, seems to be Option R with hfe 180-390
** https://pdf1.alldatasheet.com/datasheet-pdf/view/173350/ROHM/2SB1241.html
** https://pdf1.alldatasheet.com/datasheet-pdf/view/335980/ROHM/2SB1241.html
** original transistor is discontinued, have to reverse the circuitry and find a fitting alternative
** weird "3-SIP" package but there is no real space problem, so any other similar transistor (like TO-92 package) is fine
* NCP3063B voltage inverter shorted
* the power wire from the power supply has to be repaired propperly.

Info

* uses an external 15V DC SMPS
** can supply 1A, but it seems only 500mA are needed
* uses an NCP3063B as voltage inverting switching regulator to supply -15V DC
** https://www.onsemi.com/pdf/datasheet/ncp3063-d.pdf
* https://electronics.stackexchange.com/questions/623186/2sb1241-transistor-replacement
* https://electronics.stackexchange.com/questions/518706/finding-replacement-pnp-transistors
* see also [[transistors]]
* 1N5251B zener diode
** https://www.onsemi.com/pdf/datasheet/1n5221b-d.pdf
** https://www.vishay.com/docs/85588/1n5221.pdf

Repair:

I had already desoldered the 2SB1241 to have a better look at it and i then decided to test the mixing console a bit, but i couldn't figure out more about the problem.

I hat the console lying around a bit because i had other projects. I was able to think about it and i finally got a dual lab bench power supply. now i could test the PV8 much better.

I started by soldering leads to the 2 main caps for +15V, -15V and GND rails, so i could directly inject the voltage without using the original power supply and the integrated voltage inverter. I was careful and used the current limiting feature of my lab power supply. I didn't test everything but it seemed to work fine and drew less than 0.2A per voltage rail. So I don't suspect anything here.

But after the successful test i noticed that an electrolytic cap next to the NCP3063B was bulged. Its a 25V 100uF low impedance ([[107KXM025M from Cornell Dubilier / Illinois Capacitor|https://www.cde.com/resources/catalogs/KXM.pdf]]). I had some used KY-Series caps from nippon chemicon in my spare parts boxes and replaced the bulged one.
After that i moved the leads over to the 15V dc barrel jack connector to test the voltage inverting supply.
It does not draw much power but the NCP3063B quickly heats up and it does not output the voltage it's supposed to.
So the NCP3063B is probably dead.

Finding a replacement NCP3063B is not easy because it's also discontinued

* on aliexpress are some listings, but probably not originals from onsemi
* [[there is one listing on ebay which might be legit|https://www.ebay.de/itm/123866036269]]
* [[RS Components has some|https://de.rs-online.com/web/p/dc-dc-regulator-ics/7737844p]]

I finally got 3 NCP3063 from digikey when i ordered some other parts. Iirc the temp rating is a bit different but i don't think that really matters, i think both versions should work fine.

the 2SB1241 is discontinued and there are no new ones available.

important data:

* BJT PNP
* pinout: ECB or BCE
* hfe: 180-390
** "good hfe linearity"
* max Collector Current: -1A continuous
* max collector power dissipation: 1W

maybe important?

* E-B breakdown Voltage: -5V
* low V,,CE(sat),,
** C-E saturation voltage: -0.4V (I,,C,,/I,,B,,= −500mA/ −50mA)
* collector cutoff current: 1uA (V,,CB,,=-60)
* emitter cutoff current: 1uA (V,,EB,,=-4V)
* 

not as important i think:

* C-B / C-E breakdown Voltage: -80V - can be lower/higher were only working with +-15V
* transition frequency: 100MHz - we're not switching really fast, we only switch on once after some time
* output capacitance: 25pF - also not important because we're not switching fast i think

I bought some [[ST Micro BD140-16|https://www.mouser.com/datasheet/2/389/bd135-1848980.pdf]] as replacement for the burned 2SB1241 as a test. The hfe range is slightly lower but maybe i get a batch thats cood for me. when i got them and tested them they were'nt high enough though. But it's not a big loss, they are jelly bean parts and might be useful for something different, also they were'nt expensive.

i have some transistors lying around  that i scavenged from old or broken electronics. i tested them with a simple [[transistor tester|"transistor tester" (avr) component tester]] to find out if they are truly BJT PNPs and find out their hfe values.

* 3x B772 (TO-126)
** https://www.alldatasheet.com/datasheet-pdf/pdf/112939/NEC/B772.html
** https://pdf1.alldatasheet.com/datasheet-pdf/view/82698/ETC/B772.html
** https://www.alldatasheet.com/datasheet-pdf/pdf/53331/FAIRCHILD/B772.html
** good datapoints:
*** low V,,CE(sat),,
*** "good hfe linearity"
*** NEC hfe Rating "P" and no-name hfe rating "Y": 160-320, transistors measure 255, 266 and 305
*** E-B breakdown Voltage: -5V
*** max Collector Current: -3A continuous
*** max total power dissipation: 1W
*** cutoff currents and collector saturation voltage
** higher output capacitance and lower transition frequency
* 4x 2sa1020(long TO-92)
** https://pdf1.alldatasheet.com/datasheet-pdf/view/29938/TOSHIBA/2SA1020.html
** datapoints:
*** hfe: 120-240; measured: 173, 190, 203, 243 ("Y" rating) - lower range
*** pretty linear hfe
*** 900mW collector power dissipation - a little less
*** max 2A collector current
*** breakdown voltages are fine
*** cutoff currents are fine
*** low V,,CE(sat),,
*** higher output capacitance, same transition frequency
* SS8550 / 8550SS / C8550
** https://www.onsemi.com/pdf/datasheet/ss8550-d.pdf


I compared the transistors a bit. In the end i just decided to try the B772.

I removed the 100uF cap again so it's not blasted with the heat of the rework station. I shielded other parts in the vicinity of the NCP3063B with aluminium foil.

I carefully heated the NCP3063B and the area around it with the rework station and carefully removed the shorted chip. Then I carefully put the replacement NCP3063 in its place. To make sure that every pin is soldered i used the soldering iron and applied a bit more solder to each pin. I removed exess solder and tested the connections.

Then i went on to solder the B772. I bent the pins a little, so the TO-126 package can rest on a nearby inductor. I soldered the B772 with the soldering iron.

After i was satisfied with the soldering and testing the connections i wanted to try if it powers on without problems.

I first tested with my lab power supply with current limiting. Everything seemed fine. Then i checked the voltage of the original power supply and tested with it and it also works.

I cleaned the board with rubbing alcohol and q-tips to get rid of the flux.

To finish off i used some slightly elastic glue to glue down the bigger capacitors. They were glued from the factory, but it was just hotmelt glue which was a bit old and the caps didn't stick anymore. The new glue should last long. I also glued the B772 to the Inductor. I didn't use a lot of glue, but it should help dampen vibrations and shocks so the pins of the TO-126 don't break. The original, smaller transistor wasn't glued down, but the TO-126 is a bit bigger.

I let the glue dry over night and tested the mixing console fully. Everything works again.

I think the NCP3063B and 2SB1241 got damaged due to the owner trying to bodge the broken power wire and maybe reversing the polarity. The mixing console doesn't have a diode on the input, which is a oversight by the designers i think.

Now i only have to repair the bodged power supply wire and get the remaining parts of the power supply case from the owner.

I got the missing half of the power supply case from the owner and started the repair on the power supply.

First i marked the polarity on the pcb, before removing the screw terminals that were the temporary fix were the wire broke.
I then removed the screw terminals and desoldered the remaining short pieces of wire from the PCB.
I cut the part of the wire that was inside the screw terminals and a bit messed up, stripped the isolation from the wire and applied a bit of solder.
The original cable break protective sleeve wasn't usable anymore. I have a sleeve that works as replacement. To protect the cable some more i also add a bit of heatshrink tube inside the sleeve.
I slid the protection sleeve and shrink tube on the cable before soldering it to the PCB.
I also tied a knot into the cable after the sleeve to funktion as strain relieve.
Before gluing the case shut i shecked the polarity of the cable with my multimeter, so the output is right.
I used the reflow station to shrink the heatshrink tube.
I used some semi-flexible glue to close the case back up, i also glued the sleeve into the case because the replacment left some gabs. The semi-flexible glue makes it easier to open back up later. But i also used two cable ties to additionally hold the case together.

Everything fixed.
see [[static site generator]]

* https://github.com/getpelican/pelican
* https://blog.getpelican.com/
* https://docs.getpelican.com/en/latest/
* https://github.com/pelican-plugins
** https://github.com/pelican-plugins/image-process - no dithering?
** https://github.com/pelican-plugins/search - nice feature
** https://github.com/pelican-plugins/nojekyll
* https://github.com/getpelican/pelican-themes
** http://www.pelicanthemes.com/
* github pages
** https://github.com/marketplace/actions/pelican-to-github-pages
** https://fedoramagazine.org/make-github-pages-blog-with-pelican/
** https://gist.github.com/JosefJezek/6053301
** https://github.com/rehanhaider/pelican-to-github-pages
** https://justinnaldzin.github.io/create-a-website-using-github-pages-and-pelican.html

* https://solar.lowtechmagazine.com/about.html#hardware
    ** https://homebrewserver.club/low-tech-website-howto.html
    ** https://github.com/lowtechmag/solar
        *** https://github.com/lowtechmag/solar/wiki/Solar-Web-Design
    ** https://solar.lowtechmagazine.com/2020/01/how-sustainable-is-a-solar-powered-website.html
    ** https://homebrewserver.club/low-tech-website-howto.html
    ** https://github.com/lowtechmag/solar-plugins

* nojekyll file
* https://www.heise.de/ct/artikel/Einfach-erklaert-E-Mail-Verschluesselung-mit-PGP-4006652.html
* http://pep.security/
* https://www.shure.com/en-US/performance-production/louder/what-is-phantom-power-why-do-i-need-it
* https://en.wikipedia.org/wiki/Phantom_power
* https://de.wikipedia.org/wiki/Phantomspeisung
* [[EEVblog #616 - How Microphone Phantom Powering Works|https://www.youtube.com/watch?v=e5xenXTwAzo]]

tester

* http://caseyconnor.org/jl/phantastic

blocking phantom power is often just done with 

some microphones support lower voltages but in the professional sector most microphones use 48V phantom power. maybe one would like to experiment a bit with it and doesn't just want to buy a mixing console.

* https://www.learningelectronics.net/circuits/48v-phantom-microphone-power-supply.html
* https://wiki.diyrecordingequipment.com/projects/esp-project-96-48v-phantom-power-supply/
* https://www.electronicsforu.com/electronics-projects/hardware-diy/low-noise-48v-regulated-power-supply
* https://service.shure.com/s/article/how-do-i-build-a-phantom-power-supply?language=en_US
* https://www.youtube.com/results?search_query=phantom+power+supply
* https://sound-au.com/project193.htm
* https://sound-au.com/project35.htm
* https://sound-au.com/project96.htm
* [[Dangers & Solutions - Audio Phantom Power + Demo|https://www.youtube.com/watch?v=_8UTGcuAtd0]]
* https://de.wikipedia.org/wiki/Phasenwinkel
* https://de.wikipedia.org/wiki/Kategorie:Schwingungen
* https://de.wikipedia.org/wiki/Kategorie:Schwingungslehre
* https://de.wikipedia.org/wiki/Phasenverschiebung
** Phasenverzögerung: Lautsprechertechnik: Zeitlich verzögerte Wiedergabe einiger Frequenzen im Vergleich zu anderen Frequenzen. Kann für Effekte in Home-Cinema-Sound-Anlagen bewußt so eingestellt werden, ist aber im Normalfall unerwünscht. Das Gegenstück ist eine phasenlineare Wiedergabe, siehe Phasenlinearität. 
* Phasenlinearität: Wiedergabe ohne Phasenverzögerung. 

* [[ELENDES GEZAPPEL - Phasenverlauf einfach erklärt #REW|https://www.youtube.com/watch?v=zYf8fzJcA7A]]
* [[REW Home Theater Subwoofer And Main Speaker Time Alignment And New House Curve Method|https://www.youtube.com/watch?v=RNzcRTTZt5M]]
* [[ Does Phase Distortion/Shift Matter in Audio? (no*) |https://www.youtube.com/watch?v=moXaLMT_os4]]
* https://www.diyphysics.com/
the CX-J510 is a "Stereo Tuner Control Amplifier", basically just Tuner and input&control for all other parts of the system
and the M-J510 a separate stereo power amplifier

i've got these two devices from a relative, he owns them for a long time an they started to have problems. currently they don't work at all anymore, they are 20 years or older.

i suspect some capacitors are just old and voltage rails don't have a stable voltage anymore.
at a first look into the devices there already were some suspicious capacitors that might have leaked and some of the power rails were missing it seemed.

the devices come from a smoker household, so they had collected some sud over all the years. i cleaned the most obvious places with alcohol so it looks a bit nicer.

As the first step i ordered the caps from the CX-J510 that were near power supply components like the voltage regulators and were relevant for the power rails.
I replaced only the ones that looked bad, like some had corrosion, some looked like they leaked because they were a bit oily apart from the normal dust and smoking sud. Some even tested bad. If there was a bad one of one specific type/model i replaced all of them just to be sure.
I had some left over because i just ordered not just the ones that looked bad but also other power supply related caps.

When i wanted to test i was a bit confused that it didn't want to turn on, but after a bit of studying the manual and some testing i got it working.
The important clue was written on "5. How to check the product independently" (page 38 in the pdf; page 56 in the original) in the service manual below.
I followed the steps without the amplifier connected and it worked. I then tried with the amp connected and i only did step 1 (connecting the base of Q201 and Q202 to jumper lines) and it also worked fine.

The Control Amplifier requires the CD and Tape Decks to be connected to start up and Step 1 fakes them being connected.
Also the Control Amplifier needs the voltages from the Power Amplifier, so it too needs to be connected or you have to do the other steps.

I then went to testing the audio with the aux input. Audio was totally fine, but the "Function" button, for switching the inputs, still misbehaves. The owner told me about that already, but i guessed that that was due to the aging caps and the Chips inside not correctly registering the input due to power supply noise on the power lines.

So i disassembled the front of the control amplifier and drenched the button in IPA. I actuated the button a couple of times and let the IPA evaporate.
I also tried cleaning the display (a nice old vacuum fluorescent display (VFD))  and the plastic window in the front from inside with IPA. Both also had the smoking sud on them.

After that i partially reassembled the front to check it's function: it was better but still single presses registered double 50% to 1/3 of the time.
But cleaning the display and the windows did wonders, the display is clearly visible again! Before i had thought that the display is just old, because it's quite normal for VFDs to loose some of their power due to internal "wear", leaking of gases and such. But most of it just was smoking residue.

I disassembled the front again to measure the button. Its a roughly 6x6mm footprint (6,2x6,2mm to be exact) and 5mm (4,8mm) height. The size seemed pretty normal to me, but it only has 2 pins. I cant recall ever seeing these tactile, momentary push-buttons with two pins. But it turns out they are not that uncommon, it was pretty easy to find them on ebay and digikey.

When the replacement buttons arrived i desoldered the old button and compared the dimensions. They were pretty close, so it should work without problems. 
I soldered in the new button , cleaned off the flux residue, checked if i made any fingerprints on the display and reassembled the front again.

The new button is good and snappy (or tactile), it fits and functions perfectly. The difference of the snap between old and new is pretty noticeable side by side.

I'm happy it all works again and i told my relative who is also happy.


service manuals

* https://elektrotanya.com/pioneer_cx-j310_cxj410_cx-j510_arp2637_sm.pdf/download.html


stuff

* https://pdf1.alldatasheet.com/datasheet-pdf/view/38772/SANYO/2SB560.html
* https://pdf1.alldatasheet.net/datasheet-pdf/view/512108/ROHM/DTC143ZSA.html
GTC got this DJ Controller in for repair and asked me for help.
It's pretty beat up with bent faders and encoders, but the owner doesn't want these repaired.
The main problem is the owner used a random power supply which probably had a too high voltage and now the unit won't turn on.
The unit needs a 5V 3A power supply.

It's pretty well assembled, with a lot of screws, one has to be careful to keep track of them.

I started on the DSP/Mainboard were the power jack is located and started looking. I quickly could see a small SOT-3 package that was a bit charred. I tested it and it is shorted. After that i checked other components in the vicinity, but they seemed fine.

The charred component has the marking "TV" on the package but it's not easy to find something with that.
Luckily a service manual is available:

https://www.eserviceinfo.com/downloadsm/103501/Pioneer_pioneer%20ddj-sx%20rrv4382%20dj%20controller.html

The component is marked Q2 on the PCB and i could quickly find out that it's a RTR030P02 from Rohm Semiconductor.

The people at GTC ordered some new RTR030P02 and i soldered one in. After replacing the blown one i partially assembled the unit again for testing. I quickly made an adaptor to power the unit, because the barrel jack that Pioneer used has a pretty thick stem in the middle and the standard 5mm and 2.1mm or so don't fit.
I used a lab power supply for testing and set the current limiting a bit below 3A to be careful, also i made sure the voltage and polarity is correct before plugging it in.
After switching the dj controller on, it drew around 1,5A max, so well below the maximum.

We had no good setup to fully test the device, but it seems to have booted successfully.


wrote the same info 2 times, here is the older one:


<<<
The owner connected a random power supply to the dj controller and it didn't power on and won't power on again. It was propably a higher voltage one or wrong polarity.

The unit is designed for a 5V power supply 3,5A or so.

the controller was in overall bad shape, the fader for fading between channels and several encoder knobs were heavily bent. but it seems the owner only wants us to fix the power on issue.

The controller is inside pretty much just circuitboard. There are a lot of screws, so one should keep track of where they belong. you also have to be careful when disassembling, because there are some thin fpc ribbon cables that connect the PCBs, which can be easily torn and damaged.

All inputs & outputs as well as the power jack are on the DSP board, so i removed only that board. The top side of the board can be first inspected, because it has a metal support/shielding plate screwed onto the back. i could not spot anything on the front side.

after removing the metal plate i could quickly spot the slightly charred SOT Package. i checked other components (diodes, transistors, etc.) in the vicinity and around the power input/power circuitry, but could not find any obvios failed ones.

the failed component is numbered as Q2 on the silk screen, the marking on the component is only partially readable.

luckily it was easy to find a service manual for the device: https://www.eserviceinfo.com/downloadsm/103501/Pioneer_pioneer%20ddj-sx%20rrv4382%20dj%20controller.html

Q2 is marked as RTR030P02 in the schematics, which is a small mosfet by Rohm semiconductor that should match the usecase.

Due to that repair being a commission of a friend of mine, i don't know if i will also finish the repair when the replacements come in or if he repairs it.
<<<
* https://studioroosegaarde.net/project/grow
* https://youtu.be/VvWPT4VhKTk - plant sounds
* https://preciousplastic.com/
** https://community.preciousplastic.com/how-to/sun-concentrator-for-solar-plastic-melting
* https://wiki.opensourceecology.de/PET-Flaschen_zu_Schnur_verarbeiten
* plasic to 3d-printer filament
** recycling PET bottles
* [[Machining an injection mold for acrylic lenses|https://www.youtube.com/watch?v=JNXgHbBIRYQ]]
* see also [[plastic recycling]]
* see also [[bio-degradeable plastics and alternatives]]
* https://en.wikipedia.org/wiki/Spectrogram
** https://ccrma.stanford.edu/software/snd/
* https://en.wikipedia.org/wiki/Waterfall_plot
* https://en.wikipedia.org/wiki/Category:Plots_(graphics)
* charts, graphs and diagrams might not be that artsy?
** https://en.wikipedia.org/wiki/Category:Charts
* https://en.wikipedia.org/wiki/User:Wugapodes/Spectrogram
* DIY/open hardware spectroscope / spectrometer
** "Pink Floyd: Dark Side Of The Moon" album cover
* [[audio visualisation]]
* https://en.wikipedia.org/wiki/Spectral_music
* https://en.wikipedia.org/wiki/Waterfall_plot
* https://de.wikipedia.org/wiki/Spektrogramm
* https://stackoverflow.com/questions/29883344/how-can-i-make-waterfall-plots-in-matplotlib-and-python-2-7
** https://38.media.tumblr.com/tumblr_m7bk6wu3VW1qfjvexo1_500.gif
* modern art
* https://gizmodo.com/the-origin-of-joy-divisions-most-famous-album-cover-fi-1686589791
* https://www.esri.com/arcgis-blog/products/arcgis-pro/mapping/joy-plots-in-arcgis-pro/
* just the "normal" audio waveform
* https://www.pinterest.de/pin/80572280814569851/
* https://googlemapsmania.blogspot.com/2019/12/the-fabulous-joy-plot-map-maker.html
* https://gracefulspoon.com/blog/2009/03/06/iggy-wave/
* https://www.moma.org/collection/works/45257?classifications=any&date_begin=Pre-1850&date_end=2021&q=wave&utf8=%E2%9C%93&with_images=1
* https://blog.synthesizerwriter.com/2021/02/should-i-look-at-spectrum-or-waveform.html
* https://kitware.github.io/vtk-js/
* https://bokeh.org/
* https://matplotlib.org/
* https://plotly.com/
* https://python-graph-gallery.com/
* https://seaborn.pydata.org/
* https://d3js.org/
** https://www.d3-graph-gallery.com/index.html
* https://alternativlos.org/
* https://netzpolitik.org/podcast/
* https://logbuch-netzpolitik.de/
* https://0x0d.de/ - zeroday
* petzcast von volksverpetzer
* [[Logbuch:Freiheit|https://www.youtube.com/playlist?list=PLFvKRXhjAguwMBfh2nFWibm_U7rKsMkFz]]
* diverse bei der https://metaebene.me/podcasts/
* https://fyyd.de/
* https://malik.fm/m023-psychologisches-hacken-mit-linus-neumann/
* https://www.br.de/mediathek/podcast/der-mann-in-merkels-rechner-jagd-auf-putins-hacker/853
* https://minkorrekt.de/
* https://www.ardaudiothek.de/sendung/cui-bono-wtf-happened-to-ken-jebsen/89991466 - Cui Bono: WTF happened to Ken Jebsen?
* https://wissenschaftspodcasts.de/podcasts/
* wohnstand für Alle
** https://wohlstandfueralle.podigee.io/
** https://www.youtube.com/channel/UCRprqV4FxwrWQJbZ0VLFS_g
* https://www.spektrum.de/podcast/hoaxilla-hoaxilla-285-radikalisiert-durch-verschwoerungsmythen/1931338
* https://www.ardaudiothek.de/sendung/legion-hacking-anonymous/12015417/
software

* gpodder
* clementine
* Rythmbox

making one:

* https://podlove.org/ - wordpress plugin
* https://der-lautsprecher.de/ - informations
* https://das-sendezentrum.de/ - informations
* https://www.podigee.com/ - paid hosting
* https://ultraschall.fm/ - REAPER DAW Plugin for Podcasting
<<list-links "[all[current]tagging[]]">>

* https://media.ccc.de/v/32c3-7150-nach_bestem_wissen_und_gewissen_floskeln_in_der_politik

politische spektren sollten mindestens als 2d gesehen werden, obwohl das die realität dennoch vereinfacht, aber nicht so stark wie 1d.
https://de.wikipedia.org/wiki/Politisches_Spektrum
* https://www.politische-bildung.de
* https://www.bpb.de/
* https://media.ccc.de/search?p=Arne+Vogelgesang
* [[Umstrittene Polizeiaktionen: Zwei Männer, zwei Geschichten|https://www.youtube.com/watch?v=dgQ3pjdQW7I]]
* [[Die Polizei - "Bullenschweine" oder Freund und Helfer? RABIAT!|https://www.youtube.com/watch?v=MAsvflRwKKQ]]
* [[Jura Basics: Darf man Polizisten filmen? - Rechtsanwalt Christian Solmecke|https://www.youtube.com/watch?v=goEq9VuhNBU]]
* [[Leipzig: Polizei und linke Szene - unversöhnlich?|https://www.youtube.com/watch?v=Sjf-nioBK0I]]
* https://www.kritische-polizisten.de/
* [[Staatsgewalt: Wenn Polizisten ihre Macht missbrauchen|https://www.youtube.com/watch?v=BkE0NHAvnDU]]
* [[Staatsgewalt - wenn Polizisten zu Tätern werden|https://www.youtube.com/watch?v=-irAmWKhM8s]]
* Polizisten sind nicht fehlerfrei und machen auch fehler oder begehen ansichtlich auch straftaten im dienst, jedoch verhindert die polizei und die staatsanwaltschaft oft ermittlungen... korpsgeist, polizisten decken sich untereinander, einschüchterungen...
* es gibt wohl nur wenige übergriffe von polizisten die auch angezeigt werden, die meisten werden ohne verurteilung beendet oder es werden gar keine ermittlungen aufgenommen... die dunkelziffer an nicht verfolgten übergriffen, fehlern und straftaten bei der polizei ist wohl sehr groß
* Eckhard Groß, 63, pensionierter Hauptkommissar: 

<<<

"Ich weiß, dass wir bei brisanten Großdemos verdeckt agierende Beamte, die als taktische Provokateure, als vermummte Steinewerfer fungieren, unter die Demonstranten schleusen. Sie werfen auf Befehl Steine oder Flaschen in Richtung der Polizei, damit die dann mit der Räumung beginnen kann. Ich jedenfalls bin nicht Polizist geworden, um Demonstranten von irgendwelchen Straßen zu räumen oder von Bäumen runterzuholen. Ich will Gangster hinter Gitter bringen."
<<<

** https://www.abendblatt.de/hamburg/article107870345/Wir-werden-von-der-Politik-verheizt-Polizisten-erzaehlen.html
** https://www.ejz.de/lokales/lokales/den-knueppel-nie-zur-hand-genommen_50_107914478-28-.html
** https://taz.de/Polizeiinterne-Kritik-an-Provokateuren/!5133815/
** https://taz.de/Agents-Provocateurs-bei-S21-Demo/!5133691/
* https://www.tagesschau.de/investigativ/ndr-wdr/ksk-vergabepraxis-101.html
* https://www.tagesschau.de/inland/ksk-rechtsextremismus-mad-101.html - Etwa 50 rechtsextremistische Verdachtsfälle beim KSK
* https://www.mdr.de/nachrichten/sachsen/ermittlungen-generalstaatsanwaltschaft-verdacht-munitionsdiebstahl-landeskriminalamt-100.html
* die ganzen "einzelfälle" sind mittlerweile so viele das es fast normal scheint
* https://taz.de/Verdachtsfaelle-Rassismus-bei-der-Polizei/!5806075/
* https://twitter.com/vonDobrowolski
* https://kgp-sachsen.org/de/2022/12/29/polizeigewalt-ist-alltag-2/
* https://www.arte.tv/de/videos/106527-012-A/27-das-europaeische-magazin/
* https://itiotentreff.chat/
* HD15
** HD215
* Martin Audio B115
** http://hornplans.free.fr/b115.html
* Shearer horn
* X1 bandpass
* Cubo 12/15/18
* THAM 12/15...
* MTH-30
** https://www.freespeakerplans.com/plans/14-plans/basscab/24-mth-30
* TW Audio B15
* PAF212
** https://paforum.de/forum/index.php?thread/63732-2x12-1-4-forumsprojekt-paf212/
** http://hr-systems.biz/downloads/Kurzdatenblatt_PAF212.pdf
** http://hr-systems.biz/downloads/PAF-212-Dokumentation.pdf
like a soundboks, just more open.

* using a Qualcom [[Bluetooth Audio]] Module with aptx and integrated DSP?
* Euro container dimensions for easy fit in many transportation means
* [[cheap "chinese" amplifier board|cheap "chinese" amplifier boards]], Class-D
* similar battery packs
* speaker flange
* trolley-like weels and grip?
* good analog inputs, atleast xlr and 6,3mm jack combination socket (not just 3,5mm audio jack or nothing like soundboks 2 or 3)
the goal of this project is to build a portable, open and modular pa speaker system combining good features of different "competitors"

* merge with [[portable integrated pa speaker]]
* see [[efficient (12", 10" or 8") Tops/fullrange]]

box size:

# eurokiste: 40x60cm (30cm depth?)
# 1/2 eurokiste: 30x40cm (20cm depth?)
# ~~1/4 eurokiste: 20x30cm~~

speaker drivers:

* size
** ''15" = ~38.1cm''
*** just about still fits in box 1 (single)
** ''12" = ~30.48cm''
*** good for box 1 (single)
** ''10" = ~25.4cm''
*** good for box 1 (double) & box 2
** 8" = ~20.32cm
*** could be used for box 2 but maybe a bit small
** 6"
*** could be used double for box 2 but probably not that good
* cheap ones from china?
* thomann?
* coax drivers?
** B&C is expensive
** beyma is expensive
* neodymium (to reduce weight)

amps

* [[cheap "chinese" amplifier boards]] or atleast small class d IC solutions on a pcb
** Merus eximo amps aren't more efficient than other manufacturers amps
* Texas Instruments / Analog Devices / Infineon / NXP / ...

inputs/outputs: 

* XLR line input (maybe with 6.3mm jack)
* line output for chaining boxes
* bluetooth audio not really needed for professional use
* maybe audio over wifi?
* analog mixing? or just using DSP?
* analog mic inputs?
* additional 3.5mm jack/aux in
* optional wireless microphones
* maybe USB, playing, recording?

controlls/DSP/etc.

* maybe wifi?
* DSP
* no long booting times
* control panel like the thoman DSP series maybe? (LCD Panel and pushbutton-encoder)

power supply

* battery
** swapable 12V(4S) LiFePO4 battery
** integrated BMS with charge-indicator
** doesn't use heavy lead-acid batteries
** similar 20h playtime like the other
* external DC input, supports plugging in external lead batteries or hotswapping
* charger ist not included into the box
* internal SMPS for supplying the amp and the controll circuitry

inspiration:

* https://teufel.de/rockster-105575000#pdp-specifications
* [[Soundboks Internals (Teardown)]] (Soundboks 2 and "new")
** https://github.com/alexgorbatchev/boominator
* https://de-de.sennheiser.com/kabellose-lautsprecher-systeme-lsp-500-pro
* https://www.fohhn.com/de/produkte/fp-22-modular
* bass reflex
** see [[passive radiators]]
** size: 1/3 of the membrane area of the bass driver
** length is defined by the tuning
* [[The BEST Port Video EVER|https://www.youtube.com/watch?v=jN-E1dfMfO0]]
* [[The "Sealed vs. Ported" Debate|https://www.youtube.com/watch?v=S-AGcpEVUnQ]]
* [[Understanding Port Length, Box Volume, and Tuning Frequency.|https://www.youtube.com/watch?v=-yopTneS7g8]]
* [[How much does port area matter? - Tech Stuff Tuesday|https://www.youtube.com/watch?v=kFLC7G7FvCQ]]
* [[What is the best Port size?|https://www.youtube.com/watch?v=nxKkM4bXPFI]]
* [[Everything you need to know about PORT TUNING in under 3 minutes!|https://www.youtube.com/watch?v=U5BQdnagzW8]]
* [[Vented Box Modeling: T/S do's and don'ts and the occasional maybe.|https://www.youtube.com/watch?v=-2d-9MATHr0]]
* [[#LAUTSPRECHER​ #DIY​ Denkfehler Anfänger Teil 2 - Welche Fragen werden immer wieder gestellt?|https://www.youtube.com/watch?v=L1ltD6wW1qs]]
* [[#Bassreflex​ #Lautsprecher​ BASSWUNDER Bassreflex erklärt --- Funktion - Simulation - Messung|https://www.youtube.com/watch?v=trKJ0Yp6GMw]]
* [[How does a port work? Myths Busted! #subwoofer #port|https://www.youtube.com/watch?v=mHTGwEHCCRo]]
* variable resistors
* linear or logarithmic
* sliders or turn-knobs

cleaning:

* https://hackaday.com/2022/01/19/giving-vintage-synths-new-life-in-a-potentiometer-cleaning-showdown/
** https://www.keithrobertmurray.com/articles/potentiometer-cleaning-showdown.html

stuff

* https://en.wikipedia.org/wiki/Fade_(audio_engineering)#Fader
* https://www.allaboutcircuits.com/news/the-rise-of-low-cost-test-and-measurement-equipment/
* https://en.wikipedia.org/wiki/H-bridge
* [[motor controller / motor inverter]]
* [[inverter (Wechselrichter)]]
* https://github.com/OpenEMS/openems/blob/develop/README.md
* should do https://en.khanacademy.org/science/electrical-engineering
* https://learn.libre.solar/development/
* [[Leistungselektronik playlist by Elektrotechnik in 5 Minuten|https://www.youtube.com/playlist?list=PLjkreDBz1mhBdC8AnNin3kRGO2w-F_aa_]]
* [[Power Electronics (Full Course)|https://www.youtube.com/watch?v=A78yP8oApqk]]
* https://www.youtube.com/watch?v=6bicunweBAQ
* [[Electronic Basics #38: True, Reactive, Apparent & Deformed Power|https://www.youtube.com/watch?v=cxXmWZDwNEs]]
* power factor (Leistungsfaktor)
** https://de.wikipedia.org/wiki/Leistungsfaktor
** https://en.wikipedia.org/wiki/Power_factor
** https://de.aliexpress.com/item/4000210840139.html
** https://www.youtube.com/watch?v=Vb9-pbLdsfQ
* https://learn.openenergymonitor.org/electricity-monitoring/ac-power-theory/introduction
* https://www.allaboutcircuits.com/textbook/alternating-current/chpt-11/true-reactive-and-apparent-power/
* https://de.wikipedia.org/wiki/Spannungsqualit%C3%A4t
* https://de.wikipedia.org/wiki/EN_50160
* shunt or and matching meassuring circuit
* see [[measuring voltage]]
* see [[measuring current]]
* see [[multimeter]]
* https://www.tutonaut.de/test-voltcraft-energy-logger-4000/

Projects

* [[DIY ESP32 AC Power Meter (with Home Assistant/Automation Integration)|https://www.youtube.com/watch?v=PSzkaSy5lHY]]
* https://openenergymonitor.org/
** https://github.com/openenergymonitor
** https://github.com/openenergymonitor/Hardware
** https://emoncms.org/
* https://iotawatt.com/
* https://github.com/OpenEMS/openems/blob/develop/README.md
* https://www.sciencedirect.com/science/article/pii/S2468067216300293 - Open source IoT meter devices for smart and energy-efficient school buildings
* http://www.babelbee.org/
* netzsin.us - the website is no more it seems, bot the project is open but outdated
** https://github.com/netzsinus
** https://media.ccc.de/v/32c3-7323-wie_man_einen_blackout_verursacht
* https://circuitdigest.com/microcontroller-projects/esp32-power-meter-for-measuring-power-conversion-efficiency
* https://www.hackster.io/javidambra/energy-data-logger-3e2dba
* https://opensource.com/article/20/5/energy-monitoring
* https://hackaday.com/2019/07/27/building-a-safe-esp32-home-energy-monitor/
* https://hackaday.com/2016/05/25/meter-all-the-phases-three-phase-energy-meter-with-openwrt/
* https://hackaday.com/2018/08/03/measuring-energy-consumption/
* https://hackaday.com/tag/energy-monitor/
* [[ A Viewer Remade my Old Project! Is it any Good?|https://www.youtube.com/watch?v=suOimZ4gmQg]] - dc power logger

* [[#347​ Measuring Mains Voltage, Current, and Power for Home Automation|https://www.youtube.com/watch?v=Vb9-pbLdsfQ]]

* using shunts
** [[DIY Arduino power/energy meter|https://www.youtube.com/watch?v=_PKQdEUam6Y]]
* using INA219 
** [[Make your own Power Meter/Logger|https://www.youtube.com/watch?v=lrugreN2K4w]]

power quality

* https://www.ti.com/solution/power-quality-analyzer
* https://de.wikipedia.org/wiki/Spannungsqualit%C3%A4t
* https://en.wikipedia.org/wiki/Electric_power_quality


stuff

* shelly 3em is pretty good, but not open - https://cweiske.de/tagebuch/shelly-open-source.htm
* https://www.youtube.com/watch?v=RlSCe9xaUPE
insights in the working of batterypacks / [["smart"-batteries]]

[[reusing huawei smartphone batteries]]

* made a pcb desisng using ~EasyEDA (because i wasn't as familiar with kicad)
* ordered the pcb's at jlcpcb
* orderes the BM25 connectors from LCSC

getting data from all cells:

* multiplexing (shift register)
** https://www.instructables.com/Multiplexing-with-Arduino-and-the-74HC595/
** https://www.elektronik-kompendium.de/sites/kom/0211292.htm
** https://forum.arduino.cc/index.php?topic=640382.0
* I2C - I/O expander
** http://digistump.com/products/8
* projects with non-commercial licences like CC-NC are not open source software or open hardware
* https://mifactori.de/non-commercial-is-not-open-source/
* https://cccc.ncte.org/cccc/committees/ip/2009developments/openeducation
* https://nbn.org.uk/news/guidance-definition-non-commercial-use/ - some special stuff to the platform, but some interresting bits
* https://wiki.creativecommons.org/wiki/Defining_Noncommercial - not a legal definition, just a study about the perception of people

educational purposes are excluded

one big problem is also that NC licenses exclude educational purposes... that stands in contrary to the believes of the people using NC licenses, they want to make it open for education, but unknowingly restrict their creations in that regard

!! non-commercial does not mean non-profit

NC is often used for hardware... but for hardware you need to buy parts... if someone then does a workshop that is for free, the participants just have to pay for the parts (because its pretty easy to source them in bulk than everyone has to bring them themselves), that paying for the parts instantly makes the workshop commercial, even though the worksho was not for-profit
* EASE - industry standard, fee for users, manufacturers pay to get their speakers modelled
** https://audac.eu/software/d/ease-focus-3
** [[ EASE Focus 3 Tutorial - Free Professional Sound System Prediction Software|https://www.youtube.com/watch?v=La_7mnu3Hr0]]
** [[ (ENG) Webinar EASE Focus 3 - Part 1- Acoustic Prediction and System Design |https://www.youtube.com/watch?v=UW0cGUyHuPI]]
*** [[ (ENG) Webinar EASE Focus 3 - Part 2- Acoustic Prediction and System Design |https://www.youtube.com/watch?v=ZNg2rmtKUDw]]
* https://usa.yamaha.com/products/proaudio/software/ys3/index.html
* [[Lab.Gruppen]]
* https://ramaudio.com/
* linear research
* https://www.youtube.com/watch?v=XBF362YzvN8
* https://audiocore.wpengine.com/?
* powersoft
* AEQ?
* https://www.linea-research.com/
* https://www.mc2-audio.co.uk/
* https://hoellstern.com/
* ~~zoundhouse~~ - no option anymore, seem to be a bunch of conspiracy theorists
* https://www.musikhaus-korn.de/
* https://www.thomann.de/
* https://gebrauchte-veranstaltungstechnik.de/
* https://www.huss-licht-ton.de/
* https://www.just-sound.de/
* https://www.musicstore.de
* https://www.rockshop.de/
* https://www.lautsprecherteile.de/
* https://www.fat-germany.de/
* https://www.pa-world.de/
* https://www.jobst-audioshop.de/
* https://www.steinigke.de/
* https://www.soundland.de/
* https://www.recordcase.de/
* https://www.deejayladen.de/
* https://www.steinigke.de/
* https://pa-shop.de/
this list is not ordered in any way and i'm not an expert... please check for yourself if the hardware is suitable for you.

see also [[professional amp manufacturers]]


* https://ad-systems.com/
* Allen & Heath
* https://www.audio-technica.com/
* https://www.audio-zenit.de/

* beyerdynamic

* crown
* https://codaaudio.com/

* https://www.danleysoundlabs.com/
* https://www.dasaudio.com/
* [[d&b audiotechnik|https://www.dbaudio.com/]]
** https://www.dbaudio.com/global/de/produkte/filter/heritage
* https://www.dbtechnologies.com/
* https://dynacord.com/

* EAW

* https://www.fohhn.com/
* www.foeoen.de/
* http://www.funktion-one.com/

* https://www.gae.de/

* https://www.harmonic-design.com/de/
* https://hoellstern.com/

* https://www.inmusicbrands.com/ - multible brands
** https://www.altoprofessional.com/

* https://jblpro.com/ ?

* https://www.kling-freitag.de/
* https://kme-sound.com/
* http://www.kmt-sound.de/
* [[KV2 Audio|https://www.kv2audio.com/]]

* https://www.l-acoustics.com/
* lambda labs - supposedly bad marketing and stolen patents

* [[Martin Audio|https://martin-audio.com/]]
* [[Meyer Sound|https://meyersound.com/]]
* https://www.mm-acoustics.de/

* musictribe - buying many companies building a monopoly
** Behringer - more or less, a lot of cheap stuff
** Klark Teknik
** Lab.Gruppen
** Turbosound (old stuff was better; pre F1/F1-licenced)
** Midas

* [[Nexo|https://www.nexo-sa.com/]]
* https://www.novacoustic.de/index.html

* https://ohm.co.uk/

* PAS Audio - i'm told they are unexpensive but great amps, low distortion (class ab or so) and reliable
* http://www.paudiothailand.com/srs/
* https://pl-audio.de/
* https://www.powersoft.com/en/
* https://proaudio-technology.com/
** system amps from https://hoellstern.com/
* https://www.pronomic.eu/
* PSE Audio - http://www.pse-audio.com/de/

* QSC
* [[RCF|https://www.rcf.it/]]

* [[Seeburg|https://www.seeburg.net/]]
* https://www.solidstatelogic.com/
* https://www.solton-acoustic.de/
* https://www.soundgear.co.uk/index.html
* https://www.studt-akustik.de/

* https://www.twaudio.de/en/

* https://voidacoustics.com/
** https://voidacoustics.de/
* https://www.voice-acoustic.de/

* https://westlab-audio.de/

lists

* https://audioprof.thomann.de/produkte/
* [[#5 - PV Anlage - Generatoranschlusskasten (GAK-light) - Überspannungsschutz - Absicherung DC-UV|https://www.youtube.com/watch?v=geYlJ_ltIec]]
* https://www.reddit.com/r/SoundSystem/comments/185bg6x/little_experimental_setup_with_a_new_top_im/
* https://www.reddit.com/r/SoundSystem/comments/17ozsl0/variable_tilt_boards_resonant_sounds/
* [[syntripp]]
* paraflex tops
* coax 12" tops
* https://www.reddit.com/r/SoundSystem/comments/1afqi0r/syntripp_or_diyrm_meh/
** https://www.diyaudio.com/community/threads/lightweight-meh-based-on-scott-hinson-diyrm-design.398649/
*** https://drive.google.com/file/d/1nEYlXJosnRQvl0WQ-OPHkClRPTad3WSk/view
* https://www.diyaudio.com/community/threads/2x12-and-1-4-coax-cd-synergy.373100/
* https://soundforums.net/community/threads/new-diy-mid-high-90deg-aka-pm90.11601/
* https://soundforums.net/community/threads/60-degree-diy-mid-hi-aka-pm60.12390/
* https://forum.speakerplans.com/2x10-vented-horn-idea_topic100997.html
* https://forum.speakerplans.com/2x10-vented-horn-idea_topic100997_page7.html
* audio+engineering
* sound engineer
* ''https://www.animations.physics.unsw.edu.au/waves-sound/oscillations/index.html''
* https://entertainment.howstuffworks.com/live-sound-engineering.htm
* https://duckduckgo.com/?t=ffab&q=audio+engineering+streaming&ia=web
* https://www.aes.org/
* https://www.aes.org/standards/
* https://www.aes.org/publications/
* https://secure.aes.org/members/insidetrack/201808/
* https://de.wikipedia.org/wiki/Liste_von_Audio-Fachbegriffen
* https://de.wikipedia.org/wiki/Schallpegel
* https://de.wikipedia.org/wiki/Schalldruckpegel
* [[An Introduction to Acoustics ~~ S.W. Rienstra   &   A. Hirschberg ~~ Eindhoven University of Technology|https://www.win.tue.nl/~sjoerdr/papers/boek.pdf]]
* https://en.wikipedia.org/wiki/Dynamic_range_compression
* [[https://de.wikipedia.org/wiki/Kompressor_(Signalverarbeitung)]]
* http://myhometheater.homestead.com/splcalculator.html
* pa calculate app (rcf)
* http://medi.uni-oldenburg.de/download/docs/lehre/kollm_phystechmed_akustik/aku2.pdf
* https://www.spektrum.de/lexikon/physik/akustik/319
* https://www.leifiphysik.de/akustik
* http://www.hifi-forum.de/viewthread-42-15.html
* http://www.hifi-forum.de/viewthread-42-89.html
* http://www.hifi-forum.de/viewthread-42-20.html
* http://www.hifi-forum.de/viewthread-42-7.html
* http://www.hifi-forum.de/viewthread-42-54.html#1
* Über den Wirkungsgrad von passiven Lautsprechern: http://www.hifi-forum.de/viewthread-42-11.html
* Formel: Schalldruck eines Lautsprechers bei einer Verstärkerleistung berechnen: http://www.hifi-forum.de/viewthread-42-61.html
* Was ist eigentlich PA?: http://www.hifi-forum.de/viewthread-42-8.html
* http://www.hifi-forum.de/viewthread-42-21.html
* Was sagt mir die Leistungsangabe eines Verstärkers, was ist RMS etc.?: http://www.hifi-forum.de/viewthread-42-10.html
* Impedanz und Widerstand: der kleine Unterschied: http://www.hifi-forum.de/viewthread-42-23.html
* Workshops: http://www.hifi-forum.de/viewthread-239-11.html
** http://www.mix4munich.de/portal.htm
** http://www.mix4munich.de/live_gig_6.htm
** http://www.mix4munich.de/stimme.htm
** http://www.mix4munich.de/workshop_soundcheck.htm
** http://www.mix4munich.de/gates.htm
** http://www.mix4munich.de/kompressoren.htm
* Begriffe der PA-Technik: http://www.hifi-forum.de/viewthread-239-8.html
* Lexikon (zu PA Themen): http://www.hifi-forum.de/viewforum-239.html
* https://www.hifi-selbstbau.de/grundlagen-mainmenu-35
* http://www.hifi-forum.de/viewthread-239-2.html
* http://www.hifi-forum.de/viewthread-239-5.html
** http://www.jobst-audio.de/sonstigestut/159-erlaeuterungen-zu-pegel-dezibel-und-leistungsangaben
* WinISD - Einführung und Chassis-Datenbank: http://www.hifi-forum.de/viewthread-239-6.html
* Mischpult - wofür ist was?: http://www.hifi-forum.de/viewthread-239-9.html
* https://sound-au.com/articles.htm
* https://en.khanacademy.org/search?page_search_query=sound%20waves
* https://www.khanacademy.org/science/high-school-physics/x2a2d643227022488:waves
* https://www.youtube.com/channel/UCbDZO8Vh_md52hec9jp-Piw
* siehe [[Phasenwinkel, Phase, Schwingungen]]
* siehe [[Audio Fachbegriffe]]
* https://ocw.mit.edu/search/ocwsearch.htm?q=acoustics
* https://katalog.slub-dresden.de/?tx_find_find%5B__referrer%5D%5B%40extension%5D=Find&tx_find_find%5B__referrer%5D%5B%40vendor%5D=Subugoe&tx_find_find%5B__referrer%5D%5B%40controller%5D=Search&tx_find_find%5B__referrer%5D%5B%40action%5D=index&tx_find_find%5B__referrer%5D%5Barguments%5D=YToxOntzOjE6InEiO2E6MTp7czo1OiJ0b3BpYyI7czoxMDoiV2F2ZWd1aWRlcyI7fX0%3D565529389a5d769e4003f7dd512dcb2770f15ea4&tx_find_find%5B__referrer%5D%5B%40request%5D=a%3A4%3A%7Bs%3A10%3A%22%40extension%22%3Bs%3A4%3A%22Find%22%3Bs%3A11%3A%22%40controller%22%3Bs%3A6%3A%22Search%22%3Bs%3A7%3A%22%40action%22%3Bs%3A5%3A%22index%22%3Bs%3A7%3A%22%40vendor%22%3Bs%3A7%3A%22Subugoe%22%3B%7D047f3715dc7dc724d9c3866ff69a6b53a1b03d8b&tx_find_find%5B__trustedProperties%5D=a%3A1%3A%7Bs%3A1%3A%22q%22%3Ba%3A1%3A%7Bs%3A7%3A%22default%22%3Bi%3A1%3B%7D%7D6b76be83b7db9370ad51d5ea02e98dc6e757fbe2&tx_find_find%5Bq%5D%5Btopic%5D=Akustik#detail
* quarter wavelenth
* http://exertion.pbworks.com/w/page/12085531/Resonances
* https://www.academia.edu/Documents/in/Acoustics
* https://www.journals.elsevier.com/applied-acoustics/
** https://www.journals.elsevier.com/applied-acoustics/open-access-articles
* https://www.youtube.com/playlist?list=PL_onPhFCkVQjTooIlcBjXyZsHMlQw17rA
* https://medi.uni-oldenburg.de/download/docs/lehre/kollm_phystechmed_akustik/aku2.pdf
* Grundlagen Technische Akustik
* http://hyperphysics.phy-astr.gsu.edu/hbase/Audio/imped.html
* https://www.comsol.com/blogs/how-to-perform-a-nonlinear-distortion-analysis-of-a-loudspeaker-driver/
* https://en.wikipedia.org/wiki/Category:Loudspeaker_technology
* https://education.lenardaudio.com/en/
* https://education.lenardaudio.com/en/07_horns_3.html
* https://soundlab.cs.princeton.edu/
* https://projekter.aau.dk/projekter/files/9878159/Advanced_Loudspeaker_Modelling_and_Crossover_Network_Optimization.pdf
* https://engineering.purdue.edu/ece103/LectureNotes/SRS_Speaker_and_Enclosure_Intro.pdf
* https://sound-au.com/articles.htm
* https://asa.scitation.org/
* speakerscott youtube
* [[Audio Myths Workshop|https://www.youtube.com/watch?v=BYTlN6wjcvQ]]
* [[speaker arrangement/set-ups/positioning]]
* https://de.wikipedia.org/wiki/Kategorie:Beschallungstechnik
* https://de.wikipedia.org/wiki/Bewerteter_Schalldruckpegel
* https://de.wikipedia.org/wiki/Kategorie:Psychoakustik
* https://de.wikipedia.org/wiki/Kategorie:Technische_Akustik
* https://en.wikipedia.org/wiki/Category:Acoustics
** https://en.wikipedia.org/wiki/Category:Acoustic_equations
** https://en.wikipedia.org/wiki/Category:Acoustical_engineers
** https://en.wikipedia.org/wiki/Category:Acoustical_Society_of_America
** https://en.wikipedia.org/wiki/Category:Acousticians
** https://en.wikipedia.org/wiki/Category:Acoustics_software
** https://en.wikipedia.org/wiki/Category:Frequency
*** https://en.wikipedia.org/wiki/Category:Filter_frequency_response
*** https://en.wikipedia.org/wiki/Category:Frequency_mixers
*** https://en.wikipedia.org/wiki/Category:Frequency-domain_analysis
*** https://en.wikipedia.org/wiki/Category:Units_of_frequency
** https://en.wikipedia.org/wiki/Category:Acoustics_journals
** https://en.wikipedia.org/wiki/Category:Acoustic_measurement
*** https://en.wikipedia.org/wiki/Category:Sound_measurements
** https://en.wikipedia.org/wiki/Category:Psychoacoustics
** https://en.wikipedia.org/wiki/Category:Sound
*** https://en.wikipedia.org/wiki/Category:Noise
*** https://en.wikipedia.org/wiki/Category:Sound_production
**** https://en.wikipedia.org/wiki/Category:Linux_audio_video-related_software
**** https://en.wikipedia.org/wiki/Category:Sound_recording
**** https://en.wikipedia.org/wiki/Category:Sound_production_technology
*** https://en.wikipedia.org/wiki/Category:Silence
*** https://en.wikipedia.org/wiki/Category:Stereophonic_sound
*** https://en.wikipedia.org/wiki/Category:Sound_technology
**** https://en.wikipedia.org/wiki/Category:Graphical_sound
** https://en.wikipedia.org/wiki/Category:Units_of_sound
* https://de.wikipedia.org/wiki/Dynamik_(Musik)
* https://de.wikipedia.org/wiki/Dynamikumfang
* https://en.wikipedia.org/wiki/Category:Audio_Engineering_Society_standards
* https://www.youtube.com/@AudioUniversity
** [[ DI Box 101: Active vs Passive - Which is Best for Your Setup? |https://www.youtube.com/watch?v=zQ56d_IgeSo]]
* https://www.youtube.com/@MichaelCurtisAudio
* [[Optimize Gain Structure - Pro Audio (Public)|https://www.youtube.com/watch?v=-RXlnVDVLrc]]
* [[Sound System Tuning By Ear|https://www.youtube.com/watch?v=1IbvhgfGEhU]]


books

* https://paforum.de/forum/index.php?thread/1417-handbuch-der-pa-technik-contra-das-pa-handbuch/
* https://www.thomann.de/de/pa_fachbuecher.html
Lack / Lackieren

* Warnex / Tuff Cab
* Strukturrolle
* UBS Pistole zum sprühen
* https://www.lautsprecherteile.de/
* https://en.wikipedia.org/wiki/Programmable_unijunction_transistor
* https://en.wikipedia.org/wiki/Programmable_unijunction_transistor
* https://northridgefix.com/product/high-speed-eeprom-bios-efi-spi-programmer-supports-24-25-93-95/ - is just rebranded, can probably be found for cheap online
* JTAG programmer/adapter
* serial rs232/UART adapters
<<list-links "[all[current]tagging[]]">>
<<list-links "[all[current]tagging[]]">>
save aus fff wiki - https://wiki.fridaysforfuture.is/wiki/Projektion_an_Geb%C3%A4ude

<<<
Um politische Aussagen und Forderungen lesbar darzustellen kann man diese u.A. großflächig an Gebäudewände projezieren.
Beispiele hierfür sind Aktionen verschiedener (politischer) Gruppen und Initiativen, darunter Netzpolitik.Org<ref>https://netzpolitik.org/2019/wir-haben-da-mal-einen-geburtstagswunsch-aufs-kanzleramt-projiziert/</ref> und Greenpeace<ref>https://www.greenpeace.de/presse/presseerklaerungen/projektion-auf-den-petersdom-planet-earth-first</ref><ref>https://www.greenpeace.de/presse/presseerklaerungen/greenpeace-projektion-auf-tschernobyl-sarkophag</ref><ref>https://www.greenpeace.de/themen/atomkraft/projektion-den-letzten-atomkraftwerken</ref>.

Hierfür gibt es verschiendene Möglichkeiten:

"Klassische" Beamer sind u.U. sehr ineffizient und es bedarf oft großer, teurer Geräte aus dem professionellen bereich um auf der höheren distanz als in geschlossenen räumen und bei dem vonhandenem Umgebungslicht, auch ein gut erkennbares Bild zu liefern.

Eine effizientere und billigere Variante wären vlt. Laser aus der Veranstaltungstechnik. Laser sind aber immer mit Vorsicht zu handhaben [https://www.production-partner.de/story/the-regels-sind-the-regels/][https://eventfaq.de/laser/].

Solche "Laserprojektoren" arbeiten nicht wie herkömmliche Beamer, sondern mit einem einzelnen Lichtstrahl, der von Schrittmotoren oder [[wikipedia:de:Galvanometer#Galvanometerantriebe|Galvanometern]] und Spiegeln abgelenkt wird. Dadurch haben diese Projektoren keine klassische Auflösung, sondern kpps (tausend Punkte pro Sekunde). kpps steht für die Anzahl, der einzelnen Punkte, die pro Sekunde angesteuert werden können. Jede Richtungsänderung von dem Lichtstrahl ist ein Punkt.


[[Kategorie:Technik-IT Support]][[Kategorie:Aktionen & Aktivismus]]

<<<
might serve as examples for own developments

* http://www.randteam.de/Products.html
* http://www.randteam.de/VACS/Index.html
* http://www.randteam.de/AKABAK3/Index.html
* https://gedlee.azurewebsites.net/Application%20Files/Software.aspx
* https://www.qsc.com/systems/products/loudspeakers/loudspeaker-modeling-software/
* https://www.trueaudio.com/win_abt1.htm
* https://www.stonessoundstudio.com.au/stone/leap_4.htm
* madrix - https://www.madrix.com/
* touch designer
* resolume

* https://www.digikey.com/en/articles/protecting-inputs-in-digital-electronics
* see 
* https://www.pcbway.com/rapid-prototyping/ - PCB, CNC, 3D Printing, sheet metal, laser cutting
* https://www.multi-circuit-boards.eu/en/index.html - PCB, toroidal transformers
* [[Diagnosing a faulty PSU|https://www.youtube.com/watch?v=MZDX-1Arg7o]]
* https://publiccode.eu/

public authorities need software too, sometimes special-need software. but tax money is the money from all people and should be handled carefully, not to be wasted. also, ressources bought from taxpayers money are kinda owned by all taxpayers, so they should be able to use the software as well.

humanity had the biggest accomblishements through sharing knowledge and ressources, like the ISS. Even the internet relies mostly on open source software.

one doesn't have to reinvent the wheel, we can share it and the knowledge to build it.

it has some benefits:

* contributes to an open society
* might save development time and money, because there might be allready similar software that can be adapted or other people are willing to contribute to the open source project as well
* might save others money and time, because they can use the software for free and only have to add some features or to tweak something
* others, who use the software, can contribute too and can add functions which benefit all
* security might improve, because much more people can read the code and find errors
* it doesn't really add costs, because even if nobody except the one authority cares about the project, it's pretty much the same
* interoperability with other authorities or other software might improve, because APIs and similar can be implemented much more easily

there are societies like the Chaos Computer Club who like and probably would help authorieties transitioning to open source.
* https://f-droid.org/de/packages/cx.mccormick.pddroidparty/
* https://f-droid.org/de/packages/org.sensors2.pd/
type of high power dc-dc converter/[[SMPS|switched mode power supply (SMPS)]]

uses:

* [[inverter (Wechselrichter)]]
* (car) [[audio amplifiers]]
** https://web.archive.org/web/20190717131310/https://sound.whsites.net/project89.htm - Switchmode Power Supply For Car Audio

the naming seems to be very unclear/inconsistent and is pretty confusing... i find circuits for similar uses under different names

* english:
** push-pull-converter
** Full Bridge Converters
* german:
** Flusswandler
** Gegentaktwandler
** Gegentaktflusswandler

info

* https://en.wikipedia.org/wiki/Push%E2%80%93pull_converter
* https://de.wikipedia.org/wiki/Gegentaktflusswandler
** //"Speziell der Gegentaktflusswandler mit Vollbrückenansteuerung eignet sich für Gleichspannungswandler der höheren Leistungsklasse bis mehrere Kilowatt."//
** //""Umgekehrt findet der Gegentaktflusswandler auch bei Wechselrichtern höherer Leistung Anwendung. Dabei transformiert der Wandler die Kleingleichspannung (beispielsweise 12 V einer Starterbatterie) in die für den Wechselrichter benötigte Zwischenkreisspannung von etwa 325 V, welche anschließend mittels Hochvoltbrücke trapezförmig oder sinusförmig zu Netzspannung moduliert wird.""//
* push-pull converter
** https://www.quora.com/What-is-the-working-principle-of-a-push-pull-converter
** https://circuitdigest.com/tutorial/how-to-design-a-push-pull-converter
** [[Halbbrücken Gegentaktwandler single ended push-pull converter|https://www.youtube.com/watch?v=oCOKR4sKGtg]]
** [[Vollbrücke Gegentaktwandler Funktionsweise|https://www.youtube.com/watch?v=B7Kibpfnyts]]
** [[Vollbrücke Querkurzschluss Gegentaktwandler|https://www.youtube.com/watch?v=3L2pqRgbNZo]]
** https://u.dianyuan.com/bbs/u/71/2714871227765266.pdf - SWITCHING POWER SUPPLY DESIGN: LM5030 PUSH-PULL CONVERTER
* [[LE4_6h DC/DC Wandler - Eintaktflusswandler - Zeitverläufe - Simulation LTSpice|https://www.youtube.com/watch?v=iXdYjXd_UJA]]
* http://schmidt-walter-schaltnetzteile.de/smps/smps.html
* https://www.joretronik.de/Web_NT_Buch/Kap8_2/Kapitel8_2.html#8.3
* full bridge converter
** https://www.rfwireless-world.com/Terminology/Advantages-and-Disadvantages-of-Full-bridge-converter.html
** https://www.ti.com/lit/ug/tidu248/tidu248.pdf - Phase-Shifted Full Bridge DC/DC Power Converter Design Guide
** https://www.edn.com/isolated-full-bridge-converters/
* the english wikipedia article has an external link to the "solar freaks" forum which is just a archived copy where the file is not downloadable, here are still functioning options:
** https://web.archive.org/web/20170208022848/http://www.solarfreaks.com/dc-dc-converter-tutorial-t149.html
** http://electronique.marcel.free.fr/VAE/Docs/OT1%20Controleur/Conv%20DC-DC/National/cascade_tutorial_0710.pdf
* there are some special designs wich are meant to funktion in both directions, DC to AC and AC to DC. the gaol seems to simplify design and reduce component count and maybe also the losses can be reduced...
** [[2-kW isolated bidirectional DC-DC converter reference design for UPS|https://www.youtube.com/watch?v=CYb6ZJCIyOs]]
** https://www.ti.com/tool/TIDM-BIDIR-400-12#1
* EEVBlog
** https://www.eevblog.com/forum/projects/48vdc-to-160vdc-(for-inverter)/
** https://www.eevblog.com/forum/projects/how-is-this-topologycircuit-called-(solar-inverter)/
** https://www.eevblog.com/forum/projects/push-pull-transformer-driver-design/
* https://web.wpi.edu/Pubs/E-project/Available/E-project-042507-151144/unrestricted/High_Voltage_DC_Converter.pdf - High Voltage DC-DC Converter


projects

* https://github.com/twischer/PushPullConverter
* https://hackaday.io/project/158057-ts50-true-sine-inverter
* https://hackaday.io/project/159575-ts350-true-sine-inverter
* https://hackaday.io/project/10079-power-inverter-google-little-box
* https://www.ijstr.org/final-print/may2020/Soft-Switched-Current-Fed-Modified-Push-Pull-Converter-For-Pv-Application.pdf
* https://www.researchgate.net/publication/266522114_DESIGN_PROCEDURE_OF_A_PUSH_PULL_CURRENT-FED_DC-DC_CONVERTER


stuff

* https://www.cettechnology.com/push-pull-switching-transformer-design/
* https://www.analog.com/en/technical-articles/high-frequency-push-pull-dc-dc-converter.html - design only based on their own chips, proprietary
* uses PWM for switching, not as efficient but simpler

projects:

* [[PCBs from JLCPCB: Solar Charge Controller PWM5 Femto V2|https://www.youtube.com/watch?v=1Vl_6E2rzts]]
* [[PWM5 Femto (V2) Solar Charge Controller Construction|https://www.youtube.com/watch?v=6d-3BBzHFhc]]
* [[It Works! Solar Charge Controller - PWM5 Femto |https://www.youtube.com/watch?v=XdbFaPnTGF4]]
* https://www.instructables.com/DIY-Arduino-PWM5-Solar-Charge-Controller-PCB-Files/
* https://github.com/TheDIYGuy999/PWM5
* https://docs.python-guide.org/
* https://www.python.org/dev/peps/pep-0008/
* https://www.python.org/dev/peps/pep-0020/
* https://www.diegor.it/2017/06/15/the-must-read-pythons-peps/
* https://realpython.com/
* https://www.fullstackpython.com/
* https://github.com/vinta/awesome-python
* https://realpython.com/async-io-python/
* database
** peewee
** sqlalchemy
* https://wiki.python.org/moin/
* https://github.com/Tbruno25/canopy
* PyQt5
* pyqtgraph
* 
bought 2 used QSC PL1.8 to repair them.

* https://www.qsc.com/resource-files/productresources/amp/discontinued/powerlight/q_amp_powerlight_series_specs.pdf
* https://elektrotanya.com/qsc_powerlight_1.0_1.4_1.8_2.0_3.4_4.0_sch.pdf/download.html
* https://www.eserviceinfo.com/downloadsm/50764/QSC_PL1.8.html

!! problems

* one of them is overheating
** "Bei der einen sind die mosfets von den stages offen,  deswegen wird die heiß."
** probably the mosfets switching high or low power dead
* the other one has a channel with low volume
** "Bei der anderen ist garantiert ein op amp Fratze da genau 6db fehlen."
** likely opamp dead
** also caps of one particular type/manufacturer are dead
* some damaged screws, maybe due to crossthreading

!! Opamps

are NE5532 from Philips/NXP, but they aren't manufactured by Phillips/NXP anymore and thus are sold out everywhere.

the supplier i wanted to order from had NE5532P and NE5532AP from TI. both have the same datasheet, so the difference was confusing, but it seems that the version with the A postfix is a guaranteed low noise option

* https://www.ti.com/product/NE5532
* https://www.ti.com/product/NE5532A
* https://www.ti.com/lit/ds/symlink/ne5532.pdf - Datasheet
* https://pdf1.alldatasheet.com/datasheet-pdf/view/17974/PHILIPS/NE5532N.html - NPX/Philips datasheet
* https://en.wikipedia.org/wiki/NE5532
* https://e2e.ti.com/support/amplifiers-group/amplifiers/f/amplifiers-forum/344/what-is-different-between-ne5532ap-and-ne5532p
* https://forums.stevehoffman.tv/threads/the-many-versions-of-the-ne5532-and-im-confused.350248/

I got a couple of both because they seem to be pretty popular and it doesn't hurt to have some opamps around.

the opamps are probably not the problem and instead the dead electrolytic caps are.

!! capacitors

original ones are meritek vent 470uF 16V -40+85°C.
these can be found in both amps, only in one of them they seem to be damaged, but i'll change them in both amps.

i replaced them with 470uF 16V Rubycon ZLH series rated up to 105°C which should last a while.

I replaced these caps first in the amp with one quieter channel, after the replacement both channels sounded like the same volume. I have to check with a meassurement mic or so to have solid data, but the new caps might have already fixed it.

!! screws

* http://www.gewinde-norm.de/zollgewinde-grob-unc-zollgewinde.htm
* https://www.gewinde-normen.de/steigung.html
* friends suggested i check at Hornbach
* screws are slightly bigger than M4 and have slightly different thread pitch it seems
** M4 0.7mm pitch and the original ones more like 0.8mm
** UNF 8-36 is very similar to M4 but probably doesn't match
** UNC #8-32 looks like a good match, 0,794mm thread and 4,16mm diameter
** 7.5mm long, approx. 5/16"
** the screws are two types: countersunk and serrated round-head, both phillips drive
* i finally ordered some at ebay
** the original countersunk screws look like they have a steeper ankle so the head is more flat
** the new round-head screws don't have the serrations
** both are allen key, not phillips

its fucking hard to find the right screws in europe. can#t find them on ebay, can't find them on aliexpress.

maybe i can find some [[mcmaster carr alternative for europe]].

maybe it's an option to buy plain steel screws (not stainless) and blue them:

* https://en.wikipedia.org/wiki/Bluing_(steel)
* https://de.wikipedia.org/wiki/Br%C3%BCnieren

!! shorted power rail switching mosfets

QSC schematics and service manuals say:

* Q501, 502, 601, 602 are switching FETs, QSC P/N QD-000031-QD, 125W, 60V minimum, on-resistance 0.030 Ohms max.
* QD-000031-QD : FET NChan TO220 60V 50A : Q501, 502, Q601, 602
* TMOS FET (TMOS Power Field Effect Transistor) IRFZ44

check which fets in amp
failing electrolytic caps (elcos, Elkos) are a common failure mode of consumer electronics.

because they contain liquid which dries out they should be 105°C rated. lower ratings like 85°C are often not as good.

here are some good quality brands for replacing:

* Nippon Chemi-Con
* Nichicon
* Rubycon
* Cornell Dubilier
* Panasonic

other brands:

* https://caps.wiki/wiki/Capacitor_Brands
* https://www.tomshardware.com/reviews/power-supplies-101,4193-5.html
* https://eevblog.com/forum/chat/capacitor-brands/

when replacing dead caps i first try to find the datasheet to the original caps in order to see if they have a low esr or other special ratings that might be important. But most times cheap caps from some uncommon no-name brands are used and you can't find one, so you have to guess. In switching power supply circuitry the caps are almost always low esr caps. But low impedance might also be important in some applications.

when searching for a replacement i not only filter for the obvious ratings of voltage and capacity, but also filter for the good brands and filter for brands with high lifetime and temperature ratings. Then i also often exclude the worst esr ratings and fiddle around with all of the ratings in some way that seems good to get to a selection that is not overwhelming. then i choose a model of cap that seems good.

stuff

* https://forum.digikey.com/t/calculating-capacitor-esr-from-tan/2633
* [[Uncomfortable Conversations with a Black Man|https://www.youtube.com/watch?v=h8jUA7JBkF4]]
bought a 6U rack bag used for 30€ for my digital mixer, microphones and stuff. i want do modify it to make it more usable for me.


* it has rack strips on one side but rack strips on the other side for stuff would be great
* gang plugs
** https://www.thomann.de/de/steckdosenleisten.html?feature-12362%5B%5D=true&feature-12373-first=0&feature-12373-last=0&oa=pra&gk=KASL&cme=false&filter=true
<<list-links "[all[current]tagging[]]">>


* PMR446
* DMR
** https://en.wikipedia.org/wiki/Digital_mobile_radio
* CB-Funk
* Freenet
* https://t-day.net/
* ~LoRa / ~LoRaWAN

funkgeräte

* retevis
* baofeng
* MMDVM


stuff

* https://www.youtube.com/@MachiningandMicrowaves
* [[Quarter wavelength impedance matching (2/2)|https://www.youtube.com/watch?v=KLNK935wglA]]
* https://www.benkuhn.net/wireless/
* https://www.techstage.de/ratgeber/notfallkommunikation-mit-hand-und-cb-funk-wie-geht-das/ghkk8jg
* https://github.com/jopohl/urh
* https://github.com/wb2osz/direwolf
* https://en.wikipedia.org/wiki/Packet_radio
* https://en.wikipedia.org/wiki/Spectral_efficiency#Comparison_table
* https://en.wikipedia.org/wiki/Comparison_of_wireless_data_standards
* https://en.wikipedia.org/wiki/Digital_radio
* https://50ohm.de/index.html
* https://www.youtube.com/results?search_query=diy+reactive+load
* https://www.thegearpage.net/board/index.php?threads/reactive-load-line-out-re-build.2006409/
* https://www.metalguitarist.org/threads/diy-reactive-loadbox-build.106526/
* https://www.thegearpage.net/board/index.php?threads/aikens-reactive-dummy-load.1072793/page-15
* https://www.diyaudio.com/forums/equipment-and-tools/364510-dummy-load-2.html
* http://www.guitargear.net.au/discussion/index.php?topic=35145.15
* https://www.thegearpage.net/board/index.php?threads/diy-reactive-load.1884640/
* https://proaudioland.com/news/difference-resistive-reactive-loads/
* https://www.vtadiy.com/book/chapter-4-integrated-push-pull-vacuum-tube-amplifier/4-1-output-stage-or-power-stage/4-1-3-reactive-load-and-loadline-computation/ - maybe relevant?
* https://www.youtube.com/watch?v=8GwnZ7ebY7Y
* https://www.diyaudioprojects.com/Technical/DIY-Speaker-Dummy-Load/
* https://hackaday.com/2022/08/24/reactive-load-for-amplifiers-teaches-lessons-about-inductors/
** https://hackaday.io/project/186297-reactive-amplifier-load-with-headphone-out
* https://en.wikipedia.org/wiki/Real-time_operating_system
** https://de.wikipedia.org/wiki/Echtzeitbetriebssystem
* https://en.wikipedia.org/wiki/Comparison_of_real-time_operating_systems
* https://www.digikey.com/en/maker/projects/what-is-a-realtime-operating-system-rtos/28d8087f53844decafa5000d89608016
* see [[embedded device development]]
* different (open source) RTOS:
** https://os.mbed.com/ - arm specific
** https://www.zephyrproject.org/
** https://riot-os.org/
** https://freertos.org/
* [[How to work with a Real Time Operating System and is it any good? (FreeRTOS, ESP32)|https://www.youtube.com/watch?v=684KSAvYbw4]]
battery pack Data:

* Manufacturer: Go-Tech Energy Co., Ltd.
* Model Name: GV7240
* nominal voltage: 72V
* max voltage: 84V (4,2V per cell)
* min voltage: ~55V (2,75V per cell)
* nominal capacity: 40Ah
* 22p20s 18650 cells
* battery case dimensions:
* inner: 22,5x14x46
** outer: 24,5x15,5x47
* cells: ICR18650-20f (originals)
** https://secondlifestorage.com/index.php?threads/samsung-icr18650-20f-cell-specifications.1757/
** there was prior work done on this battery pack, but only 22 cells in one of the serial rows got changed, they are still good, but different from the other, original cells, also the spotwelding isn't done very well

BMS data:

* switched minus port
* 2 separate pcbs
* data/communication
** 5 headers for themp sensors
** 2x 12pin headers for balancing and voltage sensing
** 5pin serial (I²C) header (GND, SCL, SDA, 3.3V)
** 10pin header for serial (RS232?) connection + 3 other cables to the outside of pack
** unknown 6pin header on smaller board
** unknows 5pin header on larger board
* completely coated in lacquer (whaterproofing)

rebuild options:

* 440 new 18650 Li-Ion cells?
** old ones have 1.8Ah per cell, could be replaced with ones with more capacity, lowering the weight of the pack
** __owner wants to buy used but tested 18650 cells which will be the replacement for the old ones__
* 22 or 23 LFP cells in series - possible, but more research about the other components of the scooter required, search for fitting cells, different BMS and possibly different casing for the cells required
* LiPo - unsure about security, owner wanted to use cheap LiPo pouch cells meant for cheap chinese smartphones

rebuild

* required
** 440 "new" 18650 cells
** ~10m of 2-row nickel ribbon
** spotwelder
** a bit of solder for the balancing leads
** a bit of silicone sealant
** kapton tape (3cm, and mabe 2 or 1cm)

because of the size and power-capacity of the pack i offered the owner to completely rebuild the pack with new cells, but he wanted only the completely dead cells replaced because he thought it's to expensive. he also had the option to buy a completely new pack from china, but he didn't want to do that either. you can basically nearly buy a new scooter for that price.

i dindn't want the legal trouble if there would have been a fire with the batterypack when only replacing the completely dead cells. With li-ion battery packs it is unwise to mix different cell models, manufacturers or even cells of different age and usage... because all of the cells have different internal resistance and overall don't match. that will exagerate balancing issues because the bms can't keep up. and used/old cells with much higher internal resistance heat up more while charging and draining power, which can have fiery consequences, especially when combined with other adverse factors present in a mixed battery pack.
Rechte und Rechtsextreme sind schon lange nicht mehr durch Springer Stiefel und Bomberjacke erkennbar... auch Kleidung wie Thor Steinar ist nicht deckend vorzufinden bzw. wird unauffälliger gestaltet... Rechtsextreme die die Identitäre Bewegung versuchen mit einem modernen Hippster-image junge leute zu fangen und viele rechtsextreme bestrebungen gehen sehr in eine querfront richtung, indem linke themen oder aktionsformen aufgegriffen oder adaptiert werden oder auch über die esotherische szene eine bindung gesucht wird... mit der AFD sitzen rechtsextreme offen im Bundestag.


* https://www.der-rechte-rand.de/
* https://www.nsu-watch.info/
* https://exif-recherche.org/
* https://de.wikipedia.org/wiki/Kategorie:Initiative_gegen_Rechtsextremismus

NSU Geheimbericht / NSU akten:

* https://nsuakten.gratis/
** https://fragdenstaat.de/dokumente/234186-abschlussbericht-zur-aktenpruefung-im-lfv-hessen-im-jahre-2012/
* https://www.nsu-watch.info/2022/10/der-nsu-geheimbericht-zeugnis-eines-desasters/
* 

must see:

* https://media.ccc.de/v/36c3-10639-let_s_play_infokrieg

* https://media.ccc.de/v/rc3-11500-this_is_not_a_game_de


other

* [[Exklusiv: Die Vernehmungen des Stephan Ernst - STRG_F|https://www.youtube.com/watch?v=lF6_8sAHPZQ]]
* [[Kampf um den Kiez - was Nazi-Schmierereien bedeuten - Exakt - MDR|https://www.youtube.com/watch?v=t2hScZqtgTI]]
* [[Rechte Internet-Blase: So subtil passiert Radikalisierung auf YouTube und Telegram -- PULS Reportage|https://www.youtube.com/watch?v=LM2Iy9jD3OY]]
* [[Unter Neonazis: Als Journalist auf Volkslehrer-Kundgebung|https://www.youtube.com/watch?v=PvNDYG5IvbI]]
* [[Burschenschaft Germania – Heimat für Antisemitismus und Rassismus? - Exakt - MDR|https://www.youtube.com/watch?v=wP8AW9vZVzQ]]
* [[Der Terror der einsamen Wölfe - Wie radikalisieren sich Rechtsterroristen? - FAKT - MDR|https://www.youtube.com/watch?v=Q8ATfcIbc7c]]
* [[Unter Neo-Nazis - Schläger verfolgen Journalisten - ZAPP - NDR|https://www.youtube.com/watch?v=j9vEzDwcH0o]]
* [[Polizisten in der AfD - FAKT - Das Erste|https://www.youtube.com/watch?v=KcBT2EsiMdI]]
* [[Hooligans und die AfD|https://www.youtube.com/watch?v=k6cGiP2rHrM]]
* [[Gefährliche Ideologie: Völkisches Netzwerk im Norden - Panorama 3 - NDR|https://www.youtube.com/watch?v=2dhFfUybtaw]]
* [[Rechte Milizen in den USA - DW Reporter|https://www.youtube.com/watch?v=0kXMH4RQDSo]]
* https://de.wikipedia.org/wiki/Die_Schwarze_Szene_im_Spannungsfeld_rechter_Ideologien
* [[Update: Wie ist das NAZI ZU SEIN?|https://www.youtube.com/watch?v=QzO-N0mM-eQ]]
* [[Wie ist das NAZI ZU SEIN?|https://www.youtube.com/watch?v=WZhmXPNo72c]]
* [[EX - Rechte Rotlicht Rocker - Philip Schlaffer|https://www.youtube.com/channel/UCCcFnVUHZDKDUkghDspBKdQ]]
* [[Wie Rechtsextremisten unsere Schulen unterwandern | WDR Doku|https://www.youtube.com/watch?v=LQrxlpPEa98]]
* [[Rechte Bürgerwehr - Wer ist hier gefährlich?  | WDR Doku|https://www.youtube.com/watch?v=T7lqyDz4ecM]]
* [[Die Story im Ersten: Am rechten Rand|https://www.youtube.com/watch?v=YB0JsXeA-b0]]
* [[Die AfD und ihre Rechtsextremen | REPORT MAINZ|https://www.youtube.com/watch?v=ugpwTh16HrM]]

* sonarworks xref: pretty cheap mic with measurement protocol and downloadable calibration profile
* Superlux ECM999 is good
* diy measurement mic?
** https://www.diyaudioandvideo.com/Tutorial/BuildMicrophoneForSpeakerTesting/
** https://hackaday.com/2022/06/08/a-lab-grade-measurement-microphone-for-not-a-lot/
*** https://hackaday.io/project/185762-mems-based-iepe-powered-instrumentation-microphone
** https://hackaday.com/2022/07/02/an-affordable-reference-mic-you-can-build-yourself/
*** https://github.com/loudifier/OpenRefMic
* https://hifi-selbstbau.de/grundlagen-mainmenu-35/softwaremesstechnik-mainmenu-66/100-mikrofonkalibrierung-wie-geht-das
* http://www.jobst-audio.de/techniktut/158-messtechnik-messmikrofone-einstieg
* https://isemcon.net/en/#1
* https://www.minidsp.com/products/acoustic-measurement
* https://de.wikipedia.org/wiki/Rekuperation_(Technik)#Rekuperationsbremse
** https://de.wikipedia.org/wiki/Nutzbremse
** https://de.wikipedia.org/wiki/Elektromotorische_Bremse
* https://en.wikipedia.org/wiki/Regenerative_brake#Conversion_to_electric_energy:_the_motor_as_a_generator
* Videos
** [[Regenerative Braking - DIY Electric Scooter Part 4 [VESC]|https://www.youtube.com/watch?v=OZFbep8wG7E]]
** [[Regenerative Braking - Explained|https://www.youtube.com/watch?v=BhOEoXfxHMc]]
** [[Regenerative Braking tests|https://www.youtube.com/watch?v=-suxSqrP_X4]]
** [[Optimal Regenerative Braking, Explained (episode 14)|https://www.youtube.com/watch?v=Qvf35ANNC3M]]
** [[Electric Skateboard Regenerative Braking -- Testing|https://www.youtube.com/watch?v=HmUrjAJ5_jA]]
** [[Activating Regen Braking on 1000w Rear hub Ebay kit|https://www.youtube.com/watch?v=7gL5y96-GCo]]
** [[What's Regenerative Braking ? DIY 24V DC Motor to 500W Generator 26 Amps|https://www.youtube.com/watch?v=css7XfTVtyU]]
* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:rekuperation
* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:rekuperation_bei_direktantriebsmotoren_am_beispiel_des_bionx_pl-250_ht
* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:rekuperation_faustregel
* can use different storages for the generated energy:
** [[flywheel (schwungrad)]]
** accumulators
** [[caps/supercaps|capacitors]]
* https://ihateregex.io
** even generates flowcharts for the regex
* regexr.com/
* regex101.com/
* https://regex-generator.olafneumann.org/
** https://github.com/noxone/regex-generator
got this dj controller for free because it is broken, doesn't turn on.

* https://www.reloop.com/reloop-digital-jockey-2-ie
* https://www.reloop.com/reloop-digital-jockey-2-interface-edition

don't really know which one it is, they have slight differences but seem to have the same functionality

opened it, bulged/dead electrolytic cap, replaced it with one from my collection. but still no luck.
the switching regulator, an MP1410es, right after the power input seems rough and doesn't output any voltage when testing at the testpoints for 5V and gnd on the "IO-Codec-PCB".
ordered a pack of new MP1410es from china, lets see.
the markings on the chip where not easy to read, i made a dot on the chip with a white marker, spread that out with my finger and rubbed the exess of with a q-tip and isopropanol.
It might be that the electrolytic cap died first, because of high esr and low capacitance it might have caused the switchmode chip to overheat.

i got the new MP1410es, a 5 pack, from china. I changed the chip out and checked the supply without screwing it back into the controler, 5V works. after that i reassembled the controller again and connected everything. i checked again and it seems like everything works again.

the jogweels had some matte coating which is disintegrating and became sticky, its uggly and not nice to the touch. I want to remove that stuff. I also want to clean all of the poti knobs and button caps.

To do that I had to remove the Main PCB. The jogwheels have a touch function, where i had to desolder two wires to remove the PCB, apart from unscrewing all of the nuts from the encoders and potentiometers. The jogwheels are mounted inside a brass bushing and retained with a snap ring. the wires for the touch function clip to the bushings and the jogwheels fit pretty tightly into the bushings. there is some grease used but i don't know which kind. i can try silicone grease but silicone is an insulator, maybe some other grease is better.

After the pcb was removed i could see some liquid damage / corrosion on the top side of the PCB where the right jogwheel sits.
That could also explain why the switching regulator died.
It was pretty easy to clean with ethanol and isopropanol, as well as some scrubbing with a fibreglass pen. i put some solder tin on some spots but i no components were really affected it seems.

everything was a bit dusty, so i brushed everything off with a fine brush.

I put all of the knobs and caps into zipper-bags with some water and dishwashing soap, to let it soak. after some time, after i was done cleaning other parts, i came back, drained the soapy water and laid the buttons and knobs out to dry. After drying i could see that some of the poti knobs still hat some dirt on them, so i brushed them quickly off with water and dried them off again.

Cleaning the front plate was simpler without the knobs and buttons. i used brushes to get stuff out of creases/cavities and used soapy water and a some microfibre cloth to clean the surface.
there was some residue of the jogwheel coating which i removed with cotton swabs and some ethanol.

I cleaned the jogwheels mainly with ethanol, its cheaper and i used it to remove pretty much everything. only for the last pass i used isopropanol to "polish" it. both worked fine to remove the coating residue. took some time to remove the stuff, but they look and feel much better without.

i tried desoldering the faders but it was really hard, so i stopped.


Todos:

* 6V 1,5A power supply
* replace 1 missing pot cap
* right/side b fader is sticky, maybe needs some grease
* cleaning the faders
* test all functions

chips:

IO-Codec-PCB - power, usb, stereo chinch out and in, 2 mode switches

* https://www.alldatasheet.com/datasheet-pdf/pdf/1222892/MPS/MP1410.html - switchmode chip
* https://www.alldatasheet.com/datasheet-pdf/pdf/862379/TI1/TUSB3200AC97.html - usb streaming controller
* https://www.nxp.com/docs/en/data-sheet/UDA1345TS.pdf - audio codec (2x)
* 15218 - ? soic-8 opamp? (3x)
* 1117 - 3.3v linear regulator (sot-223)
* couple small transistors (d1468; C114; A124; C1740
* https://www.alldatasheet.com/datasheet-pdf/pdf/111555/ROHM/BA033T.html - low saturation 3.3v linear reulator

Monitor PCB - headphone out

* https://www.ti.com/product/TPA152 - 75mW headphone amp

Main PCB

* TMP86FS49AUG - microcontroller
** https://www.alldatasheet.com/datasheet-pdf/pdf/213305/TOSHIBA/TMP86FS49AUG.html
!! reloop RA-1500 Pro

Problem: previous owner did some stuff, ripped out one of the transformer and something shorted out on a PCB that is part of the power supply circuitry. one of the two transformers is missing

* https://www.musikhaus-korn.de/de/reloop-ra-1500-pro-silver-aktion/pd/78954

the existing transformer is 2x 52,5V and 14,5V. the 14,5V supply the opamps and some controll circuitry switching the relais.
the other one was probably also 2x 52,5V but with a 9VAC winding for a fan.

vom design her klassisches Class AB, ich denke die 480W pro kanal an 4Ohm schafft die vielleicht wirklich, hätte vom aufbau auch so ca. 450W getippt.
ist eher eine einfachere schaltung und ein billiger aufbau.

bräuchte eine neue sicherung, einen neuen ringkerntrafo (ums zu vereinfachen vlt. noch einen kleinen billo 9V trafo oder 12 netzteil), poti reinigung oder neue potis und vlt. paar neue Kondensatoren.
der trafo müsste primär 230V und sekundär 2x ~53V haben (je 4A bzw. 420VA gesamt).

wenn man durch zufall einen passenden trafo günstig findet könnte man den flott machen, oder man bastelt was mit schaltnetzteil
folgene könnte man nutzen:

* https://www.ebay.de/itm/145593466130  2x 50V  59€
* https://www.ebay.de/itm/145393028600  2x 53V 59€
* https://www.ebay.de/itm/143970738545  2x 53V 59€
* a new transformer would cost around 150-200€
* https://www.multi-circuit-boards.eu/en/products/toroidal-transformers.html - a lot more expensive

ich weiß nicht was der vorbesitzer gemacht hat, vielleicht war es nur ersatzteilspender oder bastelobjekt.
* https://www.google.com/webmasters/tools/removals
* https://www.microsoft.com/de-de/concern/bing
* https://help.yahoo.com/kb/SLN4530.html
* https://www.youtube.com/watch?v=60MP5nv35HU
* https://github.com/gitfrage/guitarspecs#readme


needed:

* ~~caliper to meassure old screws~~
* new matching screws (screws are most rusted)
** gonna ask local shops ([[Eisenfeustel|https://www.eisenfeustel.de/kontakt/]] and [[werkzeuge kliemann|http://www.werkzeuge-kliemann.de/produktuebersicht]])
** pickguard: ''13''; 2,9mm x 16mm linsensenkkopf? - meassured 2.4-2.5mm x 10mm; head diameter: 4.9mm; black
** pickups: ''4''; 2.5mm x 29-30mm; head diameter: 4.4mm; black
** tailpiece:
*** ''4''; 2.5mm x 25mm; head diameter: 6mm; silver
*** ''4''; M3 x 37,8mm head diameter: 5mm; black
*** ''8''; 11.9mm grubscrews; black
* cleanup
* electronics
** 2 new pickups?
** new jack?
** 2 new potentiometers?
** aluminium tape
* tailpiece

problems:

* removing rust from parts
* extracting broken screw (using a drill with drill chuck?)
* fixing tuner/machine head?
* checking electronics
* polishing the shellac and fixing spalls?

the bass has a black body and white pickguard, the screws seem to have been black.
* https://de.ifixit.com/Manifesto
* https://www.ifixit.com/Manifesto
* https://www.1000manifestos.com/platform-21-repair-manifesto/
* https://repair.eu/
People I know have got a full PA System made by the former german Company Klotz.

* [[Klotz P-A 1200 Ampifier|Klotz P-A 1200 Amplifier]]
* [[Klotz RPC/2 Controller (for Nano 800) including the Connector Interface|Klotz RPC/2 Controller and Interface]]
* [[and two Klotz Nano 800 Speakers|Klotz Nano 800 Speakers]]

this is a complete Klotz PA system which fits inside a 4U Rack.
some components are not made by Klotz and only rebranded i believe, more on that in the dedicated parts below.
Klotz nowadays only manufactures Cables and Cabling systems for big installations. I've read in forum posts that people have tried getting information from Klotz one didn't have any luck but others got some documents that still existed.

Every information in this post is taken from many different sources an the internet and might be wrong. I scraped forum threads, offers on (used-)equipment sale websites and infomrations from other blogs.

the original company "Klotz Digital AG" does not exist anymore but the following companies are the newer companies related or seem related

* https://www.klotz-ais.de/ - somehow related?
* https://klotzcommunications.com/ - has actually bought the original assets and stuff back from Klotz Digital AG
* https://en.wikipedia.org/wiki/Klotz_Digital - some information about the company, history and legacy
* https://web.archive.org/web/2018*/klotz-digital.de - captures of the old websites but a lot missing and not much information left

information online is really scarse and here are sources i dindn't check yet:

* https://forum.speakerplans.com/klotz-pa1200-schematic_topic35205_page2.html

!! RPC/2 Adapters

The Klotz RPC/2 comes with a 19" connection panel which is quite useful. the connection panel also houses some shunts and small transformers for isolation and measurement, but those are not important. Due to the RPC/2 not working we are using a Behringer DCX2496 DSP as Crossover, Limiter and such.
But the RPC/2 connection panel uses DB15 Sub-D connectors to connect to the RPC/2. the connecton pannel has one DB15 for each stereo channel (xlr line in & amplified out) and one for the optional mono sub channel (only out). our RPC/2 does not have the sub option fitted, so the cable is anyways not in use.

i made adapters for the stereo channels, each using a DB15 gender changer, DB15 plug and 2 XLR connectors (1x plug, 1x socket).

the connection panel has the xlr in, that is going to the DB15 and needs to be adapted again to XLR for the DSP. Also the XLR output of the dsp has to be adapted to DB15, because the connection panel has a cable going from the DB15 to the amp.

I soldered everything up, checked everything and it worked first try.
* says "Spectrum Analyzer/Graphic Equalizer Computer Control System"
* has 2 RCA Inputs, a 3.5mm Stereo Jack (labeled "CD in") and a high power input for a car radio
* separate Power connection for the amplifier part and the Spectrum analyzer/EQ controll, uses 12V like from a Car battery
* 4 audio outputs
* 2x KIA6210AH (2x 22W amplifier)
** https://www.alldatasheet.com/datasheet-pdf/pdf/69376/KEC/KIA6210AH.html
* Funktions
** EQ and spectrum for 60, 150, 400, 1k, 2,5k, 6k, 12k Hz ranges
** shows spectrum
** EQ with adjustment for above ranges
** can store 4 different EQ settings

first i had to remove random bodged wires... the remaining wires are short but it's enough to work with. the the high power input probably had a plug but that is gone.
then i had to clean the buttons on the front, some were sticky or didn't move at all.

i attached a temporary plug for power after reassembling an tested it, functioned well. when using it more often it would be best to remake the wires and add propper connectors.
the tires where flat and the trailer had a very weird coupling.
i bought a pretty standard bike trailer coupling with a ball and a pan part, it can be mounted below the saddle with a clamp.
I went to lokal self-help bike workshops to repair or modify the parts.

there are different trailer styles. the main types are trailers which mount with a coupling to your axle or with a coupling to the saddle column. Because the drawbar is raised i had to go with the one to the saddle.

These couplings also have different styles, there are ones mounting to the existing saddle-clamp which supports the saddle, or ones which come with their own clamp.
My saddle-clamp is rather spacial, so i had to get one with an extra clamp.

i removed the old coupling and drilled a hole for the pan of the new coupling and mounted the pan.

I also added some reflectors along the way.

I tried just inflating the tires and fixing the rim tape, but one quickly lost pressure again. the tires are 20" x 2.25", so not very standard, we tried using a new standard 20" inner tube, but it was not as wide (1.25? or so) and quickly got a hole. I then got a used and patched up 20" tube wich is wider and i hope it works.

along the way the threads on one axle stripped and i had to change the axle. to my luck the bike workshop had fitting used axles.

ungefähre abmessungen:

* box 86x25x48
* 71 breit
* 96 lang bis deichseldreick
* 70cm deichsel ab dreieck
* 26,5 achsenhöhe
* 32,5 boxboden-höhe
* 61cm radmitte zu mitte
* chips/components
** IRLR8726 Mosfets
*** https://www.infineon.com/dgdl/irlr8726pbf.pdf?fileId=5546d462533600a40153567181dd26f7
** L78L05 5V linear regulator
*** https://www.alldatasheet.com/datasheet-pdf/pdf/22687/STMICROELECTRONICS/78L05.html
** LGT8P22 mystery 16 Pin chip, maybe MCU
* board has a serial connection, probably I2C or SMBus, see [[serial connection stuff]]

steps

* batteries seem fine
* mosfets seem fine
recone a woofer

* https://bcspeakers.com/en/resources/tech-support/speaker-recone-guide/
* [[Refoaming JBL Control 1 Speakers|https://www.youtube.com/watch?v=SqkOdF3LTuU]]

replacing diaphragm

* https://bcspeakers.com/en/resources/tech-support/diaphragm-replacement-guide/


stuff

* [[JL Audio 15W6 15W6v1 subwoofer rebuild redesign recone great for home theater or collector boat car|https://www.youtube.com/watch?v=MwZE6Bqwcdk]]
* https://hackaday.com/2023/04/20/this-one-simple-trick-rehabilitates-scratchy-sounding-speakers/
<<list-links "[all[current]tagging[]]">>

information

* https://repair.eu/
* [[Der Tüftler-König von Deutschland - WDR Doku ("30.000 Geräte repariert")|https://www.youtube.com/watch?v=ndBdXBs2vIU]]
* [[Reparieren wird belohnt -- Weiternutzen statt Wegwerfen ~ Arte RE:|https://youtu.be/_uwIErmDhUE]]
* https://www.reparatur-initiativen.de/
* see [[electronics safety]]
* see [[electronics repair knowledge]]
* [[Equipment Repair - TheStuffMade|https://www.youtube.com/watch?v=VPM2v631rdI&list=PLj1iPGXgbNf0EXaM_uUSqlVTvBLjhV48u]]
* https://eepower.com/resistor-guide/
** https://eepower.com/resistor-guide/resistor-materials/
** https://eepower.com/resistor-guide/resistor-fundamentals/power-rating/#
* https://www.learnabout-electronics.org/Resistors/resistors_08.php
* https://www.physics-and-radio-electronics.com/electronic-devices-and-circuits/passive-components/resistors/metaloxidefilmresistor.html
* resistorcolorcodecalc.com/
* https://en.wikipedia.org/wiki/Resistor
* https://de.wikipedia.org/wiki/Widerstand_(Bauelement)
* https://www.condoraudio.com/wp-content/uploads/Reviews/How-to-Choose-Replacement-Capacitors-and-Resistors.pdf
* https://resistorselect.blogspot.com/2011/04/inside-resistor.html
* https://www.codrey.com/resistor/power-rating-of-resistors/
scavenging / salvaging parts from old/broken electronics

* [[What is worth desoldering from old electronics? -- DIY Fume Extractor|https://www.youtube.com/watch?v=Nb78wF1Tkwc]]
* [[Hack everything: re-purposing everyday devices - Matt Evans|https://www.youtube.com/watch?v=7wAPWTzK8iI]]

hardware hacking:

* https://www.youtube.com/watch?v=VY9SBPo1Oy8
the phones from huawei are designed in a, not so sustainable way, that the display assembly contains half of the whole phone, nut just the display. If someone breaks the display of their huawei and has it fixed, half of the phone is new, including the battery which is attached to the back of the display with adhesive.
if you carefully heat the display assembly you can soften the adhesive and remove the battery.

the batteries i have at hand are a couple of different types from huawei phones.

! Connection

the connectors of the batteries obviously have power + and - but also feature four connections labeled "TH", "NC", "ID" and "SW".
The connectors are 10 pin, but the 3 most outer right and outer left are used for power.

* ID: ?
* SW: ?
* TH: seems to be a standard 10k Thermistor
* NC: Not Connected

the chip on the protection board of the cell is a "Microchip" branded one with "e3827", https://www.microchip.com/ParamChartSearch/chart.aspx?branchID=9011

ID and SW are probably some kind of serial or 1-wire communication?

* https://en.wikipedia.org/wiki/1-Wire
* https://en.wikipedia.org/wiki/I%C2%B2C#Applications
* https://en.wikipedia.org/wiki/System_Management_Bus
* https://en.wikipedia.org/wiki/UNI/O
* https://mpoweruk.com/communications.htm
* ''seems more like a tri-state logic output like here: http://ww1.microchip.com/downloads/en/DeviceDoc/MCP73831-Family-Data-Sheet-DS20001984H.pdf ''

information about the Connector

* digikey/mouser also have different similar looking connectors for flex pcb's
* https://www.mouser.de/Connectors/Board-to-Board-Mezzanine-Connectors/
* searching for FPC connector huawei on ebay only returns other connectors
* BM25 https://www.hirose.com/product/series/BM25?lang=de
* https://en.wikipedia.org/wiki/Reverse_engineering
** https://de.wikipedia.org/wiki/Reverse_Engineering
* https://syonyk.blogspot.com/2018/01/reverse-engineering-tec-06-serial.html
* http://jcjc-dev.com/2016/04/08/reversing-huawei-router-1-find-uart/
* http://www.devttys0.com/2012/11/reverse-engineering-serial-ports/
* https://www.virtual-serial-port.org/articles/reverse-engeneering-tools/
* https://www.errno.fr/BypassingBitlocker.html
* https://www.scip.ch/?labs.20211202

legal

* reverse engineering and publishing the documents seems legal as long as you made the documents all yourself, but patents are a problem
* best is to publish your documents under an open licence, so deletion requests are not as easy for the companies 
* https://en.wikipedia.org/wiki/Youtube-dl#RIAA_takedown_request

hardware / PCBs / circuits

* [[ PCB Reverse Engineering: Eric Schlaepfer |https://www.youtube.com/watch?v=BsftxTbs7MA]]
* [[How I Reverse Engineer a Circuit Board to build a Schematic - ICEpower 125ASX Project Build|https://www.youtube.com/watch?v=EynJiLZVeR4]]

digital

* https://www.eevblog.com/forum/projects/reversing-engineering-serial-protocol/
* https://stackoverflow.com/questions/45865628/reverse-engineering-protocol

software

radio / wireless

* https://hackaday.com/2013/07/01/reverse-engineering-a-wireless-protocol/
* https://www.usenix.org/system/files/woot19-paper_pohl.pdf
* https://arxiv.org/pdf/1704.05432.pdf

linux:

* wireshark
** tcpdump - network capture
** usbmon - usb capture
** bluetooth
** androiddump
*** https://www.wireshark.org/docs/wsug_html_chunked/ChBuildInstallWinInstall.html#ChBuildInstallWinComponents
*** https://www.wireshark.org/docs/man-pages/androiddump.html
*** https://bugzilla.redhat.com/show_bug.cgi?id=1834367
** https://www.wireshark.org/download.html
* amidi - dump midi information
** https://www.geeksforgeeks.org/amidi-command-in-linux-with-examples/
** https://linux.die.net/man/1/amidi
* Linux Fu: Eavesdropping on Serial - https://hackaday.com/2022/09/07/linux-fu-eavesdropping-on-serial/
remote controll panel

* color LCD
* 3 buttons: "Reset", "Power Switching", "On/Off"
* internal LiPo battery, charged through micro usb port
* chips/boards
** main board
*** 4056E (wscp34) - battery cahrging chip
*** Nuvoton N76E003AT20 - 8-bit low power 8051 CISC MCU
**** https://microcontrollerslab.com/n76e003at20-microcontroller-pinout-features-programming-and-peripherals/
**** https://microcontrollerslab.com/8051-microcontroller/
*** Holtek ht1621b - "RAM Mapping 32x4 LCD Controller for I/O MCU"
**** https://www.alldatasheet.com/datasheet-pdf/pdf/96976/HOLTEK/ht1621b.html
*** nrf24l01+ on daughterboard
probably just a rebrand of chinese products, like from Kosun https://www.kosunpower.com/ (a lot of china-originated special components)

* push-pull converter
**  vertical-mount daughterboards
*** 3843B by TI - https://www.alldatasheet.com/datasheet-pdf/pdf/168280/TI/3843B.html on a small power supply module?
*** board with buzzer
**** unmarked mystery chip - maybe overall controller?
**** SG3525AP - push-pull controller https://www.mouser.com/ProductDetail/STMicroelectronics/SG3525AP/?qs=lgHKUCmDFtgKpGE934d0CQ%3D%3D
** FTP04N04ND - n-channel Mosfet (x4)
*** https://datasheetspdf.com/pdf/1306044/IPS/FTP04N04ND/1 --- https://datasheetspdf.com/pdf-file/1306044/IPS/FTP04N04ND/1
*** bat- directly on drain, source to YMP230N55-source
** YMP230N55 - n-channel Mosfet
*** https://www.ceipsa.com/datasheet/YMP230N55.pdf
*** from source to FTP04N04ND-source
** "ks-1kwp-12v2" transformer labeling
** 2x caps (CBB21 400V 684)
** full-bridge rectifier
*** (4x) MUR1660CT - ON Semi "Power Rectifier, Ultra-Fast Recovery, Switch-mode, 16 A, 600 V"
* inverter part
** cap (cbb21 630V 104) + choke
** 500V, 330uF electrolytic cap
** h-bridge: (4x) IKW30N60H3 IGBT
*** vertical daughterboard: EG8010 based EGS002-like but very simplified SPWM controller module (only doing the SPWM switching, maybe a bit of feedback but no LED controll or so)
**** https://www.lz2gl.com/data/power-inverter-3kw/eg8010_datasheet_en.pdf
*** 2 diodes (?) next to the EG8010-daughterboard
*** https://www.infineon.com/dgdl/Infineon-IKW30N60H3-DS-v02_02-en.pdf?fileId=db3a3043266237920126bc80c5f041c9
** big cap + big choke for high-frequency filtering (smothing spwm to sinewave)
* EMI
** common mode supression choke + cap (cbb21 630V 104)
* outlet


additional:

* several 222 3kV ceramic caps to ground
Components of the drivetrain:

* 38V battery pack
** 4 connections: +, - and 2 data pins (not used by controller)
* controller with motor driver
* PAS-Sensor
* throttle control
* display with a few controlls
* 250W rear-wheel motor 
* JST-SM connectors ([[Datasheet|https://www.jst-mfg.com/product/pdf/eng/eSM.pdf]])

PAS-Sensor and throttle controll are Hall-Sensor based

connections on the controller:

* power +38V
* GND/ power -
* 3pin connector for PAS-Sensor (plug)
** 5V (red)
** GND (black)
** hall-sensor 'data' (green)
* 6pin connector for throttle control (plug)
** 5V
** NC
** data?
** GND
** data?
** NC
** only one data cable gets used, so only 3 standed wire
* 5pin connector for display (Receptacle)
** 36V power (red)
** GND (black)
** Control (blue?)
** Data1 (green?)
** Data2 (yellow?)
** blue, green and yellow are on this version white, yellow, grey
* 2pin connector (plug) - not used
** voltage?
** GND
* 5pin connector (plug) - not used
** ?
** GND
** ?
** ?
** ?

info from ebay listings of chinese controllers:

* 2 Anschlüsse für 36V Lichter, 3 Anschlüsse für Motor, 1 Anschluss für das Daumengas, 2 Anschlüsse für die Batterie (+ und -), 1 Anschluss für das Display, 1 Anschluss für Hallsensor und Geschwindigkeitssensor, 2 Anschlüsse für die Bremse, 1 Anschluss für PAS (pedal assist systems) 
* displays use fully populated 5-pin connector, but some displays have an additional 2-pin connector
* connections (controller-side):
** "low-potential brake"/"brake" 2pin plug (gray, black), 2 plugs on one cable
** "electric lock"/"master switch" 2pin connector (not JST SM) with bridged connector (red from display Receptacle and violet from controller)
** "lamp" 2pin plug (yellow, black) - for connecting lamps
** "intelligent identification"
*** 2pin Receptacle (only 1 green wire)
*** 2 pin plug (only 1 green wire)
** display connection 5pin Receptacle
** "electric brake" white 3pin Receptacle (black, grey, red) - maybe regenerative breaking?
** "speed throttle" black 3pin Receptacle (black, white, red)
** 2 thick leads, red and black for battery
** 3 thick leads (colored, might be blue, yellow, green) motor phases
** "hall sensors" weird double row 6-pin connector - motor hall sensors
** "1:1 accelerator" 3pin plug (black, red, blue) - maybe torque sensor?


more information:

* https://www.pedelecforum.de/wiki/doku.php?id=elektrotechnik:forumscontroller:peripherie
* settings done in the display unit might not be stored inside the controller but only in the display
it's basically a small server/client to connect Serial devices (RS-232; DB9 connectors) too and communicate to them over ethernet.
it has 4 serial connections and you can set the following modes for each serial connection separately:

* Host Based
** ?
* TCP Server
** connect to the DE-304 via TCP and communicate with the Serial device
* TCP Client
** the DE-304 connects to an IP:Port using TCP to establish the communication
* UDP Server/Client

to connect to the eathernet network the DE-304 has 10mbit and 100mbit Ethernet, the default IP is 192.168.127.154 but it supports DHCP and ~BootP.

Protocol reverse engineering:

* started with the DE-304 in TCP Client mode for one port, set the Server IP to the PC i'm using, left Port as 4001, used wireshark to listen to the connections to my PC on port 4001
* DE-304 starts with a normal TCP SYN to attempt a TCP connection
a friend of mine got cool VT520 and a VT420 Terminal and we wanted to use them again.

They interface with the computer/mainframe via RS232 25pin using a DB-25 Connector. They also offer a parallel printer port and inputs for keyboard. The VT420 has some old keyboard input, the newer VT520 has got a PS/2 keyboard input, but these old terminals are best used with the old DEC keyboard layout with 20 f-keys.

newer RS232 interfaces are most times only DE-9 with 9 pins, because some pins were rarely used and pretty much discarded. i wonder if the terminals used the discardet data lines.

the raspberry pi has a basic TTL/UART (4pin; power, ground, Rx and Tx) connection for serial communication, it an be easily confugured to use it for the boot shell and terminal. a TTL/UART to RS232 adapter is needed (also to convert the logic levels from 3.3V to 5V) and then a DE-9 to DB-25 adapter to the terminal. i'm pretty shure some information gets lost due to the 2pin uart instead of RS232.

at last `raspi-config` has to be run and in the interfacing the serial interface and the boot shell has to be activated.

* https://www.raspberrypi.org/documentation/configuration/uart.md
* self-winding is probably possible but tedious and you have to be very careful. it is better if you have access to a winding machine or want to build one, but else i would advise against self winding
** it is easy to damage the isolation/the laquer coating of the wire
* you might have luck finding used transformers online or the one you are searching for is a pretty standard one
* https://www.multi-circuit-boards.eu/en/pricing/toroidal-transformers.html - i was told this is a pretty cheap custom manufacturer
* [[RISC-V: How much is open source? Featuring the new ESP32-C3|https://www.youtube.com/watch?v=VdPsJW6AHqc]]
* https://www.gigadevice.com/products/microcontrollers/gd32/risc-v/
** https://www.gigadevice.com/products/microcontrollers/gd32/risc-v/mainstream-line/gd32vf103-series/
* https://en.wikipedia.org/wiki/RISC-V#Implementations
* https://riscv.org/exchange/
* https://media.digikey.com/pdf/Data%20Sheets/GroupGets%20PDFs/LoFive_R1_Web.pdf
** https://groupgets.com/manufacturers/qwerty-embedded-design/products/lofive-risc-v
** https://github.com/mwelling/lofive
** https://github.com/mwelling/lofive/wiki#programming-to-lofive-r1-using-the-new-sdk
* https://hackaday.com/2017/09/18/a-smaller-cheaper-risc-v-board/
* https://github.com/riscvarchive/riscv-cores-list
* https://www.youtube.com/c/thethoughtemporium
* https://berthub.eu/articles/posts/reverse-engineering-source-code-of-the-biontech-pfizer-vaccine/ - very nice explanation with technical analogies how the Pfizer vaccine works
* https://berthub.eu/articles/posts/genetic-code-of-covid-19-vaccines/
* https://github.com/NAalytics/Assemblies-of-putative-SARS-CoV2-spike-encoding-mRNA-sequences-for-vaccines-BNT-162b2-and-mRNA-1273
* [[An Open Soure Cable Driven Robot: First Prototype|https://www.youtube.com/watch?v=3R8XS10bWdE]]
* [[WinchBot 1.5 - a robot made of winches and servos|https://www.youtube.com/watch?v=6H3LaVPMwmQ]]
* https://www.soundandvision.com/content/eminent-technology-trw-17-rotary-subwoofer
* http://www.rotarywoofer.com/
* https://www.avsforum.com/forum/113-subwoofers-bass-transducers/2991264-have-you-guys-ever-heard-rotary-subwoofers-print.html
* https://www.avsforum.com/forum/155-diy-speakers-subs/1940241-interesting-diy-rotary-subwoofer-project.html
* https://www.ohgizmo.com/worlds-most-powerful-subwoofer/
* "pelican case" or other heavy-duty storage cases
** https://hackaday.com/2015/08/13/raspberry-pi-field-unit-rpfu/
* [[diy flightcase]]
* euro container / stackable boxes
** https://back7.co/home/introducing-the-kuiper-deck
*** https://hackaday.com/2021/02/17/this-stackable-pi-portable-is-ready-to-rumble/
* https://www.paulvdiyblogs.net/2017/09/designing-single-li-ion-cell-ups-for.html
* https://www.paulvdiyblogs.net/2015/05/a-fully-automatic-psu-with-ups.html
* https://www.paulvdiyblogs.net/2015/05/simple-ups-for-raspberry-pi.html
* https://www.paulvdiyblogs.net/2016/04/rpi-power-supply-with-1-button-start.html
* [[ How To Read Schematics 3. Learn How To Understand Circuit Diagrams |https://www.youtube.com/watch?v=OirYfphm7nI]]
* 
I seem to have problems with the embeded controller in my Schenker notebook, it seems to look up/bug/freeze and not allow charging. When i first had the problem the schenker support suggested updating the firmware, which solved the problem for some time, but it happened again.
this time the EC seems to have reset itself after some tries getting into the bios, so i didn't have to redo the update.

i also seem to have problems with UPower - https://upower.freedesktop.org

"Ich konnte bisschen debuggen warum Gnome manchmal zufällig nicht mehr den aktuellen Akkustand anzeigt wenn der Akku entladen wird bzw. auch keine Warnung bei niedrigem Akkustand kommt.
Scheinbar liegt das an UPower. Gnome nutzt UPower und UPower scheint sich bei mir ab und an aufzuhängen oder so. Wenn ich das Ladekabel anstecke updated es wieder.
Das Gnome Power Manager Tool, welches die Daten auch von UPower bezieht, sowie das upower CLI Tool zeigen das selbe Verhalten.
Wenn ich jedoch das acpi CLI Tool nutze oder per Kernel sysfs (/sys/class/power_supply/BAT0/uevent) checke dann finde ich dort aktuelle Daten auch wenn UPower noch falsch reported.
Da UPower die Hardware-näheren Interfaces vom Kernel nochmal abstrahiert hat es vermutlich nichts mit der Hardware zu tun, also wohl nichts wo Sie viel Einfluss drauf haben."

* https://gitlab.gnome.org/GNOME/gnome-power-manager
** https://help.gnome.org/users/gnome-power-manager/stable/
* https://www.simplified.guide/linux/view-battery-information
* https://www.kernel.org/doc/html/latest/power/power_supply_class.html
* https://www.geeksforgeeks.org/acpi-command-in-linux-with-examples/
* https://upower.freedesktop.org/docs/


vlt. hilft es anderen:

22.07.22:

<<<
Wir empfehlen Ihnen hier ein Firmware-Update, dies sollte die Probleme mit der Ladung des Akkus lösen.
Falls nicht, können Sie Ihr Gerät natürlich für eine Garantiereparatur einsenden.

Die Firmwaredateien für Ihr Gerät können Sie hier herunterladen:
https://download.schenker-tech.de/package/schenker-via-15-pro-idsvi15pm20/

Die Anleitung für den Flashvorgang finden Sie hier:
Entschuldigen Sie bitte - hier der Link für die Anleitung & EFI Shell:

https://download.schenker-tech.de/package/bios-update-via-efi-shell/
<<<

<<<
Firmware Update hat funktioniert und direkt nach dem Update vom EC hat das Notebook auch wieder geladen.
Bios habe ich auch geupdates.
Ich hoffe die nervigen ACPI Probleme sind nun auch Vergangenheit.
<<<

10.08.2022:

<<<
Das von Ihnen beschriebene Phänomen tritt nur sehr selten auf, daher haben wir leider bisher noch keine Lösung dafür finden können.
Ein BIOS-Reset könnte hier helfen, da dadurch auch der EC zurückgesetzt wird.

Halten Sie dafür beim Start einfach die Taste F2 gedrückt.
Im BIOS drücken Sie dann die Tasten F3 und abschließend F4 für den Firmware-Reset.

Falls das Phänomen jedoch öfter auftritt, können Sie Ihr Gerät gerne für eine Überprüfung zu uns einsenden.
Melden Sie sich in diesem Fall einfach nochmal bei uns.
<<<


TODO:

* vlt. mit https://www.hirensbootcd.org/ paar firmware updates noch installieren?
* fwugmrg hat vlt. noch updates?
* amd ryzen hat sleep/suspend/deep-sleep probleme unter linux?
* https://www.phoronix.com/news/AMD-One-Liner-System-Resume
* https://docs.fedoraproject.org/en-US/quick-docs/viewing-logs/
* https://www.howtogeek.com/499623/how-to-use-journalctl-to-read-linux-system-logs/
* https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate


! GPU

freezes or is extremely slow after waking up from sleep sometimes.

* linux check cpu power mode
** http://unix.stackexchange.com/questions/182696/ddg#182699
** https://unix.cafe/wp/en/2020/07/toggle-between-cpu-powersave-and-performance-in-linux/
** https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/monitoring_and_managing_system_status_and_performance/tuning-cpu-frequency-to-optimize-energy-consumption_monitoring-and-managing-system-status-and-performance
** https://askubuntu.com/questions/203303/power-savings-and-performance-modes-on-ubuntu-system
* https://download.schenker-tech.de/package/schenker-via-15-pro-idsvi15pm20/
* https://brunox.swiss/
* WD40
* https://www.kontaktchemie.com/ - wenn die webseite funktioniert
datenschutzfeindlcher scheißverein

https://www.meineschufa.de/de/datenkopie
* [[Warum das deutsche Schulsystem so schlecht ist - Simplicissimus|https://www.youtube.com/watch?v=fxvvMjDCo_4]]
* [[Unser Schulsystem ist Mist! - Harald Lesch|https://www.youtube.com/watch?v=-q0Sm8Kldn0]]
* [[Wie sich unser Schulsystem blamiert hat - MrWissen2go|https://www.youtube.com/watch?v=8D2x1MzqVpM]]
* [[Die Wahrheit über die Schule - MrWissen2go|https://www.youtube.com/watch?v=iaVNDMgUtRo]]
* [[Warum sich unser Schulsystem ändern muss - #mirkosmeinung - MrWissen2go|https://www.youtube.com/watch?v=weB79v4Zstk]]
* https://www.youtube.com/watch?v=JtahB1-MNvk
* https://twitter.com/DavidOBowles/status/1313246219905437701
* https://de.wikipedia.org/wiki/Elektronische_Sicherung
* https://de.wikipedia.org/wiki/Kategorie:Elektrische_Schutzeinrichtung
* https://de.wikipedia.org/wiki/Schutzschalter
* https://de.wikipedia.org/wiki/Isolationsw%C3%A4chter

* https://de.wikipedia.org/wiki/Fehlerstrom-Schutzschalter (FI)
** [[⚡ N + PE = FI-Schalter löst aus! ������ Aber warum? ������ ultimative Erklärung ������ - Das musst du wissen ������‍♂️|https://www.youtube.com/watch?v=yVC9DNMRrIs]]
** [[Lebensgefahr durch defekten FI-Schutzschalter - Sinn und Zweck der Prüftaste am RCD|https://www.youtube.com/watch?v=5SS7xd4YXR8]]
** [[FI Schutzschalter / Fehlerstromschutzschalter - Funktion und Aufbau|https://www.youtube.com/watch?v=JGvMNNhQowM]]

* https://de.wikipedia.org/wiki/%C3%9Cberstromschutzeinrichtung [[[Kategorie]|https://de.wikipedia.org/wiki/Kategorie:%C3%9Cberstromschutzeinrichtung]]
** https://de.wikipedia.org/wiki/Schmelzsicherung
** https://de.wikipedia.org/wiki/Leitungsschutzschalter
*** [[Leitungsschutzschalter / LS-Schalter (Sicherung) - Funktion und Aufbau|https://www.youtube.com/watch?v=6Gjst-q-C_4]]

* https://de.wikipedia.org/wiki/Schutzleitungssystem
* https://de.wikipedia.org/wiki/SPE-PRCD
* https://de.wikipedia.org/wiki/Residual_Current_Monitor

* [[Brandschutzschalter (AFDD) - Schutz vor elektrischen Bränden - Funktion und alle wichtigen Infos|https://www.youtube.com/watch?v=Beo9U4xteJM]]

* [[Feinsicherung wechseln - wissenswerte Informationen und Daten - Geräteschutzsicherung tauschen|https://www.youtube.com/watch?v=n9DOZb62gLE]]
* https://www.westfalia.de/static/informationen/ratgeber/technik/normen_und_kennzeichnungen/kennzeichnung_von_feinsicherungen.html
* https://www.littelfuse.com/technical-resources_old/faqs/fuse-markings.aspx
** https://www.littelfuse.com/~/media/files/littelfuse/technical-resources/documents/reference-documents/littelfuse_5x20mm-iec-fuse-cap-marking_guide.pdf
* [[gusseisen schweißen/hartlöten]]


Methoden

* [[ 4 Typen des Schweißens: MAG vs WIG vs Elektrode vs Fülldraht - Für Anfänger erklärt |https://www.youtube.com/watch?v=1KusWaopEdo]]
* [[Igor Welder: Schweißen selber lernen Playlist|https://www.youtube.com/playlist?list=PL5uzLI8cqfnGfZwfLm2kPmE-WbwrcCpYr]]
* https://www.youtube.com/playlist?list=PLk8S90fhT-Ej8yONixBBZhqYwmqfR4KeB
* https://www.youtube.com/watch?v=ZZvMsnSUDqo

* E-Handschweißen - Elektrode (ohne gas, mit flussmittel an elektrode, dreckigstes aber einfachstes)
** [[Igor Welder: Elektrodenschweißen Playlist|https://www.youtube.com/playlist?list=PL5uzLI8cqfnEPEwFgmo0CwRTUuFjscn_o]]
** https://www.youtube.com/watch?v=s-QrRKhl-Rw
** https://www.youtube.com/playlist?list=PLrsdFQpmQ2MP7r3uiradxjyF8kXrOYrUF
** https://www.youtube.com/playlist?list=PLk8S90fhT-EjfeJNxwYDClJvY5R8Umwri

* Fülldraht (ohne Gas
** [[Igor Welder: Fülldraht Playlist|https://www.youtube.com/playlist?list=PL5uzLI8cqfnGP1RSYVsFIEzsRQDjxGmF3]]

* WIG/TIG
** [[TIG / WIG]]
** [[ TOP 8 Tipps und Tricks - WIG Schweißen |https://www.youtube.com/watch?v=vhd-Y2etZ9w]]
** [[Igor Welder: WIG DC Playlist|https://www.youtube.com/playlist?list=PL5uzLI8cqfnFvLHG466mgy9mr7--OCDlP]]
** [[Igor Welder: WIG AC Aluminium Playlist|https://www.youtube.com/playlist?list=PL5uzLI8cqfnFVKgBOun1njlkZ7VoYEdkT]]
** [[ Was bewirkt die AC Frequenz und Balance in der Schweißnaht?! - WIG Aluminium - Igor Welder |https://www.youtube.com/watch?v=n0gQOwYdrHo]]
** [[ Standzeit der Wolframelektrode EXTREM erhöhen |https://www.youtube.com/watch?v=AfKH_kNR3T0]]
** [[ Möglichkeiten die kaum einer kennt beim WIG Schweißen |https://www.youtube.com/watch?v=jPhG_JlK2Ys]]
** [[ Edelstahl Geländer schweißen - Schritt für Schritt - für absolute Beginner! |https://www.youtube.com/watch?v=T4e56DlxQ90]]
** [[ Wolframelektrode Farbe? - Bedeutung ausführlich erklärt! - Teil 1 - Rot, Gold, Grün |https://www.youtube.com/watch?v=iOLGDJtO16E]]
*** https://www.youtube.com/watch?v=Pg_ijg2apM4
*** https://www.youtube.com/watch?v=u-nDJNMwo_w
*** https://www.youtube.com/watch?v=8IHzCga3umI
** https://www.youtube.com/watch?v=ppX9H29QUtc
** https://www.youtube.com/playlist?list=PLk8S90fhT-EhWuybjUx2LNrfHkq_siBMZ
** https://www.youtube.com/playlist?list=PLk8S90fhT-EioFlsKKBenaqUBENFxDqKr
** https://www.youtube.com/watch?v=rO5oUSsayUc
** this old tony - tig
*** https://www.youtube.com/watch?v=38zP4cu8kgg
*** https://www.youtube.com/watch?v=svHI9nmV5nw
*** https://www.youtube.com/watch?v=--1lSmtuyUg
*** https://www.youtube.com/watch?v=a6fUCApr03g
*** https://www.youtube.com/watch?v=aGsFdudG7Ho
** https://www.youtube.com/watch?v=TgekhRZ_d2o
** https://www.youtube.com/watch?v=gCCdiksvXMU
** https://www.youtube.com/watch?v=HOL1bMC-UJQ
** https://www.youtube.com/watch?v=5ljw7fh1SiM
* https://www.youtube.com/watch?v=VOqhh36Kcxo&list=PLp0pALmMwc6sTKLkRThyuHqNfJOKeSOki&pp=iAQB

* MAG/MIG
** [[ MAG Schweißen für Anfänger - normal, überkopf und fallend! - Schritt für Schritt |https://www.youtube.com/watch?v=Hje2Ea4rjJw]]
** [[Igor Welder: MIG (Aluminium) Schweißen Playlist|https://www.youtube.com/playlist?list=PL5uzLI8cqfnHy_q7g06NeUUdGuCtNRVLG]]
** [[Igor Welder: MAG Playlist|https://www.youtube.com/playlist?list=PL5uzLI8cqfnEIgRMgA49nHgbcp05GT_Bb]]
** https://www.youtube.com/playlist?list=PLk8S90fhT-Eg97SDh905WuAcv1IBwwEpC
** https://www.youtube.com/playlist?list=PLk8S90fhT-EgZ45Gsc3Lcc7IYLZkgOIo_

* Laser


aluminium

* https://www.youtube.com/playlist?list=PLk8S90fhT-EhfjqxPt6HOqinbUkR5HfYU
* https://www.youtube.com/watch?v=1XGvvKkSd9k

how to / tips und tricks

* https://media.ccc.de/v/gpn20-29-schweien-down-the-rabbit-hole
* https://www.weldingtipsandtricks.com/
** https://www.youtube.com/c/weldingtipsandtricks
* https://www.youtube.com/c/ThisOldTony
* [[Youtube - Igor Welder|https://www.youtube.com/channel/UC19tEGPtxdnSMZnoqYUVvzA]]
** [[Igor Welder: Schweißen selber lernen Playlist|https://www.youtube.com/playlist?list=PL5uzLI8cqfnGfZwfLm2kPmE-WbwrcCpYr]]
* https://www.youtube.com/@ManfredWelding
* [[Youtube - Weld.com|https://www.youtube.com/channel/UCM0kHJXSHR1k1wtLuliKmHg]]
* [[ Welding 101 for Hobbyists (and Nerds) |https://www.youtube.com/watch?v=ZZvMsnSUDqo]]

* [[ WELDING: THE BEST WAY TO LEARN!|https://www.youtube.com/watch?v=2fUAHkUfTps]]

alte schweißtechnik (reparieren)

* [[ Es schweißt GÖTTLICH! Fehlersuche - 30 Jahre alte ESS ECOMAG 404 |https://www.youtube.com/watch?v=VF-npEsJuE4&list=PL5uzLI8cqfnG62r4hDsGiGRobiVFBy8iM]]

DIY zubehör

* [[Making a Rotary Ground Clamp for Welding - Shop Made Tools|https://www.youtube.com/watch?v=bIkHtYWENiA]]

wiki

* https://de.wikipedia.org/wiki/Stabelektrode
* https://de.wikipedia.org/wiki/Lichtbogenhandschwei%C3%9Fen

open source

* https://www.opensourceecology.org/portfolio/welder/
* https://www.opensourceecology.org/portfolio/plasma-cutter/
* [[Open Source Schweisstisch|https://www.youtube.com/watch?v=7ICCdZFgvJk]]
<<list-links "[all[current]tagging[]]">>

* http://emlab.utep.edu/opensource.htm
* http://greenteapress.com/ModSimPy/ModSimPy.pdf
* https://matplotlib.org/
* https://realpython.com/jupyter-notebook-introduction/
* https://scicomp.aalto.fi/
** https://scicomp.aalto.fi/triton/apps/jupyter/
* https://wiki.opensourceecology.de/OpenScience

* https://minkorrekt.de/ - german podcast about science, science communication and scientific methods
* science has to be freely accessible to everyone and has to be propperly documented to be able to easily replicate it.
* it is important to also publish inconclusive and bad results, in medicine but also in other sciences, because it prevents others from working on the same... it saves time and human working power... also others might be able to draw conclusions from material and data that presented nothing to you.
* https://junq.info/ - journal of unsolved questions
* researchgate - interresting but often criticised proprietary platform
** https://www.researchgate.net/
** https://de.wikipedia.org/wiki/Researchgate
** https://en.wikipedia.org/wiki/ResearchGate
* https://de.wikipedia.org/wiki/Academia.edu
** https://en.wikipedia.org/wiki/Academia.edu
* https://en.wikipedia.org/wiki/Category:Scholarly_communication
* https://en.wikipedia.org/wiki/Category:Science_websites
* https://de.wikipedia.org/wiki/Kategorie:Wissenschaftskommunikation
* https://blogs.ub.tu-berlin.de/publizieren/2016/08/artikel-bei-researchgate-und-co-hochladen-welcher-verlag-erlaubt-was-und-wie-open-access-ist-das-eigentlich/
* https://osc.universityofcalifornia.edu/2015/12/a-social-networking-site-is-not-an-open-access-repository/
* https://arxiv.org
**  https://de.wikipedia.org/wiki/ArXiv
** https://en.wikipedia.org/wiki/ArXiv
* https://en.wikipedia.org/wiki/Category:Open_science
* https://en.wikipedia.org/wiki/Category:Open-access_archives
* https://en.wikipedia.org/wiki/Category:Eprint_archives
* https://en.wikipedia.org/wiki/List_of_academic_publishers_by_preprint_policy
* https://en.wikipedia.org/wiki/List_of_academic_databases_and_search_engines
* https://en.wikipedia.org/wiki/Open-access_repository
* https://de.wikipedia.org/wiki/Kategorie:Open_Access
* https://en.wikipedia.org/wiki/List_of_preprint_repositories
* https://de.wikipedia.org/wiki/Kategorie:Dokumentenserver
* https://de.wikipedia.org/wiki/Offene_Wissenschaft
* https://de.wikipedia.org/wiki/Fachdatenbank
* https://de.wikipedia.org/wiki/ViXra
* https://publiclab.org/
* [[Applied Science|https://www.youtube.com/user/bkraz333]] - different physical and technical topics
* [[The Thought Emporium|https://www.youtube.com/user/TheChemlife]] - mainly biology/chemics topics, a few technical projects
* [[NileRed|https://www.youtube.com/user/TheRedNile]] - mainly chemistry
* [[Explosions&Fire|https://www.youtube.com/c/ExplosionsFire2]] - chemistry
* [[Cody'sLab|https://www.youtube.com/user/theCodyReeder]] - many topics
* [[Keystone Science|https://www.youtube.com/user/hobcoman]]
* [[Science Marshall|https://www.youtube.com/c/ScienceMarshall]]
* [[NurdRage|https://www.youtube.com/user/NurdRage]]
* [[NightHawkInLight|https://www.youtube.com/c/Nighthawkinlight]]
* https://www.ctcms.nist.gov/fipy/
* https://alternativeto.net/software/scipy--numpy/
* https://www.sagemath.org/
* GNU Octave
* Scilab
* Spyder - https://github.com/spyder-ide/spyder
** https://www.spyder-ide.org/
** https://de.wikipedia.org/wiki/Spyder_(Software)
* http://matplotlib.sourceforge.net/
* https://www.scipy.org/
* https://wiki.octave.org/Fem-fenics
* https://www.featool.com/tutorial/2017/06/16/python-fem-and-multiphysics-simulations-with-fenics-and-featool
* http://www.math.pitt.edu/~sussmanm/3040Summer14/FEM1D.pdf
* https://github.com/jjcremmers/PyFEM
* https://salome-platform.org/
* https://apps.kde.org/en/cantor
* https://apps.kde.org/en/labplot2
* https://github.com/oofem/oofem - ree finite element code with object oriented architecture for solving mechanical, transport, fluid and multiphysics problems. 
** http://www.oofem.org/
* https://precice.org/
** https://github.com/precice/precice - A coupling library for partitioned multi-physics simulations, including, but not restricted to fluid-structure interaction and conjugate heat transfer simulations. 
* http://projectchrono.org/
** https://github.com/projectchrono/chrono - C++ library for multi-physics simulation
* http://www.mohid.com/
** https://github.com/Mohid-Water-Modelling-System/Mohid - Official MOHID Water Modelling System repository
* https://en.wikipedia.org/wiki/Maxima_(software)

https://awesomeopensource.com/categories/science
i hoped i could use an old DVB-T USB-Stick as SDR, but i had to find out it only contains a dib7770pa from ~DiBcom for which no documentation can be found and is not supported by RTL-SDR.

* https://www.linuxtv.org/wiki/index.php/DiBcom
* https://en.wikipedia.org/wiki/DiBcom
* https://www.funk-technik.info/alles-%C3%BCber-rtl-sdr/welche-dvb-t-stick-funktionieren.html
* https://www.darc.de/fileadmin/_migrated/content_uploads/SDR_Stick_neu.pdf
* https://www.reddit.com/r/RTLSDR/wiki/compatibility
* https://wiki.radioreference.com/index.php/RTL-SDR
* https://github.com/cariboulabs/cariboulite
* https://limemicro.com/products/boards/
* https://osmocom.org/projects/sdr


stuff

* [[A Software Defined Radio (SDR) Approach to Radar|https://www.youtube.com/watch?v=v2cqUal_RLw]]
* CC1101
** https://www.rtl-sdr.com/tag/cc1101/
** https://github.com/BehindTheSciences/record-an-RF-signal-with-GNURadio-and-transmit-it-using-a-CC1101/blob/master/README.md
** https://github.com/BehindTheSciences/record-an-RF-signal-with-GNURadio-and-transmit-it-using-a-CC1101
* https://airspy.com/
* https://osmocom.org/projects/osmo-fl2k/wiki
** https://www.rtl-sdr.com/category/fl2k-sdr/
** https://laforge.gnumonks.org/blog/20180423-osmo-fl2k/
** https://www.rtl-sdr.com/setting-up-and-testing-osmo-fl2k/
** https://www.darc.de/nachrichten/meldungen/aktuelles-details/news/aus-vga-adapter-wird-sdr-sender/
** https://www.golem.de/news/software-defined-radio-wenn-der-mobilfunk-per-vga-apater-kommt-1804-134024.html
** https://amateurfunk-lueneburg.info/forum/post-pdf-export/1811/
** https://hackaday.com/2018/04/23/spoofing-cell-networks-with-a-usb-to-vga-adapter/
** https://www.eevblog.com/forum/rf-microwave/a-cheap-vga-adapter-as-sdr-tx/
* https://www.rtl-sdr.com/using-a-cheap-usb-to-serial-port-adapter-as-a-transmitting-sdr/
** https://hackaday.com/2018/12/06/your-usb-serial-adapter-just-became-a-sdr/
* https://www.qsoshack.com/transceiver-sdr-panadapter-how-to-guide/
* greenpanda
* refurbed?
* afb
* https://en.wikipedia.org/wiki/Resource_Description_Framework
** https://de.wikipedia.org/wiki/Kategorie:Semantisches_Web
* 
* RDF
** https://de.wikipedia.org/wiki/Resource_Description_Framework
** https://en.wikipedia.org/wiki/Category:Semantic_Web
* robots.txt
* https://humanstxt.org/
** example: https://lonami.dev/humans.txt
Friends asked me if i could repair a powersupply from a sennheiser radio splitter for them.
The splitter is used in a wireless microphone system from sennheiser, using only two antennas for 4 receivers or so.

The powersupply is pretty much an ordinary universal smps wall-plug with 13,8V 2A output.
But because this is from professional equipment the build quality and design is really good. The case is not glued or friction welded, but is held together with screws, so servicing is much more easy and possible without destroying the case. the components seem to be good quality and the anti-tracking cutouts to isolate the low-voltage side from the high voltage are pretty wide, much wider than in smaller and cheaper designs.

The problem is a shorted bridge rectifier (DFL1506S) and also blown fuse (T2.0A).
Other components don't seem damaged.

diode bridge was available and i bought a matching fuse.
did some rather quick checks on the major semiconductors to check for shorts but everything seemed fine.
Changed the rectifier bridge and the fuse. i reassembled it into the case and just plugged it in and checked the voltage with a multimeter.
it was perfectly on 13.8V.

* https://www.alldatasheet.com/datasheet-pdf/pdf/414455/FAIRCHILD/FAN6300A.html - mains side
*https://www.alldatasheet.com/datasheet-pdf/pdf/1397518/NXP/TEA1791T_V01.html - output side

the pcb has good anti-tracking slots, one longer one 3mm wide, another 5mm wide. the optocoupler is a pretty long package.
and there are well designed spark gabs on the mains side.
* https://github.com/pyserial/pyserial
* see also [[hardware hacking]]
* see [[inter IC or inter device communication, networking]]
* https://de.wikipedia.org/wiki/EIA-422
* [[PROTOCOLS: UART - I2C - SPI - Serial communications #001|https://www.youtube.com/watch?v=IyGwvGzrqp8
* https://mitxela.com/projects/controlling_old_tech
* https://en.wikipedia.org/wiki/List_of_interface_bit_rates

* Linux Fu: Eavesdropping on Serial - https://hackaday.com/2022/09/07/linux-fu-eavesdropping-on-serial/

RS-232

* https://electronics.stackexchange.com/questions/117241/baud-rate-calculation
* https://www.eevblog.com/forum/projects/debugging-a-unknown-rs232/
* [[Hacker's Guide to UART Root Shells|https://www.youtube.com/watch?v=01mw0oTHwxg]]
* [[The RS-232 protocol|https://www.youtube.com/watch?v=AHYNxpqKqwo]]

SPI

* https://en.wikipedia.org/wiki/Serial_Peripheral_Interface
** https://de.wikipedia.org/wiki/Serial_Peripheral_Interface
* [[SPI: The serial peripheral interface|https://www.youtube.com/watch?v=MCi7dCBhVpQ]]
* [[Electronic Basics #36: SPI and how to use it|https://www.youtube.com/watch?v=fvOAbDMzoks]]

I²C or IIC

* https://en.wikipedia.org/wiki/I%C2%B2C
** https://de.wikipedia.org/wiki/I%C2%B2C
* https://i2c.wiki.kernel.org/index.php/Main_Page
** https://i2c.wiki.kernel.org/index.php/I2C_Tools
* https://www.kernel.org/doc/html/latest/i2c/index.html
* https://onion.io/2bt-digging-into-i2cget-and-i2cset/
* https://www.ti.com/lit/an/slva704/slva704.pdf
* https://petermolnar.net/article/linux-i2c-iio-collectd/
* https://stackoverflow.com/questions/505023/reading-writing-from-using-i2c-on-linux
* https://github.com/harbaum/I2C-Tiny-USB
** https://github.com/torvalds/linux/blob/master/drivers/i2c/busses/i2c-tiny-usb.c
* https://github.com/gschorcht/i2c-ch341-usb
* https://www.fischl.de/i2c-mp-usb/
* https://wiki.analog.com/university/courses/electronics/m2k-i2c-debug
* https://www.ti.com/lit/an/slyt770/slyt770.pdf
* https://www.instructables.com/Use-I2CLCD-to-debug-your-project/
* https://hackaday.com/blog/page/2/?s=i2c
* https://swharden.com/blog/2017-02-04-logging-i2c-data-with-bus-pirate-and-python/
* [[I2C Bit-Banged without Microcontroller!|https://www.youtube.com/watch?v=8ZYMrcHm91s]]
* [[Electronic Basics #19: I2C and how to use it|https://www.youtube.com/watch?v=_fgWQ3TIhyE]]

SMBus - subset of I²C

* https://en.wikipedia.org/wiki/System_Management_Bus
** https://de.wikipedia.org/wiki/System_Management_Bus

1-Wire

* https://en.wikipedia.org/wiki/1-Wire
** https://de.wikipedia.org/wiki/1-Wire

USB

* [[How does a USB keyboard work?|https://www.youtube.com/watch?v=wdgULBpRoXk]]
* [[How does USB device discovery work?|https://www.youtube.com/watch?v=N0O5Uwc3C0o]]



stufff

* https://hackaday.com/2022/04/04/samd11-provides-two-serial-ports-for-price-of-one/
this wiki is just an interim solution, for a better option see [[flat file/static site generator wikis / note taking]].
i followed these guides to set this up:

* https://kookma.github.io/TW5-GitHub-Saver/
* https://boffosocko.com/2020/04/04/self-hosting-tiddlywiki-with-github-pages/

but there are other methods too:

* https://kookma.github.io/Tiddlywiki-and-GitHub-Pages/

stuff:

* https://stackoverflow.com/questions/43035771/tiddlywiki-make-a-list-of-all-tiddlers-tagged-with-name-of-current-tiddler


stuff i could add:

* http://tiddlymap.org/
* nojekyll file
open

* https://reel2bits.org/
** https://github.com/reel2bits/reel2bits
* https://funkwhale.audio/
** https://open.audio/

proprietary platforms

* Spotify ist nicht cool
* https://bandcamp.com/ is recht cool
* soundcloud ist recht cool
* https://tidal.com/ cooler als spotify und auch bessere quali
** https://github.com/yaronzz/Tidal-Media-Downloader
** https://github.com/yaronzz/Tidal-Media-Downloader-PRO
* https://hearthis.at/
* https://resonate.is/about/ -  Resonate: A music streaming service structured as a cooperative

tools

* https://www.tunemymusic.com/ - convert playlists between platforms
* [[Open Sound Control (OSC) (protocol)]]
* https://en.wikipedia.org/wiki/Show_control
* [[Audio streaming]]
* [[open VJ, projection/Video Mapping]]
* https://en.wikipedia.org/wiki/Open_Control_Architecture
* https://benjamin.kuperberg.fr/chataigne/en
** https://hackaday.com/2023/01/06/chataigne-an-open-source-swiss-army-knife/
* https://ossia.io/
* see [[generator]]
* https://de.wikipedia.org/wiki/Stromerzeugungsaggregat#Betriebssicherheit
* https://de.wikipedia.org/wiki/Isolationsw%C3%A4chter
* https://de.wikipedia.org/wiki/IT-Netz
** lokale Niederspannungsnetze ohne betriebsmäßig geerdeten Sternpunkt
** https://de.wikipedia.org/wiki/Sternpunkt
* generatoren müssen in gut belüfteten umgebungen betrieben werden
* https://de.wikipedia.org/wiki/Netzform
* http://www.netzmafia.de/skripten/hardware/Elektro/Netzformen.html
* https://www.stromaggregate-portal.de/Stromaggregate_Wissenswertes/Erdspiess-Stromerzeuger.html
* https://www.stromaggregate-portal.de/Stromaggregate_Wissenswertes/Isolationswaechter.html
* https://www.elektro.net/praxisprobleme/stromerzeuger-schutztrennung-mit-isolationsueberwachung-und-abschaltung/
* [[Powerstation Einspeisung Wohnwagen / Inselnetz - Gefahren - FI / RCD / LS sinnvoll? - EcoFlow|https://www.youtube.com/watch?v=yOfR3NesAJM]]
** http://www.womo-beratung.de/Strom%20Wechselrichter%20VDE.html#FI_Personenschutzschalter,_Erdung_und_Potentialausgleich
** "Gleiches gilt übrigens für die Inverter/Generatoren. Deswegen wird auch beim Feuerwehr Inverter Honda Eu22i die zweite Steckdose mechanisch verriegelt/abgedeckt und ein Verteiler ausdrücklich verboten!"
** "in Bezug auf eine Inselsolaranlage mit Wechselrichter machst und wie man da ein Neutralleiter definieren kann" ?

<<<
Da gibt's Videos zu, zum Beispiel beim niederbairischen Elektromeister ;-) Im Prinzip wird einfach einer der beiden aktiven Leiter zum Neutralleiter "deklariert", indem man ihn vor dem FI mit dem PE verbindet. Dann muss man natürlich per Messung nachweisen, dass die Abschaltbedingungen auch alle eingehalten werden, Niederohmigkeit und so weiter...

Es gibt Anlagen, die das automatisch tun, zum Beispiel von e3/dc. Da wird im Falle eines Netzausfalls das ganze System per Motorschalter vom Stromnetz getrennt und anschließend diese besagte Brücke hergestellt...
<<<

* [[Notstrom Einspeisung für Heizung / EcoFlow / Was tun bei klassischer Nullung / TN-C Netz|https://www.youtube.com/watch?v=g3fIHcCIIMk]]
* [[RCD / Fehlerstromschutzschalter|https://www.youtube.com/watch?v=dJb-hsMCBpw&list=PLfnWMbHOvEndTD8qf-N34kTxrnsiREYHD]]
* [[Baustrom|https://www.youtube.com/playlist?list=PLfnWMbHOvEneqVrXogLtIUWrrpvMaa69n]]
* [[Stromausfall / Blackout [+ Notstrom, Inselanlage]|https://www.youtube.com/playlist?list=PLfnWMbHOvEnf59L94TrhbYGe5RGJI4Wqj]]
* [[Erstprüfung elektrischer Anlagen DIN VDE 0100 - 600|https://www.youtube.com/playlist?list=PLfnWMbHOvEndJjwvxdd2IAmYpnDPydHuf]]
** [[Erdung messen Teil1 /Fundamenterder / Erdungswiderstand 3 Leiter Messung / Erdungsstab|https://www.youtube.com/watch?v=NP2WahhBV_A]]
* [[Installationstechnik Elektrotechnik|https://www.youtube.com/playlist?list=PL3vtVjIWeZWz1_v5MPl2fNn9gp8w4vf61]]
* [[Das große Camper Elektrik 1x1: Bordstrom & Solar planen & verkabeln für Vanlife & Womo - DIY Ausbau|https://youtu.be/RiUI_0mVPN4?t=1376]]
* [[DIY PV Insel Anlage mit Speicher / Victron Energy / Mach diese Fehler Bitte nicht!|https://www.youtube.com/watch?v=xuUNABNSjok]]
* [[EcoFlow 230 V Ausgang Analyse / Integration der Powerstation / Wohnmobil Strom|https://www.youtube.com/watch?v=2NCTPfb0_TI]]
* [[FI Schalter im Wohnmobil / Camper - Auch autark nach dem Wechselrichter? Geht das?|https://www.youtube.com/watch?v=FM9lvwX39g0]]
* [[WCS Goch: Katastrophe! Götz erklärt warum!|https://www.youtube.com/watch?v=uzyUiSMB27w]]
stuff

* https://hackaday.com/tag/waveform-generator/

products

* https://joy-it.net/en/products/JT-JDS6600
** https://www.ebay-kleinanzeigen.de/s-anzeige/signalgenerator-joy-it-jds6600/2240590337-168-3477 - old 70€
** https://www.ebay-kleinanzeigen.de/s-anzeige/60-mhz-signalgenerator-jds6600/1839301509-226-4564 -125€
* https://joy-it.net/en/products/JT-PSG9080 - 80MHz 33MSa/s, 2 channel, arbitrary wave, sweep, 1 frequency counter, (USB (software windows only), modulation functions
** as "Juntek" or unbranded from china on ebay for 230€
** conrad&ELV 250€, pollin 260€
** https://www.youtube.com/watch?v=b3yFxg2LwXI
** https://eevblog.com/forum/testgear/juntek-psg9080-programmable-signal-generator-(80-mhz-300-msas-14-bit)/
* https://joy-it.net/en/products/JT-JDS2915
* https://sigrok.org/wiki/Supported_hardware#Function_generators
* [[NEW Junctek JDS8080 AWG Review - No.1060|https://www.youtube.com/watch?v=BfDzHzpdLnc]]

expensive:

* https://www.mouser.de/c/test-measurement/function-generators-synthesizers/?sort=pricing
* https://www.digikey.de/de/products/filter/ausstattung-funktionsgeneratoren/


!! cheap function generator module

had a cheap function generator from ebay

* https://pdf1.alldatasheet.com/datasheet-pdf/view/25416/STMICROELECTRONICS/TL082C.html
* 7660 - switched capacitor voltage converter
** https://www.ti.com/product/LMC7660
** https://www.maximintegrated.com/en/products/power/charge-pumps/ICL7660.html
** https://octopart.com/search?q=7660&currency=EUR&specs=0&category_id=4215&numberofpins=8&case_package=SOIC&case_package=VSSOP&case_package=SOIC+N&start=20
** https://www.microchip.com/en-us/product/TC7660
** https://www.ti.com/product/TL7660
* https://wiki.analog.com/university/tools/m2k/scopy
** https://github.com/analogdevicesinc/scopy
* http://dangerousprototypes.com/docs/Main_Page#Projects
* https://www.sump.org/projects/analyzer/
* sparkfun offers a cheap one
** https://www.digikey.de/product-detail/de/sparkfun-electronics/TOL-15033/TOL-15033-ND/9682243
* https://sigrok.org/
** https://en.wikipedia.org/wiki/Sigrok
* http://gtkwave.sourceforge.net/
** https://github.com/gtkwave/gtkwave

* [[ [001] Sigrok and Logic Analyzers |https://www.youtube.com/watch?v=dobU-b0_L1I]]
* [[ [009] DSLogic Logic Analyzer Review and Teardown |https://www.youtube.com/watch?v=xZ5wKYnCNcs]]
* [[Making Custom Silicone Mats - I Like To Make Stuff|https://www.youtube.com/watch?v=23AzbrQVKzw]]
* http://www.falstad.com/mathphysics.html
* see also [[software for acoustic simulations]]
* see also [[open source CAD software]]
* https://wpg.readthedocs.io/en/latest/wpg.html
* https://github.com/cool-RR/GarlicSim
* https://github.com/ange-yaghi/engine-sim
* ~~https://hackerboards.com/~~ https://www.board-db.org/ - Single Board Computer Database
* for tasks where [[microcontroller]]s don't provide enough power/capabilities
* raspberry pi
** https://www.jeffgeerling.com/blog/2021/m2-on-raspberry-pi-tofu-compute-module-4-carrier-board
* bananapi
** http://www.banana-pi.org/index.html
* ~OrangePi
* pine64
* beaglebone
* Odroid
* www.lemaker.org
* https://onion.io/
* [[3D Printing a Siren from a Noctua A12x25......WILL IT WORK? - Biqu B1 Review|https://www.youtube.com/watch?v=wdoVBZRyUf8]]
* [[CRAZY LOUD 3D Printed Tornado Siren - Elegoo Mars|https://www.youtube.com/watch?v=39OmzYyQ_dQ]]
* https://de.wikipedia.org/wiki/Sirene_(Ger%C3%A4t)
i've got a stock radio/control panel out of a not that old Skoda car, but the warranty is already over. Its nothing too fancy, e.g. it is a version without navigation system, but replacing it costs around 1k€ apparently?. It started having problems and they got worse over time. sometimes it wouldn't start, sometimes it would randomly crash and just be off and sometimes it would crash in a way that the audio output / built in sound system had just digital garbage noise on it.

data

* from a skoda octavia 3 (5E)
* named "Bolero"
* display model/product number: 5E0 919 605 B
* https://en.wikipedia.org/wiki/%C5%A0koda_Octavia#Third_generation_(Typ_5E;_2012)

''below is a heading "more knowledge" were i describe what i learned after some more research into the topic, it's more complex than i thought.''

I suspect an electrolytic cap is to blame because when they start to go bad the internal resistance start to rise, resulting in the ripple they are meant to smothe heating them up more, which is a vicious cycle. Then the problems that causes start to increase.

to remove the radio from the dashboard you need special hooks. the radio itself is pretty thin. It has the connectors, a 4 pin coax connector (5pin if you count the outer earth connection) and a 12 pin for power and data connections. opening it up is pretty easy, there are some screws and some pretty easy to unclip clips holding the metal back and the plastic front together.
inside of the radio is a main pcb in the middle, with the display behind it and 3 smaller pcbs arround on the sides. the smaller pcbs only manage inputs/buttons and some LEDs, they are connected with Flat Flex Cables (FFC), be careful not to damage thos cables or the connectors on the PCB when removing.

the part that got my attention first is a power supply section to the left of the 12pin connector. there is a big zener diode, an inductor, a TO-252 package and an electrolytic cap that stand out.
i suspect the problem might be with the biggest electrolytic cap, the other one are all smaller. the cap doesn't have any totaly obvious sings of being degraded, but it bight be a bit bulged.

the cap is a 25V 1000uF nippon chemi-con/united chemi-con MVE Series.

* datasheet: https://www.chemi-con.co.jp/products/relatedfiles/capacitor/catalog/MVERA-e.PDF
* looks like terminal code: A
* the datasheet states LH0 or MH0 as size codes for 25V/1000uF, but that does not match with the part on the PCB i've got, the part matches size code KE0 like the 16V/1000uF version has, something it not matching here...
* the MHS and MZA series has smaller sizes but MHS has higher temp rating (EMHS250ARA102MKE0S)
* is AEC-Q200 standard, but one without is probably also fine.
* chemi-con: https://www.chemi-con.co.jp/en/products/compare-condenser.php?part_numbers=EMHS250ARA102MKE0S,EMZA250ARA102MKE0S
* 25TLV1000M12.5X13.5 if the rubycon equivalent
* https://products.nichicon.co.jp/en/condition_search/condition_search.cfm have several
* Cornell Dubilier has a bad search

finding a replacement doesn't seem that easy. due to the pcb footprint the footprint of the part is pretty fixed. the case is approx. 2mm above the cap

one option i'll probably try is to solder a bodge capacitor parallel to the existing one to test if that one even is the culprit.

see [[quality Electrolytic Capacitors]]

!! 1st repair attempt

i finally decided to buy a ESR Meter (Peak Electronic Design ESR70) and with it i bought a couple of replacement capacitors, digikey luckily had some in stock. the stock of these more special parts is pretty volatile.

i got [[nichicon UCZ series|https://www.nichicon.co.jp/english/products/pdfs/e-ucz.pdf]] caps UCZ1E102MNS1MS.
these have a ok lifetime rating and a good temperature rating of +125°C, that should be plenty. i don't think it will be that hot in the vicinity, but it should aid in the cap lasting much longer.

i immediately tested the ESR70 on the caps in the radio all seemed fine except the one i suspected and another one, both were in parallel and that skewed the result.
The new caps measured 0.060 ohms spot on, like given in the datasheet.

I carefully de-soldered the 25V 1000uF i suspected. the small one that was in parallel with it tested fine, but the one i suspected measured a bit higher than the example values given in the ESR70 manual. iirc it measured 0.23 ohms.

because i already bought replacements i decided to just swap it out. i soldered the new nichicon one carefully in place. i checked with the ESR70 if it had good connection, because the ESR70 can also be used to measure small resistances, at least that is claimed in the user guide.

i can't test the radio at my place, or at least i don't want to risk anything by just connecting 12V or so to it. So i have to wait until the owner can try it out.

the test was unsuccessful. the device started better at first but quickly had the same problems again. so i took it back to take another look.

the power connections are pretty obvious. i tried powering it just with 12V but it doesn't do anything. there are probably other signals/lines required for the radio to boot.

https://pdf1.alldatasheet.com/datasheet-pdf/view/24648/STMICROELECTRONICS/S5H100.html that is a diode on the power lines parallel with the cap i replaced. the power supply is some switching type i don't quite get. there is another shotky diode on the positive line and somehow positive is connected to the case of the device?

!! TODO

* on older models, holding setup for some seconds enters a service menu with some diagnostic functions
* check for loose cables somewhere

!! more knowledge

after i could not figure anything out with the device i got i decided to do some research into the topic.

i first tried to find out the model of infotainment system. its the "Bolero" infotainment system used in octavia 3 E5. some other models from the VW Group also use very similar designs, that just have different optics from the outside.

i then tried finding replacement units and found some on ebay-kleinanzeigen, they go for 160€ and one is even available in Dresden. on ebay they are more expensive and cost 190€ and more.
But i also found out that the whole system is not just comprised of the Unit with the display and the amplifier, but there is a "head unit".

Also if one wants to change out parts of the system a code is needed. The codes seem to be bound to the SKZ serial numbers of the devices. it was implemented by the manufacturer allegedly to stop theft. There are websites with shops, contact forms or "calculators" offering the codes, but they are probably scam.

* https://www.motor-talk.de/forum/ueber-15-euro-fuer-einen-radiocode-t1705925.html
* https://www.skodacommunity.de/threads/radio-code.16468/
* https://www.skodacommunity.de/threads/radio-code-ganz-schnell.69546/
* https://www.skodacommunity.de/threads/radiocode-verloren-so-kommt-er-zurueck.2362/ - info is old
* https://www.skodacommunity.de/threads/wo-finde-ich-den-code-fuer-das-radio.40920/ - helpful thread
* https://www.skodacommunity.de/threads/radio-radio-code.134202/  - amp might be under the seat?

i even found a thread describing similar problems:

* https://www.motor-talk.de/forum/absturz-bolero-t5512499.html

i tried searching for the cars service manuals or wiring plans but everything seems to cost a lot of money. i found some pinouts for the infotainment system though:

* https://www.skodacommunity.de/threads/pinbelegung-quadlock.115421/
** https://www.briskoda.net/forums/topic/409691-amundsen-mib-std2-infotainment-system-with-android-in-superb-ii/

It seems that the head unit does most of the radio/audio stuff. The display only manages the User inputs and controls and the display probably.

Working on the Display was probably a complete waste of time.

sellers:

* https://www.ebay-kleinanzeigen.de/s-bestandsliste.html?userId=57485160
* https://www.ebay-kleinanzeigen.de/s-skoda-octavia-bolero/k0
* https://www.ebay-kleinanzeigen.de/s-skoda-octavia-verst%C3%A4rker/k0
* https://www.ebay-kleinanzeigen.de/pro/Autoteile-Thielking

stuff

* https://www.briskoda.net/forums/topic/477657-amundsen-mib2-firmware-update/page/51/
* can easily provide approximate solutions to the [[Travelling salesman problem]]
* https://en.wikipedia.org/wiki/Physarum_polycephalum
* [[Coding Adventure: Ant and Slime Simulations|https://www.youtube.com/watch?v=X-iSQQgOd1A]]
* https://www.spektrum.de/news/schleimiger-streckenplaner/1019760
* https://de.wikipedia.org/wiki/Schleimpilze
* [[How to Craft a Deadly Monkey Fist|https://www.youtube.com/watch?v=Dc_0ywtTogw]]
* [[Destroying an Alien Invasion With Pocket Change|https://www.youtube.com/watch?v=XQYvuWF6pSA]] (sling)
* "pocket slingshot"
* [[Dynavox PS-137 (4Ohm, 6W, 79dB)|https://www.dynavox-audio.de/produkte/spalte3/lautsprecher/ps-137-minibass-4-ohm.html]]
* [[Dynavox PS-138 (8Ohm, 14W, 80dB)|https://www.dynavox-audio.de/produkte/spalte3/lautsprecher/ps-138-minibass-8-ohm.html]]
* Tangband e.g. W3-1876S (3", 15W)
the type numbers i use here are just vaguely in the order i bought them, i don't know if they have any model names

!!Type 1:

* 4 pots
* Eigenschaften: Nicht isoliertes Buck-Modul (BUCK)
* Eingangsspannung: 6-36V
* Ausgangsspannung: 1,25-32 V stufenlos einstellbar (Standardausgang 5 V)
* MPPT-Spannungseinstellbereich: 6-36V
* Ausgangsstrombereich: 0,05-5A (Der Standardausgangsstrom beträgt 3A, für lange Zeit 3A)
* Wende
* Lichtausgangsbereich: 0,01-5 A (Standard 0,3 A) Der aktuelle Bereich ist a
* kleiner Unterschied, weil der Teileparameterfehler.
* Multifunktionale Doppelanzeige: Eingangsspannung, Ausgangsspannung, Ausgangsstrom, Ausgangsleistung
* Betriebstemperatur: -40 bis + 85 Grad
* Betriebsfrequenz: 180 kHz
* Umwandlungswirkungsgrad: bis zu 95% (Wirkungsgrad hängt von Eingangsspannung, Ausgangsspannung, Strom und Spannungsdifferenz ab)
* Kurzschlussschutz: Ja
* Übertemperaturschutz: Ja (Ausgang nach Übertemperatur automatisch abschalten)
* Eingangsverpolungsschutz: Keine (falls erforderlich, fügen Sie den String in die Diode ein)
* Ausgabe
* Anti-Bewässerungsschutz: Keine, der Ausgang muss an die angeschlossen werden Batterie plus Sperrdiode, sonst brennt das Modul!
* Aufladen
* Anzeige: Aufladen rot, voll aufgeladen grün. Lichterkennungsweg drehen Für Strom. Wenn Sonnenkollektoren zur Stromversorgung verwendet werden, die kleine Sonne
* Ladestrom ist auch sehr klein, weniger als der Strom des Blinklichts, es
wird grünes Licht, aber es ist nicht voll, bitte beachten Sie diese Unterscheidung.
* Einbauhinweis: 3mm Schrauben (4)
* Anschluss: Klemmen, IN wird eingegeben, OUT wird ausgegeben
* Größe: 60 * 31 * 22 mm (L * B * H)

!! Type 2:

* 2 pots
* input voltage: DC 8 - 28V
* Ausgangsspannung : DC5 - 26V stufenlos
* Ausgangsstrom : 5A
* Verwendbar f ü r : 6V oder 12V Batterie , 8 . 4V , 12 . 6V , 16 . 8V Lithiumbatterie , 7 . 2V , 10 . 8V , 14 . 4V Lithiumeisenphosphat - Geb ü hrenmanagementbrett
* Niederdruck : 1V
* Arbeitstemperatur : - 40 - + 85 ℃
* Lasteinstellung : ± 1 %
* Spannungsregelung : ± 0 , 5 %
* Umwandlungseffizienz : Max : 93 % Spitze : 95 %
* Leerlaufstrom : 3mA
* MPPT Spannung : Einstellbar
* Protections: input AC, input polarity reversal protection, reverse current protection
* Size: ca. 1,57"x0,79"x1,97" / 4 x 2 x 5 cm 

main chip: https://www.alldatasheet.com/datasheet-pdf/pdf/1132128/CONSONANCE/CN3722.html - 5A, Multi-Chemistry Battery Charger IC 
With Photovoltaic Cell MPPT Function

* Wide Input Voltage: 7.5V to 28V 
* Complete  Charger  Controller  for  1  
or  multi-cell  Lithium-ion  Battery  or  
LiFePO4 Battery 
* behringer flow 8 - only bluetooth
* https://www.studiomaster.com/digitalmixing/digilive4c/#
** https://www.musik-produktiv.at/studiomaster-digilive-4c.html
inspiration

* https://www.youtube.com/watch?v=KTvVS8guBsY
* https://mitxela.com/projects/flash_synth
* https://mitxela.com/projects/rumbler
* https://mitxela.com/projects/silly_synth
* https://mitxela.com/projects/smallest_midi_synth

idea:
building a tiny noise generator, maybe with different noise options, for use in a PA setting. The whole circuit should be powered by phantompower like from any ordinary mixing console and fit in an ordinary 3 pin XLR connector.

the pcb can be directly soldered to the solder cups, like between them.
the pcb has to be arround 13.5mm wide to fit the connectors i got.

i'll probably also use the STM32L432KC like [[in this project|https://mitxela.com/projects/flash_synth]].
i've got a small ST Nucleo32 board 
i was thinking about using a risc-v MCU like one of the Gigadevices GD32L103, but i'm not quite experienced enough i think.

some stuff that might come in handy:

* https://www.st.com/en/embedded-software/stm32-audio100a.html
* https://www.st.com/resource/en/application_note/cd00259245-audio-and-waveform-generation-using-the-dac-in-stm32-microcontrollers-stmicroelectronics.pdf
* https://www.digikey.de/en/blog/audio-processing-with-stm32
* https://pcbartists.com/firmware/stm32-firmware/stm32-audio-tutorial-part-2-codec-i2c-setup/
* https://forum.allaboutcircuits.com/threads/producing-sound-using-stm32.89810/
* https://www.st.com/en/microcontrollers-microprocessors/stm32l432kc.html#overview
* https://deepbluembedded.com/stm32-dac-tutorial-example-hal-code-analog-signal-genreation/
* https://stm32world.com/wiki/STM32L432
* https://www.st.com/en/evaluation-tools/nucleo-l432kc.html#documentation
* https://hackaday.com/2022/05/24/the-stm32-makes-for-a-cheap-diy-usb-soundcard/

programming:

* c/c++ or rust?
while reading the WLED documentation and seing that it can output DMX i had the idea to make a small DMX over wifi receiver that fits into an off-the-shelf XRL connector.

similar:

* https://www.thomann.de/de/eurolite_akku_quickdmx_wireless_receiv.htm
* https://www.thomann.de/de/eurolite_quickdmx_wireless_receiver.htm
* there are "Wireless DMX512 2.4G Led Stage Light PCB Modules Board" one can get for around 15€ on ebay

see [[DMX]]

!! Connector (XLR)

see [[DMX Connector]]

thread

* seetronic: M18x1,5
* neutrik mxx: ...x1,0

!! controller

* Firmware: WLED, ESP artnet node or so
** [[esp32 dmx / artnet node]]
* modules
** ESP8266 ESP-01(S)
** ESP-03
** ESP-M1 & ESP-M2
** esp8285
*** ESP-01D
*** ESP-M3
*** ESP-01M
*** ESP-01F
* http://esp8266.net/
* https://hackaday.com/2023/09/07/how-small-can-the-esp32-get/

having a PCB antenna is simpler, but the pcb might need more space, but having a external antenna might be possible too and might provide better signal/connection

!! power

i forgot about powering it... that might be a bit harder to fit in a small space

18650 is really close to the XLR size

maybe some small flat cells?

integrated charger

!! case

maybe use 20mm diameter 5mm wall thickness aluminium tube, could be maschined and might fit with common XLR connectors

* or just ABS junction boxes or so
* doesn't have to be waterproof
i had the idea to build a small wireless midi transeiver using existing midi over network protocols.

see [[Midi]]

* https://mitxela.com/projects/flash_synth
* https://mitxela.com/projects/silly_synth
* https://mitxela.com/projects/polyphonic_synth_cable
* https://mitxela.com/projects/smallest_midi_synth
* https://mitxela.com/projects/midi_over_bluetooth
someone came with a Sennheiser Wireless Microphone where the cables leading to the Microphone Capsule were ripped of, i opened the Mic, removed the old wires (were to short to just resolder) and soldered new, slightly longer wires to the capsule (to also help the cables not to get ripped off again)


a nice lamp with independently dimmable cold and warm white LEDs had shorted diodes from the factory, i ordered replacement rectifier diodes and a new fuse, i soldered them in and repaired some blown tracks... then the lamp functioned again


i've got a set of two small hand-held radios, they are more like toys. the speaker in one of them failed, i searched around for potentially working speakers i had lying around, but the original one had 32Ohms and other speakers wouldn't work. i eventually found two matching speakers on digikey, they where cheap, so i bough one of both
* https://www.gl-inet.com/products/
* https://github.com/srlabs/blue-merle
preferably open source, not any gas-powered ones

* https://www.pine64.org/pinecil/
** https://pine64.com/product/pinecil-smart-mini-portable-soldering-iron/?v=0446c16e2e66
** https://hackaday.com/2021/01/05/review-pine64-pinecil-soldering-iron/
** https://eevblog.com/forum/reviews/pine64-pinecil-anyone-(dc-jack-usb-c-pdqc-soldering-iron)/
** https://www.tomshardware.com/reviews/pinecil-v2
** https://arnowelzel.de/pinecil-v2
* [[EEVblog #1114 - NEW TS80 USB Soldering Iron Review|https://www.youtube.com/watch?v=_Z9es-D9_8g]
* TS100 / TS101
** https://hackaday.com/2017/07/24/review-ts100-soldering-iron/
* aliexpress: "smart lötkolben"]
* https://www.tomshardware.com/reviews/fnirsi-hs-01
* https://www.reddit.com/r/AskElectronics/comments/l3tjgf/pinecil_alternative/
* https://www.taschenlampen-forum.de/threads/pinecil-l%C3%B6tkolben.85635/
* https://eleshop.de/atten-soldeerbout-st-2065d.html

* https://www.tomshardware.com/search?searchTerm=soldering
* https://netzpolitik.org/2023/beschlagnahmte-smartphones-ein-grundrechtseingriff-unbekannten-ausmasses/
* https://www.kuketz-blog.de/android-bei-jeder-standortermittlung-erfaehrt-google-eure-position-inkl-imsi-nummer/
* https://en.wikipedia.org/wiki/Comparison_of_mobile_operating_systems

android

* https://github.com/JStumpp/awesome-android#readme
* https://lineageos.org/
** https://wiki.lineageos.org/
** https://en.wikipedia.org/wiki/LineageOS
** https://lineageosroms.com/ - unofficial but maybe helpful
** porting
*** https://wiki.lineageos.org/device_requests.html
*** https://fat-tire.github.io/porting-intro.html
*** https://wiki.lineageos.org/build_guides.html
*** https://wiki.lineageos.org/addingdevice-howto.html
*** https://wiki.lineageos.org/submitting_device.html
*** https://www.reddit.com/r/LineageOS/comments/mnekcp/what_steps_can_i_take_to_port_lineage_os_to_my/
* https://en.wikipedia.org/wiki/LineageOS#Forks
* https://en.wikipedia.org/wiki/List_of_custom_Android_distributions
* Recovery Systems
** android stock one
** TWRP - https://twrp.me/
*** https://en.wikipedia.org/wiki/Team_Win_Recovery_Project
** https://en.wikipedia.org/wiki/ClockworkMod#ClockworkMod_Recovery
* Alternative App Stores
** fdroid - 
*** setting up f-droid playstore-repos
**** https://github.com/NoMore201/playmaker
**** https://github.com/matlink/gplayweb
** playstore mirrors/frontends
*** Aurora Store
*** https://www.apkmirror.com/
*** https://apkpure.com/
*** https://apk-dl.com/
*** https://www.makeuseof.com/tag/google-play-alternatives-downloading-android-apps-without-fuss/
*** https://www.makeuseof.com/tag/download-apk-google-play-bypass-restrictions/
* google-free android
** custom rom + MicroG + fdroid
** https://microg.org/
** https://lineage.microg.org/ - lineage with microg and fdroid allready fully setup
* adb
** https://wiki.lineageos.org/adb_fastboot_guide.html
** https://wiki.lineageos.org/how-to/logcat
** https://wiki.lineageos.org/how-to/adb-over-wifi
** https://stackoverflow.com/questions/11129817/adb-over-bluetooth-android

apps

* https://f-droid.org/packages/de.corona.tracing/
** https://github.com/mh-/corona-warn-companion-android
** https://github.com/corona-warn-app
* https://f-droid.org/de/packages/com.governikus.ausweisapp2/
* OsmAnd
** https://www.osmand.de/

android alternatives

* https://postmarketos.org/
** https://en.wikipedia.org/wiki/PostmarketOS
** https://wiki.postmarketos.org/wiki/Devices
** https://wiki.postmarketos.org/wiki/Porting_to_a_new_device
* UBPorts / Ubuntu
* ...

android emulators for linux

* https://anbox.io/
** https://www.makeuseof.com/tag/run-android-apps-games-linux/
* https://developer.android.com/studio AVD (Android Virtual Device)
* http://www.android-x86.org/
* http://www.shashlik.io/

linux on android

* Termux
* Debian Noroot
* UserLAnd
* AndroNix
* Linux Deploy (root)

nexus 5 hammerhead

* https://wiki.lineageos.org/devices/hammerhead
* https://www.zdnet.de/88376265/lineageos-android-10-fuer-nexus-5/

motorola moto G (2015) osprey

* https://wiki.lineageos.org/devices/osprey
* https://download.lineageos.org/osprey

uses for old, outdated phones

* resurect them with alternative firmware like postmarketOS
* webserver
** https://tech.scargill.net/android-phone-as-a-server/
** https://hackernoon.com/how-to-turn-an-android-device-into-a-web-server-9816b28ab199
* controller for a quadcopter

security / privacy

* https://arxiv.org/pdf/2110.07450.pdf
* https://www.heise.de/news/Schlimmer-als-Google-Welche-Daten-alternative-Android-Hersteller-sammeln-6219469.html

old phones:

* https://altehandys.de/



stuff:

* https://www.tutonaut.de/android-automatisierung/
** https://f-droid.org/de/packages/com.jens.automation2/
* 14.6V 20A LiFePO4 Charger
** TL494C "Switchmode Pulse Width Modulation Control Circuit"
** LM358 Dual Opamp
* https://duckduckgo.com/?t=ffab&q=audio+amplifier+smps&ia=web
* https://www.diyaudio.com/community/threads/smps-in-audio.378431/
* https://www.superbestaudiofriends.org/index.php?threads/using-an-smps-for-audio-amps.2455/
* https://www.homemade-circuits.com/smps-2-x-50v-350w-circuit-for-audio/
* https://electronics.stackexchange.com/questions/469364/smps-for-stereo-audio-amplifier
* https://www.audiosciencereview.com/forum/index.php?threads/smps-for-audio-applications.14307/
* https://www.psaudio.com/pauls-posts/smps/
* https://www.ti.com/lit/an/snaa057c/snaa057c.pdf
* https://vtvamplifier.com/wp-content/uploads/2020/04/SMPS3KAx00_10xx-1.pdf
* https://www.edaboard.com/threads/what-smps-topology-are-the-best-suitable-for-audio-power-amp.18521/
* https://en.wikipedia.org/wiki/Snubber
** https://de.wikipedia.org/wiki/Snubber
* https://hackaday.com/tag/bubble-machine/
* https://hackaday.com/tag/bubble-blower/
* https://hackaday.com/tag/bubble-maker/
* https://hackaday.com/2020/07/31/the-internet-of-bubble-machines/
* https://hackaday.com/2016/07/30/arduino-absentmindedly-blows-bubbles/
* https://hackaday.com/2019/01/18/talking-with-bubbles/


foam maschines

* https://hackaday.com/2012/09/28/how-to-build-a-foam-machine-for-your-next-party/
* https://hackaday.com/2010/04/22/build-a-foam-machine/
* https://www.golem.de/news/akkutechnik-und-e-mobilitaet-natrium-ionen-akkus-werden-echte-lithium-alternative-2106-156863.html
* https://www.golem.de/news/natrium-ionen-akkus-ausnahmsweise-ein-echter-durchbruch-in-der-akkutechnik-2006-149130.html
* https://twitter.com/DKurac/status/1402854199080099841
* Faradion produced by https://amtepower.com/our-products/
** https://amtepower.com/wp-content/uploads/2020/05/ULTRA-Safe-AMTE-A5-leaflet.pdf
* CATL
** https://www.catl.com/en/news/665.html
** https://www.golem.de/news/akkutechnik-catl-stellt-erste-natrium-ionen-akkus-fuer-autos-vor-2107-158529.html
** https://cnevpost.com/2021/05/21/nios-battery-supplier-catl-says-it-will-release-sodium-ion-batteries-around-july/
* [[Sodium Ion 18650 Battery Discharge Test|https://www.youtube.com/watch?v=xBPwZzBhCvE]]
* https://en.wikipedia.org/wiki/Category:Software_development_philosophies
see also [[speaker design software / calculators]], [[Simulators]]

* COMSOL Multiphysics - https://www.comsol.de/ - proprietary
** https://de.wikipedia.org/wiki/COMSOL_Multiphysics
** https://en.wikipedia.org/wiki/COMSOL_Multiphysics
** stuff
*** https://www.comsol.com/acoustics-module
*** https://www.comsol.com/blogs/6-examples-of-simulation-driven-loudspeaker-development/

* finite element analysis - https://en.wikipedia.org/wiki/Finite_element_method
** https://de.wikipedia.org/wiki/Kategorie:Software_f%C3%BCr_Finite-Elemente-Berechnung
** https://en.wikipedia.org/wiki/List_of_finite_element_software_packages
** https://www.researchgate.net/post/What-is-the-best-open-source-finite-element-software-for-mechanical-problems
** https://parafem.org.uk/

* Boundary element method
** http://www.boundary-element-method.com/
*** http://www.boundary-element-method.com/acoustics/
** http://www.sam.math.ethz.ch/betl/
** https://temf.github.io/bembel/
** https://bempp.com/
** http://www.yijunliu.com/Software/
** https://sourceforge.net/projects/puma-em/
** http://www.boundaryelements.com/index.php
** https://en.wikipedia.org/wiki/Boundary_element_method
** https://de.wikipedia.org/wiki/Randelementmethode

* multiphysics
** https://www.tu-braunschweig.de/ifl/forschung/multiphysics
** https://en.wikipedia.org/wiki/Multiphysics

* Elmer - https://www.csc.fi/web/elmer
** https://de.wikipedia.org/wiki/Elmer_(Software)
** https://sourceforge.net/projects/elmerfem/
** http://www.elmerfem.org/blog/
** [[Speaker - FEM Acoustic Simulation with Elmer|https://www.youtube.com/watch?v=dfLHVUcvnDo]]
* http://emlab.utep.edu/opensource.htm
* ~OpenFOAM - https://openfoam.org/
** https://www.openfoam.com/
** [[How to run your first simulation in OpenFOAM® - Part 1 - tutorial|https://www.youtube.com/watch?v=KznljrgWSvo]]
* http://acousto.sourceforge.net/
* https://fenicsproject.org/
* https://firedrakeproject.org/
* https://www.featool.com/
* https://github.com/maqifrnswa/scimpy
* http://www.hifi-forum.de/viewthread-42-54.html#1
* wavefront / wavefront propagation simulations
* https://phet.colorado.edu/en/simulations/filter?subjects=sound-and-waves&sort=alpha&view=grid
 * https://phet.colorado.edu/en/simulation/sound
* https://www.falstad.com/mathphysics.html
* https://github.com/IoSR-Surrey/PyZones
* https://github.com/luisgonzalex/Room-Acoustics-Sim
* https://github.com/syauqylei/WaveSimulation
* https://github.com/flaviostutz/acoustics-simulator
* http://www.k-wave.org/
* https://github.com/kpyuan1776/acousticSimWrapper
* coda audio (propietary):
** https://codaaudio.com/softwares/coda-system-optimiser/
** https://codaaudio.com/softwares/ease-focus-ii/
* https://www.afmg.eu/index.php/products.html
* https://i-simpa.ifsttar.fr/ - An Open Source software for 3D sound propagation modelling
** https://github.com/Ifsttar/I-Simpa
* https://noise-planet.org/index.html
* https://github.com/topics/room-acoustics
* https://github.com/topics/acoustic
** https://github.com/ovcharenkoo/WaveProp_in_MATLAB
** https://github.com/ovcharenkoo/CUDA_FDTD_2D_acoustic_wave_propagation
** sound modelling, sound propagation modelling, wave propagation modelling
* https://soundlab.cs.princeton.edu/software/
* https://www.afmg.eu/index.php/products.html
* https://amcoustics.com/tools/amroc - Room Mode Calculator
* https://lightbit.gitlab.io/file/
** https://gitlab.com/LightBit/SpeakerSim/
* https://www.ness.music.ed.ac.uk/
** https://www.heise.de/hintergrund/Wie-klingt-eigentlich-eine-kilometerlange-Trompete-6268452.html?utm_source=pocket-newtab-global-de-DE

* https://github.com/search?q=acoustic+sim

a basic solar or photovoltaic system contains of:

# the solar panels
# a charge controller which charges the battery until it's full - https://libre.solar/devices/cc-overview
## an [[MPPT|MPPT - Maximum Power Point Tracking]] charge controller, draving the ideal ammount of current to get the most out of the solar panels to charge the battery
## PWM charge controller - not as interresting i think
## https://learn.libre.solar/system/charge_controller.html
# some [[battery|accumulator - battery - rechargeable energy storage]] for storage/buffer
## the battery should have a [[BMS|Battery Management System (BMS)]] or some type or protection circuitry because most battery types will atleast take damage and loose capacity when over discarged
# [[DC microgrid / nanogrid]] to supply some devices
# some a [[power inverter|inverter (Wechselrichter)]] or other [[power supply circuitry|switched mode power supply (SMPS)]] to convert the power to the needed/desired AC or DC voltage

informations:

* https://www.ose-germany.de/projekte/libresolarbox/
* https://libre.solar/
** https://learn.libre.solar/system/
* https://wiki.opensourceecology.de/SolarBox
* [[https://wiki.opensourceecology.de/Solarspeicher_(station%C3%A4r)]]

advanced:

* https://de.wikipedia.org/wiki/Solarsimulation
* https://en.wikipedia.org/wiki/Solar_irradiance
* https://de.wikipedia.org/wiki/Insolation_(Physik)
* https://photovoltaic-software.com/principle-ressources/how-calculate-solar-energy-power-pv-systems
** https://photovoltaic-software.com/pv-softwares-calculators
*** https://photovoltaic-software.com/pv-softwares-calculators/online-free-photovoltaic-software
* https://www.sisifo.info/en/default
<<list-links "[all[current]tagging[]]">>

* [[YT: DIY Solar Power with Will Prowse|https://www.youtube.com/channel/UCoj6RxIAQq8kmJme-5dnN0Q]]
* [[YT: Land to House|https://www.youtube.com/c/LandtoHouse]]
* [[YT: jehugarcia|https://www.youtube.com/channel/UCcMfCkN1juSa49DJFYltOTw]]
* [[GreatScott!|https://www.youtube.com/channel/UC6mIxFTvXkWQVEHPsEdflzQ]]
* [[Basic Solar Parts Needed for a DIY Camper Van or RV Solar Install|https://www.youtube.com/watch?v=xuZg4NasCVw]]
* [[12v Solar Charge Controller Buyers Guide - Beginner Friendly!|https://www.youtube.com/watch?v=kF_cVEYxj3E]]
* https://wiki.opensourceecology.de/Open_Source_Ecology_Germany
* https://hackaday.io/search?term=solar
* https://www.ose-germany.de/projekte/libresolarbox/
* https://libre.solar/
** https://learn.libre.solar/system/
* https://www.eevblog.com/forum/renewable-energy/
* https://www.youtube.com/channel/UCHrBjgyy51_c0s_CYh8iizg
* https://diysolarforum.com/
* https://www.mobile-solarpower.com/

stuff:

* [[How to Design an Off-grid Solar Power Array Wire Configuration|https://www.youtube.com/watch?v=C-k0WHJ4RxQ]]
* https://youtu.be/oGLkXuJaTiM
* https://www.youtube.com/c/opengreenenergy
* [[Optimizing a Small Off Grid Solar System.|https://www.youtube.com/watch?v=SfRTSo4sJAQ]]
* [[DIY: 12kW Solaranlage + 22kWh Batterie & das richtig günstig|https://www.youtube.com/watch?v=K0Ea4-O2Q4o&list=PLQ2DhY8DrRvyt_o8eeLeKedzLWQ-huw0t]]
* https://selbstbau.solar/
* [[Testing Solar Panel Defects|https://www.youtube.com/watch?v=YZ8_Xk9aYTE]]
* https://www.lowtechmagazine.com/2021/10/how-to-build-a-low-tech-solar-panel.html
* see [[battery pack safety]]
* see [[electronics safety]]
* see [[Schutzschaltungen / Sicherungen]]
* fuses
* [[Fuses - Solar Safety Part 1 - 12v Solar Shed|https://www.youtube.com/watch?v=GyzrxAwxtgA]]
* [[Breakers AC, DC & AC/DC - Solar Safety Part 2 - 12v Solar Shed|https://www.youtube.com/watch?v=S0diAeysxVo]]
* [[300 Amp Fuse Blowing with 4KW of Load from an Inverter - Safety Mechanism Prepare for the Unexpected|https://www.youtube.com/watch?v=gMvrMemPxrg]]
* high DC systems
** https://diysolarforum.com/resources/solar-array-arc-fault-protection-summary.145/
* [[Electric Cable & Fuse Sizing - Camper Van Conversion Series|https://www.youtube.com/watch?v=koFg6oFs0RU]]
* [[Fuses EXPLAINED! What size do YOU need & MORE!|https://www.youtube.com/watch?v=0H005TcKHKo]]
* [[Electricity Explained: Volts, Amps, Watts, Fuse Sizing, Wire Gauge, AC/DC, Solar Power and more!|https://www.youtube.com/watch?v=cX4s-bxn4fs]]
* https://en.wikipedia.org/wiki/Solar_thermal_energy
* https://www.instructables.com/Solar-OSE-Solar-concentrator-for-steam-generation/
* https://en.wikipedia.org/wiki/Category:Solar_architecture - https://de.wikipedia.org/wiki/Kategorie:Solararchitektur
** https://en.wikipedia.org/wiki/Trombe_wall
*** https://de.wikipedia.org/wiki/Trombe-Wand
* http://www.stadtbus2.de/magazin/m_tut_solaris-hybrid.htm
* https://www.solarisbus.com/public/assets/content/pojazdy/Katalogi_stycze_2020/DE_Napdy_zeroemisyjne_2019_02.pdf
* https://invidio.us/watch?v=hHI61GHNGJM
* "Solarpunk is a Revolt of Hope Against Despair"
** Read about the optimistic aesthetic here: https://solarpunkanarchists.com/2016/05/27/what-is-solarpunk/
* https://t.me/SolarPunk
* https://www.youtube.com/watch?v=nyuvUPAI0gg
* https://www.ozy.com/fast-forward/sci-fi-doesnt-have-to-be-depressing-welcome-to-solarpunk/82586
* https://hackaday.com/2023/04/21/solar-protocol-envisions-a-solar-powered-web/
* carbon or hepa filter?
* stacked PC fans for more stativ pressure trough the filter?
* https://neonkev.com/2021/03/07/diy-high-performance-solder-fume-extractor/
appart from obvious required tools like a solodering iron, there is other stuff that can make life more easy

* aluminium foil tape - to deflect heat, protect parts of a circuitboard from heat
* microscope - for smd and small board work
** DIY microscopy
** maybe with HD cam
** ring light for good illumination
* https://northridgefix.com/product-category/repair-tools/


soldering irons

* [[ SDG #284 130W Capable JBC C245 Soldering Iron |https://www.youtube.com/watch?v=ge7WHLgs4q8]]
* TS100 soldering irons
* pinecil
* [[ NF.Mini Amazing Micro Soldering pen review |https://www.youtube.com/watch?v=SP_R4Zkza0Y]]
see [[pcb repair]]

general/soldering

* https://www.stannol.de/ has some good quality products
* 

repair

* solder mask
** often used keywords: "UV Solder Mask PCB repair paint soldering"
** needs uv-source for curing
* UV glue?
* "isolierlack"
* flux
** (liquid) rosin flux
** flux pen
* glass fibre brush
* https://de.aliexpress.com/wholesale?trafficChannel=main&d=y&CatId=0&SearchText=pcb+repair&ltype=wholesale&SortType=default&page=2
* solder wick
* small pcb grinding pen (polish; handy schleif stift
* rosin evaporator
* PCB holders
* conductive silver paint? i'm pretty sceptical about it
* solder pads
* jumper wire (pen/tool) ("flying pen")
* cutters, scalpell

cleaning

* http://www.kontaktchemie.com/KOC/KOCproductsV2.csp
** Kontakt WL - general cleaning, removing flux
** Kontakt PR - cleaning potis
** Kontakt 600/Tuner 600?
* q-tip
* esd safe brushes
* solder wick
* flux
** (liquid) rosin flux
** flux pen


* Kontakt 60 - eher für grobe sachen, filmrückstände oxidieren kupfer, messing, und kohle/grafitschichten
* Tuner 600/kontakt 600/ Kontakt WL - reinigung, verdunstet rückstandslos, super für flussmittel-reste
* Kontakt 61 / Kontakt Gold 2000 - schmier/gleitmittel, schutz, u.A. für potis/fader geeignet
* Kwasny Kontaktreiniger aus'm Globus - günstig auch für potis geeignet
** https://www.globus-baumarkt.de/spraytec-kontaktreiniger-400ml?fs=592332339
** https://www.auto-k.de/lacksprays/weitere-marken/spraytec/technische-sprays/kontaktreiniger-spray/
* faderreiniger extra für fader
** oder Bahn mit isoprop und nem qtip reinigen und danach mit harzfreiem Öl schmieren
* Mannol 9893 ?
* A-Z Elektronik in Dresden empfehlt wohl Teslanol Kontaktspray (~7€) auch für Potis, keine ahnung wie die langzeit erfahrung damit ist, ob das die kontakte bzw. grafitbahnen angreift
* http://www.miniware.com.cn/product-category/soldering-pen/hot-plate-preheater/
** Miniware MHP30
** [[MiniWare MHP30 Hot Plate Review - Reflow, Rework, Solder or De-solder SMD or THT components|https://www.youtube.com/watch?v=JKlTd1B6Au8]]
* various simple ones can be found by "soldering heating plate" or similar on ebay
* projects on hackaday
** https://hackaday.com/tag/hotplate/
** https://hackaday.com/blog/page/2/?s=solder%20plate
** https://hackaday.com/tag/hot-plate/
** https://hackaday.com/2018/04/25/reflow-rig-makes-smd-soldering-a-wok-in-the-park/
** https://hackaday.com/2016/05/21/ptc-heaters-for-reflow-soldering/
** https://hackaday.com/?s=reflow+oven
* [[The Best way to Solder? Hot Plate to the rescue! (DIY or Buy)|https://www.youtube.com/watch?v=QarizoUnRfk]]
this is about hacking for fun... hacking is not just about computers

* wifi pineapple
** Karma
** rickroll
* https://www.youtube.com/watch?v=rJ5jILY1vlw
* bug bounty stuff like with hackerone
* https://www.greatscottgadgets.com/
globalization

* globalization is sometimes more sustainable, but some things are better if locally sources (e.g. less transportation)
* over all globalization is not bad and has good benefits
* globalization of knowledge is fundamental to the collective knowledge of humanity
* but local and decentralised production and sourcing is sometimes better
* though this must not mean nationalism and such
* the rituals and traditions of different people living in different places where allways shifting, mixing and transforming since humans exist, so it is nothing bad today

war and weapons

* humans should have the ability to live peacefully together... i hope were not as primitive as we seem to be
* wars might not even benefit the economy (https://www.thoughtco.com/are-wars-good-for-the-economy-1148174) and only bring death and pain
* ban weapons with artificial intelligence
** https://youtu.be/qhvuBT1Mvz0 (DE)
** https://www.youtube.com/watch?v=9fa9lVwHHqg&t=14
* https://www.sonnensystem.info/
* https://pluto.sonnensystem.info/
** https://nachbauen.sonnensystem.info/

similar:

* https://eventbikezero.de/
* https://www.pikip-solarspeakers.com/en
** based on 48V pyltontec rack battteries, 230V powersoft amps and inverter

die Designs der boxen sind u.A. von BS-Tek aus bayern, dass design vom kompletten system, primär der Ton und Strommodule/powerpacks (und von der alten version des ganzen) ist von den sonnensystem menschen aus braunschweig

* https://www.eton-gmbh.com/produkte/car-hifi/verstaerker/product/power-4502/


<<list-links "[all[current]tagging[]]">>
* carla cargo: 20" 55-406 - Schwalbe Big Ben Plus
* Räder 
** 47-507 (24 x 1.75) - Schwalbe Marathon Plus
*** alt: 24 x 1.95 (50-507)
*** Felgenband Schwalbe HP 22-507
*** Schlauch: 24" (507) Schwalbe DV10
** 55-406 (20 x 2.15) - Schwalbe Big Ben (Plus?)
*** alt: 20 x 1.95 (50-406)
*** Felgenband: Schwalbe HP 22-406
*** Schlauch: 20" (406) Schwalbe DV7
CAD drawings / immages of the wiring inside the modules
immages/illustrations showing how everything plugs together

using allready existing models and [[Open Source/Creative Common vectors/SVGs]]

original CADs made using CATIA, i use ~FreeCAD.
for other immages i use inkscape

anderson powerpole (SBE 160) instead of ravioli plugs:

* https://www.andersonpower.com/us/en/resources/SBEXOResourcesPage.html
* https://www.andersonpower.com/content/dam/app/ecommerce/product-pdfs/SBE160-SBX175/114127S1.pdf
_____

* need din rail CAD model
* CAD model for isolationchecker and circuit breaker
* ask local bussiness to donate needed parts
the whole signal chain of the current ~SoSy Setup has to be checked in order to get the best sound quality and as prerequisite to measuring the frequency response of the whole system.


!  [[5-Wege horngeladene PA wird neu verkabelt - Auftrag Sound 25|https://www.youtube.com/watch?v=PUjD0vGstwk]]


* [[ FREE Acoustical Measurement Software: Room EQ Wizard (REW) |https://www.youtube.com/watch?v=td7Ue86Snfc]]
* [[#REW #TUTORIAL #LAUTSPRECHER - REW (Room EQ Wizard) von Anfang an erklärt - Teil 1|https://www.youtube.com/watch?v=dZIPGvgGOQs]]
** [[#REW #TUTORIAL Teil 2 #DIY - REW (Room EQ Wizard) von Anfang an erklärt - SPL Messmenü erklärt|https://www.youtube.com/watch?v=-81GDvqCoqE]]
** [[Ach deshalb klingt es so lahm - Group Delay #REW (Room EQ Wizard) Die Messung der Gruppenlaufzeit|https://www.youtube.com/watch?v=9SNLU69nJQM]]
* [[Room EQ Wizard (REW) Tutorial German - Einmessung von Lautsprechern mit REW|https://www.youtube.com/watch?v=5vL2KdUjqiQ]]
* [[speaker testing, measurement and analysis]]

check gain chain

* https://www.jobst-audio.de/tool/helfer/limiter-rechner

! inputs:

* yamaha mg06 (?)
** ~~"stereo out" +4dBu (?)~~
** to unbalanced 6.3mm jack
** https://de.yamaha.com/de/products/proaudio/mixers/mg_series_xu_model/specs.html#product-tabs
** +4 dBu (1.228 V) balanced... aber auch unbalanced?
* xlr to unbalanced 6.3mm jack


! [[the t.racks DSP 4x4 Mini|the t.racks DSP 4x4 Mini and Mini Pro reverse engineering]]

* the gains, sensitivity and internal reference is a bit fucked up, the thomann reviews describe it pretty well it seems
* the inputs and outputs don't seem to have overhead and clip sooner than given in the datasheet it seems
* unbalanced inputs and outputs seem to have a bit more room till clipping, but better check the current setup for issues
* i can also check the real performance with my 4x4 mini dsp
* check
** input sensitivity
** input clipping point
** input gain
** gains inbetween, like excessive gain in EQ
** output gain
** output clipping point
** output "sensitivity"/level
** system gain
** more/other gain?


!! the other dsp

* similar to the dsp 4x4 mini, but different
* Thomann t.racks DS 2/4: +5dBu * maybe?
* laut jobst: Thomann t.racks DS 2/4: 0dBu ** DSP senkt Pegel um 5dB ab


!amps

* sensitivity / gain?
* 3x [[Eton POWER 450.2|https://eton-audio.com/verstaerker/power-450-2.html]]
** [[manual|https://eton-audio.com/media/catalog/product/bedienungsanleitung/BDA_POWER_AMP.pdf]]
** Output Power @ 14,4V 1% THD: 2x 270W RMS @ 4Ohm; 2x 454W RMS @ 2Ohm
*** Verstärkerleistung an 4 Ohm: 2x270 (1x908 gebr.) W(RMS)
*** Verstärkerleistung an 2 Ohm: 2x454 W(RMS)
*** Bridge output power measured @ 14,4V 1% THD: 1x 908W RMS @ 4W
*** theoretisch 135W in 8Ohm, vielleicht auch 140W
** THD+N (total harmonic dist. + noise) @ 1WRMS 13,6V / 4Ohm: 0,008%
** THD+N (total harmonic dist. + noise) @ 5WRMS 13,6V / 4Ohm: 0,006%
** different setups: bridged mode for bass, stereo mode for small tops and bridged mode for big tops
* 2ohm min. in stereo, 4ohm min. in bridged
* gain might have to be checked manually using osci
* gain settings of the amps was done rather arbitrary it seems, because the information i got and the settings i've seen the last time i touched the amps was very contradicting
* line level inputs are used
* internal filters are not used
* externe pegelfernbedienung überbrückt? -> verbessert signal-rausch-abstand

<<<
LAUTSTÄRKE (GAIN) EINSTELLEN

Dieser Regler dient der Anpassung Ihrer
Verstärkerkanäle an das Ausgangssignal
Ihrer Audioquelle. Für eine bestmögliche
Rauschfreiheit steuern Sie ihre Audioquelle
höchstmöglich aus und passen auf diese Si-
gnalhöhe Ihren Verstärker an.
Der Gainregler ist kein Volumenregler son-
dern gibt ihnen die Einstellmöglichkeit mit
wieviel Eingangssignal die Maximale Aus-
gangsleistung des Verstärkers erreicht wird.
Bei maximaler Empfindlichkeit wird der Ver-
stärker mit 500mV Eingangssignal ausge-
steuert, bei maximaler Unempfindlichkeit
(6V Stellung) mit 6V Eingangssignal. Pas-
sen Sie den Regler entsprechend der ge-
wünschten bzw. der benötigten Lautstärke
des angeschlossenen Lautsprechers bzw.
des Systems an.
<<<


* sowohl Lautstärke, Gain als auch Eingangs-Empfindlichkeit als bezeichnung für den regler
* ich glaube der gain regler steht eigentlich für die empfindlichkeit. einstellbar von 500mV bis 6V.
* aber in welchen schritten, linear (easy) oder log?
* sicher gehen und mit messungen checken
* 500mV bis 6V
* 40 klicks bei dem regler?
* 0,775V oder 1V standards?
* benötige Eingangsempfindlichkeit, Leistung bei Impedanz und voltage gain oder sensitivity
** gain kann aus leistung, sensitivity und impedance berechnet werden

<<<
ichhabe den verstärkungsfaktor der amps gemessen
die messung war nicht so krass genau, aber ich bin so bei 30-31dB raus gekommen.
ich muss nochmal mehr damit experimentieren um eine bessere messung zu machen.

getestet:
tonmodul ohne mischpult

gain poti:
amps haben 0,45 - 6V drauf stehen
laut anleitung 0,5-6V
40 schritte

amp einstellungen momentan:
amp 1 auf 12 vor 0,45
amp 2 auf 0,45
amp 3 auf 0,45

nach bisschen rumprobieren mit meinem Analog Discovery und ausrechnen zu allen messungen die ich gemacht habe denke ich kommt ''31dB'' dem verstärkungsfaktor am nächsten, außerdem ist aufrunden eh sicherer als abrunden.
<<<


! [[Sonnensystem Speaker]]


!! setups




! notizen

* https://t.me/onefunktion/71 - limiter berechnungen verstehen




```
##################################################################################
```


<<<
Tim | TurboTheSergal, [06.06.23 12:04]
k.A welche empfindlichkeit die Stufen haben, sonst würde ich Mal berechnen was der limiter aktuell an Leistung wäre ������

Tino, [06.06.23 12:05]
Voltage Gain waere eine hilfreichere Angabe. Empfindlichkeit bezogen auf Ausgangsleistung ist immer eine totale Schaetzung

Tim | TurboTheSergal, [06.06.23 12:06]
Wenn man den wüsste würde ich den auch lieber zum rechnen nutzten

Tino, [06.06.23 12:06]
Kannste in 5 Minuten mit nem Multimeter rausfinden

Tino, [06.06.23 12:08]
einfach 50 Hz Sinusgenerator aufm Handy am Eingang auf max Lautstaerke abspielen, Multi im AC-Messmodus einmal an den input Link am XLR zwischen hot und cold um die Eingangsspannung zu messen und dann das Gleiche am Ausgang

Tino, [06.06.23 12:08]
Die Differenz als Faktor in dB umrechnen was auch recht ez ist

Tino, [06.06.23 12:09]
20*log(out/in)

Tino, [06.06.23 12:12]
Limiter berechnen ist essentiell wenn man irgendwie weiterkommen will, war anfangs auch zu faul

Tino, [06.06.23 12:13]
es hilft halt auch dem Verstandnis... mit nem simplen Peaklimiter laesst sich RMS allerdings nicht sinnvoll limitieren, ohne Headroom zu verschenken

Tino, [06.06.23 12:13]
Peak liegt eigentlich mind. 4 dB ueber RMS

Tino, [06.06.23 12:13]
Je nach Typ vielfach hoeher

Tino, [06.06.23 12:14]
RMS... ich meine halt thermische Belastbarkeit. Gibt viele Begriffe dafuer.

Tim | TurboTheSergal, [06.06.23 12:19]
Da komme ich bei der großen von den beiden Stufen auf 36,5691274

Tim | TurboTheSergal, [06.06.23 12:35]
Kleine sagt 11,6144387

Tim | TurboTheSergal, [06.06.23 12:40]
Aber um den limiter gut berechnen zu können brauche ich doch immer noch die eingangsempfindlichkeit... Anleitung finde ich zu den Endstufen nicht also keine Ahnung.

Oder habe ich nen Dreher im Kopf

Tim | TurboTheSergal, [06.06.23 12:52]
Kann man die Empfindlichkeit irgendwie rausfinden ohne ein Datenblatt

Tino, [06.06.23 12:52]
Hoher Voltage Gain wow

Tino, [06.06.23 12:52]
Potis voll aufgedreht of course....?

Tino, [06.06.23 12:53]
Es gibt  schon Stufen mit bis 40 dB Voltage Gain, aber idR sind es 20 bis 36 oder so

Tino, [06.06.23 12:53]
Es sind ja nur Spannungsteiler, die hindern dich ja nich dran Vollgas zu geben

Tino, [06.06.23 12:53]
Das ist unrealistisch niedrig, Potis offen,...?

Tino, [06.06.23 13:29]
Naja war es Faktor 11 oder 11 dB?

Tino, [06.06.23 13:30]
waeren sonst ja so +21,3 dB

Tino, [06.06.23 14:21]
nur 11 dB ist super winzig, selbst Hifizeug hat um die 20 oder mehr

Tim | TurboTheSergal, [06.06.23 17:18]
So, dieses mal Beide Amps kurz vor Clipping (Laut eingebauter LED) gemessen...
PA-1100 hat ergeben 38.107
[ 20*log(53.8/0.669) ]

PA-400 hat ergeben 31.440
[ 20*log(19.56/0.524) ]

Tim | TurboTheSergal, [06.06.23 17:23]
Ohne Last btw... Oder muss das mit nem LS dran? Denn ich hätte nichts da was das volle Breitseite fressen würde.

Tim | TurboTheSergal, [06.06.23 17:29]
Mit Last könnte ich es nur mit einem minimalen Eingangssignal machen
Edit: Endstufe immernoch Vollgas aber ausm Mixer minimal weil... Nachbarn

Tino, [06.06.23 17:48]
Die LED sagt halt verdammt wenig aus

Tino, [06.06.23 17:48]
das ist so ein grober Schätzkreis

Tim | TurboTheSergal, [06.06.23 17:48]
Ohne Oszi geht nicht viel mehr ������

Tim | TurboTheSergal, [06.06.23 18:09]
Aber mit oder ohne Last, was wäre jetzt richtig?

Wenn's mit Last sein muss, ist das schlimm wenn's wenig Input vom Mischpult aus wäre und der gain beim amp trotzdem Vollgas ist?

Tino, [06.06.23 20:18]
Es gibt leider verschiedene Konzepte, nach denen Clipanzeigen funktionieren

Tim | TurboTheSergal, [06.06.23 20:20]
Bleibt der voltage gain bei geringem Eingangssignal gleich? Also am Mixer weniger Output, aber Endstufe Vollgas?

Tim | TurboTheSergal, [06.06.23 20:20]
Und die mit/ohne Last Frage steht auch noch

Tim | TurboTheSergal, [06.06.23 20:37]
Ansonsten Könnte ich das mitm clipping Per widerstand und REW Scope checken.

Tino, [06.06.23 21:08]
Natürlich

Tino, [06.06.23 21:10]
Der Voltage Gain ist einfach nur ein Faktor, welcher aussagt, wie viel höher als die Eingangsspannung – bei voll aufgedrehten Gain Pots – die Signalspannung an den Leistungsausgängen ist.

Tino, [06.06.23 21:11]
Das einzige, was den Faktor minimal beeinflussen kann, ist der Innenwiderstand der Endstufe, der hat aber nix mit der momentan abgegebenen Leistung zu tun sondern nur mit der angeschlossenen Lastimpedanz.

Tino, [06.06.23 21:11]
Also eigentlich musste keine Last anschließen. Würde sich der Voltage Gain dann relevant ändern, wäre dein Amp kaputt

Tino, [06.06.23 21:14]
Sobald es clippt verfälscht du das Ergebnis

Tino, [06.06.23 21:14]
Weil dann ja nur Ausgang clippt

Tino, [06.06.23 21:14]
Wodurch sich der Voltage Gain verringert

Tim | TurboTheSergal, [07.06.23 10:42]
So, Erledigt.
Ich kam jetzt auf folgende werte.
PA-400:
20*log(10.48/0.28) = 31.464
PA-1100
20*log(10.86/0.28) = 31.773

Für mich sehen sie so etwas realistischer aus.

Tim | TurboTheSergal, [07.06.23 10:49]
Zu der PA-400 Habe ich mittlerweile die Eingangsempfindlichkeit gefunden, die ist nicht umschaltbar und bei 1V

EDIT: Der Jobsti Eingangsempfindlichkeit Rechner sagt mir allerdings das bei 110W @ 8 Ohm und 31.464db Gain eine Eingangsempfindlichkeit von 0.793 rauskommt. Es kann halt auch sein das das ausm Rechner richtig is da ich die Eingangsempfindlichkeit nicht aus einer Anleitung sondern nur eines Erfahrungsbericht auf irgendeinem schon lange toten forum gesehen hatte.

EDIT 2: Der Jobsti Rechner sagt zur PA-1100 eine Eingangsempfindlichkeit von 1.345V. Also denke ich mal das im datenblatt bei den endstufen damals bei der 400er 0.775 drinne stand und bei der 1100er 1.4 drinne stand

Tino, [07.06.23 16:10]
Ja, das ist absolut realistisch

Tino, [07.06.23 16:11]
Denke es sind offiziell 32 dB Amps so wie die meisten.
<<<
Bausätze von [[BS-Tek|https://www.bs-tek.de/]]

alle limiter berechnungen aktuell fürs 0,45/0,5V Setting an den amps was zu 31dB verstärkungsfaktor führt!

!! kleine 8" Tops - [[Sonnentop8|https://www.bs-tek.de/bausaetze/sonnensystem/sonnentop8/]]

* die 8"er sind: [[8 N 2,5 PL|https://sica.it/prodotto/8-n-2-5-pl/]] (300W)
** nur in der 4 ohm variante (den gibts bei sica als 4 ohm beim werk)
* hochtöner?
* 8" 4Ohm (gemessen 3,6 ohm) 300Wrms
* limiter
** 270W@4Ohm (32,86V out; max!): 0,93V = 1,55 dBu = -0,67 dBV (=-20,45 dB DCX)
** 200W@4Om (28,28V out): 0,8V = 0,24 dBu = -1,97 dBV (= -21,76 dB DCX)


!! 12" Tops

* ähnlich [[BS.M12|https://www.bs-tek.de/bausaetze/fullrangelautsprecher/bs-m-12/]]?
* 12" woofer: [[B&C 12NDL76|https://www.bcspeakers.com/en/products/lf-driver/12-0/8/12ndl76]] (400Wrms)
* 1,4" hochton: [[18s ND1424bt|https://www.eighteensound.it/en/products/hf-driver/1-4/8/ND1424BT]] (70Wrms) am B&C ME90
* 400Wrms?
* 4Ohm?
* limiter:
** 400W@4Ohm bridged (20,05V out): 0,57V = -2,74 dBu = -4,96dbV (=-24,74 dB DCX)

!! 15" Subs - [[Sonnensub15|https://www.bs-tek.de/bausaetze/sonnensystem/sonnensub15/]]

* Der 15er ist: [[15 S 3 PL|https://sica.it/prodotto/15-s-3-pl/]] (400Wrms) in 8 ohm
* 15" 8Ohm (gemessen 5,2-5,3 ohm)
* 400Wrms
* limiter bridged 800W@4Ohm (28,35V out): 0,8V = 0,27 dBu = -1,95 dBV (= -21,73 dB DCX)
* limiter single:
** 130W@8Ohm (32,25V out): 0,91V = 1,38 dBu = -0,83 dBV (= -20,62 dB DCX)
** 100W@8Om (28,28V out): 0,8V = 0,24 dBu = -1,97 dBV (= -21,76 dB DCX)
** 100,5W@8Ohm (28,35V out): 0,8V = 0,27 dBu = -1,95 dBV (= -21,73 dB DCX)

!! 21" Infras "Waschmaschine" - [[BS.M21s|https://www.bs-tek.de/bausaetze/subwoofer/bs-m-21s/]]

* 21" 4 ohm (gemessen 2,6-2,8 ohm)
* [[Sica: 21 S 4 PL|https://sica.it/prodotto/21-s-4-pl/]] (1200 Wrms)
*1200Wrms
* limiter
** 900W@4Ohm bridged (30,07V out): 0,85V = 0,78dBu = -1,44 dBV (= -21,22 dB DCX)
** 908W@4Ohm bridged (30,20V out): 0,85V = 0,82 dBu = -1,40 dBV (= -21,18 dB DCX)
* https://www.physicsclassroom.com/class/sound
* https://perkaudio.wordpress.com/acoustics/sound/
* https://perkaudio.wordpress.com/acoustics/reverberation-time/
* transform spectrogram and spectra to sound
* might be cool for auralizing (visualization counterpart?) stuff
* inverse fourier transform
** https://de.wikipedia.org/wiki/Fourier-Transformation
** https://en.wikipedia.org/wiki/Fourier_transform
** https://en.wikipedia.org/wiki/Fourier_inversion_theorem
** https://web.stanford.edu/class/ee102/lectures/fourtran
** https://electricalacademia.com/signals-and-systems/fourier-transform-and-inverse-fourier-transform-with-examples-and-solutions/
* https://pythontic.com/visualization/signals/fouriertransform-ifft
* like making different spectra hearable
** https://en.wikipedia.org/wiki/Gamma-ray_spectrometer
** [[DIY/open hardware light spectroscope / spectrometer]]
* https://blog.synthesizerwriter.com/2021/02/should-i-look-at-spectrum-or-waveform.html
* [[Sound System Tuning By Ear|https://www.youtube.com/watch?v=1IbvhgfGEhU]]
* [[How to EQ Live Sound Systems Tricks - Updated Version|https://www.youtube.com/watch?v=KdnvhwWyPDs]]
someone wanted their battery for the soundboks repaired, it wasn't charging anymore.

I opened it up, the design is ok, best thing is that the case is screwed together and not glued or so.
the battery is a pretty standard 12V ~LiFePO4 pack, 4s2p (4x 2 parallel cells in series).

all cells were dead and had no voltage, i was able to revive 3 of the 4 parallel pairs of cells, but one pair was not holding any charge, it quickly discharged.

i agreed with the owner to look for new cells that fit into the case when i got time.

i haven't looked at the bms jet, but it has a state of charge indicator and balancing.
the label on the case indicates it jas data communication, maybe something like: https://www.maximintegrated.com/en/products/power/battery-management/battery-fuel-gauges.html/tab1?fam=batt_stat&node=13600&374=OR%7C1-Wire&152=OR%7C1-10%20Cell%20Li-Ion%7C2-4%20Cell%20Li-Ion%7CMulti-Cell%20Li-Ion

i remember noting the dimensions somewhere, but i seem to have misplaced the sheet unfortunately.
* Teardown: https://www.youtube.com/watch?v=WYk2dAuHJWo (Russian?)
* https://www.soundboks.com/de/products/soundboks-2/techspecs/
* https://www.soundboks.com/products/soundboks-2/techspecs/
* https://www.soundboks.com/products/new-soundboks/compare/
* https://github.com/alexgorbatchev/boominator
* https://www.diyaudio.com/forums/class-d/104402-boominator-stab-ultimate-party-machine.html
* see [[Soundboks Batteryboks repair]]

tecspecs:

* power supply
** battery: 12.8V, 7.8Ah, 99.84Wh Lithium Iron Phosphate (LiFePO4) with [[BMS|Battery Management System (BMS)]] (with 5-step indicator)
*** normal LFP which doesn't like to get charged below 0°C, ABS case
*** Go: 40h mid volume, 10h full volume
*** 3: 40h mid volume, 5h full volume
** "Dynamic DC/DC Boost Converter" - just a step-up/boost [[SMPS|switched mode power supply (SMPS)]]


* amplifier:
** "Merus Audio eximo® amp switching (Merus Audio eximo® Amp-Schaltung)"
** 2&3: "3 x 72Wrms class D amplifier"
** Go: "2 × 72 Watt continuous - Class D amplifiers"
** ~~216Wrms combined, ~90W per woofer and 35-40W for the tweeter?~~
** https://www.infineon.com/cms/en/product/power/class-d-audio-amplifier-ic/
** [[PDF-Copy of an AudioXPress Article, published by Infineon|https://www.infineon.com/dgdl/Infineon-Infineon_Article_AudioXpress_SOUNDBOKS_ridiculously_large_portable_bluetooth_speaker_powered_by_merus_audio_eximo_amplifier_technology_EN-ART-v01_00-EN.pdf?fileId=5546d46265f064ff016658aa18890d1f]]
*** stating the soundboks 2 uses 2 MA12070P ICs
*** that it uses an amp IC with digital input was not unexpected because the soundboks utilises a DSP
** using both MA12070P in BTL mode but only using 3 outputs? the datasheet states 60W peak with no heatsink at THD+N = 1%, how do they want to get 72Wrms out of that?
** Merus eximo amps aren't more efficient than other manufacturers amps


* drivers:
** 2
*** "1 x 96dB 1” (Ø25mm) neodymium silk dome tweeter"
*** "2 x 96dB 10” (Ø254mm) woofers"
*** 2 × Ø56mm Ports
** 3
*** 1” 104 dB Compression Driver Tweeter
*** 2 × 10” 96dB woofers
*** "Pulse Reflex Port", just some proprietary bass reflex port
** Go
*** 1 × 10” woofer
*** 1 × 1” silk dome tweeter


* bluetooth chip/functions:
** soundboks 2: Bt v3.0
** new soundboks: Bt v5.0
** DSP (probably just some EQ and active crossover)
*** there are bluetooth receiver (boards) with integrated DSP functionality
*** the version 3 seems to have more functions there
** "~TeamUP connection (SKAA)"


* Dimensions
** 3: 66 × 43 × 32 cm / 25.6 × 17 × 13 inches (H × W × D)


* misc:
** "Effective frequency range: 40Hz - 20kHz (Effektiver Frequenzbereich: 40Hz - 20kHz)"
** max SPL: 122 dB (2), 126 dB (new)
** "1 x Ø35mm Pole mount (Ø35mm Stangenhalterung)"

Price:

* Go: 700€
* 2: 700€, was 1000€
* 3: 1000€
i was able to buy this nice, old mixing console for cheap, because it is partially broken.

* https://www.soundcraft.com/en/products/spirit-live
** https://www.soundcraft.com/en/product_documents/spirit-live-user-guide-pdf

as a first step i disassembled the mixing console completely to give it a good clean, because it was pretty dirty.

the previous owner told me something is not right with the master outs, possibly intermittent contact of the faders and the LED bars.

i my first tests i could not replicate these problems
* [[Playlist: Audio University: Sound System Design Guide (Speakers, Amplifiers, & Cables)|https://www.youtube.com/playlist?list=PLASEfdY-tiDohUXN3tEC9Pm-qRfyGWucP]]
* [[ Start Here: Sound System Design & Tuning Basics |https://www.youtube.com/playlist?list=PLqLfCybtxh0HTXmXl4nKZO64yHmQP0lRi]]
** [[ 10 Sound System Design & Tuning Terms You Need To Know|https://www.youtube.com/watch?v=3u_jQCshHXw]]
* [[Subwoofers & Low End|https://www.youtube.com/playlist?list=PLqLfCybtxh0H7gaGak2Gfe3ogiyogc6bX]]


stuff

* https://www.sweetwater.com/insync/pa-speaker-buying-guide/
* https://www.instructables.com/id/How-to-Build-a-DJ-Setup-for-Beginners-Classic-Turn/
* https://www.instructables.com/id/Battery-Powered-Mobile-Party-Sound-Systems/
* https://www.instructables.com/id/How-To-Prepare-For-Buying-Sound-Equipment/
* https://www.thomann.de/de/onlineexpert_topic_pa_anlagen.html
combines [[lab bench power supply]] and [[electronic load]] into one

* https://hackaday.com/2021/08/18/diy-source-measurement-unit-shows-all-the-details/
** https://www.djerickson.com/diy_smu/
** https://github.com/jaromir-sukuba/J-SMU
** [[DIY Source-Measure Unit SMU Chapter 1|https://www.youtube.com/watch?v=B26SW3N2zoA]]
** [[DIY-SMU Chapter 2: New Teensy CPU and Enclosure|https://www.youtube.com/watch?v=Cadw8k-lSd4]]
** https://www.electronicdesign.com/technologies/test-measurement/video/21211786/diy-sourcemeasure-unit-smu
** https://github.com/djerickson/diy-smu
* https://www.ossila.com/products/xtralien-source-measure-unit-source-meter
* micro smu (uSMU)?
* https://en.wikipedia.org/wiki/Source_measure_unit
* https://jpralves.net/post/2021/08/19/diy-smu-source-measure-unit.html
* https://www.ti.com/solution/source-measurement-unit-smu
* https://www.analog.com/en/analog-dialogue/studentzone/studentzone-december-2017.html
* https://www.trendradars.com/technology/show/342133/
* https://octopart.com/
* https://sourceme.com/
* [[electronic suppliers]]

stuff

* https://www.findchips.com/
* https://componentsearchengine.com/
solar panels - nico asks nice human from meißen if he donates panels

solar companies in dresden

* victron energy
** https://www.service-doebeln.de/
** http://lisunenergy.de/
* andere
** https://www.solarwatt.de/
** https://www.sunstrom.de/ (FFF sehr aufgeschlossen)

holzhandel in dresden

ironmongery

* [[Eisenfeustel|https://www.eisenfeustel.de/kontakt/]]
* [[werkzeuge kliemann|http://www.werkzeuge-kliemann.de/produktuebersicht]]

ebay?
alibaba?
aliexpress?
taobao?
bangood?

sourcing used cells from local battery/electronic recyclers (https://www.youtube.com/watch?v=Tto6bglCevA), sourcing them from old electric vehicles

* broken huawei display assemblies
* https://www.secondlife-evbatteries.com/
* https://shop.gwl.eu/
* https://nkon.nl - wohl Gute Preise, zuverlässiger Service, top Quali
* https://www.mobile-solarpower.com/ - a lot of ressources/links/parts/sources
* https://www.autobatterienbilliger.de/
* https://www.verbraucherzentrale.de/wissen/digitale-welt/phishingradar/spam-emailmuell-im-internet-10757
* https://www.internet-beschwerdestelle.de/de/beschwerde/einreichen/e-mail-und-spam.html
* https://de.wikipedia.org/wiki/Thoms_Fassung_von_Framstags_freundlichem_Folterfragebogen
* https://www.heise.de/newsticker/meldung/DSGVO-Folterfragebogen-im-Selbsttest-3974512.html
* https://www.heise.de/select/ct/2018/5/1519949473427199#zsdb-article-links
** https://www.heise.de/select/ct/2018/5/softlinks/ycyu?wt_mc=pred.red.ct.ct052018.112.softlink.softlink
* beschwerde beim zuständigen dateschutzbeauftragten, vor allem wenn die dsgvo anfrage nicht rechtzeitig beantwortet wird
testing amps without speakers, measuring the power of amps; see also [[amplifier power measurement]]

* needs power resistors (hochlast widerstände)

* 4, 6, 8 Ohm
* 2 and 16 Ohm only in special cases
* https://de.wikipedia.org/wiki/Ersatzlast
* https://en.wikipedia.org/wiki/Dummy_load
* elektronische lasten werden wohl nicht funktionieren
* real speakers are not just ohmic loads (resistive), they also presend a high inductance which is varying depending on the frequency
* https://www.epanorama.net/documents/audio/speaker_impedance.html
* see [[Thiele & Small Parameters]]

types

* the simplest dummy load is completely comprised of power resistors and is pretty much only an ohmic load
** https://www.mario001.de/audio/2014/10/27/audio-dummyload/
** http://www.pmillett.com/dummyload.html
** https://andydoz.blogspot.com/2016/04/arduino-audio-wattmeter.html
** https://diyaudioprojects.com/Testeq/Dummy-Speaker-Load/
** https://diyaudioprojects.com/Technical/DIY-Speaker-Dummy-Load/
** https://www.youtube.com/watch?v=QS8GgUWnbq0
** https://www.youtube.com/watch?v=hA12uYxHBXM
* a clever design working like a hairdryer or some air heater is using resistive wire (like nichrome); has a slight inductance when curled
** https://de.wikipedia.org/wiki/Heizleiterlegierung
** https://en.wikipedia.org/wiki/Nichrome
** https://www.element14.com/community/community/project14/questionofscale/blog/2019/01/11/building-a-miniature-300w-speaker-simulator
** https://www.youtube.com/watch?v=rK8aVadsu6A
* RLC Circuits to not only provide a load but to also simulate the inductance
** https://hackaday.com/2018/11/20/simulating-a-speaker/
** https://circuitdigest.com/electronic-circuits/simulate-speaker-with-equivalent-rlc-circuit
** https://www.aikenamps.com/index.php/designing-a-reactive-speaker-load-emulator
** https://www.hexefx.com/diy/gear/spkload


instructions:

* https://www.diyaudio.com/forums/equipment-and-tools/313382-amplifier-dummy-load-thd-measurements-inductive-2.html
* https://audiokarma.org/forums/index.php?threads/dummy-load-resistor-question.30694/
* https://www.youtube.com/watch?v=HeQH0ZQTMtU
* https://www.prosoundtraining.com/2011/08/09/dummy-load-testing-large-amplifiers/
* [[ Audio Test Bench Setup and Dummy Load Build - BG052 |https://www.youtube.com/watch?v=piRtOAUIKzw]]
** [[ Audio Analyzer & Dummy Load Using Analog Discovery 2 - 2019 Version |https://www.youtube.com/watch?v=1rOvdsxQVTY]]

stuff

* https://www.down4soundshop.com/AD-1/ - Amp Dyno AD-1
** https://cdn11.bigcommerce.com/s-209k8v1/images/stencil/1280x1280/products/3355/45402/smd-amp-dyno-ad-1__24703.1659025096.jpg?c=2&imbypass=on
** uses break resistors easily obtainable from china
* https://diyaudioprojects.com/Technical/DIY-Speaker-Dummy-Load/
* https://diyaudioprojects.com/Testeq/Dummy-Speaker-Load/
* https://www.aikenamps.com/index.php/dummy-loads
* https://www.soundonsound.com/techniques/build-guitar-amp-dummy-speaker-load
* https://www.diyaudio.com/community/threads/testing-amplifiers-speaker-or-dummy-load.167853/
* https://www.thegearpage.net/board/index.php?threads/speaker-and-dummy-load-in-parallel.2108684/
* https://www.diyaudio.com/community/threads/8-ohm-dummy-load-across-speaker-terminals.356652/
* https://www.tedweber.com/tru-load/
* https://audiokarma.org/forums/index.php?threads/speaker-dummy-loads.1015588/
* https://electronics.stackexchange.com/questions/643800/simulated-speaker-dummy-load-for-solid-state
* https://audioxpress.com/article/you-can-diy-build-an-audio-dummy-load
* https://gearspace.com/board/geekzone/1124737-dummy-load-build.html
* https://www.youtube.com/watch?v=QS8GgUWnbq0
* 
* stereo
** classic

bass/subwoofer

* https://eaw.com/directional-subwoofer-arrays-a-practical-approach/
* [[TECH: LIVE SOUND SUBS SUBWOOFER PLACEMENT & CONFIGURATION - LR, Center, Line, Cardioid, End Fire|https://www.youtube.com/watch?v=1uD6Szdcqpw]]
* [[Pt 1 Live Sound Subwoofer Configurations|https://www.youtube.com/watch?v=VwLH7zP6Lwo]]
** [[Pt 2 Live Sound Subwoofer configurations|https://www.youtube.com/watch?v=B-3pURYOwfw]]
** [[Pt 3 Live Sound Subwoofer Configurations|https://www.youtube.com/watch?v=aSZK9Altvm8]]

* double bass array
** https://de.wikipedia.org/wiki/Double_Bass_Array
** https://en.wikipedia.org/wiki/Double_bass_array
* end-fire
* [[Subwoofer Secrets: Rear Cancellation Part 1|https://www.youtube.com/watch?v=Fz2c_PjP7P8]]
** [[Subwoofer Secrets: Rear Cancellation Part 2|https://www.youtube.com/watch?v=hkCst8-AKdI]]
* [[https://www.youtube.com/watch?v=e90v1NVT7bQ|https://www.youtube.com/watch?v=e90v1NVT7bQ|]]
* [[ Better Sounding Subwoofer Arrays Part 1 - Coverage and Quality |https://www.youtube.com/watch?v=qvp-CKHVLrA]]
** [[ Better Sounding Subwoofer Arrays Part 2 - Sub Arcs, Delay & End-Fire |https://www.youtube.com/watch?v=184UVCC-NSE]]
** [[ Better Sounding Subwoofer Arrays Part 3 - Orgasmatron & Endfire ARC |https://www.youtube.com/watch?v=Y2GJ77IpjjA]]
* [[ Four Subwoofers, Seven Setups For Live Sound - Groundstacked Edition |https://www.youtube.com/watch?v=Q4ny703u-ks]]
** [[ Left / Right Sub Setups - Everything You Need To Know |https://www.youtube.com/watch?v=Y2GJ77IpjjA]]
** [[ Two Subs, Six Setups - Killer Low End For Portable DJ's and Small Concerts |https://www.youtube.com/watch?v=I9SJ36FtEyY]]
** [[ Cardioid Subs Explained For Normal Audio People |https://www.youtube.com/watch?v=EgHK1s7SzIE]]

stuff:

* https://fohonline.com/articles/tech-feature/back-to-basics-directional-subwoofer-arrays/
* https://electrovoice.com/media/downloads/wp_subwoofer_arrays_v04.pdf
* [[ Speaker Placement Basics For Small Concerts, DJ's, and Portable Churches |https://www.youtube.com/watch?v=OeaMtRvIysM]]
list of software to design speakers

* WinISD - freeware
** http://www.linearteam.org/
** http://forum.speakerplans.com/guide-to-winisd-pro-and-hornresp_topic1314_post11070.html#11070

* AJHorn - http://www.aj-systems.de/index.htm - expensive, useless demo
** https://www.hifi-selbstbau.de/grundlagen-mainmenu-35/softwaremesstechnik-mainmenu-66/143-aj-horn-das-schweizer-allzweckmesser

* Hornresp - freeware
** http://www.hornresp.net/
** https://www.diyaudio.com/community/threads/hornresp.119854/
** http://forum.speakerplans.com/guide-to-winisd-pro-and-hornresp_topic1314_post11070.html#11070

* Virtuixcad - freeware
** https://kimmosaunisto.net/
** [[#SIMULATION #VITUIX SCHNELL & KOSTENLOS - Simulationssoftware VituixCAD2 an Omnes Audio Lautsprecher|https://www.youtube.com/watch?v=bDAASiz5fhE]]

* mfblabs woofer tool?

* SpeakerSim - open source
** https://lightbit.gitlab.io/file/
** https://gitlab.com/LightBit/SpeakerSim
** https://www.diyaudio.com/community/threads/speakersim-speaker-simulation-software.314378/

* Loudspeaker Design Calculations Toolkit - open source, abandoned?
** https://sourceforge.net/projects/ldct/

* GnomeSpeakers - open source, abandoned?
** https://sourceforge.net/projects/gspeakers/
** http://gspeakers.sourceforge.net/


(simpler) online-calculators:

* https://www.hifi-selbstbau.de/onlinerechner
* https://www.madisoundspeakerstore.com/calculators
* https://www.micka.de/en/

unsorted:

* http://mh-audio.nl/Loudspeakers.html
* https://www.diyaudioandvideo.com/Calculator/SpeakerBoxVolume/
* https://www.diyaudioandvideo.com/Calculator/SpeakerBoxEnclosure/
* http://www.speakerbuilding.com/software/
* http://sbp.softica.dk/2.0/en/?id=
* http://www.audiogurus.com/learn/news/speaker-cabinet-design-styles-techniques/2037
* https://www.micka.de/
* http://www.jobst-audio.de/interactiv/tools
* http://boxsim.de/
* https://github.com/maqifrnswa/scimpy
* https://github.com/n-heptane-lab/speaker-design
* https://sourceforge.net/projects/jdsspeakerdesigner/
** https://github.com/lsiberian/JDsSpeakerDesigner
* https://github.com/skahl/speaker-design-notebook
* https://site.diy-loudspeakers.com/design-tools/enclosure-design-s-w
* http://www.mh-audio.nl/Loudspeakers.html
* https://sourceforge.net/projects/speakerworkshop/
* https://sourceforge.net/projects/gspeakers/
* https://sourceforge.net/projects/xlds/
* https://sourceforge.net/projects/kfilter/
* https://github.com/molke-productions/qloud
* http://www.jobst-audio.de/tools-frequenzweiche/cbgehaeuse
* https://www.sps.tue.nl/rmaarts/RMA_papers/aar06pu1.pdf
* https://celestion.com/blog/now-even-more-horn-design-functionality-with-hornwizard-2-0/
* http://www.loudspeakerdatabase.com/Simulators/ClosedBox
** https://books.google.de/books?id=NdOZDwAAQBAJ&lpg=PP1&pg=PA402&redir_esc=y#v=onepage&q&f=false
* https://www.subwoofer-builder.com/design/
* https://www.hifi-selbstbau.de/grundlagen-mainmenu-35/softwaremesstechnik-mainmenu-66
* https://www.tolvan.com/index.php?page=/main/home.php
* https://www.audionet.de/apps/carma/
* https://www.audio-software.de
* https://www.eighteensound.it/en/resources/suggested-designs/
* https://www.precision-devices.com/enclosure-designs/
* https://www.eminence.com/support/designing-enclosures/ - link does not work anymore
* https://bcspeakers.com/en/resources/suggested-designs/
<<list-links "[all[current]tagging[]]">>
<<list-links "[all[current]tagging[]]">>
* https://www.freespeakerplans.com/plans
* https://www.speakerplans.com/index.php?id=plans
* https://perkhorns.wordpress.com/speakers/plans/
* http://enclosures.perkhorns.net/
* http://hornplans.free.fr/
* see [[speaker design suggestions from manufacturers]]
* https://www.jobst-audio.de/public-address
* https://paforum.de/forum/index.php?board/27-selbstbau-und-reparatur-lautsprecher-und-boxen/
<<list-links "[all[current]tagging[]]">>
* less power required
* less heat generated, longer component life

speaker sensitivity

* used to determine the amount of power necessary to drive or operate a loudspeaker
* measurement of the amount of sound output derived from a speaker with 1W of power input
* measured using a sound level meter, one meter in front of the speaker, in dB

Sources

* https://www.klipsch.com/education/speaker-sensitivity
* https://www.musiciansfriend.com/thehub/understanding-wattage-speaker-efficiency-amplifier-loudness
* https://www.lifewire.com/amp-power-speaker-efficiency-3135077
* https://everything2.com/title/Speaker+efficiency
* https://www.audioholics.com/loudspeaker-design/loudspeaker-sensitivity
* http://www.sengpielaudio.com/calculator-efficiency.htm
* https://en.wikipedia.org/wiki/Loudspeaker#Efficiency_vs._sensitivity
* https://www.lifewire.com/speaker-sensitivity-3134850
* https://electronics.howstuffworks.com/how-to-explain-speaker-sensitivity.htm
* https://geoffthegreygeek.com/understanding-speaker-sensitivity/
* https://chuckhawks.com/speaker_spl_amp_power.htm
* http://www.sengpielaudio.com/Rechner-wirkungsgrad.htm
* http://sensitivity.perkhorns.net/
frequency responce

* https://www.diyaudioandvideo.com/Tutorial/SpeakerResponseTesting/

Impedance

* https://de.wikihow.com/Die-Impedanz-von-Lautsprechern-messen
* [[Denkfehler Anfänger Teil 1 - Der Impedanzverlauf und seine Tücken|https://www.youtube.com/watch?v=NhN_wrpzIyo]]

other / not sorted

* http://www.audio-software.de/index.html
* http://www.audio-software.de/umschaltbox.html
* https://www.youtube.com/channel/UC-Y8jmNTBsS3OoJoxG1qKzQ/videos
* ARTA - software (proprietary, shareware) + hardware box design
** http://www.artalabs.hr/index.htm
** https://www.youtube.com/watch?v=qBhmLW72Qq8
* https://www.roomeqwizard.com/index.html
* http://www.elektronik-labor.de/HF/Lautsprecher/LS1.html
* [[Thiele / Small Parameters]]
* [[Speaker Impedance Measurement - how to|https://www.youtube.com/watch?v=g1zda0WMDGc]]
* http://www.audiodesignguide.com/AudioMesurement/index.html
* https://web.archive.org/web/20181222023032/http://www.bassreflex.de/index/index1.html
* https://en.wikipedia.org/wiki/Real-time_analyzer
* https://github.com/maqifrnswa/scimpy
* https://github.com/molke-productions/qloud
* http://www.hifi-forum.de/viewforum-137.html
* http://www.hifi-forum.de/viewthread-42-42.html
* http://www.pmillett.com/ATEST.htm
* http://www.pmillett.com/hp_8903_software.htm
* https://audiokarma.org/forums/index.php?threads/is-this-how-i-measure-speaker-sensitivity.66381/
* https://www.stereophile.com/content/measuring-loudspeakers-part-one-page-3
* https://www.cuidevices.com/blog/understanding-and-measuring-sensitivity-in-audio-components
* https://hifi-selbstbau.de/grundlagen-mainmenu-35/softwaremesstechnik-mainmenu-66
* [[#REW #TUTORIAL #LAUTSPRECHER - REW (Room EQ Wizard) von Anfang an erklärt - Teil 1|https://www.youtube.com/watch?v=dZIPGvgGOQs]]
** [[#REW #TUTORIAL Teil 2 #DIY - REW (Room EQ Wizard) von Anfang an erklärt - SPL Messmenü erklärt|https://www.youtube.com/watch?v=-81GDvqCoqE]]
** [[Ach deshalb klingt es so lahm - Group Delay #REW (Room EQ Wizard) Die Messung der Gruppenlaufzeit|https://www.youtube.com/watch?v=9SNLU69nJQM]]
* [[Room EQ Wizard (REW) Tutorial German - Einmessung von Lautsprechern mit REW|https://www.youtube.com/watch?v=5vL2KdUjqiQ]]
* [[ FREE Acoustical Measurement Software: Room EQ Wizard (REW) |https://www.youtube.com/watch?v=td7Ue86Snfc]]
<<list-links "[all[current]tagging[]]">>

* https://perkhorns.wordpress.com/horns/
* http://subs.perkhorns.net/
* http://enclosures.perkhorns.net/
* http://subapp.perkhorns.net/
* http://horns.perkhorns.net/
* http://www.loudspeakerdatabase.com/
* https://de.wikipedia.org/wiki/Kategorie:Lautsprecher
* http://hifilounge.eu/1.-introduction--structure.html
* https://av-wiki.de/lautsprecher
* http://www.jobst-audio.de/ - http://www.jobst-audio.de/selbstbau
** http://www.jobst-audio.de/interactiv/artikel-und-tutorials
** http://www.jobst-audio.de/interactiv/tools
*https://www.lautsprecherforum.eu/viewforum.php?f=40
* https://www.itwissen.info/Speakon-Stecker-speaker-connector.html
* https://www.itwissen.info/tag/Lautsprecher
* http://www.sengpielaudio.com/Rechner-VerstaerkerLautsprecherUndOhm.htm
* [[Franks Werkstatt der Lautsprechertechnik|https://www.youtube.com/channel/UC-Y8jmNTBsS3OoJoxG1qKzQ]]
* https://www.youtube.com/channel/UClO5ZcbwcJV2Kp75E8YsmBw/videos
* https://www.youtube.com/c/SoundBlab/videos
** https://www.youtube.com/watch?v=ew4aED-K5og
* [[HiFi DIY: Lautsprecher - Tipps & Bauanleitungen|http://www.hifi-forum.de/viewforum-104.html]] - haben auch PA foren
* https://www.speakerplans.com/index.php
** https://www.speakerplans.com/index.php?id=links
** https://forum.speakerplans.com/general_forums_cat1.html
* https://web.archive.org/web/20181222022547/http://www.bassreflex.de/index/index.html
* https://www.diyaudio.com/
* https://github.com/search?p=4&q=speaker+design&type=Repositories
** https://github.com/maqifrnswa/scimpy
** https://github.com/alexgorbatchev/boominator
** https://github.com/BryceAshey/speaker-designs
** https://github.com/skahl/speaker-design-notebook
** https://github.com/ShazimC/Stereo_Speaker_Design
** https://github.com/nickmomrik/bluetooth-speaker-design
** https://github.com/bneibarg/Speaker-Design-and-Fabrication
** https://github.com/hubbellc/Speaker
** https://github.com/Connor-Devitt/USB_Speaker
** https://github.com/eerotal/2-way-speaker
** https://github.com/666immortal/BluetoothSpeaker
* https://www.tweekgeek.com/blog-tweek-geek-speek/the-open-source-open-baffle-speaker-project/
* https://site.diy-loudspeakers.com/
*http://www.mh-audio.nl/
* https://speakerwizard.co.uk/
* https://github.com/Taur-Tech/Project-Ryu---Loudspeaker-Drivers
* https://github.com/bang-olufsen/create
* Gehäusebau, Leitungen, Schalldruck, Berechnungen usw.: http://www.hifi-forum.de/viewthread-239-5.html
* https://www.youtube.com/c/JosephCrowesDIYSpeakerBuilding/featured
* https://www.hifi-selbstbau.de/grundlagen-mainmenu-35
* https://www.diysubwoofers.org/
* https://celestion.com/speakerworld/pa_tech/
* https://celestion.com/replace/
* https://celestion.com/speakerworld/cabinetdesigns/
* https://hackaday.com/tag/speaker/
* https://linkwitzlab.com/Fitz/considerations.htm
* https://audiomention.com/types-of-loudspeakers/
* https://education.lenardaudio.com/en/05_speakers.html
* https://www.sps.tue.nl/rmaarts/RMA_papers/aar06pu1.pdf
* https://www.speakerplans.com/index.php?id=faq
* https://www.youtube.com/@frankswerkstatt
* https://www.lutronic.biz/en/connectivity/range/panel-mount-connectors#serie-LT02d
* https://www.lutronic.biz/en/connectivity/range/field-attachables#serie-LT03d
* https://www.lumberg.com/de/quicklock-lumberg-lutronic-de
* https://www.lumberg.com/de/produkte/sortiment/rundsteckverbinder#serie-002
* https://www.cnlinko.com/product/whole
* https://www.tme.eu/de/katalog/p,lutronic_1489/?params=412:1443409_anzahl-pole:3
* https://connector-distribution.com/eu/industrie/netzstecker/lp-serie-netzanschluss/lp-16-serie/m16-kunststoff/188/lp-16-power-netz-steckverbinder-m16-3-pol-maennchen-ip67-max.-400-v-10-a
* https://connector24.de/c/power-steckverbinder/lp-serie-power-stecker
moc3023
repair of a Stairville "led bar 240/8 rgb dmx 30°"

info

* https://www.thomann.de/de/stairville_led_bar_2408_rgb_dmx_30.htm

!! PCBs

LED PCBs

* 4 pieces
* each has 2 LED "segments"
* 10mm LEDs

power supply

* IN: 100-240V 50Hz/60Hz AC
* datecode: 2017/01/05
* "PAUO-36WS(3)"
* OUT: 12V, likely 36W

control board

* chips:
** STC 12C5A60S2
*** MCU
*** https://www.alldatasheet.com/datasheet-pdf/pdf/1179047/STC/STC12C5A60S2.html
*** http://www.stcmicro.com/datasheet/STC12C5A60S2-en.pdf
** TI SN75176B
*** https://www.ti.com/product/SN75176B
** TI LM358 - dual opamp
** 78M05 - 5V 0,5A V-REG
** 2x STC 11F01
*** MCU
*** http://www.stcmicro.com/datasheet/STC11F-10Fxx-en.pdf
** UTC ULN2803G
*** Eight Darlington Arrays
*** http://www.unisonic.com.tw/datasheet/ULN2803.pdf
*** https://www.alldatasheet.com/datasheet-pdf/pdf/168892/UTC/ULN2803.html
*** https://www.conrad.de/de/ratgeber/industrie-40/elektronik-bauteile/uln2803.html
** HEF4069UBT
*** general purpose hex inverter
*** https://www.alldatasheet.com/datasheet-pdf/pdf/17728/PHILIPS/HEF4069UBT.html

display/button board

* 4x LED 7-segment displays
* 4 buttons
* ...

DMX board

* XLR3 male + XLR3 female
* ...


stuff to repair

* control pcb
** 2x 100uF 25V (RVT series?) electrolytics
** likely all darlington array chips (ULN2803G)
** check hex inverter (HEF4069UBT)

* LED PCBs
** few red
** a lot of green
** some blue
** wire resoldering

* check power supply caps
* housing endcap

had to change out some LEDs, particularly green ones are prone to fail.
changed 2 darlington array chips and one electrolytic cap.
works great now.

used some 3mm thick aluminium sheet offcut as new endcap
* https://wiki.opensourceecology.de/Liste_von_m%C3%B6glichen_OSE-Standards
* https://en.wikipedia.org/wiki/List_of_DIN_standards
* https://en.wikipedia.org/wiki/Category:Lists_of_standards
* https://en.wikipedia.org/wiki/List_of_EN_standards
* https://en.wikipedia.org/wiki/List_of_International_Organization_for_Standardization_standards
* https://en.wikipedia.org/wiki/List_of_International_Electrotechnical_Commission_standards
* https://de.wikipedia.org/wiki/Liste_der_DIN-Normen#DIN_1%E2%80%9349999
* https://de.wikipedia.org/wiki/Liste_der_DIN-Normen/DIN_EN
* https://de.wikipedia.org/wiki/Liste_der_DIN-Normen/DIN_EN_ISO
* https://de.wikipedia.org/wiki/Kategorie:DIN
* https://de.wikipedia.org/wiki/Normenliste_DIN_500_bis_DIN_999
* https://www.fasteners.eu/standards/DIN/
* https://www.gewinde-normen.de/
https://opensource.guide/

https://github.com/github/opensource.guide#readme
* jekyll - https://jekyllrb.com/
* hugo - https://gohugo.io/
* pelican - https://blog.getpelican.com/ - used by lowtechmagazine
* zola - https://www.getzola.org/ - rust
* cobalt - https://cobalt-org.github.io/ - rust

lists

* https://staticsitegenerators.net/
* https://jamstack.org/generators/
* https://medium.com/@nampara17/whats-the-best-cms-for-static-websites-12364ab911ef
* https://wiki.python.org/moin/PythonBlogSoftware#Static
* https://wiki.python.org/moin/StaticSiteGenerator
* https://gist.github.com/denji/7205625

Frontends:

* https://www.netlifycms.org/
* https://gohugo.io/tools/frontends/
* https://jekyll.github.io/jekyll-admin/
** https://github.com/jekyll/jekyll-admin/

other tools:

* https://gohugo.io/tools/
* https://github.com/planetjekyll/awesome-jekyll-plugins
* Github Pages, Gitlab Pages
* https://phiresky.github.io/blog/2021/hosting-sqlite-databases-on-github-pages/
friend got a steinberg UR22, an old usb audio interface, i hope to get it working under linux.

* https://alsa-project.org/wiki/Matrix:Main - not to be found
* some people seem to have got it working, even just by pugging it in, without any manual changes
* linus asio?
* https://forums.steinberg.net/t/linux-support-steinberg-ur22/46903/31
* https://o.steinberg.net/en/support/downloads_hardware/downloads_ur22.html
** https://download.steinberg.net/downloads_hardware/UR22/UR22_documentation/UR22_OperationManual_de.pdf

after plugging it in it has some nasty digital noise tone and the real audio has pretty low volume. i have to test a bit more.

stuff

* https://patchwork.kernel.org/project/alsa-devel/patch/20201209161835.13625-1-tiwai@suse.de/
* https://duckduckgo.com/?q=%22alsa%22+steinberg+ur22&t=ffab&ia=web
* https://www.alsa-project.org/main/index.php?search=steinberg&title=Special%3ASearch&profile=default&fulltext=1
** https://www.alsa-project.org/wiki/Matrix:Module-usb-audio
* https://ubuntuforums.org/showthread.php?t=205449
* https://forums.steinberg.net/t/linux-support-steinberg-ur22/46903/44
* https://linustechtips.com/topic/250301-steinberg-ur22-audio-interface-unofficial-linux-support/
projects:

* https://github.com/twischer/StepDownConverter
stepper driver

* https://duckduckgo.com/?t=ffab&q=smoothieware+external+driver&ia=web
* A4982 - 35V 2A
* https://reprap.org/forum/read.php?13,457335
* https://www.pololu.com/product/3730
* https://www.digikey.de/de/products/filter/motortreiberkarten-module/
* https://www.digikey.de/de/products/detail/pololu-corporation/3730/10450537
* https://www.ti.com/lit/ds/symlink/drv8711.pdf
* https://www.ti.com/product/DRV8711#tech-docs


controller

* https://duckduckgo.com/?t=ffab&q=tiny+g+firmware&ia=web
* https://marlinfw.org/
* GRBL
* https://reprap.org/forum/read.php?13,457335
* https://github.com/Smoothieware/Smoothieware
* https://buildbotics.com/
* https://smoothieware.github.io/Webif-pack/documentation/web/html/smoothieboard.html
* https://reprap.org/wiki/Smoothieboard
* https://reprap.org/wiki/Category:32-bit_board


software

* https://winder.github.io/ugs_website/
* https://cnc.js.org/
* http://linuxcnc.org/
* https://deepnest.io/
* https://mellowpine.com/cnc/best-open-source-cnc-software/
* [[Schnell Millionär werden mit diesem Geheim-Trick! - NEO MAGAZIN ROYALE|https://www.youtube.com/watch?v=YNcBqW0CkpM]]
* Cum-Ex und Cum-Cum
* wenn selbsständige oder kleine unternehmer fehler bei der steuererklärung machen kommen hohe strafen auf sie zu, obwohl fehler menschlich sind... wenn große firmen oder kriminelle banden organisiert steuern hinterziehen bzw. dem staat rückerstattete steuern klauen wird kaum etwas gemacht

stuff about storing, mounting, housing hardware in some way

<<list-links "[all[current]tagging[]]">>

* DIN-rail
** https://en.wikipedia.org/wiki/DIN_rail
** https://de.wikipedia.org/wiki/Tragschiene
* https://wiki.opensourceecology.de/Universal_Prototyping_Kit
* https://de.wikipedia.org/wiki/Baugruppentr%C3%A4ger - "Systemgehäuse", based on the 19" Rack and Eurocard standards
** https://en.wikipedia.org/wiki/Eurocard_(printed_circuit_board)
** https://de.wikipedia.org/wiki/Europakarte
* ISPR
** https://de.wikipedia.org/wiki/International_Standard_Payload_Rack
** https://en.wikipedia.org/wiki/International_Standard_Payload_Rack

* organizer
** https://www.kistenberg.com/de

* messebau verbinder? rigging?
* reutlinger / drahtseilhalter
** https://www.messebau.de/montage-verpackung/seilabhaengung/
* draht keilschloss
* https://de.wikipedia.org/wiki/TV-Zapfen
* https://www.huss-licht-ton.de/index.php/Rigging/cat/10037.html
* [[Warum wird Strom immer teurer? (EEG-Umlage, Strommarkt, Strompreis)|https://www.youtube.com/watch?v=YkA65vpeA5g]]
* https://www.verbund.com/de-at/privatkunden/themenwelten/strom-aus-wasserkraft/strompreis-entstehung
* https://github.com/fsr/Stoffkiste
* [[Super Capacitor Module - 12v Solar Shed|https://www.youtube.com/watch?v=OuVUJ3_awiw]]
* [[#139​ Is there a simple and cheap way to protect your super caps? How?|https://www.youtube.com/watch?v=NsTAyD2i3rc]]
* [[Playing with: SuperCapacitor Module 6x 120F 2.7V|https://www.youtube.com/watch?v=trEnwNaEgJ0]]
** [[Scary Update: SuperCapacitor Module 6x 120F 2.7V|https://www.youtube.com/watch?v=_o4Cp-CA6NU]]
* [[Reverse Engineering a Supercapacitor Protection PCB|https://www.youtube.com/watch?v=dJklnvxLR5A]]
** [[700F Super Capacitor Protection PCB - Reverse Engineer Update|https://www.youtube.com/watch?v=JjLiG-X7Htk]]
* [[Electrical engineer explains ultracapacitor Safety Tips and Tricks - Car Audio Applications|https://www.youtube.com/watch?v=BzjVzg_aWcY]]
* [[Fun with ultracapacitors!!|https://www.youtube.com/watch?v=EoWMF3VkI6U]]
<<list-links "[all[current]tagging[]]">>

it is great to get still working or broken stuff from ebay (also ebay-kleinanzeigen in germany) or from dumpsters... maybe you can get stuff from your local recycling depot... it might save you money and maybe you can resell or repair the broken stuff for others to save money.

also: Sharing is Caring... it's nice if people can lend stuff from you if they only need it for one occasion...

* https://depot.social/
* an open alternative to https://nebenan.de/ but also funded by nebenan.de
* https://depot.social/blog/welche-plattform-fuer-welchen-zweck
* https://umsonstladendd.wordpress.com/

and if your don't need something anymore: give it away instead of throwing it away.

it's give and take, you give stuff to someone and might get something from someone else

https://coma-emerald.de/%C3%B6kologische%20Stadtteilzentren.html


some stuff

* https://sustburbia.blogspot.com/
* https://wiki.opensourceecology.de/Open_Source_Ecology_Germany
* https://wiki.opensourceecology.org/wiki/Main_Page
* https://utopia.de/
* https://de.wikipedia.org/wiki/Hanf#Nutzhanf
* Klimannsland
** https://www.youtube.com/channel/UCLKPfqBGqL4gaEvegb_If0Q
* https://www.offene-werkstaetten.org/
* https://wikifactory.com/discover/topics - there are a lot of sustainable projects
* https://www.at-fire.de/


(nutz-)hanf, bio-baumwolle und leinen/flachs und Jute sind gute grundstoffe für vieles

* [[Nachhaltiger reisen: Sind Containerschiffe eine Alternative zum Flugzeug? -- PULS Reportage|https://www.youtube.com/watch?v=D8k1dw0J9LA]]
* cotton?
* hemp?
* linen?

water usage in production?
microplastics?
* https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API
* https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API
* three.js
* [[open source web based 3D model/file viewer]]
* SVG
** https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model#svg_interfaces
* https://hubs.mozilla.com/
120W Mono PA mixing amplifier.
it is meant for installed PA systems but because of it's 24V DC Power option was used with batteries for non-professional mobile use. While using it with a battery a cable with a 3.5mm jack dropped down and shorted on the battery terminals.
After the incident the amp didn't work with either Battery or mains power.
It is not known which of the contacts shorted out but due to the people mentioning sparks i guessed it was the ground of the jack to 24V battery plus. there would've been no sparks if it had hit the ground connection and if it hit the signal connections then the opamps would have just clipped shortly but there would have been caps in line to prevent DC from having a big effect.

I have reverse engineered the whole circuit in order to learn a bit more.

I pretty quickly found the culprit: a blown ground track on the amp-PCB, next to the linear voltage regulator section supplying the mixing circuitry of the amp.
And I also found kind of a design error: only the poweramplifier section is protected by a fuse, the mixing circuitry is not protected by any fuse.
It's more unlikely that the mixing part will cause a short, but there also is no good place to add a fuse for it.
(not realy an audio repair but whatever)

! repair

the micro usb port is completely broken and has to be replaced...

opening the device:

# the fabric cover of the speakers can be pried off pretty easily
# now you can see the two speakers and 9 screw-holes, the screws have to be removed
# now the back-side can be pried open
# you can slide the plastic case out of the metal-frame to the front, be careful with the cables
# the board with all the connections is glued into a small compartment at the backside of the plastic case, is is also held shut by two screws which might be hidden by the glue, carefully remove the glue without damaging the FFC

you need a pretty specific micro usb port, others won't fit propperly, but soldering it is pretty easy once you have the correct one. i soldered with a tiny bit of solderpaste and a hot air soldering statioin.

while opening be careful with the flex cable, if you break it, you need a ~16cm FFC (Flat flex cable) with 15 pins and 1mm pitch (connections on the same side)... but beware: cables for the raspberry pi cameras are also 15pin and 1mm pitch but not same side, which mixes up the pins

repair of FFC

* pretty much all of the glue has to be removed
* you have to remove the PCB at the top of the plastic housing, carefully disconnect the cables and also remove the glue from the wires and the port through the case
* take the damaged FFC out, i carefully removed the foam from the FFC and glued it on the new one, because i didn't have similar foam and din't know where to get it, it might improve accoustics, prevent rattling of the FFC on the case or other cables
* carefully fit the new FFC
* you have to completely close the through-hole to the PCB with glue or else you will have very poor bass performance and bad sounds from the air escaping through the hole

! reverse engineering

in the reverse engineering i just focused on the main parts:

2x 18650 cells in series(?)

uses a CSR8635 bluetooth audio chip by broadcom on a module ([[manufacturer page|https://www.qualcomm.com/products/csr8635]], [[independent wiki page|https://www.electrodragon.com/w/CSR8635]])

N79E814AT20 8051-based microcontroller by nuvoton

NPCA110B "Audio Enhancing Engine and CODEC" - [[Datasheet|https://www.nuvoton.com/resource-files/DA03-NPCA110B1.pdf]]

TPA3130 "15-W stereo, 30-W mono, 4.5- to 26-V supply, analog input Class-D audio amplifier w/ filter free" - [[manufacturer page|https://www.ti.com/product/TPA3130D2]], [[datasheet|https://www.ti.com/lit/ds/symlink/tpa3130d2.pdf]]

not known: some 8-pin IC labeled SUN4004BS
switched mode power supplies very efficient power supply designs rectifying the AC Voltage and stepping it down/up to the desired DC voltage; but DC-to-DC Converters are also often SMPS.
you should know the [[electronic basics]] first

lists/general information

* https://www.we-online.com/web/en/index.php/show/media/07_electronic_components/news_1/blog/midcom_blog_photos/SMPSChart.pdf
* https://www.ti.com/seclit/ug/slyu036/slyu036.pdf
* https://www.ieee.li/pdf/viewgraphs/topology_review_dc_dc_converters.pdf
* https://www.maximintegrated.com/en/design/technical-documents/app-notes/6/6129.html
* https://techweb.rohm.com/knowledge/acdc/acdc_pwm/acdc_pwm04/3551
* https://www.monolithicpower.com/en/the-difference-between-ccm-and-dcm-explained
* [[Texas Instrument's Power Stage Designer Intro - Best Kept Secret|https://www.youtube.com/watch?v=00LJ-ESrMvQ]]

types/topologies:

* Boost/Step-Up (Aufwärtswandler)
** [[DC-DC Boost converter tutorial|https://www.youtube.com/watch?v=wJU7AJgERG8]]
** [[HACKED!: Adding a Current Limit Feature to a Buck/Boost Converter|https://www.youtube.com/watch?v=8uoo5pAeWZI]]

* Buck/Step-Down (Abwärtswandler)
** [[Switch mode power supply tutorial: DC-DC buck converters|https://www.youtube.com/watch?v=CEhBN5_fO5o]]
** [[DIY Buck Converter -- How to step down DC voltage efficiently|https://www.youtube.com/watch?v=m8rK9gU30v4]]
** https://www.ti.com/lit/an/snva038b/snva038b.pdf
* https://sound-au.com/project220.htm
* [[How a PSU With Too LOW Voltage Can Kill Your Electronics Devices! HOW A Buck Converter Works!|https://www.youtube.com/watch?v=KAJbetbyK8Q]]

* Buck–boost - combination/hybrid of above

* single-ended primary-inductor converter (SEPIC) - most buck-boost are sepic
** [[The Most Versatile Voltage Converter you never heard of! The (S)EPIC Converter|https://www.youtube.com/watch?v=XOcA7ijtlCY]]

* Ćuk

* Split-pi topology

* Flyback (Sperrwandler)

* Forward (Eintaktflusswandler)
** 2 Switch forward

* Push-Pull (Gegentaktflusswandler)

* Synchronous Converter
** [[Is this the BEST Voltage Converter? Trying to build a Synchronous Converter!|https://www.youtube.com/watch?v=W4i2FRZ8gXc]]

general

* [[How does a modern Power Supply work?! (230V AC to 5/12V DC) DIY Flyback Converter!|https://www.youtube.com/watch?v=ycT-PItAzNk]]
* [[How does a mobile charger work? SMPS with Opto-Coupler. |https://www.youtube.com/watch?v=2N_T7VFymFg]]
* EEVblog
**[[EEVblog: Power Supply Design|https://www.youtube.com/playlist?list=PLBF35875F73B5C9B5]]
** [[EEVblog #139 - Let's Select a DC-DC Boost Converter|https://www.youtube.com/watch?v=-V_p1GBH4pk]]
* [[The Post Apocalyptic Inventor: SMPS Tutorial|https://www.youtube.com/playlist?list=PLxaGnte1Dq0lgNtfA9H5Hd_YDyjylThJJ]]
** [[SMPS Tutorial (1): Introduction - Switched Mode Power Supplies and Power Conversion|https://www.youtube.com/watch?v=nbKwUSH9NiY]]
** [[SMPS Tutorial (2): Linear Regulators, Voltage References, Switched Mode Power Supplies|https://www.youtube.com/watch?v=BjTD9EVs9v8]]
* [[Power Supply Design #8 How Much Power?|https://www.youtube.com/watch?v=0A49MIG1HrU]]
* [[How SMPS works ~ What Components We Need? Switched Mode Power Supply|https://www.youtube.com/watch?v=cK5WLMFSGnw]]
* https://en.wikipedia.org/wiki/Switched-mode_power_supply
* https://de.wikipedia.org/wiki/Schaltnetzteil
* [[How SMPS works ~ What Components We Need? Switched Mode Power Supply|https://www.youtube.com/watch?v=cK5WLMFSGnw]]
* [[FLYBACK DC - DC Converter Theory And Example|https://www.youtube.com/watch?v=HOXgOWoN0EY]]
* [[Power Supply Troubleshooting and Repair Tips|https://www.youtube.com/watch?v=pffOJdCQ7kw]]

* [[Switch mode power supply tutorial: DC-DC buck converters|https://www.youtube.com/watch?v=CEhBN5_fO5o]]
* https://libre.solar/docs/dcdc_control/
** https://learn.libre.solar/development/dcdc_converter.html
* [[DIY Buck/Boost Converter (Flyback) -- How to step up/down DC voltage efficiently|https://www.youtube.com/watch?v=ZiD_X-uo_TQ]]
* [[DIY LiPo Charge/Protect/5V Boost Circuit|https://www.youtube.com/watch?v=Fj0XuYiE7HU]]
* [[Solar Battery Charger (LiPo/Li-Ion) -- DIY or Buy|https://www.youtube.com/watch?v=kEttqWJrdww]]
* [[EEVblog #272 - Manson 9400 40A 3-15V Switchmode PSU Teardown|https://www.youtube.com/watch?v=bX8IIjf15qY]]
* [[Solar Panel, SuperCapacitors and a Buck/Boost|https://www.youtube.com/watch?v=ITsmOBdBKzk]]
* [[DIY Buck converter - TUTORIAL|https://www.youtube.com/watch?v=SM5qPrOrDrc]]
* https://circuitdigest.com/smps-power-supply-circuits
* https://en.wikipedia.org/wiki/DC-to-DC_converter
** https://en.wikipedia.org/wiki/Category:DC-to-DC_converters
* https://web.archive.org/web/20190717131310/https://sound.whsites.net/project89.htm - Switchmode Power Supply For Car Audio
* https://www.youtube.com/watch?v=Edel3eduRj4
* https://sound-au.com/articles.htm#psud
* [[AC/DC Switch Mode Power Supply (SMPS) Intro and Demo|https://www.youtube.com/watch?v=NZcfn413s0A]]
* https://de.wikipedia.org/wiki/Gleichspannungswandler
* https://de.wikipedia.org/wiki/Kategorie:Gleichspannungswandler
* https://www.ti.com/solution/automotive-dc-dc-converter
* https://www.ti.com/solution/energy-storage-power-conversion-system
* mean well sells some pretty good supplies https://www.meanwell.com/index.html
* [[How Does a Switching Power Supply Work 1 (schematic, explanation, example, modifications)|https://www.youtube.com/watch?v=cX4q0e124C4]]
* [[How Does a Switching Power Supply Work 3 (CCM vs. DCM)|https://www.youtube.com/watch?v=3ySlJ99OSN4]]
* https://www.microchip.com/stellent/groups/SiteComm_sg/documents/Training_Tutorials/en528010.pdf
* https://sound-au.com/project69.htm
* https://sound-au.com/project77.htm
* https://sound-au.com/project89.htm
* https://sound-au.com/project95.htm
* https://sound-au.com/project108.htm
* https://www.tomshardware.com/reviews/power-supplies-101,4193.html
* [[DC-DC CONVERTER controlled via ARDUINO|https://www.youtube.com/watch?v=7UDwytEPK-E]]
* [[This component can control tons of circuits! Digital Potentiometer Guide! EB#51|https://www.youtube.com/watch?v=uezoQ5fkixY]]
* [[Constant Voltage or Current Supply with ARDUINO|https://www.youtube.com/watch?v=rwqY0rYPlVE]]
* [[Reparatur von Schaltnetzteilen an Audio und Video Geräten Teil 1|https://www.youtube.com/watch?v=R4p9ChtH-Gc]]
* [[SDG #263 How to modify the output voltage of a SMPSU power supply|https://www.youtube.com/watch?v=OQAFSKKWOoE]]
* [[Switching Regulator Component Selection & Sizing - Phil's Lab #71|https://www.youtube.com/watch?v=FqT_Ofd54fo]]
* [[Switching Regulator PCB Design - Phil's Lab #60|https://www.youtube.com/watch?v=AmfLhT5SntE]]
* https://www.learnabout-electronics.org/PSU/psu30.php
* [[How a 2 Phase Boost Converter works with LTC3784|https://www.youtube.com/watch?v=g_mwHuC0QtU]]
* [[Wie funktioniert ein Schaltnetzteil? - Grundlagen der Primärseite (Teil 1)|https://www.youtube.com/watch?v=Hj0NSPcv9x0]]
* [[ EW0075 - Phoenix Contact DIN Rail Power Supply Teardown |https://www.youtube.com/watch?v=PZ3v-qSZ2Tk]]
* https://hackaday.com/2018/05/17/the-pros-and-cons-of-microcontrollers-for-boost-converters/




PFC

* [[Electronics Tutorial - Common Power Factor Correction methods|https://www.youtube.com/watch?v=YiBuFQD1TYw]]
* [[How a PFC converter Works with Texas Instruments UCC28180|https://www.youtube.com/watch?v=qPx2CWA0WTI]]
* [[How PFC works pt2 with Texas Instruments UCC28180|https://www.youtube.com/watch?v=95UYDVM_EIs]]
* [[Electronics Tutorial - Common Power Factor Correction methods|https://www.youtube.com/watch?v=YiBuFQD1TYw]]


running AC SMPS from DC

* https://electronics.stackexchange.com/questions/262645/using-dc-voltage-instead-of-ac-to-supply-smps
* https://www.heise.de/select/ct/2016/2/1452238205894722?hg=1&hgi=2&hgf=false

design:

* Simulation Software can help a lot with designing
** https://de.wikipedia.org/wiki/LTspice
** https://de.wikipedia.org/wiki/SPICE_(Software)
** https://en.wikipedia.org/wiki/SPICE
* https://www.joretronik.de/Web_NT_Buch/Vorwort/Vorwort.html
* https://en.wikipedia.org/wiki/Synchronverter
* https://de.wikipedia.org/wiki/Regelleistung_(Stromnetz)#Frequenzregelung_in_der_UCTE
* "synthetic inertia", "virtual inertia", "added mass"
* "momentanreserve", "rotierende masse", "virtuelle schwungmasse"
* https://www.elektroniknet.de/power/spannungswandler/virtuelle-schwungmasse-fuer-das-stromnetz-der-zukunft.138767.html
hardware

* https://mutable-instruments.net/ - open modular synth modules
* https://vonkonow.com/wordpress/leet-synthesizer/
* https://zynthian.org/
* diy analog synth stuff
** [[DIY SYNTH VCF Part 1: Analog Filtering Basics|https://www.youtube.com/watch?v=3tMGNI--ofU]]
** [[DIY SYNTH VCF Part 2: Active Filters & Resonance|https://www.youtube.com/watch?v=YNoj9Rrw_VM]]
** [[DIY SYNTH VCF Part 3: Resonant High-Pass & Vactrol-Based Voltage Control|https://www.youtube.com/watch?v=ITJX9jP-zm4]]
** [[Designing a diode ladder filter from scratch|https://www.youtube.com/watch?v=jvNNgUl3al0]]
** [[DIY SYNTH PSU: How to design a simple dual power supply|https://www.youtube.com/watch?v=pQKN30Mzi2g]]
** [[Playlist: modular synth|https://www.youtube.com/playlist?list=PLluPQLh1xzlJE1XECrfIHch-rwNusG16s]]
** [[Playlist: JUST BUILD IT SERIES. build a modular synth|https://www.youtube.com/playlist?list=PLluPQLh1xzlL2agiCCQFClcsutli90Qnz]]
** [[Playlist: LOOK MUM NO COMPUTER HOW TO's|https://www.youtube.com/playlist?list=PLluPQLh1xzlIzqgTBwTo_a5k_O63JxwjQ]]
** https://www.youtube.com/c/MoritzKlein0/videos
* [[DIY VCF series|https://www.youtube.com/playlist?list=PLHeL0JWdJLvT1PAqW4TtvxtRoXyk741WM]]
* [[DIY VCO series|https://www.youtube.com/playlist?list=PLHeL0JWdJLvTuGCyC3qvx0RM39YvopVQN]]
* [[DIY arpeggiator series|https://www.youtube.com/playlist?list=PLHeL0JWdJLvQikVrVPdnbrtIM8qbdLc5E]]
* [[Synth Diy Guy|https://www.youtube.com/channel/UCaTca38SJErVLsfYkrg2R9w]]
** [[Easy beginner kits!|https://www.youtube.com/playlist?list=PLRbjRzRH7DfGdyUK0ptKbzp72qwDG5NTC]]
** [[SDIY Tutorials|https://www.youtube.com/playlist?list=PLRbjRzRH7DfELfoWWa6J-Srjq1u4sShKP]]
* [[I AM O VCA/RingMod/Voltage Controlled Gate - DIY Modular in a Week 2.2|https://www.youtube.com/watch?v=m_z0NfnLqRM]]
* [[A 70's Synth You Made At Home With Monthly Magazines|https://www.youtube.com/watch?v=evndbrVoG2Y]]
* https://hackaday.com/2019/01/27/open-source-fader-bank-modulates-our-hearts/
** https://16n-faderbank.github.io/
* https://blog.zynthian.org/
* [[#1197 DIY Analog Synthesizer (part 1 of )|https://www.youtube.com/watch?v=h61_3Sw2uYk]]
* [[ Stephen Hawes: DIY Synth|https://www.youtube.com/playlist?list=PLIeJXmcg1baInh2B4i02_7BnUDyPs9Rog]]
* https://www.youtube.com/watch?v=otkW_q0_VIU
* https://www.youtube.com/watch?v=yz37Yz315eU
* 

software

* https://awesomeopensource.com/projects/synthesizer
* https://github.com/webprofusion/OpenAudio
* https://surge-synthesizer.github.io/
* [[Arduino polyphonic synthesizer up to 32 voices! asmsynth library - make your 8-bit music|https://www.youtube.com/watch?v=F6uLDALwZoA]]

stuff

* TB-303 - acid synth
** https://de.wikipedia.org/wiki/Roland_TB-303
** https://en.wikipedia.org/wiki/Roland_TB-303
** https://github.com/search?q=303+synth&ref=opensearch
** https://sourceforge.net/projects/open303/
** https://blog.wavosaur.com/best-free-tb-303-emulation-sotware-vst-plugins-standalone/
* https://www.hitsquad.com/smm/lic/Open-Source/SOFTWARE_SYNTHESIZERS/
* http://www.vintagesynth.com/articles/open-source-synth-projects
* https://www.diyaudio.com/community/threads/syntripp-2-way-2-part-virtual-single-point-source-horn.264485/
* https://github.com/finominal/SynTripP
* https://www.youtube.com/watch?v=sdlf9oPrTdY
* https://www.reddit.com/r/SoundSystem/comments/ykgj8c/metric_plans_for_syntripp_speakers/

builds

* https://www.reddit.com/r/diyaudio/comments/lnfo27/art_welters_syntripp_build_pics/
* https://www.reddit.com/r/diyaudio/comments/t8byxy/my_syntripp_rig_is_finally_complete_feels_so_good/
* https://www.reddit.com/r/diyaudio/comments/r17sv5/syntripp_paraflex_subs_aures_soundsystem/
* https://www.reddit.com/r/SoundSystem/comments/16xun0m/syntripp_build_log/
* https://www.reddit.com/r/diyaudio/comments/z330ez/3d_printing_a_pair_of_syntripp_speakers/
* https://www.reddit.com/r/diyaudio/comments/16xxqua/syntripp_build_log/
* https://www.reddit.com/r/diyaudio/comments/12jmj99/wip_syntripp_hd215_trailer/
* https://www.reddit.com/r/diyaudio/comments/1acavkc/syntripp_over_paraflex_c2d/
create systemd unit files and copy them to the folder /etc/systemd/system/

backup.service - change <path_to_script_file> to the path where your script from above lies

```
[Unit]
Description=Service+Timer for backing up stuff
After=network.target
#OnFailure=unit-status-mail@%n.service

[Service]
Type=simple
ExecStart=<path_to_script_file>
```

backup.timer - modify timer to your liking

```
[Unit]
Description=Service+Timer for backing up stuff
After=network.target
#OnFailure=unit-status-mail@%n.service

[Timer]
OnCalendar=*-*-* *:00/15:05
Persistent=true

[Install]
WantedBy=timers.target
```

and run:

```
systemctl daemon-reload
systemctl enable backup.service
```
<div class="tc-table-of-contents">

<<toc-selective-expandable 'TableOfContents'>>

</div>
Someone came in with a Tascam Midistudio 688 with problems. The 688 is an analog 10 Channel Studio Mixing Console with integrated Tape recorder which can record and play back 8 different tracks onto the tape.

The Problem was with the Tape Mechanism seemingly randomly stopping playback or recording, the owner suspected a slipping capstan belt.

There is a great Video on youtube explaining how to open the recorder assembly, access the belt and also explains another possible failure mode related to the mechanism detecting the tape and tape type:
https://www.youtube.com/watch?v=fEL9AI7ux0I

during the first opening i was annoyed by the meterbridge beeing verry loose, so i just carefully fastened the two screws at the hinges a bit more. That was not requested by the owner, but was appreciated by the owner.

the belt seemed still fine to me at first, so i only cleaned the belt and the capstan as well as using contact cleaner for the tape and tape-type detecting switches.

i also cleaned the inside of the console a bit, but it wasn't too dirty, just a bit of dust.

the owner of the device decided to replace the belt anyways, due to the device being 30 years old or so and the belt being still original.

when the new belt arrived i immediately noticed the belt beeing much stronger and with firmer fit compared to the old one. I simply changed the belt, made sure everything is where it belongs, restored the very nice cable management and assembled the console again.

i couldn't replicate the stopping of playback or recording neither before nor after. But the owner got it back and didn't report any problems till now.

The electronics might be dated in it, but the console still runs and has a really good build quality. Every cable is managed in some way and there are nice reusable wire cableties fastened to the frame and boards which made servicing easy and it looks super clean.
nowadays you probably would have much less pcb's in there, maybe everything on one pcb and would need much less cables for interconnecting.
got offered a partially broken TM-D1000 digital mixing console on ebay-kleinanzeigen

first two inputs are broken

* https://www.tascam.eu/de/docs/TM-D1000_Referenzhandbuch.pdf
* https://en.audiofanzine.com/digital-mixer/tascam/TM-D1000/
* https://www.soundonsound.com/reviews/tascam-tmd1000
* has no motorized faders
* TDIF
** https://de.wikipedia.org/wiki/TASCAM_Digital_Interface
** https://en.wikipedia.org/wiki/Tascam_Digital_Interface
** tdif is pretty old and useless nowadays
* https://elektrotanya.com/tascam_tm-d1000_digital_mixer_sm.rar/download.html
* the AC-Adaptor seems to be 9V AC

i did not buy it.

tascam dm24 is nicer, bigger display but modern digital mixers offer much more features like the XAir series or Allen & Heath QU-16
* https://github.com/mdnghtman/us122-linux
* https://wiki.briata.org/doku.php
* https://linuxmusicians.com/viewtopic.php?t=1073
* https://bbs.archlinux.org/viewtopic.php?id=124964
* https://www.alsa-project.org/wiki/GIT_Server
* https://www.alsa-project.org/wiki/Matrix:Vendor-Tascam
** https://www.alsa-project.org/wiki/Matrix:Module-usb-usx2y
** https://www.alsa-project.org/main/index.php/Matrix:Module-usb-us122l
* https://forum.manjaro.org/t/tascam-us-122l-not-recognized/88977
* https://www.lix.polytechnique.fr/~smimram/tascam/
* https://www.linuxquestions.org/questions/linux-hardware-18/tascam-usb-us-122l-does-yours-work-with-ubuntu-9-04-please-read-help-755171/
* https://alsa.opensrc.org/Tascam_US-122
* https://wiki.ubuntuusers.de/.asoundrc/
* see also [[linux audio]]
* https://github.com/alsa-project/alsa-lib/issues/269
* https://help.ubuntu.com/community/UbuntuStudio/UsbAudioDevices
* usb_stream
* https://askubuntu.com/questions/485988/tascam-us-122l-usb-audio-interface-jackd
* https://github.com/SaberMage/Alsa-USB
* keywords
** linux usx2y
*** https://github.com/torvalds/linux/tree/master/sound/usb/usx2y
*** https://help.ubuntu.com/community/TASCAM_US-122#Step_3:_Download_TASCAM_US-122_Firmware
*** https://www.kernel.org/doc/html/latest/sound/alsa-configuration.html#module-snd-usb-usx2y
*** https://www.kernel.org/doc/html/latest/sound/cards/index.html
*** https://www.kernel.org/doc/html/latest/sound/cards/hdspm.html
*** https://www.kernel.org/doc/html/latest/sound/cards/emu10k1-jack.html
** linux usb_stream
** aplay -l usb_stream
** pulseaudio usb_stream
** alsa usb_stream
** jack usb_stream
** pipewire usb_stream
** alsa us-122l
* https://fedoraproject.org/wiki/Audio
** https://fedoraproject.org/wiki/How_to_troubleshoot_sound_problems
* https://help.ubuntu.com/community/UbuntuStudio/UsbAudioDevices
* https://wiki.ubuntuusers.de/Audiodateien_umwandeln/
* https://alsa-project.org/wiki/Help_To_Debug
* https://debianforum.de/forum/viewtopic.php?t=154286
* US-122 and US-122L are very different
* https://wiki.briata.org/doku.php
* https://discourse.ardour.org/t/tascam-us-122-on-recent-ubuntu-debian/89211
* https://forums.linuxmint.com/viewtopic.php?f=42&t=83565
* https://bbs.archlinux.org/viewtopic.php?id=124964
* https://ubuntubin.com/de/q/137158
* https://ubuntustudio.org/ & https://labs.fedoraproject.org/de/jam/
* https://discourse.ardour.org/t/tascam-us-122-with-ubuntustudio-7-10/80780
* https://bugs.archlinux.org/task/33499
* https://forum.ubuntuusers.de/topic/usb-audio-interface-tascam-us-122l-in-ubuntu-/


todo:

* linux troubleshoot soundcard
* https://www.linuxfromscratch.org/blfs/view/stable/multimedia/multimedia.html
* https://www.linuxfromscratch.org/blfs/view/stable/postlfs/devices.html
* https://wiki.archlinux.de/title/Kategorie:Sound
* https://wiki.archlinux.org/title/General_recommendations#Multimedia
* https://wiki.gentoo.org/wiki/Project:Sound
* https://wiki.gentoo.org/wiki/Category:Multimedia
** https://wiki.gentoo.org/wiki/ALSA
** https://wiki.gentoo.org/wiki/PulseAudio
* https://duckduckgo.com/?t=ffab&q=linux+troubleshoot+soundcard
Tascam US-428 - 7,5VAC 1A Netzteil fehlt - Mischpult/DAW-Controller/Audio-interface

The Controller states on the model/serial sticker to require a 7,5V AC 1A power supply.

Finding a 7,5V power supply is pretty hard, also finding single 7,5V transformers is not easy. But i've got a 8V transformer that might work.

I Tried different things but the controller always behaved strange. Different LEDs would light and stay on after power up and i don't recall it being recognized by a PC.

Because the transformer was bare, without case, i designed a case in freecad and a friend 3d printed it for me.
The case is screwed together so it can be easily serviced later.

Because i didn't know what to do i had it collecting dust for a few month.

Then, after i had acquired some new tools i decided to give it another try.

I started checking the internal power lines on the PCB. They were pretty easy to find because the traces were easy to follow back to the linear regulators. There also were testpoints, though they are unmarked, not every trace has testpoints.
It has 2 separate 5V lines, 3,3V probably mainly for digital stuff, as well as 12V and -12V for analog audio circuits. One of the 5V lines uses the same connector as the +-12V, so it might be some 5V for analog circuitry.

I used a multimeter and measured the DC and AC voltage on each line. One of the 5V lines was ~400mV low and had quite some ripple which was apparent with the AC function.
The other lines seemed pretty fine.

Both 5V and the 3,3V linear regulators are fed by a 16V 2200uF electrolytic cap and each regulator has a small 25V 47uF smc electrolytic.
I measured these caps with my ESR meter. The small 47uF ones are a bit suspect, might be a bit high, but the 2200uF one shows as possibly leaky and with a really  high ESR.
I desoldered the 2200uF cap to check it out of circuit and the measurement got confirmed. It does not look bad outside, so i had no different clue on that one missbehaving.
The other 5V rail and the 3,3V rail were not heavily affected bad the bad cap it seems.
Luckily 16V 2200uF caps are common in PC components and i got a few lying around that i salvaged. I found a fitting one as replacement.
After soldering it i measured the voltages again and it was spot on 5V and no more ripple.

I then tried connecting it to a PC again, but it crashed my OS. So i decided to carry on any other test with another PC and maybe check the circuit again.
* madelineproto (php)
* pyrogramm (python) - https://github.com/pyrogram/pyrogram
* telethon (python)
* https://github.com/eternnoir/pyTelegramBotAPI
* https://python-telegram-bot.org/
* https://t.me/BotTalk
* https://telegra.ph/Introduction-to-bot-programming-02-21
* https://t.me/AtAdminBot
** https://git.thevillage.chat/Abfelbaum/atadminbot
* Captcha Bot
* [[telegram bot/mtproto frameworks]]
* https://t.me/GroupHelpBot - questionable
* https://t.me/MissRose_bot
* @join_captcha_bot
* https://storebot.me
** Wenn sie n hohes Ranking haben, und die sourcen offen sind, kann man dem Vertrauen, weil er auch in vielen anderen Gruppen ist. Aber, da du mit so nem bot ziemlich viel an Daten abgreifen kannst, vertrau ich da nur nem offiziell im Store stehenden oder selbst geschriebenen
* https://t.me/SangMata_BOT - name changes
* https://t.me/shieldy_bot
** https://github.com/1inch/shieldy
* Combot Anti-Spam (CAS) is shit, it's not clear on which basis messages get flagged as spam and banned and there seems to be a pretty high false positive rate... getting someone or yourself unbanned from CAS is pretty hard because the support is unfriendly and not helpful at all, they don't want to admit any arror in their shitty algorythms

other bots

* @letmebot
there are a lot of far-right and conspiracy groups on telegram... but there're also a lot of spam bots and probably spy bots... one should respect private data and only use public data... tools i might develop will only be used for independent and antifascist journalism...

* https://github.com/th3unkn0n/TeleGram-Scraper
* https://github.com/UnderdogDE/TeleGram-Scraper
* https://github.com/search?q=telegram+scrape - a lot of malicios scrappers for spam-adding people to groups
* https://github.com/paulpierre/informer
* https://sector035.nl/articles/2021-05
* https://www.getsignal.info/blog/telegram-for-osint
* https://github.com/Postuf/telegram-osint-lib
* https://en.wikipedia.org/wiki/Gephi
there are a lot of spam bots on telegram. scapping other groups for users and spam-adding these people to other groups is not common anymore. most of the spam that is currently going on are messages promoting pornographic content or crypto-financial "trading" scams. often with join or website links.

some spammers seem to scrape names from groups scramble them up ans use them as names for their bots. profile pictures might also be stolen.
the bots seem to 

meassures:

- manually deleting spam - annoying and cumbersome
- simple one-button captcha - bots seem to press the fist button they encounter
- 
<<list-links "[all[current]tagging[]]">>

------------------------------

* https://sound-au.com/articles.htm#test
* https://sigrok.org/
* https://sound-au.com/p-cat.htm#tst

cheap testing tools:

* Lc100-a LC Meters (the lc200-a is more expensive)
** https://www.youtube.com/watch?v=FB2xF3PGix8
* Gm328 Transistor / component tester with potetiometer (seems to be an improved version of the single button one, more features)
** https://www.youtube.com/watch?v=C38eSPOF1o0
* https://www.youtube.com/watch?v=YdUsomCH5eE
* https://www.youtube.com/watch?v=BK7gnJavW28
* https://hackaday.com/tag/test-and-measurement/
* https://hackaday.com/tag/test-equipment/
* https://hackaday.com/tag/measurement/
* https://hackaday.io/list/11054-test-equipment-projects
* https://hackaday.com/tag/tester/
* https://mitxela.com/projects/better_continuity_test
* [[ Build A Cheap DIY Signal Injector Pen Useful For Electronics Fault Finding - In A Pen! |https://www.youtube.com/watch?v=_aI6TLLVpDQ]]
* https://www.youtube.com/watch?v=cGRPBV-_ZQc
* https://www.youtube.com/watch?v=LyrOzRsCPqA
* https://www.youtube.com/watch?v=nWCZCLGtyDU
* https://www.youtube.com/watch?v=wp1dPG9_N1w
* https://www.youtube.com/watch?v=vefQWjOLsFg

stuff

* [[Test & Measurement Fundamentals|https://www.youtube.com/playlist?list=PLKxVoO5jUTlvsVtDcqrVn0ybqBVlLj2z8]]

* https://www.hackster.io/projects/tags/oscilloscope
* https://www.hackster.io/projects/tags/test+equipment
* https://www.crowdsupply.com/test-equipment
* [[Learn Electronics Repair #11 - Test Equipment|https://www.youtube.com/watch?v=lutL4wft6fQ]]
* https://www.youtube.com/watch?v=T2UNVoT4gCI
* battery capacity can be meassured using some kind of [[powerlogging / power meter|powerlogging / power meter / AC power analysis / energy monitor]] constantly measuring the voltage and current.
** some [[electronic load]]s have such features build in, but sometimes just any load (e.g. an inverter with some high power heater) is more suitable for big batteries.
** testing from fully charged to lowest safe voltage
* with used cells it might be usefull to note initial voltage
* meassuring voltage after full charge and one wek of storage indicates the self-discharge rate
** does it indicate internal resistance?
* internal resistance is also important
** cells with high internal resistance are bad and should get recycled, but that depends on the cell chemistry
** https://en.wikipedia.org/wiki/Internal_resistance
** https://www.landtinst.com/what-is-internal-resistance-ir-and-how-to-test-ir/
** https://www.dv-power.com/battery-capacity-test-or-internal-resistance/
** https://batteryuniversity.com/learn/article/how_to_measure_internal_resistance
** https://batteryuniversity.com/index.php/learn/article/rising_internal_resistance
** https://learn.sparkfun.com/tutorials/measuring-internal-resistance-of-batteries/all
** https://diysolarforum.com/threads/testing-internal-resistance-280ah-cells.14750/
* [[EEVblog #140​ - Battery Capacity Tutorial|https://www.youtube.com/watch?v=R8hTQXqURB4]]
* https://www.paulvdiyblogs.net/2019/03/a-pretty-universal-battery-cell-tester.html
* https://www.paulvdiyblogs.net/2016/06/simple-method-to-log-charging-and.html

tools i came accross:

* EBC-A20 - charger + electronic load
* i have a B6AC charger + load
* chargers and electronic loads are important, no matter the type
* YR1035+ - measures internal resistance
* https://simulationcorner.net/index.php?page=sam
* espeak
* https://commonvoice.mozilla.org/
* https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API
** https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis
there are diffent versions of this concept around. 7 R's is pretty common, but there are more in-depht versions too.

Reduce - reducing consumption in the first place, don't use single-use products, buy concious

Refuse - e.g. refuse poorly designed products not made to last or not repairable 

Reuse - e.g. borrowing, sharing, reselling, donating

Repair - repair broken items

Recycle/Recover - if the item can't be repaired and used anymore, extract salvageable parts and recover/recycle materials to produce new things

links

* https://www.rethinkrecycling.com/blog/reduce-reuse-recycle-repair-refuse/
* https://www.theoceanpreneur.com/entrepreneurship/what-can-you-do-rethink-refuse-reduce-re-choose-reuse-recycle/
* https://prezi.com/bsmsksc0dxdc/5rs-reuse-reduce-reuse-recycle-repair-and-recover/
* https://repair.eu/
* https://www.thomann.de/de/the_t.racks_dsp_206.htm

save file format on first look pretty similar to the [[the t.racks DSP 4x4 Mini|the t.racks DSP 4x4 Mini and Mini Pro reverse engineering]] format.

the pc software has an integrated pdf or so, that shows the RS232 settings and some of the RS232 commands and data for controlling the device.
https://www.thomann.de/de/the_t.racks_dsp_4x4_mini.htm

seems to be made by http://en.musicrown-audio.com/index.html

* reports as "Musicrown Dsp Process" in Linux
* uses the USB HID class
* see below for lsusb output
* https://www.thomann.de/de/the_t.racks_dsp_4x4_mini_reviews.htm reviews give some information on gains and sensitivity

!! file format reverse engineering


!! pc software reverse engineering

i thought i don't need to reverse engineer the software, but i can't make full sense of everything in the file format, so it seems like i need too.


!! tests 

''TODO: muss nochmal eine messreihe machen in der ich mit den festen limiter werten den genauen output messe und nicht versuche die limiter werte an die output amplitude anzupassen''

also bei unsymmetrisch in:
* symmetrisch out ist normal, aber bisschen lauter, ca. 0,536-0,537V
* unsymmetrisch out: halbiert (0,268V)

```
alle tests 1kHz und unsymm in

symm out ~0,53 ca. -0,4-0,7dB output Gain

2V in; symm out:
out 0,57: limit: -5,5dB
out 0,8: limit: -2,5 ... -3dB
out 0,93: limit: -1 ... -1,5dB
out 0,91: limit: -1,5dB
out 0,85: limit: -2 ... -2,5dB


2V in; unsymm out:
out 0,57: limit: 0 ... 0,5dB
out 0,8: limit: +3dB?
out 0,93: limit: +5dB
out 0,91: limit: +4,5dB
out 0,85: limit: +3,5 ... +4dB


alles unsymm out:
3,6V is noch gut, 3,7V ist clip am input
3,6V in und +1,2dB input gain geht gerade so. (1,96V out)
3,6V in und 1,3dB input gain ist clip
3,6V in; 0dB input gain; +0,5db output gain (bei einem -0,7dB korrigiertem kanal; also -0,2dB out gain) ist clip - auch auf symmetrisch out - sind ~3,92V out symm; 1,96V unsymm
```

!! lsusb -v output:

```
Bus 003 Device 002: ID 0168:0821 Musicrown Dsp Process
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x0168 
  idProduct          0x0821 
  bcdDevice            0.00
  iManufacturer           1 Musicrown
  iProduct                2 Dsp Process
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0029
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      27
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
```



!! the t.racks DSP 4x4 Mini Pro

* https://www.thomann.de/de/the_t.racks_dsp_4x4_mini_pro.htm
* manual: https://images.static-thomann.de/pics/atg/atgdata/document/manual/555772_c_555772_de_online.pdf

i bought one to check it out to improve the [[Sonnensystem]], because of the preset-switching functionality.

this device is basically the same. it uses the same dsp pcb and only uses a slightly different main pcb. it obviously has XLR inputs and outputs, so the pcb has to be a bit bigger. it also feaures a latching power switch. 

the input signal leds are missing on the pro version, but the 5-pin connector for the leds is still present, so you could probably diy them if you need to. one of the pins is probably a fixed power-rail or ground and the other ones are the switched lines for each led.

the pro has ventilations grilles, i wonder what they expect to get hot? it also got rack brackets included, but they waste a lot of space. one can easily fit two of the pros next to each other in 1U, but maybe not many people would use them that way.

the preset switch input was a main reason for me buying it, but sadly there is not much documentation on it. another buyer commented in their review that the switch input is potential-free, but the official manual doesn't state anything about the input.

it seems one has to hold the build in buttons pressed for atleast around 3 seconds before it changes preset.
probably a good idea so it doesn't change when something accidentaly bumps against it.
we would like to use a key-switch as preset selector, but i'm not sure how it would behave with a permanent-on switch, because the built-in buttons are just momentary.
the built-in buttons an the switch input are just in parallel.
they use a common ground and a 5V-pullup data line which gets pulled down to ground by the button/switch. they might only register changes 
there are cheap IR thermal cams from china based on the 8x8 pixel AMG8833, costing around 60€

* https://www.diy-thermocam.net/
* https://en.wikipedia.org/wiki/Thiele/Small_parameters
* https://de.wikipedia.org/wiki/Thiele-Small-Parameter
* https://www.eminence.com/support/understanding-loudspeaker-data/
* "added mass method thiele small"
* frequency response - spectrum analysis
* (total) harmonic distortion
* impulse response
* http://www.audiodesignguide.com/AudioMesurement/index.html
* https://en.wikipedia.org/wiki/Audio_system_measurements
* https://en.wikipedia.org/wiki/Electrical_characteristics_of_dynamic_loudspeakers
* https://www.epanorama.net/documents/audio/speaker_impedance.html
* [[T/S Parameters Explained (Part 1)|https://www.youtube.com/watch?v=JdQ3mLU5zBE]]
* [[T/S Parameters Explained (Part 2)|https://www.youtube.com/watch?v=JdQ3mLU5zBE]]
* [[Speaker Specs Explained! |https://www.youtube.com/watch?v=jASaNuQ1-JQ]]
* http://parameters.perkhorns.net/
* [[#TSP #Lautsprecher WUNDERWAFFE Thiele & Small - kinderleicht gemessen und praktisch erklärt|https://www.youtube.com/watch?v=LNO-yVwfpKQ]]
* [[#TSP #Lautsprecher UNENTSCHIEDEN? - Thiele & Small Messung im Vergleich|https://www.youtube.com/watch?v=rjTHHEGzC6I]]
<<list-links "[all[current]tagging[]]">>

* https://github.com/gr4per/dsp206
a crew gifted me this monitor speaker, it got blown up by someone. they connected the aux speaker output to the line input or something.

2x tda7294

* https://www.st.com/resource/en/datasheet/tda7294.pdf
* https://www.st.com/en/audio-ics/tda7294.html

there are 3 electrolytic caps (10uF 63V) dead, 2 are completely blown up and one is just bulged.
had to clean the mess from the 2 blown up ones.

the tda7294 for the aux speaker output is cracked an has a burnhole in it, so it's pretty visibly dead.

the main tda7294 looked fine at first, but it rapidly heats up, a lot when powered on.
both tda7294 need replacement then.

also 2 diodes are shorted, they are part of the standby/mute circuitry, which switches the amps on after a short delay to prevent pop-noises when switching it on and the caps charge up.

one is marked ZD1 on the pcb and has a blue ring on the small SOD-80/DO-213 glass package, so it's a zener diode.
the other one seems to be a normal diode, according to the ST micro application circuits and other example circuits the other diode was probably a 1N4148, a very common diode.

i could not find out which model or atleast zener voltage the zener diode has, so i have to guess.
the supply is 29V AC (~40V rectified DC). i'm guessing 20-25V zener voltage should be fine. I'll get ZMM20 and ZMM24 diodes for testing.
** IR gp4063d
*** https://www.infineon.com/dgdl/Infineon-IRGP4063D-DataSheet-vNA-EN.pdf?fileId=5546d462533600a401535655ee0c2450
*** https://octopart.com/search?q=gp4063d&currency=USD&specs=0
* marking "RT#" stands for "resistor - temperature dependant" like an NTC
** it was an ntc: NTC10D-20
* https://pdf1.alldatasheet.com/datasheet-pdf/view/1132215/VATRONICS/NTC10D-20.html
* https://www.alldatasheet.com/datasheet-pdf/pdf/1132215/VATRONICS/NTC10D-20.html
* http://www.hifi-forum.de/viewthread-182-6835-2.html
* https://www.mikrocontroller.net/topic/341606
* i head the NTCs failing might be a common problem on those amps, but the igbts failing also seems common
* it seems 

!! https://www.lautsprecherforum.eu/viewtopic.php?t=6787
* [[the t.racks DSP 4x4 Mini|the t.racks DSP 4x4 Mini and Mini Pro reverse engineering]]
* [[the t.racks DSP 206|the t.racks DSP 206 reverse engineering]]

not yet:

* https://www.thomann.de/de/the_t.racks_dsp_204.htm
* https://www.thomann.de/de/the_t.racks_dsp_408.htm
* https://www.thomann.de/de/the_t.racks_fir_dsp_408.htm
* https://www.thomann.de/de/the_t.racks_8x8_matrix.htm
* https://www.thomann.de/de/the_tracks_ds_24.htm

other:

* [[Behringer Ultradrive Pro DCX2496]]
* https://de.wikipedia.org/wiki/Thyristor
* https://en.wikipedia.org/wiki/Thyristor
* https://de.wikipedia.org/wiki/Dimmer
* https://de.wikipedia.org/wiki/Diac
* https://de.wikipedia.org/wiki/Triac
general info

* https://de.wikipedia.org/wiki/Service-Management
* https://de.wikipedia.org/wiki/Issue-Tracking-System
** https://en.wikipedia.org/wiki/Issue_tracking_system
* https://en.wikipedia.org/wiki/Category:Bug_and_issue_tracking_software
* https://en.wikipedia.org/wiki/Category:Task_management_software
* https://de.wikipedia.org/wiki/Helpdesk
** https://en.wikipedia.org/wiki/Help_desk
** https://en.wikipedia.org/wiki/Help_desk_software
* https://de.wikipedia.org/wiki/Kategorie:Customer-Relationship-Management
** https://en.wikipedia.org/wiki/Category:Customer_relationship_management_software
* https://de.wikipedia.org/wiki/Kategorie:Bugtracker - mehr oder weniger
* https://de.wikipedia.org/wiki/Kategorie:Projektmanagementsoftware
** https://en.wikipedia.org/wiki/Project_management_software
** https://de.wikipedia.org/wiki/Kategorie:Freie_Projektmanagementsoftware
* https://de.wikipedia.org/wiki/Projektmanagement-Software

lists

* https://en.wikipedia.org/wiki/Comparison_of_issue_tracking_systems
* https://de.wikipedia.org/wiki/Issue-Tracking-System#Software
* https://en.wikipedia.org/wiki/Comparison_of_help_desk_issue_tracking_software
* https://en.wikipedia.org/wiki/Category:Free_task_management_software
* https://en.wikipedia.org/wiki/Category:Free_customer_relationship_management_software
* https://de.wikipedia.org/wiki/Kategorie:CRM-Software
* https://en.wikipedia.org/wiki/Category:Customer_relationship_management_software
* https://en.wikipedia.org/wiki/Help_desk_software
* https://de.wikipedia.org/wiki/Kategorie:Freie_Projektmanagementsoftware
** https://en.wikipedia.org/wiki/Category:Free_project_management_software
* https://en.wikipedia.org/wiki/Comparison_of_project_management_software
* https://en.wikipedia.org/wiki/Comparison_of_CRM_systems
* 

software

* OTRS-CE / forks
** https://en.wikipedia.org/wiki/OTRS
** https://otrscommunityedition.com/ ?
** https://de.wikipedia.org/wiki/OTRS
** https://www.softoft.de/blog/otobo-ticketsystem
** https://www.znuny.org/en

* Zammad
** https://de.wikipedia.org/wiki/Zammad

* Redmine
** https://www.redmine.org/
** https://en.wikipedia.org/wiki/Redmine
** https://de.wikipedia.org/wiki/Redmine

* ~OpenProject
** https://de.wikipedia.org/wiki/OpenProject
** https://en.wikipedia.org/wiki/OpenProject

* osTicket
** https://osticket.com/
* [[ Your Very First TIG Welds with EXTREME Detail |https://www.youtube.com/watch?v=TgekhRZ_d2o]]
* [[ Adventures in TIG Brazing |https://www.youtube.com/watch?v=jM2_LBvzg6c]]
* [[ TIG TAWK! AC Welding Aluminum |https://www.youtube.com/watch?v=38zP4cu8kgg]]
* [[ Cheap Ebay Welder -- WILL IT TIG?! |https://www.youtube.com/watch?v=--1lSmtuyUg]]
* [[ Random Weldy Talk (Pulse TIG Welding Aluminum) |https://www.youtube.com/watch?v=a6fUCApr03g]]
* [[ Welding Straight Is Hard To Do |https://www.youtube.com/watch?v=svHI9nmV5nw]]
* [[ TFS: 5 Aluminum Welding Drills |https://www.youtube.com/watch?v=YoWSOC_Gx0w]]
* [[ Making A Stand! Why I Love TIG Welding |https://www.youtube.com/watch?v=aGsFdudG7Ho]]
* [[ PuLsEd TiG WeLdiNg |https://www.youtube.com/watch?v=HOL1bMC-UJQ]]
* [[ Making A Stand! Why I Love TIG Welding |https://www.youtube.com/watch?v=aGsFdudG7Ho]]
* [[ TIG Welding - Puddle Control |https://www.youtube.com/watch?v=Vfhz9anpaWE]]
* [[ TIG Welding 101: An All Inclusive Introduction to GTAW |https://www.youtube.com/watch?v=gCCdiksvXMU]]
* [[ TIG Welding Aluminum Basics |https://www.youtube.com/watch?v=XSGnCf0Bcto]]
* [[ How to TIG Weld Aluminum part 1 |https://www.youtube.com/watch?v=VOqhh36Kcxo&list=PLp0pALmMwc6sTKLkRThyuHqNfJOKeSOki]]
* [[So zündet Dein WIG Schweißgerät perfekt! HF Zündung optimieren|https://www.youtube.com/watch?v=YN0Xw2Esw_M]]
a friend of mine wants to start a repair bussiness and got me a pair of nice TOA SC-35L horn speakers (mid-high frequency) from is broken electronics supplier. these speakers came with mounting brakets and a mounting plate with suction cups. I don't know how or where they have been used, they had a pretty long cable with an old DIN 41529 Plug (they where connected in parallel). They are in very good condition and only have one defect, where they must have been dropped and the edge of the back housing is slightly deformed and cracked, but not mayor.

! TOA SC-35L data:

* rated power: 35W
* max power: 53W
* horn mouth diameter: 355x224mm
* impedance: 16Ohms
*

! amplifier design

because these speakers are 16 Ohms and are not meant for low frequencies it's not as easy as just hooking them up to an amp and playing musik. The amp should be able to propperly work with these Speakers and deliver enough voltage to drive them, also it is best to use a crossover with a high pass to filter out lower frequencies. These horns use a high freuency compression driver which is really inefficient for low frequencies, these mostly get converted to heat and that can easily damage the drivers and destroy them.

I've allready got a cheap chinese amplifier board with an [[TPA7498|https://www.st.com/en/audio-ics/tda7498.html]] amplifier chip on it. I started with basically copying the Test circuit/Application circuit from the datasheet with KiCAD. But i had problems because different parts are not or not propperly documented. choosing the values for the low pass filter at the output and the frequency shift circuit is pretty much undocumented and the likelyhood of getting answers in the communityforums seems pretty low.

I then changed my plan to use other integrated amplifier chips.
* [[bypass / decoupling capacitors]]

* [[Tonstudio bauen - Heimwerkerking Fynn Kliemann|https://www.youtube.com/watch?v=yUhnwmvSFb0]]
* [[Oben ohne, unten offen - Der Studiobau - Kliemannsland|https://www.youtube.com/watch?v=qEZM_ANORcA]]
* [[Building My Dream Music Studio - Step 1 of 3 - Marble Machine X #128|https://www.youtube.com/watch?v=Y19FucqIZ3A]]
* [[DIY Recording Studio at Home for Cheap - I Like To Make Stuff|https://www.youtube.com/watch?v=EqKMGA03KYY]]
<<list-links "[all[current]tagging[]]">>

tools needed for different stuff

* multimeter
** different probes, e.g. normal/fine tips, clips, hooks
* usb programmer (programming eprom)
* glue/adhesive
** T8000/T7000
* oscilloscope
** there are cheap oscilloscopes from china
** miniware sells the DS212 and DS213 which seem to be pretty good
** probes
* soldering tools
** irons/stations
*** miniware TS80 and TS100
*** pine64 pinecil (cheaper and more open then miniware)
** hotair (for reflow soldering / reworking)
*** often integrated in a soldering station with a normal soldering iron
** hotplates (for reflow soldering)
*** miniware hotplate
*** DIY hotplates


guides etc.

* [[EEVblog #168 - How To Set Up An Electronics Lab|https://www.youtube.com/watch?v=R_PbjbRaO2E]]
* chinese company miniware makes some pretty good inexpensive tools
* https://hackaday.com/category/tool-hacks/
* http://www.miniware.com.cn/products/
* pine64
* https://www.greatscottgadgets.com/
* https://www.sainsmart.com/collections/tools-instruments
* [[Essential Tools that you will need for creating electronics projects!|https://www.youtube.com/watch?v=7-djg27lJyQ]]
* [[Basic/Advanced Tools & Materials for Electronics|https://www.youtube.com/watch?v=cL8FHz-TOzQ]]
* [[EEVblog #954 - How To Setup An Electronics Lab For $300|https://www.youtube.com/watch?v=HicV3Z6XLFA]]
* [[EEVblog #1248 - INSANE! A 0.02% Process Meter for $9? WTF!|https://www.youtube.com/watch?v=y3h02BDPMJw]]
* [[EEVblog 1378 - NEW Uni-T UT61E+ Multimeter - Still bang-per-buck king?|https://www.youtube.com/watch?v=ZxzQZFRznp0]]
* [[Adam Savage's Guide to Drill Bits!|https://www.youtube.com/watch?v=vetc7rEYnjI]]

stuff

* https://hackaday.com/category/tool-hacks/
* https://vonroc.de/produkte - cheap powertools
basic transistors

* [[Electronic Basics #22: Transistor (BJT) as a Switch|https://www.youtube.com/watch?v=WRm2oUw4owE]]
* [[MOSFET BJT or IGBT - Brief comparison Basic components #004|https://www.youtube.com/watch?v=VlMdSCI29A0]]
* [[SSTC pt. 2 - BJT vs MOSFET vs IGBT|https://www.youtube.com/watch?v=dRxBfXlIWiA]]
* [[Transistors Explained - How transistors work|https://www.youtube.com/watch?v=J4oO7PT_nzQ]]
* [[LE3_6f Integrierte Gate Treiber für Mosfet/IGBT|https://www.youtube.com/watch?v=OXm8SRZ46Fk]]
* transistors are not just switches but current amplifiers
* https://de.wikipedia.org/wiki/Transistorgrundschaltungen
* [[Transistor Lied - Song about Bipolartransistors - lyrics by Sophia Transistor|https://www.youtube.com/watch?v=yFCnzuOLizw]]
* BJT - bipolar junction transistor
** [[All About Electronics: BJT (Bipolar Junction Transistor)|https://www.youtube.com/playlist?list=PLwjK_iyK4LLDoFG8FeiKAr3IStRkPSxqq]]
* JFET
* https://www.youtube.com/watch?v=GDDwTbM9DLw

FET - Mosfet

* https://www.mikrocontroller.net/articles/MOSFET-%C3%9Cbersicht
* [[Electronic Basics #23: Transistor (MOSFET) as a Switch|https://www.youtube.com/watch?v=o4_NeqlJgOs]]
* [[Here is why MOSFET drivers are sometimes essential! -- MOSFET Driver Part 1 (Driver, Bootstrapping)|https://www.youtube.com/watch?v=8swJ_Bnsgl4]]
** [[Warum MOSFET Treiber manchmal essentiell sind?! - MOSFET Ansteuerung Teil 1 (Treiber, Bootstrapping)|https://www.youtube.com/watch?v=pdTRzBHOC5w]]
* [[Here is why Gate-Drive Transformers are sometimes essential! - MOSFET Driver Part 2 (Potential-free)|https://www.youtube.com/watch?v=B7Eqrf2M-Iw]]
* [[Should you buy a GaN Power Adapter? Or is it a scam? -- Testing GaN FETs!|https://www.youtube.com/watch?v=oTUZQDpQcU4]]
* [[Designing Power MOSFET Circuits - Circuit Tips and Tricks|https://www.youtube.com/watch?v=56p3_aORiJ0]]
* https://www.youtube.com/results?search_query=driving+mosfets
* [[MOSFET – The Most significant invention of the 20th Century|https://www.youtube.com/watch?v=bHwl8TdEI6k]]
* [[MOSFETs und Mikrocontroller - Grundlagen, Datenblätter, praktische Schaltungen & Typen|https://www.youtube.com/watch?v=uxGzMDKNvTo]]
* [[Arduino DC Motor mit MOSFET H-Brücke steuern - Einstellbare Drehrichtung & Geschwindigkeit|https://www.youtube.com/watch?v=13bCzydTz8I]]
* LMG1210 - mosfet driver
* [[Dual Complementary Opto-Isolator (DCOI) MOSFET Driver #6 - Holy Grail|https://www.youtube.com/watch?v=d_5LwHLcsu0]]
* [[EEVblog 1461 - The MOSFET Search CHALLENGE|https://www.youtube.com/watch?v=9wuyPZjjR9k]]
* [[SDG #279 Simple Common Base MOSFET driver|https://www.youtube.com/watch?v=6gPfDS5ELww]]
* [[ MOSFETs Drivers and Bootstrap - Types, Logic Level and More |https://www.youtube.com/watch?v=wtMOtueXNJQ]]
* [[ SDG #273 MOSFETs, Gate Drivers and PWM Driver Design |https://www.youtube.com/watch?v=6mPzyz_I2zE]]
* A1SHB and A2SHB mosfets
* [[ How To Test MOSFETs In Circuit Using A Multimeter |https://www.youtube.com/watch?v=zIzEm-YDdyA]]
* https://www.youtube.com/watch?v=LNu00nMBaaQ

IGBTs

* [[Electronic Basics #28: IGBT and when to use them|https://www.youtube.com/watch?v=RxRJW09A_XA]]
* [[SSTC pt. 3 - choosing IGBT transistors & how to read datasheets|https://www.youtube.com/watch?v=hGQsfOeYhuc]]
* https://hatchjs.com/how-to-check-an-igbt-with-a-multimeter/


replacing

* https://www.electronics-notes.com/articles/electronic_components/transistor/choosing-replacements-transistors.php
Example:

* https://nicosemsrott.eu/en/budget
* https://www.youtube.com/channel/UC_bMh2cqdwioGicb_zbdevw
* Lobbyregister
* transparenz fördert die glaubhaftigkeit von politikern und ihren entscheidungen, es macht entscheidungen für die bevölkerung nachvollziehbar und fördert insgesammt das vertrauen in die politik.
* [[Korruption / Lobbyismus]]
* [[Tilo Jung: "Wenig Interesse an Aufklärung" - ZAPP - NDR|https://www.youtube.com/watch?v=ZxgB2r_GCgg]]
* https://www.abgeordnetenwatch.de/

* https://en.wikipedia.org/wiki/Travelling_salesman_problem
* https://de.wikipedia.org/wiki/Problem_des_Handlungsreisenden
* [[Coding Adventure: Ant and Slime Simulations|https://www.youtube.com/watch?v=X-iSQQgOd1A]]
* [[Die unverzichtbare galvanische Trennung durch einen Trenntrafo|https://www.youtube.com/watch?v=Q8QSarnGstw]]
* [[ Test - Do Audio Transformers Mess Up Sound? - Part 1 |https://www.youtube.com/watch?v=so_sXkH8QOk]]
** [[ Do Audio Transformers Change the Sound? - Part 2 |https://www.youtube.com/watch?v=8C4hzzFijm4]]
it's a fucking proprietary and monetary shithole

* https://taz.de/Alternative-Streamingangebote/!5760402/ - alternativen zu netflix, amazon und co
* https://de.wikipedia.org/wiki/Miracast

public broadcast in germany is pretty open:

* https://mediathekview.de/
open

* https://solokeys.com/
** https://github.com/conorpp/u2f-zero - predecessor, no longer maintained, not as secure
* https://www.nitrokey.com/


closed, proprietary

* https://thetis.io/
* https://store.google.com/product/titan_security_key
* https://onlykey.io/
* https://www.yubico.com/
* https://www.minusrus.com/en/
* Danley Synergy horns or Jericho series
* https://www.diyaudio.com/forums/multi-way/233453-whats-easiest-diy-unity-horn-project.html
* http://www.hificircuit.com/community/threads/index-of-diy-synergy-and-unity-horns.23/
* https://www.cowanaudio.com/unity.html
* https://www.diyaudio.com/forums/multi-way/212513-spreadsheet-design-own-synergy-simple-conical-horns.html
* https://www.libinst.com/SynergyCalc/
** https://www.libinst.com/SynergyCalc/Synergy%20Calc%20V5.pdf
* http://techtalk.parts-express.com/forum/tech-talk-forum/50902-buyouts-into-a-synergy?231569-Buyouts-into-a-Synergy=
* as DAW Controller or control for Behringer XAir devices or so
* https://hackaday.com/tag/digital-gauge/
* see [[Midi]]
* see [[Open Sound Control (OSC) (protocol)]]
* https://hackaday.com/2022/04/19/oled-display-kicks-knob-up-several-accurate-notches/
* https://hackaday.com/tag/volume-knob/

using

* normal [[encoders]] or [[potentiometers]] are great, but lack feedback
* feedback can be provided using Displays or LED indicators, like bars or rings
* [[bldc motor (as) encoder]]
* [[motor / motorized faders / potentiometers]]
* [[microcontroller IO expansion (shift register, multiplexer, io expander)]]

* inspiration
** https://www.thomann.de/de/daw_controller.html
** https://www.thomann.de/de/computer_controller_etc.html


first design primarily for behringr XR18

* channel number in multibles of 2, atleast 4? maybe 6?
* mute buttons with (red) leds
* fader/encoder/potis for volume
** motorized?
** or just visual feedback
* display for information
* led to show colour from scribble strip
* volume indication (bargraph or so)
* displays? (oled or tft?)

other projects

* http://www.instructables.com/id/A-Framework-For-Making-Affordable-Stylish-Modula/
** https://www.reddit.com/r/arduino/comments/2linqg/my_custom_midi_controller/
* https://forum.arduino.cc/t/arduino-daw-controller-motorized-fader/541497/4
* https://recording.de/threads/ansteuerung-motorfader-potorpoti-diy-midi-controller.180379/
* [[Arduino based MIDI remote controller with motorized faders|https://www.youtube.com/watch?v=L6clR0FPKQM]]
* http://96khz.org/htm/midicontroller31.htm
* http://wiki.midibox.org/doku.php?id=start
** https://www.musiker-board.de/threads/diy-projekt-faderbox.537871/
** http://ucapps.de/
* monome - not all hardware is open, but there are "clone" projects
** https://hackaday.com/blog/?s=monome
** https://github.com/TheSlowGrowth/MonomeArcClone
* https://gearspace.com/board/music-computers/1164315-build-yourself-daw-controllers.html
* https://www.diyrecordingequipment.com/blogs/news/15851772-diy-daw-controller-part-1-choosing-a-midi-interface
* https://hackaday.com/2019/09/29/upgrading-a-midi-controller-with-an-fpga/
* https://en.wikipedia.org/wiki/MIDIbox
* https://en.wikipedia.org/wiki/Arduinome
* https://dartmobo.com/
tiddlers i forgot to tag (so i don't loose them)

<<list-links "[all[tiddlers]untagged[]!is[system]]">>
* https://www.itwissen.info/Elektrostat-electrostatic-loudspeaker.html
* https://www.itwissen.info/Elektrostatischer-Lautsprecher-electrostatic-loudspeaker.html
* https://www.itwissen.info/Piezo-Lautsprecher-piezoelectric-loudspeaker.html (not unusual)
* https://assemblepapers.com.au/2017/04/28/technological-disobedience-ernesto-oroza/
* https://www.technologicaldisobedience.com/
<<list-links "[all[current]tagging[]]">>




* https://hackaday.com/series_of_posts/all-about-usb-c/
* https://de.wikipedia.org/wiki/USB-C
* https://en.wikipedia.org/wiki/USB-C
* https://hackaday.com/2022/11/13/diy-usb-charging-the-right-way/
* XLR 5pin or 3pin connector see [[DMX Connector]]
* isolation using optocouplers or so
* MAX485 and the SN75176 RS-485 to serial transceiver
** or ADM483
* FT232RL adapter
* one can get cheap DMX to usb adapters for 10-15€ online (ebay/aliexpress/etc.)

these adapters can be bought for around 20€ from china or for about 50€ from western manufacturers/resellers

stuff


* https://opendmx.net/index.php/Category:USB
* FT232RL/FT232BM (USB to Serial/RS232) + SN75176 (RS-485 bus transceiver) - unbuffered, without protection
** https://www.enttec.com/product/lighting-communication-protocols/dmx512/open-dmx-usb/
** https://sourceforge.net/projects/opendmxusb/ ?
** https://openschemes.com/homebrew-usb-dmx-interface-with-sparkfun/
** https://opendmx.net/index.php/Open_DMX_USB
** https://www.erwinrol.com/page/projects/op en-dmx-usb/
* https://opendmx.net/index.php/Anyma_uDMX
* https://opendmx.net/index.php/Digital_Enlightenment_USB-DMX
* https://opendmx.net/index.php/KarateLight
* https://opendmx.net/index.php/DMXking_USB_DMX512-A
* https://wiki-de.dmxcontrol-projects.org/index.php?title=DMX-Sender_f%C3%BCr_weniger_als_10_Euro
* https://sourceforge.net/projects/open-rdm/
** http://www.hoelscher-hi.de/hendrik/light/openrdm.htm
* https://sourceforge.net/projects/dmx485/ - abandoned
* https://sourceforge.net/projects/avrdmx/ - abandoned
* https://openschemes.com/homebrew-usb-dmx-interface-with-sparkfun/
* maxim integrated has a big selection of rs485 transceiver chips
* https://lienher.org/jean-marc/usb2dmx/index_en.html - very old design
* https://www.epanorama.net/newepa/2019/10/20/enttec-open-dmx-diy/
* https://doityourselfchristmas.com/forums/showthread.php?7009-USB-to-DMX-dongle-Enttec-Pro-compatible
* https://fritzing.org/projects/arduino-to-dmx-converter/
* https://github.com/xanthium-enterprises/usb-to-serial-rs485-Converter-non-isolated
* https://github.com/magmastonealex/DMXAdapters
* https://github.com/arneman44/4Port-usb-DMX-adaptor - 4 ports
* https://diyprojects.tech/2013/05/diy-usb-dmx-dongle-interface-for-under-10/
** https://diyprojects.tech/2014/03/diy-usb-dmx-controller-for-under-10_2_ethernet_cable/
** https://diyprojects.tech/2014/04/dmx-rs485-wrong-board-fix/
** https://diyprojects.tech/2014/06/ft_prog-fix-your-ftdi-rs485-dmx-interface/
* https://juvar.mbnet.fi/blog/?p=384 - OpenDMX Compatible Unbuffered USB-DMX Interface (part 2)
* http://www.hoelscher-hi.de/hendrik/light/openrdm.htm
** https://sourceforge.net/projects/open-rdm/

opto isolation

* https://www.crazy-logic.co.uk/archives/171
* https://www.maximintegrated.com/en/design/technical-documents/app-notes/2/2116.html
* https://www.mathertel.de/Arduino/DMXShield.aspx
* https://electronics.stackexchange.com/questions/472507/ft232r-for-rs-485-dmx512-with-isolation-tx-optocoupler
* https://antwortenhier.me/q/wie-kann-dmx-512-mit-optokopplern-entkoppelt-werden-61692948001
* https://www.instructables.com/FTDI-USB-Adapter-Based-DMX-Transmitter-With-Isolat/
* [[DMX USB Pro - RF Hackhttps://www.youtube.com/watch?v=EHe0AoqLXVw]]
* [[Compact USB to DMX Converter with full electrical isolation|https://www.youtube.com/watch?v=iuj_EAr7pkQ]]
** https://www.elektormagazine.com/magazine/elektor-52/42072
* https://github.com/xanthium-enterprises/isolated-usb-to-serial-rs232-rs485-converter - missing schematics and propper information
** https://www.xanthium.in/industrial-grade-din-rail-mountable-isolated-usb-to-serial-rs232-rs485-converter
* https://github.com/crossfireprod/USB-DMX-Isolated
* https://github.com/embeddedee/IsoNxpDmxRdm
* 


buffered?

* https://github.com/DaAwesomeP/dmxusb
* https://github.com/OpenLightingProject/rp2040-dmxsun
* https://www.eeweb.com/dmx512-a-controller-implementation/

software

* https://www.erwinrol.com/page/projects/open-dmx-usb/
* https://hackaday.com/2022/10/12/usb-power-isolator-keeps-smoke-in/
* https://hackaday.com/2014/04/27/galvanic-isolated-ftdi-saves-your-computer/
* one can get "1500V USB to USB Isolator ADUM4160 ADUM3160 USB Isolation Module" for around 10€ from ebay/aliexpress
* http://designideas.cocolog-nifty.com/blog/usb/index.html
hantek

* there is no hantek oscilloscope which provides AC coupling
* the software from hantek is pretty bad, but ~OpenHantek and Sigrok / ~PulseView

for some meassurements an isolation transformer and USB isolators should be uesed

stuff

* https://hackaday.com/tag/usb-oscilloscope/
*  https://hackaday.com/2021/01/16/usb-c-programmable-power-supply-for-any-project/
* USB PPS power bank?
* https://techtest.org/usb-power-delivery-ladegeraete-mit-pps-uebersicht-und-info/#Welche_Ladegeraete_unterstuetzen_USB_PPS
* https://akkutest.org/was-ist-pps-und-avs-bei-usb-c-powerbanks-und-ladegeraeten/
* https://techtest.org/die-elecjet-powerpie-powerbank-mit-pps-im-test-ideal-fuer-das-samsung-galaxy-s20/
* https://techtest.org/test-baseus-power-bank-20000mah-mit-65w-power-delivery-mit-pps/
* https://www.reddit.com/r/UsbCHardware/comments/rcemh4/power_banks_with_pps/
* USB PPS trigger
* fnirsi fnr48
* xilica
* dbx
** not PX series - has a pop when switching off, can destroy tweeters
* alto dsp
* Behringer DCX2496
got some old LED Modules/Spots that got replaced at a local company.

most of them had their cables cut, without the driver, but one of them luckily had the LED driver still connected. I connected the led driver to a power cord for testing and measured the output voltage and current of the LED Driver.

35,8V - 36V - 36,2V
0,22A - 0,23A -

have to measure the open circuit voltage of the driver
* https://www.thomann.de/de/classified.html
* kleinanzeigen.de
* ebay.de
* gebrauchte-veranstaltungstechnik.de/
* https://www.sonderposten-veranstaltungstechnik.de/
* https://www.zoll-auktion.de/auktion/index.php
* https://www.dresden.de/de/stadtraum/umwelt/abfall-stadtreinigung/entsorgung/gebrauchtwaren.php
** https://www.dresden.de/de/stadtraum/umwelt/abfall-stadtreinigung/entsorgung/gebrauchtwaren.php
** https://www.verschenkmarkt-dresden.de/cid_641
had this amp laying around for a while because it doesn't output anything and i wanted to check if one could repair it. its really cheap and pretty much only worth the scrap aluminium from the case but one can try.

i hoped that maybe the amp chip is still fine and just some other cheap component is dead.
the amp chip used is a TDA7377 with 2x 30W (class AB). the case claims it has "1400W max", that is just bullshit.
other active components were a c1815 npn transistor and JRC 4558D dual opamps, and a diode or two.

i tested the signals at the rca inputs, the opamps and the inputs to the amp chip. the signal seemed fine. also the power and the standby signal seemed good. so the amp chip is pretty dead probably. i didn't check if the fault open-collector pin on the TDA7377 indicated something. i disassembled the amp completely and desoldered salvageable parts. got a few parts from it.
* [[ Testing a UV/UVC test card |https://www.youtube.com/watch?v=n3KaLlaDZEg]]
* https://web.archive.org/web/20160421120324/https://www.musikhaus-korn.de/de/varytec-wind-up-stativ-mit-kurbel-und-aluminium-38m/pd/61981
* https://www.musikhaus-korn.de/de/varytec-wind-up-stativ-mit-kurbel-und-aluminium-38m/pd/61981
* https://www.manualslib.de/manual/411003/Varytec-Wind-Up-380.html

Wartung

* https://www.musikhaus-korn.de/de/eurolite-stw-370a-kurbelstativ-370cm-alu/pd/142187
* https://www.manualslib.de/manual/411003/Varytec-Wind-Up-380.html
* https://images.static-thomann.de/pics/atg/atgdata/document/manual/339407_c_339407_de_online.pdf

copy of Manfrotto 087NW:

* https://www.manfrotto.com/de-de/wind-up-alu-lampenstativ-silber-3-segmente-087nw/
* https://www.manfrotto.com/global/wind-up-with-safety-release-cable-087nw/
https://konglomerat.org/projekte/velozack.html

Goals

* improvements of original design
** better documentation with FreeCAD, Inkscape SVG or similar instead of files from proprietary software
** better build guides
* new design which fits Euro Containers better
** https://en.wikipedia.org/wiki/Euro_container
** multible options of fastening cargo
*** holes/cutouts for ratchet straps
*** airline rail
** fastening options could at the same time be used for an optional ratched strap box


optional box idea

* douze G4 Traveller Eco Box
* https://friedafriedrich.de/cb-items/grunalf/
* https://friedafriedrich.de/cb-items/adfc-friedrich/
* https://www.youtube.com/c/christianjackson/playlists
* https://www.youtube.com/c/EventelevatorDe/playlists
* https://www.youtube.com/c/mothergrid_veranstaltungstechnik_news/playlists
* https://www.youtube.com/c/stage223/featured
** [[Veranstaltungstechnik -- Grundlagen ~ stage223|https://www.youtube.com/watch?v=BDxjGPF517k&list=PLHZD33csOYTTOQNm4gqOkvOpXf_ob5BMq]]
* [[Entertainment industry connectors.|https://www.youtube.com/watch?v=6Ay9T3o9OSw]]
* [[Entertainment industry 400A powersafe connectors.|https://www.youtube.com/watch?v=tTakz9rYIqY]]
* [[My favourite industrial connector (Ceeform).|https://www.youtube.com/watch?v=feCZs9YpH3M]]
* http://www.hifi-forum.de/viewforum-127.html
* http://www.hifi-forum.de/viewforum-237.html

* https://wiki.production-partner.de/allgemein/seitenverzeichnis-alle-themen-in-der-uebersicht/
cool:

* prodd
* Turbo Events
* Leipzig: Ultraschall
** https://ultraschall-pa.de/
** https://gebrauchte-veranstaltungstechnik.de/?modul=ads&site=userads&userid=2423

kenne ich nicht näher:

* https://stageport.de/
* [[Schimpfen.Drängeln.Mittelfinger - Kampf auf dem Asphalt - Exakt - Die Story - MDR|https://www.youtube.com/watch?v=qDoSIV37aM0]]
* andere menschen wissen was das thema angeht mehr als ich, aber ich sammle hier mal gedanken
* wir müssen den induvidualverkehr dauerhaft veringern, es reicht nicht wenn alle menschen auf elektro autos umsteigen, es müssen mehr menschen mit fahrrad und ÖPNV fahren oder carsharing nutzen, wenn sie mal ein auto brauchen
* lastenräder können sogar für firmen und handwerker interessant sein, ansonsten wäre es für handwerker und firmen auch sinnvoll Elektro transporter wie Streetscooter zu haben.
* sogar VW autohändler können gute ideen haben: https://www.spiegel.de/auto/fahrkultur/kaufpraemie-fuer-elektroautos-autohaendler-sieht-foerderung-kritisch-a-a7505e65-ef9b-4eff-97cf-8376208ae546
* https://www.victronenergy.com/live/start?do=index
* see also [[inter IC or inter device communication, networking]]
* https://www.victronenergy.com/upload/documents/Whitepaper-Data-communication-with-Victron-Energy-products_EN.pdf
* https://www.victronenergy.com/live/open_source:start

some information here focusses on the connections of the VE ~ColorControl GX (different VE devices support different connections/protocolls)

IP/TCP networking and VE VRM platform

* the free but proprietary VE VRM portal with API needs an internet connection (ethernet cable, wlan-usb-dongle or a gsm/3g dongle with sim card)
    * data can be saved internally (last 48h) or on flashdrive or sd card if no internet connection is present, data can be transfered to VRM if connection resumes
* https://www.victronenergy.com/live/ccgx:modbustcp_faq - open, industry-standard protocoll for integration with PLCs and all kinds of other devices
* MQTT: https://github.com/victronenergy/dbus-mqtt/


Venus OS

* "Venus OS" is the open source linux-based operating system of the colorcontrol gx and several other VE products... programmers can extend it due to it being open source
* https://github.com/victronenergy/venus/wiki

VE.Bus

* weird proprietary protocoll

VE.Can / CANBus / NMEA 2000

* proprietary, but seems to be CANBus compatible.
* has different pinout than other CANBus ports
* people arround SimpBMS have reverse engineered the VE.Can protocoll atleast to some extend
** https://www.secondlife-evbatteries.com/collections/accessories/products/simp-bms
** https://github.com/Tom-evnut/SimpBMS
** https://github.com/Tom-evnut/VEcan
* https://www.victronenergy.com/live/ve.can:nmea-2000:start

VE.Direct

* VE.Direct protocol is open
* uses I²C?
* https://www.victronenergy.com/live/vedirect_protocol:faq
* https://beta.ivc.no/wiki/index.php/Victron_VE_Direct_DIY_Cable - the cable is a 4-pin 2.54mm pitch JST-XH cable

~ColorControll GX special stuff

* "USB device" ist wohl nicht belegt
* "Wenn mehr als zwei VE.Direkt Produkte angeschlossen werden müssen, kann ein USB-Anschluss verwendet werden."??? gibt es da einen adapter?

some other sources

* https://community.victronenergy.com/questions/48924/can-bms-protocol-specification.html
* https://community.victronenergy.com/questions/47702/vecan-and-vebus.html
* ~OpenBroadcasterStudio (OBS) - https://obsproject.com/
** https://obsproject.com/wiki/
*** [[Quickstart|https://obsproject.com/wiki/OBS-Studio-Quickstart]]
*** [[Overview|https://obsproject.com/wiki/OBS-Studio-Overview]]
*** [[Sources|https://obsproject.com/wiki/Sources-Guide]]
*** [[using SRT Protokoll|https://obsproject.com/wiki/Streaming-With-SRT-Protocol]]
** https://streamlabs.com/ - based on OBS, the normal desktop clients seems to be also open source, other software and service is proprietary though
** https://www.obs.live/ - some tutorial articles
*** https://www.obs.live/articles/2019/5/1/how-to-stream-with-two-pcs-using-obs-studio-and-the-ndi-plugin
** https://en.wikipedia.org/wiki/Open_Broadcaster_Software
** due to OBS supporting the use of ffmpeg it is possible to use all input and output formats, codecs and protocols supported by ffmpeg (libavcodec and libavformat)
*** https://ffmpeg.org/ffmpeg-codecs.html
*** https://ffmpeg.org/ffmpeg-formats.html
*** https://ffmpeg.org/ffmpeg-protocols.html
** VLC and all formats/codecs and streams supported by can be used as OBS Source
** Tools
*** Outfield (Fernsteuerung für Open Broadcaster Software (OBS).) - https://f-droid.org/packages/com.matt.outfield
* https://digital-stage.org/

* https://en.wikipedia.org/wiki/Software_vision_mixer#Open_source
* https://en.wikipedia.org/wiki/Comparison_of_screencasting_software
* [[Hinter den Kulissen unseres LIVESTREAM Studios!! & ZOTAC GAMING RTX 3080 AMP Holo Einbau! - FlipFloid|https://www.youtube.com/watch?v=_sYZPMMkRpk]]
* [[Building a FULL Streaming Setup on the Cheap!|https://www.youtube.com/watch?v=L6ZJaKqALgM]]
* https://en.wikipedia.org/wiki/Audio_Video_Bridging
* https://github.com/Avnu/libavtp
* https://github.com/Avnu/OpenAvnu
* https://opensource.com/article/19/1/basic-live-video-streaming-server
* https://opensource.com/article/20/6/obs-websockets-streaming
* https://alternativeto.net/software/streamster/about/
* https://bozhang-26963.medium.com/low-latency-dash-streaming-using-open-source-tools-f93142ece69d


* Hardware
** https://hackaday.com/2019/09/27/a-raspberry-pi-4-video-streaming-backpack/
** [[FreeDeck - Open Source Stream Deck Alternative - HID, Arduino|https://www.youtube.com/watch?v=-3Zw8hbpVq4]]


* Protocols
** SRT
*** https://obsproject.com/wiki/Streaming-With-SRT-Protocol
** HLS
*** https://de.wikipedia.org/wiki/HTTP-Streaming
*** https://en.wikipedia.org/wiki/HTTP_Live_Streaming
*** https://obsproject.com/forum/resources/how-to-do-hls-streaming-in-obs-open-broadcast-studio.945/
*** https://opensource.com/article/20/2/video-streaming-tools
*** https://ffmpeg.org/ffmpeg-formats.html#hls-2
** RTMP - proprietary, old, not very reliable
*** https://opensource.com/article/19/1/basic-live-video-streaming-server
** Dash
*** https://ffmpeg.org/ffmpeg-formats.html#dash-2
** NDI?


* Android Streaming apps
** https://github.com/fyhertz/spydroid-ipcamera
** https://github.com/begeekmyfriend/yasea ?
** https://github.com/hypeapps/Endoscope
*** Endoscope (Live-Video-Streaming zwischen Android-Geräten über WLAN) - https://f-droid.org/packages/pl.hypeapp.endoscope

* full conference
** https://opensource.com/article/20/5/conference-free-software
** rc3 vom CCC



eine idee für streaming von einem lokalen computer mit eriner lokalen und einer mobilen kamera:

~WhiteKIBA
Also für Stationär kann man OBS gut benutzen. Unterwegs gibt es ne hand voll Apps

nginx rtmp Server

https://github.com/arut/ngin

https://www.nginx.com/products/nginx/modules/rtmp-media-streaming/

Das geht mit minimaler Config auf kleinster Hardware

Den RTMP Stream holt man sich dann halt als Source in OBS

Also in OBS richtet man sich eine VLC Videoquelle ein

Und VLC zieht dann halt den RTMP Stream

Thorbijoern
ok, danke, das hilft mir auf jeden fall schon mal weiter.
könnt ihr mir noch eine gute, am besten open source, app empfehlen?

~WhiteKIBA
[Antwort auf Thorbijoern]
Als quelle? Da würde ich mir nicht so viele Gedanken machen. Da gibt es so ungefähr 100. Einfach mal durchprobieren

Brauchst halt irgendwas was RTMP senden kann

Ich denke da kommt es auf persönliche Präferenz an.

Ich weiß dass es auf F-Droid ein paar RTMP Camera Apps gibt

Oh und beachten solltest du dass RTMP nicht so gut auf hohe Latenz und Netzwerkprobleme reagiert

Eventuell willst du ne App die HLS kann

Das eliminiert auch noch den letzten Faktor eines proprietären Protokolls. RTMP ist nämlich technisch gesehen proprietär

Wie wärs mit VLC auf Android?

Ist jetzt grad ne Idee. VLC auf Desktop OS kann HLS und RTMP Streamen von lokalen Quellen

Thorbijoern
ich glaube die app kann das nicht
usb infos:
Actions Semiconductor Co., Ltd
D-Wave 2GB MP4 Player / AK1025 MP3/MP4 Player
wird als 120mb angezeigt

* https://celly.space/2016/02/25/hacking-the-card-tv/
* https://www.youtube.com/watch?v=LToGY45okTo
* https://unframework.com/2020/05/09/disassembling-a-video-greeting-card/
* https://www.igorkromin.net/index.php/2017/08/24/teardown-of-a-videopak-7inch-hd-display-promotional-video-brochure/
* https://web.archive.org/web/20210411083325/https://www.instructables.com/community/Help-with-Video-Brochure-IC/
* https://web.archive.org/web/20210420050725/https://www.instructables.com/community/SerialConsole-Interface-for-Video-Brochure/

chips:

* v100 fn40emp 34c - ?
* att2089 - ?
* [[H5DU5162ETR-E3C - 512mb sdram|https://www.alldatasheet.com/datasheet-pdf/pdf/333498/HYNIX/H5DU5162ETR-E3C.html]]
* [[TC58NVG0S3ETA00 - 1GB Nand Eprom|https://www.alldatasheet.com/datasheet-pdf/pdf/507515/TOSHIBA/TC58NVG0S3ETA00.html]]

stuff:

* https://www.eetimes.com/esolo-mp4-apple-nano-clone-adds-some-extras/
* https://thevideocards.com/how-are-video-brochures-made/
* https://www.stormmedia.co.za/video-brochures
* https://www.actions-semi.com/index.php?id=3577&siteId=4
* https://www.alibaba.com/product-detail/4-3-inch-video-brochure-module_60160463299.html

gibt scheinbar auch welche die loopen, vlt. kann man das iwie konfigurieren
fehlenden buttons sind unter anderem fürs wechseln zwischen unterschiedlichen dateien
* https://hackaday.com/2022/05/23/vintage-pro-audio-hack-chat/
* [[Vintage Concert Audio: Historische Professionelle Lautsprecher von den 60er bis 90er Jahren|https://www.youtube.com/watch?v=zTvFLaVv9Jo]]
maybe ~PulseAudio with an appropriate frontend/GUI for easy configuration?

* https://wiki.archlinux.org/index.php/PulseAudio#Front-ends
* https://wiki.ubuntuusers.de/PulseAudio/#Hilfsprogramme

JACK seems it's setup-heavy and needs to be supported by the application, but there are tools

* lhttps://wiki.linuxaudio.org/wiki/start
* https://kx.studio/
* https://wiki.archlinux.org/index.php/Professional_audio#Tips_and_tricks
* https://jackaudio.org/applications/
* https://alsa-project.org/wiki/Applications
* http://pkl.net/~node/software/alsa-patch-bay/
* http://drobilla.net/software/patchage
* 


only for windows:

* Synchronous Audio Router - http://sar.audio/
* https://www.reddit.com/r/software/comments/3dup5u/request_freeopen_source_virtual_sound_card_for/
* small/compact aktive speaker (monitor) with coax driver and a bit of mixing
* Image: https://www.gearbooker.com/images/listing/00002897.jpg

Problems:

* distortion in the amplifier or mixing/input section

Repair:

i basically just opened it up to visually check for obvious problems, when i found nothing i assembled it back again.
after a while i wanted to come back to it and check it more in depth, but when i first just make a normal sound test again it worked without problems.
I probably fixed it by accident because it was just a bad connection and removing cables and plugging them back in fixed stuff.
* similar tactics to the hong kong protests or guerilla groups?
** decentralize
** secure communication without internet, use mesh networks and similar
* https://archive.org/details/TotalResistanceSwissArmyGuideToGuerrillaWarfareAndUnderground
* https://media.ccc.de/v/36c3-10933-what_the_world_can_learn_from_hongkong
* https://twitter.com/SpencerGuard/status/1497583307504046087
* https://mwi.usma.edu/defending-the-city-an-overview-of-defensive-tactics-from-the-modern-history-of-urban-warfare/
* https://news.ycombinator.com/item?id=30471631
* https://www.reddit.com/r/interestingasfuck/comments/t1u29s/how_to_deal_with_russian_tanks_for_ukrainians/
** https://twitter.com/Hogan698/status/1497291283106250761
** https://twitter.com/Hogan698/status/1497372625487736832
* use molotov cocktails
** "In the fire service we use a mix of diesel and gas 3:2 to make a linger burning fuel for ignition. Kerosene should work too." - https://twitter.com/jbeal82/status/1497360013685235714
** use burnable thickening agents
*** crushed styrofoam makes a stiky goo with gasoline
*** soap flakes, crushed up soap, powdered soap
*** gasoline allone will burn off too quickly, spread too much and evaporate
*** https://twitter.com/Hogan698/status/1497374782203039749
** https://twitter.com/Hogan698/status/1497374782203039749
* make anti-tank barrikades out of old steel, railroad tracks, concrete
* twitter
** https://twitter.com/_Imaqib_/status/1497481087194255366
** https://twitter.com/strategy0071/status/1497596505049362433
** https://twitter.com/Alerez14/status/1497452606884655107
** https://twitter.com/ZeroPark30/status/1497445963111280647
** https://twitter.com/zeikarus/status/1497279793154297856
** https://twitter.com/CogNitocat/status/1497647915526856710
** https://twitter.com/kisan_putri/status/1497613512503623680
** https://twitter.com/PopularFront_/status/1497549909121196032
* https://twitter.com/SpencerGuard/status/1497583325816385537
* [[ A W-shaped wave guide |https://www.youtube.com/watch?v=yavj84JWjOA]]
* [[Web media technologies|https://developer.mozilla.org/en-US/docs/Web/Media]]
* [[Media type and format guide: image, audio, and video content|https://developer.mozilla.org/en-US/docs/Web/Media/Formats]]

Audio

* https://www.w3.org/TR/webaudio/
* https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API
* https://www.redblobgames.com/x/1618-webaudio/
* https://webaudio.github.io/demo-list/
* https://webaudiodemos.appspot.com/
** https://webaudiodemos.appspot.com/MIDIDrums/index.html
* https://webaudioapi.com/
** https://webaudioapi.com/samples/
* https://www.html5rocks.com/en/tutorials/webaudio/intro/
* https://dzone.com/articles/exploring-html5-web-audio
* https://noisehack.com/
* https://teropa.info/blog/2016/08/10/frequency-and-pitch.html
* https://github.com/mdn/webaudio-examples
* https://github.com/mdn?q=audio
* https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Best_practices
* https://webaudioplayground.appspot.com/
** https://github.com/cwilso/WebAudio
* https://dobrian.github.io/cmp/topics/intro-to-web-audio-api/0.introduction-to-web-audio-api.html

* uses
** https://github.com/vitling/acid-banger
** [[frequency response webapp]]
** https://errozero.co.uk/acid-machine/
** https://github.com/hvianna/audioMotion.js
** https://audiomass.co/ - https://github.com/pkalogiros/AudioMass
** https://wavesurfer-js.org/projects/
** https://github.com/sebpiq/WebPd - PureData in the browser
** https://charlie-roberts.com/gibber/ - https://github.com/charlieroberts/gibber.audio.lib
** https://dsp.audio/editor/
** https://xsound.app/
** https://github.com/naomiaro/waveform-playlist
** https://plink.in/
*** http://labs.dinahmoe.com/plink/

* libraries/frameworks
** https://tonejs.github.io/
** https://github.com/bit101/tones
** https://xsound.dev/
** https://github.com/Theodeus/tuna
** https://wavesurfer-js.org/ -  https://github.com/katspaugh/wavesurfer.js
** https://nexus-js.github.io/ui/ - https://github.com/nexus-js/ui
** https://p5js.org/reference/#/libraries/p5.sound
** https://github.com/goldfire/howler.js
** https://github.com/Theodeus/tuna
** https://github.com/audiojs/audio
** https://github.com/katspaugh/wavesurfer.js
** https://meyda.js.org/
** https://github.com/benji6/virtual-audio-graph

* tools
** https://firefox-source-docs.mozilla.org/devtools-user/deprecated_tools/index.html#id6


MIDI

* see [[Midi]]
* https://www.midi.org/midi-articles/about-web-midi
* https://webaudio.github.io/web-midi-api/
* https://webmidi.info/
* https://arachsys.github.io/webmidi/
* https://webmidi-examples.glitch.me/
* https://developer.mozilla.org/en-US/search?q=web+midi

other

* https://w3c.github.io/mediacapture-main/getusermedia.html
* lists with great stuff:
** https://github.com/notthetup/awesome-webaudio
** https://github.com/amilajack/awesome-web-audio
** https://github.com/jonahvsweb/awesome-web-audio-resources
** https://github.com/Catsvilles/awesome-web-audio-api-projects
!1. recording

record audio from a selected input

* https://developer.mozilla.org/en-US/docs/Web/API/MediaStream_Recording_API/Using_the_MediaStream_Recording_API
* https://github.com/streamproc/MediaStreamRecorder
* https://www.webrtc-experiment.com/msr/audio-recorder.html
* http://w3c.github.io/mediacapture-record/MediaRecorder.html
* https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder
* https://stackoverflow.com/questions/21234902/record-sound-of-a-webaudio-apis-audio-context
* https://www.sitepoint.com/mediastream-api-record-audio/
* https://webaudioapi.com/samples/microphone/
* https://dobrian.github.io/cmp/topics/sample-recording-and-playback-with-web-audio-api/0.sample-recording-and-playback.html
* https://webaudiodemos.appspot.com/AudioRecorder/index.html

libs (not maintained, old, don't want to use them)

* https://github.com/higuma/web-audio-recorder-js
* https://github.com/mattdiamond/Recorderjs

related [[web audio api|https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API]] objects:

* https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode
* https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer
* https://developer.mozilla.org/en-US/docs/Web/API/MediaElementAudioSourceNode
* https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamAudioSourceNode

!2. noise / sweep

white (and pink?) noise and frequency sweep to audio output

!3. fft / analysing / display

* https://webaudioapi.com/samples/visualizer/
* https://webaudiodemos.appspot.com/oscilloscope/index.html

!5. controlls

* https://webaudioapi.com/samples/metering/
* https://webaudiodemos.appspot.com/volume-meter/index.html
* btw. i hate web design
* i want web design that sucks less, i hat websites using tons of cookies for tracking and other shit and a ton of scripts, libraries and stuff for styling and some nice buttons
* https://opensource.com/article/21/3/open-source-tools-web-design

# https://motherfuckingwebsite.com/
# http://bettermotherfuckingwebsite.com/
# https://perfectmotherfuckingwebsite.com/

i like minimal web design

* https://lonami.dev/
* https://solar.lowtechmagazine.com/
** https://solar.lowtechmagazine.com/2018/09/how-to-build-a-lowtech-website.html
** https://solar.lowtechmagazine.com/2020/01/how-sustainable-is-a-solar-powered-website.html
* https://homebrewserver.club/low-tech-website-howto.html
* https://weitblick.org/ - some questionable stuff but also a lot of good informations

ressources:

* https://github.com/you-dont-need/You-Dont-Need-JavaScript
* https://smartquotesforsmartpeople.com/
* https://wowjs.uk/
* https://animate.style/
* https://amicaldo.de/ fancy colorful interactivewater/smoke/turbulence animation stuff
** https://amicaldo.de/js/main-colors.js
* i dont care about supporting older browsers for people who are to subborn to change to modern ones
** https://css-tricks.com/how-to-create-an-ie-only-stylesheet/ - also useful to inform users that their browser is not supported
* sites should work even without js
* fonts
** https://www.w3schools.com/cssref/css_websafe_fonts.asp
** https://web.mit.edu/jmorzins/www/fonts.html
** `font-family: Arial, Helvetica, sans-serif;`
* https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout
** https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Grids
* https://caniuse.com/
* https://css-tricks.com/
** https://css-tricks.com/how-to-stack-elements-in-css/
* see also [[semantic web]]
* https://scrapy.org/
* Beautifulsoup
* https://owasp.org/www-project-web-security-testing-guide/
* https://www.zaproxy.org/getting-started/
* https://www.zaproxy.org/
* https://openvas.org/
* https://portswigger.net/burp/communitydownload
* https://www.keycloak.org/
Politiker diverser wirtschaftsliberaler Parteien fordern, aus angst von der industrie nicht mehr gemocht zu werden, nur das sich die menschen im privaten, zuhause einschränken sollen. Aber es ist im grunde konsens in und zwischen den klima- und umweltbewegungen, dass das bei weitem nicht reicht.
Die Wirtschaft trägt wesentlich mehr zu Umweltverschmutzung und Klimagaserzeugung bei als alle privathaushalte zusammen gezählt.

der staat muss einerseits die dreckigsten vertreter anktionieren, die umweltfreundlichsten z.b. mit steuersenkungen belohnen und beim umweltfreundlichen umbau z.b. mit förderungen oder auf anderen wegen unterstützen.

In einigen Punkten gibt es schon gute ansätze, die z.B. in skandinavischen ländern oft schon viel weiter sind.

Stromprodukion muss komplett auf erneuerbare energien umgestellt werden. Damit wird schon einiges klimaneutraler.
Die umstellung ist möglich, wie es viele Wissenschaftler, darunter Volker Quaschning, vorrechnen. Deutschland hat sein geringes potential an wasserkraft im grunde schon komplett ausgeschöpft, aber mit photovoltaik(solar) und windkraft läst sich noch viel machen. Städte haben ein riesiges potental an ungenutzter dachfläche, die mit photovoltaik bedeckt schon einen guten teil des strombedarfs einer stadt decken würde.
Stromspeicher verschiedenster art/technologie und größe (Akkus, Power to gas, etc.) machen phasen hoher stromproduktion gut ausnutzbar, können bedarfsspitzen problemlos ausgleichen und auch längere perioden in denen weniger strom produziert wird überbrücken.

aber es gibt auch bestimmte industrien die riesige mengen Klimagase zu verantworten haben:

Die stahl- und betonproduktion sind zusammen mit dem bausektor eine riesige dreckschleuder. Die produktion von stahl und beton verbraucht unmengen an energie und setzt unmengen an CO2 frei. diese rohstoffe werden u.a. als stahlbeton in der bauindustrie verwendet. Klar brauchen wir gebäude und wohnungen, aber da braucht es ein umdenken in der art wie wir gebäude entwerfen und bauen. Es gibt z.B. schon mindestens ein hochhaus das aus holz statt aus stahlbeton gebaut ist. Die Architects for Future wären da ein guter ansprechspartner.
Ein großer faktor bei Häusern sind die heizungen. Heizungen die auf fossilen stoffen wie Heizöl, Gas oder auf Holz angewiesen sind müssen ersetzt werden.
In deutschland gibt es kaum potential für erdwärme, aber z.B. Luft-Wärmepumpenheizungen wären gute option.

Eine weitere dreckige Industrie ist die Autoindustrie. die autos müssen klimaneutral werden, aber leider wird es da auch auf die privaten haushalte zurück laufen, denn der individualverkehr wie er jetzt existiert muss wesentlich geringer werden. Wir brauchen einen ausbau von bus und bahn, auch in ländlichen regionen.

ansonsten ist es in der wirtschaft gängige praxis das viele noch gute, funktionierende güter, z.B. maschienen oder material, weggeschmissen wird, weil umgerüstet wird, fehlbestellt wurde oder einfach um temporär platz im lager zu schaffen. es gibt projekte wie die materialvermittlung in dresden, die material annehmen und an leute weiter verteilen die es brauchen, aber in den firmen will sich da oft niemand drum kümmern weil es zusätzliche arbeit ist. außerdem gibt es auch teilweise garkeine andere möglichkeit als entsorgen, da anderes durch gesetze oder behördliche vorgaben (z.b. finanzamt) sinnlos verboten wird. die politik müsste anreize schaffen, das weniger weggeschmissen wird, bzw. müsste müllproduktion teilweise sanktionieren. 
es muss mehr recycled werden, aber bevor das geschiet können viele sachen auch einfach reused werden

* https://sound-au.com/manufacture.htm
* https://sound-au.com/articles/sustainability.htm
* https://coma-emerald.de/KlimawendeVonUnten.pdf
* https://media.ccc.de/v/r3c-oio-251-the-challenges-of-decarbonizing-everything
<<list-links "[all[current]tagging[]]">>

mig/mag
neomag 2000
MB14/MB15 Brenner


```
12mm düse
0,8mm draht/muffe
6mm fewinde drahtmuffe
abicore binzel 12mm mag düse
```

schleifböcke

```
creusen
ds 6150 ts
230W
2860u/min
scheiben: 150x20x15
schraub-basis 9x9cm

interkrenn
v150/4
400W
2800u/min
scheiben 150x32x15
basis 11,5-12 x 10,5-11cm

westfalia
250w
2800u/m
scheiben 125x16mm
basis 12x11mm

interkrenn
ds125/3
230w
scheiben 125mm
2900u/m
basis 12x11cm

ddr eigenbau
400w 2a
1410u/min

bosch
psm150
300w
2990u/min
scheibe 150x20x20?
basis 8,5x13,5?

+ nassschleifbock (muss repariert werden)
```

wäre nice:

* Planscheiben
** https://en.wikipedia.org/wiki/Lathe_faceplate
** https://de.wikipedia.org/wiki/Planscheibe
* Drehtisch
** https://de.wikipedia.org/wiki/Drehtisch
* Teilapparat - dividing head
** https://de.wikipedia.org/wiki/Teilapparat
* Drehbank Vierbackenfutter mit einzeln beweglichen Backen
* [[(wire) EDM CNC]]
* induction metal furnace
* kühlmittelschlauch nebel
** https://www.youtube.com/results?search_query=chinese+mist+cooling+test
* messuhr
* fühlhebel messuhr

TODO:

* haltefeder mb14
* ~~schalter~~
* ~~rohrendstopfen für lastenrad~~
* ~~dekupiersägeblätter~~



stuff

* https://www.youtube.com/watch?v=hZbnLDvDbFogerade
** sauerstoffkonzentrator
is shit, use XMPP or Matrix instead

if you need to read the DB files:

* https://andreas-mausch.de/whatsapp-viewer/ - https://github.com/andreas-mausch/whatsapp-viewer
* Wikipedia
* [[wiki.sonnenstaatland.com/wiki/Hauptseite|https://wiki.sonnenstaatland.com/wiki/Hauptseite]] - Infos über Rechsbürger und Ähnliche
* https://www.psiram.com/de/index.php/Hauptseite
** https://rationalwiki.org/wiki/Main_Page
* [[nsu-watch.info|https://www.nsu-watch.info/]]
* [[Blick nach Rechts|https://www.bnr.de/]]
* https://blog.zeit.de/stoerungsmelder/
* https://de.wikipedia.org/wiki/Kategorie:Initiative_gegen_Rechtsextremismus
* [[bildblog.de|https://bildblog.de/]]
* [[uebermedien.de|https://uebermedien.de/]]
* [[correctiv.org|https://correctiv.org/]]
* [[mimikama.at|https://www.mimikama.at/]]
* [[ourworldindata.org|https://ourworldindata.org/]]
* [[volksverpetzer.de|https://www.volksverpetzer.de/]]
* [[Youtube: Kurzgesagt (En)|https://www.youtube.com/user/Kurzgesagt]]
* [[Youtube: Kurzgesagt (De)|https://www.youtube.com/user/KurzgesagtDE]]
* [[Youtube: maiLab|https://www.youtube.com/channel/UCyHDQ5C6z1NDmJ4g6SerW8g]]
* [[Youtube: Doktor Whatson|https://www.youtube.com/channel/UCesjlAoEgN_Sz_cKTvKEmmw]]
* [[Youtube: Ultralativ|https://www.youtube.com/channel/UCb-cM927p9tWkqmpOrBabOQ]]
* [[Youtube: Simplicissimus|https://www.youtube.com/channel/UCKGMHVipEvuZudhHD05FOYA]]
* [[Youtube: MrWissen2go|https://www.youtube.com/user/MrWissen2go]]
* [[NDR zapp|https://www.ndr.de/fernsehen/sendungen/zapp/index.html]]
* [[abgeordnetenwatch.de|https://www.abgeordnetenwatch.de/]]
* [[Chaos Computer Club|https://www.ccc.de]]
** https://ds.ccc.de/
* [[lobbycontrol.de|https://www.lobbycontrol.de/]]
* [[netzpolitik.org|https://netzpolitik.org/]]
* [[Landeszentralen für politische Bildung|https://www.politische-bildung.de/]]
* [[Bundeszentrale für politische Bildung|https://www.bpb.de/]]
* https://archive.org/
* https://media.ccc.de/search?p=Arne+Vogelgesang
* https://noyb.eu/en
** https://en.wikipedia.org/wiki/NOYB
* https://www.transparency.de/
* https://dickstinction.com/
https://en.wiktionary.org/wiki/jellybean_part

other lists

* https://www.eevblog.com/forum/chat/jellybean-list/
* https://theknowledgeaccelerator.com/2016/04/16/jellybean-components/
* https://forum.allaboutcircuits.com/threads/components-selection-guide.65137/
* https://www.eevblog.com/forum/beginners/common-generic-cheap-easy-to-find-parts/
* https://www.eevblog.com/forum/beginners/what-parts-to-get-at-the-store/
* https://www.eevblog.com/forum/chat/dave_s-_jellybean_/
* https://www.mikrocontroller.net/articles/Standardbauelemente
* https://sparks.gogo.co.nz/assets/_site_/downloads/smd-discrete-jellybeans.pdf

transistors BJT

* https://en.wikipedia.org/wiki/2N3906
* https://en.wikipedia.org/wiki/2N3904
* https://en.wikipedia.org/wiki/BC548
* https://en.wikipedia.org/wiki/2N2907
* https://en.wikipedia.org/wiki/2N2222
* https://en.wikipedia.org/wiki/BC108_family
* PN2907
* https://www.eevblog.com/forum/projects/jelly-bean-logic-level-fast-switching-transistor-bjtfet/

mosfets

* https://components101.com/articles/popular-mosfets-frequently-used-in-power-electronics-designs
* https://www.mikrocontroller.net/articles/MOSFET-%C3%9Cbersicht
* https://www.eevblog.com/forum/reviews/jelly-bean-mosfet/
* https://www.reddit.com/r/AskElectronics/comments/r29e5n/jelly_bean_mosfet/
* https://www.eevblog.com/forum/projects/jelly-bean-logic-level-fast-switching-transistor-bjtfet/

Diodes

* https://en.wikipedia.org/wiki/Category:Diodes
* https://en.wikipedia.org/wiki/1N400x_general-purpose_diode
* https://en.wikipedia.org/wiki/1N58xx_Schottky_diodes

* 1n4004
* 1n4007
* 1N4148
** https://en.wikipedia.org/wiki/1N4148_signal_diode

Chips general

* [[Probably the most used component nobody knows of! TL431 Guide! EB#50|https://www.youtube.com/watch?v=isutYMU2HHU]]
** [[This IC is Multifunctional - TL431 Circuits|https://www.youtube.com/watch?v=NecbHbGAkkc]]
* 555 Timer IC
* [[EEVblog 1438 - The TOP 5 Jellybean Regulators & References|https://www.youtube.com/watch?v=YHRxvUqy3Uw]]
* [[EEVblog 1464 - TOP 5 Jellybean Comparators|https://www.youtube.com/watch?v=c5M8P6oe9xY]]

Opamps

* https://components101.com/article/major-difference-between-lm358-op-amp-and-lm393-comparator
* https://en.wikipedia.org/wiki/NE5532 - one of the best audio opamps
* (RC/JRC)4558 - maybe a pretty sheap and not so good opamp
* [[EEVBlog 1436 - The TOP 5 Jellybean OPAMP's|https://www.youtube.com/watch?v=uq1DMWtjL2U]]

smps chips

* 7660 - switched capacitor voltage converter
** https://www.ti.com/product/LMC7660
** https://www.maximintegrated.com/en/products/power/charge-pumps/ICL7660.html
** https://octopart.com/search?q=7660&currency=EUR&specs=0&category_id=4215&numberofpins=8&case_package=SOIC&case_package=VSSOP&case_package=SOIC+N&start=20
** https://www.microchip.com/en-us/product/TC7660
** https://www.ti.com/product/TL7660
* https://firms.modaps.eosdis.nasa.gov/
* https://www.youtube.com/watch?v=7q1znQQoZdQ
* https://at-fire.de
* https://windempowerment.org/
** https://windempowerment.org/erni-kollektiv/
* [[Mini Wind Turbine - DIY or Buy|https://www.youtube.com/watch?v=938dTRrwrYc]]
* libre.solar might do something in this direction
* https://deltaempower.org/
* https://kappa.deltaempower.org/deltaempower/windkit
* https://www.researchgate.net/publication/319606042_The_suitability_of_the_IEC_61400-2_wind_model_for_small_wind_turbines_operating_in_the_built_environment
* https://www.treehugger.com/build-diy-wind-turbine-4858226
* https://github.com/IEAWindTask37/IEA-15-240-RWT
** https://github.com/blueOceanSustainableSolutions/15MW-turbine-open-source
* https://wiki.opensourceecology.de/Wind_Turbine/en - vertical wind turbines are pretty inefficient or have other big flaws
i don't like windows and i don't recommend using it.

some tools:

* https://chocolatey.org/
* https://ninite.com/
proprietary freeware; http://www.linearteam.org/

* ~WinISD - Einführung und Chassis-Datenbank: http://www.hifi-forum.de/viewthread-239-6.html
* ~WinlSD Pro Alpha "Lexikon": http://www.hifi-forum.de/viewthread-104-19619.html
* http://www.hifi-forum.de/viewthread-70-4502.html
* https://www.hifi-selbstbau.de/grundlagen-mainmenu-35/softwaremesstechnik-mainmenu-66/213-winisd-beta
* http://www.dwusel.de/hifi/Anleitung%20WinISD.pdf

* https://vgnotepad.blogspot.com/2021/04/reprogramming-old-sennheiser-skm-3072-u.html?m=1
* https://news.ycombinator.com/from?site=vgnotepad.blogspot.com
* https://www.rtl-sdr.com/rtlmic-wireless-microphone-receiver-for-rtl-sdr/
* https://www.sharebrained.com/2013/06/15/wireless-microphones-and-hackrf/
* https://www.youtube.com/watch?v=kEFCy1e-7Bs
* https://www.reddit.com/r/hacking/comments/2hncq1/hack_microphone_frequency/
* https://gearspace.com/board/live-sound/1242872-reprogramming-wireless-mics.html
* https://hackaday.com/2021/08/01/hacking-a-pic-to-redefine-a-microphones-transmit-frequency/

stuff

* https://ieeexplore.ieee.org/document/10289700
verschiedene Wirtschaftssysteme

* [[Kapitalismus]] - scheiße
* kommunismus/sozialismus - semi gut/semi scheiße(?)
* https://de.wikipedia.org/wiki/Solidarische_%C3%96konomie
* [[Gemeinwohlökonomie]]
* https://pedalkreis.org/low-tech/gute-arbeit/?
* https://opensourceecology.de/
** https://wiki.opensourceecology.de/Open_Source_Ecology_Germany/Open_Source_Economy
** https://en.wikipedia.org/wiki/Open-source_economics
** https://de.wikipedia.org/wiki/Open_Source_Ecology
** https://en.wikipedia.org/wiki/Open_Source_Ecology
* Purpose-Bewegung - Firmen gehören einer Stiftung (alle Mitarbeiter sind mitglieder) die einen Sinn verfolgt
** [[Mehr Sinn statt Gier -- Kapitalismus neu Gedacht ~ Arte RE:|https://www.youtube.com/watch?v=DCmsvPR6PuE]]
* https://en.wikipedia.org/wiki/Business_models_for_open-source_software
nehme auch kaputtes an...

* USB oscilloscop / Analog Discovery 2
* differenzieller hochspannungstastkopf
* LCR meter mit ESR funktion
* akkus und akkupacks; z.B. von Laptops, E-Bikes, auch große von elektroautos
* fahrradtaschen
* Audio-Equipment
** PA Lautsprecher
** Verstärker (primär Class D mit Schaltnetzteil)
** Kabel/Stecker/Buchsen/ Adapter und co
** allgemein Veranstaltungstechnik/PA kram
** Car-Hifi verstärker
** Mikrofone
** Mischpulte
** DSPs/Lautsprechermanagementsysteme
* guter Messschieber
* Wechselrichter
* alten LPT Drucker oder vlt. einen Drucker mit HP C6602 Patronen, oder auch nur die patronen
* Hochlastwiderstände, am besten 2, 4, 6, 8, 16 Ohm oder andere multible
* Solarpanele
* MPPT solarladeregler
* BF-888(S)
* [[audio/sound level calibrator]]
* audio analyzer
* https://www.thomann.de/de/superlux_pink_stick.htm
* https://www.lidl.de/p/parkside-messinstrumente/p100345800
* werkzeug
* True RMS Multimeter
* LED Par scheinwerfer
* Multiplex
* Bügelmessschraube? https://www.lidl.de/p/parkside-messinstrumente/p100345800003
* schuko-kaltgeräte und XLR Multicore/hybrid kabel
* USB Mikroskop


brauche ich speziell für projekte:

* Tascam US-428 7,5VAC 1A Netzteil
bei vielen menschen herrscht kein verständnis von wissenschaft und wie diese funktioniert und es herrscht großes misstrauen in die wissenschaft.... hier sind informationen um vlt. zu helfen... (sehr unvollständig)

* https://de.wikipedia.org/wiki/Peer-Review
* https://www.youtube.com/channel/UCyHDQ5C6z1NDmJ4g6SerW8g/videos - MaiLab, viele Themen wissenschaftlich gut erklärt
* https://de.wikipedia.org/wiki/Kategorie:Wissenschaftliche_Methode
* https://rc3.cert.ccc.de/mt/
* https://mutterallerprobleme.de
wled

* https://wled.discourse.group/t/multiple-gpio/244
* https://wled.discourse.group/t/esp32dev-with-p9813-led-driver-and-analog-strips/4757
* https://www.reddit.com/r/WLED/
* https://www.reddit.com/r/WLED/comments/z0oi5y/new_led_controller_design/
* https://pdf1.alldatasheet.com/datasheet-pdf/view/1221780/ETC1/P9813.html
* https://kno.wled.ge/basics/install-binary/
* https://kno.wled.ge/basics/getting-started/#wifi-setup
* https://kno.wled.ge/basics/tutorials/
* https://kno.wled.ge/basics/faq/#led-issues_1
* https://github.com/Aircoookie/WLED/wiki/Learning-the-ropes
* https://kno.wled.ge/interfaces/serial/
* https://kno.wled.ge/
* https://mm.kno.wled.ge/
** https://github.com/atuline/WLED/wiki
** https://mm.kno.wled.ge/moonmodules/what-is-moonmodules/
** https://kno.wled.ge/advanced/custom-features/


fastled

* https://www.reddit.com/r/FastLED/comments/p4pbp1/built_some_performance_stage_lights_running/
* checking the data & ground connection
* selecting the right resistor/testing different resistors
* checking signal level and integrity/shape
* levelshifter as "booster"
** https://quinled.info/quinled-data-booster/
** level shifter modules from alibaba might work
** 74HCTxx logic chips might work
* https://www.ulrichradig.de/home/index.php/dmx/ws2812-range-extender
<<list-links "[all[current]tagging[]]">>


platten

* [[Plywood|https://en.wikipedia.org/wiki/Plywood]] - [[Sperrholz|https://de.wikipedia.org/wiki/Sperrholz]]
** [[Multiplex|https://de.wikipedia.org/wiki/Multiplex-Platte]]
*** [[ Alles was Du zu Multiplex wissen solltest. Lerne aus meinen Fehlern! |https://www.youtube.com/watch?v=zsVaZqHjFqc]]
** https://en.wikipedia.org/wiki/Category:Plywood
* [[Grobspanplatte / OSB-Platte|https://de.wikipedia.org/wiki/Grobspanplatte]]
* [[Fiberboard|https://en.wikipedia.org/wiki/Fiberboard]] - [[Faserplatten|https://de.wikipedia.org/wiki/Faserplatte]]
** vor allem
*** MDF - [[medium density fiberboard|https://en.wikipedia.org/wiki/Medium-density_fibreboard]] - [[mitteldichte Holzfaserplatte|https://de.wikipedia.org/wiki/Mitteldichte_Holzfaserplatte]]
*** HDF - [[high density fiberboard/hardboard|https://en.wikipedia.org/wiki/Hardboard]] - [[hochdichte Faserplatte|https://de.wikipedia.org/wiki/Hochdichte_Faserplatte]]
*** [[Particle board|https://en.wikipedia.org/wiki/Particle_board]] - [[Spanplatte|https://de.wikipedia.org/wiki/Spanplatte]]
**** garbage/ schmutz imho
* Tischlerplatte
** https://de.wikipedia.org/wiki/Tischlerplatte
* [[ Plattenwerkstoffe und ihre Eigenschaften . mit Animation |https://www.youtube.com/watch?v=JYsxy-plDYQ]]


balken / bretter

* https://de.wikipedia.org/wiki/Kantholz
* https://de.wikipedia.org/wiki/Bauholz#Konstruktionsvollholz


kaufen / buying / sourcing

* https://www.holz-rentsch.de/unser-sortiment/
** https://www.ihr-holzshop.de/
* baumärkte sind nicht soo gut meist
* [[ So kauft man Holz beim Händler - Beratung, Infos und Tipps inklusive Händlerliste für Privatkäufer|https://www.youtube.com/watch?v=rhVZUnhOZgQ]]
* [[ Realtalk - Wo und wie sollte man sein Holz richtig kaufen? Viele machen es intuitiv falsch! |https://www.youtube.com/watch?v=CwToRyqKKPY]]

holzbau

* https://selbermachen.de/tools-tipps/material/balkenverbindungen-die-wichtigsten-modelle-mit-skizzen
* https://de.wikihow.com/Holzbalken-miteinander-verbinden
* https://baubeaver.de/holzbalken-verbinden/
* https://de.wikipedia.org/wiki/Kategorie:Holzbau
* https://de.wikipedia.org/wiki/Bauholz
* https://de.wikipedia.org/wiki/Holzbau

stuff

* https://en.wikipedia.org/wiki/Category:Engineered_wood
* https://wiki.opensourceecology.de/Werkmaterial_Holz
* https://de.wikipedia.org/wiki/Kategorie:Holzbau
* https://de.wikipedia.org/wiki/Kategorie:Werkholz
* https://de.wikipedia.org/wiki/Kategorie:Holz-Halbzeug
* https://de.wikipedia.org/wiki/Schnittholz
* https://de.wikipedia.org/wiki/Schnittholzsortierung
* https://www.youtube.com/watch?v=2p7tEH2uJS8&list=PLTi98hQI3Z-WTAgLdU7juPZFcyfiWPQNx
* https://de.wikipedia.org/wiki/Kategorie:Holzbearbeitung
* https://de.wikipedia.org/wiki/Holzschutz
* https://de.wikipedia.org/wiki/Holzverbindung#Sto%C3%9Fverbindungen
* https://tatendrang-netzwerk.eu/projekte/nawaro-fahrrad/
* https://green-bamboo-bike.de/
** https://tatendrang-netzwerk.eu/projekte/green-bamboo-bike/
** [[Lignin]]
** they used 3d printing filament with lignin, the company they used it from is out of business but there are other filaments with lignin. but they all seem to be blends of other plastics with lignin so the sustainability and wether it is degredaable is questionable
* https://www.youtube.com/c/Matthiaswandel
** http://woodgears.ca/
*** https://www.woodgears.ca/techniques.html
* https://de.wikipedia.org/wiki/Keilzinkung
* https://de.wikipedia.org/wiki/Bullshit_Jobs
* [[Gridfinity: Your Ultimate Modular Workshop is FREE!|https://www.youtube.com/watch?v=ra_9zU-mnl8]]
* [[3D Print a Modular Toolbox, Soldering Station, and More!|https://www.youtube.com/watch?v=Bd4NnHvTRAY]]
* https://www.youtube.com/results?search_query=adam+savage+organization
i can get some very small PAR-Type (PAR16 i think) lamps from someone. these are designed to accept 12V halogen bulbs that just clip in.
we suspect they were originally used in series to run them with 230V.

I want to convert them to RGB LEDs.

using a ws2811 would be an easy and cheap way to control the LEDs. ordinary Ws2812 LEDs don't have a lot of power and you can only fit so much 5050 smd chips inside these mini PAR cans.
So I want to try and use 3W or higher power LED chips.

if everything fails i can resort to smart MR16 LED bulbs

maybe not only rgb (ws2811) but also rgbw or so (sk6812)?

there are a few commercial modules available, but buying them is not easy because they are out of stock or the sellers don't ship to germany (or shipping would be expensive).

* aliexpress - not shipping to europe
** https://aliexpress.com/item/32798198341.html
** https://imall.com/product/3W-high-power-led-UCS1903-WS2811-controlled-RGB-spotlight-DC5V-input-addressable-IP40-5-degree-beam-angle/Lights-Lighting-Outdoor-Floodlights/aliexpress.com/33035867933/567-20220884/en
** https://de.aliexpress.com/item/10000279651349.html
** https://de.aliexpress.com/item/32773133114.html
* https://www.led-genial.de/navi.php?suchausdruck=power+dot
* https://www.ulrichradig.de/home/index.php/dmx/3watt-power-dot
* https://www.zedfy.shop/high-power-rgb-led-1-led-3-watt-typ-ws2811-ic-adressierbar
* https://www.nledshop.com/ws2811fet/
** https://www.ebay.com/itm/143566018541
** https://www.nledshop.com/downloads/datasheets/nled-ws2811fet-datasheet.pdf
* overly expensive and not compact enough
** https://www.ledlightinghut.com/3w-chainable-digital-ws2811-rgb-pixel-dot.html
** https://www.ledlightinghut.com/9w-rgb-high-power-digital-ws2811-pixel-dot.html
** https://www.ledlightinghut.com/12w-rgbw-chainable-digital-pixel-dot.html
** https://www.ledlightinghut.com/30w-digital-ws2811-pixel-dot.html
** https://www.ledlightinghut.com/ws2811-digital-led-circuit-board-with-6-leds.html
** https://www.ledlightinghut.com/ws2811-digital-led-pixel-module-with-12-leds.html
** https://www.ledlightinghut.com/65mm-12-led-dmx-rgbw-plate-pcb.html
* https://www.adafruit.com/product/4544
** https://www.ipixelleds.com/index.php?id=611
** https://www.ipixelleds.com/index.php?id=975
* https://www.tindie.com/stores/RobG/
** https://www.tindie.com/products/robg/pixelflood-10w-rgb-flood-light-kit-ws2811-pixel/
*** https://www.diychristmas.org/wiki/index.php?title=10W_RGB_LED_Driver_Board_Assembly_(WS2811_version)
** https://www.tindie.com/products/robg/pixelflood-20w-rgb-flood-light-ws2811-pixel/
*** https://www.diychristmas.org/wiki/index.php?title=20W_RGB_LED_Driver_Board_Assembly_(WS2811_version)
*** https://www.pinterest.co.uk/pin/69454019241843846/ - 20W V7
** ''could be reverse engineered using the pictures''
** components
*** https://en.wikipedia.org/wiki/2N3904 - common npn
*** PT4115 - CC buck led driver
** https://hackaday.io/project/6124-10w-rgb-flood-drivers
** https://www.tindie.com/products/robg/pixelflood-50w-rgb-flood-light-ws2811-pixel/
** https://www.tindie.com/products/robg/pixelflood-100w-rgb-led-ws2811-mega-pixel/


there are a few questions/posts on the net on how to drive mosfets with the ws2811 chips

* https://electronics.stackexchange.com/questions/649439/ws2811-mosfet-driver-components-help
* https://forum.arduino.cc/t/ws2811-mosfet-driver-alternative-components-help/1075281
* https://forum.arduino.cc/t/ws2811-high-power-driver/1114493?page=2
* https://nootropicdesign.com/projectlab/2016/05/21/individually-addressable-incandescent-lamps/
** https://hackaday.com/2016/06/12/using-ws2811-chip-to-drive-incandescent-lamps/
* https://forums.adafruit.com/viewtopic.php?t=44670
* https://forum.arduino.cc/t/ws2811-led-analog-strip-controller/248937
* https://community.element14.com/technologies/experts/f/forum/46839/help-using-ws2811-to-drive-12v-rgb-led-strip
* http://www.riderx.info/?s=WS2811+Expander
* https://www.mikrocontroller.net/topic/310669
* https://forum.arduino.cc/t/ws2811b-and-mosfets/688946
* https://electronics.stackexchange.com/questions/619779/using-the-ws2811-as-a-vibration-motor-control
* https://wiki.mobaledlib.de/anleitungen/anwendungen/strassenbeleuchtung
* https://www.reddit.com/r/electronics/comments/oyfnc/how_to_connect_mosfets_to_a_ws2801_chip_instead/
* https://forum.arduino.cc/t/ws2811-pixel-driver/199725
* https://www.reddit.com/r/electronics/comments/oyfnc/how_to_connect_mosfets_to_a_ws2801_chip_instead/
* https://electronics.stackexchange.com/questions/598820/knowledge-requested-for-ws2811-based-rgb-led-driver-module
* https://www.reddit.com/r/led/comments/hacj6p/highpower_addressable_leds/
* https://www.youtube.com/watch?v=yGDkNJZdvDA
* [[WS2811 on Steroids |https://www.youtube.com/watch?v=pZl-YRROb4Q]]
* https://www.reddit.com/r/led/comments/sv3d4r/need_help_using_a_ws2811_led_driver_to_control_a/
* https://electronics.stackexchange.com/questions/191994/driving-high-power-led-using-ws2811-or-ws2801
* https://www.mikrocontroller.net/topic/553800

a great company making their design public

* https://www.freetronics.com.au/products/addressable-n-mosfet-driver-output-module
** schematic: https://cdn.shopify.com/s/files/1/0045/8932/files/FREENFET-v1_0-schematic.pdf?15966285591977644917
* https://www.freetronics.com.au/products/addressable-triple-n-mosfet-driver-output-module
** https://cdn.shopify.com/s/files/1/0045/8932/files/FREENFET3-v1_0-schematic.pdf?17886992959179520710
* https://www.freetronics.com.au/pages/freenfet-quickstart-guide
* https://forum.arduino.cc/t/ws2811-mosfet-driver-alternative-components-help/1075281
* https://electronics.stackexchange.com/questions/649439/ws2811-mosfet-driver-components-help

driving high power LEDs

* [[LED Driver (constant current)]]
* https://www.youtube.com/watch?v=JOqSCbm9G0c
* https://www.youtube.com/watch?v=rib9GeZvjU4
* https://www.youtube.com/watch?v=piET0Biqo0I
* https://www.youtube.com/watch?v=A64kpzhzlqI
* https://www.youtube.com/watch?v=rDkP97-BHXI
* https://www.youtube.com/watch?v=2ojNDKIScpI
* https://www.youtube.com/watch?v=WSpkLsp_9_o
** https://www.infineon.com/cms/en/product/power/lighting-ics/linear-led-driver-ic/bcr421u/
** https://www.infineon.com/cms/en/product/power/lighting-ics/linear-led-driver-ic/bcr420u/
* aliexpress
** "dmx led constant"
** "led constant current 3 channel"
*** https://de.aliexpress.com/item/1005005450523131.html
*** https://de.aliexpress.com/item/1005005069916507.html
*** https://de.aliexpress.com/item/1005003917892363.html
*** https://de.aliexpress.com/item/1005005069991618.html
*** https://de.aliexpress.com/item/1005005769194518.html
*** https://de.aliexpress.com/item/1005005127762766.html
* https://de.aliexpress.com/item/4000154187480.html - other ws chips?
* https://electronics.stackexchange.com/questions/543244/control-a-3w-rgb-led-with-an-arduino
* https://www.onsemi.com/pdf/datasheet/cat4103-d.pdf
* https://www.tindie.com/products/antonveretenenko/mini-constant-current-led-driver/
* P9813 based modules?
** https://raw.githubusercontent.com/SeeedDocument/Grove-Chainable_RGB_LED/master/res/P9813_datasheet.pdf

notes

<<<
snjor köttr, [20.08.23 21:15]
kann mir jemensch von euch tipps geben wie ich am besten 3W, 6W oder so RGB LEDs mit strom versorge?
schalten/dimmen will ich die einfach mit mosfets angesteuert vom microcontroller oder ws2811, aber ich bin mir unsicher wie ich die am besten mit strom versorge.
ich bräuchte ja im grunde für jeden channel bzw. jeden led chip eine eigene strombegrenze versorgung, oder?
oder habt ihr ideen wie ichs am besten machen könnte?

Ennar ������������/ ������������, [20.08.23 22:03]
n dedizierter LED-Treiber mit PWM/Analogeingang ist da besser geeignet als diskrete MOSFETs

die haben alles an Board, inklusive Schutzbeschalten gegen internes Überhitzen und ESD

http://www.h-tronic.com/Presse/download/HV9910datasheet.pdf

so was hatten wir mal in der alten Firma in mehreren Produkten drin, geht ziemlich gut. Braucht allerdings einen externen FET, gibt so was auch mit internem FET

snjor köttr, [20.08.23 23:16]
hmm... ich überlege aber ob ich ws2812 artige ansteuerung möchte, weil das unsere anderen lampen schon nutzen

Ennar ������������/ ������������, [20.08.23 23:17]
du kannst natürlich den WS-Chip zur Ansteuerung benutzen, nur dass dann die PWM Ausgänge nicht direkt an LEDs gehen

snjor köttr, [20.08.23 23:56]
klar, halt mit mosfets dazwischen

meine original frage war aber bzgl. wie ich dann die CC stromversorgung verschalten müsste/kann?
ich müsste dann ja für jeden kanal eine eigene CC versorgung haben, oder?

Ennar ������������/ ������������, [21.08.23 00:02]
ja, steuerbar

oder eine zentrale CC Quelle und die LEDs nie gleichzeitig betreiben

so hat Philips das mal mit einer Hue-Leuchte gemacht

snjor köttr, [21.08.23 00:08]
was meinst du mit steuerbar?

Ennar ������������/ ������������, [21.08.23 00:08]
dass du die CC extern steuern kannst

snjor köttr, [21.08.23 00:09]
warum? wenn ich schon den ws2811 habe zum steuern?

Ennar ������������/ ������������, [21.08.23 00:09]
...der dann die CC Quellen steuert

du solltest lieber nicht versuchen, das CC von extern mit PWM zu unterbrechen. Das kann die Regelung durcheinander bringen. Lieber eine CC Quelle nehmen, die von extern durch irgendein Signal (analog oder PWM) gesteuert werden kann

snjor köttr, [21.08.23 00:11]
achso... also CCs mit PWM input der mit der schaltfrequenz der ws2811 kompatibel ist... daran habe ich noch nicht gedacht

muss ich dann bei gelegenheit mal schauen ob das geht, würde das ganze natürlich nochmal um einiges vereinfachen
<<<



!! my experiments

i bought some ws2811 sop-8/soic-8 breakouts, 3W and 10W rgb LEDs and different small 300-350mA led drivers for 5 to 12V as well as esp8266 (esp-01s).

i wanted to try controlling the led drivers using the pwm of the ws2811, but that did not work. i even tried tricking the constant current drive of the ws2811 but that did not improve things

driving the led drivers with an esp directly would work

wled pwm frequency:

* https://github.com/Aircoookie/WLED/issues/2205
* https://github.com/Aircoookie/WLED/issues/2868
* https://kno.wled.ge/basics/compatible-led-strips/#non-addressable-led-strips


[[esp32 ws281x/ws2812 RMT parse/read]]
company seems to be dead since the end of 2019

* https://www.youtube.com/playlist?list=PL29OnkRjK38cut9g6SvXEYbKAhIWF92B9
* https://www.youtube.com/@boxzy1167/videos
* https://desktop-3dprinter.com/ - website, but outdated
* https://boxzy.dozuki.com/c/BoXZY_Manual - original manual but offline - maybe available in the archive?
* https://github.com/mwasilew/boxzy - unofficial manual but seems extensive

mill

the mill that came with it is an original makita but a US 110V version. i don't know if it is possible to rewire it, but probably not as easy because i don't know the 230V wiring and the speed-controll pcb probably also has to be modified.
it might be possible to get spare parts for the current version that fit in the old version?

there are some cheap china models available which seem to work with the same 65mm base.

PC software

* https://www.reddit.com/r/3Dprinting/comments/i0u54i/boxzy_software/
**https://drive.google.com/file/d/0B0gOyqLrz4L-ZEcxQ2E2dnVsTlU/view?resourcekey=0-yQH9hragkKfnHfCFjtz3wQ
* https://www.youtube.com/watch?v=7wva9jHEdbo - software install

firmware 

* https://forum.repetier.com/discussion/9567/what-do-i-need-to-know-to-update-the-firmware-for-boxzy
* https://www.facebook.com/groups/boxzyusers/posts/975861179691346/
* https://github.com/dewhisna/Repetier-Firmware/blob/BoXZY_Custom/README.md
* https://github.com/chappy1978/Boxzy-
* https://github.com/mwasilew/boxzy/blob/master/Upgrading_firmware.md
** https://github.com/rbdavison/boxzy/blob/master/Upgrading_firmware.md
** https://github.com/mwasilew/boxzy/issues/1
not possible because of limitations in wayland (security). xdotool was written for xorg, you could change to that or use other tools.
sources:

* https://unix.stackexchange.com/questions/381831/keyboard-emulation-in-wayland
* https://github.com/ReimuNotMoe/ydotool
* https://superuser.com/questions/1032270/wayland-alternative-for-xorgs-xdotool
* https://askubuntu.com/questions/956640/equivalent-to-xdotool-for-wayland

i wanted to use it to controll a pc from my sofa with a phone using the app xmouse on fdroid. ''using KDE connect or GSConnect (KDE connect support for gnome) was great too.''


!! https://github.com/ReimuNotMoe/ydotool
* https://en.wikipedia.org/wiki/XLR_connector
*https://de.wikipedia.org/wiki/XLR
zeug das sich nich lohnt extra zu bestellen oder zu holen oder ich für gemeinnützige projekte gebrauchen kann

* Hochlastwiderstände, am besten 2, 4, 6, 8, 16 Ohm oder andere multible
* alten LPT Drucker oder vlt. einen Drucker mit HP C6602 Patronen, oder auch nur die patronen
* Eurokisten, diverse formate
* stabile räder für rollbrett
* wechselrichter, egal welche leistung, auch kaputte
* Veranstaltungstechnik bzw. PA/Beschallungstechnik, Lautsprecher, Mischpulte, Mikros, Car-Hifi verstärker, kabel/stecker/buchsen (xlr, große klinke, speakon), auch kaputt
* Elektro Auto Akkus
* "Wo ein Trog ist, sammeln sich die Schweine" - Staatsrechtler Christoph Gusy
** https://www.heise.de/tp/news/Wo-ein-Trog-ist-sammeln-sich-die-Schweine-2570570.html
** https://www.zeit.de/digital/datenschutz/2009-12/vds-bverfg-karlsruhe

* https://de.wikipedia.org/wiki/Raumschiff_Erde
* https://de.wikipedia.org/wiki/Pale_Blue_Dot#Buch_und_%C3%9Cberlegungen_von_Carl_Sagan
*  https://en.wikipedia.org/wiki/Overview_effect
** https://de.wikipedia.org/wiki/Overview-Effekt
* https://www.youtube.com/watch?v=tFW5E9MDJPo
* https://www.bpb.de/shop/lernen/themen-und-materialien/37246/zivilcourage-lernen-analysen-modelle-arbeitshilfen
* https://www.bpb.de/nachschlagen/lexika/das-junge-politik-lexikon/321489/zivilcourage
* https://www.bpb.de/apuz/25723/zivilcourage-politisches-engagement
* https://www.bpb.de/shop/lernen/themenblaetter/211704/zivilcourage
! Zoom H2n - for Coloradio

This one is missing the cap from the power switch. without the cap one cannot switch the device on, because the switch is hidden in the case. It seems the cap is only clipped in from the outside, that is why i was able to fall out.
I think that is a big design flaw.

because the cap is very small and delicate pretty much the only option is to resin 3d print the part.
I designed a version that is pretty close to the original how i imagine it.
Additionally i designed my own version that comes out from the inside and therefore cannot fall out. Its not as pleasing to look at but should work all right.

! Zoom H4 - for a customer of GTC

The customer used a power supply with way to much voltage or with the wrong polarity on the poor recorder.
switching the polarity of a barrel jack, so that + is outside, is pretty stupid and companies who do that hate their customers. on top of that the device seems to have no input protection. thats just a huge fuckup by zoom. probably not the fault of the engineers, but of some stupid manager who just wanted to cheap out and rip off customers.
These devices are not cheap.

Anyways, there are blown and shorted regulators all over the powersupply pcb, not even battery power does work. the barrel jack got melted, a small ferrite inductor on the power input is smoked.

its not really salvageable because i can't find the smd parts that were used.



! more info

* https://sound.stackexchange.com/questions/1383/broken-zoom-h2-solutions
* http://studiorepair.com/gallery/Zoom/H4/index.html
* https://ludwigschuster.de/zoom-h4-defekt-reparatur/
* https://de.ifixit.com/Device/Voice_Recorder