|
|
|
|
|
|
|
|
|
<!doctype html>
|
|
|
|
|
<!-- The following comment is called a MOTW comment and is necessary for the TiddlyIE Internet Explorer extension -->
|
|
|
|
|
<!-- saved from url=(0021)https://tiddlywiki.com -->
|
|
|
|
|
<html lang="en-GB">
|
|
|
|
|
<head>
|
|
|
|
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
|
|
|
|
<!--~~ Raw markup for the top of the head section ~~-->
|
|
|
|
|
|
|
|
|
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
|
|
|
|
|
<meta name="application-name" content="TiddlyWiki" />
|
|
|
|
|
<meta name="generator" content="TiddlyWiki" />
|
|
|
|
|
<meta name="tiddlywiki-version" content="5.3.1" />
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
|
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
|
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
|
|
|
<meta name="mobile-web-app-capable" content="yes"/>
|
|
|
|
|
<meta name="format-detection" content="telephone=no" />
|
|
|
|
|
<meta name="copyright" content="TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2004-2007, Jeremy Ruston
|
|
|
|
|
Copyright (c) 2007-2023, UnaMesa Association
|
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright notice, this
|
|
|
|
|
list of conditions and the following disclaimer.
|
|
|
|
|
|
|
|
|
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
|
this list of conditions and the following disclaimer in the documentation
|
|
|
|
|
and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
|
|
* Neither the name of the copyright holder nor the names of its
|
|
|
|
|
contributors may be used to endorse or promote products derived from
|
|
|
|
|
this software without specific prior written permission.
|
|
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
|
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
|
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
|
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." />
|
|
|
|
|
<link id="faviconLink" rel="shortcut icon" href="favicon.ico">
|
|
|
|
|
<title>copinchapedia — la wiki de copincha</title>
|
|
|
|
|
<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->
|
|
|
|
|
|
|
|
|
|
<!--~~ Raw markup ~~-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</head>
|
|
|
|
|
<body class="tc-body">
|
|
|
|
|
<!--~~ Raw markup for the top of the body section ~~-->
|
|
|
|
|
|
|
|
|
|
<!--~~ Static styles ~~-->
|
|
|
|
|
<div id="styleArea">
|
|
|
|
|
<style data-tiddler-title="$:/boot/boot.css" data-tiddler-type="text/css" type="text/css">/*
|
|
|
|
|
Basic styles used before we boot up the parsing engine
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Error message and password prompt
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
.tc-error-form {
|
|
|
|
|
font-family: sans-serif;
|
|
|
|
|
color: #fff;
|
|
|
|
|
z-index: 20000;
|
|
|
|
|
position: fixed;
|
|
|
|
|
background-color: rgb(255, 75, 75);
|
|
|
|
|
border: 8px solid rgb(255, 0, 0);
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
width: 50%;
|
|
|
|
|
margin-left: 25%;
|
|
|
|
|
margin-top: 4em;
|
|
|
|
|
padding: 0 2em 1em 2em;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tc-error-form h1 {
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tc-error-prompt {
|
|
|
|
|
text-align: center;
|
|
|
|
|
color: #000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tc-error-message {
|
|
|
|
|
overflow: auto;
|
|
|
|
|
max-height: 40em;
|
|
|
|
|
padding-right: 1em;
|
|
|
|
|
margin: 1em 0;
|
|
|
|
|
white-space: pre-line;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tc-password-wrapper {
|
|
|
|
|
font-family: sans-serif;
|
|
|
|
|
z-index: 20000;
|
|
|
|
|
position: fixed;
|
|
|
|
|
text-align: center;
|
|
|
|
|
width: 200px;
|
|
|
|
|
top: 4em;
|
|
|
|
|
left: 50%;
|
|
|
|
|
margin-left: -144px; /* - width/2 - paddingHorz/2 - border */
|
|
|
|
|
padding: 16px 16px 16px 16px;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tc-password-wrapper {
|
|
|
|
|
color: #000;
|
|
|
|
|
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
|
|
|
|
background-color: rgb(197, 235, 183);
|
|
|
|
|
border: 8px solid rgb(164, 197, 152);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tc-password-wrapper form {
|
|
|
|
|
text-align: left;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tc-password-wrapper h1 {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
line-height: 20px;
|
|
|
|
|
padding-bottom: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tc-password-wrapper input {
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
</div>
|
|
|
|
|
<!--~~ Static content for Google and browsers without JavaScript ~~-->
|
|
|
|
|
<noscript>
|
|
|
|
|
<div id="splashArea">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<p>This <a class="tc-tiddlylink-external" href="https://tiddlywiki.com" rel="noopener noreferrer" target="_blank">TiddlyWiki</a> contains the following tiddlers:</p><p><ul>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/DefaultColourMappings/menubar-background</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/DefaultColourMappings/menubar-foreground</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/advanced-search</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-tiddler</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/save-wiki</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/contents</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/hamburger</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/pagecontrols</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/search</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/search 1</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/server</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/sidebar</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/topleftbar</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/toprightbar</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/plugins/menubar/TableOfContents/Tag</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/RelinkOnRename</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/close</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/delete</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/edit</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/more-tiddler-actions</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/SideBar/More</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/SideBar/Open</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/SideBar/Tools</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/SideBarSegments/page-controls</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/SideBarSegments/search</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/SideBarSegments/site-subtitle</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/SideBarSegments/site-title</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/SideBarSegments/tabs</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/ViewTemplate/subtitle</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/ViewTemplate/subtitle/modified</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/ViewTemplate/tags</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/ViewTemplate/title</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/core/ui/ViewTemplate/title/default</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/DefaultTiddlers</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/favicon.ico</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/Import</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/isEncrypted</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/palette</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/palettes/copincha</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/felixhayashi/respawn</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/felixhayashi/topstoryview</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/sycom/leaflet</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/sycom/leaflet/lib/leaflet.css</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/items/about</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/items/actividades</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/items/calendario</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/items/contacto</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/items/join</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/items/miembros</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/items/proyectos</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/items/search 1</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/items/servicios</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/items/talleres</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/menu</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/plugins/tiddlywiki/menubar/styles</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/SiteSubtitle</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/SiteTitle</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/advancedsearch/currentTab</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/Excise/-386158927/type</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/http-requests</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/peek-stylesheets/open/-1116772087$:/plugins/sq/streams/contextmenu/contextmenu-styles</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/plugin-info--778185000-$:/plugins/tiddlywiki/filesystem---1320199477</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/plugin-info-713020762-$:/plugins/tiddlywiki/menubar--777473238</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/search/currentTab</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/showeditpreview</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/ShowPaletteEditor</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sidebar</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928041541658--1254993181</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928041546393-934822130</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928041548495--369046925</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928042426730-2022682073</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928042740135-782739965</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928042840565--156986883</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928062923658-235852612</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928062926521-119290700</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928062931943--1779145438</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928063011441-1517244705</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928063013515--2009532357</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928063019801--1466208351</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928063307747-1329551714</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/sq/streams/visibility/copincha/20230928071813328-1752783608</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/tab--1498284803</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/tab--1963855381</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/tab--2112689675</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/tab--86143343</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/tab--959111941</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/tab-1749438307</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/tab-453520357</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/tab/search-results/sidebar</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/tab/sidebar--595412856</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/tabs/controlpanel/toolbars-1345989671</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/toc/contenidos-Talleres--944721818</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/toc/TableOfContents-Actividades--944721818</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/toc/TableOfContents-Actividades-1684905998</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/toc/TableOfContents-Proyectos--944721818</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/toc/TableOfContents-Proyectos-1684905998</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/toc/TableOfContents-Servicios--944721818</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/state/toc/TableOfContents-Talleres--944721818</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/status/RequireReloadDueToPluginChange</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/StoryList</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/tags/ViewToolbar</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/theme</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/centralised</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/snowwhite</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/metrics/bodylineheight</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/metrics/fontsize</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/metrics/lineheight</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/metrics/storyleft</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/metrics/storyright</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/metrics/storytop</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/metrics/storywidth</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/settings/backgroundimage</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/settings/codefontfamily</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/settings/editorfontfamily</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/themes/tiddlywiki/vanilla/settings/fontfamily</li>
|
|
|
|
|
|
|
|
|
|
<li>$:/view</li>
|
|
|
|
|
|
|
|
|
|
<li>2023-09-25_08-19.png</li>
|
|
|
|
|
|
|
|
|
|
<li>About</li>
|
|
|
|
|
|
|
|
|
|
<li>Actividades</li>
|
|
|
|
|
|
|
|
|
|
<li>agregar marca de licencia creative commons</li>
|
|
|
|
|
|
|
|
|
|
<li>asiento</li>
|
|
|
|
|
|
|
|
|
|
<li>barra</li>
|
|
|
|
|
|
|
|
|
|
<li>cafe-reparador</li>
|
|
|
|
|
|
|
|
|
|
<li>cafe-sorpresa</li>
|
|
|
|
|
|
|
|
|
|
<li>Calendario</li>
|
|
|
|
|
|
|
|
|
|
<li>carta resistor</li>
|
|
|
|
|
|
|
|
|
|
<li>coche</li>
|
|
|
|
|
|
|
|
|
|
<li>Contacto</li>
|
|
|
|
|
|
|
|
|
|
<li>contenidos</li>
|
|
|
|
|
|
|
|
|
|
<li>copincha</li>
|
|
|
|
|
|
|
|
|
|
<li>copincha--mapa</li>
|
|
|
|
|
|
|
|
|
|
<li>copincha--mapa--hackerspace</li>
|
|
|
|
|
|
|
|
|
|
<li>copincha--miembro--m00</li>
|
|
|
|
|
|
|
|
|
|
<li>copincha--miembro--nestor</li>
|
|
|
|
|
|
|
|
|
|
<li>copincha--miembro--sergio</li>
|
|
|
|
|
|
|
|
|
|
<li>copincha--miembro--template</li>
|
|
|
|
|
|
|
|
|
|
<li>copincha--projecto--3d-a-lo-cubano</li>
|
|
|
|
|
|
|
|
|
|
<li>copincha--proyecto--hackerspace</li>
|
|
|
|
|
|
|
|
|
|
<li>copincha--proyecto--pph</li>
|
|
|
|
|
|
|
|
|
|
<li>copincha-descripcion</li>
|
|
|
|
|
|
|
|
|
|
<li>copinchapedia</li>
|
|
|
|
|
|
|
|
|
|
<li>crear servidor alternativa a node.js</li>
|
|
|
|
|
|
|
|
|
|
<li>Crear una Paleta</li>
|
|
|
|
|
|
|
|
|
|
<li>Desarrollo del wiki</li>
|
|
|
|
|
|
|
|
|
|
<li>Desarrollo del wiki/20230928050314967</li>
|
|
|
|
|
|
|
|
|
|
<li>Diseno intersticial</li>
|
|
|
|
|
|
|
|
|
|
<li>Diseno participativo intersticial</li>
|
|
|
|
|
|
|
|
|
|
<li>habilitar dominio sergio.copincha.org</li>
|
|
|
|
|
|
|
|
|
|
<li>Hackerspace</li>
|
|
|
|
|
|
|
|
|
|
<li>Hackerspace Copincha</li>
|
|
|
|
|
|
|
|
|
|
<li>Impresion 3D</li>
|
|
|
|
|
|
|
|
|
|
<li>impresoras 3D RepRap</li>
|
|
|
|
|
|
|
|
|
|
<li>Intersticialidad</li>
|
|
|
|
|
|
|
|
|
|
<li>La maquina intersticial</li>
|
|
|
|
|
|
|
|
|
|
<li>La maquina intersticial 1</li>
|
|
|
|
|
|
|
|
|
|
<li>New Tiddler</li>
|
|
|
|
|
|
|
|
|
|
<li>New Tiddler 1</li>
|
|
|
|
|
|
|
|
|
|
<li>Notas</li>
|
|
|
|
|
|
|
|
|
|
<li>quitar elementos de tiddler</li>
|
|
|
|
|
|
|
|
|
|
<li>Servicios</li>
|
|
|
|
|
|
|
|
|
|
<li>Talleres</li>
|
|
|
|
|
|
|
|
|
|
<li>Templates</li>
|
|
|
|
|
|
|
|
|
|
<li>To do</li>
|
|
|
|
|
|
|
|
|
|
<li>Unirse</li>
|
|
|
|
|
|
|
|
|
|
<li>Untitled</li>
|
|
|
|
|
|
|
|
|
|
<li>Ventajas de la instersticialidad</li>
|
|
|
|
|
|
|
|
|
|
<li>Ventajas de la instersticialidad 1</li>
|
|
|
|
|
|
|
|
|
|
<li>volante</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
.tc-remove-when-wiki-loaded {display: none;}
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</noscript>
|
|
|
|
|
<!--~~ Ordinary tiddlers ~~-->
|
|
|
|
|
<script class="tiddlywiki-tiddler-store" type="application/json">[
|
|
|
|
|
{"created":"20230928083723989","text":"#f5f2e9","title":"$:/config/DefaultColourMappings/menubar-background","modified":"20230928083725645"},
|
|
|
|
|
{"created":"20230928083910399","text":"menubar-background","title":"$:/config/DefaultColourMappings/menubar-foreground","modified":"20230928083912310"},
|
|
|
|
|
{"created":"20230930045902539","text":"show","title":"$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/advanced-search","modified":"20230930045902539"},
|
|
|
|
|
{"created":"20230929204329952","text":"show","title":"$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home","modified":"20230929204329952"},
|
|
|
|
|
{"created":"20230929204339475","text":"hide","title":"$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-tiddler","modified":"20230929204339475"},
|
|
|
|
|
{"created":"20230929204347388","text":"hide","title":"$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/save-wiki","modified":"20230929204347388"},
|
|
|
|
|
{"created":"20230929115731062","text":"hide","title":"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/contents","modified":"20230929115746121"},
|
|
|
|
|
{"created":"20230928092309468","text":"show","title":"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/hamburger","modified":"20230928152409425"},
|
|
|
|
|
{"created":"20230928092236057","text":"show","title":"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/pagecontrols","modified":"20230930053549607"},
|
|
|
|
|
{"created":"20230928182228358","text":"hide","title":"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/search","modified":"20230930053550960"},
|
|
|
|
|
{"created":"20230929093532645","text":"hide","title":"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/search 1","modified":"20230929105610913"},
|
|
|
|
|
{"created":"20230928092218000","text":"hide","title":"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/server","modified":"20230929105628231"},
|
|
|
|
|
{"created":"20230928161436942","text":"hide","title":"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/sidebar","modified":"20230929204523419"},
|
|
|
|
|
{"created":"20230928092258081","text":"show","title":"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/topleftbar","modified":"20230930050015268"},
|
|
|
|
|
{"created":"20230928092201524","text":"hide","title":"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/toprightbar","modified":"20230930051213880"},
|
|
|
|
|
{"created":"20230928090647497","title":"$:/config/plugins/menubar/TableOfContents/Tag","text":"contenidos","modified":"20230928090647497"},
|
|
|
|
|
{"created":"20230927223047457","text":"yes","title":"$:/config/RelinkOnRename","modified":"20230927223047457"},
|
|
|
|
|
{"created":"20230929204302303","text":"hide","title":"$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/close","modified":"20230930052005825"},
|
|
|
|
|
{"created":"20230930050507080","text":"hide","title":"$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/delete","modified":"20230930051245778"},
|
|
|
|
|
{"created":"20230928074541041","text":"show","title":"$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/edit","modified":"20231001053146669"},
|
|
|
|
|
{"created":"20230929204237557","text":"hide","title":"$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/more-tiddler-actions","modified":"20231001053145444"},
|
|
|
|
|
{"title":"$:/core","name":"Core","description":"TiddlyWiki5 core","author":"JeremyRuston","core-version":">=5.0.0","plugin-priority":"0","list":"readme","version":"5.3.1","plugin-type":"plugin","dependents":"","type":"application/json","text":"{\"tiddlers\":{\"$:/Acknowledgements\":{\"title\":\"$:/Acknowledgements\",\"text\":\"TiddlyWiki incorporates code from these fine OpenSource projects:\\n\\n* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]\\n* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]\\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-2023, 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\":\"\\\\parameters (size:\\\"22pt\\\")\\n\u003Csvg width=\u003C\u003Csize>> height=\u003C\u003Csize>> viewBox=\\\"0 0 128 128\\\">\u003Cpath d=\\\"M64 0l54.56 32v64L64 128 9.44 96V32L64 0zm21.127 95.408c-3.578-.103-5.15-.094-6.974-3.152l-1.42.042c-1.653-.075-.964-.04-2.067-.097-1.844-.07-1.548-1.86-1.873-2.8-.52-3.202.687-6.43.65-9.632-.014-1.14-1.593-5.17-2.157-6.61-1.768.34-3.546.406-5.34.497-4.134-.01-8.24-.527-12.317-1.183-.8 3.35-3.16 8.036-1.21 11.44 2.37 3.52 4.03 4.495 6.61 4.707 2.572.212 3.16 3.18 2.53 4.242-.55.73-1.52.864-2.346 1.04l-1.65.08c-1.296-.046-2.455-.404-3.61-.955-1.93-1.097-3.925-3.383-5.406-5.024.345.658.55 1.938.24 2.53-.878 1.27-4.665 1.26-6.4.47-1.97-.89-6.73-7.162-7.468-11.86 1.96-3.78 4.812-7.07 6.255-11.186-3.146-2.05-4.83-5.384-4.61-9.16l.08-.44c-3.097.59-1.49.37-4.82.628-10.608-.032-19.935-7.37-14.68-18.774.34-.673.664-1.287 1.243-.994.466.237.4 1.18.166 2.227-3.005 13.627 11.67 13.732 20.69 11.21.89-.25 2.67-1.936 3.905-2.495 2.016-.91 4.205-1.282 6.376-1.55 5.4-.63 11.893 2.276 15.19 2.37 3.3.096 7.99-.805 10.87-.615 2.09.098 4.143.483 6.16 1.03 1.306-6.49 1.4-11.27 4.492-12.38 1.814.293 3.213 2.818 4.25 4.167 2.112-.086 4.12.46 6.115 1.066 3.61-.522 6.642-2.593 9.833-4.203-3.234 2.69-3.673 7.075-3.303 11.127.138 2.103-.444 4.386-1.164 6.54-1.348 3.507-3.95 7.204-6.97 7.014-1.14-.036-1.805-.695-2.653-1.4-.164 1.427-.81 2.7-1.434 3.96-1.44 2.797-5.203 4.03-8.687 7.016-3.484 2.985 1.114 13.65 2.23 1
|
|
|
|
|
{"created":"20230928083221493","text":"\\whitespace trim\n\u003Cdiv class={{{ [{$:/config/ui/SideBar/More/horizontal}match[yes]then[tc-sidebar-tabs]else[tc-more-sidebar]] }}}>\n\u003C$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]\" default={{$:/config/DefaultMoreSidebarTab}} state=\"$:/state/tab/moresidebar\" class={{{ [{$:/config/ui/SideBar/More/horizontal}match[yes]then[tc-sidebar-tabs-more]else[tc-vertical tc-sidebar-tabs-more]] }}} explicitState=\"$:/state/tab/moresidebar-1850697562\"/>\n\u003C/div>\n","title":"$:/core/ui/SideBar/More","tags":"","caption":"{{$:/language/SideBar/More/Caption}}","modified":"20230928083223334"},
|
|
|
|
|
{"created":"20230928083236382","text":"\\whitespace trim\n\\define lingo-base() $:/language/CloseAll/\n\n\\define drop-actions()\n\u003C$action-listops $tiddler=\u003C\u003Ctv-story-list>> $subfilter=\"+[insertbefore\u003CactionTiddler>,\u003CcurrentTiddler>]\"/>\n\\end\n\n\\define placeholder()\n\u003Cdiv class=\"tc-droppable-placeholder\"/>\n\\end\n\n\\define droppable-item(button)\n\\whitespace trim\n\u003C$droppable actions=\u003C\u003Cdrop-actions>> enable=\u003C\u003Ctv-allow-drag-and-drop>> tag=\"div\">\n\u003C\u003Cplaceholder>>\n\u003Cdiv>\n$button$\n\u003C/div>\n\u003C/$droppable>\n\\end\n\n\u003Cdiv class=\"tc-sidebar-tab-open\">\n\u003C$list filter=\"[list\u003Ctv-story-list>]\" history=\u003C\u003Ctv-history-list>> storyview=\"pop\">\n\u003Cdiv class=\"tc-sidebar-tab-open-item\">\n\u003C$macrocall $name=\"droppable-item\" button=\"\u003C$button message='tm-close-tiddler' tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class='tc-btn-invisible tc-btn-mini tc-small-gap-right'>{{$:/core/images/close-button}}\u003C/$button>\u003C$link/>\"/>\n\u003C/div>\n\u003C/$list>\n\u003C$tiddler tiddler=\"\">\n\u003Cdiv>\n\u003C$macrocall $name=\"droppable-item\" button=\"\u003C$button message='tm-close-all-tiddlers' class='tc-btn-invisible tc-btn-mini'>\u003C\u003Clingo Button>>\u003C/$button>\"/>\n\u003C/div>\n\u003C/$tiddler>\n\u003C/div>\n","title":"$:/core/ui/SideBar/Open","tags":"","caption":"{{$:/language/SideBar/Open/Caption}}","modified":"20230928083238470"},
|
|
|
|
|
{"created":"20230928083149362","text":"\\define lingo-base() $:/language/ControlPanel/\n\\define config-title()\n$:/config/PageControlButtons/Visibility/$(listItem)$\n\\end\n\n\u003C\u003Clingo Basics/Version/Prompt>> \u003C\u003Cversion>>\n\n\u003C$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n\u003C$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n\u003C$set name=\"tv-config-toolbar-class\" value=\"\">\n\n\u003C$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]\" variable=\"listItem\">\n\n\u003Cdiv style=\"position:relative;\" class={{{ [\u003ClistItem>encodeuricomponent[]addprefix[tc-btn-]] }}}>\n\n\u003C$checkbox tiddler=\u003C\u003Cconfig-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> \u003C$transclude tiddler=\u003C\u003ClistItem>>/> \u003Ci class=\"tc-muted\">\u003C$transclude tiddler=\u003C\u003ClistItem>> field=\"description\"/>\u003C/i>\n\n\u003C/div>\n\n\u003C/$list>\n\n\u003C/$set>\n\n\u003C/$set>\n\n\u003C/$set>\n","title":"$:/core/ui/SideBar/Tools","tags":"","caption":"{{$:/language/SideBar/Tools/Caption}}","modified":"20230928083155482"},
|
|
|
|
|
{"created":"20230930050642407","text":"\u003C!--{{||$:/core/ui/PageTemplate/pagecontrols}}-->\n","title":"$:/core/ui/SideBarSegments/page-controls","tags":"$:/tags/SideBarSegment","modified":"20230930050649297"},
|
|
|
|
|
{"created":"20230930050843894","text":"\u003C!--\n\n\\whitespace trim\n\n\\define count-popup-button()\n\\whitespace trim\n\u003C$button popup=\u003C\u003Cqualify \"$:/state/popup/search-dropdown\">> class=\"tc-btn-invisible\">\n{{$:/core/images/down-arrow}}\n\u003C$list filter=\"[{$(searchTiddler)$}minlength{$:/config/Search/MinLength}limit[1]]\" variable=\"listItem\">\n\u003C$vars userInput={{{ [\u003CsearchTiddler>get[text]] }}} configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}} replaceRegexp=\"limit\\[\\d+\\]\">\n\u003C$vars primaryListFilter={{{ [\u003CconfigTiddler>get[first-search-filter]search-replace:g:regexp\u003CreplaceRegexp>,[]] }}} secondaryListFilter={{{ [\u003CconfigTiddler>get[second-search-filter]search-replace:g:regexp\u003CreplaceRegexp>,[]] }}}>\n\u003C$set name=\"resultCount\" value=\"\"\"\u003C$count filter=\"[subfilter\u003CprimaryListFilter>] [subfilter\u003CsecondaryListFilter>]\"/>\"\"\">\n{{$:/language/Search/Matches}}\n\u003C/$set>\n\u003C/$vars>\n\u003C/$vars>\n\u003C/$list>\n\u003C/$button>\n\\end\n\n\\define search-results-list()\n\\whitespace trim\n\u003C$vars userInput={{$(searchTiddler)$}} configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}}>\n\u003C$list filter=\"[\u003CuserInput>minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"\u003Cdiv class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}\u003C/div>\"\"\" variable=\"listItem\">\n\n\u003C$tiddler tiddler=\u003C\u003CconfigTiddler>>>\n\n{{$:/core/ui/SearchResults}}\n\n\u003C/$tiddler>\n\n\u003C/$list>\n\u003C/$vars>\n\\end\n\n\\define cancel-search-actions() \u003C$list filter=\"[\u003CsearchTiddler>get[text]!match{$:/temp/search}]\" emptyMessage=\"\"\"\u003C$action-deletetiddler $filter=\"[[$:/temp/search]] [\u003CsearchTiddler>] [\u003CsearchListState>]\"/>\"\"\">\u003C$action-setfield $tiddler=\"$:/temp/search\" text={{{ [\u003CsearchTiddler>get[text]] }}}/>\u003C$action-setfield $tiddler=\"$:/temp/search/refresh\" text=\"yes\"/>\u003C/$list>\n\n\\define input-accept-actions() \u003C$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"\u003C$list filter=\"[\u003C__tiddler__>get[text]!is[missing]] ~[\u003C__tiddler__>get[text]is[shadow]]\">\u003C$action-navigate $to={{{ [\u003C__tiddler__>get[text]] }}}/>\u003C/$list>\"\"\">\u003C$action-navigate $to={{{ [\u003C__tiddler__>get[text]] }}}/>\u003C/$list>\n\n\\define input-accept-variant-actions() \u003C$list filter=\"[{$:/config/Search/NavigateOnEnter/enable}match[yes]]\" emptyMessage=\"\"\"\u003C$list filter=\"[\u003C__tiddler__>get[text]!is[missing]] ~[\u003C__tiddler__>get[text]is[shadow]]\">\u003C$list filter=\"[\u003C__tiddler__>get[text]minlength[1]]\">\u003C$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{ [\u003C__tiddler__>get[text]] }}}/>\u003C/$list>\u003C/$list>\"\"\">\u003C$list filter=\"[\u003C__tiddler__>get[text]minlength[1]]\">\u003C$action-sendmessage $message=\"tm-edit-tiddler\" $param={{{ [\u003C__tiddler__>get[text]] }}}/>\u003C/$list>\u003C/$list>\n\n\\define set-next-input-tab(beforeafter:\"after\") \u003C$macrocall $name=\"change-input-tab\" stateTitle=\"$:/state/tab/search-results/sidebar\" tag=\"$:/tags/SearchResults\" beforeafter=\"$beforeafter$\" defaultState={{$:/config/SearchResults/Default}} actions=\"\"\"\u003C$action-setfield $tiddler=\"$:/state/search/currentTab\" text=\u003C\u003CnextTab>>/>\"\"\"/>\n\n\\define advanced-search-actions() \u003C$action-setfield $tiddler=\"$:/temp/advancedsearch\" text={{$:/temp/search/input}}/>\u003C$action-setfield $tiddler=\"$:/temp/advancedsearch/input\" text={{$:/temp/search/input}}/>\u003C\u003Cdelete-state-tiddlers>>\u003C$action-navigate $to=\"$:/AdvancedSearch\"/>\u003C$action-setfield $tiddler=\"$:/temp/advancedsearch/refresh\" text=\"yes\"/>\u003C$action-sendmessage $message=\"tm-focus-selector\" $param=\"\"\"[data-tiddler-title=\"$:/AdvancedSearch\"] .tc-search input\"\"\" preventScroll=\"true\"/>\u003C$action-de
|
|
|
|
|
{"created":"20230930051028154","text":"\u003C!--\n\n\u003Cdiv class=\"tc-site-subtitle\">\n\n\u003C$transclude tiddler=\"$:/SiteSubtitle\" mode=\"inline\"/>\n\n\u003C/div>\n\n-->","title":"$:/core/ui/SideBarSegments/site-subtitle","tags":"$:/tags/SideBarSegment","modified":"20230930051037150"},
|
|
|
|
|
{"created":"20230930051008081","text":"\u003C!--\n\n\u003Ch1 class=\"tc-site-title\">\n\n\u003C$transclude tiddler=\"$:/SiteTitle\" mode=\"inline\"/>\n\n\u003C/h1>\n\n-->","title":"$:/core/ui/SideBarSegments/site-title","tags":"$:/tags/SideBarSegment","modified":"20230930051016972"},
|
|
|
|
|
{"created":"20230930050725457","text":"\u003C!--\n\n\u003Cdiv class=\"tc-sidebar-lists tc-sidebar-tabs\" role=\"region\" aria-label={{$:/language/SideBar/Caption}}>\n\n\u003C$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\" explicitState=\"$:/state/tab/sidebar--595412856\"/>\n\n\u003C/div>\n\n-->","title":"$:/core/ui/SideBarSegments/tabs","tags":"$:/tags/SideBarSegment","modified":"20230930050735988"},
|
|
|
|
|
{"created":"20230928051519736","text":"\u003C!--\\whitespace trim\n\u003C$reveal type=\"nomatch\" stateTitle=\u003C\u003Cfolded-state>> text=\"hide\" tag=\"div\" retain=\"yes\" animate=\"yes\">\n\u003Cdiv class=\"tc-subtitle\">\n\u003C$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewTemplate/Subtitle]!has[draft.of]]\" variable=\"subtitleTiddler\" counter=\"indexSubtitleTiddler\">\n\u003C$list filter=\"[\u003CindexSubtitleTiddler-first>match[no]]\" variable=\"ignore\">\n \n\u003C/$list>\n\u003C$transclude tiddler=\u003C\u003CsubtitleTiddler>> mode=\"inline\"/>\n\u003C/$list>\n\u003C/div>\n\u003C/$reveal>\n-->","title":"$:/core/ui/ViewTemplate/subtitle","tags":"$:/tags/ViewTemplate","modified":"20230928051529190"},
|
|
|
|
|
{"created":"20230928050424077","text":"\u003C!--\n\u003C$view field=\"modified\" format=\"date\" template={{$:/language/Tiddler/DateFormat}}/>\n-->","title":"$:/core/ui/ViewTemplate/subtitle/modified","tags":"$:/tags/ViewTemplate/Subtitle","modified":"20230928050437446"},
|
|
|
|
|
{"created":"20231001053317652","text":"\u003C!--\n\\whitespace trim\n\u003C$reveal type=\"nomatch\" stateTitle=\u003C\u003Cfolded-state>> text=\"hide\" tag=\"div\" retain=\"yes\" animate=\"yes\">\n\u003Cdiv class=\"tc-tags-wrapper\">\u003C$list filter=\"[all[current]tags[]sort[title]]\" template=\"$:/core/ui/TagTemplate\" storyview=\"pop\"/>\u003C/div>\n\u003C/$reveal>\n-->","title":"$:/core/ui/ViewTemplate/tags","tags":"$:/tags/ViewTemplate","modified":"20231001053329116"},
|
|
|
|
|
{"created":"20230930063938280","text":"\u003C!--\n\n\\whitespace trim\n\\define title-styles()\nfill:$(foregroundColor)$;\n\\end\n\u003Cdiv class=\"tc-tiddler-title\">\n\u003Cdiv class=\"tc-titlebar\">\n\u003Cspan class=\"tc-tiddler-controls\">\n\u003C$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]] :filter[lookup[$:/config/ViewToolbarButtons/Visibility/]!match[hide]]\" storyview=\"pop\" variable=\"listItem\">\u003C$set name=\"tv-config-toolbar-class\" filter=\"[\u003Ctv-config-toolbar-class>] [\u003ClistItem>encodeuricomponent[]addprefix[tc-btn-]]\">\u003C$transclude tiddler=\u003C\u003ClistItem>>/>\u003C/$set>\u003C/$list>\n\u003C/span>\n\u003C$set name=\"tv-wikilinks\" value={{$:/config/Tiddlers/TitleLinks}}>\n\u003C$link>\n\u003C$list filter=\"[\u003CcurrentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] +[!is[blank]]\" variable=\"ignore\">\n\u003C$let foregroundColor={{{ [\u003CcurrentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}>\n\u003Cspan class=\"tc-tiddler-title-icon\" style=\u003C\u003Ctitle-styles>>>\n{{||$:/core/ui/TiddlerIcon}}\n\u003C/span>\n\u003C/$let>\n\u003C/$list>\n\u003C$transclude tiddler={{{ [\u003CcurrentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/ViewTemplateTitleFilter]!is[draft]get[text]] :and[!is[blank]else[$:/core/ui/ViewTemplate/title/default]] }}} />\n\u003C/$link>\n\u003C/$set>\n\u003C/div>\n\n\u003C$reveal type=\"nomatch\" text=\"\" default=\"\" state=\u003C\u003CtiddlerInfoState>> class=\"tc-tiddler-info tc-popup-handle\" animate=\"yes\" retain=\"yes\">\n\n\u003C$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TiddlerInfoSegment]!has[draft.of]] [[$:/core/ui/TiddlerInfo]]\" variable=\"listItem\">\u003C$transclude tiddler=\u003C\u003ClistItem>> mode=\"block\"/>\u003C/$list>\n\n\u003C/$reveal>\n\u003C/div>\n\n-->","title":"$:/core/ui/ViewTemplate/title","tags":"$:/tags/ViewTemplate","modified":"20230930063950278"},
|
|
|
|
|
{"title":"$:/core/ui/ViewTemplate/title/default","text":"\\whitespace trim\n\u003Ch2 class=\"tc-title\">\n\u003C$view field=\"title\"/>\n\u003C/h2>\n"},
|
|
|
|
|
{"created":"20230927063326064","title":"$:/DefaultTiddlers","text":"copinchapedia\ncopincha\ncopincha--mapa","modified":"20230930061940172"},
|
|
|
|
|
{"title":"$:/favicon.ico","type":"image/x-icon","text":"AAABAAEAAAAAAAEAIABxrwEAFgAAAIlQTkcNChoKAAAADUlIRFIAAAJEAAACRAgGAAAA9+A7WgAAIABJREFUeJzsvXmYXOV95/s5S51aetNuJBAYCUkgFmFsE3AwxhCwnQmZiY0x9p3rubHH12P73iR3nuTemcdPcnMzmbETPInH4JjFjAVILEaA2JERqxASEkKtfd9aLbXU+1Jd61nuH+953zpVXa21perl/eg5T7eqa/nVqVPn/Z7fagRBgEaj0Wg0Gs1Exqy1ARqNRqPRaDS1RgsijUaj0Wg0Ex4tiDQajUaj0Ux4tCDSaDQajUYz4dGCSKPRaDQazYRHCyKNRqPRaDQTHi2INBqNRqPRTHi0INJoNBqNRjPh0YJIo9FoNBrNhMeutQEajWZMYAPTgWnAVGAKMBmYFG6N4dYA1AN1QApIAgkgHm6xcLPCzQSM8DUCwAe8cCuGWz7cckAWyACDQBoYAPrDrTfceoBuoAvoBDoAd4T3h0ajGWcYenSHRjPhmR1uFwEXArOAmeF2ATADIYTGMp1AO3AMaAu3o8ARoBU4HG4ajWaCogWRRjP+mQRcFm5zgEvD7ZJwi9XOtFFFETgUbgfCbT+wN9x6a2eaRqM512hBpNGMHy4Brgi3BeE2H+Hx0Zw9R4HdwK5w2xFuh2pplEajGRm0INJoxh4NwDXhdjVwFXAlIq9Hc/7pBrYBW4EtwOZwG6ilURqN5vTQgkijGd00AJ8GrgM+BVyLEECa0c9WoBnYCHwMbECLJI1m1KIFkUYzurgGuB74bLh9qrbmaEaYjcD6cFuH8CRpNJpRgBZEGk3tsIHfB24MtxsQFV2aiUM7sBZYE26r0S0CNJqaoAWRRnP+sICbgc8DNyHEUKqmFmlGGxmEKHofWAW8h+jJpNFozjFaEGk055bPALcAXwi3hppaoxlrDADvhts7wEc1tUajGcdoQaTRjCwXALeF262IUniNZqQ4BLwFvBlux2prjkYzftCCSKM5ez4D3AHcjvAGaTTni3eAN4Dfob1HGs1ZoQWRRnNmfDncvgRcXmNbNBqAncAK4PVw02g0p4EWRBrNqREH/lW4/SEiNKbRjFaOAa8Cr4RbvrbmaDSjHy2INJrhiQN3htsfoTtBa8Ym3cDLwEvhpsWRRlMFLYg0mqHcCfwb4I8Z+1PeNZooncCLwHKEONJoNCFaEGk0gpuBryKEkK4M00wEDiGE0XOIfkcazYRGCyLNRGYB8LVwu67Gtmg0teRj4Nlw21VjWzSamqAFkWaiEQe+DtyNCI1pNJpyXgJ+CzyDzjfSTCC0INJMFH4P+AZCCF1YY1s0mrHAEYQwehr4sMa2aDTnHC2INOOZJPBN4B5E00SNRnNmvAE8BTwJZGtsi0ZzTtCCSDMeuQb4X4BvARfV2BaNZjzRCjwBLAU219gWjWZE0YJIM57418C/Be6qtSEazQRgGbAEeKHWhmg0I4EWRJqxTgPw7XC7vsa2aDQTkXXAY+E2UGNbNJozRgsizVjlMuDfhdvsGtui0WjgMPBouO2tsS0azWmjBZFmrPF7wP8G/CmihF6j0Ywu8sBvgMXo6jTNGEILIs1Y4XbgO4iKMY1GMzZ4CvifiCo1jWZUowWRZrTzr4HvopsoajRjmZeAR9AJ2JpRjBZEmtHK14F/D9xRa0M0Gs2I8Tvg14gu2BrNqEILIs1o4xvA94Dbam2IRqM5Z7wJPIzogq3RjAq0INKMFu4Cvg/8Qa0N0Wg0542VwIOInkYaTU3RgkhTa/4Y+A/AV2ptiEajqRmvAQ8AL9baEM3ERQsiTa34A+AHwFdrbYhGoxk1PAf8CuE50mjOK1oQac431wM/RDRU1Gg0mmo8CvwLogu2RnNe0IJIc764DPgR8H8Ado1t0Wg0ox8XuB/4JbrzteY8oAWR5lzTCPyfCCF0QY1t0Wg0Y49jCGF0H9BfY1s04xgtiDTnku8gxNC1tTZEo9GMeZoRouh/1toQzfhECyLNueAO4M+Af1VrQzQazbjjFeAXiCaPGs2IoQWRZiSZD/w5Imlao9FoziX/AvwPYHetDdGMD7Qg0owEJvB/AX8BXFRjWzQazcShFfg58M+AX2NbNGMcLYg0Z8udCDH0xVobUkvk98gwjKp/932/7G/D3U+jgdLxBKVjpdoxFgQBQRBgmub5NXD08TZCFL1Ua0M0YxctiDRnylzgP6LDY8NS7bulhZCmGkEQDBE6EsMwqgqk4R47wfkX4J+AfbU2RDP20IJIcyb8ACGGLqu1IaOV6PdKX8FrTpXhhI8WRKfFXoQo+lWtDdGMLbQg0pwONwJ/iR63ccqcLJSm0ZwtWhANy3PAz4A1tTZEMzbQgkhzKsQRQugvgUk1tmVUooWP5nxyIo+RpoxehCj6GZCvsS2aUY4WRJqTcTvwV+FPzTCcTBBVfs/0IqaJUi2HSN4mc4gqk6sl+lg6Jd4A7g1/ajRV0YJIMxwNCCH0fyM8RJpTpDJ/KPpTLnDyd40GRBWizDMLggDf95UIMk0T13XV79FjSHNa5IF/RAijgRrbohmFaEGkqcaXEELo1lobMhaRV/eVYghKgkiLIk0Uz/OU2AmCAM/zygRRLpfDsixs28ayrFqbO9Z5CyGMVtTaEM3oQpe+aKIkgb8FlqPFUBlRgRP9f7ULCrmQWZaF53kMDg5SLBaxbRvf9ykWi2WhENd1z+db0YxCoiI5CAJs26ZQKKjbfN9Xx49E/u55Xtlt0fvI56v8/wS/EL4VcY77W8Q5T6MBtIdIU+IW4P8BvlxjO0Yl0ZCG/H/lIuZ5nhJCIBYquVi5rotpmuo5TNPEsiwMwxjy3JrxT7Xzbj6fJ5FIqL8XCgV1jEgP0uDgIJZlUVdXN+R4O9Fzn2oJ/wTkdeAfgHdqbIdmFKDPwhoQ1WPL0GJoWCoXlGpiSIYzPM+jWCwC4DgOjuOUXblXLkJaDGkMw8C27bL/+77P4OCgus22bWzbVoJGHm+u65Z5hSpDspXH23DiaILyZcS57y9rbYim9mgP0cTmGuA/A/fU2pDRjBRAUUFzomoy2YjRdV3a29s5duwYsViMOXPmKHEUj8eHPE5frU885Pm3UCgQj8fxfZ9CoUAikaBYLCrP0IYNG0gmk8yaNYvp06cPW3l2qseQrlSrylPAT4DNtTZEUxusv/3bv621DZra8O+AXyBCZZoqVMsZkomvUMrdkCENWQlkWRbpdJqPPvqIZ555hieeeIJ0Os0VV1zBpEmTcF13SD5IFL04jT+GEyzRJHvTNJVn0fd9HMfBsixWrVrFT37yE9avX08qlWLu3LnYtq0Sr6tVp0VfV4bWqr1m9DYNVyHyiwaATTW2RVMD7JPfRTPOmIbwCv3HWhsylpAiJpoILfOI5ILkOA75fJ7Nmzfz9ttv89Zbb/Hxxx/T1tbG0aNHueGGG5g1axaO4+B5Hr7vY1mW+qmZmARBoER0LBYjHo+TyWRwHIfu7m6effZZXnvtNWKxGD09PRw8eJBrr72Wa6+9lunTp5cJocoNKCvXl6+nqxyHZQGwGOE9/wnQWVNrNOcV7SGaWNwC/Bz4tzW2Y9RTGVKIVvnk83klYjzPI51Ok81m6ejo4IMPPmDJkiUsXbqUjz76iHQ6jeM49Pb2MnPmTObOncukSZPKru6rzTrTC9X4olqYVeaVBUFAJpNhYGAA27aJxWIYhkFnZycrV67k2Wefpbe3l2KxSEtLC++//z579uwhm82q8JrMP5LeykKhUOaxrBRA+vg6KTcCnwIOAwdra4rmfKEF0cThRwgxdG2tDRlrRPvBFAoFMpkMlmWpPI+uri42btzIG2+8wdNPP80777xDe3s7lmWppFdZSj1//nxmz54NlK7cpSjSIYyJg/TgSFEUj8dJJpPE43EKhQK2bbNmzRruu+8+mpubyWQyxGIxbNtmcHCQzs5ONmzYwM6dO6mvr2fevHnqeJN5SJ7nEYvFSCQSVXthaU7KXOAOREPH9TW2RXMe0CGz8c9M4McIQTRhqVZqHBUhlRVglRVkhUKBVCqF7/skEgl
|
|
|
|
|
{"title":"$:/Import","text":"The following tiddlers were imported:\n\n# [[$:/core/ui/ViewTemplate/tags]]","status":"complete"},
|
|
|
|
|
{"title":"$:/isEncrypted","text":"no"},
|
|
|
|
|
{"created":"20230927221145042","title":"$:/palette","text":"$:/palettes/copincha","modified":"20230927221145042"},
|
|
|
|
|
{"created":"20230927220926364","text":"alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #ffffff\nbackground: #ffffff\nblockquote-bar: \u003C\u003Ccolour muted-foreground>>\nbutton-background: \nbutton-foreground: \nbutton-border: \ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndiff-delete-background: #ffc9c9\ndiff-delete-foreground: \u003C\u003Ccolour foreground>>\ndiff-equal-background: \ndiff-equal-foreground: \u003C\u003Ccolour foreground>>\ndiff-insert-background: #aaefad\ndiff-insert-foreground: \u003C\u003Ccolour foreground>>\ndiff-invisible-background: \ndiff-invisible-foreground: \u003C\u003Ccolour muted-foreground>>\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: \u003C\u003Ccolour background>>\ndragger-background: \u003C\u003Ccolour foreground>>\ndragger-foreground: \u003C\u003Ccolour background>>\ndropdown-background: #000000\ndropdown-border: #000000\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: #4e4e4e\nhighlight-background: #ffff00\nhighlight-foreground: #000000\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: #000000\nmodal-background: #000000\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #000000\nnetwork-activity-foreground: #448844\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #f5f2e9\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #5778d8\nselection-background: \nselection-foreground: \nselect-tag-background: \nselect-tag-foreground: \nsidebar-button-foreground: \u003C\u003Ccolour 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: \u003C\u003Ccolour tab-border-selected>>\nsidebar-tab-border: \u003C\u003Ccolour tab-border>>\nsidebar-tab-divider: #e4e4e4\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: \u003C\u003Ccolour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #999999\nsite-title-foreground: \u003C\u003Ccolour 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: \u003C\u003Ccolour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ec6\ntag-foreground: #ffffff\ntiddler-background: #f5f2e9\ntiddler-border: #f5f2e9\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #4e4e4e\ntiddler-editor-background: #f5f2e9\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #888888\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: \u003C\u003Ccolour background>>\ntiddler-link-foreground: \u003C\u003Ccolour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #2b2b2b\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\nwikili
|
|
|
|
|
{"text":"{\n \"tiddlers\": {\n \"$:/plugins/felixhayashi/respawn/respawn.js\": {\n \"title\": \"$:/plugins/felixhayashi/respawn/respawn.js\",\n \"text\": \"/*\\\\\\n\\ntitle: $:/plugins/felixhayashi/respawn/respawn.js\\ntype: application/javascript\\nmodule-type: startup\\n\\n@preserve\\n\\n\\\\*/\\n\\n(function(){\\n \\n /*jslint node: true, browser: true */\\n /*global $tw: false */\\n \\\"use strict\\\";\\n \\n var configTRef = \\\"$:/plugins/felixhayashi/respawn/config\\\";\\n \\n var changeListener = function(changedTiddlers) {\\n \\n if(!changedTiddlers[\\\"$:/StoryList\\\"]) return;\\n \\n var tObj = $tw.wiki.getTiddler(\\\"$:/StoryList\\\");\\n if(tObj && !tObj.fields[\\\"list\\\"].length) {\\n \\n var confTObj = $tw.wiki.getTiddler(configTRef);\\n var config = confTObj ? confTObj.fields : {};\\n \\n window.setTimeout(function() {\\n $tw.rootWidget.dispatchEvent({\\n type: \\\"tm-home\\\"\\n });\\n }, parseInt(config.delay) || 500);\\n }\\n \\n };\\n \\n exports.name = \\\"respawn\\\";\\n exports.platforms = [\\\"browser\\\"];\\n exports.after = [\\\"story\\\"];\\n exports.synchronous = true;\\n \\n exports.startup = function() {\\n \\n $tw.wiki.addEventListener(\\\"change\\\", changeListener);\\n \\n };\\n\\n})();\\n\",\n \"type\": \"application/javascript\",\n \"module-type\": \"startup\"\n },\n \"$:/plugins/felixhayashi/respawn/Configuration\": {\n \"title\": \"$:/plugins/felixhayashi/respawn/Configuration\",\n \"text\": \"\u003C!-- The config output is not written to this tiddler! -->\\n\\nPlease see the [[GitHub page|https://github.com/felixhayashi/TW5-Respawn]] for more information on the options.\\n\\nYou may have to save and reload the wiki to activate changes.\\n\\n\u003Ctable>\\n \u003Ctr>\\n \u003Cth align=\\\"left\\\">Delay (seconds):\u003C/th>\\n \u003Ctd>\\n \u003C$edit-text\\n tiddler=\\\"$:/plugins/felixhayashi/respawn/config\\\"\\n field=\\\"delay\\\"\\n tag=\\\"input\\\"\\n default=\\\"500\\\" />\\n \u003C/td>\\n \u003C/tr>\\n\u003C/table>\"\n },\n \"$:/plugins/felixhayashi/respawn/License\": {\n \"title\": \"$:/plugins/felixhayashi/respawn/License\",\n \"text\": \"This code is released under the BSD license. For the exact terms visit:\\n\\nhttps://github.com/felixhayashi/TW5-Respawn/blob/master/LICENSE\"\n },\n \"$:/plugins/felixhayashi/respawn/Readme\": {\n \"title\": \"$:/plugins/felixhayashi/respawn/Readme\",\n \"text\": \"Please visit the [[GitHub page|https://github.com/felixhayashi/TW5-Respawn]] for more information.\"\n }\n }\n}","version":"0.0.3","type":"application/json","title":"$:/plugins/felixhayashi/respawn","source":"https://github.com/felixhayashi/TW5-respawn","released":"","plugin-type":"plugin","list":"Configuration License Readme","description":"Respawn – Open default tiddlers when river is empty","dependents":"","core-version":">=5.1.5","author":"Felix Küppers"},
|
|
|
|
|
{"text":"{\n \"tiddlers\": {\n \"$:/plugins/felixhayashi/topstoryview/config.js\": {\n \"text\": \"/*\\\\\\n\\ntitle: $:/plugins/felixhayashi/topstoryview/config.js\\ntype: application/javascript\\nmodule-type: library\\n\\n@preserve\\n\\n\\\\*/\\n(function(){\\\"use strict\\\";exports.config={classNames:{storyRiver:\\\"tc-story-river\\\",backDrop:\\\"story-backdrop\\\",tiddlerFrame:\\\"tc-tiddler-frame\\\",tiddlerTitle:\\\"tc-title\\\"},references:{userConfig:\\\"$:/config/topStoryView\\\",focussedTiddlerStore:\\\"$:/temp/focussedTiddler\\\",refreshTrigger:\\\"$:/temp/focussedTiddler/refresh\\\"},checkbackTime:$tw.utils.getAnimationDuration()}})();\",\n \"title\": \"$:/plugins/felixhayashi/topstoryview/config.js\",\n \"type\": \"application/javascript\",\n \"module-type\": \"library\"\n },\n \"$:/plugins/felixhayashi/topstoryview/layout\": {\n \"title\": \"$:/plugins/felixhayashi/topstoryview/layout\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"tags\": [\n \"$:/tags/Stylesheet\"\n ],\n \"text\": \"html .tc-story-river:after {\\n content: \\\"\\\";\\n display: block; }\\n\"\n },\n \"$:/plugins/felixhayashi/topstoryview/Configuration\": {\n \"title\": \"$:/plugins/felixhayashi/topstoryview/Configuration\",\n \"text\": \"Please see the [[GitHub page|https://github.com/felixhayashi/TW5-TopStoryView]] for more information on the options.\\n\\nSave and reload the wiki to activate changes.\\n\\n\u003Ctable>\\n \u003Ctr>\\n \u003Cth align=\\\"left\\\">Scroll offset:\u003C/th>\\n \u003Ctd>\u003C$edit-text tiddler=\\\"$:/config/topStoryView\\\" field=\\\"scroll-offset\\\" tag=\\\"input\\\" default=\\\"150px\\\" />\u003C/td>\\n \u003C/tr>\\n\u003C/table>\"\n },\n \"$:/plugins/felixhayashi/topstoryview/License\": {\n \"title\": \"$:/plugins/felixhayashi/topstoryview/License\",\n \"text\": \"This code is released under the BSD license. For the exact terms visit:\\n\\nhttps://github.com/felixhayashi/TW5-TopStoryView/blob/master/LICENSE\"\n },\n \"$:/plugins/felixhayashi/topstoryview/Readme\": {\n \"title\": \"$:/plugins/felixhayashi/topstoryview/Readme\",\n \"text\": \"Please visit the [[GitHub page|https://github.com/felixhayashi/TW5-TopStoryView]] for more information.\"\n },\n \"$:/plugins/felixhayashi/topstoryview/top.js\": {\n \"text\": \"/*\\\\\\ntitle: $:/plugins/felixhayashi/topstoryview/top.js\\ntype: application/javascript\\nmodule-type: storyview\\n\\nViews the story as a linear sequence\\n\\n@preserve\\n\\n\\\\*/\\n(function(){\\\"use strict\\\";var t=require(\\\"$:/plugins/felixhayashi/topstoryview/config.js\\\").config;var e=\\\"cubic-bezier(0.645, 0.045, 0.355, 1)\\\";var i=function(e){this.listWidget=e;this.pageScroller=new $tw.utils.PageScroller;this.pageScroller.scrollIntoView=this.scrollIntoView;this.pageScroller.storyRiverDomNode=document.getElementsByClassName(t.classNames.storyRiver)[0];var i=$tw.wiki.getTiddler(t.references.userConfig);var o=i?i.fields:{};$tw.hooks.addHook(\\\"th-opening-default-tiddlers-list\\\",this.hookOpenDefaultTiddlers);var r=parseInt(o[\\\"scroll-offset\\\"]);this.pageScroller.scrollOffset=isNaN(r)?71:r;this.recalculateBottomSpace()};i.prototype.refreshStart=function(t,e){};i.prototype.refreshEnd=function(t,e){};i.prototype.hookOpenDefaultTiddlers=function(t){return t};i.prototype.navigateTo=function(t){var e=this.listWidget.findListItem(0,t.title);if(e===undefined)return;var i=this.listWidget.children[e];var o=i.findFirstDomNode();if(!(o instanceof Element))return;this.pageScroller.scrollIntoView(o)};i.prototype.insert=function(t){if(!t)return;var e=t.findFirstDomNode();if(!(e instanceof Element))return;this.startInsertAnimation(e,function(){this.recalculateBottomSpace()}.bind(this))};i.prototype.remove=function(t){if(!t)return;var e=t.findFirstDomNode();if(!(e instanceof Element)){t.removeChildDomNodes();return
|
|
|
|
|
{"text":"{\n \"tiddlers\": {\n \"GeoTiddler\": {\n \"title\": \"GeoTiddler\",\n \"created\": \"20151130173416239\",\n \"modified\": \"20170115153450584\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"[[GeoTiddler]]s are tiddlers containing geographical data. [[geoSyntax|$:/plugins/sycom/leaflet/geoSyntax]] lists the available objects. [[geoJson|https://en.wikipedia.org/wiki/GeoJSON]] data are also accepted. You may specify a color for all objects displayed through `color` field.\\n\\n!! tiddler with geo TiddlerFields\\nYou can upgrade your tiddler by putting some geo metadata ([[wgs 84 coordinates|https://en.wikipedia.org/wiki/World_Geodetic_System#WGS84]]) in it's TiddlerFields. See [[geoSyntax|$:/plugins/sycom/leaflet/geoSyntax]] for the list of object types you can draw. Popup will show the first part of the tiddler. If the tiddler contains a leafmap widget, it will be rendered as `text/plain` in order to avoid crash...\\n\\n!! geoJSON tiddler\\nYou can define a geoJson tiddler like [[tiddlyWikiFrCommunity|$:/plugins/sycom/leaflet/example/tiddlyWikiFrCommunity]] and then display the data by calling it. Just put your geoJson data in the body and declare the tiddler as application/json. Any `application/json` tiddler called will be considered as geoJson. The popups will show\\n\\n* a title\\n** the `name` or the `title` attribute in properties if exists,\\n** if not, the firsts attributes of properties until they are 8 characters long\\n* a description\\n** the `description` attribute in properties if exists,\\n** if not, the data stored in each feature as a bulleted list.\\n\\n!! tiddler grouping [[GeoTiddler]]s\\nYou can use `tiddlers` or `filter` as TiddlerFields to make a group of tiddlers. You can apply some styling options to all the group using `style`, `color` or `marker` TiddlerFields and then call the tiddler in your map to render all those tiddler at the same time. This will be a good way to make thematic maps indeed...\\n\"\n },\n \"$:/plugins/sycom/leaflet/devDiary\": {\n \"title\": \"$:/plugins/sycom/leaflet/devDiary\",\n \"created\": \"20151110173416000\",\n \"modified\": \"20180531171500000\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"Some notes about coding this plugin. Might be useful to others...\\n\\n* 20180602\\n** added a template that will display a map of embeded object for tiddlers containing one of the geoTiddlers fiels.\\n** updtated leaflet and marker-cluster to 1.3.1 - the easy way. Just replaced with new version and no deprecation at all \\\\o/ !\\n* 20180531\\n** converting all `.svg.tid` files to `.svg` + `.svg.meta` pairs. Will allow git client to make svg viewable in web interface. Also compressed SVG as much as possible with great https://jakearchibald.github.io/svgomg/ tool.\\n** tweak : for svg embedding local TiddlyWiki colors (eg `$primary$`), forced type to `text/vnd.tiddlywiki` to preserve them.\\n* 20170317\\n** lot of work around cluster size, cluster color when using filter. Cluster size depends on point % for the cluster, clusterRadius and zoom.\\n* 20170311\\n** added styling options and also the grouping tiddler capabilities. Discovered that direct styling in SVG ''does not always'' [[overwrite css styling|http://stackoverflow.com/questions/24293880/svg-why-does-external-css-override-inline-style-for-text]].\\n* 20170129\\n** adding some markers. And it's possible to create yours.\\n* 20170115\\n** darling birthday edit. Clustering by tiddler is on track. Will have to look for clustering direct passing object through widget.\\n* 20161111\\n** armistice edit! can now disable clustering or set clustering distance. Bug #9 fixed. may be cluster size will be too big for big databases\\n* 20161106\\n** color parameter is partially implemented. Note that direct styling like `fill` in svg element wont take on class styling through css...\\n* 20161104\\n** after many attemps, managed to include tiddler excerpt in popups for mapping ge
|
|
|
|
|
{"created":"20210808053648139","text":"/* required styles */\n\n.leaflet-pane,\n.leaflet-tile,\n.leaflet-marker-icon,\n.leaflet-marker-shadow,\n.leaflet-tile-container,\n.leaflet-pane > svg,\n.leaflet-pane > canvas,\n.leaflet-zoom-box,\n.leaflet-image-layer,\n.leaflet-layer {\n position: absolute;\n left: 0;\n top: 0;\n }\n.leaflet-container {\n overflow: hidden;\n }\n.leaflet-tile,\n.leaflet-marker-icon,\n.leaflet-marker-shadow {\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n -webkit-user-drag: none;\n }\n/* Safari renders non-retina tile on retina better with this, but Chrome is worse */\n.leaflet-safari .leaflet-tile {\n image-rendering: -webkit-optimize-contrast;\n }\n/* hack that prevents hw layers \"stretching\" when loading new tiles */\n.leaflet-safari .leaflet-tile-container {\n width: 1600px;\n height: 1600px;\n -webkit-transform-origin: 0 0;\n }\n.leaflet-marker-icon,\n.leaflet-marker-shadow {\n display: block;\n }\n/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */\n/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */\n.leaflet-container .leaflet-overlay-pane svg,\n.leaflet-container .leaflet-marker-pane img,\n.leaflet-container .leaflet-shadow-pane img,\n.leaflet-container .leaflet-tile-pane img,\n.leaflet-container img.leaflet-image-layer {\n max-width: none !important;\n max-height: none !important;\n }\n\n.leaflet-container.leaflet-touch-zoom {\n -ms-touch-action: pan-x pan-y;\n touch-action: pan-x pan-y;\n }\n.leaflet-container.leaflet-touch-drag {\n -ms-touch-action: pinch-zoom;\n /* Fallback for FF which doesn't support pinch-zoom */\n touch-action: none;\n touch-action: pinch-zoom;\n}\n.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {\n -ms-touch-action: none;\n touch-action: none;\n}\n.leaflet-container {\n -webkit-tap-highlight-color: transparent;\n}\n.leaflet-container a {\n -webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);\n}\n.leaflet-tile {\n filter: inherit;\n visibility: hidden;\n }\n.leaflet-tile-loaded {\n visibility: inherit;\n }\n.leaflet-zoom-box {\n width: 0;\n height: 0;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n z-index: 800;\n }\n/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */\n.leaflet-overlay-pane svg {\n -moz-user-select: none;\n }\n\n.leaflet-pane { z-index: 400; }\n\n.leaflet-tile-pane { z-index: 200; }\n.leaflet-overlay-pane { z-index: 400; }\n.leaflet-shadow-pane { z-index: 500; }\n.leaflet-marker-pane { z-index: 600; }\n.leaflet-tooltip-pane { z-index: 650; }\n.leaflet-popup-pane { z-index: 700; }\n\n.leaflet-map-pane canvas { z-index: 100; }\n.leaflet-map-pane svg { z-index: 200; }\n\n.leaflet-vml-shape {\n width: 1px;\n height: 1px;\n }\n.lvml {\n behavior: url(#default#VML);\n display: inline-block;\n position: absolute;\n }\n\n\n/* control positioning */\n\n.leaflet-control {\n position: relative;\n z-index: 800;\n pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */\n pointer-events: auto;\n }\n.leaflet-top,\n.leaflet-bottom {\n position: absolute;\n z-index: 1000;\n pointer-events: none;\n }\n.leaflet-top {\n top: 0;\n }\n.leaflet-right {\n right: 0;\n }\n.leaflet-bottom {\n bottom: 0;\n }\n.leaflet-left {\n left: 0;\n }\n.leaflet-control {\n float: left;\n clear: both;\n }\n.leaflet-right .leaflet-control {\n float: right;\n }\n.leaflet-top .leaflet-control {\n margin-top: 10px;\n }\n.leaflet-bottom .leaflet-control {\n margin-bottom: 10px;\n }\n.leaflet-left .leaflet-control {\n margin-left: 10px;\n }\n.leaflet-right .leaflet-control {\n margin-right: 10px;\n }\n\n\n/* zoom and fade animations */\n\n.leaflet-fade-anim .leaflet-tile {\n will-change: opacity;\n }\n.leaflet-fade-anim .leaflet-popup {\n opac
|
|
|
|
|
{"title":"$:/plugins/tiddlywiki/menubar","name":"Menu Bar","description":"Menu Bar","list":"readme config","version":"5.3.1","plugin-type":"plugin","dependents":"","type":"application/json","text":"{\"tiddlers\":{\"$:/config/DefaultColourMappings/menubar-foreground\":{\"title\":\"$:/config/DefaultColourMappings/menubar-foreground\",\"text\":\"#fff\"},\"$:/config/DefaultColourMappings/menubar-background\":{\"title\":\"$:/config/DefaultColourMappings/menubar-background\",\"text\":\"#5778d8\"},\"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/pagecontrols\":{\"title\":\"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/pagecontrols\",\"text\":\"hide\"},\"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/server\":{\"title\":\"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/server\",\"text\":\"hide\"},\"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/sidebar\":{\"title\":\"$:/config/plugins/menubar/MenuItems/Visibility/$:/plugins/tiddlywiki/menubar/items/sidebar\",\"text\":\"hide\"},\"$:/config/plugins/menubar/TableOfContents/Tag\":{\"title\":\"$:/config/plugins/menubar/TableOfContents/Tag\",\"text\":\"TableOfContents\"},\"$:/config/plugins/menubar/breakpoint\":{\"title\":\"$:/config/plugins/menubar/breakpoint\",\"text\":\"620px\"},\"$:/plugins/tiddlywiki/menubar/config\":{\"title\":\"$:/plugins/tiddlywiki/menubar/config\",\"tags\":\"$:/tags/ControlPanel/Toolbars\",\"caption\":\"Menu Bar\",\"text\":\"\\\\define config-base() $:/config/plugins/menubar/MenuItems/Visibility/\\n\\n! Menu Bar Configuration\\n\\n!! Menu Items\\n\\nSelect which menu items will be shown. You can also drag items to reorder them.\\n\\n\u003C$set name=\\\"tv-config-toolbar-icons\\\" value=\\\"yes\\\">\\n\\n\u003C$set name=\\\"tv-config-toolbar-text\\\" value=\\\"yes\\\">\\n\\n\u003C$macrocall $name=\\\"list-tagged-draggable\\\" tag=\\\"$:/tags/MenuBar\\\" itemTemplate=\\\"$:/core/ui/ControlPanel/Toolbars/ItemTemplate\\\"/>\\n\\n\u003C/$set>\\n\\n\u003C/$set>\\n\\n!! Breakpoint Position\\n\\nThe breakpoint position between narrow and wide screens. Should include CSS units (eg. `400px`).\\n\\n\u003C$edit-text tiddler=\\\"$:/config/plugins/menubar/breakpoint\\\" default=\\\"\\\" tag=\\\"input\\\"/>\\n\\n!! Contents Tag\\n\\nThe tag for the ~TableOfContents used in the Contents dropdown\\n\\n\u003C$edit-text tiddler=\\\"$:/config/plugins/menubar/TableOfContents/Tag\\\" default=\\\"\\\" tag=\\\"input\\\"/>\\n\\n!! Menu Bar Colours\\n\\nTo change the colour of the menu bar, define the colours `menubar-foreground` and `menubar-background` in the currently selected palette\\n\"},\"$:/plugins/tiddlywiki/menubar/items/contents\":{\"title\":\"$:/plugins/tiddlywiki/menubar/items/contents\",\"caption\":\"Contents\",\"description\":\"Table of Contents\",\"is-dropdown\":\"yes\",\"tags\":\"$:/tags/MenuBar\",\"text\":\"\u003Cdiv class=\\\"tc-table-of-contents\\\">\\n\\n\u003C$macrocall $name=\\\"toc-selective-expandable\\\" tag={{$:/config/plugins/menubar/TableOfContents/Tag}}/>\\n\\n\u003C/div>\\n\"},\"$:/plugins/tiddlywiki/menubar/items/hamburger\":{\"title\":\"$:/plugins/tiddlywiki/menubar/items/hamburger\",\"tags\":\"$:/tags/MenuBar\",\"caption\":\"Hamburger\",\"description\":\"Show the full menu bar on a narrow screen\",\"custom-menu-content\":\"{{$:/plugins/tiddlywiki/menubar/items/hamburger}}\",\"show-when\":\"narrow\",\"text\":\"\u003C$list filter=\\\"[[$:/state/popup/menubar/hamburger]get[text]else[no]match[no]]\\\">\\n\u003C$button set=\\\"$:/state/popup/menubar/hamburger\\\" setTo=\\\"yes\\\">\\n{{$:/core/images/menu-button}}\\n\u003C/$button>\\n\u003C/$list>\\n\u003C$list filter=\\\"[[$:/state/popup/menubar/hamburger]get[text]else[no]match[yes]]\\\">\\n\u003C$button set=\\\"$:/state/popup/menubar/hamburger\\\" setTo=\\\"no\\\">\\n{{$:/core/images/close-button}}\\n\u003C/$button>\\n\u003C/$list>\\n\"},\"$:/plugins/tiddlywiki/menubar/items/pagecontrols\":{\"title\":\"$:/plugins/tiddlywiki/me
|
|
|
|
|
{"created":"20230928091243648","text":"\n","title":"$:/plugins/tiddlywiki/menubar/items/about","caption":"About","description":"Table of Proyectos","is-dropdown":"yes","tags":"$:/tags/MenuBar","modified":"20230928091329047"},
|
|
|
|
|
{"created":"20230928091359995","text":"\u003Cdiv class=\"tc-table-of-contents\">\n\n\u003C\u003Ctoc-selective-expandable 'Actividades'>>\n\n\u003C/div>\n","title":"$:/plugins/tiddlywiki/menubar/items/actividades","caption":"Actividades","description":"Table of Proyectos","is-dropdown":"yes","tags":"$:/tags/MenuBar","modified":"20230928091829374"},
|
|
|
|
|
{"created":"20230928091435928","text":"\n","title":"$:/plugins/tiddlywiki/menubar/items/calendario","caption":"Calendario","description":"Table of Proyectos","is-dropdown":"yes","tags":"$:/tags/MenuBar","modified":"20230928091455399"},
|
|
|
|
|
{"created":"20230928091531502","text":"","title":"$:/plugins/tiddlywiki/menubar/items/contacto","caption":"Contactos","description":"Table of Proyectos","is-dropdown":"yes","tags":"$:/tags/MenuBar","modified":"20230928091605967"},
|
|
|
|
|
{"created":"20230928091916557","text":"","title":"$:/plugins/tiddlywiki/menubar/items/join","caption":"Unirse","description":"Table of Proyectos","is-dropdown":"yes","tags":"$:/tags/MenuBar","modified":"20230928092014541"},
|
|
|
|
|
{"created":"20231001043217539","text":"\u003Cdiv class=\"tc-table-of-contents\">\n\n\u003C\u003Ctoc-selective-expandable 'miembros'>>\n\n\u003C/div>\n","title":"$:/plugins/tiddlywiki/menubar/items/miembros","caption":"Miembros","description":"Sobre los miembros","is-dropdown":"yes","tags":"$:/tags/MenuBar","modified":"20231001043802179","list-before":"$:/plugins/tiddlywiki/menubar/items/join"},
|
|
|
|
|
{"created":"20230928090940096","text":"\u003Cdiv class=\"tc-table-of-contents\">\n\n\u003C\u003Ctoc-selective-expandable 'Proyectos'>>\n\n\u003C/div>\n","title":"$:/plugins/tiddlywiki/menubar/items/proyectos","caption":"Proyectos","description":"Table of Proyectos","is-dropdown":"yes","tags":"$:/tags/MenuBar","modified":"20230928091100434"},
|
|
|
|
|
{"created":"20230929093048647","text":"\n","title":"$:/plugins/tiddlywiki/menubar/items/search 1","custom-menu-content":"{{$:/plugins/tiddlywiki/menubar/items/search}}","description":"Search","caption":"Search","tags":"$:/tags/MenuBar","modified":"20230929093447396"},
|
|
|
|
|
{"created":"20230928091613323","text":"\u003Cdiv class=\"tc-table-of-contents\">\n\n\u003C\u003Ctoc-selective-expandable 'Servicios'>>\n\n\u003C/div>","title":"$:/plugins/tiddlywiki/menubar/items/servicios","caption":"Servicios","description":"Table of Proyectos","is-dropdown":"yes","tags":"$:/tags/MenuBar","modified":"20230928091642285"},
|
|
|
|
|
{"created":"20230928091653493","text":"\u003Cdiv class=\"tc-table-of-contents\">\n\n\u003C\u003Ctoc-selective-expandable 'Talleres'>>\n\n\u003C/div>","title":"$:/plugins/tiddlywiki/menubar/items/talleres","caption":"Talleres","description":"Table of Proyectos","is-dropdown":"yes","tags":"$:/tags/MenuBar","modified":"20230928091906040"},
|
|
|
|
|
{"created":"20231001020015937","text":"\\define menubar-inner(size)\n\u003Cul class=\"tc-menubar-list\">\n\u003C$list filter=\"[all[shadows+tiddlers]tag[$:/tags/MenuBar]!has[draft.of]] -[all[tiddlers+shadows]tag[$:/tags/TopLeftBar]limit[1]then[]else[$:/plugins/tiddlywiki/menubar/items/topleftbar]] -[all[tiddlers+shadows]tag[$:/tags/TopRightBar]limit[1]then[]else[$:/plugins/tiddlywiki/menubar/items/toprightbar]]\">\n\u003C$list filter=\"[\u003CcurrentTiddler>addprefix[$:/config/plugins/menubar/MenuItems/Visibility/]get[text]] ~show +[match[show]]\" variable=\"ignore\">\n\u003C$list filter=\"[[$size$]match[wide]] ~[\u003CcurrentTiddler>get[show-when]match[$size$]] ~[{$:/state/popup/menubar/hamburger}match[yes]]\" variable=\"ignore\">\n\u003Cli style={{!!custom-menu-styles-$size$}} class={{{ [\u003CcurrentTiddler>get[show-when]addprefix[tc-menubar-]] tc-menubar-item +[join[ ]] }}}>\n\u003C$list filter=\"[\u003CcurrentTiddler>!is-dropdown[yes]]\" variable=\"listItem\" emptyMessage=\"\"\"\n\t\u003C!-- Dropdown -->\n\t\u003C$set name=\"dropdown-state\" value=\u003C\u003Cqualify \"$:/state/popup/topmenu/dropdown/\">>>\n\t\u003C$set name=\"dropdown-state\" value={{{ [\u003Cdropdown-state>addsuffix\u003CcurrentTiddler>] }}}>\n\t\u003C$button popup=\u003C\u003Cdropdown-state>> selectedClass=\"tc-selected\">\n\t\u003C$set name=\"tv-wikilinks\" value=\"no\">\n\t\u003C$transclude field=\"caption\" mode=\"inline\"/>\n\t\u003C$text text=\" \"/>\n\t\u003Cspan class=\"tc-menubar-dropdown-arrow\">\n\t\u003C$transclude tiddler=\"$:/core/images/down-arrow\" mode=\"inline\"/>\n\t\u003C/span>\n\t\u003C/$set>\n\t\u003C/$button>\n\t\u003C/$set>\n\t\u003C/$set>\n\"\"\">\n\u003C$list filter=\"[\u003CcurrentTiddler>has[custom-menu-content]]\" variable=\"listItem\" emptyMessage=\"\"\"\n\t\u003C!-- Link -->\n\t\u003C$link to={{!!target}}>\n\t\u003C$set name=\"tv-wikilinks\" value=\"no\">\n\t\u003C$transclude field=\"caption\" mode=\"inline\"/>\n\t\u003C/$set>\n\t\u003C/$link>\n\"\"\">\n\u003C!-- Custom content -->\n\u003C$transclude field=\"custom-menu-content\" mode=\"inline\"/>\n\u003C/$list>\n\u003C/$list>\n\u003C/li>\n\u003C/$list>\n\u003C/$list>\n\u003C/$list>\n\u003Cbr>\n\u003C/ul>\n\n\\end\n\n\u003C$list filter=\"[\u003Ctv-config-static>!match[yes]]\" variable=\"ignore\">\n\u003C$list filter=\"[all[shadows+tiddlers]tag[$:/tags/MenuBar]!has[draft.of]] -[all[tiddlers+shadows]tag[$:/tags/TopLeftBar]limit[1]then[]else[$:/plugins/tiddlywiki/menubar/items/topleftbar]] -[all[tiddlers+shadows]tag[$:/tags/TopRightBar]limit[1]then[]else[$:/plugins/tiddlywiki/menubar/items/toprightbar]] +[limit[1]]\" variable=\"listItem\">\n\u003Cnav class=\"tc-menubar tc-adjust-top-of-scroll\">\n\u003Cdiv class=\"tc-menubar-narrow\">\n\u003C\u003Cmenubar-inner narrow>>\n\u003C/div>\n\u003Cdiv class=\"tc-menubar-wide\">\n\u003C\u003Cmenubar-inner wide>>\n\u003C/div>\n\u003Cdiv style=\"clear:both;\"/>\n\u003C$list filter=\"[all[shadows+tiddlers]tag[$:/tags/MenuBar]!has[draft.of]is-dropdown[yes]]\">\n\u003C$list filter=\"[\u003CcurrentTiddler>addprefix[$:/config/plugins/menubar/MenuItems/Visibility/]get[text]] ~show +[match[show]]\" variable=\"ignore\">\n\u003C$set name=\"dropdown-state\" value=\u003C\u003Cqualify \"$:/state/popup/topmenu/dropdown/\">>>\n\u003C$set name=\"dropdown-state\" value={{{ [\u003Cdropdown-state>addsuffix\u003CcurrentTiddler>] }}}>\n\u003C$reveal type=\"popup\" state=\u003C\u003Cdropdown-state>> position={{{ [\u003CcurrentTiddler>get[dropdown-position]else[below]] }}} class={{{ [\u003CcurrentTiddler>get[class]] }}} tag=\"div\">\n\u003Cdiv class=\"tc-drop-down\">\n\u003C$transclude/>\n\u003C/div>\n\u003C/$reveal>\n\u003C/$set>\n\u003C/$set>\n\u003C/$list>\n\u003C/$list>\n\u003C/nav>\n\u003C/$list>\n\u003C/$list>\n","title":"$:/plugins/tiddlywiki/menubar/menu","tags":"$:/tags/PageTemplate","modified":"20231001030048303"},
|
|
|
|
|
{"created":"20230928084148274","text":"\\define breakpoint-plus-one()\n\u003C$text text={{{ [{$:/config/plugins/menubar/breakpoint}removesuffix[px]add[1]addsuffix[px]] ~[{$:/config/plugins/menubar/breakpoint}] }}} />\n\\end\n\n\\define sidebarbreakpoint-minus-one()\n\u003C$text text={{{ [{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}removesuffix[px]subtract[1]addsuffix[px]] ~[{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}] }}} />\n\\end\n\n\\define set-sidebar-scrollable-top-if-hamburger()\n\u003C$list filter=\"[all[tiddlers+shadows]tag[$:/tags/MenuBar]] -[all[tiddlers+shadows]prefix[$:/config/plugins/menubar/MenuItems/Visibility/]regexp:text[hide]removeprefix[$:/config/plugins/menubar/MenuItems/Visibility/]] -[all[tiddlers+shadows]tag[$:/tags/TopLeftBar]limit[1]then[]else[$:/plugins/tiddlywiki/menubar/items/topleftbar]] -[all[tiddlers+shadows]tag[$:/tags/TopRightBar]limit[1]then[$:/plugins/tiddlywiki/menubar/items/toprightbar]] -$:/plugins/tiddlywiki/menubar/items/hamburger +[limit[1]]\">\n\n\t.tc-sidebar-scrollable {\n\t\tmargin-top: 2em;\n\t}\n\n\u003C/$list>\n\\end\n\n\\define set-sidebar-scrollable-top()\n\u003C$list filter=\"[all[tiddlers+shadows]tag[$:/tags/MenuBar]] -[all[tiddlers+shadows]prefix[$:/config/plugins/menubar/MenuItems/Visibility/]regexp:text[hide]removeprefix[$:/config/plugins/menubar/MenuItems/Visibility/]] -[all[tiddlers+shadows]tag[$:/tags/TopLeftBar]limit[1]then[]else[$:/plugins/tiddlywiki/menubar/items/topleftbar]] -[all[tiddlers+shadows]tag[$:/tags/TopRightBar]limit[1]then[$:/plugins/tiddlywiki/menubar/items/toprightbar]] +[limit[1]]\">\n\n\t.tc-sidebar-scrollable {\n\t\tmargin-top: 2em;\n\t}\n\n\u003C/$list>\n\u003C$reveal state=\"$:/state/popup/menubar/hamburger\" type=\"match\" text=\"yes\">\n\n\t\u003C$set name=\"itemCount\" value={{{ [all[tiddlers+shadows]tag[$:/tags/MenuBar]] -[all[tiddlers+shadows]prefix[$:/config/plugins/menubar/MenuItems/Visibility/]regexp:text[hide]removeprefix[$:/config/plugins/menubar/MenuItems/Visibility/]] -[all[tiddlers+shadows]tag[$:/tags/TopLeftBar]limit[1]then[]else[$:/plugins/tiddlywiki/menubar/items/topleftbar]] -[all[tiddlers+shadows]tag[$:/tags/TopRightBar]limit[1]then[]else[$:/plugins/tiddlywiki/menubar/items/toprightbar]] +[count[]] }}}>\n\n\t\t.tc-sidebar-scrollable {\n\t\t\tmargin-top: calc(\u003C\u003CitemCount>> * 2em);\n\t\t}\n\n\t\u003C/$set>\n\n\u003C/$reveal>\n\\end\n\n\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\n\nnav.tc-menubar {\n\tposition: fixed;\n\tz-index: 850;\n\tdisplay: inline-block;\n\ttop: 0;\n\tright: 0;\n\tleft: 0;\n}\n\nnav.tc-menubar ul.tc-menubar-list {\n\tposition: relative;\n\tlist-style-type: none;\n\tmargin: 0;\n\tpadding: 0 0 0 42px;\n\tbackground: \u003C\u003Ccolour background>>;\n\tbackground: \u003C\u003Ccolour menubar-background>>;\n\t\u003C\u003Cbox-shadow \"0px 0px 0px rgba(0, 0, 0, 0.3)\">>\n}\n\n@media (max-width: \u003C\u003Csidebarbreakpoint-minus-one>>) {\n\n\thtml nav.tc-menubar ul.tc-menubar-list {\n\t\tpadding: 0 0 0 8px;\n\t}\n\n}\n\nnav.tc-menubar li.tc-menubar-item {\n\tdisplay: inline-block;\n\tmargin: 0;\n\tpadding: 0;\n}\n\nnav.tc-menubar .tc-menubar-narrow li.tc-menubar-item {\n\tdisplay: block;\n}\n\nnav.tc-menubar li.tc-menubar-item > a,\nnav.tc-menubar li.tc-menubar-item > button {\n\tdisplay: inline-block;\n/*\ttext-transform: uppercase; */\n\tline-height: 1;\n\tfont-weight: 700;\n\tcolor: \u003C\u003Ccolour foreground>>;\n\tcolor: \u003C\u003Ccolour menubar-foreground>>;\n\tfill: \u003C\u003Ccolour foreground>>;\n\tfill: \u003C\u003Ccolour menubar-foreground>>;\n\ttext-decoration: none;\n\tpadding: 0.5em;\n\tmargin: 0;\n\tbackground: none;\n\tborder: none;\n\tcursor: pointer;\n\tborder-radius: 0;\n\ttext-decoration: none;\n}\n\nnav.tc-menubar li.tc-menubar-item > a.tc-selected,\nnav.tc-menubar li.tc-menubar-item > button.tc-selected {\n\tbackground: \u003C\u003Ccolour foreground>>;\n\tbackground: \u003C\u003Ccolour menubar-foreground>>;\n\tcolor: \u003C\u003Ccolour background>>;\n\tcolor: \u003C\u003Ccolour menubar-background>>;\n\tfill: \u003
|
|
|
|
|
{"created":"20230928040958401","title":"$:/SiteSubtitle","text":"la wiki de copincha","modified":"20230929114627397"},
|
|
|
|
|
{"created":"20230927063258094","title":"$:/SiteTitle","text":"{{copinchapedia!!title}}","modified":"20230929105437160"},
|
|
|
|
|
{"created":"20230928045458113","title":"$:/state/advancedsearch/currentTab","text":"$:/core/ui/AdvancedSearch/Shadows","modified":"20231001053011347"},
|
|
|
|
|
{"created":"20230927222940543","title":"$:/state/Excise/-386158927/type","text":"link","modified":"20230927222940543"},
|
|
|
|
|
{"title":"$:/state/http-requests","text":"0"},
|
|
|
|
|
{"created":"20230928040714964","title":"$:/state/peek-stylesheets/open/-1116772087$:/plugins/sq/streams/contextmenu/contextmenu-styles","text":"no","modified":"20230928040716256"},
|
|
|
|
|
{"created":"20230927070527942","title":"$:/state/plugin-info--778185000-$:/plugins/tiddlywiki/filesystem---1320199477","text":"contents","modified":"20230927070527942"},
|
|
|
|
|
{"created":"20230928182221280","title":"$:/state/plugin-info-713020762-$:/plugins/tiddlywiki/menubar--777473238","text":"config","modified":"20230928182221280"},
|
|
|
|
|
{"created":"20230928081548527","title":"$:/state/search/currentTab","text":"$:/plugins/sq/streams-search/StreamSearchResults","modified":"20230928083123854"},
|
|
|
|
|
{"created":"20230927211845025","title":"$:/state/showeditpreview","text":"no","modified":"20230928161353596"},
|
|
|
|
|
{"created":"20230927222316056","title":"$:/state/ShowPaletteEditor","text":"yes","modified":"20230927222316056"},
|
|
|
|
|
{"created":"20230927213815511","title":"$:/state/sidebar","text":"yes","modified":"20230930050058978"},
|
|
|
|
|
{"created":"20230928063718600","title":"$:/state/sq/streams/visibility/copincha/20230928041541658--1254993181","text":"show","modified":"20230928070932222"},
|
|
|
|
|
{"created":"20230928043111137","title":"$:/state/sq/streams/visibility/copincha/20230928041546393-934822130","text":"show","modified":"20230928075641616"},
|
|
|
|
|
{"created":"20230928073413378","title":"$:/state/sq/streams/visibility/copincha/20230928041548495--369046925","text":"show","modified":"20230928081419794"},
|
|
|
|
|
{"created":"20230928063345542","title":"$:/state/sq/streams/visibility/copincha/20230928042426730-2022682073","text":"show","modified":"20230928081956517"},
|
|
|
|
|
{"created":"20230928063717342","title":"$:/state/sq/streams/visibility/copincha/20230928042740135-782739965","text":"show","modified":"20230928075151693"},
|
|
|
|
|
{"created":"20230928064351601","title":"$:/state/sq/streams/visibility/copincha/20230928042840565--156986883","text":"show","modified":"20230928081124929"},
|
|
|
|
|
{"created":"20230928063352669","title":"$:/state/sq/streams/visibility/copincha/20230928062923658-235852612","text":"show","modified":"20230928071956627"},
|
|
|
|
|
{"created":"20230928063353731","title":"$:/state/sq/streams/visibility/copincha/20230928062926521-119290700","text":"show","modified":"20230928072017969"},
|
|
|
|
|
{"created":"20230928063354897","title":"$:/state/sq/streams/visibility/copincha/20230928062931943--1779145438","text":"show","modified":"20230928072019256"},
|
|
|
|
|
{"created":"20230928063356245","title":"$:/state/sq/streams/visibility/copincha/20230928063011441-1517244705","text":"show","modified":"20230928072021418"},
|
|
|
|
|
{"created":"20230928063359743","title":"$:/state/sq/streams/visibility/copincha/20230928063013515--2009532357","text":"show","modified":"20230928072022587"},
|
|
|
|
|
{"created":"20230928063400836","title":"$:/state/sq/streams/visibility/copincha/20230928063019801--1466208351","text":"show","modified":"20230928072024930"},
|
|
|
|
|
{"created":"20230928063401750","title":"$:/state/sq/streams/visibility/copincha/20230928063307747-1329551714","text":"show","modified":"20230928072026869"},
|
|
|
|
|
{"created":"20230928071850912","title":"$:/state/sq/streams/visibility/copincha/20230928071813328-1752783608","text":"show","modified":"20230928075603755"},
|
|
|
|
|
{"created":"20230928045458114","title":"$:/state/tab--1498284803","text":"$:/core/ui/AdvancedSearch/Shadows","modified":"20231001053011347"},
|
|
|
|
|
{"created":"20230927221015986","title":"$:/state/tab--1963855381","text":"$:/core/ui/ControlPanel/Toolbars","modified":"20231001053139717"},
|
|
|
|
|
{"created":"20230928040704540","title":"$:/state/tab--2112689675","text":"$:/core/ui/ControlPanel/Basics","modified":"20230930064022866"},
|
|
|
|
|
{"created":"20230928083530469","title":"$:/state/tab--86143343","text":"$:/core/ui/ControlPanel/Plugins/Installed/Plugins","modified":"20230929172413552"},
|
|
|
|
|
{"created":"20230928040708019","title":"$:/state/tab--959111941","text":"$:/core/ui/ControlPanel/Stylesheets","modified":"20230928054758889"},
|
|
|
|
|
{"created":"20230927070359746","title":"$:/state/tab-1749438307","text":"$:/core/ui/ControlPanel/Appearance","modified":"20231001053130334"},
|
|
|
|
|
{"created":"20230928040939296","title":"$:/state/tab-453520357","text":"$:/core/ui/ControlPanel/EditTemplateBody","modified":"20230928040947232"},
|
|
|
|
|
{"created":"20230928081548527","title":"$:/state/tab/search-results/sidebar","text":"$:/plugins/sq/streams-search/StreamSearchResults","modified":"20230928083123854"},
|
|
|
|
|
{"created":"20230927063409101","title":"$:/state/tab/sidebar--595412856","text":"$:/core/ui/SideBar/Recent","modified":"20230929114245664"},
|
|
|
|
|
{"created":"20230928083324802","title":"$:/state/tabs/controlpanel/toolbars-1345989671","text":"$:/core/ui/ControlPanel/Toolbars/ViewToolbar","modified":"20230930063857265"},
|
|
|
|
|
{"created":"20230928153609332","title":"$:/state/toc/contenidos-Talleres--944721818","text":"open","modified":"20230928153609332"},
|
|
|
|
|
{"created":"20230928081521858","title":"$:/state/toc/TableOfContents-Actividades--944721818","text":"open","modified":"20230928081521858"},
|
|
|
|
|
{"created":"20230928081805243","title":"$:/state/toc/TableOfContents-Actividades-1684905998","text":"open","modified":"20230928081805243"},
|
|
|
|
|
{"created":"20230928081520164","title":"$:/state/toc/TableOfContents-Proyectos--944721818","text":"open","modified":"20230928081520164"},
|
|
|
|
|
{"created":"20230928081806500","title":"$:/state/toc/TableOfContents-Proyectos-1684905998","text":"open","modified":"20230928081806500"},
|
|
|
|
|
{"created":"20230928082306069","title":"$:/state/toc/TableOfContents-Servicios--944721818","text":"open","modified":"20230928082306069"},
|
|
|
|
|
{"created":"20230928082231303","title":"$:/state/toc/TableOfContents-Talleres--944721818","text":"open","modified":"20230928083015283"},
|
|
|
|
|
{"title":"$:/status/RequireReloadDueToPluginChange","text":"no"},
|
|
|
|
|
{"title":"$:/StoryList","text":"","list":"copinchapedia copincha copincha--mapa"},
|
|
|
|
|
{"created":"20231001053351143","title":"$:/tags/ViewToolbar","list":"$:/core/ui/Buttons/more-tiddler-actions $:/core/ui/Buttons/info $:/core/ui/ViewTemplate/tags $:/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 $:/core/ui/Buttons/fold-bar","modified":"20231001053351143"},
|
|
|
|
|
{"created":"20230928034438840","title":"$:/theme","text":"$:/themes/tiddlywiki/vanilla","modified":"20230930051353927"},
|
|
|
|
|
{"title":"$:/themes/tiddlywiki/centralised","name":"Centralised","author":"JeremyRuston","core-version":">=5.0.0","plugin-type":"theme","description":"Centralises the story river","dependents":"$:/themes/tiddlywiki/snowwhite","version":"5.3.1","type":"application/json","text":"{\"tiddlers\":{\"$:/themes/tiddlywiki/centralised/styles.tid\":{\"title\":\"$:/themes/tiddlywiki/centralised/styles.tid\",\"tags\":\"[[$:/tags/Stylesheet]]\",\"text\":\"\\\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\\n\\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n\\n\\thtml .tc-page-container {\\n\\t\\ttext-align: center;\\n\\t}\\n\\n\\thtml .tc-story-river {\\n\\t\\tposition: relative;\\n\\t\\twidth: 770px;\\n\\t\\tpadding: 42px;\\n\\t\\tmargin: 0 auto;\\n\\t\\ttext-align: left;\\n\\t}\\n\\n\\thtml .tc-sidebar-scrollable {\\n\\t\\ttext-align: left;\\n\\t\\tleft: 50%;\\n\\t\\tright: 0;\\n\\t\\tmargin-left: 343px;\\n\\t}\\n}\\n\"}}}"},
|
|
|
|
|
{"title":"$:/themes/tiddlywiki/snowwhite","name":"Snow White","author":"JeremyRuston","core-version":">=5.0.0","plugin-type":"theme","description":"Emphasises individual tiddlers","dependents":"$:/themes/tiddlywiki/vanilla","plugin-priority":"0","version":"5.3.1","type":"application/json","text":"{\"tiddlers\":{\"$:/themes/tiddlywiki/snowwhite/base\":{\"title\":\"$:/themes/tiddlywiki/snowwhite/base\",\"tags\":\"[[$:/tags/Stylesheet]]\",\"text\":\"\\\\define sidebarbreakpoint-minus-one()\\n\u003C$text text={{{ [{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}removesuffix[px]subtract[1]addsuffix[px]] ~[{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}] }}}/>\\n\\\\end\\n\\n\\\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\\n\\n.tc-sidebar-header {\\n\\ttext-shadow: 0 1px 0 \u003C\u003Ccolour sidebar-foreground-shadow>>;\\n}\\n\\n.tc-tiddler-info {\\n\\t\u003C\u003Cbox-shadow \\\"inset 1px 2px 3px rgba(0,0,0,0.1)\\\">>\\n}\\n\\n@media screen {\\n\\t.tc-tiddler-frame {\\n\\t\\t\u003C\u003Cbox-shadow \\\"1px 1px 5px rgba(0, 0, 0, 0.3)\\\">>\\n\\t}\\n}\\n\\n@media (max-width: \u003C\u003Csidebarbreakpoint-minus-one>>) {\\n\\t.tc-tiddler-frame {\\n\\t\\t\u003C\u003Cbox-shadow none>>\\n\\t}\\n}\\n\\n.tc-page-controls button svg, .tc-tiddler-controls button svg, .tc-topbar button svg {\\n\\t\u003C\u003Ctransition \\\"fill 150ms ease-in-out\\\">>\\n}\\n\\n.tc-tiddler-controls button.tc-selected,\\n.tc-page-controls button.tc-selected {\\n\\t\u003C\u003Cfilter \\\"drop-shadow(0px -1px 2px rgba(0,0,0,0.25))\\\">>\\n}\\n\\n.tc-tiddler-frame input.tc-edit-texteditor,\\n.tc-tiddler-frame select.tc-edit-texteditor {\\n\\t\u003C\u003Cbox-shadow \\\"inset 0 1px 8px rgba(0, 0, 0, 0.15)\\\">>\\n}\\n\\n.tc-edit-tags {\\n\\t\u003C\u003Cbox-shadow \\\"inset 0 1px 8px rgba(0, 0, 0, 0.15)\\\">>\\n}\\n\\n.tc-tiddler-frame .tc-edit-tags input.tc-edit-texteditor {\\n\\t\u003C\u003Cbox-shadow \\\"none\\\">>\\n\\tborder: none;\\n\\toutline: none;\\n}\\n\\ntextarea.tc-edit-texteditor {\\n\\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/editorfontfamily}};\\n}\\n\\ncanvas.tc-edit-bitmapeditor {\\n\\t\u003C\u003Cbox-shadow \\\"2px 2px 5px rgba(0, 0, 0, 0.5)\\\">>\\n}\\n\\n.tc-drop-down {\\n\\tborder-radius: 4px;\\n\\t\u003C\u003Cbox-shadow \\\"2px 2px 10px rgba(0, 0, 0, 0.5)\\\">>\\n}\\n\\n.tc-block-dropdown {\\n\\tborder-radius: 4px;\\n\\t\u003C\u003Cbox-shadow \\\"2px 2px 10px rgba(0, 0, 0, 0.5)\\\">>\\n}\\n\\n.tc-modal {\\n\\tborder-radius: 6px;\\n\\t\u003C\u003Cbox-shadow \\\"0 3px 7px rgba(0,0,0,0.3)\\\">>\\n}\\n\\n.tc-modal-footer {\\n\\tborder-radius: 0 0 6px 6px;\\n\\t\u003C\u003Cbox-shadow \\\"inset 0 1px 0 #fff\\\">>;\\n}\\n\\n\\n.tc-alert {\\n\\tborder-radius: 6px;\\n\\t\u003C\u003Cbox-shadow \\\"0 3px 7px rgba(0,0,0,0.6)\\\">>\\n}\\n\\n.tc-notification {\\n\\tborder-radius: 6px;\\n\\t\u003C\u003Cbox-shadow \\\"0 3px 7px rgba(0,0,0,0.3)\\\">>\\n\\ttext-shadow: 0 1px 0 rgba(255,255,255, 0.8);\\n}\\n\\n.tc-sidebar-lists .tc-tab-set .tc-tab-divider {\\n\\tborder-top: none;\\n\\theight: 1px;\\n\\t\u003C\u003Cbackground-linear-gradient \\\"left, rgba(0,0,0,0.15) 0%, rgba(0,0,0,0.0) 100%\\\">>\\n}\\n\\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button {\\n\\t\u003C\u003Cbackground-linear-gradient \\\"left, rgba(0,0,0,0.01) 0%, rgba(0,0,0,0.1) 100%\\\">>\\n}\\n\\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button.tc-tab-selected {\\n\\t\u003C\u003Cbackground-linear-gradient \\\"left, rgba(0,0,0,0.05) 0%, rgba(255,255,255,0.05) 100%\\\">>\\n}\\n\\n.tc-message-box img {\\n\\t\u003C\u003Cbox-shadow \\\"1px 1px 3px rgba(0,0,0,0.5)\\\">>\\n}\\n\\n.tc-plugin-info {\\n\\t\u003C\u003Cbox-shadow \\\"1px 1px 3px rgba(0,0,0,0.5)\\\">>\\n}\\n\"}}}"},
|
|
|
|
|
{"title":"$:/themes/tiddlywiki/vanilla","name":"Vanilla","author":"JeremyRuston","core-version":">=5.0.0","plugin-type":"theme","description":"Basic theme","plugin-priority":"0","version":"5.3.1","dependents":"","type":"application/json","text":"{\"tiddlers\":{\"$:/themes/tiddlywiki/vanilla/themetweaks\":{\"title\":\"$:/themes/tiddlywiki/vanilla/themetweaks\",\"tags\":\"$:/tags/ControlPanel/Appearance\",\"caption\":\"{{$:/language/ThemeTweaks/ThemeTweaks}}\",\"text\":\"\\\\define lingo-base() $:/language/ThemeTweaks/\\n\\n\\\\define replacement-text()\\n[img[$(imageTitle)$]]\\n\\\\end\\n\\n\\\\define backgroundimage-dropdown()\\n\u003Cdiv class=\\\"tc-drop-down-wrapper\\\">\\n\u003C$set name=\\\"state\\\" value=\u003C\u003Cqualify \\\"$:/state/popup/themetweaks/backgroundimage\\\">>>\\n\u003C$button popup=\u003C\u003Cstate>> class=\\\"tc-btn-invisible tc-btn-dropdown\\\">{{$:/core/images/down-arrow}}\u003C/$button>\\n\u003C$reveal state=\u003C\u003Cstate>> type=\\\"popup\\\" position=\\\"belowleft\\\" text=\\\"\\\" default=\\\"\\\" class=\\\"tc-popup-keep\\\">\\n\u003Cdiv class=\\\"tc-drop-down\\\" style=\\\"text-align:center;\\\">\\n\u003C$macrocall $name=\\\"image-picker\\\" actions=\\\"\\\"\\\"\\n\\n\u003C$action-setfield\\n\\t$tiddler=\\\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\\\"\\n\\t$value=\u003C\u003CimageTitle>>\\n/>\\n\\n\u003C$action-deletetiddler $tiddler=\u003C\u003Cstate>>/>\\n\\n\\\"\\\"\\\"/>\\n\u003C/div>\\n\u003C/$reveal>\\n\u003C/$set>\\n\u003C/div>\\n\\\\end\\n\\n\\\\define backgroundimageattachment-dropdown()\\n\u003C$select tiddler=\\\"$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment\\\" default=\\\"scroll\\\">\\n\u003Coption value=\\\"scroll\\\">\u003C\u003Clingo Settings/BackgroundImageAttachment/Scroll>>\u003C/option>\\n\u003Coption value=\\\"fixed\\\">\u003C\u003Clingo Settings/BackgroundImageAttachment/Fixed>>\u003C/option>\\n\u003C/$select>\\n\\\\end\\n\\n\\\\define backgroundimagesize-dropdown()\\n\u003C$select tiddler=\\\"$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize\\\" default=\\\"scroll\\\">\\n\u003Coption value=\\\"auto\\\">\u003C\u003Clingo Settings/BackgroundImageSize/Auto>>\u003C/option>\\n\u003Coption value=\\\"cover\\\">\u003C\u003Clingo Settings/BackgroundImageSize/Cover>>\u003C/option>\\n\u003Coption value=\\\"contain\\\">\u003C\u003Clingo Settings/BackgroundImageSize/Contain>>\u003C/option>\\n\u003C/$select>\\n\\\\end\\n\\n\u003C\u003Clingo ThemeTweaks/Hint>>\\n\\n! \u003C\u003Clingo Options>>\\n\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\\\">\u003C\u003Clingo Options/SidebarLayout>>\u003C/$link> |\u003C$select tiddler=\\\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\\\">\u003Coption value=\\\"fixed-fluid\\\">\u003C\u003Clingo Options/SidebarLayout/Fixed-Fluid>>\u003C/option>\u003Coption value=\\\"fluid-fixed\\\">\u003C\u003Clingo Options/SidebarLayout/Fluid-Fixed>>\u003C/option>\u003C/$select> |\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/options/stickytitles\\\">\u003C\u003Clingo Options/StickyTitles>>\u003C/$link>\u003Cbr>//\u003C\u003Clingo Options/StickyTitles/Hint>>// |\u003C$select tiddler=\\\"$:/themes/tiddlywiki/vanilla/options/stickytitles\\\">\u003Coption value=\\\"no\\\">{{$:/language/No}}\u003C/option>\u003Coption value=\\\"yes\\\">{{$:/language/Yes}}\u003C/option>\u003C/$select> |\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/options/codewrapping\\\">\u003C\u003Clingo Options/CodeWrapping>>\u003C/$link> |\u003C$select tiddler=\\\"$:/themes/tiddlywiki/vanilla/options/codewrapping\\\">\u003Coption value=\\\"pre\\\">{{$:/language/No}}\u003C/option>\u003Coption value=\\\"pre-wrap\\\">{{$:/language/Yes}}\u003C/option>\u003C/$select> |\\n\\n! \u003C\u003Clingo Settings>>\\n\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/settings/fontfamily\\\">\u003C\u003Clingo Settings/FontFamily>>\u003C/$link> |\u003C$edit-text tiddler=\\\"$:/themes/tiddlywiki/vanilla/settings/fontfamily\\\" default=\\\"\\\" tag=\\\"input\\\"/> | |\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/settings/co
|
|
|
|
|
{"created":"20230930044401245","title":"$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize","text":"15px","modified":"20230930044413758"},
|
|
|
|
|
{"created":"20230930044353147","title":"$:/themes/tiddlywiki/vanilla/metrics/bodylineheight","text":"25px","modified":"20230930051107843"},
|
|
|
|
|
{"created":"20230928064822405","title":"$:/themes/tiddlywiki/vanilla/metrics/fontsize","text":"1rem","modified":"20230928065502903"},
|
|
|
|
|
{"created":"20230928064817626","title":"$:/themes/tiddlywiki/vanilla/metrics/lineheight","text":"1.6rem","modified":"20230928064817626"},
|
|
|
|
|
{"created":"20230928055921803","title":"$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint","text":"960px","modified":"20230930044216096"},
|
|
|
|
|
{"created":"20230928055946271","title":"$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth","text":"350px","modified":"20230930044622631"},
|
|
|
|
|
{"created":"20230928061041902","title":"$:/themes/tiddlywiki/vanilla/metrics/storyleft","text":"20%","modified":"20230930051120125"},
|
|
|
|
|
{"created":"20230928060105639","title":"$:/themes/tiddlywiki/vanilla/metrics/storyright","text":"70%","modified":"20230930044727641"},
|
|
|
|
|
{"created":"20230930043532912","title":"$:/themes/tiddlywiki/vanilla/metrics/storytop","text":"80px","modified":"20230930044323792"},
|
|
|
|
|
{"created":"20230928060035928","title":"$:/themes/tiddlywiki/vanilla/metrics/storywidth","text":"900px","modified":"20230930044447211"},
|
|
|
|
|
{"created":"20230928055906111","title":"$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth","text":"900px","modified":"20230930044633749"},
|
|
|
|
|
{"created":"20230928085232868","title":"$:/themes/tiddlywiki/vanilla/settings/backgroundimage","text":"","modified":"20230928085347894"},
|
|
|
|
|
{"created":"20230928085302230","title":"$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment","text":"fixed","modified":"20230928085304673"},
|
|
|
|
|
{"created":"20230928085307601","title":"$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize","text":"cover","modified":"20230928085307601"},
|
|
|
|
|
{"created":"20230928034143363","title":"$:/themes/tiddlywiki/vanilla/settings/codefontfamily","text":"\"inconsolata\"","modified":"20230928034244016"},
|
|
|
|
|
{"created":"20230928062723733","title":"$:/themes/tiddlywiki/vanilla/settings/editorfontfamily","text":"\"inconsolata\"","modified":"20230928062723733"},
|
|
|
|
|
{"created":"20230928034127438","title":"$:/themes/tiddlywiki/vanilla/settings/fontfamily","text":"\"inconsolata\"","modified":"20230928034240079"},
|
|
|
|
|
{"created":"20230930052113906","title":"$:/view","text":"top","modified":"20230930064450818"},
|
|
|
|
|
{"title":"2023-09-25_08-19.png","text":"iVBORw0KGgoAAAANSUhEUgAAA24AAATrCAIAAABq6XbVAAAACXBIWXMAABnWAAAZ1gEY0crtAAAgAElEQVR4nOy9WZMkS3oddr7PPSIza+nqve+93bMDBGZoEkFiKJmMg4GZKCwiTGYCIPCRehEko+kH0PQLSIp6oOGJouEFb5RAM4pmehL0QgMgmUhowY5ZLu7MnXt77+quqqzMjAj37+jBIyKz9qzqWrKy4lh1dVVWLB7hHu4nvuV8srGxgQ6HgeRVN6FDhw4dbjRE5Kqb0KFDhxPgr7oBi4iORHbo0KHDIiDNxh2h7NBhkdFRyT3oSGSHDh06LBo6QtmhwyJDr7oBHTp06NChQ4cOHa4rOqvkHrRvvZ15skOHDh0WAZ0xskOHBUdnlTwEHY/s0KFDhwVBNyF36LDg6KySe9DNWR06dOiwaOhiJTt0WGR0VskpOh7ZoUOHDguLboru0GEx0VklgW6G6tChQ4frgM482aHDAuKmU8l9JPJXf/VXvvnNn/7qV7/y0UdPHjy4v76+7pxr/9rNX4sOgWCZ+2ied55DR+klD91D2vkeXXPwaMffh5Mv9ojGpB0PPThBnK4VC4SbOHEd0cUL2GcX0aTDhuvpEGPc2dl59erV06dPP/7Lv/yDf/cH/+pf/S/n1LoOSwjpqt2Q/Nmf/fbf/bu/9q1vfevRo0fHbHkTZ+TrhY5KAlgANnlmyjvn0d6XSgIiwIGhIgICh67BB9fm91+tLxk3a/rqqOR5H/XFixe/+3u/+y9/+1/+m3/zu+d86A7XHzedSn7rZ/7Wr/9Xv/7zP/9z82x8s+bia4hD+cEyYW4qicN40qXdmbmaeXFUcv7jH9zmxDV4AbnI/LhBM1hHJS/gQtP4+Z3f+d/+2T/7H3//9//P8z9Bh2uLG00l/9E//of/5d/7e/Nvf4Mm4muIpeeRONWqc+BOiMjBxfUMy1jzFBy367517Bhv8jxozzQ97GlbLe3/jXDsmVfahaMip8aNmMc6KnlhVDLht37rt/7BP/jvzv8cHa4nXL/fv+o2XAG+/vWv/+Zv/vNf+qVfOtVeN2IKvra4Cb0jMvdX2mF2OSEI7vu6GGJ04LCy99t7HPh9Ied0nOuOZQ8FWf4LvArMzrE/9VM/9a1vfesP//CPXr9+fYVN6rAguIlU8hd/8Rd+4zf+6Te+8Y3T7ngTyMo1xY3pGpn/64KW0rPf6gVa3ckDttITjUPLN8aW74qmWKDBtjzYN2CePHnyt//2f/zpp59+/PHHV9WkDguCG0clf/EXf+Gf/A//5MMPPjjDvss8815zHNU1J+Vn4Mx2svN0S82x7C2OY+5UT4HMYmGW9pRbc9reX8oIitPOaec4Di92Or3ZVFL2PnnnhYMn2tjY+Pa3f+bjjz/u2OQNx82ikl//+td/4zf+6dl4JDoqucA4Y9csyHqzIM2YD6elkiduc4Us+ZTXgo5KXptTX6tn6lpjZWXlm9/86d/7vd/vPN03GTeLSv7mb/7zM/i1W3RUcjGxr19OlZuyIOvNBQ2t92RpN2HAz3+NHZW8TqdemEf7JmBjY+Mnf/In/8W/+J+uuiEdrgw3iEr+o//+H/7S3zldns0+3ISV9TpiKaL3FhGH3tgz+cEWF21z57iqa3VhJ2FxuupCmtE92heAY56OL3zhycOHD37nd/73q25jh6vBTRED+ta3/tZv//b//J4HWZCZt8M+nN0quey4CKvkHE/B4vdA08IbSTjeZx67iK69TCq5gENzAZt0OOZ4WH7lV37193///7ic5nRYKNyUwon/9a//uhwQKLkmT3CHDmdE9/JzBGoj49FLI48qe3OdIPt+O5Urv8a++9COqGtX7Odm4Yrekf7+3/9vOip5M6FX3YDLwM/+7Ld/4ef/ExGKcFZyr1tmFwM89Esge+VtKOAptHDm/upw0yByuGB7C/JyeeT8cqGn+DpcafSkZrSu/Kmk1OHGaRw4wVm/OiwNfu7nfv5nf/ZnrroVHa4AN8Iq+Wv/xa+Qtic2KPkUKJ1tcjGwvxNEVCgzfzp2bef7+ezOvOeNxFW5OM/lvItppr1yJ/vJt0UOfU4W8WZeOyzmmDwzfu3Xfq0r0n0DcSOo5Df/xk9VReGzzDknAEmpjZIERWbYZBd1d7VokxtqWwiFIBkAAyiSjOgHl7WDHSUz3zssNubrJRG5tIT09z/XtcCSkZgOi4Bvf/vbV92EDleA5Xdw/9Lf+cW1lZViMgllaSGQJrX/tDF3XbY3q8MxEEBUHVMwVhPfytmFfa7lb1E6lPPhqpvZYT9OTOg+R1z6pS1Q+naHJcOjR49++Zf/86tuRYfLxvJTyZ/8iR+fjHfLYlyWk6oqGQNqNmlIZGV/Pk6HS8b+wEUzQ83xE8sXESdwgNYxk3vDHclDv9AxtAXiQMfU37gs43FH2esIx9Pf8KMiJjt0OIi/+Te/edVN6HDZWH4H94M7G6PhUCjJpa0C7zNxmvykQvAUM+QxS1E3z74PZPaH6ZKfiEbya/Pg9gLgCMLYpu8c3i83nlNcOBaTeZBczIZdAt7/wtsjdKS8wzH42td+7Kqb0OGysfxUcm2wMtoZwkAzmjFa3meW55riJpH4xqEz4/6Z99j58+YuUecOERhZJ9MIakaZfN4k6jSF2rhCoaY7v1+eJB7PGJdzMbzkMXhWuZkrxI1lk+d14deDRx7+FnkdWn798fjxh1fdhA6XjeWnkrnX0e6QRovRYogxGA2gzzNVRwgFoEISSdmnqNbh0tBmaidLMaEADFBVEREYAAYjCCgUiV3WhkkC4NS+LCKANun5UyMnZ6IuZ9Otmp8uoMvn0mA5h4Og0ZKbn8+djRPM1g98b+54NbTkJrNJTCe5U7ljrp+K5PWgvMuIBw8fXXUTOlw2lp9KKjje3YWRtPQFELAeBz7LxTlAIEwqk7Nzz01caq4YDclDCuJtlj0hU+9FGqmqquogogoRqwLNnHOiOkMaJfGFKZVMdJS0mnYSs10sbQPOJwdr2pDzGEfzHuSUusRyxjzlc3wyztqE98aNZZNoB6e0j9sNvQ8dLgjra2tX3YQOl40lp5Ik1SwURQlVUSfqVAWSMjqE4nOIOoolXgIjZ7WBukn2siBNJBZZWxdFlUTKkApmFmkhgsyzTEWg3gwxxKKoYozOOxURVadOxAlUFWYwkoyi0FpIyPalgx/Rlve+nKmA6eURpTO0+8qo3EwTrsr+f5PZJDC966298UbfjQ7nB+fcVTehw2VjyakkAAdBtKooVNU7dU5TEgeNoPRIn+fqfW2WTAtrrY3dTayXCzJl+UJTEQwzMoQqQgwq4pF5MRtVVRwXk6Ia7o53h7vj8TiEAIGqZlmW57n3vTzr3bp1a9DvOVWnyDJVowgFNBINh2jddunXlsue4zUdvzyf77nOVuzvVG04inpeUxayIGzy4tzHs9EIJzdjb88uwp3p0KHDtcAyU8k0M2ojfhGrqixK55xAImgEIZHsg5mIepW9RcK6SjiXC2noHQAhEUkzkgimUXwwCcHGu7ubbzc3t95tbu1s7exOxkVVVtEiAVVRdd577zLvs41btx7cu3v31tqdW6t31lcGuVcxAM6pqso05aqG1iuutZ9ctbnuOmHPvbr4eM1zxEKwyQu7B0e9XcxDMa+8a84LJ17I1Q+A88YFvZws343qcF5YWirZTh/K5vcQyvEYNDNmNALWPG6E5CKqGWaSuWfK9p1L6kSH49CmAojAiDImdugJmGFnVDx/s/Vma7j59t3rd++2RrvjogqWKItGg4hK8moXJAtBqW9Hq89e399YfXz/zpOHdx/eubXaz/MsU/VQhUgdOJuywPesN6ftyyVZcc8NR61jDcVcNI4yk4l1stjNcqym+yjm/Bc1Z9+dysB/Mbf0FKNs/k2Xo/c7dDh3LC2VbKEpJ9iMgFksLOnMMNV8UKfqnDgnKiLwPksZGzMmKz2KWnTTyjmCZLv6UISQSC0L7A4nm++2X7x6+8MXb59vjYYVhiGMoxIDEQdIjBFtmnedUUMRKG1rWGxNiq2dne13b7fu3/3w/p1
|
|
|
|
|
{"created":"20230928041724703","text":"\u003Ccenter>[img height=150px [media/image/copincha-logo.png]]\u003C/center>\n\n''Copincha'' es un [[hackerspace|Hackerspace]] situado en La Habana. Es un laboratorio para el desarrollo de collectividades alrededor de las technologías digitales, la filosofía de hazlo tu mismo (DIY) y la colaboración abierta. \n\n\n\u003C\u003C\u003C\nEn la jerga local cubana, \"pincha\" significa trabajo. Copincha así se traduce como trabajo colaborativo.\n\n\u003C\u003C\u003C\n\nFacilitamos un programa de talleres y charlas, desde las que se generan preguntas, opiniones, ayuda y soluciones colectivas.\n\nEmpleamos herramientas digitales que nos dan autonomía y en la medida de lo posible soberanía sobre nuestros datos, mantenemos así nuestro propio [[repositorio de código abierto|https://git.copincha.org/]]. Aprendemos juntos cosas nuevas con cada proyecto y mantenemos documentación de nuestras actividades en [[Copinchapedia|https://copinchapedia.copincha.org/]].","title":"About","modified":"20231001043032724","tags":"contenidos"},
|
|
|
|
|
{"created":"20230928042327983","text":"","title":"Actividades","modified":"20230928090614514","tags":"contenidos"},
|
|
|
|
|
{"created":"20231001004026091","text":"","tags":"todo","title":"agregar marca de licencia creative commons","modified":"20231001050110801"},
|
|
|
|
|
{"created":"20230929162127862","text":"","tags":"","title":"asiento","modified":"20230929163015570","parent":"coche"},
|
|
|
|
|
{"created":"20230928040240740","text":"[[about]]\n\n[[activities]]\n\n[[projects]]\n\n[[contact]]\n","tags":"","title":"barra","modified":"20230928040359452"},
|
|
|
|
|
{"created":"20230928081322642","text":"","title":"cafe-reparador","modified":"20230928081322642","tags":"Actividades"},
|
|
|
|
|
{"created":"20230928081309285","text":"","title":"cafe-sorpresa","modified":"20230928081309285","tags":"Actividades"},
|
|
|
|
|
{"created":"20230928063746635","text":"\n\nLunes\n\nMartes\n\nMiercoles\n\nJueves\n\nViernes\n\nSabados\n\nDomingos","tags":"contenidos","title":"Calendario","modified":"20230928090614514"},
|
|
|
|
|
{"created":"20230928192600848","text":"Maurice es el cofundador de un hackerspace/laboratorio comunitario en La Habana, Cuba, donde sus miembros desarrollan y comparten soluciones de código abierto a retos locales, como la escasez de recursos y el acceso limitado a Internet. Uno de sus principales proyectos actuales trata sobre la conversión de residuos plásticos en filamentos que puedan alimentar impresoras 3D, que a su vez pueden construirse con piezas impresas a partir de plástico reciclado. Ha impartido cursos de formación sobre todo este proceso, desde la clasificación de los tipos de plástico hasta la construcción de extrusoras de bricolaje, pasando por el modelado 3D paramétrico y el resto del flujo de trabajo de la impresión 3D. (Puedes leer más sobre su trayectoria y el hackerspace en su página web: https://m00.copincha.org/) ¿Le interesaría este tipo de taller a Resistor?\nMaurice estará en Estados Unidos este verano para asistir a la Conferencia sobre la Web Descentralizada (DWeb) del Archivo de Internet y hacer una residencia en el Action Lab de Nueva York, pero tendrá mucho tiempo libre a finales de julio y agosto. Viene con un visado de negocios/turismo, por lo que no puede realizar trabajos remunerados, pero estaría encantado de ofrecer una clase de forma voluntaria. En cualquier caso, tiene muchas ganas de visitar Resistor cuando llegue.","tags":"","title":"carta resistor","modified":"20230928192613885"},
|
|
|
|
|
{"created":"20230929162134991","text":"\u003C$list filter=\"[parent\u003CcurrentTiddler>]\"/>\n\n","tags":"","title":"coche","modified":"20230929170048608","a":""},
|
|
|
|
|
{"created":"20230928042505635","text":"tel:\n+5354115734\n\nemail:\ncopinchacomunidad@copincha.org\n\nfacebook:\nfacebook.com/copincha\n\ngit:\ngit.copincha.org\ngithub.copincha.org\n\ninstagram:\ninstagram.com/copincha\n\ntelegram:\nt.com/copincha\n\nwhatsapp:\nwa.me/copincha","title":"Contacto","modified":"20230928090614514","tags":"contenidos"},
|
|
|
|
|
{"created":"20140809114010378","text":"\u003Cdiv class=\"tc-table-of-contents\">\n\n\u003C\u003Ctoc-selective-expandable 'contenidos'>>\n\n\u003C/div>\n","title":"contenidos","caption":"{{$:/language/SideBar/Contents/Caption}}","list":"HelloThere Learning [[Working with TiddlyWiki]] [[Customise TiddlyWiki]] Features Languages Editions Plugins Platforms Reference Community About","list-after":"$:/core/ui/SideBar/Open","modified":"20230928090614514","tags":"","type":"text/vnd.tiddlywiki"},
|
|
|
|
|
{"created":"20230930055153584","text":" \u003Cdiv style=\"width: 25%; float:left; padding: 10px 20px 10px 10px;\"> \n\u003Ccenter>\n[img width=150 [./media/logo-copincha-negro.png]]\n\u003C/center> \n \u003C/div> \n\n\u003Ch1> {{!!title}} \u003C/h1>\n\nEs un [[hackerspace|Hackerspace]] situado en La Habana. Un laboratorio para compartir experiencias tecnológicas a través de la colaboración abierta.\n\nEn la jerga local cubana, \"pincha\" significa trabajo. Copincha así se traduce como trabajo colaborativo.\n\n[[Ver mas ... |About]]\n","tags":"","title":"copincha","modified":"20231001042955292"},
|
|
|
|
|
{"created":"20230930060320534","text":"\u003C$leafmap tile='osm'\n\tplaces='{\"filter\":\"[tag[copincha--punto]]\"}' clusterType='tiddler'\nzoom='12'\n/>\n","tags":"","title":"copincha--mapa","modified":"20231001034512811"},
|
|
|
|
|
{"created":"20210325045828732","text":"Dirección: \u003C$tiddler tiddler={{!!caption}}>{{!!direccion}}\u003C/$tiddler>\n\nEmail: \u003C$tiddler tiddler={{!!caption}}>{{!!email}}\u003C/$tiddler>\n\nTeléfono: \u003C$tiddler tiddler={{!!caption}}>{{!!telefono}}\u003C/$tiddler>","type":"text/vnd.tiddlywiki","tmap.id":"43981f03-b629-4576-be77-3546d93bfcd4","title":"copincha--mapa--hackerspace","telefono":"\u003Ca href=\"tel: +53 54115734\">+53 54115734\u003C/a>","tags":"copincha--punto","revision":"0","point":"23.1391890, -82.3735227","osm":"[[23.1391890,82.3735227|https://www.openstreetmap.org/#map=23.1391890,82.3735227]]","modifier":"Sylvain Comte","modified":"20230930233351790","mapa":"\u003C$leafmap tile='toner' places='{\"filter\":\"[tag[geocopincha]]\"}' clusterType='tiddler' style='{\"color\":\"orange\"}' marker='marker' height=300px width=100%/>","email":"[[comunidad@copincha.org|mailto:comunidad@copincha.org]]","direccion":"Ánimas 964-101 e/Soledad y Oquendo, Centrohabana, La Habana, Cuba","creator":"Sylvain Comte","color":"#000000","caption":"Copincha Hackersapce","bag":"default"},
|
|
|
|
|
{"created":"20231001045119103","text":"! {{!!name}}\n\ndescripcion\n\nweb:{{!!web}}","tags":"miembros","title":"copincha--miembro--m00","modified":"20231001045320117","caption":"{{!!name}}","name":"m00","web":"https://m00.copincha.org"},
|
|
|
|
|
{"created":"20231001045303490","text":"! {{!!name}}\n\ndescripcion\n\nweb:{{!!web}}","tags":"miembros","title":"copincha--miembro--nestor","modified":"20231001045403485","caption":"{{!!name}}","name":"nestor","web":"https://nestorsire.com"},
|
|
|
|
|
{"created":"20230718184446694","text":"\u003Ccenter>\n\n\u003Cimg src=\"./media/copincha--miembro--sergio.png\" style=\"height:200px; border-radius: 50%;\">\n\n! {{!!name}}\n\n{{!!first-name}} {{!!last-name}}\n\n{{!!about}} \n\n\u003Cbr>\n\n{{!!email}}\n\n{{!!website}}","modified":"20231001052718986","title":"copincha--miembro--sergio","tags":"miembros","email":"sergio@copincha.org","website":"https://sergio.copincha.org","about":"Me gusta Copincha","name":"sergio","image":"[img [./medios/miembros--sergio.png]]","first-name":"Sergio","last-name":"Valdés García","caption":"{{!!name}}"},
|
|
|
|
|
{"created":"20231001044244006","text":"! {{!!name}}\n\ndescripcion\n\nweb:{{!!web}}","tags":"copincha--templates","title":"copincha--miembro--template","modified":"20231001045251279","caption":"{{!!name}}","name":"miembro","web":"https://copincha.org"},
|
|
|
|
|
{"created":"20231001034828011","text":"{{!!banner}}\n\n! {{!!name}}\n\nLaboratorio iniciado en 2021 para fomentar la búsqueda de soluciones de impresión 3D asequibles y respetuosas con el medio ambiente en Cuba. En este proyecto construimos extrusoras de filamento de plástico reciclado que se utiliza como materia prima para las [[impresoras 3D RepRap]] que también construimos \n\nWeb: {{!!web}}\n","tags":"Proyectos impresion-3d","title":"copincha--projecto--3d-a-lo-cubano","modified":"20231001040557175","caption":"{{!!name}}","name":"3D a lo Cubano","banner":"[img [./media/3d-a-lo-cubano--banner.svg]]","web":"https://3d-a-lo-cubano.copincha.org/"},
|
|
|
|
|
{"created":"20230930234024042","text":"{{!!banner}}\n\n! {{!!name}}\n\nEs un proyecto de colaboración abierta para combatir la contaminación plástica en La Habana. Como nodo local de la red global [[Precious Plastic|https://preciousplastic.com]], conectamos sus conocimientos y experiencias con las locales.\n\nWeb: https://pph.copincha.org\n\n\n\n\n\n\n\n\n","title":"copincha--proyecto--hackerspace","modified":"20231001035159083","tags":"Proyectos","banner":"[img [./media/hackerspace--banner.svg]]","name":"Copincha Hackerspace","caption":"{{!!name}}"},
|
|
|
|
|
{"created":"20230928081511282","text":"{{!!banner}}\n\n! {{!!name}}\n\nEs un proyecto de colaboración abierta para combatir la contaminación plástica en La Habana. Como nodo local de la red global [[Precious Plastic|https://preciousplastic.com]], conectamos sus conocimientos y experiencias con las locales.\n\nWeb: https://pph.copincha.org\n\n\n\n\n\n\n\n\n","title":"copincha--proyecto--pph","modified":"20231001040829118","tags":"Proyectos plastico reciclaje","banner":"[img [./media/pph--banner.svg]]","name":"Precious Plastic Havana","caption":"{{!!name}}"},
|
|
|
|
|
{"created":"20230928074901132","text":"","tags":"","title":"copincha-descripcion","modified":"20230928075233442"},
|
|
|
|
|
{"created":"20230927224934205","text":"[img [./media/image/banner--01.svg]]\n\n! Bienvenido a {{!!title}}\n\nEn este sitio documentamos colaborativamente el conocimiento y las experiencias de [[Copincha|copincha]]. Todo el trabajo se publica bajo una [[Licencia Creative Commons Atribución-CompartirIgual 4.0 Internacional|https://creativecommons.org/licenses/by-sa/4.0/]].\n\nEste sitio está cambiando todo el tiempo. A menudo se agregan ligeros ajustes, una sección completamente nueva o se elimina algo que ya no es relevante. Así que espere enlaces rotos y errores de escritura ocasionales en material nuevo. Hacemos lo posible por mantenerlo ordenado.\n\nAl recopilar estos materiales, hemos tomado prestado ocasionalmente muchos recursos en línea (como: textos, imágenes o ideas inspiradoras). Intentamos reunir el crédito de todas las fuentes en cada página; pero por favor, [[contáctenos|mailto:comunidad@copincha.org]] si encuentra alguna omisión o igualmente para brindarnos preguntas o comentarios.","title":"copinchapedia","modified":"20230930065941537","nombre de pagina":""},
|
|
|
|
|
{"created":"20230929172520412","text":"https://bun.sh/","tags":"","title":"crear servidor alternativa a node.js","modified":"20230929172545663"},
|
|
|
|
|
{"created":"20230927222942065","modified":"20230927222942065","title":"Crear una Paleta","text":"Crear una paleta\n\npara crear una paleta solo debes copiar el tiddler de paleta que tienes la etiqueta $:/tags/Palette\n\nuna vez copiada cambiar los valores en los campos ","tags":""},
|
|
|
|
|
{"created":"20230927063243063","text":"Aprendizaje-tw\n\n* [[Crear una Paleta]]\n\nPor hacer en el wiki:\n\n* ","tags":"Notas","title":"Desarrollo del wiki","modified":"20230928082741415","stream-list":"[[Desarrollo del wiki/20230928050314967]]","stream-type":"default"},
|
|
|
|
|
{"created":"20230928050314973","text":"[[quitar elementos de tiddler]]","parent":"Desarrollo del wiki","stream-type":"default","stream-list":"","modified":"20230928050332953","title":"Desarrollo del wiki/20230928050314967"},
|
|
|
|
|
{"created":"20230928160731701","text":"Un diseño intersticial es un enfoque de diseño que se utiliza en diversas disciplinas, como la arquitectura, el diseño web, el diseño gráfico y otros campos creativos. El término \"intersticial\" se refiere a algo que está ubicado o que ocurre entre dos cosas o en un espacio intermedio. En el contexto del diseño, un diseño intersticial implica crear elementos, estructuras o soluciones que se insertan de manera armónica y funcional en un espacio o contexto existente.\n\nAquí hay ejemplos de cómo se puede aplicar el concepto de diseño intersticial en diferentes campos:\n\n1. Diseño web: En diseño web, un anuncio intersticial es un tipo de anuncio que se muestra a los usuarios entre las páginas de un sitio web. Por lo general, aparece antes de que el usuario acceda al contenido deseado y puede ocupar toda la pantalla temporalmente. El objetivo es captar la atención del usuario antes de que vea el contenido principal del sitio web.\n\n2. Arquitectura: En arquitectura, un diseño intersticial podría referirse a la creación de una estructura o edificio que se integra de manera armoniosa en un entorno existente. Esto implica considerar cuidadosamente el contexto circundante y diseñar la nueva estructura de manera que se mezcle con el entorno en lugar de destacarse de manera discordante.\n\n3. Diseño gráfico: En diseño gráfico, un diseño intersticial podría referirse a la creación de elementos gráficos que se insertan entre otros elementos en una composición de diseño, como imágenes, texto o ilustraciones. Estos elementos intersticiales pueden utilizarse para separar secciones de contenido o agregar interés visual.\n\nEn resumen, un diseño intersticial es un enfoque que se centra en la integración armoniosa y efectiva de elementos o soluciones en un espacio o contexto existente, ya sea en diseño web, arquitectura, diseño gráfico u otras disciplinas creativas. El objetivo es lograr una transición fluida y una experiencia cohesiva para los usuarios o espectadores.","title":"Diseno intersticial","modified":"20230928165618248"},
|
|
|
|
|
{"created":"20230928163648359","text":"El diseño participativo intersticial es un enfoque de diseño que promueve la participación activa de diferentes actores y partes interesadas en el proceso de diseño de un sistema, producto o servicio. Se basa en la idea de que la participación y la colaboración de diversas perspectivas pueden generar soluciones más inclusivas y efectivas.\n\nLa palabra \"intersticial\" se refiere a los espacios o momentos dentro del proceso de diseño en los que se fomenta la participación. Estos espacios suelen ser momentos de encuentro y diálogo entre los diseñadores y las personas que serán afectadas o beneficiadas por el diseño. El objetivo es promover la co-creación, la retroalimentación y la toma de decisiones conjuntas.\n\nEn un diseño participativo intersticial, se busca incluir a diferentes partes interesadas, como usuarios finales, expertos en la materia, diseñadores, desarrolladores y otros actores relevantes. Cada uno aporta su conocimiento, experiencia y opiniones para enriquecer el proceso de diseño.\n\nEste enfoque intersticial se caracteriza por ser iterativo y flexible. Se pueden organizar talleres, sesiones de lluvia de ideas, pruebas de prototipos y otras actividades que permitan la participación activa de todos los involucrados. Además, se fomenta la transparencia y la apertura en la comunicación, para construir una relación de confianza entre los participantes.\n\nEl diseño participativo intersticial tiene como objetivo final desarrollar soluciones más contextualizadas y adaptadas a las necesidades reales de las personas. Al involucrar a los usuarios y otras partes interesadas desde las primeras etapas del diseño, se pueden evitar problemas potenciales y generar soluciones más satisfactorias.","title":"Diseno participativo intersticial","modified":"20230928165555359"},
|
|
|
|
|
{"created":"20231001004026091","text":"","tags":"todo","title":"habilitar dominio sergio.copincha.org","modified":"20231001004202880"},
|
|
|
|
|
{"created":"20210304163741217","text":"! {{!!title}}\n\nLos hackerspaces son lugares físicos gestionados de forma comunitaria, donde las personas se reunen y comparten su interés por la tecnología, trabajan en sus proyectos y aprenden de los demás.","type":"text/vnd.tiddlywiki","tmap.id":"45ae7ea8-487e-4aae-973e-2ee87dd23a67","title":"Hackerspace","tags":"glosario","modifier":"M0","modified":"20230930070215504","creator":"M0"},
|
|
|
|
|
{"created":"20210325045828732","text":"Dirección: {{Hackerspace Copincha!!direccion}}\n\nEmail: {{Hackerspace Copincha!!email}}\n\nTeléfono: {{Hackerspace Copincha!!telefono}}","type":"text/vnd.tiddlywiki","tmap.id":"43981f03-b629-4576-be77-3546d93bfcd4","title":"Hackerspace Copincha","telefono":"\u003Ca href=\"tel: +53 54115734\">+53 54115734\u003C/a>","tags":"copincha--punto","revision":"0","point":"23.1391890, -82.3735227","osm":"[[23.1391890,82.3735227|https://www.openstreetmap.org/#map=23.1391890,82.3735227]]","modifier":"Sylvain Comte","modified":"20230930060735609","mapa":"\u003C$leafmap tile='toner' places='{\"filter\":\"[tag[geocopincha]]\"}' clusterType='tiddler' style='{\"color\":\"orange\"}' marker='marker' height=300px width=100%/>","email":"[[comunidad@copincha.org|mailto:comunidad@copincha.org]]","direccion":"Ánimas 964, apto 101, entre Soledad y Oquendo, Centrohabana, La Habana, Cuba","creator":"Sylvain Comte","color":"#000000","caption":"Copincha","bag":"default"},
|
|
|
|
|
{"created":"20230928082255138","text":"","title":"Impresion 3D","modified":"20230928082256355","tags":"Servicios"},
|
|
|
|
|
{"created":"20231001035659543","text":"Las impresoras 3D RepRap son impresoras que pueden autorreplicarse imprimiendo un kit de sus propias piezas, un kit que cualquiera puede montar con tiempo y materiales.","title":"impresoras 3D RepRap","modified":"20231001035701384"},
|
|
|
|
|
{"created":"20230928161216472","text":"La intersticialidad se refiere a la característica de estar ubicado o existir en el espacio entre cosas o elementos. \n\nEspacio intersticial en el contexto social y cultural:** A nivel social y cultural, la intersticialidad se puede usar para describir la experiencia o la identidad de personas o grupos que se encuentran en un espacio entre dos culturas, identidades, o roles sociales. Esto puede ser relevante en discusiones sobre migración, identidad étnica, o cualquier situación en la que una persona o grupo se sienta \"en el medio\" de dos realidades culturales o sociales.","title":"Intersticialidad","modified":"20230928165539638"},
|
|
|
|
|
{"created":"20230928073732659","text":"[[Intersticialidad]]\n\n[[Diseno intersticial]]\n\n[[Diseno participativo intersticial]]\n\n[[Ventajas de la instersticialidad]]\n\n[[Ventajas de la instersticialidad 1]]\n\n[[La maquina intersticial 1]]\n\n[[carta resistor]]\n\n---\n\n# A quien van dirijido?\n\n# Cuantas sesiones serian?\n\n# Cuales son los colectivo?\n\n* XFR\n\n* Archivistas\n\n* Bases?\n\n* Tecnologia como un proceso rizomatico\n\n** En la medida que somos capaces de crear e interconectar alternativas reevaluamos el pontencial de la tecnologia para nosotors mismo y nuestra comunidad.\n\nIntersticialidad \n\n\n* diy-diwo\n** hardware abierto\n*** opensource vs privado \n*** opensorce y autonomia comunitaria\n*** opensource y sentido de pertenencia\n*** amplificar la participacion\n***pequena escala\n***vista panoramica\n\n* sinergia\n** tejido comunitario.\n*** tejido con el territorios\n** tejido digital desde lo online\n*** trabajar en red, (con otros colectivos, otros contextos)\n** que problemas solucionan?\n*** reciclaje. \n\nofrecer a partir de la escusa de la maquina,.\n\ntoca las 3 patas:\n\nmedioambiental del reciclaje\nreuso\n\nsocial\nparticipacion \n\ndisenar de manera colectiva y abierta. \n\n* openstructures\n\n** disenar con una pauta en comun\n** disenar metasistemas:\n** contienen y organizan la diversidad\n\n\n....\n\n2. definir las dinamicas\n\n * desarrolalr diferentes proyectos o miniproyectos que haya en diferentes colectivos,.\n * la creatividad en sinergias. caso habana . poder explircar como se va articulando. \n * poder comunica, comunicar, sistematizar. \n * modulos,. como hacer maquinas de forma modular, y para que:\n\n la suma de trabajar en colectivo que la suma de las partes\n\n \n\n","title":"La maquina intersticial","modified":"20230929114501419","tags":"Talleres"},
|
|
|
|
|
{"created":"20230928192759382","text":"Propuestas:\n\n* Como disenar de forma modular para reciclar, reusar y reparar.\n\n* Como fabricar filamento 3D a partir de botellas de plástico reciclado.\n\n* Como construir cosas creando intersticialidad participativa entre diferentes redes.\n\nLa conversión de residuos plásticos en filamentos para impresoras 3D.\n\nComenzaremos por establecer la conexión entre la red mundial de recicladores de código abierto Precious Plastic, la red de openstructures de fabricación a base de una retícula modular de diseño común y la red Reprap de construcción de máquinas autorreplicables de código abierto. A través de la comprensión de estas relaciones colaborativas, desarrollaremos sistemas sinérgicos que permitan a los participantes reflexionar sobre la construcción de comunidades más resilientes. donde se promueve el reuso de componentes y materiales. y tambien que las maquinas puedan ser construidas con l mayor variedad de procesos disponibles localmente y sin mucha complejid de formas en sus partes para ue cualquiera pueda reproducir estas partes por mas cantidad de procesos.\n\nDurante estos cursos, abordaremos temáticas fundamentales:\n\n* La clasificación de los plásticos y su importancia en el proceso de reciclaje local\n\n* El proceso de transformar estos residuos plásticos en filamentos aptos para ser utilizados en impresoras 3D.\n\n* El diseno modular usando la reticula de openstructures y su importancia para la reutilizacion de componentes y la creacion de dinamicas aprticipativas.\n\n* El diseno 3D y la creación de modelos paramétricos, utilizando software de codigo abierto. donde Los participantes aprenderán a modelar piezas y objetos que se adaptarán a las necesidades específicas de cada proyecto. Fomentando la creatividad y la personalización. \n\n\ntodo esto es la practica que tengo,. que se enfoca ahora po busca en lo instersticial. o se cohesiona como practica hlistica. \n\n\nLas técnicas fabricacion digital asociados\n\nAbordaremos esto revisando la construcción diy de extrusores de filamentos de impresion 3D y , desde la búsqueda de relaciones intersticiales entre distintas redes, los participantes aprenderán a construir estos extrusores a través de un enfoque DIY (Do It Yourself) y DIWO (Do It With Others). Se fomentará el reuso de las partes diseñadas, promoviendo así el valor de la economía circular y el aprovechamiento de recursos.\n\nEn resumen, los cursos de formación que ofrecemos proporcionarán a los participantes las habilidades y conocimientos necesarios para la construcción y utilización de impresoras 3D que funcionen gracias a filamentos obtenidos a partir de plástico reciclado. Trabajaremos de forma colaborativa, aprovechando las ventajas del código abierto, el diseño modular y la autorreplicación de máquinas para crear comunidades más resilientes.","tags":"","title":"La maquina intersticial 1","modified":"20230929113431266"},
|
|
|
|
|
{"created":"20230928052135645","text":"","tags":"","title":"New Tiddler","modified":"20230928052139390"},
|
|
|
|
|
{"created":"20230929180802098","text":"","tags":"","title":"New Tiddler 1","modified":"20230929180804673"},
|
|
|
|
|
{"created":"20230928082455352","text":"\u003Cdiv class=\"tc-table-of-contents\">\n\n\u003C\u003Ctoc-selective-expandable 'Notas'>>\n\n\u003C/div>","tags":"$:/tags/SideBar","title":"Notas","modified":"20231001003537215"},
|
|
|
|
|
{"created":"20230928050341828","text":"$:/core/ui/ViewTemplate/","title":"quitar elementos de tiddler","modified":"20230928050343529"},
|
|
|
|
|
{"created":"20230928082239577","text":"","title":"Servicios","modified":"20230928090614514","tags":"contenidos"},
|
|
|
|
|
{"created":"20230928082136289","text":"","title":"Talleres","modified":"20230928090614514","tags":"contenidos"},
|
|
|
|
|
{"created":"20231001043845810","text":"\u003Cdiv class=\"tc-table-of-contents\">\n\n\u003C\u003Ctoc-selective-expandable 'copincha--templates'>>\n\n\u003C/div>\n","tags":"$:/tags/SideBar","title":"Templates","modified":"20231001044802706"},
|
|
|
|
|
{"created":"20231001003431084","text":"\u003Cdiv class=\"tc-table-of-contents\">\n\n\u003C\u003Ctoc-selective-expandable 'todo'>>\n\n\u003C/div>","tags":"$:/tags/SideBar","title":"To do","modified":"20231001003856743"},
|
|
|
|
|
{"created":"20230928063648195","text":"Te puedes unir de la siguiente forma","tags":"contenidos","title":"Unirse","modified":"20230928090614514"},
|
|
|
|
|
{"title":"Untitled","text":"75"},
|
|
|
|
|
{"created":"20230928185727463","text":"Cuando algo es más \"intersticial\", se refiere a que está integrado o se encuentra en el espacio entre otras cosas o sistemas. Aquí tienes algunas ventajas de adoptar un enfoque más intersticial:\n\n1. Flexibilidad y adaptabilidad: Al estar ubicado entre diferentes elementos, un enfoque intersticial permite una mayor flexibilidad y adaptabilidad a los cambios. Puede responder de manera más efectiva a las necesidades cambiantes y acomodar diferentes contextos o sistemas sin tener que realizar cambios drásticos.\n\n2. Conexión y sinergia: Adoptar un enfoque intersticial fomenta la conexión y la sinergia entre diferentes partes o sistemas. Permite la integración de diferentes ideas, perspectivas y conocimientos, lo que puede conducir a soluciones más completas y robustas. Al conectar diferentes elementos, se pueden lograr resultados más integrales y eficaces.\n\n3. Innovación y creatividad: La intersticialidad proporciona oportunidades para la innovación y la creatividad. Al interactuar con diferentes elementos o perspectivas, se pueden generar nuevas ideas, soluciones originales y enfoques no convencionales. Al tener una visión más amplia y diversa, se pueden explorar oportunidades innovadoras que pueden ser pasadas por alto en un enfoque más convencional.\n\n4. Colaboración y participación: Adoptar un enfoque intersticial fomenta la colaboración y la participación activa de diferentes partes interesadas. Permite que diferentes personas y grupos trabajen juntos, compartan ideas y contribuyan a la toma de decisiones. Esto promueve la igualdad de participación y la valoración de diversas perspectivas, lo que a menudo conduce a soluciones más equitativas y sostenibles.\n\n5. Resolución de conflictos: En contextos en los que hay conflictos o divergencias de intereses, un enfoque intersticial puede ayudar a encontrar soluciones comunes o puntos de conexión. Al integrar diferentes perspectivas y encontrar áreas de superposición o intersección, se puede avanzar hacia la resolución de conflictos y la construcción de consensos.\n\nEn resumen, adoptar un enfoque más intersticial ofrece ventajas como flexibilidad, conexión, innovación, colaboración y resolución de conflictos. Permite aprovechar la diversidad y los intercambios entre diferentes elementos o sistemas para lograr mejores resultados.","title":"Ventajas de la instersticialidad","modified":"20230928185749855"},
|
|
|
|
|
{"created":"20230928185802600","text":"Cuando algo es más \"intersticial\", se refiere a que está integrado o se encuentra en el espacio entre otras cosas o sistemas. Aquí tienes algunas ventajas de adoptar un enfoque más intersticial:\n\n1. Flexibilidad y adaptabilidad: Al estar ubicado entre diferentes elementos, un enfoque intersticial permite una mayor flexibilidad y adaptabilidad a los cambios. Puede responder de manera más efectiva a las necesidades cambiantes y acomodar diferentes contextos o sistemas sin tener que realizar cambios drásticos.\n\nModular\n\n2. Conexión y sinergia: Adoptar un enfoque intersticial fomenta la conexión y la sinergia entre diferentes partes o sistemas. Permite la integración de diferentes ideas, perspectivas y conocimientos, lo que puede conducir a soluciones más completas y robustas. Al conectar diferentes elementos, se pueden lograr resultados más integrales y eficaces.\n\n3. Innovación y creatividad: La intersticialidad proporciona oportunidades para la innovación y la creatividad. Al interactuar con diferentes elementos o perspectivas, se pueden generar nuevas ideas, soluciones originales y enfoques no convencionales. Al tener una visión más amplia y diversa, se pueden explorar oportunidades innovadoras que pueden ser pasadas por alto en un enfoque más convencional.\n\n\n4. Colaboración y participación: Adoptar un enfoque intersticial fomenta la colaboración y la participación activa de diferentes partes interesadas. Permite que diferentes personas y grupos trabajen juntos, compartan ideas y contribuyan a la toma de decisiones. Esto promueve la igualdad de participación y la valoración de diversas perspectivas, lo que a menudo conduce a soluciones más equitativas y sostenibles.\n\n5. Resolución de conflictos: En contextos en los que hay conflictos o divergencias de intereses, un enfoque intersticial puede ayudar a encontrar soluciones comunes o puntos de conexión. Al integrar diferentes perspectivas y encontrar áreas de superposición o intersección, se puede avanzar hacia la resolución de conflictos y la construcción de consensos.\n\nEn resumen, adoptar un enfoque más intersticial ofrece ventajas como flexibilidad, conexión, innovación, colaboración y resolución de conflictos. Permite aprovechar la diversidad y los intercambios entre diferentes elementos o sistemas para lograr mejores resultados.","title":"Ventajas de la instersticialidad 1","modified":"20230928191613509","tags":""},
|
|
|
|
|
{"created":"20230929162057208","text":"","tags":"","title":"volante","modified":"20230929163027730","parent":"coche"}
|
|
|
|
|
]</script><div id="storeArea" style="display:none;"></div>
|
|
|
|
|
<!--~~ Library modules ~~-->
|
|
|
|
|
<div id="libraryModules" style="display:none;">
|
|
|
|
|
<script data-tiddler-library="yes" data-tiddler-title="$:/library/sjcl.js" data-tiddler-type="application/javascript" type="text/javascript">"use strict";var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a},notReady:function(a){this.toString=function(){return"NOT READY: "+this.message};this.message=a}}};
|
|
|
|
|
sjcl.cipher.aes=function(a){this.s[0][0][0]||this.O();var b,c,d,e,f=this.s[0][4],g=this.s[1];b=a.length;var h=1;if(4!==b&&6!==b&&8!==b)throw new sjcl.exception.invalid("invalid aes key size");this.b=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(0===a%b||8===b&&4===a%b)c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255],0===a%b&&(c=c<<8^c>>>24^h<<24,h=h<<1^283*(h>>7));d[a]=d[a-b]^c}for(b=0;a;b++,a--)c=d[b&3?a:a-4],e[b]=4>=a||4>b?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^g[3][f[c&
|
|
|
|
|
255]]};
|
|
|
|
|
sjcl.cipher.aes.prototype={encrypt:function(a){return t(this,a,0)},decrypt:function(a){return t(this,a,1)},s:[[[],[],[],[],[]],[[],[],[],[],[]]],O:function(){var a=this.s[0],b=this.s[1],c=a[4],d=b[4],e,f,g,h=[],k=[],l,n,m,p;for(e=0;0x100>e;e++)k[(h[e]=e<<1^283*(e>>7))^e]=e;for(f=g=0;!c[f];f^=l||1,g=k[g]||1)for(m=g^g<<1^g<<2^g<<3^g<<4,m=m>>8^m&255^99,c[f]=m,d[m]=f,n=h[e=h[l=h[f]]],p=0x1010101*n^0x10001*e^0x101*l^0x1010100*f,n=0x101*h[m]^0x1010100*m,e=0;4>e;e++)a[e][f]=n=n<<24^n>>>8,b[e][m]=p=p<<24^p>>>8;for(e=
|
|
|
|
|
0;5>e;e++)a[e]=a[e].slice(0),b[e]=b[e].slice(0)}};
|
|
|
|
|
function t(a,b,c){if(4!==b.length)throw new sjcl.exception.invalid("invalid aes block size");var d=a.b[c],e=b[0]^d[0],f=b[c?3:1]^d[1],g=b[2]^d[2];b=b[c?1:3]^d[3];var h,k,l,n=d.length/4-2,m,p=4,r=[0,0,0,0];h=a.s[c];a=h[0];var q=h[1],v=h[2],w=h[3],x=h[4];for(m=0;m<n;m++)h=a[e>>>24]^q[f>>16&255]^v[g>>8&255]^w[b&255]^d[p],k=a[f>>>24]^q[g>>16&255]^v[b>>8&255]^w[e&255]^d[p+1],l=a[g>>>24]^q[b>>16&255]^v[e>>8&255]^w[f&255]^d[p+2],b=a[b>>>24]^q[e>>16&255]^v[f>>8&255]^w[g&255]^d[p+3],p+=4,e=h,f=k,g=l;for(m=
|
|
|
|
|
0;4>m;m++)r[c?3&-m:m]=x[e>>>24]<<24^x[f>>16&255]<<16^x[g>>8&255]<<8^x[b&255]^d[p++],h=e,e=f,f=g,g=b,b=h;return r}
|
|
|
|
|
sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.$(a.slice(b/32),32-(b&31)).slice(1);return void 0===c?a:sjcl.bitArray.clamp(a,c-b)},extract:function(a,b,c){var d=Math.floor(-b-c&31);return((b+c-1^b)&-32?a[b/32|0]<<32-d^a[b/32+1|0]>>>d:a[b/32|0]>>>d)&(1<<c)-1},concat:function(a,b){if(0===a.length||0===b.length)return a.concat(b);var c=a[a.length-1],d=sjcl.bitArray.getPartial(c);return 32===d?a.concat(b):sjcl.bitArray.$(b,d,c|0,a.slice(0,a.length-1))},bitLength:function(a){var b=a.length;return 0===
|
|
|
|
|
b?0:32*(b-1)+sjcl.bitArray.getPartial(a[b-1])},clamp:function(a,b){if(32*a.length<b)return a;a=a.slice(0,Math.ceil(b/32));var c=a.length;b=b&31;0<c&&b&&(a[c-1]=sjcl.bitArray.partial(b,a[c-1]&2147483648>>b-1,1));return a},partial:function(a,b,c){return 32===a?b:(c?b|0:b<<32-a)+0x10000000000*a},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return!1;var c=0,d;for(d=0;d<a.length;d++)c|=a[d]^b[d];return 0===
|
|
|
|
|
c},$:function(a,b,c,d){var e;e=0;for(void 0===d&&(d=[]);32<=b;b-=32)d.push(c),c=0;if(0===b)return d.concat(a);for(e=0;e<a.length;e++)d.push(c|a[e]>>>b),c=a[e]<<32-b;e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,32<b+a?c:d.pop(),1));return d},i:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]},byteswapM:function(a){var b,c;for(b=0;b<a.length;++b)c=a[b],a[b]=c>>>24|c>>>8&0xff00|(c&0xff00)<<8|c<<24;return a}};
|
|
|
|
|
sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d<c/8;d++)0===(d&3)&&(e=a[d/4]),b+=String.fromCharCode(e>>>8>>>8>>>8),e<<=8;return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c<a.length;c++)d=d<<8|a.charCodeAt(c),3===(c&3)&&(b.push(d),d=0);c&3&&b.push(sjcl.bitArray.partial(8*(c&3),d));return b}};
|
|
|
|
|
sjcl.codec.hex={fromBits:function(a){var b="",c;for(c=0;c<a.length;c++)b+=((a[c]|0)+0xf00000000000).toString(16).substr(4);return b.substr(0,sjcl.bitArray.bitLength(a)/4)},toBits:function(a){var b,c=[],d;a=a.replace(/\s|0x/g,"");d=a.length;a=a+"00000000";for(b=0;b<a.length;b+=8)c.push(parseInt(a.substr(b,8),16)^0);return sjcl.bitArray.clamp(c,4*d)}};
|
|
|
|
|
sjcl.codec.base32={B:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",X:"0123456789ABCDEFGHIJKLMNOPQRSTUV",BITS:32,BASE:5,REMAINING:27,fromBits:function(a,b,c){var d=sjcl.codec.base32.BASE,e=sjcl.codec.base32.REMAINING,f="",g=0,h=sjcl.codec.base32.B,k=0,l=sjcl.bitArray.bitLength(a);c&&(h=sjcl.codec.base32.X);for(c=0;f.length*d<l;)f+=h.charAt((k^a[c]>>>g)>>>e),g<d?(k=a[c]<<d-g,g+=e,c++):(k<<=d,g-=d);for(;f.length&7&&!b;)f+="=";return f},toBits:function(a,b){a=a.replace(/\s|=/g,"").toUpperCase();var c=sjcl.codec.base32.BITS,
|
|
|
|
|
d=sjcl.codec.base32.BASE,e=sjcl.codec.base32.REMAINING,f=[],g,h=0,k=sjcl.codec.base32.B,l=0,n,m="base32";b&&(k=sjcl.codec.base32.X,m="base32hex");for(g=0;g<a.length;g++){n=k.indexOf(a.charAt(g));if(0>n){if(!b)try{return sjcl.codec.base32hex.toBits(a)}catch(p){}throw new sjcl.exception.invalid("this isn't "+m+"!");}h>e?(h-=e,f.push(l^n>>>h),l=n<<c-h):(h+=d,l^=n<<c-h)}h&56&&f.push(sjcl.bitArray.partial(h&56,l,1));return f}};
|
|
|
|
|
sjcl.codec.base32hex={fromBits:function(a,b){return sjcl.codec.base32.fromBits(a,b,1)},toBits:function(a){return sjcl.codec.base32.toBits(a,1)}};
|
|
|
|
|
sjcl.codec.base64={B:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b,c){var d="",e=0,f=sjcl.codec.base64.B,g=0,h=sjcl.bitArray.bitLength(a);c&&(f=f.substr(0,62)+"-_");for(c=0;6*d.length<h;)d+=f.charAt((g^a[c]>>>e)>>>26),6>e?(g=a[c]<<6-e,e+=26,c++):(g<<=6,e-=6);for(;d.length&3&&!b;)d+="=";return d},toBits:function(a,b){a=a.replace(/\s|=/g,"");var c=[],d,e=0,f=sjcl.codec.base64.B,g=0,h;b&&(f=f.substr(0,62)+"-_");for(d=0;d<a.length;d++){h=f.indexOf(a.charAt(d));
|
|
|
|
|
if(0>h)throw new sjcl.exception.invalid("this isn't base64!");26<e?(e-=26,c.push(g^h>>>e),g=h<<32-e):(e+=6,g^=h<<32-e)}e&56&&c.push(sjcl.bitArray.partial(e&56,g,1));return c}};sjcl.codec.base64url={fromBits:function(a){return sjcl.codec.base64.fromBits(a,1,1)},toBits:function(a){return sjcl.codec.base64.toBits(a,1)}};sjcl.hash.sha256=function(a){this.b[0]||this.O();a?(this.F=a.F.slice(0),this.A=a.A.slice(0),this.l=a.l):this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()};
|
|
|
|
|
sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.F=this.Y.slice(0);this.A=[];this.l=0;return this},update:function(a){"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));var b,c=this.A=sjcl.bitArray.concat(this.A,a);b=this.l;a=this.l=b+sjcl.bitArray.bitLength(a);if(0x1fffffffffffff<a)throw new sjcl.exception.invalid("Cannot hash more than 2^53 - 1 bits");if("undefined"!==typeof Uint32Array){var d=new Uint32Array(c),e=0;for(b=512+b-(512+b&0x1ff);b<=a;b+=512)u(this,d.subarray(16*e,
|
|
|
|
|
16*(e+1))),e+=1;c.splice(0,16*e)}else for(b=512+b-(512+b&0x1ff);b<=a;b+=512)u(this,c.splice(0,16));return this},finalize:function(){var a,b=this.A,c=this.F,b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);b.push(Math.floor(this.l/0x100000000));for(b.push(this.l|0);b.length;)u(this,b.splice(0,16));this.reset();return c},Y:[],b:[],O:function(){function a(a){return 0x100000000*(a-Math.floor(a))|0}for(var b=0,c=2,d,e;64>b;c++){e=!0;for(d=2;d*d<=c;d++)if(0===c%d){e=
|
|
|
|
|
!1;break}e&&(8>b&&(this.Y[b]=a(Math.pow(c,.5))),this.b[b]=a(Math.pow(c,1/3)),b++)}}};
|
|
|
|
|
function u(a,b){var c,d,e,f=a.F,g=a.b,h=f[0],k=f[1],l=f[2],n=f[3],m=f[4],p=f[5],r=f[6],q=f[7];for(c=0;64>c;c++)16>c?d=b[c]:(d=b[c+1&15],e=b[c+14&15],d=b[c&15]=(d>>>7^d>>>18^d>>>3^d<<25^d<<14)+(e>>>17^e>>>19^e>>>10^e<<15^e<<13)+b[c&15]+b[c+9&15]|0),d=d+q+(m>>>6^m>>>11^m>>>25^m<<26^m<<21^m<<7)+(r^m&(p^r))+g[c],q=r,r=p,p=m,m=n+d|0,n=l,l=k,k=h,h=d+(k&l^n&(k^l))+(k>>>2^k>>>13^k>>>22^k<<30^k<<19^k<<10)|0;f[0]=f[0]+h|0;f[1]=f[1]+k|0;f[2]=f[2]+l|0;f[3]=f[3]+n|0;f[4]=f[4]+m|0;f[5]=f[5]+p|0;f[6]=f[6]+r|0;f[7]=
|
|
|
|
|
f[7]+q|0}
|
|
|
|
|
sjcl.mode.ccm={name:"ccm",G:[],listenProgress:function(a){sjcl.mode.ccm.G.push(a)},unListenProgress:function(a){a=sjcl.mode.ccm.G.indexOf(a);-1<a&&sjcl.mode.ccm.G.splice(a,1)},fa:function(a){var b=sjcl.mode.ccm.G.slice(),c;for(c=0;c<b.length;c+=1)b[c](a)},encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,k=h.bitLength(c)/8,l=h.bitLength(g)/8;e=e||64;d=d||[];if(7>k)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(f=2;4>f&&l>>>8*f;f++);f<15-k&&(f=15-k);c=h.clamp(c,
|
|
|
|
|
8*(15-f));b=sjcl.mode.ccm.V(a,b,c,d,e,f);g=sjcl.mode.ccm.C(a,g,c,b,e,f);return h.concat(g.data,g.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var f=sjcl.bitArray,g=f.bitLength(c)/8,h=f.bitLength(b),k=f.clamp(b,h-e),l=f.bitSlice(b,h-e),h=(h-e)/8;if(7>g)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(b=2;4>b&&h>>>8*b;b++);b<15-g&&(b=15-g);c=f.clamp(c,8*(15-b));k=sjcl.mode.ccm.C(a,k,c,l,e,b);a=sjcl.mode.ccm.V(a,k.data,c,d,e,b);if(!f.equal(k.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");
|
|
|
|
|
return k.data},na:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,k=h.i;d=[h.partial(8,(b.length?64:0)|d-2<<2|f-1)];d=h.concat(d,c);d[3]|=e;d=a.encrypt(d);if(b.length)for(c=h.bitLength(b)/8,65279>=c?g=[h.partial(16,c)]:0xffffffff>=c&&(g=h.concat([h.partial(16,65534)],[c])),g=h.concat(g,b),b=0;b<g.length;b+=4)d=a.encrypt(k(d,g.slice(b,b+4).concat([0,0,0])));return d},V:function(a,b,c,d,e,f){var g=sjcl.bitArray,h=g.i;e/=8;if(e%2||4>e||16<e)throw new sjcl.exception.invalid("ccm: invalid tag length");
|
|
|
|
|
if(0xffffffff<d.length||0xffffffff<b.length)throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data");c=sjcl.mode.ccm.na(a,d,c,e,g.bitLength(b)/8,f);for(d=0;d<b.length;d+=4)c=a.encrypt(h(c,b.slice(d,d+4).concat([0,0,0])));return g.clamp(c,8*e)},C:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.i;var k=b.length,l=h.bitLength(b),n=k/50,m=n;c=h.concat([h.partial(8,f-1)],c).concat([0,0,0]).slice(0,4);d=h.bitSlice(g(d,a.encrypt(c)),0,e);if(!k)return{tag:d,data:[]};for(g=0;g<k;g+=4)g>n&&(sjcl.mode.ccm.fa(g/
|
|
|
|
|
k),n+=m),c[3]++,e=a.encrypt(c),b[g]^=e[0],b[g+1]^=e[1],b[g+2]^=e[2],b[g+3]^=e[3];return{tag:d,data:h.clamp(b,l)}}};
|
|
|
|
|
sjcl.mode.ocb2={name:"ocb2",encrypt:function(a,b,c,d,e,f){if(128!==sjcl.bitArray.bitLength(c))throw new sjcl.exception.invalid("ocb iv must be 128 bits");var g,h=sjcl.mode.ocb2.S,k=sjcl.bitArray,l=k.i,n=[0,0,0,0];c=h(a.encrypt(c));var m,p=[];d=d||[];e=e||64;for(g=0;g+4<b.length;g+=4)m=b.slice(g,g+4),n=l(n,m),p=p.concat(l(c,a.encrypt(l(c,m)))),c=h(c);m=b.slice(g);b=k.bitLength(m);g=a.encrypt(l(c,[0,0,0,b]));m=k.clamp(l(m.concat([0,0,0]),g),b);n=l(n,l(m.concat([0,0,0]),g));n=a.encrypt(l(n,l(c,h(c))));
|
|
|
|
|
d.length&&(n=l(n,f?d:sjcl.mode.ocb2.pmac(a,d)));return p.concat(k.concat(m,k.clamp(n,e)))},decrypt:function(a,b,c,d,e,f){if(128!==sjcl.bitArray.bitLength(c))throw new sjcl.exception.invalid("ocb iv must be 128 bits");e=e||64;var g=sjcl.mode.ocb2.S,h=sjcl.bitArray,k=h.i,l=[0,0,0,0],n=g(a.encrypt(c)),m,p,r=sjcl.bitArray.bitLength(b)-e,q=[];d=d||[];for(c=0;c+4<r/32;c+=4)m=k(n,a.decrypt(k(n,b.slice(c,c+4)))),l=k(l,m),q=q.concat(m),n=g(n);p=r-32*c;m=a.encrypt(k(n,[0,0,0,p]));m=k(m,h.clamp(b.slice(c),p).concat([0,
|
|
|
|
|
0,0]));l=k(l,m);l=a.encrypt(k(l,k(n,g(n))));d.length&&(l=k(l,f?d:sjcl.mode.ocb2.pmac(a,d)));if(!h.equal(h.clamp(l,e),h.bitSlice(b,r)))throw new sjcl.exception.corrupt("ocb: tag doesn't match");return q.concat(h.clamp(m,p))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.S,e=sjcl.bitArray,f=e.i,g=[0,0,0,0],h=a.encrypt([0,0,0,0]),h=f(h,d(d(h)));for(c=0;c+4<b.length;c+=4)h=d(h),g=f(g,a.encrypt(f(h,b.slice(c,c+4))));c=b.slice(c);128>e.bitLength(c)&&(h=f(h,d(h)),c=e.concat(c,[-2147483648,0,0,0]));g=f(g,c);
|
|
|
|
|
return a.encrypt(f(d(f(h,d(h))),g))},S:function(a){return[a[0]<<1^a[1]>>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^135*(a[0]>>>31)]}};
|
|
|
|
|
sjcl.mode.gcm={name:"gcm",encrypt:function(a,b,c,d,e){var f=b.slice(0);b=sjcl.bitArray;d=d||[];a=sjcl.mode.gcm.C(!0,a,f,d,c,e||128);return b.concat(a.data,a.tag)},decrypt:function(a,b,c,d,e){var f=b.slice(0),g=sjcl.bitArray,h=g.bitLength(f);e=e||128;d=d||[];e<=h?(b=g.bitSlice(f,h-e),f=g.bitSlice(f,0,h-e)):(b=f,f=[]);a=sjcl.mode.gcm.C(!1,a,f,d,c,e);if(!g.equal(a.tag,b))throw new sjcl.exception.corrupt("gcm: tag doesn't match");return a.data},ka:function(a,b){var c,d,e,f,g,h=sjcl.bitArray.i;e=[0,0,
|
|
|
|
|
0,0];f=b.slice(0);for(c=0;128>c;c++){(d=0!==(a[Math.floor(c/32)]&1<<31-c%32))&&(e=h(e,f));g=0!==(f[3]&1);for(d=3;0<d;d--)f[d]=f[d]>>>1|(f[d-1]&1)<<31;f[0]>>>=1;g&&(f[0]^=-0x1f000000)}return e},j:function(a,b,c){var d,e=c.length;b=b.slice(0);for(d=0;d<e;d+=4)b[0]^=0xffffffff&c[d],b[1]^=0xffffffff&c[d+1],b[2]^=0xffffffff&c[d+2],b[3]^=0xffffffff&c[d+3],b=sjcl.mode.gcm.ka(b,a);return b},C:function(a,b,c,d,e,f){var g,h,k,l,n,m,p,r,q=sjcl.bitArray;m=c.length;p=q.bitLength(c);r=q.bitLength(d);h=q.bitLength(e);
|
|
|
|
|
g=b.encrypt([0,0,0,0]);96===h?(e=e.slice(0),e=q.concat(e,[1])):(e=sjcl.mode.gcm.j(g,[0,0,0,0],e),e=sjcl.mode.gcm.j(g,e,[0,0,Math.floor(h/0x100000000),h&0xffffffff]));h=sjcl.mode.gcm.j(g,[0,0,0,0],d);n=e.slice(0);d=h.slice(0);a||(d=sjcl.mode.gcm.j(g,h,c));for(l=0;l<m;l+=4)n[3]++,k=b.encrypt(n),c[l]^=k[0],c[l+1]^=k[1],c[l+2]^=k[2],c[l+3]^=k[3];c=q.clamp(c,p);a&&(d=sjcl.mode.gcm.j(g,h,c));a=[Math.floor(r/0x100000000),r&0xffffffff,Math.floor(p/0x100000000),p&0xffffffff];d=sjcl.mode.gcm.j(g,d,a);k=b.encrypt(e);
|
|
|
|
|
d[0]^=k[0];d[1]^=k[1];d[2]^=k[2];d[3]^=k[3];return{tag:q.bitSlice(d,0,f),data:c}}};sjcl.misc.hmac=function(a,b){this.W=b=b||sjcl.hash.sha256;var c=[[],[]],d,e=b.prototype.blockSize/32;this.w=[new b,new b];a.length>e&&(a=b.hash(a));for(d=0;d<e;d++)c[0][d]=a[d]^909522486,c[1][d]=a[d]^1549556828;this.w[0].update(c[0]);this.w[1].update(c[1]);this.R=new b(this.w[0])};
|
|
|
|
|
sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a){if(this.aa)throw new sjcl.exception.invalid("encrypt on already updated hmac called!");this.update(a);return this.digest(a)};sjcl.misc.hmac.prototype.reset=function(){this.R=new this.W(this.w[0]);this.aa=!1};sjcl.misc.hmac.prototype.update=function(a){this.aa=!0;this.R.update(a)};sjcl.misc.hmac.prototype.digest=function(){var a=this.R.finalize(),a=(new this.W(this.w[1])).update(a).finalize();this.reset();return a};
|
|
|
|
|
sjcl.misc.pbkdf2=function(a,b,c,d,e){c=c||1E4;if(0>d||0>c)throw new sjcl.exception.invalid("invalid params to pbkdf2");"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,k,l=[],n=sjcl.bitArray;for(k=1;32*l.length<(d||1);k++){e=f=a.encrypt(n.concat(b,[k]));for(g=1;g<c;g++)for(f=a.encrypt(f),h=0;h<f.length;h++)e[h]^=f[h];l=l.concat(e)}d&&(l=n.clamp(l,d));return l};
|
|
|
|
|
sjcl.prng=function(a){this.c=[new sjcl.hash.sha256];this.m=[0];this.P=0;this.H={};this.N=0;this.U={};this.Z=this.f=this.o=this.ha=0;this.b=[0,0,0,0,0,0,0,0];this.h=[0,0,0,0];this.L=void 0;this.M=a;this.D=!1;this.K={progress:{},seeded:{}};this.u=this.ga=0;this.I=1;this.J=2;this.ca=0x10000;this.T=[0,48,64,96,128,192,0x100,384,512,768,1024];this.da=3E4;this.ba=80};
|
|
|
|
|
sjcl.prng.prototype={randomWords:function(a,b){var c=[],d;d=this.isReady(b);var e;if(d===this.u)throw new sjcl.exception.notReady("generator isn't seeded");if(d&this.J){d=!(d&this.I);e=[];var f=0,g;this.Z=e[0]=(new Date).valueOf()+this.da;for(g=0;16>g;g++)e.push(0x100000000*Math.random()|0);for(g=0;g<this.c.length&&(e=e.concat(this.c[g].finalize()),f+=this.m[g],this.m[g]=0,d||!(this.P&1<<g));g++);this.P>=1<<this.c.length&&(this.c.push(new sjcl.hash.sha256),this.m.push(0));this.f-=f;f>this.o&&(this.o=
|
|
|
|
|
f);this.P++;this.b=sjcl.hash.sha256.hash(this.b.concat(e));this.L=new sjcl.cipher.aes(this.b);for(d=0;4>d&&(this.h[d]=this.h[d]+1|0,!this.h[d]);d++);}for(d=0;d<a;d+=4)0===(d+1)%this.ca&&y(this),e=z(this),c.push(e[0],e[1],e[2],e[3]);y(this);return c.slice(0,a)},setDefaultParanoia:function(a,b){if(0===a&&"Setting paranoia=0 will ruin your security; use it only for testing"!==b)throw new sjcl.exception.invalid("Setting paranoia=0 will ruin your security; use it only for testing");this.M=a},addEntropy:function(a,
|
|
|
|
|
b,c){c=c||"user";var d,e,f=(new Date).valueOf(),g=this.H[c],h=this.isReady(),k=0;d=this.U[c];void 0===d&&(d=this.U[c]=this.ha++);void 0===g&&(g=this.H[c]=0);this.H[c]=(this.H[c]+1)%this.c.length;switch(typeof a){case "number":void 0===b&&(b=1);this.c[g].update([d,this.N++,1,b,f,1,a|0]);break;case "object":c=Object.prototype.toString.call(a);if("[object Uint32Array]"===c){e=[];for(c=0;c<a.length;c++)e.push(a[c]);a=e}else for("[object Array]"!==c&&(k=1),c=0;c<a.length&&!k;c++)"number"!==typeof a[c]&&
|
|
|
|
|
(k=1);if(!k){if(void 0===b)for(c=b=0;c<a.length;c++)for(e=a[c];0<e;)b++,e=e>>>1;this.c[g].update([d,this.N++,2,b,f,a.length].concat(a))}break;case "string":void 0===b&&(b=a.length);this.c[g].update([d,this.N++,3,b,f,a.length]);this.c[g].update(a);break;default:k=1}if(k)throw new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string");this.m[g]+=b;this.f+=b;h===this.u&&(this.isReady()!==this.u&&A("seeded",Math.max(this.o,this.f)),A("progress",this.getProgress()))},
|
|
|
|
|
isReady:function(a){a=this.T[void 0!==a?a:this.M];return this.o&&this.o>=a?this.m[0]>this.ba&&(new Date).valueOf()>this.Z?this.J|this.I:this.I:this.f>=a?this.J|this.u:this.u},getProgress:function(a){a=this.T[a?a:this.M];return this.o>=a?1:this.f>a?1:this.f/a},startCollectors:function(){if(!this.D){this.a={loadTimeCollector:B(this,this.ma),mouseCollector:B(this,this.oa),keyboardCollector:B(this,this.la),accelerometerCollector:B(this,this.ea),touchCollector:B(this,this.qa)};if(window.addEventListener)window.addEventListener("load",
|
|
|
|
|
this.a.loadTimeCollector,!1),window.addEventListener("mousemove",this.a.mouseCollector,!1),window.addEventListener("keypress",this.a.keyboardCollector,!1),window.addEventListener("devicemotion",this.a.accelerometerCollector,!1),window.addEventListener("touchmove",this.a.touchCollector,!1);else if(document.attachEvent)document.attachEvent("onload",this.a.loadTimeCollector),document.attachEvent("onmousemove",this.a.mouseCollector),document.attachEvent("keypress",this.a.keyboardCollector);else throw new sjcl.exception.bug("can't attach event");
|
|
|
|
|
this.D=!0}},stopCollectors:function(){this.D&&(window.removeEventListener?(window.removeEventListener("load",this.a.loadTimeCollector,!1),window.removeEventListener("mousemove",this.a.mouseCollector,!1),window.removeEventListener("keypress",this.a.keyboardCollector,!1),window.removeEventListener("devicemotion",this.a.accelerometerCollector,!1),window.removeEventListener("touchmove",this.a.touchCollector,!1)):document.detachEvent&&(document.detachEvent("onload",this.a.loadTimeCollector),document.detachEvent("onmousemove",
|
|
|
|
|
this.a.mouseCollector),document.detachEvent("keypress",this.a.keyboardCollector)),this.D=!1)},addEventListener:function(a,b){this.K[a][this.ga++]=b},removeEventListener:function(a,b){var c,d,e=this.K[a],f=[];for(d in e)e.hasOwnProperty(d)&&e[d]===b&&f.push(d);for(c=0;c<f.length;c++)d=f[c],delete e[d]},la:function(){C(this,1)},oa:function(a){var b,c;try{b=a.x||a.clientX||a.offsetX||0,c=a.y||a.clientY||a.offsetY||0}catch(d){c=b=0}0!=b&&0!=c&&this.addEntropy([b,c],2,"mouse");C(this,0)},qa:function(a){a=
|
|
|
|
|
a.touches[0]||a.changedTouches[0];this.addEntropy([a.pageX||a.clientX,a.pageY||a.clientY],1,"touch");C(this,0)},ma:function(){C(this,2)},ea:function(a){a=a.accelerationIncludingGravity.x||a.accelerationIncludingGravity.y||a.accelerationIncludingGravity.z;if(window.orientation){var b=window.orientation;"number"===typeof b&&this.addEntropy(b,1,"accelerometer")}a&&this.addEntropy(a,2,"accelerometer");C(this,0)}};
|
|
|
|
|
function A(a,b){var c,d=sjcl.random.K[a],e=[];for(c in d)d.hasOwnProperty(c)&&e.push(d[c]);for(c=0;c<e.length;c++)e[c](b)}function C(a,b){"undefined"!==typeof window&&window.performance&&"function"===typeof window.performance.now?a.addEntropy(window.performance.now(),b,"loadtime"):a.addEntropy((new Date).valueOf(),b,"loadtime")}function y(a){a.b=z(a).concat(z(a));a.L=new sjcl.cipher.aes(a.b)}function z(a){for(var b=0;4>b&&(a.h[b]=a.h[b]+1|0,!a.h[b]);b++);return a.L.encrypt(a.h)}
|
|
|
|
|
function B(a,b){return function(){b.apply(a,arguments)}}sjcl.random=new sjcl.prng(6);
|
|
|
|
|
a:try{var D,E,F,G;if(G="undefined"!==typeof module&&module.exports){var H;try{H=require("crypto")}catch(a){H=null}G=E=H}if(G&&E.randomBytes)D=E.randomBytes(128),D=new Uint32Array((new Uint8Array(D)).buffer),sjcl.random.addEntropy(D,1024,"crypto['randomBytes']");else if("undefined"!==typeof window&&"undefined"!==typeof Uint32Array){F=new Uint32Array(32);if(window.crypto&&window.crypto.getRandomValues)window.crypto.getRandomValues(F);else if(window.msCrypto&&window.msCrypto.getRandomValues)window.msCrypto.getRandomValues(F);
|
|
|
|
|
else break a;sjcl.random.addEntropy(F,1024,"crypto['getRandomValues']")}}catch(a){"undefined"!==typeof window&&window.console&&(console.log("There was an error collecting entropy from the browser:"),console.log(a))}
|
|
|
|
|
sjcl.json={defaults:{v:1,iter:1E4,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},ja:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.g({iv:sjcl.random.randomWords(4,0)},e.defaults),g;e.g(f,c);c=f.adata;"string"===typeof f.salt&&(f.salt=sjcl.codec.base64.toBits(f.salt));"string"===typeof f.iv&&(f.iv=sjcl.codec.base64.toBits(f.iv));if(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||"string"===typeof a&&100>=f.iter||64!==f.ts&&96!==f.ts&&128!==f.ts||128!==f.ks&&192!==f.ks&&0x100!==f.ks||2>f.iv.length||
|
|
|
|
|
4<f.iv.length)throw new sjcl.exception.invalid("json encrypt: invalid parameters");"string"===typeof a?(g=sjcl.misc.cachedPbkdf2(a,f),a=g.key.slice(0,f.ks/32),f.salt=g.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.publicKey&&(g=a.kem(),f.kemtag=g.tag,a=g.key.slice(0,f.ks/32));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));"string"===typeof c&&(f.adata=c=sjcl.codec.utf8String.toBits(c));g=new sjcl.cipher[f.cipher](a);e.g(d,f);d.key=a;f.ct="ccm"===f.mode&&sjcl.arrayBuffer&&sjcl.arrayBuffer.ccm&&
|
|
|
|
|
b instanceof ArrayBuffer?sjcl.arrayBuffer.ccm.encrypt(g,b,f.iv,c,f.ts):sjcl.mode[f.mode].encrypt(g,b,f.iv,c,f.ts);return f},encrypt:function(a,b,c,d){var e=sjcl.json,f=e.ja.apply(e,arguments);return e.encode(f)},ia:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.g(e.g(e.g({},e.defaults),b),c,!0);var f,g;f=b.adata;"string"===typeof b.salt&&(b.salt=sjcl.codec.base64.toBits(b.salt));"string"===typeof b.iv&&(b.iv=sjcl.codec.base64.toBits(b.iv));if(!sjcl.mode[b.mode]||!sjcl.cipher[b.cipher]||"string"===
|
|
|
|
|
typeof a&&100>=b.iter||64!==b.ts&&96!==b.ts&&128!==b.ts||128!==b.ks&&192!==b.ks&&0x100!==b.ks||!b.iv||2>b.iv.length||4<b.iv.length)throw new sjcl.exception.invalid("json decrypt: invalid parameters");"string"===typeof a?(g=sjcl.misc.cachedPbkdf2(a,b),a=g.key.slice(0,b.ks/32),b.salt=g.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.secretKey&&(a=a.unkem(sjcl.codec.base64.toBits(b.kemtag)).slice(0,b.ks/32));"string"===typeof f&&(f=sjcl.codec.utf8String.toBits(f));g=new sjcl.cipher[b.cipher](a);f="ccm"===
|
|
|
|
|
b.mode&&sjcl.arrayBuffer&&sjcl.arrayBuffer.ccm&&b.ct instanceof ArrayBuffer?sjcl.arrayBuffer.ccm.decrypt(g,b.ct,b.iv,b.tag,f,b.ts):sjcl.mode[b.mode].decrypt(g,b.ct,b.iv,f,b.ts);e.g(d,b);d.key=a;return 1===c.raw?f:sjcl.codec.utf8String.fromBits(f)},decrypt:function(a,b,c,d){var e=sjcl.json;return e.ia(a,e.decode(b),c,d)},encode:function(a){var b,c="{",d="";for(b in a)if(a.hasOwnProperty(b)){if(!b.match(/^[a-z0-9]+$/i))throw new sjcl.exception.invalid("json encode: invalid property name");c+=d+'"'+
|
|
|
|
|
b+'":';d=",";switch(typeof a[b]){case "number":case "boolean":c+=a[b];break;case "string":c+='"'+escape(a[b])+'"';break;case "object":c+='"'+sjcl.codec.base64.fromBits(a[b],0)+'"';break;default:throw new sjcl.exception.bug("json encode: unsupported type");}}return c+"}"},decode:function(a){a=a.replace(/\s/g,"");if(!a.match(/^\{.*\}$/))throw new sjcl.exception.invalid("json decode: this isn't json!");a=a.replace(/^\{|\}$/g,"").split(/,/);var b={},c,d;for(c=0;c<a.length;c++){if(!(d=a[c].match(/^\s*(?:(["']?)([a-z][a-z0-9]*)\1)\s*:\s*(?:(-?\d+)|"([a-z0-9+\/%*_.@=\-]*)"|(true|false))$/i)))throw new sjcl.exception.invalid("json decode: this isn't json!");
|
|
|
|
|
null!=d[3]?b[d[2]]=parseInt(d[3],10):null!=d[4]?b[d[2]]=d[2].match(/^(ct|adata|salt|iv)$/)?sjcl.codec.base64.toBits(d[4]):unescape(d[4]):null!=d[5]&&(b[d[2]]="true"===d[5])}return b},g:function(a,b,c){void 0===a&&(a={});if(void 0===b)return a;for(var d in b)if(b.hasOwnProperty(d)){if(c&&void 0!==a[d]&&a[d]!==b[d])throw new sjcl.exception.invalid("required parameter overridden");a[d]=b[d]}return a},sa:function(a,b){var c={},d;for(d in a)a.hasOwnProperty(d)&&a[d]!==b[d]&&(c[d]=a[d]);return c},ra:function(a,
|
|
|
|
|
b){var c={},d;for(d=0;d<b.length;d++)void 0!==a[b[d]]&&(c[b[d]]=a[b[d]]);return c}};sjcl.encrypt=sjcl.json.encrypt;sjcl.decrypt=sjcl.json.decrypt;sjcl.misc.pa={};sjcl.misc.cachedPbkdf2=function(a,b){var c=sjcl.misc.pa,d;b=b||{};d=b.iter||1E3;c=c[a]=c[a]||{};d=c[d]=c[d]||{firstSalt:b.salt&&b.salt.length?b.salt.slice(0):sjcl.random.randomWords(2,0)};c=void 0===b.salt?d.firstSalt:b.salt;d[c]=d[c]||sjcl.misc.pbkdf2(a,c,b.iter);return{key:d[c].slice(0),salt:c.slice(0)}};
|
|
|
|
|
"undefined"!==typeof module&&module.exports&&(module.exports=sjcl);"function"===typeof define&&define([],function(){return sjcl});
|
|
|
|
|
</script>
|
|
|
|
|
</div>
|
|
|
|
|
<!--~~ Boot kernel prologue ~~-->
|
|
|
|
|
<div id="bootKernelPrefix" style="display:none;">
|
|
|
|
|
<script data-tiddler-title="$:/boot/bootprefix.js" data-tiddler-type="application/javascript" type="text/javascript">/*\
|
|
|
|
|
title: $:/boot/bootprefix.js
|
|
|
|
|
type: application/javascript
|
|
|
|
|
|
|
|
|
|
This file sets up the globals that need to be available when JavaScript modules are executed in the browser. The overall sequence is:
|
|
|
|
|
|
|
|
|
|
# BootPrefix.js
|
|
|
|
|
# <module definitions>
|
|
|
|
|
# Boot.js
|
|
|
|
|
|
|
|
|
|
See Boot.js for further details of the boot process.
|
|
|
|
|
|
|
|
|
|
\*/
|
|
|
|
|
|
|
|
|
|
var _bootprefix = (function($tw) {
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
$tw = $tw || Object.create(null);
|
|
|
|
|
$tw.boot = $tw.boot || Object.create(null);
|
|
|
|
|
|
|
|
|
|
// Detect platforms
|
|
|
|
|
if(!("browser" in $tw)) {
|
|
|
|
|
$tw.browser = typeof(window) !== "undefined" ? {} : null;
|
|
|
|
|
}
|
|
|
|
|
if(!("node" in $tw)) {
|
|
|
|
|
$tw.node = typeof(process) === "object" ? {} : null;
|
|
|
|
|
}
|
|
|
|
|
if(!("nodeWebKit" in $tw)) {
|
|
|
|
|
$tw.nodeWebKit = $tw.node && global.window && global.window.nwDispatcher ? {} : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set default boot tasks
|
|
|
|
|
$tw.boot.tasks = {
|
|
|
|
|
trapErrors: !!($tw.browser && !$tw.node),
|
|
|
|
|
readBrowserTiddlers: !!($tw.browser && !$tw.node)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Information about each module is kept in an object with these members:
|
|
|
|
|
moduleType: type of module
|
|
|
|
|
definition: object, function or string defining the module; see below
|
|
|
|
|
exports: exports of the module, filled in after execution
|
|
|
|
|
|
|
|
|
|
The `definition` can be of several types:
|
|
|
|
|
|
|
|
|
|
* An object can be used to directly specify the exports of the module
|
|
|
|
|
* A function with the arguments `module,require,exports` that returns `exports`
|
|
|
|
|
* A string function body with the same arguments
|
|
|
|
|
|
|
|
|
|
Each moduleInfo object is stored in two hashmaps: $tw.modules.titles and $tw.modules.types. The first is indexed by title and the second is indexed by type and then title
|
|
|
|
|
*/
|
|
|
|
|
$tw.modules = {
|
|
|
|
|
titles: {}, // hashmap by module name of moduleInfo
|
|
|
|
|
types: {} // hashmap by module type and then name of moduleInfo
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Define a JavaScript tiddler module for later execution
|
|
|
|
|
moduleName: name of module being defined
|
|
|
|
|
moduleType: type of module
|
|
|
|
|
definition: module definition; see discussion above
|
|
|
|
|
*/
|
|
|
|
|
$tw.modules.define = function(moduleName,moduleType,definition) {
|
|
|
|
|
// Create the moduleInfo
|
|
|
|
|
var moduleInfo = {
|
|
|
|
|
moduleType: moduleType,
|
|
|
|
|
definition: definition,
|
|
|
|
|
exports: undefined
|
|
|
|
|
};
|
|
|
|
|
// If the definition is already an object we can use it as the exports
|
|
|
|
|
if(typeof moduleInfo.definition === "object") {
|
|
|
|
|
moduleInfo.exports = definition;
|
|
|
|
|
}
|
|
|
|
|
// Store the module in the titles hashmap
|
|
|
|
|
if(Object.prototype.hasOwnProperty.call($tw.modules.titles,moduleName)) {
|
|
|
|
|
console.log("Warning: Redefined module - " + moduleName);
|
|
|
|
|
}
|
|
|
|
|
$tw.modules.titles[moduleName] = moduleInfo;
|
|
|
|
|
// Store the module in the types hashmap
|
|
|
|
|
if(!Object.prototype.hasOwnProperty.call($tw.modules.types,moduleType)) {
|
|
|
|
|
$tw.modules.types[moduleType] = {};
|
|
|
|
|
}
|
|
|
|
|
if(Object.prototype.hasOwnProperty.call($tw.modules.types[moduleType],moduleName)) {
|
|
|
|
|
console.log("Warning: Redefined module - " + moduleName);
|
|
|
|
|
}
|
|
|
|
|
$tw.modules.types[moduleType][moduleName] = moduleInfo;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
External JavaScript can populate this array before calling boot.js in order to preload tiddlers
|
|
|
|
|
*/
|
|
|
|
|
$tw.preloadTiddlers = $tw.preloadTiddlers || [];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Convenience function for pushing a tiddler onto the preloading array
|
|
|
|
|
*/
|
|
|
|
|
$tw.preloadTiddler = function(fields) {
|
|
|
|
|
$tw.preloadTiddlers.push(fields);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Convenience function for pushing an array of tiddlers onto the preloading array
|
|
|
|
|
*/
|
|
|
|
|
$tw.preloadTiddlerArray = function(fieldsArray) {
|
|
|
|
|
$tw.preloadTiddlers.push.apply($tw.preloadTiddlers,fieldsArray);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return $tw;
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(typeof(exports) === "undefined") {
|
|
|
|
|
// Set up $tw global for the browser
|
|
|
|
|
window.$tw = _bootprefix(window.$tw);
|
|
|
|
|
} else {
|
|
|
|
|
// Export functionality as a module
|
|
|
|
|
exports.bootprefix = _bootprefix;
|
|
|
|
|
}
|
|
|
|
|
//# sourceURL=$:/boot/bootprefix.js
|
|
|
|
|
</script>
|
|
|
|
|
</div>
|
|
|
|
|
<!--~~ Boot kernel ~~-->
|
|
|
|
|
<div id="bootKernel" style="display:none;">
|
|
|
|
|
<script data-tiddler-title="$:/boot/boot.js" data-tiddler-type="application/javascript" type="text/javascript">/*\
|
|
|
|
|
title: $:/boot/boot.js
|
|
|
|
|
type: application/javascript
|
|
|
|
|
|
|
|
|
|
The main boot kernel for TiddlyWiki. This single file creates a barebones TW environment that is just sufficient to bootstrap the modules containing the main logic of the application.
|
|
|
|
|
|
|
|
|
|
On the server this file is executed directly to boot TiddlyWiki. In the browser, this file is packed into a single HTML file.
|
|
|
|
|
|
|
|
|
|
\*/
|
|
|
|
|
|
|
|
|
|
var _boot = (function($tw) {
|
|
|
|
|
|
|
|
|
|
/*jslint node: true, browser: true */
|
|
|
|
|
/*global modules: false, $tw: false */
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
// Include bootprefix if we're not given module data
|
|
|
|
|
if(!$tw) {
|
|
|
|
|
$tw = require("./bootprefix.js").bootprefix();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$tw.utils = $tw.utils || Object.create(null);
|
|
|
|
|
|
|
|
|
|
/////////////////////////// Standard node.js libraries
|
|
|
|
|
|
|
|
|
|
var fs, path, vm;
|
|
|
|
|
if($tw.node) {
|
|
|
|
|
fs = require("fs");
|
|
|
|
|
path = require("path");
|
|
|
|
|
vm = require("vm");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////// Utility functions
|
|
|
|
|
|
|
|
|
|
$tw.boot.log = function(str) {
|
|
|
|
|
$tw.boot.logMessages = $tw.boot.logMessages || [];
|
|
|
|
|
$tw.boot.logMessages.push(str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Check if an object has a property
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.hop = function(object,property) {
|
|
|
|
|
return object ? Object.prototype.hasOwnProperty.call(object,property) : false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Determine if a value is an array
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.isArray = function(value) {
|
|
|
|
|
return Object.prototype.toString.call(value) == "[object Array]";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Check if an array is equal by value and by reference.
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.isArrayEqual = function(array1,array2) {
|
|
|
|
|
if(array1 === array2) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
array1 = array1 || [];
|
|
|
|
|
array2 = array2 || [];
|
|
|
|
|
if(array1.length !== array2.length) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return array1.every(function(value,index) {
|
|
|
|
|
return value === array2[index];
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Add an entry to a sorted array if it doesn't already exist, while maintaining the sort order
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.insertSortedArray = function(array,value) {
|
|
|
|
|
var low = 0, high = array.length - 1, mid, cmp;
|
|
|
|
|
while(low <= high) {
|
|
|
|
|
mid = (low + high) >> 1;
|
|
|
|
|
cmp = value.localeCompare(array[mid]);
|
|
|
|
|
if(cmp > 0) {
|
|
|
|
|
low = mid + 1;
|
|
|
|
|
} else if(cmp < 0) {
|
|
|
|
|
high = mid - 1;
|
|
|
|
|
} else {
|
|
|
|
|
return array;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
array.splice(low,0,value);
|
|
|
|
|
return array;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Push entries onto an array, removing them first if they already exist in the array
|
|
|
|
|
array: array to modify (assumed to be free of duplicates)
|
|
|
|
|
value: a single value to push or an array of values to push
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.pushTop = function(array,value) {
|
|
|
|
|
var t,p;
|
|
|
|
|
if($tw.utils.isArray(value)) {
|
|
|
|
|
// Remove any array entries that are duplicated in the new values
|
|
|
|
|
if(value.length !== 0) {
|
|
|
|
|
if(array.length !== 0) {
|
|
|
|
|
if(value.length < array.length) {
|
|
|
|
|
for(t=0; t<value.length; t++) {
|
|
|
|
|
p = array.indexOf(value[t]);
|
|
|
|
|
if(p !== -1) {
|
|
|
|
|
array.splice(p,1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for(t=array.length-1; t>=0; t--) {
|
|
|
|
|
p = value.indexOf(array[t]);
|
|
|
|
|
if(p !== -1) {
|
|
|
|
|
array.splice(t,1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Push the values on top of the main array
|
|
|
|
|
array.push.apply(array,value);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
p = array.indexOf(value);
|
|
|
|
|
if(p !== -1) {
|
|
|
|
|
array.splice(p,1);
|
|
|
|
|
}
|
|
|
|
|
array.push(value);
|
|
|
|
|
}
|
|
|
|
|
return array;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Determine if a value is a date
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.isDate = function(value) {
|
|
|
|
|
return Object.prototype.toString.call(value) === "[object Date]";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Iterate through all the own properties of an object or array. Callback is invoked with (element,title,object)
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.each = function(object,callback) {
|
|
|
|
|
var next,f,length;
|
|
|
|
|
if(object) {
|
|
|
|
|
if(Object.prototype.toString.call(object) == "[object Array]") {
|
|
|
|
|
for (f=0, length=object.length; f<length; f++) {
|
|
|
|
|
next = callback(object[f],f,object);
|
|
|
|
|
if(next === false) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
var keys = Object.keys(object);
|
|
|
|
|
for (f=0, length=keys.length; f<length; f++) {
|
|
|
|
|
var key = keys[f];
|
|
|
|
|
next = callback(object[key],key,object);
|
|
|
|
|
if(next === false) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Helper for making DOM elements
|
|
|
|
|
tag: tag name
|
|
|
|
|
options: see below
|
|
|
|
|
Options include:
|
|
|
|
|
namespace: defaults to http://www.w3.org/1999/xhtml
|
|
|
|
|
attributes: hashmap of attribute values
|
|
|
|
|
style: hashmap of styles
|
|
|
|
|
text: text to add as a child node
|
|
|
|
|
children: array of further child nodes
|
|
|
|
|
innerHTML: optional HTML for element
|
|
|
|
|
class: class name(s)
|
|
|
|
|
document: defaults to current document
|
|
|
|
|
eventListeners: array of event listeners (this option won't work until $tw.utils.addEventListeners() has been loaded)
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.domMaker = function(tag,options) {
|
|
|
|
|
var doc = options.document || document;
|
|
|
|
|
var element = doc.createElementNS(options.namespace || "http://www.w3.org/1999/xhtml",tag);
|
|
|
|
|
if(options["class"]) {
|
|
|
|
|
element.className = options["class"];
|
|
|
|
|
}
|
|
|
|
|
if(options.text) {
|
|
|
|
|
element.appendChild(doc.createTextNode(options.text));
|
|
|
|
|
}
|
|
|
|
|
$tw.utils.each(options.children,function(child) {
|
|
|
|
|
element.appendChild(child);
|
|
|
|
|
});
|
|
|
|
|
if(options.innerHTML) {
|
|
|
|
|
element.innerHTML = options.innerHTML;
|
|
|
|
|
}
|
|
|
|
|
$tw.utils.each(options.attributes,function(attribute,name) {
|
|
|
|
|
element.setAttribute(name,attribute);
|
|
|
|
|
});
|
|
|
|
|
$tw.utils.each(options.style,function(value,name) {
|
|
|
|
|
element.style[name] = value;
|
|
|
|
|
});
|
|
|
|
|
if(options.eventListeners) {
|
|
|
|
|
$tw.utils.addEventListeners(element,options.eventListeners);
|
|
|
|
|
}
|
|
|
|
|
return element;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Display an error and exit
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.error = function(err) {
|
|
|
|
|
// Prepare the error message
|
|
|
|
|
var errHeading = ( $tw.language == undefined ? "Internal JavaScript Error" : $tw.language.getString("InternalJavaScriptError/Title") ),
|
|
|
|
|
promptMsg = ( $tw.language == undefined ? "Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser" : $tw.language.getString("InternalJavaScriptError/Hint") );
|
|
|
|
|
// Log the error to the console
|
|
|
|
|
console.error($tw.node ? "\x1b[1;31m" + err + "\x1b[0m" : err);
|
|
|
|
|
if($tw.browser && !$tw.node) {
|
|
|
|
|
// Display an error message to the user
|
|
|
|
|
var dm = $tw.utils.domMaker,
|
|
|
|
|
heading = dm("h1",{text: errHeading}),
|
|
|
|
|
prompt = dm("div",{text: promptMsg, "class": "tc-error-prompt"}),
|
|
|
|
|
message = dm("div",{text: err, "class":"tc-error-message"}),
|
|
|
|
|
button = dm("div",{children: [dm("button",{text: ( $tw.language == undefined ? "close" : $tw.language.getString("Buttons/Close/Caption") )})], "class": "tc-error-prompt"}),
|
|
|
|
|
form = dm("form",{children: [heading,prompt,message,button], "class": "tc-error-form"});
|
|
|
|
|
document.body.insertBefore(form,document.body.firstChild);
|
|
|
|
|
form.addEventListener("submit",function(event) {
|
|
|
|
|
document.body.removeChild(form);
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
return false;
|
|
|
|
|
},true);
|
|
|
|
|
return null;
|
|
|
|
|
} else if(!$tw.browser) {
|
|
|
|
|
// Exit if we're under node.js
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Use our custom error handler if we're in the browser
|
|
|
|
|
*/
|
|
|
|
|
if($tw.boot.tasks.trapErrors) {
|
|
|
|
|
window.onerror = function(errorMsg,url,lineNumber) {
|
|
|
|
|
$tw.utils.error(errorMsg);
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Extend an object with the properties from a list of source objects
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.extend = function(object /*, sourceObjectList */) {
|
|
|
|
|
$tw.utils.each(Array.prototype.slice.call(arguments,1),function(source) {
|
|
|
|
|
if(source) {
|
|
|
|
|
for (var p in source) {
|
|
|
|
|
object[p] = source[p];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return object;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Fill in any null or undefined properties of an object with the properties from a list of source objects. Each property that is an object is called recursively
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.deepDefaults = function(object /*, sourceObjectList */) {
|
|
|
|
|
$tw.utils.each(Array.prototype.slice.call(arguments,1),function(source) {
|
|
|
|
|
if(source) {
|
|
|
|
|
for (var p in source) {
|
|
|
|
|
if(object[p] === null || object[p] === undefined) {
|
|
|
|
|
object[p] = source[p];
|
|
|
|
|
}
|
|
|
|
|
if(typeof object[p] === "object" && typeof source[p] === "object") {
|
|
|
|
|
$tw.utils.deepDefaults(object[p],source[p]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return object;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Convert a URIComponent encoded string to a string safely
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.decodeURIComponentSafe = function(s) {
|
|
|
|
|
var v = s;
|
|
|
|
|
try {
|
|
|
|
|
v = decodeURIComponent(s);
|
|
|
|
|
} catch(e) {}
|
|
|
|
|
return v;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Convert a URI encoded string to a string safely
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.decodeURISafe = function(s) {
|
|
|
|
|
var v = s;
|
|
|
|
|
try {
|
|
|
|
|
v = decodeURI(s);
|
|
|
|
|
} catch(e) {}
|
|
|
|
|
return v;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Convert "&" to &, " " to nbsp, "<" to <, ">" to > and """ to "
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.htmlDecode = function(s) {
|
|
|
|
|
return s.toString().replace(/</mg,"<").replace(/ /mg,"\xA0").replace(/>/mg,">").replace(/"/mg,"\"").replace(/&/mg,"&");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.getLocationHash = function() {
|
|
|
|
|
var href = window.location.href;
|
|
|
|
|
var idx = href.indexOf('#');
|
|
|
|
|
if(idx === -1) {
|
|
|
|
|
return "#";
|
|
|
|
|
} else if(href.substr(idx + 1,1) === "#" || href.substr(idx + 1,3) === "%23") {
|
|
|
|
|
// Special case: ignore location hash if it itself starts with a #
|
|
|
|
|
return "#";
|
|
|
|
|
} else {
|
|
|
|
|
return href.substring(idx);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Pad a string to a given length with "0"s. Length defaults to 2
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.pad = function(value,length) {
|
|
|
|
|
length = length || 2;
|
|
|
|
|
var s = value.toString();
|
|
|
|
|
if(s.length < length) {
|
|
|
|
|
s = "000000000000000000000000000".substr(0,length - s.length) + s;
|
|
|
|
|
}
|
|
|
|
|
return s;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Convert a date into UTC YYYYMMDDHHMMSSmmm format
|
|
|
|
|
$tw.utils.stringifyDate = function(value) {
|
|
|
|
|
return value.getUTCFullYear() +
|
|
|
|
|
$tw.utils.pad(value.getUTCMonth() + 1) +
|
|
|
|
|
$tw.utils.pad(value.getUTCDate()) +
|
|
|
|
|
$tw.utils.pad(value.getUTCHours()) +
|
|
|
|
|
$tw.utils.pad(value.getUTCMinutes()) +
|
|
|
|
|
$tw.utils.pad(value.getUTCSeconds()) +
|
|
|
|
|
$tw.utils.pad(value.getUTCMilliseconds(),3);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Parse a date from a UTC YYYYMMDDHHMMSSmmm format string
|
|
|
|
|
$tw.utils.parseDate = function(value) {
|
|
|
|
|
if(typeof value === "string") {
|
|
|
|
|
var negative = 1;
|
|
|
|
|
if(value.charAt(0) === "-") {
|
|
|
|
|
negative = -1;
|
|
|
|
|
value = value.substr(1);
|
|
|
|
|
}
|
|
|
|
|
var year = parseInt(value.substr(0,4),10) * negative,
|
|
|
|
|
d = new Date(Date.UTC(year,
|
|
|
|
|
parseInt(value.substr(4,2),10)-1,
|
|
|
|
|
parseInt(value.substr(6,2),10),
|
|
|
|
|
parseInt(value.substr(8,2)||"00",10),
|
|
|
|
|
parseInt(value.substr(10,2)||"00",10),
|
|
|
|
|
parseInt(value.substr(12,2)||"00",10),
|
|
|
|
|
parseInt(value.substr(14,3)||"000",10)));
|
|
|
|
|
d.setUTCFullYear(year); // See https://stackoverflow.com/a/5870822
|
|
|
|
|
return d;
|
|
|
|
|
} else if($tw.utils.isDate(value)) {
|
|
|
|
|
return value;
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Stringify an array of tiddler titles into a list string
|
|
|
|
|
$tw.utils.stringifyList = function(value) {
|
|
|
|
|
if($tw.utils.isArray(value)) {
|
|
|
|
|
var result = new Array(value.length);
|
|
|
|
|
for(var t=0, l=value.length; t<l; t++) {
|
|
|
|
|
var entry = value[t] || "";
|
|
|
|
|
if(entry.match(/[^\S\xA0]/mg)) {
|
|
|
|
|
result[t] = "[[" + entry + "]]";
|
|
|
|
|
} else {
|
|
|
|
|
result[t] = entry;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result.join(" ");
|
|
|
|
|
} else {
|
|
|
|
|
return value || "";
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Parse a string array from a bracketted list. For example "OneTiddler [[Another Tiddler]] LastOne"
|
|
|
|
|
$tw.utils.parseStringArray = function(value, allowDuplicate) {
|
|
|
|
|
if(typeof value === "string") {
|
|
|
|
|
var memberRegExp = /(?:^|[^\S\xA0])(?:\[\[(.*?)\]\])(?=[^\S\xA0]|$)|([\S\xA0]+)/mg,
|
|
|
|
|
results = [], names = {},
|
|
|
|
|
match;
|
|
|
|
|
do {
|
|
|
|
|
match = memberRegExp.exec(value);
|
|
|
|
|
if(match) {
|
|
|
|
|
var item = match[1] || match[2];
|
|
|
|
|
if(item !== undefined && (!$tw.utils.hop(names,item) || allowDuplicate)) {
|
|
|
|
|
results.push(item);
|
|
|
|
|
names[item] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} while(match);
|
|
|
|
|
return results;
|
|
|
|
|
} else if($tw.utils.isArray(value)) {
|
|
|
|
|
return value;
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Parse a block of name:value fields. The `fields` object is used as the basis for the return value
|
|
|
|
|
$tw.utils.parseFields = function(text,fields) {
|
|
|
|
|
fields = fields || Object.create(null);
|
|
|
|
|
text.split(/\r?\n/mg).forEach(function(line) {
|
|
|
|
|
if(line.charAt(0) !== "#") {
|
|
|
|
|
var p = line.indexOf(":");
|
|
|
|
|
if(p !== -1) {
|
|
|
|
|
var field = line.substr(0, p).trim(),
|
|
|
|
|
value = line.substr(p+1).trim();
|
|
|
|
|
if(field) {
|
|
|
|
|
fields[field] = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return fields;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Safely parse a string as JSON
|
|
|
|
|
$tw.utils.parseJSONSafe = function(text,defaultJSON) {
|
|
|
|
|
try {
|
|
|
|
|
return JSON.parse(text);
|
|
|
|
|
} catch(e) {
|
|
|
|
|
if(typeof defaultJSON === "function") {
|
|
|
|
|
return defaultJSON(e);
|
|
|
|
|
} else {
|
|
|
|
|
return defaultJSON || {};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Resolves a source filepath delimited with `/` relative to a specified absolute root filepath.
|
|
|
|
|
In relative paths, the special folder name `..` refers to immediate parent directory, and the
|
|
|
|
|
name `.` refers to the current directory
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.resolvePath = function(sourcepath,rootpath) {
|
|
|
|
|
// If the source path starts with ./ or ../ then it is relative to the root
|
|
|
|
|
if(sourcepath.substr(0,2) === "./" || sourcepath.substr(0,3) === "../" ) {
|
|
|
|
|
var src = sourcepath.split("/"),
|
|
|
|
|
root = rootpath.split("/");
|
|
|
|
|
// Remove the filename part of the root
|
|
|
|
|
root.splice(root.length-1,1);
|
|
|
|
|
// Process the source path bit by bit onto the end of the root path
|
|
|
|
|
while(src.length > 0) {
|
|
|
|
|
var c = src.shift();
|
|
|
|
|
if(c === "..") { // Slice off the last root entry for a double dot
|
|
|
|
|
if(root.length > 0) {
|
|
|
|
|
root.splice(root.length-1,1);
|
|
|
|
|
}
|
|
|
|
|
} else if(c !== ".") { // Ignore dots
|
|
|
|
|
root.push(c); // Copy other elements across
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return root.join("/");
|
|
|
|
|
} else {
|
|
|
|
|
// If it isn't relative, just return the path
|
|
|
|
|
if(rootpath) {
|
|
|
|
|
var root = rootpath.split("/");
|
|
|
|
|
// Remove the filename part of the root
|
|
|
|
|
root.splice(root.length - 1, 1);
|
|
|
|
|
return root.join("/") + "/" + sourcepath;
|
|
|
|
|
} else {
|
|
|
|
|
return sourcepath;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Parse a semantic version string into its constituent parts -- see https://semver.org
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.parseVersion = function(version) {
|
|
|
|
|
var match = /^v?((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/.exec(version);
|
|
|
|
|
if(match) {
|
|
|
|
|
return {
|
|
|
|
|
version: match[1],
|
|
|
|
|
major: parseInt(match[2],10),
|
|
|
|
|
minor: parseInt(match[3],10),
|
|
|
|
|
patch: parseInt(match[4],10),
|
|
|
|
|
prerelease: match[5],
|
|
|
|
|
build: match[6]
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Returns +1 if the version string A is greater than the version string B, 0 if they are the same, and +1 if B is greater than A.
|
|
|
|
|
Missing or malformed version strings are parsed as 0.0.0
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.compareVersions = function(versionStringA,versionStringB) {
|
|
|
|
|
var defaultVersion = {
|
|
|
|
|
major: 0,
|
|
|
|
|
minor: 0,
|
|
|
|
|
patch: 0
|
|
|
|
|
},
|
|
|
|
|
versionA = $tw.utils.parseVersion(versionStringA) || defaultVersion,
|
|
|
|
|
versionB = $tw.utils.parseVersion(versionStringB) || defaultVersion,
|
|
|
|
|
diff = [
|
|
|
|
|
versionA.major - versionB.major,
|
|
|
|
|
versionA.minor - versionB.minor,
|
|
|
|
|
versionA.patch - versionB.patch
|
|
|
|
|
];
|
|
|
|
|
if((diff[0] > 0) || (diff[0] === 0 && diff[1] > 0) || (diff[0] === 0 & diff[1] === 0 & diff[2] > 0)) {
|
|
|
|
|
return +1;
|
|
|
|
|
} else if((diff[0] < 0) || (diff[0] === 0 && diff[1] < 0) || (diff[0] === 0 & diff[1] === 0 & diff[2] < 0)) {
|
|
|
|
|
return -1;
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Returns true if the version string A is greater than the version string B. Returns true if the versions are the same
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.checkVersions = function(versionStringA,versionStringB) {
|
|
|
|
|
return $tw.utils.compareVersions(versionStringA,versionStringB) !== -1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Register file type information
|
|
|
|
|
options: {flags: flags,deserializerType: deserializerType}
|
|
|
|
|
flags:"image" for image types
|
|
|
|
|
deserializerType: defaults to type if not specified
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.registerFileType = function(type,encoding,extension,options) {
|
|
|
|
|
options = options || {};
|
|
|
|
|
if($tw.utils.isArray(extension)) {
|
|
|
|
|
$tw.utils.each(extension,function(extension) {
|
|
|
|
|
$tw.config.fileExtensionInfo[extension] = {type: type};
|
|
|
|
|
});
|
|
|
|
|
extension = extension[0];
|
|
|
|
|
} else {
|
|
|
|
|
$tw.config.fileExtensionInfo[extension] = {type: type};
|
|
|
|
|
}
|
|
|
|
|
$tw.config.contentTypeInfo[type] = {encoding: encoding, extension: extension, flags: options.flags || [], deserializerType: options.deserializerType || type};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Given an extension, always access the $tw.config.fileExtensionInfo
|
|
|
|
|
using a lowercase extension only.
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.getFileExtensionInfo = function(ext) {
|
|
|
|
|
return ext ? $tw.config.fileExtensionInfo[ext.toLowerCase()] : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Given an extension, get the correct encoding for that file.
|
|
|
|
|
defaults to utf8
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.getTypeEncoding = function(ext) {
|
|
|
|
|
var extensionInfo = $tw.utils.getFileExtensionInfo(ext),
|
|
|
|
|
type = extensionInfo ? extensionInfo.type : null,
|
|
|
|
|
typeInfo = type ? $tw.config.contentTypeInfo[type] : null;
|
|
|
|
|
return typeInfo ? typeInfo.encoding : "utf8";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var globalCheck =[
|
|
|
|
|
" Object.defineProperty(Object.prototype, '__temp__', {",
|
|
|
|
|
" get: function () { return this; },",
|
|
|
|
|
" configurable: true",
|
|
|
|
|
" });",
|
|
|
|
|
" if(Object.keys(__temp__).length){",
|
|
|
|
|
" console.log(\"Warning: Global assignment detected\",Object.keys(__temp__));",
|
|
|
|
|
" delete Object.prototype.__temp__;",
|
|
|
|
|
" }",
|
|
|
|
|
" delete Object.prototype.__temp__;",
|
|
|
|
|
].join('\n');
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Run code globally with specified context variables in scope
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
|
|
|
|
|
var contextCopy = $tw.utils.extend(Object.create(null),context);
|
|
|
|
|
// Get the context variables as a pair of arrays of names and values
|
|
|
|
|
var contextNames = [], contextValues = [];
|
|
|
|
|
$tw.utils.each(contextCopy,function(value,name) {
|
|
|
|
|
contextNames.push(name);
|
|
|
|
|
contextValues.push(value);
|
|
|
|
|
});
|
|
|
|
|
// Add the code prologue and epilogue
|
|
|
|
|
code = [
|
|
|
|
|
"(function(" + contextNames.join(",") + ") {",
|
|
|
|
|
" (function(){" + code + "\n;})();\n",
|
|
|
|
|
(!$tw.browser && sandbox && !allowGlobals) ? globalCheck : "",
|
|
|
|
|
"\nreturn exports;\n",
|
|
|
|
|
"})"
|
|
|
|
|
].join("");
|
|
|
|
|
|
|
|
|
|
// Compile the code into a function
|
|
|
|
|
var fn;
|
|
|
|
|
if($tw.browser) {
|
|
|
|
|
fn = window["eval"](code + "\n\n//# sourceURL=" + filename);
|
|
|
|
|
} else {
|
|
|
|
|
if(sandbox){
|
|
|
|
|
fn = vm.runInContext(code,sandbox,filename)
|
|
|
|
|
} else {
|
|
|
|
|
fn = vm.runInThisContext(code,filename);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Call the function and return the exports
|
|
|
|
|
return fn.apply(null,contextValues);
|
|
|
|
|
};
|
|
|
|
|
$tw.utils.sandbox = !$tw.browser ? vm.createContext({}) : undefined;
|
|
|
|
|
/*
|
|
|
|
|
Run code in a sandbox with only the specified context variables in scope
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.evalSandboxed = $tw.browser ? $tw.utils.evalGlobal : function(code,context,filename,allowGlobals) {
|
|
|
|
|
return $tw.utils.evalGlobal(
|
|
|
|
|
code,context,filename,
|
|
|
|
|
allowGlobals ? vm.createContext({}) : $tw.utils.sandbox,
|
|
|
|
|
allowGlobals
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Creates a PasswordPrompt object
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.PasswordPrompt = function() {
|
|
|
|
|
// Store of pending password prompts
|
|
|
|
|
this.passwordPrompts = [];
|
|
|
|
|
// Create the wrapper
|
|
|
|
|
this.promptWrapper = $tw.utils.domMaker("div",{"class":"tc-password-wrapper"});
|
|
|
|
|
document.body.appendChild(this.promptWrapper);
|
|
|
|
|
// Hide the empty wrapper
|
|
|
|
|
this.setWrapperDisplay();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Hides or shows the wrapper depending on whether there are any outstanding prompts
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.PasswordPrompt.prototype.setWrapperDisplay = function() {
|
|
|
|
|
if(this.passwordPrompts.length) {
|
|
|
|
|
this.promptWrapper.style.display = "block";
|
|
|
|
|
} else {
|
|
|
|
|
this.promptWrapper.style.display = "none";
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Adds a new password prompt. Options are:
|
|
|
|
|
submitText: text to use for submit button (defaults to "Login")
|
|
|
|
|
serviceName: text of the human readable service name
|
|
|
|
|
noUserName: set true to disable username prompt
|
|
|
|
|
canCancel: set true to enable a cancel button (callback called with null)
|
|
|
|
|
repeatPassword: set true to prompt for the password twice
|
|
|
|
|
callback: function to be called on submission with parameter of object {username:,password:}. Callback must return `true` to remove the password prompt
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.PasswordPrompt.prototype.createPrompt = function(options) {
|
|
|
|
|
// Create and add the prompt to the DOM
|
|
|
|
|
var self = this,
|
|
|
|
|
submitText = options.submitText || "Login",
|
|
|
|
|
dm = $tw.utils.domMaker,
|
|
|
|
|
children = [dm("h1",{text: options.serviceName})];
|
|
|
|
|
if(!options.noUserName) {
|
|
|
|
|
children.push(dm("input",{
|
|
|
|
|
attributes: {type: "text", name: "username", placeholder: $tw.language.getString("Encryption/Username")}
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
children.push(dm("input",{
|
|
|
|
|
attributes: {
|
|
|
|
|
type: "password",
|
|
|
|
|
name: "password",
|
|
|
|
|
placeholder: ( $tw.language == undefined ? "Password" : $tw.language.getString("Encryption/Password") )
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
if(options.repeatPassword) {
|
|
|
|
|
children.push(dm("input",{
|
|
|
|
|
attributes: {
|
|
|
|
|
type: "password",
|
|
|
|
|
name: "password2",
|
|
|
|
|
placeholder: $tw.language.getString("Encryption/RepeatPassword")
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
if(options.canCancel) {
|
|
|
|
|
children.push(dm("button",{
|
|
|
|
|
text: $tw.language.getString("Encryption/Cancel"),
|
|
|
|
|
attributes: {
|
|
|
|
|
type: "button"
|
|
|
|
|
},
|
|
|
|
|
eventListeners: [{
|
|
|
|
|
name: "click",
|
|
|
|
|
handlerFunction: function(event) {
|
|
|
|
|
self.removePrompt(promptInfo);
|
|
|
|
|
options.callback(null);
|
|
|
|
|
}
|
|
|
|
|
}]
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
children.push(dm("button",{
|
|
|
|
|
attributes: {type: "submit"},
|
|
|
|
|
text: submitText
|
|
|
|
|
}));
|
|
|
|
|
var form = dm("form",{
|
|
|
|
|
attributes: {autocomplete: "off"},
|
|
|
|
|
children: children
|
|
|
|
|
});
|
|
|
|
|
this.promptWrapper.appendChild(form);
|
|
|
|
|
window.setTimeout(function() {
|
|
|
|
|
form.elements[0].focus();
|
|
|
|
|
},10);
|
|
|
|
|
// Add a submit event handler
|
|
|
|
|
var self = this;
|
|
|
|
|
form.addEventListener("submit",function(event) {
|
|
|
|
|
// Collect the form data
|
|
|
|
|
var data = {},t;
|
|
|
|
|
$tw.utils.each(form.elements,function(element) {
|
|
|
|
|
if(element.name && element.value) {
|
|
|
|
|
data[element.name] = element.value;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// Check that the passwords match
|
|
|
|
|
if(options.repeatPassword && data.password !== data.password2) {
|
|
|
|
|
alert($tw.language.getString("Encryption/PasswordNoMatch"));
|
|
|
|
|
} else {
|
|
|
|
|
// Call the callback
|
|
|
|
|
if(options.callback(data)) {
|
|
|
|
|
// Remove the prompt if the callback returned true
|
|
|
|
|
self.removePrompt(promptInfo);
|
|
|
|
|
} else {
|
|
|
|
|
// Clear the password if the callback returned false
|
|
|
|
|
$tw.utils.each(form.elements,function(element) {
|
|
|
|
|
if(element.name === "password" || element.name === "password2") {
|
|
|
|
|
element.value = "";
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
return false;
|
|
|
|
|
},true);
|
|
|
|
|
// Add the prompt to the list
|
|
|
|
|
var promptInfo = {
|
|
|
|
|
serviceName: options.serviceName,
|
|
|
|
|
callback: options.callback,
|
|
|
|
|
form: form,
|
|
|
|
|
owner: this
|
|
|
|
|
};
|
|
|
|
|
this.passwordPrompts.push(promptInfo);
|
|
|
|
|
// Make sure the wrapper is displayed
|
|
|
|
|
this.setWrapperDisplay();
|
|
|
|
|
return promptInfo;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$tw.utils.PasswordPrompt.prototype.removePrompt = function(promptInfo) {
|
|
|
|
|
var i = this.passwordPrompts.indexOf(promptInfo);
|
|
|
|
|
if(i !== -1) {
|
|
|
|
|
this.passwordPrompts.splice(i,1);
|
|
|
|
|
promptInfo.form.parentNode.removeChild(promptInfo.form);
|
|
|
|
|
this.setWrapperDisplay();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Crypto helper object for encrypted content. It maintains the password text in a closure, and provides methods to change
|
|
|
|
|
the password, and to encrypt/decrypt a block of text
|
|
|
|
|
*/
|
|
|
|
|
$tw.utils.Crypto = function() {
|
|
|
|
|
var sjcl = $tw.node ? (global.sjcl || require("./sjcl.js")) : window.sjcl,
|
|
|
|
|
currentPassword = null,
|
|
|
|
|
callSjcl = function(method,inputText,password) {
|
|
|
|
|
password = password || currentPassword;
|
|
|
|
|
var outputText;
|
|
|
|
|
try {
|
|
|
|
|
if(password) {
|
|
|
|
|
outputText = sjcl[method](password,inputText);
|
|
|
|
|
}
|
|
|
|
|
} catch(ex) {
|
|
|
|
|
console.log("Crypto error:" + ex);
|
|
|
|
|
outputText = null;
|
|
|
|
|
}
|
|
|
|
|
return outputText;
|
|
|
|
|
};
|
|
|
|
|
this.setPassword = function(newPassword) {
|
|
|
|
|
currentPassword = newPassword;
|
|
|
|
|
this.updateCryptoStateTiddler();
|
|
|
|
|
};
|
|
|
|
|
this.updateCryptoStateTiddler = function() {
|
|
|
|
|
if($tw.wiki) {
|
|
|
|
|
var state = currentPassword ? "yes" : "no",
|
|
|
|
|
tiddler = $tw.wiki.getTiddler("$:/isEncrypted");
|
|
|
|
|
if(!tiddler || tiddler.fields.text !== state) {
|
|
|
|
|
$tw.wiki.addTiddler(new $tw.Tiddler({title: "$:/isEncrypted", text: state}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.hasPassword = function() {
|
|
|
|
|
return !!currentPassword;
|
|
|
|
|
}
|
|
|
|
|
this.encrypt = function(text,password) {
|
|
|
|
|
return callSjcl("encrypt",text,password);
|
|
|
|
|
};
|
|
|
|
|
this.decrypt = function(text,password) {
|
|
|
|
|
return callSjcl("decrypt",text,password);
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/////////////////////////// Module mechanism
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Execute the module named 'moduleName'. The name can optionally be relative to the module named 'moduleRoot'
|
|
|
|
|
*/
|
|
|
|
|
$tw.modules.execute = function(moduleName,moduleRoot) {
|
|
|
|
|
var name = moduleName;
|
|
|
|
|
if(moduleName.charAt(0) === ".") {
|
|
|
|
|
name = $tw.utils.resolvePath(moduleName,moduleRoot)
|
|
|
|
|
}
|
|
|
|
|
if(!$tw.modules.titles[name]) {
|
|
|
|
|
if($tw.modules.titles[name + ".js"]) {
|
|
|
|
|
name = name + ".js";
|
|
|
|
|
} else if($tw.modules.titles[name + "/index.js"]) {
|
|
|
|
|
name = name + "/index.js";
|
|
|
|
|
} else if($tw.modules.titles[moduleName]) {
|
|
|
|
|
name = moduleName;
|
|
|
|
|
} else if($tw.modules.titles[moduleName + ".js"]) {
|
|
|
|
|
name = moduleName + ".js";
|
|
|
|
|
} else if($tw.modules.titles[moduleName + "/index.js"]) {
|
|
|
|
|
name = moduleName + "/index.js";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var moduleInfo = $tw.modules.titles[name],
|
|
|
|
|
tiddler = $tw.wiki.getTiddler(name),
|
|
|
|
|
_exports = {},
|
|
|
|
|
sandbox = {
|
|
|
|
|
module: {exports: _exports},
|
|
|
|
|
//moduleInfo: moduleInfo,
|
|
|
|
|
exports: _exports,
|
|
|
|
|
console: console,
|
|
|
|
|
setInterval: setInterval,
|
|
|
|
|
clearInterval: clearInterval,
|
|
|
|
|
setTimeout: setTimeout,
|
|
|
|
|
clearTimeout: clearTimeout,
|
|
|
|
|
Buffer: $tw.browser ? undefined : Buffer,
|
|
|
|
|
$tw: $tw,
|
|
|
|
|
require: function(title) {
|
|
|
|
|
return $tw.modules.execute(title, name);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Object.defineProperty(sandbox.module, "id", {
|
|
|
|
|
value: name,
|
|
|
|
|
writable: false,
|
|
|
|
|
enumerable: true,
|
|
|
|
|
configurable: false
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(!$tw.browser) {
|
|
|
|
|
$tw.utils.extend(sandbox,{
|
|
|
|
|
process: process
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
/*
|
|
|
|
|
CommonJS optional require.main property:
|
|
|
|
|
In a browser we offer a fake main module which points back to the boot function
|
|
|
|
|
(Theoretically, this may allow TW to eventually load itself as a module in the browser)
|
|
|
|
|
*/
|
|
|
|
|
Object.defineProperty(sandbox.require, "main", {
|
|
|
|
|
value: (typeof(require) !== "undefined") ? require.main : {TiddlyWiki: _boot},
|
|
|
|
|
writable: false,
|
|
|
|
|
enumerable: true,
|
|
|
|
|
configurable: false
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if(!moduleInfo) {
|
|
|
|
|
// We could not find the module on this path
|
|
|
|
|
// Try to defer to browserify etc, or node
|
|
|
|
|
var deferredModule;
|
|
|
|
|
if($tw.browser) {
|
|
|
|
|
if(window.require) {
|
|
|
|
|
try {
|
|
|
|
|
return window.require(moduleName);
|
|
|
|
|
} catch(e) {}
|
|
|
|
|
}
|
|
|
|
|
throw "Cannot find module named '" + moduleName + "' required by module '" + moduleRoot + "', resolved to " + name;
|
|
|
|
|
} else {
|
|
|
|
|
// If we don't have a module with that name, let node.js try to find it
|
|
|
|
|
return require(moduleName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Execute the module if we haven't already done so
|
|
|
|
|
if(!moduleInfo.exports) {
|
|
|
|
|
try {
|
|
|
|
|
// Check the type of the definition
|
|
|
|
|
if(typeof moduleInfo.definition === "function") { // Function
|
|
|
|
|
moduleInfo.exports = _exports;
|
|
|
|
|
moduleInfo.definition(moduleInfo,moduleInfo.exports,sandbox.require);
|
|
|
|
|
} else if(typeof moduleInfo.definition === "string") { // String
|
|
|
|
|
moduleInfo.exports = _exports;
|
|
|
|
|
$tw.utils.evalSandboxed(moduleInfo.definition,sandbox,tiddler.fields.title);
|
|
|
|
|
if(sandbox.module.exports) {
|
|
|
|
|
moduleInfo.exports = sandbox.module.exports; //more codemirror workaround
|
|
|
|
|
}
|
|
|
|
|
} else { // Object
|
|
|
|
|
moduleInfo.exports = moduleInfo.definition;
|
|
|
|
|
}
|
|
|
|
|
} catch(e) {
|
|
|
|
|
if (e instanceof SyntaxError) {
|
|
|
|
|
var line = e.lineNumber || e.line; // Firefox || Safari
|
|
|
|
|
if (typeof(line) != "undefined" && line !== null) {
|
|
|
|
|
$tw.utils.error("Syntax error in boot module " + name + ":" + line + ":\n" + e.stack);
|
|
|
|
|
} else if(!$tw.browser) {
|
|
|
|
|
// this is the only way to get node.js to display the line at which the syntax error appeared,
|
|
|
|
|
// and $tw.utils.error would exit anyway
|
|
|
|
|
// cf. https://bugs.chromium.org/p/v8/issues/detail?id=2589
|
|
|
|
|
throw e;
|
|
|
|
|
} else {
|
|
|
|
|
// Opera: line number is included in e.message
|
|
|
|
|
// Chrome/IE: there's currently no way to get the line number
|
|
|
|
|
$tw.utils.error("Syntax error in boot module " + name + ": " + e.message + "\n" + e.stack);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// line number should be included in e.stack for runtime errors
|
|
|
|
|
$tw.utils.error("Error executing boot module " + name + ": " + String(e) + "\n\n" + e.stack);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Return the exports of the module
|
|
|
|
|
return moduleInfo.exports;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Apply a callback to each module of a particular type
|
|
|
|
|
moduleType: type of modules to enumerate
|
|
|
|
|
callback: function called as callback(title,moduleExports) for each module
|
|
|
|
|
*/
|
|
|
|
|
$tw.modules.forEachModuleOfType = function(moduleType,callback) {
|
|
|
|
|
var modules = $tw.modules.types[moduleType];
|
|
|
|
|
$tw.utils.each(modules,function(element,title) {
|
|
|
|
|
callback(title,$tw.modules.execute(title));
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Get all the modules of a particular type in a hashmap by their `name` field
|
|
|
|
|
*/
|
|
|
|
|
$tw.modules.getModulesByTypeAsHashmap = function(moduleType,nameField) {
|
|
|
|
|
nameField = nameField || "name";
|
|
|
|
|
var results = Object.create(null);
|
|
|
|
|
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
|
|
|
|
results[module[nameField]] = module;
|
|
|
|
|
});
|
|
|
|
|
return results;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Apply the exports of the modules of a particular type to a target object
|
|
|
|
|
*/
|
|
|
|
|
$tw.modules.applyMethods = function(moduleType,targetObject) {
|
|
|
|
|
if(!targetObject) {
|
|
|
|
|
targetObject = Object.create(null);
|
|
|
|
|
}
|
|
|
|
|
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
|
|
|
|
|
$tw.utils.each(module,function(element,title,object) {
|
|
|
|
|
targetObject[title] = module[title];
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
return targetObject;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Return a class created from a modules. The module should export the properties to be added to those of the optional base class
|
|
|
|
|
*/
|
|
|
|
|
$tw.modules.createClassFromModule = function(moduleExports,baseClass) {
|
|
|
|
|
var newClass = function() {};
|
|
|
|
|
if(baseClass) {
|
|
|
|
|
newClass.prototype = new baseClass();
|
|
|
|
|
newClass.prototype.constructor = baseClass;
|
|
|
|
|
}
|
|
|
|
|
$tw.utils.extend(newClass.prototype,moduleExports);
|
|
|
|
|
return newClass;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Return an array of classes created from the modules of a specified type. Each module should export the properties to be added to those of the optional base class
|
|
|
|
|
*/
|
|
|
|
|
$tw.modules.createClassesFromModules = function(moduleType,subType,baseClass) {
|
|
|
|
|
var classes = Object.create(null);
|
|
|
|
|
$tw.modules.forEachModuleOfType(moduleType,function(title,moduleExports) {
|
|
|
|
|
if(!subType || moduleExports.types[subType]) {
|
|
|
|
|
classes[moduleExports.name] = $tw.modules.createClassFromModule(moduleExports,baseClass);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return classes;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/////////////////////////// Barebones tiddler object
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Construct a tiddler object from a hashmap of tiddler fields. If multiple hasmaps are provided they are merged,
|
|
|
|
|
taking precedence to the right
|
|
|
|
|
*/
|
|
|
|
|
$tw.Tiddler = function(/* [fields,] fields */) {
|
|
|
|
|
this.fields = Object.create(null);
|
|
|
|
|
this.cache = Object.create(null);
|
|
|
|
|
for(var c=0; c<arguments.length; c++) {
|
|
|
|
|
var arg = arguments[c],
|
|
|
|
|
src = (arg instanceof $tw.Tiddler) ? arg.fields : arg;
|
|
|
|
|
for(var t in src) {
|
|
|
|
|
if(src[t] === undefined || src[t] === null) {
|
|
|
|
|
if(t in this.fields) {
|
|
|
|
|
delete this.fields[t]; // If we get a field that's undefined, delete any previous field value
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Parse the field with the associated field module (if any)
|
|
|
|
|
var fieldModule = $tw.Tiddler.fieldModules[t],
|
|
|
|
|
value;
|
|
|
|
|
if(fieldModule && fieldModule.parse) {
|
|
|
|
|
value = fieldModule.parse.call(this,src[t]);
|
|
|
|
|
} else {
|
|
|
|
|
value = src[t];
|
|
|
|
|
}
|
|
|
|
|
// Freeze the field to keep it immutable
|
|
|
|
|
if(value != null && typeof value === "object") {
|
|
|
|
|
Object.freeze(value);
|
|
|
|
|
}
|
|
|
|
|
this.fields[t] = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Freeze the tiddler against modification
|
|
|
|
|
Object.freeze(this.fields);
|
|
|
|
|
Object.freeze(this);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$tw.Tiddler.prototype.hasField = function(field) {
|
|
|
|
|
return $tw.utils.hop(this.fields,field);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Compare two tiddlers for equality
|
|
|
|
|
tiddler: the tiddler to compare
|
|
|
|
|
excludeFields: array of field names to exclude from the comparison
|
|
|
|
|
*/
|
|
|
|
|
$tw.Tiddler.prototype.isEqual = function(tiddler,excludeFields) {
|
|
|
|
|
if(!(tiddler instanceof $tw.Tiddler)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
excludeFields = excludeFields || [];
|
|
|
|
|
var self = this,
|
|
|
|
|
differences = []; // Fields that have differences
|
|
|
|
|
// Add to the differences array
|
|
|
|
|
function addDifference(fieldName) {
|
|
|
|
|
// Check for this field being excluded
|
|
|
|
|
if(excludeFields.indexOf(fieldName) === -1) {
|
|
|
|
|
// Save the field as a difference
|
|
|
|
|
$tw.utils.pushTop(differences,fieldName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Returns true if the two values of this field are equal
|
|
|
|
|
function isFieldValueEqual(fieldName) {
|
|
|
|
|
var valueA = self.fields[fieldName],
|
|
|
|
|
valueB = tiddler.fields[fieldName];
|
|
|
|
|
// Check for identical string values
|
|
|
|
|
if(typeof(valueA) === "string" && typeof(valueB) === "string" && valueA === valueB) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// Check for identical array values
|
|
|
|
|
if($tw.utils.isArray(valueA) && $tw.utils.isArray(valueB) && $tw.utils.isArrayEqual(valueA,valueB)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// Check for identical date values
|
|
|
|
|
if($tw.utils.isDate(valueA) && $tw.utils.isDate(valueB) && valueA.getTime() === valueB.getTime()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// Otherwise the fields must be different
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// Compare our fields
|
|
|
|
|
for(var fieldName in this.fields) {
|
|
|
|
|
if(!isFieldValueEqual(fieldName)) {
|
|
|
|
|
addDifference(fieldName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// There's a difference for every field in the other tiddler that we don't have
|
|
|
|
|
for(fieldName in tiddler.fields) {
|
|
|
|
|
if(!(fieldName in this.fields)) {
|
|
|
|
|
addDifference(fieldName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Return whether there were any differences
|
|
|
|
|
return differences.length === 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Register and install the built in tiddler field modules
|
|
|
|
|
*/
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerfields/modified","tiddlerfield",{
|
|
|
|
|
name: "modified",
|
|
|
|
|
parse: $tw.utils.parseDate,
|
|
|
|
|
stringify: $tw.utils.stringifyDate
|
|
|
|
|
});
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerfields/created","tiddlerfield",{
|
|
|
|
|
name: "created",
|
|
|
|
|
parse: $tw.utils.parseDate,
|
|
|
|
|
stringify: $tw.utils.stringifyDate
|
|
|
|
|
});
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerfields/color","tiddlerfield",{
|
|
|
|
|
name: "color",
|
|
|
|
|
editTag: "input",
|
|
|
|
|
editType: "color"
|
|
|
|
|
});
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerfields/tags","tiddlerfield",{
|
|
|
|
|
name: "tags",
|
|
|
|
|
parse: $tw.utils.parseStringArray,
|
|
|
|
|
stringify: $tw.utils.stringifyList
|
|
|
|
|
});
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerfields/list","tiddlerfield",{
|
|
|
|
|
name: "list",
|
|
|
|
|
parse: $tw.utils.parseStringArray,
|
|
|
|
|
stringify: $tw.utils.stringifyList
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/////////////////////////// Barebones wiki store
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Wiki constructor. State is stored in private members that only a small number of privileged accessor methods have direct access. Methods added via the prototype have to use these accessors and cannot access the state data directly.
|
|
|
|
|
options include:
|
|
|
|
|
enableIndexers - Array of indexer names to enable, or null to use all available indexers
|
|
|
|
|
*/
|
|
|
|
|
$tw.Wiki = function(options) {
|
|
|
|
|
options = options || {};
|
|
|
|
|
var self = this,
|
|
|
|
|
tiddlers = Object.create(null), // Hashmap of tiddlers
|
|
|
|
|
tiddlerTitles = null, // Array of tiddler titles
|
|
|
|
|
getTiddlerTitles = function() {
|
|
|
|
|
if(!tiddlerTitles) {
|
|
|
|
|
tiddlerTitles = Object.keys(tiddlers).sort(function(a,b) {return a.localeCompare(b);});
|
|
|
|
|
}
|
|
|
|
|
return tiddlerTitles;
|
|
|
|
|
},
|
|
|
|
|
pluginTiddlers = [], // Array of tiddlers containing registered plugins, ordered by priority
|
|
|
|
|
pluginInfo = Object.create(null), // Hashmap of parsed plugin content
|
|
|
|
|
shadowTiddlers = Object.create(null), // Hashmap by title of {source:, tiddler:}
|
|
|
|
|
shadowTiddlerTitles = null,
|
|
|
|
|
getShadowTiddlerTitles = function() {
|
|
|
|
|
if(!shadowTiddlerTitles) {
|
|
|
|
|
shadowTiddlerTitles = Object.keys(shadowTiddlers).sort(function(a,b) {return a.localeCompare(b);});
|
|
|
|
|
}
|
|
|
|
|
return shadowTiddlerTitles;
|
|
|
|
|
},
|
|
|
|
|
enableIndexers = options.enableIndexers || null,
|
|
|
|
|
indexers = [],
|
|
|
|
|
indexersByName = Object.create(null);
|
|
|
|
|
|
|
|
|
|
this.addIndexer = function(indexer,name) {
|
|
|
|
|
// Bail if this indexer is not enabled
|
|
|
|
|
if(enableIndexers && enableIndexers.indexOf(name) === -1) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
indexers.push(indexer);
|
|
|
|
|
indexersByName[name] = indexer;
|
|
|
|
|
indexer.init();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.getIndexer = function(name) {
|
|
|
|
|
return indexersByName[name] || null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Add a tiddler to the store
|
|
|
|
|
this.addTiddler = function(tiddler) {
|
|
|
|
|
if(!(tiddler instanceof $tw.Tiddler)) {
|
|
|
|
|
tiddler = new $tw.Tiddler(tiddler);
|
|
|
|
|
}
|
|
|
|
|
// Save the tiddler
|
|
|
|
|
if(tiddler) {
|
|
|
|
|
var title = tiddler.fields.title;
|
|
|
|
|
if(title) {
|
|
|
|
|
// Uncomment the following line for detailed logs of all tiddler writes
|
|
|
|
|
// console.log("Adding",title,tiddler)
|
|
|
|
|
// Record the old tiddler state
|
|
|
|
|
var updateDescriptor = {
|
|
|
|
|
old: {
|
|
|
|
|
tiddler: this.getTiddler(title),
|
|
|
|
|
shadow: this.isShadowTiddler(title),
|
|
|
|
|
exists: this.tiddlerExists(title)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Save the new tiddler
|
|
|
|
|
tiddlers[title] = tiddler;
|
|
|
|
|
// Check we've got the title
|
|
|
|
|
tiddlerTitles = $tw.utils.insertSortedArray(tiddlerTitles || [],title);
|
|
|
|
|
// Record the new tiddler state
|
|
|
|
|
updateDescriptor["new"] = {
|
|
|
|
|
tiddler: tiddler,
|
|
|
|
|
shadow: this.isShadowTiddler(title),
|
|
|
|
|
exists: this.tiddlerExists(title)
|
|
|
|
|
}
|
|
|
|
|
// Update indexes
|
|
|
|
|
this.clearCache(title);
|
|
|
|
|
this.clearGlobalCache();
|
|
|
|
|
$tw.utils.each(indexers,function(indexer) {
|
|
|
|
|
indexer.update(updateDescriptor);
|
|
|
|
|
});
|
|
|
|
|
// Queue a change event
|
|
|
|
|
this.enqueueTiddlerEvent(title);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Delete a tiddler
|
|
|
|
|
this.deleteTiddler = function(title) {
|
|
|
|
|
// Uncomment the following line for detailed logs of all tiddler deletions
|
|
|
|
|
// console.log("Deleting",title)
|
|
|
|
|
if($tw.utils.hop(tiddlers,title)) {
|
|
|
|
|
// Record the old tiddler state
|
|
|
|
|
var updateDescriptor = {
|
|
|
|
|
old: {
|
|
|
|
|
tiddler: this.getTiddler(title),
|
|
|
|
|
shadow: this.isShadowTiddler(title),
|
|
|
|
|
exists: this.tiddlerExists(title)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Delete the tiddler
|
|
|
|
|
delete tiddlers[title];
|
|
|
|
|
// Delete it from the list of titles
|
|
|
|
|
if(tiddlerTitles) {
|
|
|
|
|
var index = tiddlerTitles.indexOf(title);
|
|
|
|
|
if(index !== -1) {
|
|
|
|
|
tiddlerTitles.splice(index,1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Record the new tiddler state
|
|
|
|
|
updateDescriptor["new"] = {
|
|
|
|
|
tiddler: this.getTiddler(title),
|
|
|
|
|
shadow: this.isShadowTiddler(title),
|
|
|
|
|
exists: this.tiddlerExists(title)
|
|
|
|
|
}
|
|
|
|
|
// Update indexes
|
|
|
|
|
this.clearCache(title);
|
|
|
|
|
this.clearGlobalCache();
|
|
|
|
|
$tw.utils.each(indexers,function(indexer) {
|
|
|
|
|
indexer.update(updateDescriptor);
|
|
|
|
|
});
|
|
|
|
|
// Queue a change event
|
|
|
|
|
this.enqueueTiddlerEvent(title,true);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Get a tiddler from the store
|
|
|
|
|
this.getTiddler = function(title) {
|
|
|
|
|
if(title) {
|
|
|
|
|
var t = tiddlers[title];
|
|
|
|
|
if(t !== undefined) {
|
|
|
|
|
return t;
|
|
|
|
|
} else {
|
|
|
|
|
var s = shadowTiddlers[title];
|
|
|
|
|
if(s !== undefined) {
|
|
|
|
|
return s.tiddler;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return undefined;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Get an array of all tiddler titles
|
|
|
|
|
this.allTitles = function() {
|
|
|
|
|
return getTiddlerTitles().slice(0);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Iterate through all tiddler titles
|
|
|
|
|
this.each = function(callback) {
|
|
|
|
|
var titles = getTiddlerTitles(),
|
|
|
|
|
index,titlesLength,title;
|
|
|
|
|
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
|
|
|
|
|
title = titles[index];
|
|
|
|
|
callback(tiddlers[title],title);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Get an array of all shadow tiddler titles
|
|
|
|
|
this.allShadowTitles = function() {
|
|
|
|
|
return getShadowTiddlerTitles().slice(0);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Iterate through all shadow tiddler titles
|
|
|
|
|
this.eachShadow = function(callback) {
|
|
|
|
|
var titles = getShadowTiddlerTitles(),
|
|
|
|
|
index,titlesLength,title;
|
|
|
|
|
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
|
|
|
|
|
title = titles[index];
|
|
|
|
|
if(tiddlers[title]) {
|
|
|
|
|
callback(tiddlers[title],title);
|
|
|
|
|
} else {
|
|
|
|
|
var shadowInfo = shadowTiddlers[title];
|
|
|
|
|
callback(shadowInfo.tiddler,title);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Iterate through all tiddlers and then the shadows
|
|
|
|
|
this.eachTiddlerPlusShadows = function(callback) {
|
|
|
|
|
var index,titlesLength,title,
|
|
|
|
|
titles = getTiddlerTitles();
|
|
|
|
|
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
|
|
|
|
|
title = titles[index];
|
|
|
|
|
callback(tiddlers[title],title);
|
|
|
|
|
}
|
|
|
|
|
titles = getShadowTiddlerTitles();
|
|
|
|
|
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
|
|
|
|
|
title = titles[index];
|
|
|
|
|
if(!tiddlers[title]) {
|
|
|
|
|
var shadowInfo = shadowTiddlers[title];
|
|
|
|
|
callback(shadowInfo.tiddler,title);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Iterate through all the shadows and then the tiddlers
|
|
|
|
|
this.eachShadowPlusTiddlers = function(callback) {
|
|
|
|
|
var index,titlesLength,title,
|
|
|
|
|
titles = getShadowTiddlerTitles();
|
|
|
|
|
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
|
|
|
|
|
title = titles[index];
|
|
|
|
|
if(tiddlers[title]) {
|
|
|
|
|
callback(tiddlers[title],title);
|
|
|
|
|
} else {
|
|
|
|
|
var shadowInfo = shadowTiddlers[title];
|
|
|
|
|
callback(shadowInfo.tiddler,title);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
titles = getTiddlerTitles();
|
|
|
|
|
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
|
|
|
|
|
title = titles[index];
|
|
|
|
|
if(!shadowTiddlers[title]) {
|
|
|
|
|
callback(tiddlers[title],title);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Test for the existence of a tiddler (excludes shadow tiddlers)
|
|
|
|
|
this.tiddlerExists = function(title) {
|
|
|
|
|
return !!$tw.utils.hop(tiddlers,title);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Determines if a tiddler is a shadow tiddler, regardless of whether it has been overridden by a real tiddler
|
|
|
|
|
this.isShadowTiddler = function(title) {
|
|
|
|
|
return $tw.utils.hop(shadowTiddlers,title);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.getShadowSource = function(title) {
|
|
|
|
|
if($tw.utils.hop(shadowTiddlers,title)) {
|
|
|
|
|
return shadowTiddlers[title].source;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Get an array of all the currently recognised plugin types
|
|
|
|
|
this.getPluginTypes = function() {
|
|
|
|
|
var types = [];
|
|
|
|
|
$tw.utils.each(pluginTiddlers,function(pluginTiddler) {
|
|
|
|
|
var pluginType = pluginTiddler.fields["plugin-type"];
|
|
|
|
|
if(pluginType && types.indexOf(pluginType) === -1) {
|
|
|
|
|
types.push(pluginType);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return types;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Read plugin info for all plugins, or just an array of titles. Returns the number of plugins updated or deleted
|
|
|
|
|
this.readPluginInfo = function(titles) {
|
|
|
|
|
var results = {
|
|
|
|
|
modifiedPlugins: [],
|
|
|
|
|
deletedPlugins: []
|
|
|
|
|
};
|
|
|
|
|
$tw.utils.each(titles || getTiddlerTitles(),function(title) {
|
|
|
|
|
var tiddler = tiddlers[title];
|
|
|
|
|
if(tiddler) {
|
|
|
|
|
if(tiddler.fields.type === "application/json" && tiddler.hasField("plugin-type") && tiddler.fields.text) {
|
|
|
|
|
pluginInfo[tiddler.fields.title] = $tw.utils.parseJSONSafe(tiddler.fields.text);
|
|
|
|
|
results.modifiedPlugins.push(tiddler.fields.title);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if(pluginInfo[title]) {
|
|
|
|
|
delete pluginInfo[title];
|
|
|
|
|
results.deletedPlugins.push(title);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return results;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Get plugin info for a plugin
|
|
|
|
|
this.getPluginInfo = function(title) {
|
|
|
|
|
return pluginInfo[title];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Register the plugin tiddlers of a particular type, or null/undefined for any type, optionally restricting registration to an array of tiddler titles. Return the array of titles affected
|
|
|
|
|
this.registerPluginTiddlers = function(pluginType,titles) {
|
|
|
|
|
var self = this,
|
|
|
|
|
registeredTitles = [],
|
|
|
|
|
checkTiddler = function(tiddler,title) {
|
|
|
|
|
if(tiddler && tiddler.fields.type === "application/json" && tiddler.fields["plugin-type"] && (!pluginType || tiddler.fields["plugin-type"] === pluginType)) {
|
|
|
|
|
var disablingTiddler = self.getTiddler("$:/config/Plugins/Disabled/" + title);
|
|
|
|
|
if(title === "$:/core" || !disablingTiddler || (disablingTiddler.fields.text || "").trim() !== "yes") {
|
|
|
|
|
self.unregisterPluginTiddlers(null,[title]); // Unregister the plugin if it's already registered
|
|
|
|
|
pluginTiddlers.push(tiddler);
|
|
|
|
|
registeredTitles.push(tiddler.fields.title);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
if(titles) {
|
|
|
|
|
$tw.utils.each(titles,function(title) {
|
|
|
|
|
checkTiddler(self.getTiddler(title),title);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
this.each(function(tiddler,title) {
|
|
|
|
|
checkTiddler(tiddler,title);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return registeredTitles;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Unregister the plugin tiddlers of a particular type, or null/undefined for any type, optionally restricting unregistering to an array of tiddler titles. Returns an array of the titles affected
|
|
|
|
|
this.unregisterPluginTiddlers = function(pluginType,titles) {
|
|
|
|
|
var self = this,
|
|
|
|
|
unregisteredTitles = [];
|
|
|
|
|
// Remove any previous registered plugins of this type
|
|
|
|
|
for(var t=pluginTiddlers.length-1; t>=0; t--) {
|
|
|
|
|
var tiddler = pluginTiddlers[t];
|
|
|
|
|
if(tiddler.fields["plugin-type"] && (!pluginType || tiddler.fields["plugin-type"] === pluginType) && (!titles || titles.indexOf(tiddler.fields.title) !== -1)) {
|
|
|
|
|
unregisteredTitles.push(tiddler.fields.title);
|
|
|
|
|
pluginTiddlers.splice(t,1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return unregisteredTitles;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Unpack the currently registered plugins, creating shadow tiddlers for their constituent tiddlers
|
|
|
|
|
this.unpackPluginTiddlers = function() {
|
|
|
|
|
var self = this;
|
|
|
|
|
// Sort the plugin titles by the `plugin-priority` field
|
|
|
|
|
pluginTiddlers.sort(function(a,b) {
|
|
|
|
|
if("plugin-priority" in a.fields && "plugin-priority" in b.fields) {
|
|
|
|
|
return a.fields["plugin-priority"] - b.fields["plugin-priority"];
|
|
|
|
|
} else if("plugin-priority" in a.fields) {
|
|
|
|
|
return -1;
|
|
|
|
|
} else if("plugin-priority" in b.fields) {
|
|
|
|
|
return +1;
|
|
|
|
|
} else if(a.fields.title < b.fields.title) {
|
|
|
|
|
return -1;
|
|
|
|
|
} else if(a.fields.title === b.fields.title) {
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
return +1;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// Now go through the plugins in ascending order and assign the shadows
|
|
|
|
|
shadowTiddlers = Object.create(null);
|
|
|
|
|
$tw.utils.each(pluginTiddlers,function(tiddler) {
|
|
|
|
|
// Extract the constituent tiddlers
|
|
|
|
|
if($tw.utils.hop(pluginInfo,tiddler.fields.title)) {
|
|
|
|
|
$tw.utils.each(pluginInfo[tiddler.fields.title].tiddlers,function(constituentTiddler,constituentTitle) {
|
|
|
|
|
// Save the tiddler object
|
|
|
|
|
if(constituentTitle) {
|
|
|
|
|
shadowTiddlers[constituentTitle] = {
|
|
|
|
|
source: tiddler.fields.title,
|
|
|
|
|
tiddler: new $tw.Tiddler(constituentTiddler,{title: constituentTitle})
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
shadowTiddlerTitles = null;
|
|
|
|
|
this.clearCache(null);
|
|
|
|
|
this.clearGlobalCache();
|
|
|
|
|
$tw.utils.each(indexers,function(indexer) {
|
|
|
|
|
indexer.rebuild();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if(this.addIndexersToWiki) {
|
|
|
|
|
this.addIndexersToWiki();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Dummy methods that will be filled in after boot
|
|
|
|
|
$tw.Wiki.prototype.clearCache =
|
|
|
|
|
$tw.Wiki.prototype.clearGlobalCache =
|
|
|
|
|
$tw.Wiki.prototype.enqueueTiddlerEvent = function() {};
|
|
|
|
|
|
|
|
|
|
// Add an array of tiddlers
|
|
|
|
|
$tw.Wiki.prototype.addTiddlers = function(tiddlers) {
|
|
|
|
|
for(var t=0; t<tiddlers.length; t++) {
|
|
|
|
|
this.addTiddler(tiddlers[t]);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Define all modules stored in ordinary tiddlers
|
|
|
|
|
*/
|
|
|
|
|
$tw.Wiki.prototype.defineTiddlerModules = function() {
|
|
|
|
|
this.each(function(tiddler,title) {
|
|
|
|
|
if(tiddler.hasField("module-type")) {
|
|
|
|
|
switch (tiddler.fields.type) {
|
|
|
|
|
case "application/javascript":
|
|
|
|
|
// We only define modules that haven't already been defined, because in the browser modules in system tiddlers are defined in inline script
|
|
|
|
|
if(!$tw.utils.hop($tw.modules.titles,tiddler.fields.title)) {
|
|
|
|
|
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],tiddler.fields.text);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "application/json":
|
|
|
|
|
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],$tw.utils.parseJSONSafe(tiddler.fields.text));
|
|
|
|
|
break;
|
|
|
|
|
case "application/x-tiddler-dictionary":
|
|
|
|
|
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],$tw.utils.parseFields(tiddler.fields.text));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Register all the module tiddlers that have a module type
|
|
|
|
|
*/
|
|
|
|
|
$tw.Wiki.prototype.defineShadowModules = function() {
|
|
|
|
|
var self = this;
|
|
|
|
|
this.eachShadow(function(tiddler,title) {
|
|
|
|
|
// Don't define the module if it is overidden by an ordinary tiddler
|
|
|
|
|
if(!self.tiddlerExists(title) && tiddler.hasField("module-type")) {
|
|
|
|
|
// Define the module
|
|
|
|
|
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],tiddler.fields.text);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Enable safe mode by deleting any tiddlers that override a shadow tiddler
|
|
|
|
|
*/
|
|
|
|
|
$tw.Wiki.prototype.processSafeMode = function() {
|
|
|
|
|
var self = this,
|
|
|
|
|
overrides = [];
|
|
|
|
|
// Find the overriding tiddlers
|
|
|
|
|
this.each(function(tiddler,title) {
|
|
|
|
|
if(self.isShadowTiddler(title)) {
|
|
|
|
|
console.log(title);
|
|
|
|
|
overrides.push(title);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// Assemble a report tiddler
|
|
|
|
|
var titleReportTiddler = "TiddlyWiki Safe Mode",
|
|
|
|
|
report = [];
|
|
|
|
|
report.push("TiddlyWiki has been started in [[safe mode|https://tiddlywiki.com/static/SafeMode.html]]. All plugins are temporarily disabled. Most customisations have been disabled by renaming the following tiddlers:")
|
|
|
|
|
// Delete the overrides
|
|
|
|
|
overrides.forEach(function(title) {
|
|
|
|
|
var tiddler = self.getTiddler(title),
|
|
|
|
|
newTitle = "SAFE: " + title;
|
|
|
|
|
self.deleteTiddler(title);
|
|
|
|
|
self.addTiddler(new $tw.Tiddler(tiddler, {title: newTitle}));
|
|
|
|
|
report.push("* [[" + title + "|" + newTitle + "]]");
|
|
|
|
|
});
|
|
|
|
|
report.push()
|
|
|
|
|
this.addTiddler(new $tw.Tiddler({title: titleReportTiddler, text: report.join("\n\n")}));
|
|
|
|
|
// Set $:/DefaultTiddlers to point to our report
|
|
|
|
|
this.addTiddler(new $tw.Tiddler({title: "$:/DefaultTiddlers", text: "[[" + titleReportTiddler + "]]"}));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Extracts tiddlers from a typed block of text, specifying default field values
|
|
|
|
|
*/
|
|
|
|
|
$tw.Wiki.prototype.deserializeTiddlers = function(type,text,srcFields,options) {
|
|
|
|
|
srcFields = srcFields || Object.create(null);
|
|
|
|
|
options = options || {};
|
|
|
|
|
var deserializer = $tw.Wiki.tiddlerDeserializerModules[options.deserializer],
|
|
|
|
|
fields = Object.create(null);
|
|
|
|
|
if(!deserializer) {
|
|
|
|
|
deserializer = $tw.Wiki.tiddlerDeserializerModules[type];
|
|
|
|
|
}
|
|
|
|
|
if(!deserializer && $tw.utils.getFileExtensionInfo(type)) {
|
|
|
|
|
// If we didn't find the serializer, try converting it from an extension to a content type
|
|
|
|
|
type = $tw.utils.getFileExtensionInfo(type).type;
|
|
|
|
|
deserializer = $tw.Wiki.tiddlerDeserializerModules[type];
|
|
|
|
|
}
|
|
|
|
|
if(!deserializer && $tw.config.contentTypeInfo[type]) {
|
|
|
|
|
// see if this type has a different deserializer registered with it
|
|
|
|
|
type = $tw.config.contentTypeInfo[type].deserializerType;
|
|
|
|
|
deserializer = $tw.Wiki.tiddlerDeserializerModules[type];
|
|
|
|
|
}
|
|
|
|
|
if(!deserializer) {
|
|
|
|
|
// If we still don't have a deserializer, treat it as plain text
|
|
|
|
|
deserializer = $tw.Wiki.tiddlerDeserializerModules["text/plain"];
|
|
|
|
|
}
|
|
|
|
|
for(var f in srcFields) {
|
|
|
|
|
fields[f] = srcFields[f];
|
|
|
|
|
}
|
|
|
|
|
if(deserializer) {
|
|
|
|
|
return deserializer.call(this,text,fields,type);
|
|
|
|
|
} else {
|
|
|
|
|
// Return a raw tiddler for unknown types
|
|
|
|
|
fields.text = text;
|
|
|
|
|
return [fields];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Register the built in tiddler deserializer modules
|
|
|
|
|
*/
|
|
|
|
|
var deserializeHeaderComment = function(text,fields) {
|
|
|
|
|
var headerCommentRegExp = new RegExp($tw.config.jsModuleHeaderRegExpString,"mg"),
|
|
|
|
|
match = headerCommentRegExp.exec(text);
|
|
|
|
|
fields.text = text;
|
|
|
|
|
if(match) {
|
|
|
|
|
fields = $tw.utils.parseFields(match[1].split(/\r?\n\r?\n/mg)[0],fields);
|
|
|
|
|
}
|
|
|
|
|
return [fields];
|
|
|
|
|
};
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerdeserializer/js","tiddlerdeserializer",{
|
|
|
|
|
"application/javascript": deserializeHeaderComment
|
|
|
|
|
});
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerdeserializer/css","tiddlerdeserializer",{
|
|
|
|
|
"text/css": deserializeHeaderComment
|
|
|
|
|
});
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerdeserializer/tid","tiddlerdeserializer",{
|
|
|
|
|
"application/x-tiddler": function(text,fields) {
|
|
|
|
|
var split = text.split(/\r?\n\r?\n/mg);
|
|
|
|
|
if(split.length >= 1) {
|
|
|
|
|
fields = $tw.utils.parseFields(split[0],fields);
|
|
|
|
|
}
|
|
|
|
|
if(split.length >= 2) {
|
|
|
|
|
fields.text = split.slice(1).join("\n\n");
|
|
|
|
|
}
|
|
|
|
|
return [fields];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerdeserializer/tids","tiddlerdeserializer",{
|
|
|
|
|
"application/x-tiddlers": function(text,fields) {
|
|
|
|
|
var titles = [],
|
|
|
|
|
tiddlers = [],
|
|
|
|
|
match = /\r?\n\r?\n/mg.exec(text);
|
|
|
|
|
if(match) {
|
|
|
|
|
fields = $tw.utils.parseFields(text.substr(0,match.index),fields);
|
|
|
|
|
var lines = text.substr(match.index + match[0].length).split(/\r?\n/mg);
|
|
|
|
|
for(var t=0; t<lines.length; t++) {
|
|
|
|
|
var line = lines[t];
|
|
|
|
|
if(line.charAt(0) !== "#") {
|
|
|
|
|
var colonPos= line.indexOf(":");
|
|
|
|
|
if(colonPos !== -1) {
|
|
|
|
|
var tiddler = $tw.utils.extend(Object.create(null),fields);
|
|
|
|
|
tiddler.title = (tiddler.title || "") + line.substr(0,colonPos).trim();
|
|
|
|
|
if(titles.indexOf(tiddler.title) !== -1) {
|
|
|
|
|
console.log("Warning: .multids file contains multiple definitions for " + tiddler.title);
|
|
|
|
|
}
|
|
|
|
|
titles.push(tiddler.title);
|
|
|
|
|
tiddler.text = line.substr(colonPos + 2).trim();
|
|
|
|
|
tiddlers.push(tiddler);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return tiddlers;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerdeserializer/txt","tiddlerdeserializer",{
|
|
|
|
|
"text/plain": function(text,fields,type) {
|
|
|
|
|
fields.text = text;
|
|
|
|
|
fields.type = type || "text/plain";
|
|
|
|
|
return [fields];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerdeserializer/html","tiddlerdeserializer",{
|
|
|
|
|
"text/html": function(text,fields) {
|
|
|
|
|
fields.text = text;
|
|
|
|
|
fields.type = "text/html";
|
|
|
|
|
return [fields];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerdeserializer/json","tiddlerdeserializer",{
|
|
|
|
|
"application/json": function(text,fields) {
|
|
|
|
|
var isTiddlerValid = function(data) {
|
|
|
|
|
// Not valid if it's not an object with a title property
|
|
|
|
|
if(typeof(data) !== "object" || !$tw.utils.hop(data,"title")) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
for(var f in data) {
|
|
|
|
|
if($tw.utils.hop(data,f)) {
|
|
|
|
|
// Check field name doesn't contain control characters
|
|
|
|
|
if(typeof(data[f]) !== "string" || /[\x00-\x1F]/.test(f)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
isTiddlerArrayValid = function(data) {
|
|
|
|
|
for(var t=0; t<data.length; t++) {
|
|
|
|
|
if(!isTiddlerValid(data[t])) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
data = $tw.utils.parseJSONSafe(text);
|
|
|
|
|
if($tw.utils.isArray(data) && isTiddlerArrayValid(data)) {
|
|
|
|
|
return data;
|
|
|
|
|
} else if(isTiddlerValid(data)) {
|
|
|
|
|
return [data];
|
|
|
|
|
} else {
|
|
|
|
|
// Plain JSON file
|
|
|
|
|
fields.text = text;
|
|
|
|
|
fields.type = "application/json";
|
|
|
|
|
return [fields];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/////////////////////////// Browser definitions
|
|
|
|
|
|
|
|
|
|
if($tw.browser && !$tw.node) {
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Decrypt any tiddlers stored within the element with the ID "encryptedArea". The function is asynchronous to allow the user to be prompted for a password
|
|
|
|
|
callback: function to be called the decryption is complete
|
|
|
|
|
*/
|
|
|
|
|
$tw.boot.decryptEncryptedTiddlers = function(callback) {
|
|
|
|
|
var encryptedArea = document.getElementById("encryptedStoreArea");
|
|
|
|
|
if(encryptedArea) {
|
|
|
|
|
var encryptedText = encryptedArea.innerHTML,
|
|
|
|
|
prompt = "Enter a password to decrypt this TiddlyWiki";
|
|
|
|
|
// Prompt for the password
|
|
|
|
|
if($tw.utils.hop($tw.boot,"encryptionPrompts")) {
|
|
|
|
|
prompt = $tw.boot.encryptionPrompts.decrypt;
|
|
|
|
|
}
|
|
|
|
|
$tw.passwordPrompt.createPrompt({
|
|
|
|
|
serviceName: prompt,
|
|
|
|
|
noUserName: true,
|
|
|
|
|
submitText: "Decrypt",
|
|
|
|
|
callback: function(data) {
|
|
|
|
|
// Attempt to decrypt the tiddlers
|
|
|
|
|
$tw.crypto.setPassword(data.password);
|
|
|
|
|
var decryptedText = $tw.crypto.decrypt(encryptedText);
|
|
|
|
|
if(decryptedText) {
|
|
|
|
|
var json = $tw.utils.parseJSONSafe(decryptedText);
|
|
|
|
|
for(var title in json) {
|
|
|
|
|
$tw.preloadTiddler(json[title]);
|
|
|
|
|
}
|
|
|
|
|
// Call the callback
|
|
|
|
|
callback();
|
|
|
|
|
// Exit and remove the password prompt
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
// We didn't decrypt everything, so continue to prompt for password
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// Just invoke the callback straight away if there weren't any encrypted tiddlers
|
|
|
|
|
callback();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Register a deserializer that can extract tiddlers from the DOM
|
|
|
|
|
*/
|
|
|
|
|
$tw.modules.define("$:/boot/tiddlerdeserializer/dom","tiddlerdeserializer",{
|
|
|
|
|
"(DOM)": function(node) {
|
|
|
|
|
var extractTextTiddlers = function(node) {
|
|
|
|
|
var e = node.firstChild;
|
|
|
|
|
while(e && e.nodeName.toLowerCase() !== "pre") {
|
|
|
|
|
e = e.nextSibling;
|
|
|
|
|
}
|
|
|
|
|
var title = node.getAttribute ? node.getAttribute("title") : null;
|
|
|
|
|
if(e && title) {
|
|
|
|
|
var attrs = node.attributes,
|
|
|
|
|
tiddler = {
|
|
|
|
|
text: $tw.utils.htmlDecode(e.innerHTML)
|
|
|
|
|
};
|
|
|
|
|
for(var i=attrs.length-1; i >= 0; i--) {
|
|
|
|
|
tiddler[attrs[i].name] = attrs[i].value;
|
|
|
|
|
}
|
|
|
|
|
return [tiddler];
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
extractModuleTiddlers = function(node) {
|
|
|
|
|
if(node.hasAttribute && node.hasAttribute("data-tiddler-title")) {
|
|
|
|
|
var text = node.innerHTML,
|
|
|
|
|
s = text.indexOf("{"),
|
|
|
|
|
e = text.lastIndexOf("}");
|
|
|
|
|
if(node.hasAttribute("data-module") && s !== -1 && e !== -1) {
|
|
|
|
|
text = text.substring(s+1,e);
|
|
|
|
|
}
|
|
|
|
|
var fields = {text: text},
|
|
|
|
|
attributes = node.attributes;
|
|
|
|
|
for(var a=0; a<attributes.length; a++) {
|
|
|
|
|
if(attributes[a].nodeName.substr(0,13) === "data-tiddler-") {
|
|
|
|
|
fields[attributes[a].nodeName.substr(13)] = attributes[a].value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return [fields];
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
t,result = [];
|
|
|
|
|
if(node) {
|
|
|
|
|
var type = (node.getAttribute && node.getAttribute("type")) || null;
|
|
|
|
|
if(type) {
|
|
|
|
|
// A new-style container with an explicit deserialization type
|
|
|
|
|
result = $tw.wiki.deserializeTiddlers(type,node.textContent);
|
|
|
|
|
} else {
|
|
|
|
|
// An old-style container of classic DIV-based tiddlers
|
|
|
|
|
for(t = 0; t < node.childNodes.length; t++) {
|
|
|
|
|
var childNode = node.childNodes[t],
|
|
|
|
|
tiddlers = extractTextTiddlers(childNode);
|
|
|
|
|
tiddlers = tiddlers || extractModuleTiddlers(childNode);
|
|
|
|
|
if(tiddlers) {
|
|
|
|
|
result.push.apply(result,tiddlers);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$tw.loadTiddlersBrowser = function() {
|
|
|
|
|
// In the browser, we load tiddlers from certain elements
|
|
|
|
|
var containerSelectors = [
|
|
|
|
|
// IDs for old-style v5.1.x tiddler stores
|
|
|
|
|
"#libraryModules",
|
|
|
|
|
"#modules",
|
|
|
|
|
"#bootKernelPrefix",
|
|
|
|
|
"#bootKernel",
|
|
|
|
|
"#styleArea",
|
|
|
|
|
"#storeArea",
|
|
|
|
|
"#systemArea",
|
|
|
|
|
// Classes for new-style v5.2.x JSON tiddler stores
|
|
|
|
|
"script.tiddlywiki-tiddler-store"
|
|
|
|
|
];
|
|
|
|
|
for(var t=0; t<containerSelectors.length; t++) {
|
|
|
|
|
var nodes = document.querySelectorAll(containerSelectors[t]);
|
|
|
|
|
for(var n=0; n<nodes.length; n++) {
|
|
|
|
|
$tw.wiki.addTiddlers($tw.wiki.deserializeTiddlers("(DOM)",nodes[n]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
/////////////////////////// Server definitions
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Get any encrypted tiddlers
|
|
|
|
|
*/
|
|
|
|
|
$tw.boot.decryptEncryptedTiddlers = function(callback) {
|
|
|
|
|
// Storing encrypted tiddlers on the server isn't supported yet
|
|
|
|
|
callback();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // End of if($tw.browser && !$tw.node)
|
|
|
|
|
|
|
|
|
|
/////////////////////////// Node definitions
|
|
|
|
|
|
|
|
|
|
if($tw.node) {
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Load the tiddlers contained in a particular file (and optionally extract fields from the accompanying .meta file) returned as {filepath:,type:,tiddlers:[],hasMetaFile:}
|
|
|
|
|
*/
|
|
|
|
|
$tw.loadTiddlersFromFile = function(filepath,fields) {
|
|
|
|
|
var ext = path.extname(filepath),
|
|
|
|
|
extensionInfo = $tw.utils.getFileExtensionInfo(ext),
|
|
|
|
|
type = extensionInfo ? extensionInfo.type : null,
|
|
|
|
|
typeInfo = type ? $tw.config.contentTypeInfo[type] : null,
|
|
|
|
|
data = fs.readFileSync(filepath,typeInfo ? typeInfo.encoding : "utf8"),
|
|
|
|
|
tiddlers = $tw.wiki.deserializeTiddlers(ext,data,fields),
|
|
|
|
|
metadata = $tw.loadMetadataForFile(filepath);
|
|
|
|
|
if(metadata) {
|
|
|
|
|
if(type === "application/json") {
|
|
|
|
|
tiddlers = [{text: data, type: "application/json"}];
|
|
|
|
|
}
|
|
|
|
|
tiddlers = [$tw.utils.extend({},tiddlers[0],metadata)];
|
|
|
|
|
}
|
|
|
|
|
return {filepath: filepath, type: type, tiddlers: tiddlers, hasMetaFile: !!metadata};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Load the metadata fields in the .meta file corresponding to a particular file
|
|
|
|
|
*/
|
|
|
|
|
$tw.loadMetadataForFile = function(filepath) {
|
|
|
|
|
var metafilename = filepath + ".meta";
|
|
|
|
|
if(fs.existsSync(metafilename)) {
|
|
|
|
|
return $tw.utils.parseFields(fs.readFileSync(metafilename,"utf8") || "");
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
A default set of files for TiddlyWiki to ignore during load.
|
|
|
|
|
This matches what NPM ignores, and adds "*.meta" to ignore tiddler
|
|
|
|
|
metadata files.
|
|
|
|
|
*/
|
|
|
|
|
$tw.boot.excludeRegExp = /^\.DS_Store$|^.*\.meta$|^\..*\.swp$|^\._.*$|^\.git$|^\.github$|^\.vscode$|^\.hg$|^\.lock-wscript$|^\.svn$|^\.wafpickle-.*$|^CVS$|^npm-debug\.log$/;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Load all the tiddlers recursively from a directory, including honouring `tiddlywiki.files` files for drawing in external files. Returns an array of {filepath:,type:,tiddlers: [{..fields...}],hasMetaFile:}. Note that no file information is returned for externally loaded tiddlers, just the `tiddlers` property.
|
|
|
|
|
*/
|
|
|
|
|
$tw.loadTiddlersFromPath = function(filepath,excludeRegExp) {
|
|
|
|
|
excludeRegExp = excludeRegExp || $tw.boot.excludeRegExp;
|
|
|
|
|
var tiddlers = [];
|
|
|
|
|
if(fs.existsSync(filepath)) {
|
|
|
|
|
var stat = fs.statSync(filepath);
|
|
|
|
|
if(stat.isDirectory()) {
|
|
|
|
|
var files = fs.readdirSync(filepath);
|
|
|
|
|
// Look for a tiddlywiki.files file
|
|
|
|
|
if(files.indexOf("tiddlywiki.files") !== -1) {
|
|
|
|
|
Array.prototype.push.apply(tiddlers,$tw.loadTiddlersFromSpecification(filepath,excludeRegExp));
|
|
|
|
|
} else {
|
|
|
|
|
// If not, read all the files in the directory
|
|
|
|
|
$tw.utils.each(files,function(file) {
|
|
|
|
|
if(!excludeRegExp.test(file) && file !== "plugin.info") {
|
|
|
|
|
tiddlers.push.apply(tiddlers,$tw.loadTiddlersFromPath(filepath + path.sep + file,excludeRegExp));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else if(stat.isFile()) {
|
|
|
|
|
tiddlers.push($tw.loadTiddlersFromFile(filepath,{title: filepath}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return tiddlers;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Load all the tiddlers defined by a `tiddlywiki.files` specification file
|
|
|
|
|
filepath: pathname of the directory containing the specification file
|
|
|
|
|
*/
|
|
|
|
|
$tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
|
|
|
|
var tiddlers = [];
|
|
|
|
|
// Read the specification
|
|
|
|
|
var filesInfo = $tw.utils.parseJSONSafe(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"));
|
|
|
|
|
// Helper to process a file
|
|
|
|
|
var processFile = function(filename,isTiddlerFile,fields,isEditableFile,rootPath) {
|
|
|
|
|
var extInfo = $tw.config.fileExtensionInfo[path.extname(filename)],
|
|
|
|
|
type = (extInfo || {}).type || fields.type || "text/plain",
|
|
|
|
|
typeInfo = $tw.config.contentTypeInfo[type] || {},
|
|
|
|
|
pathname = path.resolve(filepath,filename),
|
|
|
|
|
text = fs.readFileSync(pathname,typeInfo.encoding || "utf8"),
|
|
|
|
|
metadata = $tw.loadMetadataForFile(pathname) || {},
|
|
|
|
|
fileTiddlers;
|
|
|
|
|
if(isTiddlerFile) {
|
|
|
|
|
fileTiddlers = $tw.wiki.deserializeTiddlers(path.extname(pathname),text,metadata) || [];
|
|
|
|
|
} else {
|
|
|
|
|
fileTiddlers = [$tw.utils.extend({text: text},metadata)];
|
|
|
|
|
}
|
|
|
|
|
var combinedFields = $tw.utils.extend({},fields,metadata);
|
|
|
|
|
$tw.utils.each(fileTiddlers,function(tiddler) {
|
|
|
|
|
$tw.utils.each(combinedFields,function(fieldInfo,name) {
|
|
|
|
|
if(typeof fieldInfo === "string" || $tw.utils.isArray(fieldInfo)) {
|
|
|
|
|
tiddler[name] = fieldInfo;
|
|
|
|
|
} else {
|
|
|
|
|
var value = tiddler[name];
|
|
|
|
|
switch(fieldInfo.source) {
|
|
|
|
|
case "subdirectories":
|
|
|
|
|
value = path.relative(rootPath, filename).split('/').slice(0, -1);
|
|
|
|
|
break;
|
|
|
|
|
case "filepath":
|
|
|
|
|
value = path.relative(rootPath, filename);
|
|
|
|
|
break;
|
|
|
|
|
case "filename":
|
|
|
|
|
value = path.basename(filename);
|
|
|
|
|
break;
|
|
|
|
|
case "filename-uri-decoded":
|
|
|
|
|
value = $tw.utils.decodeURIComponentSafe(path.basename(filename));
|
|
|
|
|
break;
|
|
|
|
|
case "basename":
|
|
|
|
|
value = path.basename(filename,path.extname(filename));
|
|
|
|
|
break;
|
|
|
|
|
case "basename-uri-decoded":
|
|
|
|
|
value = $tw.utils.decodeURIComponentSafe(path.basename(filename,path.extname(filename)));
|
|
|
|
|
break;
|
|
|
|
|
case "extname":
|
|
|
|
|
value = path.extname(filename);
|
|
|
|
|
break;
|
|
|
|
|
case "created":
|
|
|
|
|
value = new Date(fs.statSync(pathname).birthtime);
|
|
|
|
|
break;
|
|
|
|
|
case "modified":
|
|
|
|
|
value = new Date(fs.statSync(pathname).mtime);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(fieldInfo.prefix) {
|
|
|
|
|
value = fieldInfo.prefix + value;
|
|
|
|
|
}
|
|
|
|
|
if(fieldInfo.suffix) {
|
|
|
|
|
value = value + fieldInfo.suffix;
|
|
|
|
|
}
|
|
|
|
|
tiddler[name] = value;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
if(isEditableFile) {
|
|
|
|
|
tiddlers.push({filepath: pathname, hasMetaFile: !!metadata && !isTiddlerFile, isEditableFile: true, tiddlers: fileTiddlers});
|
|
|
|
|
} else {
|
|
|
|
|
tiddlers.push({tiddlers: fileTiddlers});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
// Helper to recursively search subdirectories
|
|
|
|
|
var getAllFiles = function(dirPath, recurse, arrayOfFiles) {
|
|
|
|
|
recurse = recurse || false;
|
|
|
|
|
arrayOfFiles = arrayOfFiles || [];
|
|
|
|
|
var files = fs.readdirSync(dirPath);
|
|
|
|
|
files.forEach(function(file) {
|
|
|
|
|
if (recurse && fs.statSync(dirPath + path.sep + file).isDirectory()) {
|
|
|
|
|
arrayOfFiles = getAllFiles(dirPath + path.sep + file, recurse, arrayOfFiles);
|
|
|
|
|
} else if(fs.statSync(dirPath + path.sep + file).isFile()){
|
|
|
|
|
arrayOfFiles.push(path.join(dirPath, path.sep, file));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return arrayOfFiles;
|
|
|
|
|
}
|
|
|
|
|
// Process the listed tiddlers
|
|
|
|
|
$tw.utils.each(filesInfo.tiddlers,function(tidInfo) {
|
|
|
|
|
if(tidInfo.prefix && tidInfo.suffix) {
|
|
|
|
|
tidInfo.fields.text = {prefix: tidInfo.prefix,suffix: tidInfo.suffix};
|
|
|
|
|
} else if(tidInfo.prefix) {
|
|
|
|
|
tidInfo.fields.text = {prefix: tidInfo.prefix};
|
|
|
|
|
} else if(tidInfo.suffix) {
|
|
|
|
|
tidInfo.fields.text = {suffix: tidInfo.suffix};
|
|
|
|
|
}
|
|
|
|
|
processFile(tidInfo.file,tidInfo.isTiddlerFile,tidInfo.fields);
|
|
|
|
|
});
|
|
|
|
|
// Process any listed directories
|
|
|
|
|
$tw.utils.each(filesInfo.directories,function(dirSpec) {
|
|
|
|
|
// Read literal directories directly
|
|
|
|
|
if(typeof dirSpec === "string") {
|
|
|
|
|
var pathname = path.resolve(filepath,dirSpec);
|
|
|
|
|
if(fs.existsSync(pathname) && fs.statSync(pathname).isDirectory()) {
|
|
|
|
|
tiddlers.push.apply(tiddlers,$tw.loadTiddlersFromPath(pathname,excludeRegExp));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Process directory specifier
|
|
|
|
|
var dirPath = path.resolve(filepath,dirSpec.path);
|
|
|
|
|
if(fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
|
|
|
|
|
var files = getAllFiles(dirPath, dirSpec.searchSubdirectories),
|
|
|
|
|
fileRegExp = new RegExp(dirSpec.filesRegExp || "^.*$"),
|
|
|
|
|
metaRegExp = /^.*\.meta$/;
|
|
|
|
|
for(var t=0; t<files.length; t++) {
|
|
|
|
|
var thisPath = path.relative(filepath, files[t]),
|
|
|
|
|
filename = path.basename(thisPath);
|
|
|
|
|
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
|
|
|
|
|
processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile,dirSpec.path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
console.log("Warning: a directory in a tiddlywiki.files file does not exist.");
|
|
|
|
|
console.log("dirPath: " + dirPath);
|
|
|
|
|
console.log("tiddlywiki.files location: " + filepath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return tiddlers;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Load the tiddlers from a plugin folder, and package them up into a proper JSON plugin tiddler
|
|
|
|
|
*/
|
|
|
|
|
$tw.loadPluginFolder = function(filepath,excludeRegExp) {
|
|
|
|
|
excludeRegExp = excludeRegExp || $tw.boot.excludeRegExp;
|
|
|
|
|
var infoPath = filepath + path.sep + "plugin.info";
|
|
|
|
|
if(fs.existsSync(filepath) && fs.statSync(filepath).isDirectory()) {
|
|
|
|
|
// Read the plugin information
|
|
|
|
|
if(!fs.existsSync(infoPath) || !fs.statSync(infoPath).isFile()) {
|
|
|
|
|
console.log("Warning: missing plugin.info file in " + filepath);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
var pluginInfo = $tw.utils.parseJSONSafe(fs.readFileSync(infoPath,"utf8"),function() {return null;});
|
|
|
|
|
if(!pluginInfo) {
|
|
|
|
|
console.log("warning: invalid JSON in plugin.info file at " + infoPath);
|
|
|
|
|
pluginInfo = {};
|
|
|
|
|
}
|
|
|
|
|
// Read the plugin files
|
|
|
|
|
var pluginFiles = $tw.loadTiddlersFromPath(filepath,excludeRegExp);
|
|
|
|
|
// Save the plugin tiddlers into the plugin info
|
|
|
|
|
pluginInfo.tiddlers = pluginInfo.tiddlers || Object.create(null);
|
|
|
|
|
for(var f=0; f<pluginFiles.length; f++) {
|
|
|
|
|
var tiddlers = pluginFiles[f].tiddlers;
|
|
|
|
|
for(var t=0; t<tiddlers.length; t++) {
|
|
|
|
|
var tiddler= tiddlers[t];
|
|
|
|
|
if(tiddler.title) {
|
|
|
|
|
pluginInfo.tiddlers[tiddler.title] = tiddler;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Give the plugin the same version number as the core if it doesn't have one
|
|
|
|
|
if(!("version" in pluginInfo)) {
|
|
|
|
|
pluginInfo.version = $tw.packageInfo.version;
|
|
|
|
|
}
|
|
|
|
|
// Use "plugin" as the plugin-type if we don't have one
|
|
|
|
|
if(!("plugin-type" in pluginInfo)) {
|
|
|
|
|
pluginInfo["plugin-type"] = "plugin";
|
|
|
|
|
}
|
|
|
|
|
pluginInfo.dependents = pluginInfo.dependents || [];
|
|
|
|
|
pluginInfo.type = "application/json";
|
|
|
|
|
// Set plugin text
|
|
|
|
|
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers});
|
|
|
|
|
delete pluginInfo.tiddlers;
|
|
|
|
|
// Deserialise array fields (currently required for the dependents field)
|
|
|
|
|
for(var field in pluginInfo) {
|
|
|
|
|
if($tw.utils.isArray(pluginInfo[field])) {
|
|
|
|
|
pluginInfo[field] = $tw.utils.stringifyList(pluginInfo[field]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return pluginInfo;
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
name: Name of the plugin to find
|
|
|
|
|
paths: array of file paths to search for it
|
|
|
|
|
Returns the path of the plugin folder
|
|
|
|
|
*/
|
|
|
|
|
$tw.findLibraryItem = function(name,paths) {
|
|
|
|
|
var pathIndex = 0;
|
|
|
|
|
do {
|
|
|
|
|
var pluginPath = path.resolve(paths[pathIndex],"./" + name)
|
|
|
|
|
if(fs.existsSync(pluginPath) && fs.statSync(pluginPath).isDirectory()) {
|
|
|
|
|
return pluginPath;
|
|
|
|
|
}
|
|
|
|
|
} while(++pathIndex < paths.length);
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
name: Name of the plugin to load
|
|
|
|
|
paths: array of file paths to search for it
|
|
|
|
|
*/
|
|
|
|
|
$tw.loadPlugin = function(name,paths) {
|
|
|
|
|
var pluginPath = $tw.findLibraryItem(name,paths);
|
|
|
|
|
if(pluginPath) {
|
|
|
|
|
var pluginFields = $tw.loadPluginFolder(pluginPath);
|
|
|
|
|
if(pluginFields) {
|
|
|
|
|
$tw.wiki.addTiddler(pluginFields);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
console.log("Warning: Cannot find plugin '" + name + "'");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
libraryPath: Path of library folder for these plugins (relative to core path)
|
|
|
|
|
envVar: Environment variable name for these plugins
|
|
|
|
|
Returns an array of search paths
|
|
|
|
|
*/
|
|
|
|
|
$tw.getLibraryItemSearchPaths = function(libraryPath,envVar) {
|
|
|
|
|
var pluginPaths = [path.resolve($tw.boot.corePath,libraryPath)],
|
|
|
|
|
env = process.env[envVar];
|
|
|
|
|
if(env) {
|
|
|
|
|
env.split(path.delimiter).map(function(item) {
|
|
|
|
|
if(item) {
|
|
|
|
|
pluginPaths.push(item);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return pluginPaths;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
plugins: Array of names of plugins (eg, "tiddlywiki/filesystemadaptor")
|
|
|
|
|
libraryPath: Path of library folder for these plugins (relative to core path)
|
|
|
|
|
envVar: Environment variable name for these plugins
|
|
|
|
|
*/
|
|
|
|
|
$tw.loadPlugins = function(plugins,libraryPath,envVar) {
|
|
|
|
|
if(plugins) {
|
|
|
|
|
var pluginPaths = $tw.getLibraryItemSearchPaths(libraryPath,envVar);
|
|
|
|
|
for(var t=0; t<plugins.length; t++) {
|
|
|
|
|
$tw.loadPlugin(plugins[t],pluginPaths);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
path: path of wiki directory
|
|
|
|
|
options:
|
|
|
|
|
parentPaths: array of parent paths that we mustn't recurse into
|
|
|
|
|
readOnly: true if the tiddler file paths should not be retained
|
|
|
|
|
*/
|
|
|
|
|
$tw.loadWikiTiddlers = function(wikiPath,options) {
|
|
|
|
|
options = options || {};
|
|
|
|
|
var parentPaths = options.parentPaths || [],
|
|
|
|
|
wikiInfoPath = path.resolve(wikiPath,$tw.config.wikiInfo),
|
|
|
|
|
wikiInfo,
|
|
|
|
|
pluginFields;
|
|
|
|
|
// Bail if we don't have a wiki info file
|
|
|
|
|
if(fs.existsSync(wikiInfoPath)) {
|
|
|
|
|
wikiInfo = $tw.utils.parseJSONSafe(fs.readFileSync(wikiInfoPath,"utf8"),function() {return null;});
|
|
|
|
|
if(!wikiInfo) {
|
|
|
|
|
console.log("warning: invalid JSON in tiddlywiki.info file at " + wikiInfoPath);
|
|
|
|
|
wikiInfo = {};
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
// Save the path to the tiddlers folder for the filesystemadaptor
|
|
|
|
|
var config = wikiInfo.config || {};
|
|
|
|
|
if($tw.boot.wikiPath == wikiPath) {
|
|
|
|
|
$tw.boot.wikiTiddlersPath = path.resolve($tw.boot.wikiPath,config["default-tiddler-location"] || $tw.config.wikiTiddlersSubDir);
|
|
|
|
|
}
|
|
|
|
|
// Load any parent wikis
|
|
|
|
|
if(wikiInfo.includeWikis) {
|
|
|
|
|
parentPaths = parentPaths.slice(0);
|
|
|
|
|
parentPaths.push(wikiPath);
|
|
|
|
|
$tw.utils.each(wikiInfo.includeWikis,function(info) {
|
|
|
|
|
if(typeof info === "string") {
|
|
|
|
|
info = {path: info};
|
|
|
|
|
}
|
|
|
|
|
var resolvedIncludedWikiPath = path.resolve(wikiPath,info.path);
|
|
|
|
|
if(parentPaths.indexOf(resolvedIncludedWikiPath) === -1) {
|
|
|
|
|
var subWikiInfo = $tw.loadWikiTiddlers(resolvedIncludedWikiPath,{
|
|
|
|
|
parentPaths: parentPaths,
|
|
|
|
|
readOnly: info["read-only"]
|
|
|
|
|
});
|
|
|
|
|
// Merge the build targets
|
|
|
|
|
wikiInfo.build = $tw.utils.extend([],subWikiInfo.build,wikiInfo.build);
|
|
|
|
|
} else {
|
|
|
|
|
$tw.utils.error("Cannot recursively include wiki " + resolvedIncludedWikiPath);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// Load any plugins, themes and languages listed in the wiki info file
|
|
|
|
|
$tw.loadPlugins(wikiInfo.plugins,$tw.config.pluginsPath,$tw.config.pluginsEnvVar);
|
|
|
|
|
$tw.loadPlugins(wikiInfo.themes,$tw.config.themesPath,$tw.config.themesEnvVar);
|
|
|
|
|
$tw.loadPlugins(wikiInfo.languages,$tw.config.languagesPath,$tw.config.languagesEnvVar);
|
|
|
|
|
// Load the wiki files, registering them as writable
|
|
|
|
|
var resolvedWikiPath = path.resolve(wikiPath,$tw.config.wikiTiddlersSubDir);
|
|
|
|
|
$tw.utils.each($tw.loadTiddlersFromPath(resolvedWikiPath),function(tiddlerFile) {
|
|
|
|
|
if(!options.readOnly && tiddlerFile.filepath) {
|
|
|
|
|
$tw.utils.each(tiddlerFile.tiddlers,function(tiddler) {
|
|
|
|
|
$tw.boot.files[tiddler.title] = {
|
|
|
|
|
filepath: tiddlerFile.filepath,
|
|
|
|
|
type: tiddlerFile.type,
|
|
|
|
|
hasMetaFile: tiddlerFile.hasMetaFile,
|
|
|
|
|
isEditableFile: config["retain-original-tiddler-path"] || tiddlerFile.isEditableFile || tiddlerFile.filepath.indexOf($tw.boot.wikiTiddlersPath) !== 0
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
$tw.wiki.addTiddlers(tiddlerFile.tiddlers);
|
|
|
|
|
});
|
|
|
|
|
if ($tw.boot.wikiPath == wikiPath) {
|
|
|
|
|
// Save the original tiddler file locations if requested
|
|
|
|
|
var output = {}, relativePath, fileInfo;
|
|
|
|
|
for(var title in $tw.boot.files) {
|
|
|
|
|
fileInfo = $tw.boot.files[title];
|
|
|
|
|
if(fileInfo.isEditableFile) {
|
|
|
|
|
relativePath = path.relative($tw.boot.wikiTiddlersPath,fileInfo.filepath);
|
|
|
|
|
fileInfo.originalpath = relativePath;
|
|
|
|
|
output[title] =
|
|
|
|
|
path.sep === "/" ?
|
|
|
|
|
relativePath :
|
|
|
|
|
relativePath.split(path.sep).join("/");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(Object.keys(output).length > 0){
|
|
|
|
|
$tw.wiki.addTiddler({title: "$:/config/OriginalTiddlerPaths", type: "application/json", text: JSON.stringify(output)});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Load any plugins within the wiki folder
|
|
|
|
|
var wikiPluginsPath = path.resolve(wikiPath,$tw.config.wikiPluginsSubDir);
|
|
|
|
|
if(fs.existsSync(wikiPluginsPath)) {
|
|
|
|
|
var pluginFolders = fs.readdirSync(wikiPluginsPath);
|
|
|
|
|
for(var t=0; t<pluginFolders.length; t++) {
|
|
|
|
|
pluginFields = $tw.loadPluginFolder(path.resolve(wikiPluginsPath,"./" + pluginFolders[t]));
|
|
|
|
|
if(pluginFields) {
|
|
|
|
|
$tw.wiki.addTiddler(pluginFields);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Load any themes within the wiki folder
|
|
|
|
|
var wikiThemesPath = path.resolve(wikiPath,$tw.config.wikiThemesSubDir);
|
|
|
|
|
if(fs.existsSync(wikiThemesPath)) {
|
|
|
|
|
var themeFolders = fs.readdirSync(wikiThemesPath);
|
|
|
|
|
for(var t=0; t<themeFolders.length; t++) {
|
|
|
|
|
pluginFields = $tw.loadPluginFolder(path.resolve(wikiThemesPath,"./" + themeFolders[t]));
|
|
|
|
|
if(pluginFields) {
|
|
|
|
|
$tw.wiki.addTiddler(pluginFields);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Load any languages within the wiki folder
|
|
|
|
|
var wikiLanguagesPath = path.resolve(wikiPath,$tw.config.wikiLanguagesSubDir);
|
|
|
|
|
if(fs.existsSync(wikiLanguagesPath)) {
|
|
|
|
|
var languageFolders = fs.readdirSync(wikiLanguagesPath);
|
|
|
|
|
for(var t=0; t<languageFolders.length; t++) {
|
|
|
|
|
pluginFields = $tw.loadPluginFolder(path.resolve(wikiLanguagesPath,"./" + languageFolders[t]));
|
|
|
|
|
if(pluginFields) {
|
|
|
|
|
$tw.wiki.addTiddler(pluginFields);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return wikiInfo;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$tw.loadTiddlersNode = function() {
|
|
|
|
|
// Load the boot tiddlers
|
|
|
|
|
$tw.utils.each($tw.loadTiddlersFromPath($tw.boot.bootPath),function(tiddlerFile) {
|
|
|
|
|
$tw.wiki.addTiddlers(tiddlerFile.tiddlers);
|
|
|
|
|
});
|
|
|
|
|
// Load the core tiddlers
|
|
|
|
|
$tw.wiki.addTiddler($tw.loadPluginFolder($tw.boot.corePath));
|
|
|
|
|
// Load any extra plugins
|
|
|
|
|
$tw.utils.each($tw.boot.extraPlugins,function(name) {
|
|
|
|
|
if(name.charAt(0) === "+") { // Relative path to plugin
|
|
|
|
|
var pluginFields = $tw.loadPluginFolder(name.substring(1));
|
|
|
|
|
if(pluginFields) {
|
|
|
|
|
$tw.wiki.addTiddler(pluginFields);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
var parts = name.split("/"),
|
|
|
|
|
type = parts[0];
|
|
|
|
|
if(parts.length === 3 && ["plugins","themes","languages"].indexOf(type) !== -1) {
|
|
|
|
|
$tw.loadPlugins([parts[1] + "/" + parts[2]],$tw.config[type + "Path"],$tw.config[type + "EnvVar"]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// Load the tiddlers from the wiki directory
|
|
|
|
|
if($tw.boot.wikiPath) {
|
|
|
|
|
$tw.boot.wikiInfo = $tw.loadWikiTiddlers($tw.boot.wikiPath);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// End of if($tw.node)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////// Main startup function called once tiddlers have been decrypted
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Startup TiddlyWiki
|
|
|
|
|
*/
|
|
|
|
|
$tw.boot.initStartup = function(options) {
|
|
|
|
|
// Get the URL hash and check for safe mode
|
|
|
|
|
$tw.locationHash = "#";
|
|
|
|
|
if($tw.browser && !$tw.node) {
|
|
|
|
|
if(location.hash === "#:safe") {
|
|
|
|
|
$tw.safeMode = true;
|
|
|
|
|
} else {
|
|
|
|
|
$tw.locationHash = $tw.utils.getLocationHash();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Initialise some more $tw properties
|
|
|
|
|
$tw.utils.deepDefaults($tw,{
|
|
|
|
|
modules: { // Information about each module
|
|
|
|
|
titles: Object.create(null), // hashmap by module title of {fn:, exports:, moduleType:}
|
|
|
|
|
types: {} // hashmap by module type of hashmap of exports
|
|
|
|
|
},
|
|
|
|
|
config: { // Configuration overridables
|
|
|
|
|
pluginsPath: "../plugins/",
|
|
|
|
|
themesPath: "../themes/",
|
|
|
|
|
languagesPath: "../languages/",
|
|
|
|
|
editionsPath: "../editions/",
|
|
|
|
|
wikiInfo: "./tiddlywiki.info",
|
|
|
|
|
wikiPluginsSubDir: "./plugins",
|
|
|
|
|
wikiThemesSubDir: "./themes",
|
|
|
|
|
wikiLanguagesSubDir: "./languages",
|
|
|
|
|
wikiTiddlersSubDir: "./tiddlers",
|
|
|
|
|
wikiOutputSubDir: "./output",
|
|
|
|
|
jsModuleHeaderRegExpString: "^\\/\\*\\\\(?:\\r?\\n)((?:^[^\\r\\n]*(?:\\r?\\n))+?)(^\\\\\\*\\/$(?:\\r?\\n)?)",
|
|
|
|
|
fileExtensionInfo: Object.create(null), // Map file extension to {type:}
|
|
|
|
|
contentTypeInfo: Object.create(null), // Map type to {encoding:,extension:}
|
|
|
|
|
pluginsEnvVar: "TIDDLYWIKI_PLUGIN_PATH",
|
|
|
|
|
themesEnvVar: "TIDDLYWIKI_THEME_PATH",
|
|
|
|
|
languagesEnvVar: "TIDDLYWIKI_LANGUAGE_PATH",
|
|
|
|
|
editionsEnvVar: "TIDDLYWIKI_EDITION_PATH"
|
|
|
|
|
},
|
|
|
|
|
log: {}, // Log flags
|
|
|
|
|
unloadTasks: []
|
|
|
|
|
});
|
|
|
|
|
if(!$tw.boot.tasks.readBrowserTiddlers) {
|
|
|
|
|
// For writable tiddler files, a hashmap of title to {filepath:,type:,hasMetaFile:}
|
|
|
|
|
$tw.boot.files = Object.create(null);
|
|
|
|
|
// System paths and filenames
|
|
|
|
|
$tw.boot.bootPath = options.bootPath || path.dirname(module.filename);
|
|
|
|
|
$tw.boot.corePath = path.resolve($tw.boot.bootPath,"../core");
|
|
|
|
|
// If there's no arguments then default to `--help`
|
|
|
|
|
if($tw.boot.argv.length === 0) {
|
|
|
|
|
$tw.boot.argv = ["--help"];
|
|
|
|
|
}
|
|
|
|
|
// Parse any extra plugin references
|
|
|
|
|
$tw.boot.extraPlugins = $tw.boot.extraPlugins || [];
|
|
|
|
|
while($tw.boot.argv[0] && $tw.boot.argv[0].indexOf("+") === 0) {
|
|
|
|
|
$tw.boot.extraPlugins.push($tw.boot.argv[0].substring(1));
|
|
|
|
|
$tw.boot.argv.splice(0,1);
|
|
|
|
|
}
|
|
|
|
|
// If the first command line argument doesn't start with `--` then we
|
|
|
|
|
// interpret it as the path to the wiki folder, which will otherwise default
|
|
|
|
|
// to the current folder
|
|
|
|
|
if($tw.boot.argv[0] && $tw.boot.argv[0].indexOf("--") !== 0) {
|
|
|
|
|
$tw.boot.wikiPath = $tw.boot.argv[0];
|
|
|
|
|
$tw.boot.argv = $tw.boot.argv.slice(1);
|
|
|
|
|
} else {
|
|
|
|
|
$tw.boot.wikiPath = process.cwd();
|
|
|
|
|
}
|
|
|
|
|
// Read package info
|
|
|
|
|
$tw.packageInfo = $tw.packageInfo || require("../package.json");
|
|
|
|
|
// Check node version number
|
|
|
|
|
if(!$tw.utils.checkVersions(process.version.substr(1),$tw.packageInfo.engines.node.substr(2))) {
|
|
|
|
|
$tw.utils.error("TiddlyWiki5 requires node.js version " + $tw.packageInfo.engines.node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Add file extension information
|
|
|
|
|
$tw.utils.registerFileType("text/vnd.tiddlywiki","utf8",".tid");
|
|
|
|
|
$tw.utils.registerFileType("application/x-tiddler","utf8",".tid");
|
|
|
|
|
$tw.utils.registerFileType("application/x-tiddlers","utf8",".multids");
|
|
|
|
|
$tw.utils.registerFileType("application/x-tiddler-html-div","utf8",".tiddler");
|
|
|
|
|
$tw.utils.registerFileType("text/vnd.tiddlywiki2-recipe","utf8",".recipe");
|
|
|
|
|
$tw.utils.registerFileType("text/plain","utf8",".txt");
|
|
|
|
|
$tw.utils.registerFileType("text/css","utf8",".css");
|
|
|
|
|
$tw.utils.registerFileType("text/html","utf8",[".html",".htm"]);
|
|
|
|
|
$tw.utils.registerFileType("application/hta","utf16le",".hta",{deserializerType:"text/html"});
|
|
|
|
|
$tw.utils.registerFileType("application/javascript","utf8",".js");
|
|
|
|
|
$tw.utils.registerFileType("application/json","utf8",".json");
|
|
|
|
|
$tw.utils.registerFileType("application/pdf","base64",".pdf",{flags:["image"]});
|
|
|
|
|
$tw.utils.registerFileType("application/zip","base64",".zip");
|
|
|
|
|
$tw.utils.registerFileType("application/x-zip-compressed","base64",".zip");
|
|
|
|
|
$tw.utils.registerFileType("image/jpeg","base64",[".jpg",".jpeg"],{flags:["image"]});
|
|
|
|
|
$tw.utils.registerFileType("image/jpg","base64",[".jpg",".jpeg"],{flags:["image"]});
|
|
|
|
|
$tw.utils.registerFileType("image/png","base64",".png",{flags:["image"]});
|
|
|
|
|
$tw.utils.registerFileType("image/gif","base64",".gif",{flags:["image"]});
|
|
|
|
|
$tw.utils.registerFileType("image/webp","base64",".webp",{flags:["image"]});
|
|
|
|
|
$tw.utils.registerFileType("image/heic","base64",".heic",{flags:["image"]});
|
|
|
|
|
$tw.utils.registerFileType("image/heif","base64",".heif",{flags:["image"]});
|
|
|
|
|
$tw.utils.registerFileType("image/svg+xml","utf8",".svg",{flags:["image"]});
|
|
|
|
|
$tw.utils.registerFileType("image/vnd.microsoft.icon","base64",".ico",{flags:["image"]});
|
|
|
|
|
$tw.utils.registerFileType("image/x-icon","base64",".ico",{flags:["image"]});
|
|
|
|
|
$tw.utils.registerFileType("application/font-woff","base64",".woff");
|
|
|
|
|
$tw.utils.registerFileType("application/x-font-ttf","base64",".woff");
|
|
|
|
|
$tw.utils.registerFileType("application/font-woff2","base64",".woff2");
|
|
|
|
|
$tw.utils.registerFileType("audio/ogg","base64",".ogg");
|
|
|
|
|
$tw.utils.registerFileType("audio/mp4","base64",[".mp4",".m4a"]);
|
|
|
|
|
$tw.utils.registerFileType("video/ogg","base64",[".ogm",".ogv",".ogg"]);
|
|
|
|
|
$tw.utils.registerFileType("video/webm","base64",".webm");
|
|
|
|
|
$tw.utils.registerFileType("video/mp4","base64",".mp4");
|
|
|
|
|
$tw.utils.registerFileType("audio/mp3","base64",".mp3");
|
|
|
|
|
$tw.utils.registerFileType("audio/mpeg","base64",[".mp3",".m2a",".mp2",".mpa",".mpg",".mpga"]);
|
|
|
|
|
$tw.utils.registerFileType("text/markdown","utf8",[".md",".markdown"],{deserializerType:"text/x-markdown"});
|
|
|
|
|
$tw.utils.registerFileType("text/x-markdown","utf8",[".md",".markdown"]);
|
|
|
|
|
$tw.utils.registerFileType("application/enex+xml","utf8",".enex");
|
|
|
|
|
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.wordprocessingml.document","base64",".docx");
|
|
|
|
|
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","base64",".xlsx");
|
|
|
|
|
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.presentationml.presentation","base64",".pptx");
|
|
|
|
|
$tw.utils.registerFileType("text/x-bibtex","utf8",".bib",{deserializerType:"application/x-bibtex"});
|
|
|
|
|
$tw.utils.registerFileType("application/x-bibtex","utf8",".bib");
|
|
|
|
|
$tw.utils.registerFileType("application/epub+zip","base64",".epub");
|
|
|
|
|
$tw.utils.registerFileType("application/octet-stream","base64",".octet-stream");
|
|
|
|
|
// Create the wiki store for the app
|
|
|
|
|
$tw.wiki = new $tw.Wiki($tw.safeMode && {enableIndexers: []});
|
|
|
|
|
// Install built in tiddler fields modules
|
|
|
|
|
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
|
|
|
|
|
// Install the tiddler deserializer modules
|
|
|
|
|
$tw.Wiki.tiddlerDeserializerModules = Object.create(null);
|
|
|
|
|
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
|
|
|
|
|
// Call unload handlers in the browser
|
|
|
|
|
if($tw.browser) {
|
|
|
|
|
window.onbeforeunload = function(event) {
|
|
|
|
|
event = event || {};
|
|
|
|
|
var result;
|
|
|
|
|
$tw.utils.each($tw.unloadTasks,function(task) {
|
|
|
|
|
var r = task(event);
|
|
|
|
|
if(r) {
|
|
|
|
|
result = r;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
$tw.boot.loadStartup = function(options){
|
|
|
|
|
|
|
|
|
|
// Load tiddlers
|
|
|
|
|
if($tw.boot.tasks.readBrowserTiddlers) {
|
|
|
|
|
$tw.loadTiddlersBrowser();
|
|
|
|
|
} else {
|
|
|
|
|
$tw.loadTiddlersNode();
|
|
|
|
|
}
|
|
|
|
|
// Load any preloaded tiddlers
|
|
|
|
|
if($tw.preloadTiddlers) {
|
|
|
|
|
$tw.wiki.addTiddlers($tw.preloadTiddlers);
|
|
|
|
|
}
|
|
|
|
|
// Give hooks a chance to modify the store
|
|
|
|
|
$tw.hooks.invokeHook("th-boot-tiddlers-loaded");
|
|
|
|
|
}
|
|
|
|
|
$tw.boot.execStartup = function(options){
|
|
|
|
|
// Unpack plugin tiddlers
|
|
|
|
|
$tw.wiki.readPluginInfo();
|
|
|
|
|
$tw.wiki.registerPluginTiddlers("plugin",$tw.safeMode ? ["$:/core"] : undefined);
|
|
|
|
|
$tw.wiki.unpackPluginTiddlers();
|
|
|
|
|
// Process "safe mode"
|
|
|
|
|
if($tw.safeMode) {
|
|
|
|
|
$tw.wiki.processSafeMode();
|
|
|
|
|
}
|
|
|
|
|
// Register typed modules from the tiddlers we've just loaded
|
|
|
|
|
$tw.wiki.defineTiddlerModules();
|
|
|
|
|
// And any modules within plugins
|
|
|
|
|
$tw.wiki.defineShadowModules();
|
|
|
|
|
// Make sure the crypto state tiddler is up to date
|
|
|
|
|
if($tw.crypto) {
|
|
|
|
|
$tw.crypto.updateCryptoStateTiddler();
|
|
|
|
|
}
|
|
|
|
|
// Gather up any startup modules
|
|
|
|
|
$tw.boot.remainingStartupModules = []; // Array of startup modules
|
|
|
|
|
$tw.modules.forEachModuleOfType("startup",function(title,module) {
|
|
|
|
|
if(module.startup) {
|
|
|
|
|
$tw.boot.remainingStartupModules.push(module);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// Keep track of the startup tasks that have been executed
|
|
|
|
|
$tw.boot.executedStartupModules = Object.create(null);
|
|
|
|
|
$tw.boot.disabledStartupModules = $tw.boot.disabledStartupModules || [];
|
|
|
|
|
// Repeatedly execute the next eligible task
|
|
|
|
|
$tw.boot.executeNextStartupTask(options.callback);
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
Startup TiddlyWiki
|
|
|
|
|
*/
|
|
|
|
|
$tw.boot.startup = function(options) {
|
|
|
|
|
options = options || {};
|
|
|
|
|
// Get the URL hash and check for safe mode
|
|
|
|
|
$tw.boot.initStartup(options);
|
|
|
|
|
$tw.boot.loadStartup(options);
|
|
|
|
|
$tw.boot.execStartup(options);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Add another unload task
|
|
|
|
|
*/
|
|
|
|
|
$tw.addUnloadTask = function(task) {
|
|
|
|
|
if($tw.unloadTasks.indexOf(task) === -1) {
|
|
|
|
|
$tw.unloadTasks.push(task);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Execute the remaining eligible startup tasks
|
|
|
|
|
*/
|
|
|
|
|
$tw.boot.executeNextStartupTask = function(callback) {
|
|
|
|
|
// Find the next eligible task
|
|
|
|
|
var taskIndex = 0, task,
|
|
|
|
|
asyncTaskCallback = function() {
|
|
|
|
|
if(task.name) {
|
|
|
|
|
$tw.boot.executedStartupModules[task.name] = true;
|
|
|
|
|
}
|
|
|
|
|
return $tw.boot.executeNextStartupTask(callback);
|
|
|
|
|
};
|
|
|
|
|
while(taskIndex < $tw.boot.remainingStartupModules.length) {
|
|
|
|
|
task = $tw.boot.remainingStartupModules[taskIndex];
|
|
|
|
|
if($tw.boot.isStartupTaskEligible(task)) {
|
|
|
|
|
// Remove this task from the list
|
|
|
|
|
$tw.boot.remainingStartupModules.splice(taskIndex,1);
|
|
|
|
|
// Assemble log message
|
|
|
|
|
var s = ["Startup task:",task.name];
|
|
|
|
|
if(task.platforms) {
|
|
|
|
|
s.push("platforms:",task.platforms.join(","));
|
|
|
|
|
}
|
|
|
|
|
if(task.after) {
|
|
|
|
|
s.push("after:",task.after.join(","));
|
|
|
|
|
}
|
|
|
|
|
if(task.before) {
|
|
|
|
|
s.push("before:",task.before.join(","));
|
|
|
|
|
}
|
|
|
|
|
$tw.boot.log(s.join(" "));
|
|
|
|
|
// Execute task
|
|
|
|
|
if(!$tw.utils.hop(task,"synchronous") || task.synchronous) {
|
|
|
|
|
task.startup();
|
|
|
|
|
if(task.name) {
|
|
|
|
|
$tw.boot.executedStartupModules[task.name] = true;
|
|
|
|
|
}
|
|
|
|
|
return $tw.boot.executeNextStartupTask(callback);
|
|
|
|
|
} else {
|
|
|
|
|
task.startup(asyncTaskCallback);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
taskIndex++;
|
|
|
|
|
}
|
|
|
|
|
if(typeof callback === 'function') {
|
|
|
|
|
callback();
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Returns true if we are running on one of the platforms specified in taskModule's
|
|
|
|
|
`platforms` array; or if `platforms` property is not defined.
|
|
|
|
|
*/
|
|
|
|
|
$tw.boot.doesTaskMatchPlatform = function(taskModule) {
|
|
|
|
|
var platforms = taskModule.platforms;
|
|
|
|
|
if(platforms) {
|
|
|
|
|
for(var t=0; t<platforms.length; t++) {
|
|
|
|
|
switch (platforms[t]) {
|
|
|
|
|
case "browser":
|
|
|
|
|
if ($tw.browser) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "node":
|
|
|
|
|
if ($tw.node) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
$tw.utils.error("Module " + taskModule.name + ": '" + platforms[t] + "' in export.platforms invalid");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$tw.boot.isStartupTaskEligible = function(taskModule) {
|
|
|
|
|
var t;
|
|
|
|
|
// Check that the platform is correct
|
|
|
|
|
if(!$tw.boot.doesTaskMatchPlatform(taskModule)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
var name = taskModule.name,
|
|
|
|
|
remaining = $tw.boot.remainingStartupModules;
|
|
|
|
|
if(name) {
|
|
|
|
|
// Fail if this module is disabled
|
|
|
|
|
if($tw.boot.disabledStartupModules.indexOf(name) !== -1) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// Check that no other outstanding tasks must be executed before this one
|
|
|
|
|
for(t=0; t<remaining.length; t++) {
|
|
|
|
|
var task = remaining[t];
|
|
|
|
|
if(task.before && task.before.indexOf(name) !== -1) {
|
|
|
|
|
if($tw.boot.doesTaskMatchPlatform(task) && (!task.name || $tw.boot.disabledStartupModules.indexOf(task.name) === -1)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Check that all of the tasks that we must be performed after has been done
|
|
|
|
|
var after = taskModule.after;
|
|
|
|
|
if(after) {
|
|
|
|
|
for(t=0; t<after.length; t++) {
|
|
|
|
|
if(!$tw.boot.executedStartupModules[after[t]]) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Global Hooks mechanism which allows plugins to modify default functionality
|
|
|
|
|
*/
|
|
|
|
|
$tw.hooks = $tw.hooks || { names: {}};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Add hooks to the hashmap
|
|
|
|
|
*/
|
|
|
|
|
$tw.hooks.addHook = function(hookName,definition) {
|
|
|
|
|
if($tw.utils.hop($tw.hooks.names,hookName)) {
|
|
|
|
|
$tw.hooks.names[hookName].push(definition);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$tw.hooks.names[hookName] = [definition];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Invoke the hook by key
|
|
|
|
|
*/
|
|
|
|
|
$tw.hooks.invokeHook = function(hookName /*, value,... */) {
|
|
|
|
|
var args = Array.prototype.slice.call(arguments,1);
|
|
|
|
|
if($tw.utils.hop($tw.hooks.names,hookName)) {
|
|
|
|
|
for (var i = 0; i < $tw.hooks.names[hookName].length; i++) {
|
|
|
|
|
args[0] = $tw.hooks.names[hookName][i].apply(null,args);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return args[0];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/////////////////////////// Main boot function to decrypt tiddlers and then startup
|
|
|
|
|
|
|
|
|
|
$tw.boot.boot = function(callback) {
|
|
|
|
|
// Initialise crypto object
|
|
|
|
|
$tw.crypto = new $tw.utils.Crypto();
|
|
|
|
|
// Initialise password prompter
|
|
|
|
|
if($tw.browser && !$tw.node) {
|
|
|
|
|
$tw.passwordPrompt = new $tw.utils.PasswordPrompt();
|
|
|
|
|
}
|
|
|
|
|
// Preload any encrypted tiddlers
|
|
|
|
|
$tw.boot.decryptEncryptedTiddlers(function() {
|
|
|
|
|
// Startup
|
|
|
|
|
$tw.boot.startup({callback: callback});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/////////////////////////// Autoboot in the browser
|
|
|
|
|
|
|
|
|
|
if($tw.browser && !$tw.boot.suppressBoot) {
|
|
|
|
|
$tw.boot.boot();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $tw;
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(typeof(exports) !== "undefined") {
|
|
|
|
|
exports.TiddlyWiki = _boot;
|
|
|
|
|
} else {
|
|
|
|
|
_boot(window.$tw);
|
|
|
|
|
}
|
|
|
|
|
//# sourceURL=$:/boot/boot.js
|
|
|
|
|
</script>
|
|
|
|
|
</div>
|
|
|
|
|
<!--~~ Raw markup for the bottom of the body section ~~-->
|
|
|
|
|
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|