Sometimes it is useful to define additional variables local to the function. By convention, the `/local` refinement is reserved for this purpose.
Table of Contents
hide
{ "tiddlers": { "$:/Acknowledgements": { "title": "$:/Acknowledgements", "type": "text/vnd.tiddlywiki", "text": "TiddlyWiki incorporates code from these fine OpenSource projects:\n\n* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]\n* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]\n* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]\n\nAnd media from these projects:\n\n* World flag icons from [[Wikipedia|http://commons.wikimedia.org/wiki/Category:SVG_flags_by_country]]\n" }, "$:/core/copyright.txt": { "title": "$:/core/copyright.txt", "type": "text/plain", "text": "TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)\n\nCopyright (c) 2004-2007, Jeremy Ruston\nCopyright (c) 2007-2017, UnaMesa Association\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the copyright holder nor the names of its\n contributors may be used to endorse or promote products derived from\n this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." }, "$:/core/icon": { "title": "$:/core/icon", "tags": "$:/tags/Image", "text": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\"><path d=\"M64 0l54.56 32v64L64 128 9.44 96V32L64 0zm21.127 95.408c-3.578-.103-5.15-.094-6.974-3.152l-1.42.042c-1.653-.075-.964-.04-2.067-.097-1.844-.07-1.548-1.86-1.873-2.8-.52-3.202.687-6.43.65-9.632-.014-1.14-1.593-5.17-2.157-6.61-1.768.34-3.546.406-5.34.497-4.134-.01-8.24-.527-12.317-1.183-.8 3.35-3.16 8.036-1.21 11.44 2.37 3.52 4.03 4.495 6.61 4.707 2.572.212 3.16 3.18 2.53 4.242-.55.73-1.52.864-2.346 1.04l-1.65.08c-1.296-.046-2.455-.404-3.61-.955-1.93-1.097-3.925-3.383-5.406-5.024.345.658.55 1.938.24 2.53-.878 1.27-4.665 1.26-6.4.47-1.97-.89-6.73-7.162-7.468-11.86 1.96-3.78 4.812-7.07 6.255-11.186-3.146-2.05-4.83-5.384-4.61-9.16l.08-.44c-3.097.59-1.49.37-4.82.628-10.608-.032-19.935-7.37-14.68-18.774.34-.673.664-1.287 1.243-.994.466.237.4 1.18.166 2.227-3.005 13.627 11.67 13.732 20.69 11.21.89-.25 2.67-1.936 3.905-2.495 2.016-.91 4.205-1.282 6.376-1.55 5.4-.63 11.893 2.276 15.19 2.37 3.3.096 7.99-.805 10.87-.615 2.09.098 4.143.483 6.16 1.03 1.306-6.49 1.4-11.27 4.492-12.38 1.814.293 3.213 2.818 4.25 4.167 2.112-.086 4.12.46 6.115 1.066 3.61-.522 6.642-2.593 9.833-4.203-3.234 2.69-3.673 7.075-3.303 11.127.138 2.103-.444 4.386-1.164 6.54-1.348 3.507-3.95 7.204-6.97 7.014-1.14-.036-1.805-.695-2.653-1.4-.164 1.427-.81 2.7-1.434 3.96-1.44 2.797-5.203 4.03-8.687 7.016-3.484 2.985 1.114 13.65 2.23 15.594 1.114 1.94 4.226 2.652 3.02 4.406-.37.58-.936.785-1.54 1.01l-.82.11zm-40.097-8.85l.553.14c.694-.27 2.09.15 2.83.353-1.363-1.31-3.417-3.24-4.897-4.46-.485-1.47-.278-2.96-.174-4.46l.02-.123c-.582 1.205-1.322 2.376-1.72 3.645-.465 1.71 2.07 3.557 3.052 4.615l.336.3z\" fill-rule=\"evenodd\"/></svg>" }, "$:/core/images/advanced-search-button": { "title": "$:/core/images/advanced-search-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-advanced-search-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M74.5651535,87.9848361 C66.9581537,93.0488876 57.8237115,96 48,96 C21.490332,96 0,74.509668 0,48 C0,21.490332 21.490332,0 48,0 C74.509668,0 96,21.490332 96,48 C96,57.8541369 93.0305793,67.0147285 87.9377231,74.6357895 L122.284919,108.982985 C125.978897,112.676963 125.973757,118.65366 122.284271,122.343146 C118.593975,126.033442 112.613238,126.032921 108.92411,122.343793 L74.5651535,87.9848361 Z M48,80 C65.673112,80 80,65.673112 80,48 C80,30.326888 65.673112,16 48,16 C30.326888,16 16,30.326888 16,48 C16,65.673112 30.326888,80 48,80 Z\"></path>\n <circle cx=\"48\" cy=\"48\" r=\"8\"></circle>\n <circle cx=\"28\" cy=\"48\" r=\"8\"></circle>\n <circle cx=\"68\" cy=\"48\" r=\"8\"></circle>\n </g>\n</svg>" }, "$:/core/images/auto-height": { "title": "$:/core/images/auto-height", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-auto-height tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <path d=\"M67.9867828,114.356363 L67.9579626,99.8785426 C67.9550688,98.4248183 67.1636987,97.087107 65.8909901,96.3845863 L49.9251455,87.5716209 L47.992126,95.0735397 L79.8995411,95.0735397 C84.1215894,95.0735397 85.4638131,89.3810359 81.686497,87.4948823 L49.7971476,71.5713518 L48.0101917,79.1500092 L79.992126,79.1500092 C84.2093753,79.1500092 85.5558421,73.4676733 81.7869993,71.5753162 L49.805065,55.517008 L48.0101916,63.0917009 L79.9921259,63.0917015 C84.2035118,63.0917016 85.5551434,57.4217887 81.7966702,55.5218807 L65.7625147,47.4166161 L67.9579705,50.9864368 L67.9579705,35.6148245 L77.1715737,44.8284272 C78.7336709,46.3905243 81.2663308,46.3905243 82.8284279,44.8284271 C84.390525,43.2663299 84.390525,40.7336699 82.8284278,39.1715728 L66.8284271,23.1715728 C65.2663299,21.6094757 62.73367,21.6094757 61.1715729,23.1715729 L45.1715729,39.1715729 C43.6094757,40.73367 43.6094757,43.26633 45.1715729,44.8284271 C46.73367,46.3905243 49.26633,46.3905243 50.8284271,44.8284271 L59.9579705,35.6988837 L59.9579705,50.9864368 C59.9579705,52.495201 60.806922,53.8755997 62.1534263,54.5562576 L78.1875818,62.6615223 L79.9921261,55.0917015 L48.0101917,55.0917009 C43.7929424,55.0917008 42.4464755,60.7740368 46.2153183,62.6663939 L78.1972526,78.7247021 L79.992126,71.1500092 L48.0101917,71.1500092 C43.7881433,71.1500092 42.4459197,76.842513 46.2232358,78.7286665 L78.1125852,94.6521971 L79.8995411,87.0735397 L47.992126,87.0735397 C43.8588276,87.0735397 42.4404876,92.5780219 46.0591064,94.5754586 L62.024951,103.388424 L59.9579785,99.8944677 L59.9867142,114.32986 L50.8284271,105.171573 C49.26633,103.609476 46.73367,103.609476 45.1715729,105.171573 C43.6094757,106.73367 43.6094757,109.26633 45.1715729,110.828427 L61.1715729,126.828427 C62.73367,128.390524 65.2663299,128.390524 66.8284271,126.828427 L82.8284278,110.828427 C84.390525,109.26633 84.390525,106.73367 82.8284279,105.171573 C81.2663308,103.609476 78.7336709,103.609476 77.1715737,105.171573 L67.9867828,114.356363 L67.9867828,114.356363 Z M16,20 L112,20 C114.209139,20 116,18.209139 116,16 C116,13.790861 114.209139,12 112,12 L16,12 C13.790861,12 12,13.790861 12,16 C12,18.209139 13.790861,20 16,20 L16,20 Z\"></path>\n</svg>" }, "$:/core/images/blank": { "title": "$:/core/images/blank", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-blank tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\"></svg>" }, "$:/core/images/bold": { "title": "$:/core/images/bold", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-bold tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M41.1456583,51.8095238 L41.1456583,21.8711485 L67.4985994,21.8711485 C70.0084159,21.8711485 72.4285598,22.0802967 74.7591036,22.4985994 C77.0896475,22.9169022 79.1512515,23.6638602 80.9439776,24.7394958 C82.7367036,25.8151314 84.170863,27.3090474 85.2464986,29.2212885 C86.3221342,31.1335296 86.859944,33.5835518 86.859944,36.5714286 C86.859944,41.9496067 85.2465147,45.8337882 82.0196078,48.2240896 C78.792701,50.614391 74.6694929,51.8095238 69.6498599,51.8095238 L41.1456583,51.8095238 Z M13,0 L13,128 L75.0280112,128 C80.7647346,128 86.3519803,127.28292 91.789916,125.848739 C97.2278517,124.414559 102.068139,122.203563 106.310924,119.215686 C110.553709,116.22781 113.929959,112.373506 116.439776,107.652661 C118.949592,102.931816 120.204482,97.3445701 120.204482,90.8907563 C120.204482,82.8832466 118.262391,76.0411115 114.378151,70.3641457 C110.493911,64.6871798 104.607883,60.7133634 96.719888,58.442577 C102.456611,55.6937304 106.788968,52.1680887 109.717087,47.8655462 C112.645206,43.5630037 114.109244,38.1849062 114.109244,31.7310924 C114.109244,25.7553389 113.123259,20.7357813 111.151261,16.6722689 C109.179262,12.6087565 106.400578,9.35201972 102.815126,6.90196078 C99.2296739,4.45190185 94.927196,2.68908101 89.907563,1.61344538 C84.8879301,0.537809748 79.3305627,0 73.2352941,0 L13,0 Z M41.1456583,106.128852 L41.1456583,70.9915966 L71.8011204,70.9915966 C77.896389,70.9915966 82.7964334,72.3958776 86.5014006,75.2044818 C90.2063677,78.0130859 92.0588235,82.7039821 92.0588235,89.2773109 C92.0588235,92.6237329 91.4911355,95.3725383 90.3557423,97.5238095 C89.2203491,99.6750808 87.6965548,101.378145 85.7843137,102.633053 C83.8720726,103.887961 81.661077,104.784311 79.1512605,105.322129 C76.641444,105.859947 74.0121519,106.128852 71.2633053,106.128852 L41.1456583,106.128852 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/cancel-button": { "title": "$:/core/images/cancel-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-cancel-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n\t<g fill-rule=\"evenodd\">\n\t <path d=\"M64,76.3137085 L47.0294734,93.2842351 C43.9038742,96.4098343 38.8399231,96.4084656 35.7157288,93.2842712 C32.5978915,90.166434 32.5915506,85.0947409 35.7157649,81.9705266 L52.6862915,65 L35.7157649,48.0294734 C32.5901657,44.9038742 32.5915344,39.8399231 35.7157288,36.7157288 C38.833566,33.5978915 43.9052591,33.5915506 47.0294734,36.7157649 L64,53.6862915 L80.9705266,36.7157649 C84.0961258,33.5901657 89.1600769,33.5915344 92.2842712,36.7157288 C95.4021085,39.833566 95.4084494,44.9052591 92.2842351,48.0294734 L75.3137085,65 L92.2842351,81.9705266 C95.4098343,85.0961258 95.4084656,90.1600769 92.2842712,93.2842712 C89.166434,96.4021085 84.0947409,96.4084494 80.9705266,93.2842351 L64,76.3137085 Z M64,129 C99.346224,129 128,100.346224 128,65 C128,29.653776 99.346224,1 64,1 C28.653776,1 1.13686838e-13,29.653776 1.13686838e-13,65 C1.13686838e-13,100.346224 28.653776,129 64,129 Z M64,113 C90.509668,113 112,91.509668 112,65 C112,38.490332 90.509668,17 64,17 C37.490332,17 16,38.490332 16,65 C16,91.509668 37.490332,113 64,113 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/chevron-down": { "title": "$:/core/images/chevron-down", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-chevron-down tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n\t<g fill-rule=\"evenodd\" transform=\"translate(64.000000, 40.500000) rotate(-270.000000) translate(-64.000000, -40.500000) translate(-22.500000, -26.500000)\">\n <path d=\"M112.743107,112.12741 C111.310627,113.561013 109.331747,114.449239 107.145951,114.449239 L27.9777917,114.449239 C23.6126002,114.449239 20.0618714,110.904826 20.0618714,106.532572 C20.0618714,102.169214 23.6059497,98.6159054 27.9777917,98.6159054 L99.2285381,98.6159054 L99.2285381,27.365159 C99.2285381,22.9999675 102.77295,19.4492387 107.145205,19.4492387 C111.508562,19.4492387 115.061871,22.993317 115.061871,27.365159 L115.061871,106.533318 C115.061871,108.71579 114.175869,110.694669 112.743378,112.127981 Z\" transform=\"translate(67.561871, 66.949239) rotate(-45.000000) translate(-67.561871, -66.949239) \"></path>\n <path d=\"M151.35638,112.12741 C149.923899,113.561013 147.94502,114.449239 145.759224,114.449239 L66.5910645,114.449239 C62.225873,114.449239 58.6751442,110.904826 58.6751442,106.532572 C58.6751442,102.169214 62.2192225,98.6159054 66.5910645,98.6159054 L137.841811,98.6159054 L137.841811,27.365159 C137.841811,22.9999675 141.386223,19.4492387 145.758478,19.4492387 C150.121835,19.4492387 153.675144,22.993317 153.675144,27.365159 L153.675144,106.533318 C153.675144,108.71579 152.789142,110.694669 151.356651,112.127981 Z\" transform=\"translate(106.175144, 66.949239) rotate(-45.000000) translate(-106.175144, -66.949239) \"></path>\n\t</g>\n</svg>" }, "$:/core/images/chevron-left": { "title": "$:/core/images/chevron-left", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-chevron-left tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\" version=\"1.1\">\n <g fill-rule=\"evenodd\" transform=\"translate(92.500000, 64.000000) rotate(-180.000000) translate(-92.500000, -64.000000) translate(6.000000, -3.000000)\">\n <path d=\"M112.743107,112.12741 C111.310627,113.561013 109.331747,114.449239 107.145951,114.449239 L27.9777917,114.449239 C23.6126002,114.449239 20.0618714,110.904826 20.0618714,106.532572 C20.0618714,102.169214 23.6059497,98.6159054 27.9777917,98.6159054 L99.2285381,98.6159054 L99.2285381,27.365159 C99.2285381,22.9999675 102.77295,19.4492387 107.145205,19.4492387 C111.508562,19.4492387 115.061871,22.993317 115.061871,27.365159 L115.061871,106.533318 C115.061871,108.71579 114.175869,110.694669 112.743378,112.127981 Z\" transform=\"translate(67.561871, 66.949239) rotate(-45.000000) translate(-67.561871, -66.949239) \"></path>\n <path d=\"M151.35638,112.12741 C149.923899,113.561013 147.94502,114.449239 145.759224,114.449239 L66.5910645,114.449239 C62.225873,114.449239 58.6751442,110.904826 58.6751442,106.532572 C58.6751442,102.169214 62.2192225,98.6159054 66.5910645,98.6159054 L137.841811,98.6159054 L137.841811,27.365159 C137.841811,22.9999675 141.386223,19.4492387 145.758478,19.4492387 C150.121835,19.4492387 153.675144,22.993317 153.675144,27.365159 L153.675144,106.533318 C153.675144,108.71579 152.789142,110.694669 151.356651,112.127981 Z\" transform=\"translate(106.175144, 66.949239) rotate(-45.000000) translate(-106.175144, -66.949239) \"></path>\n </g>\n</svg>" }, "$:/core/images/chevron-right": { "title": "$:/core/images/chevron-right", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-chevron-right tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\" transform=\"translate(-48.000000, -3.000000)\">\n <path d=\"M112.743107,112.12741 C111.310627,113.561013 109.331747,114.449239 107.145951,114.449239 L27.9777917,114.449239 C23.6126002,114.449239 20.0618714,110.904826 20.0618714,106.532572 C20.0618714,102.169214 23.6059497,98.6159054 27.9777917,98.6159054 L99.2285381,98.6159054 L99.2285381,27.365159 C99.2285381,22.9999675 102.77295,19.4492387 107.145205,19.4492387 C111.508562,19.4492387 115.061871,22.993317 115.061871,27.365159 L115.061871,106.533318 C115.061871,108.71579 114.175869,110.694669 112.743378,112.127981 Z\" transform=\"translate(67.561871, 66.949239) rotate(-45.000000) translate(-67.561871, -66.949239) \"></path>\n <path d=\"M151.35638,112.12741 C149.923899,113.561013 147.94502,114.449239 145.759224,114.449239 L66.5910645,114.449239 C62.225873,114.449239 58.6751442,110.904826 58.6751442,106.532572 C58.6751442,102.169214 62.2192225,98.6159054 66.5910645,98.6159054 L137.841811,98.6159054 L137.841811,27.365159 C137.841811,22.9999675 141.386223,19.4492387 145.758478,19.4492387 C150.121835,19.4492387 153.675144,22.993317 153.675144,27.365159 L153.675144,106.533318 C153.675144,108.71579 152.789142,110.694669 151.356651,112.127981 Z\" transform=\"translate(106.175144, 66.949239) rotate(-45.000000) translate(-106.175144, -66.949239) \"></path>\n </g>\n</svg>" }, "$:/core/images/chevron-up": { "title": "$:/core/images/chevron-up", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-chevron-up tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n\t<g fill-rule=\"evenodd\" transform=\"translate(64.000000, 89.500000) rotate(-90.000000) translate(-64.000000, -89.500000) translate(-22.500000, 22.500000)\">\n <path d=\"M112.743107,112.12741 C111.310627,113.561013 109.331747,114.449239 107.145951,114.449239 L27.9777917,114.449239 C23.6126002,114.449239 20.0618714,110.904826 20.0618714,106.532572 C20.0618714,102.169214 23.6059497,98.6159054 27.9777917,98.6159054 L99.2285381,98.6159054 L99.2285381,27.365159 C99.2285381,22.9999675 102.77295,19.4492387 107.145205,19.4492387 C111.508562,19.4492387 115.061871,22.993317 115.061871,27.365159 L115.061871,106.533318 C115.061871,108.71579 114.175869,110.694669 112.743378,112.127981 Z\" transform=\"translate(67.561871, 66.949239) rotate(-45.000000) translate(-67.561871, -66.949239) \"></path>\n <path d=\"M151.35638,112.12741 C149.923899,113.561013 147.94502,114.449239 145.759224,114.449239 L66.5910645,114.449239 C62.225873,114.449239 58.6751442,110.904826 58.6751442,106.532572 C58.6751442,102.169214 62.2192225,98.6159054 66.5910645,98.6159054 L137.841811,98.6159054 L137.841811,27.365159 C137.841811,22.9999675 141.386223,19.4492387 145.758478,19.4492387 C150.121835,19.4492387 153.675144,22.993317 153.675144,27.365159 L153.675144,106.533318 C153.675144,108.71579 152.789142,110.694669 151.356651,112.127981 Z\" transform=\"translate(106.175144, 66.949239) rotate(-45.000000) translate(-106.175144, -66.949239) \"></path>\n\t</g>\n</svg>" }, "$:/core/images/clone-button": { "title": "$:/core/images/clone-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-clone-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M32.2650915,96 L32.2650915,120.002359 C32.2650915,124.419334 35.8432884,128 40.2627323,128 L120.002359,128 C124.419334,128 128,124.421803 128,120.002359 L128,40.2627323 C128,35.8457573 124.421803,32.2650915 120.002359,32.2650915 L96,32.2650915 L96,48 L108.858899,48 C110.519357,48 111.853018,49.3405131 111.853018,50.9941198 L111.853018,108.858899 C111.853018,110.519357 110.512505,111.853018 108.858899,111.853018 L50.9941198,111.853018 C49.333661,111.853018 48,110.512505 48,108.858899 L48,96 L32.2650915,96 Z\"></path>\n <path d=\"M40,56 L32.0070969,56 C27.5881712,56 24,52.418278 24,48 C24,43.5907123 27.5848994,40 32.0070969,40 L40,40 L40,32.0070969 C40,27.5881712 43.581722,24 48,24 C52.4092877,24 56,27.5848994 56,32.0070969 L56,40 L63.9929031,40 C68.4118288,40 72,43.581722 72,48 C72,52.4092877 68.4151006,56 63.9929031,56 L56,56 L56,63.9929031 C56,68.4118288 52.418278,72 48,72 C43.5907123,72 40,68.4151006 40,63.9929031 L40,56 Z M7.9992458,0 C3.58138434,0 0,3.5881049 0,7.9992458 L0,88.0007542 C0,92.4186157 3.5881049,96 7.9992458,96 L88.0007542,96 C92.4186157,96 96,92.4118951 96,88.0007542 L96,7.9992458 C96,3.58138434 92.4118951,0 88.0007542,0 L7.9992458,0 Z M19.0010118,16 C17.3435988,16 16,17.336731 16,19.0010118 L16,76.9989882 C16,78.6564012 17.336731,80 19.0010118,80 L76.9989882,80 C78.6564012,80 80,78.663269 80,76.9989882 L80,19.0010118 C80,17.3435988 78.663269,16 76.9989882,16 L19.0010118,16 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/close-all-button": { "title": "$:/core/images/close-all-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-close-all-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\" transform=\"translate(-23.000000, -23.000000)\">\n <path d=\"M43,131 L22.9976794,131 C18.5827987,131 15,127.418278 15,123 C15,118.590712 18.5806831,115 22.9976794,115 L43,115 L43,94.9976794 C43,90.5827987 46.581722,87 51,87 C55.4092877,87 59,90.5806831 59,94.9976794 L59,115 L79.0023206,115 C83.4172013,115 87,118.581722 87,123 C87,127.409288 83.4193169,131 79.0023206,131 L59,131 L59,151.002321 C59,155.417201 55.418278,159 51,159 C46.5907123,159 43,155.419317 43,151.002321 L43,131 Z\" transform=\"translate(51.000000, 123.000000) rotate(-45.000000) translate(-51.000000, -123.000000) \"></path>\n <path d=\"M43,59 L22.9976794,59 C18.5827987,59 15,55.418278 15,51 C15,46.5907123 18.5806831,43 22.9976794,43 L43,43 L43,22.9976794 C43,18.5827987 46.581722,15 51,15 C55.4092877,15 59,18.5806831 59,22.9976794 L59,43 L79.0023206,43 C83.4172013,43 87,46.581722 87,51 C87,55.4092877 83.4193169,59 79.0023206,59 L59,59 L59,79.0023206 C59,83.4172013 55.418278,87 51,87 C46.5907123,87 43,83.4193169 43,79.0023206 L43,59 Z\" transform=\"translate(51.000000, 51.000000) rotate(-45.000000) translate(-51.000000, -51.000000) \"></path>\n <path d=\"M115,59 L94.9976794,59 C90.5827987,59 87,55.418278 87,51 C87,46.5907123 90.5806831,43 94.9976794,43 L115,43 L115,22.9976794 C115,18.5827987 118.581722,15 123,15 C127.409288,15 131,18.5806831 131,22.9976794 L131,43 L151.002321,43 C155.417201,43 159,46.581722 159,51 C159,55.4092877 155.419317,59 151.002321,59 L131,59 L131,79.0023206 C131,83.4172013 127.418278,87 123,87 C118.590712,87 115,83.4193169 115,79.0023206 L115,59 Z\" transform=\"translate(123.000000, 51.000000) rotate(-45.000000) translate(-123.000000, -51.000000) \"></path>\n <path d=\"M115,131 L94.9976794,131 C90.5827987,131 87,127.418278 87,123 C87,118.590712 90.5806831,115 94.9976794,115 L115,115 L115,94.9976794 C115,90.5827987 118.581722,87 123,87 C127.409288,87 131,90.5806831 131,94.9976794 L131,115 L151.002321,115 C155.417201,115 159,118.581722 159,123 C159,127.409288 155.419317,131 151.002321,131 L131,131 L131,151.002321 C131,155.417201 127.418278,159 123,159 C118.590712,159 115,155.419317 115,151.002321 L115,131 Z\" transform=\"translate(123.000000, 123.000000) rotate(-45.000000) translate(-123.000000, -123.000000) \"></path>\n </g>\n</svg>" }, "$:/core/images/close-button": { "title": "$:/core/images/close-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-close-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <g fill-rule=\"evenodd\">\n <path d=\"M65.0864256,75.4091629 L14.9727349,125.522854 C11.8515951,128.643993 6.78104858,128.64922 3.65685425,125.525026 C0.539017023,122.407189 0.5336324,117.334539 3.65902635,114.209145 L53.7727171,64.0954544 L3.65902635,13.9817637 C0.537886594,10.8606239 0.532659916,5.79007744 3.65685425,2.6658831 C6.77469148,-0.451954124 11.8473409,-0.457338747 14.9727349,2.66805521 L65.0864256,52.7817459 L115.200116,2.66805521 C118.321256,-0.453084553 123.391803,-0.458311231 126.515997,2.6658831 C129.633834,5.78372033 129.639219,10.8563698 126.513825,13.9817637 L76.4001341,64.0954544 L126.513825,114.209145 C129.634965,117.330285 129.640191,122.400831 126.515997,125.525026 C123.39816,128.642863 118.32551,128.648248 115.200116,125.522854 L65.0864256,75.4091629 L65.0864256,75.4091629 Z\"></path>\n </g>\n</svg>\n" }, "$:/core/images/close-others-button": { "title": "$:/core/images/close-others-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-close-others-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M64,128 C99.346224,128 128,99.346224 128,64 C128,28.653776 99.346224,0 64,0 C28.653776,0 0,28.653776 0,64 C0,99.346224 28.653776,128 64,128 Z M64,112 C90.509668,112 112,90.509668 112,64 C112,37.490332 90.509668,16 64,16 C37.490332,16 16,37.490332 16,64 C16,90.509668 37.490332,112 64,112 Z M64,96 C81.673112,96 96,81.673112 96,64 C96,46.326888 81.673112,32 64,32 C46.326888,32 32,46.326888 32,64 C32,81.673112 46.326888,96 64,96 Z M64,80 C72.836556,80 80,72.836556 80,64 C80,55.163444 72.836556,48 64,48 C55.163444,48 48,55.163444 48,64 C48,72.836556 55.163444,80 64,80 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/copy-clipboard": { "title": "$:/core/images/copy-clipboard", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-copy-clipboard tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n\t<g fill-rule=\"evenodd\">\n\t\t<rect x=\"40\" y=\"40\" width=\"33\" height=\"8\" rx=\"4\"></rect>\n\t\t<rect x=\"40\" y=\"82\" width=\"17\" height=\"8\" rx=\"4\"></rect>\n\t\t<rect x=\"40\" y=\"54\" width=\"17\" height=\"8\" rx=\"4\"></rect>\n\t\t<rect x=\"40\" y=\"96\" width=\"33\" height=\"8\" rx=\"4\"></rect>\n\t\t<rect x=\"40\" y=\"68\" width=\"12\" height=\"8\" rx=\"4\"></rect>\n\t\t<path d=\"M40,16 L23.9992458,16 C19.5813843,16 16,19.5907123 16,24 C16,24.0016363 16.0000005,24.0032725 16.0000015,24.0049086 C16.0000005,24.0065441 16,24.0081803 16,24.0098166 L16,119.990183 C16,119.99182 16.0000005,119.993456 16.0000015,119.995092 C16.0000005,119.996727 16,119.998364 16,120 C16,124.409288 19.5813843,128 23.9992458,128 L104.000754,128 C106.205061,128 108.203844,127.105595 109.652065,125.659342 C111.102424,124.21251 112,122.214511 112,120.007595 L112,103.992405 C112,99.5776607 108.418278,96 104,96 C99.5907123,96 96,99.5783218 96,103.992405 L96,112 L32,112 L32,32 L96,32 L96,40.0075946 C96,44.4223393 99.581722,48 104,48 C108.409288,48 112,44.4216782 112,40.0075946 L112,23.9924054 C112,21.7851587 111.104671,19.7871591 109.657101,18.3409203 C108.203844,16.8944047 106.205061,16 104.000754,16 L88,16 C88,11.5907123 84.4151006,8 79.9929031,8 L48.0070969,8 C43.5881712,8 40,11.581722 40,16 Z M44,14.9958262 C44,12.7889923 45.7964248,11 48.0000255,11 L79.9999745,11 C82.2091276,11 84,12.7965212 84,14.9958262 L84,19.0041738 C84,21.2110077 82.2035752,23 79.9999745,23 L48.0000255,23 C45.7908724,23 44,21.2034788 44,19.0041738 L44,14.9958262 Z\"></path>\n\t\t<rect x=\"62\" y=\"64\" width=\"66\" height=\"16\" rx=\"8\"></rect>\n\t\t<path d=\"M60.6568542,85.6568542 L76.6568542,69.6568543 L65.3431458,69.6568542 L81.3431458,85.6568542 C84.4673401,88.7810486 89.5326599,88.7810486 92.6568542,85.6568542 C95.7810486,82.5326599 95.7810486,77.4673401 92.6568542,74.3431458 L76.6568542,58.3431458 C73.5326599,55.2189514 68.4673401,55.2189514 65.3431458,58.3431457 L49.3431458,74.3431457 C46.2189514,77.4673401 46.2189514,82.5326599 49.3431457,85.6568542 C52.4673401,88.7810486 57.5326599,88.7810486 60.6568542,85.6568542 L60.6568542,85.6568542 Z\" transform=\"translate(71.000000, 72.000000) rotate(-90.000000) translate(-71.000000, -72.000000) \"></path>\n\t</g>\n</svg>" }, "$:/core/images/delete-button": { "title": "$:/core/images/delete-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-delete-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <g fill-rule=\"evenodd\" transform=\"translate(12.000000, 0.000000)\">\n <rect x=\"0\" y=\"11\" width=\"105\" height=\"16\" rx=\"8\"></rect>\n <rect x=\"28\" y=\"0\" width=\"48\" height=\"16\" rx=\"8\"></rect>\n <rect x=\"8\" y=\"16\" width=\"16\" height=\"112\" rx=\"8\"></rect>\n <rect x=\"8\" y=\"112\" width=\"88\" height=\"16\" rx=\"8\"></rect>\n <rect x=\"80\" y=\"16\" width=\"16\" height=\"112\" rx=\"8\"></rect>\n <rect x=\"56\" y=\"16\" width=\"16\" height=\"112\" rx=\"8\"></rect>\n <rect x=\"32\" y=\"16\" width=\"16\" height=\"112\" rx=\"8\"></rect>\n </g>\n</svg>" }, "$:/core/images/done-button": { "title": "$:/core/images/done-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-done-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <g fill-rule=\"evenodd\">\n <path d=\"M3.52445141,76.8322939 C2.07397484,75.3828178 1.17514421,73.3795385 1.17514421,71.1666288 L1.17514421,23.1836596 C1.17514421,18.7531992 4.75686621,15.1751442 9.17514421,15.1751442 C13.5844319,15.1751442 17.1751442,18.7606787 17.1751442,23.1836596 L17.1751442,63.1751442 L119.173716,63.1751442 C123.590457,63.1751442 127.175144,66.7568662 127.175144,71.1751442 C127.175144,75.5844319 123.592783,79.1751442 119.173716,79.1751442 L9.17657227,79.1751442 C6.96796403,79.1751442 4.9674142,78.279521 3.51911285,76.8315312 Z\" id=\"Rectangle-285\" transform=\"translate(64.175144, 47.175144) rotate(-45.000000) translate(-64.175144, -47.175144) \"></path>\n </g>\n</svg>" }, "$:/core/images/down-arrow": { "title": "$:/core/images/down-arrow", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-down-arrow tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <path d=\"M109.35638,81.3533152 C107.923899,82.7869182 105.94502,83.6751442 103.759224,83.6751442 L24.5910645,83.6751442 C20.225873,83.6751442 16.6751442,80.1307318 16.6751442,75.7584775 C16.6751442,71.3951199 20.2192225,67.8418109 24.5910645,67.8418109 L95.8418109,67.8418109 L95.8418109,-3.40893546 C95.8418109,-7.77412698 99.3862233,-11.3248558 103.758478,-11.3248558 C108.121835,-11.3248558 111.675144,-7.78077754 111.675144,-3.40893546 L111.675144,75.7592239 C111.675144,77.9416955 110.789142,79.9205745 109.356651,81.3538862 Z\" transform=\"translate(64.175144, 36.175144) rotate(45.000000) translate(-64.175144, -36.175144) \"></path>\n</svg>" }, "$:/core/images/download-button": { "title": "$:/core/images/download-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-download-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\"><g fill-rule=\"evenodd\"><path class=\"tc-image-download-button-ring\" d=\"M64,128 C99.346224,128 128,99.346224 128,64 C128,28.653776 99.346224,0 64,0 C28.653776,0 0,28.653776 0,64 C0,99.346224 28.653776,128 64,128 Z M64,112 C90.509668,112 112,90.509668 112,64 C112,37.490332 90.509668,16 64,16 C37.490332,16 16,37.490332 16,64 C16,90.509668 37.490332,112 64,112 Z\"/><path d=\"M34.3496823,66.4308767 L61.2415823,93.634668 C63.0411536,95.4551107 65.9588502,95.4551107 67.7584215,93.634668 L94.6503215,66.4308767 C96.4498928,64.610434 96.4498928,61.6588981 94.6503215,59.8384554 C93.7861334,58.9642445 92.6140473,58.4731195 91.3919019,58.4731195 L82.9324098,58.4731195 C80.3874318,58.4731195 78.3243078,56.3860674 78.3243078,53.8115729 L78.3243078,38.6615466 C78.3243078,36.0870521 76.2611837,34 73.7162058,34 L55.283798,34 C52.7388201,34 50.675696,36.0870521 50.675696,38.6615466 L50.675696,38.6615466 L50.675696,53.8115729 C50.675696,56.3860674 48.612572,58.4731195 46.0675941,58.4731195 L37.608102,58.4731195 C35.063124,58.4731195 33,60.5601716 33,63.134666 C33,64.3709859 33.4854943,65.5566658 34.3496823,66.4308767 L34.3496823,66.4308767 Z\"/></g></svg>" }, "$:/core/images/edit-button": { "title": "$:/core/images/edit-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-edit-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <g fill-rule=\"evenodd\">\n <path d=\"M116.870058,45.3431458 L108.870058,45.3431458 L108.870058,45.3431458 L108.870058,61.3431458 L116.870058,61.3431458 L116.870058,45.3431458 Z M124.870058,45.3431458 L127.649881,45.3431458 C132.066101,45.3431458 135.656854,48.9248678 135.656854,53.3431458 C135.656854,57.7524334 132.07201,61.3431458 127.649881,61.3431458 L124.870058,61.3431458 L124.870058,45.3431458 Z M100.870058,45.3431458 L15.6638275,45.3431458 C15.5064377,45.3431458 15.3501085,45.3476943 15.1949638,45.3566664 L15.1949638,45.3566664 C15.0628002,45.3477039 14.928279,45.3431458 14.7913977,45.3431458 C6.68160973,45.3431458 -8.34314575,53.3431458 -8.34314575,53.3431458 C-8.34314575,53.3431458 6.85614548,61.3431458 14.7913977,61.3431458 C14.9266533,61.3431458 15.0596543,61.3384973 15.190398,61.3293588 C15.3470529,61.3385075 15.5049057,61.3431458 15.6638275,61.3431458 L100.870058,61.3431458 L100.870058,45.3431458 L100.870058,45.3431458 Z\" transform=\"translate(63.656854, 53.343146) rotate(-45.000000) translate(-63.656854, -53.343146) \"></path>\n <path d=\"M35.1714596,124.189544 C41.9594858,123.613403 49.068777,121.917633 58.85987,118.842282 C60.6854386,118.268877 62.4306907,117.705515 65.1957709,116.802278 C81.1962861,111.575575 87.0734839,109.994907 93.9414474,109.655721 C102.29855,109.242993 107.795169,111.785371 111.520478,118.355045 C112.610163,120.276732 115.051363,120.951203 116.97305,119.861518 C118.894737,118.771832 119.569207,116.330633 118.479522,114.408946 C113.146151,105.003414 104.734907,101.112919 93.5468356,101.66546 C85.6716631,102.054388 79.4899908,103.716944 62.7116783,109.197722 C59.9734132,110.092199 58.2519873,110.64787 56.4625698,111.20992 C37.002649,117.322218 25.6914684,118.282267 16.8654804,112.957098 C14.9739614,111.815848 12.5154166,112.424061 11.3741667,114.31558 C10.2329168,116.207099 10.84113,118.665644 12.7326489,119.806894 C19.0655164,123.627836 26.4866335,124.926678 35.1714596,124.189544 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/erase": { "title": "$:/core/images/erase", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-erase tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M60.0870401,127.996166 L123.102318,64.980888 C129.636723,58.4464827 129.629513,47.8655877 123.098967,41.3350425 L99.4657866,17.7018617 C92.927448,11.1635231 82.3486358,11.1698163 75.8199411,17.698511 L4.89768189,88.6207702 C-1.63672343,95.1551755 -1.6295126,105.736071 4.90103262,112.266616 L20.6305829,127.996166 L60.0870401,127.996166 Z M25.1375576,120.682546 L10.812569,106.357558 C7.5455063,103.090495 7.54523836,97.793808 10.8048093,94.5342371 L46.2691086,59.0699377 L81.7308914,94.5317205 L55.5800654,120.682546 L25.1375576,120.682546 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/excise": { "title": "$:/core/images/excise", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-excise tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M56,107.313709 L53.6568542,109.656854 C50.5326599,112.781049 45.4673401,112.781049 42.3431457,109.656854 C39.2189514,106.53266 39.2189514,101.46734 42.3431458,98.3431457 L58.3431458,82.3431457 C61.4673401,79.2189514 66.5326599,79.2189514 69.6568542,82.3431458 L85.6568542,98.3431458 C88.7810486,101.46734 88.7810486,106.53266 85.6568542,109.656854 C82.5326599,112.781049 77.4673401,112.781049 74.3431458,109.656854 L72,107.313708 L72,121.597798 C72,125.133636 68.418278,128 64,128 C59.581722,128 56,125.133636 56,121.597798 L56,107.313709 Z M0,40.0070969 C0,35.5848994 3.59071231,32 8,32 C12.418278,32 16,35.5881712 16,40.0070969 L16,71.9929031 C16,76.4151006 12.4092877,80 8,80 C3.581722,80 0,76.4118288 0,71.9929031 L0,40.0070969 Z M32,40.0070969 C32,35.5848994 35.5907123,32 40,32 C44.418278,32 48,35.5881712 48,40.0070969 L48,71.9929031 C48,76.4151006 44.4092877,80 40,80 C35.581722,80 32,76.4118288 32,71.9929031 L32,40.0070969 Z M80,40.0070969 C80,35.5848994 83.5907123,32 88,32 C92.418278,32 96,35.5881712 96,40.0070969 L96,71.9929031 C96,76.4151006 92.4092877,80 88,80 C83.581722,80 80,76.4118288 80,71.9929031 L80,40.0070969 Z M56,8.00709688 C56,3.58489938 59.5907123,0 64,0 C68.418278,0 72,3.58817117 72,8.00709688 L72,39.9929031 C72,44.4151006 68.4092877,48 64,48 C59.581722,48 56,44.4118288 56,39.9929031 L56,8.00709688 Z M112,40.0070969 C112,35.5848994 115.590712,32 120,32 C124.418278,32 128,35.5881712 128,40.0070969 L128,71.9929031 C128,76.4151006 124.409288,80 120,80 C115.581722,80 112,76.4118288 112,71.9929031 L112,40.0070969 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/export-button": { "title": "$:/core/images/export-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-export-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M8.00348646,127.999999 C8.00464867,128 8.00581094,128 8.00697327,128 L119.993027,128 C122.205254,128 124.207939,127.101378 125.657096,125.651198 L125.656838,125.65759 C127.104563,124.210109 128,122.21009 128,119.999949 L128,56.0000511 C128,51.5817449 124.409288,48 120,48 C115.581722,48 112,51.5797863 112,56.0000511 L112,112 L16,112 L16,56.0000511 C16,51.5817449 12.4092877,48 8,48 C3.581722,48 7.10542736e-15,51.5797863 7.10542736e-15,56.0000511 L7.10542736e-15,119.999949 C7.10542736e-15,124.418255 3.59071231,128 8,128 C8.00116233,128 8.0023246,128 8.00348681,127.999999 Z M56.6235633,27.3113724 L47.6580188,36.2769169 C44.5333664,39.4015692 39.4634864,39.4061295 36.339292,36.2819351 C33.2214548,33.1640979 33.2173444,28.0901742 36.3443103,24.9632084 L58.9616908,2.34582788 C60.5248533,0.782665335 62.5748436,0.000361191261 64.624516,2.38225238e-14 L64.6193616,0.00151809229 C66.6695374,0.000796251595 68.7211167,0.781508799 70.2854358,2.34582788 L92.9028163,24.9632084 C96.0274686,28.0878607 96.0320289,33.1577408 92.9078345,36.2819351 C89.7899973,39.3997724 84.7160736,39.4038827 81.5891078,36.2769169 L72.6235633,27.3113724 L72.6235633,88.5669606 C72.6235633,92.9781015 69.0418413,96.5662064 64.6235633,96.5662064 C60.2142756,96.5662064 56.6235633,92.984822 56.6235633,88.5669606 L56.6235633,27.3113724 L56.6235633,27.3113724 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/file": { "title": "$:/core/images/file", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-file tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"nonzero\">\n <path d=\"M111.96811,30.5 L112,30.5 L112,119.999079 C112,124.417866 108.419113,128 104.000754,128 L23.9992458,128 C19.5813843,128 16,124.417687 16,119.999079 L16,8.00092105 C16,3.58213437 19.5808867,0 23.9992458,0 L81,0 L81,0.0201838424 C83.1589869,-0.071534047 85.3482153,0.707077645 86.9982489,2.35711116 L109.625176,24.9840387 C111.151676,26.510538 111.932942,28.4998414 111.96811,30.5 L111.96811,30.5 Z M81,8 L24,8 L24,120 L104,120 L104,30.5 L89.0003461,30.5 C84.5818769,30.5 81,26.9216269 81,22.4996539 L81,8 Z\"></path>\n <rect x=\"32\" y=\"36\" width=\"64\" height=\"8\" rx=\"4\"></rect>\n <rect x=\"32\" y=\"52\" width=\"64\" height=\"8\" rx=\"4\"></rect>\n <rect x=\"32\" y=\"68\" width=\"64\" height=\"8\" rx=\"4\"></rect>\n <rect x=\"32\" y=\"84\" width=\"64\" height=\"8\" rx=\"4\"></rect>\n <rect x=\"32\" y=\"100\" width=\"64\" height=\"8\" rx=\"4\"></rect>\n <rect x=\"32\" y=\"20\" width=\"40\" height=\"8\" rx=\"4\"></rect>\n </g>\n</svg>" }, "$:/core/images/fixed-height": { "title": "$:/core/images/fixed-height", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-fixed-height tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M60,35.6568542 L50.8284271,44.8284271 C49.26633,46.3905243 46.73367,46.3905243 45.1715729,44.8284271 C43.6094757,43.26633 43.6094757,40.73367 45.1715729,39.1715729 L61.1715729,23.1715729 C62.73367,21.6094757 65.2663299,21.6094757 66.8284271,23.1715728 L82.8284278,39.1715728 C84.390525,40.7336699 84.390525,43.2663299 82.8284279,44.8284271 C81.2663308,46.3905243 78.7336709,46.3905243 77.1715737,44.8284272 L68,35.6568539 L68,93.3431461 L77.1715737,84.1715728 C78.7336709,82.6094757 81.2663308,82.6094757 82.8284279,84.1715729 C84.390525,85.7336701 84.390525,88.2663301 82.8284278,89.8284272 L66.8284271,105.828427 C65.2663299,107.390524 62.73367,107.390524 61.1715729,105.828427 L45.1715729,89.8284271 C43.6094757,88.26633 43.6094757,85.73367 45.1715729,84.1715729 C46.73367,82.6094757 49.26633,82.6094757 50.8284271,84.1715729 L60,93.3431458 L60,35.6568542 L60,35.6568542 Z M16,116 L112,116 C114.209139,116 116,114.209139 116,112 C116,109.790861 114.209139,108 112,108 L16,108 C13.790861,108 12,109.790861 12,112 C12,114.209139 13.790861,116 16,116 L16,116 Z M16,20 L112,20 C114.209139,20 116,18.209139 116,16 C116,13.790861 114.209139,12 112,12 L16,12 C13.790861,12 12,13.790861 12,16 C12,18.209139 13.790861,20 16,20 L16,20 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/fold-all-button": { "title": "$:/core/images/fold-all-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-fold-all tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <rect x=\"0\" y=\"0\" width=\"128\" height=\"16\" rx=\"8\"></rect>\n <rect x=\"0\" y=\"64\" width=\"128\" height=\"16\" rx=\"8\"></rect>\n <path d=\"M64.0292774,58.6235628 C61.9791013,58.6242848 59.9275217,57.8435723 58.3632024,56.279253 L35.7458219,33.6618725 C32.6211696,30.5372202 32.6166093,25.4673401 35.7408036,22.3431458 C38.8586409,19.2253085 43.9325646,19.2211982 47.0595304,22.348164 L64.0250749,39.3137085 L80.9906194,22.348164 C84.1152717,19.2235117 89.1851518,19.2189514 92.3093461,22.3431458 C95.4271834,25.460983 95.4312937,30.5349067 92.3043279,33.6618725 L69.6869474,56.279253 C68.1237851,57.8424153 66.0737951,58.6247195 64.0241231,58.6250809 Z\" transform=\"translate(64.024316, 39.313708) scale(1, -1) translate(-64.024316, -39.313708) \"></path>\n <path d=\"M64.0292774,123.621227 C61.9791013,123.621949 59.9275217,122.841236 58.3632024,121.276917 L35.7458219,98.6595365 C32.6211696,95.5348842 32.6166093,90.4650041 35.7408036,87.3408098 C38.8586409,84.2229725 43.9325646,84.2188622 47.0595304,87.345828 L64.0250749,104.311373 L80.9906194,87.345828 C84.1152717,84.2211757 89.1851518,84.2166154 92.3093461,87.3408098 C95.4271834,90.458647 95.4312937,95.5325707 92.3043279,98.6595365 L69.6869474,121.276917 C68.1237851,122.840079 66.0737951,123.622383 64.0241231,123.622745 Z\" transform=\"translate(64.024316, 104.311372) scale(1, -1) translate(-64.024316, -104.311372) \"></path>\n </g>\n</svg>" }, "$:/core/images/fold-button": { "title": "$:/core/images/fold-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-fold tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <rect x=\"0\" y=\"0\" width=\"128\" height=\"16\" rx=\"8\"></rect>\n <path d=\"M64.0292774,63.6235628 C61.9791013,63.6242848 59.9275217,62.8435723 58.3632024,61.279253 L35.7458219,38.6618725 C32.6211696,35.5372202 32.6166093,30.4673401 35.7408036,27.3431458 C38.8586409,24.2253085 43.9325646,24.2211982 47.0595304,27.348164 L64.0250749,44.3137085 L80.9906194,27.348164 C84.1152717,24.2235117 89.1851518,24.2189514 92.3093461,27.3431458 C95.4271834,30.460983 95.4312937,35.5349067 92.3043279,38.6618725 L69.6869474,61.279253 C68.1237851,62.8424153 66.0737951,63.6247195 64.0241231,63.6250809 Z\" transform=\"translate(64.024316, 44.313708) scale(1, -1) translate(-64.024316, -44.313708) \"></path>\n <path d=\"M64.0049614,105.998482 C61.9547853,105.999204 59.9032057,105.218491 58.3388864,103.654172 L35.7215059,81.0367916 C32.5968535,77.9121393 32.5922933,72.8422592 35.7164876,69.7180649 C38.8343248,66.6002276 43.9082485,66.5961173 47.0352144,69.7230831 L64.0007589,86.6886276 L80.9663034,69.7230831 C84.0909557,66.5984308 89.1608358,66.5938705 92.2850301,69.7180649 C95.4028673,72.8359021 95.4069777,77.9098258 92.2800119,81.0367916 L69.6626314,103.654172 C68.099469,105.217334 66.0494791,105.999639 63.999807,106 Z\" transform=\"translate(64.000000, 86.688628) scale(1, -1) translate(-64.000000, -86.688628) \"></path>\n </g>\n</svg>" }, "$:/core/images/fold-others-button": { "title": "$:/core/images/fold-others-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-fold-others tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <rect x=\"0\" y=\"56.0314331\" width=\"128\" height=\"16\" rx=\"8\"></rect>\n <path d=\"M101.657101,104.948818 C100.207918,103.498614 98.2051847,102.599976 95.9929031,102.599976 L72,102.599976 L72,78.6070725 C72,76.3964271 71.1036108,74.3936927 69.6545293,72.9441002 L69.6571005,72.9488183 C68.2079177,71.4986143 66.2051847,70.5999756 63.9929031,70.5999756 L32.0070969,70.5999756 C27.5881712,70.5999756 24,74.1816976 24,78.5999756 C24,83.0092633 27.5848994,86.5999756 32.0070969,86.5999756 L56,86.5999756 L56,110.592879 C56,112.803524 56.8963895,114.806259 58.3454713,116.255852 L58.3429,116.251133 C59.7920828,117.701337 61.7948156,118.599976 64.0070969,118.599976 L88,118.599976 L88,142.592879 C88,147.011804 91.581722,150.599976 96,150.599976 C100.409288,150.599976 104,147.015076 104,142.592879 L104,110.607072 C104,108.396427 103.103611,106.393693 101.654529,104.9441 Z\" transform=\"translate(64.000000, 110.599976) rotate(-45.000000) translate(-64.000000, -110.599976) \"></path>\n <path d=\"M101.725643,11.7488671 C100.27646,10.2986632 98.2737272,9.40002441 96.0614456,9.40002441 L72.0685425,9.40002441 L72.0685425,-14.5928787 C72.0685425,-16.8035241 71.1721533,-18.8062584 69.7230718,-20.255851 L69.725643,-20.2511329 C68.2764602,-21.7013368 66.2737272,-22.5999756 64.0614456,-22.5999756 L32.0756394,-22.5999756 C27.6567137,-22.5999756 24.0685425,-19.0182536 24.0685425,-14.5999756 C24.0685425,-10.1906879 27.6534419,-6.59997559 32.0756394,-6.59997559 L56.0685425,-6.59997559 L56.0685425,17.3929275 C56.0685425,19.6035732 56.964932,21.6063078 58.4140138,23.0559004 L58.4114425,23.0511823 C59.8606253,24.5013859 61.8633581,25.4000244 64.0756394,25.4000244 L88.0685425,25.4000244 L88.0685425,49.3929275 C88.0685425,53.8118532 91.6502645,57.4000244 96.0685425,57.4000244 C100.47783,57.4000244 104.068542,53.815125 104.068542,49.3929275 L104.068542,17.4071213 C104.068542,15.1964759 103.172153,13.1937416 101.723072,11.744149 Z\" transform=\"translate(64.068542, 17.400024) scale(1, -1) rotate(-45.000000) translate(-64.068542, -17.400024) \"></path>\n </g>\n</svg>" }, "$:/core/images/folder": { "title": "$:/core/images/folder", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-folder tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M55.6943257,128.000004 L7.99859666,128.000004 C3.5810937,128.000004 0,124.413822 0,119.996384 L0,48.0036243 C0,43.5833471 3.58387508,40.0000044 7.99859666,40.0000044 L16,40.0000044 L16,31.9999914 C16,27.5817181 19.5783731,24 24.0003461,24 L55.9996539,24 C60.4181231,24 64,27.5800761 64,31.9999914 L64,40.0000044 L104.001403,40.0000044 C108.418906,40.0000044 112,43.5861868 112,48.0036243 L112,59.8298353 L104,59.7475921 L104,51.9994189 C104,49.7887607 102.207895,48.0000044 99.9972215,48.0000044 L56,48.0000044 L56,36.0000255 C56,33.7898932 54.2072328,32 51.9957423,32 L28.0042577,32 C25.7890275,32 24,33.7908724 24,36.0000255 L24,48.0000044 L12.0027785,48.0000044 C9.78987688,48.0000044 8,49.7906032 8,51.9994189 L8,116.00059 C8,118.211248 9.79210499,120.000004 12.0027785,120.000004 L58.7630167,120.000004 L55.6943257,128.000004 L55.6943257,128.000004 Z\"></path>\n <path d=\"M23.8728955,55.5 L119.875702,55.5 C124.293205,55.5 126.87957,59.5532655 125.650111,64.5630007 L112.305967,118.936999 C111.077582,123.942356 106.497904,128 102.083183,128 L6.08037597,128 C1.66287302,128 -0.923492342,123.946735 0.305967145,118.936999 L13.650111,64.5630007 C14.878496,59.5576436 19.4581739,55.5 23.8728955,55.5 L23.8728955,55.5 L23.8728955,55.5 Z M25.6530124,64 L113.647455,64 C115.858129,64 117.151473,66.0930612 116.538306,68.6662267 L105.417772,115.333773 C104.803671,117.910859 102.515967,120 100.303066,120 L12.3086228,120 C10.0979492,120 8.8046054,117.906939 9.41777189,115.333773 L20.5383062,68.6662267 C21.1524069,66.0891409 23.4401107,64 25.6530124,64 L25.6530124,64 L25.6530124,64 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/full-screen-button": { "title": "$:/core/images/full-screen-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-full-screen-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g>\n <g>\n <path d=\"M5.29777586e-31,8 C1.59060409e-15,3.581722 3.581722,0 8,0 L40,0 C44.418278,0 48,3.581722 48,8 C48,12.418278 44.418278,16 40,16 L16,16 L16,40 C16,44.418278 12.418278,48 8,48 C3.581722,48 -3.55271368e-15,44.418278 0,40 L3.55271368e-15,8 Z\"></path>\n </g>\n <g transform=\"translate(104.000000, 104.000000) rotate(-180.000000) translate(-104.000000, -104.000000) translate(80.000000, 80.000000)\">\n <path d=\"M5.29777586e-31,8 C1.59060409e-15,3.581722 3.581722,0 8,0 L40,0 C44.418278,0 48,3.581722 48,8 C48,12.418278 44.418278,16 40,16 L16,16 L16,40 C16,44.418278 12.418278,48 8,48 C3.581722,48 -3.55271368e-15,44.418278 0,40 L3.55271368e-15,8 Z\"></path>\n </g>\n <g transform=\"translate(24.000000, 104.000000) rotate(-90.000000) translate(-24.000000, -104.000000) translate(0.000000, 80.000000)\">\n <path d=\"M5.29777586e-31,8 C1.59060409e-15,3.581722 3.581722,0 8,0 L40,0 C44.418278,0 48,3.581722 48,8 C48,12.418278 44.418278,16 40,16 L16,16 L16,40 C16,44.418278 12.418278,48 8,48 C3.581722,48 -3.55271368e-15,44.418278 0,40 L3.55271368e-15,8 Z\"></path>\n </g>\n <g transform=\"translate(104.000000, 24.000000) rotate(90.000000) translate(-104.000000, -24.000000) translate(80.000000, 0.000000)\">\n <path d=\"M5.29777586e-31,8 C1.59060409e-15,3.581722 3.581722,0 8,0 L40,0 C44.418278,0 48,3.581722 48,8 C48,12.418278 44.418278,16 40,16 L16,16 L16,40 C16,44.418278 12.418278,48 8,48 C3.581722,48 -3.55271368e-15,44.418278 0,40 L3.55271368e-15,8 Z\"></path>\n </g>\n </g>\n</svg>" }, "$:/core/images/github": { "title": "$:/core/images/github", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-github tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M63.9383506,1.60695328 C28.6017227,1.60695328 -0.055756057,30.2970814 -0.055756057,65.6906208 C-0.055756057,94.003092 18.2804728,118.019715 43.7123154,126.493393 C46.9143781,127.083482 48.0812647,125.104717 48.0812647,123.405261 C48.0812647,121.886765 48.02626,117.85449 47.9948287,112.508284 C30.1929317,116.379268 26.4368926,103.916587 26.4368926,103.916587 C23.5255693,96.5129372 19.3294921,94.5420399 19.3294921,94.5420399 C13.5186324,90.5687739 19.7695302,90.6474524 19.7695302,90.6474524 C26.1933001,91.099854 29.5721638,97.2525155 29.5721638,97.2525155 C35.2808718,107.044059 44.5531024,104.215566 48.1991321,102.575118 C48.7806109,98.4366275 50.4346826,95.612068 52.2616263,94.0109598 C38.0507543,92.3941159 23.1091047,86.8944862 23.1091047,62.3389152 C23.1091047,55.3443933 25.6039634,49.6205298 29.6978889,45.1437211 C29.0378318,43.5229433 26.8415704,37.0044266 30.3265147,28.1845627 C30.3265147,28.1845627 35.6973364,26.4615028 47.9241083,34.7542205 C53.027764,33.330139 58.5046663,32.6220321 63.9462084,32.5944947 C69.3838216,32.6220321 74.856795,33.330139 79.9683085,34.7542205 C92.1872225,26.4615028 97.5501864,28.1845627 97.5501864,28.1845627 C101.042989,37.0044266 98.8467271,43.5229433 98.190599,45.1437211 C102.292382,49.6205298 104.767596,55.3443933 104.767596,62.3389152 C104.767596,86.9574291 89.8023734,92.3744463 75.5482834,93.9598188 C77.8427675,95.9385839 79.8897303,99.8489072 79.8897303,105.828476 C79.8897303,114.392635 79.8111521,121.304544 79.8111521,123.405261 C79.8111521,125.120453 80.966252,127.114954 84.2115327,126.489459 C109.623731,117.996111 127.944244,93.9952241 127.944244,65.6906208 C127.944244,30.2970814 99.2867652,1.60695328 63.9383506,1.60695328\"></path>\n </g>\n </svg>\n" }, "$:/core/images/globe": { "title": "$:/core/images/globe", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-globe tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M72.8111354,37.1275855 C72.8111354,37.9789875 72.8111354,38.8303894 72.8111354,39.6817913 C72.8111354,41.8784743 73.7885604,46.5631866 72.8111354,48.5143758 C71.3445471,51.4420595 68.1617327,52.0543531 66.4170946,54.3812641 C65.2352215,55.9575873 61.7987417,64.9821523 62.7262858,67.3005778 C66.6959269,77.2228204 74.26087,70.4881886 80.6887657,76.594328 C81.5527211,77.415037 83.5758191,78.8666631 83.985137,79.8899578 C87.2742852,88.1128283 76.4086873,94.8989524 87.7419325,106.189751 C88.9872885,107.430443 91.555495,102.372895 91.8205061,101.575869 C92.6726866,99.0129203 98.5458765,96.1267309 100.908882,94.5234439 C102.928056,93.1534443 105.782168,91.8557166 107.236936,89.7775886 C109.507391,86.5342557 108.717505,82.2640435 110.334606,79.0328716 C112.473794,74.7585014 114.163418,69.3979002 116.332726,65.0674086 C120.230862,57.2857361 121.054075,67.1596684 121.400359,67.5059523 C121.757734,67.8633269 122.411167,67.5059523 122.916571,67.5059523 C123.011132,67.5059523 124.364019,67.6048489 124.432783,67.5059523 C125.0832,66.5705216 123.390209,49.5852316 123.114531,48.2089091 C121.710578,41.1996597 116.17083,32.4278331 111.249523,27.7092761 C104.975994,21.6942076 104.160516,11.5121686 92.9912146,12.7547535 C92.7872931,12.7774397 87.906794,22.9027026 85.2136766,26.2672064 C81.486311,30.9237934 82.7434931,22.1144904 78.6876623,22.1144904 C78.6065806,22.1144904 77.5045497,22.0107615 77.4353971,22.1144904 C76.8488637,22.9942905 75.9952305,26.0101404 75.1288269,26.5311533 C74.8635477,26.6906793 73.4071369,26.2924966 73.2826811,26.5311533 C71.0401728,30.8313939 81.5394677,28.7427264 79.075427,34.482926 C76.7225098,39.9642538 72.747373,32.4860199 72.747373,43.0434079\"></path>\n <path d=\"M44.4668556,7.01044608 C54.151517,13.1403033 45.1489715,19.2084878 47.1611905,23.2253896 C48.8157833,26.5283781 51.4021933,28.6198851 48.8753629,33.038878 C46.8123257,36.6467763 42.0052989,37.0050492 39.251679,39.7621111 C36.2115749,42.8060154 33.7884281,48.7028116 32.4624592,52.6732691 C30.8452419,57.5158356 47.0088721,59.5388126 44.5246867,63.6811917 C43.1386839,65.9923513 37.7785192,65.1466282 36.0880227,63.8791519 C34.9234453,63.0059918 32.4946425,63.3331166 31.6713597,62.0997342 C29.0575851,58.1839669 29.4107339,54.0758543 28.0457962,49.9707786 C27.1076833,47.1493864 21.732611,47.8501656 20.2022714,49.3776393 C19.6790362,49.8998948 19.8723378,51.1703278 19.8723378,51.8829111 C19.8723378,57.1682405 26.9914913,55.1986414 26.9914913,58.3421973 C26.9914913,72.9792302 30.9191897,64.8771867 38.1313873,69.6793121 C48.1678018,76.3618966 45.9763926,76.981595 53.0777543,84.0829567 C56.7511941,87.7563965 60.8192437,87.7689005 62.503478,93.3767069 C64.1046972,98.7081071 53.1759798,98.7157031 50.786754,100.825053 C49.663965,101.816317 47.9736094,104.970571 46.5680513,105.439676 C44.7757187,106.037867 43.334221,105.93607 41.6242359,107.219093 C39.1967302,109.040481 37.7241465,112.151588 37.6034934,112.030935 C35.4555278,109.88297 34.0848666,96.5511248 33.7147244,93.7726273 C33.1258872,89.3524817 28.1241923,88.2337027 26.7275443,84.7420826 C25.1572737,80.8164061 28.2518481,75.223612 25.599097,70.9819941 C19.0797019,60.557804 13.7775712,56.4811506 10.2493953,44.6896152 C9.3074899,41.5416683 13.5912267,38.1609942 15.1264825,35.8570308 C17.0029359,33.0410312 17.7876232,30.0028946 19.8723378,27.2224065 C22.146793,24.1888519 40.8551166,9.46076832 43.8574051,8.63490613 L44.4668556,7.01044608 Z\"></path>\n <path d=\"M64,126 C98.2416545,126 126,98.2416545 126,64 C126,29.7583455 98.2416545,2 64,2 C29.7583455,2 2,29.7583455 2,64 C2,98.2416545 29.7583455,126 64,126 Z M64,120 C94.927946,120 120,94.927946 120,64 C120,33.072054 94.927946,8 64,8 C33.072054,8 8,33.072054 8,64 C8,94.927946 33.072054,120 64,120 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/heading-1": { "title": "$:/core/images/heading-1", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-heading-1 tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M14,30 L27.25,30 L27.25,60.104 L61.7,60.104 L61.7,30 L74.95,30 L74.95,105.684 L61.7,105.684 L61.7,71.552 L27.25,71.552 L27.25,105.684 L14,105.684 L14,30 Z M84.3350766,43.78 C86.8790893,43.78 89.3523979,43.5680021 91.7550766,43.144 C94.1577553,42.7199979 96.3307336,42.0133383 98.2740766,41.024 C100.21742,40.0346617 101.87807,38.7626744 103.256077,37.208 C104.634084,35.6533256 105.535075,33.7453446 105.959077,31.484 L115.817077,31.484 L115.817077,105.684 L102.567077,105.684 L102.567077,53.32 L84.3350766,53.32 L84.3350766,43.78 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/heading-2": { "title": "$:/core/images/heading-2", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-heading-2 tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M6,30 L19.25,30 L19.25,60.104 L53.7,60.104 L53.7,30 L66.95,30 L66.95,105.684 L53.7,105.684 L53.7,71.552 L19.25,71.552 L19.25,105.684 L6,105.684 L6,30 Z M125.519077,105.684 L74.8510766,105.684 C74.9217436,99.5359693 76.4057288,94.1653563 79.3030766,89.572 C82.2004244,84.9786437 86.1577182,80.986017 91.1750766,77.594 C93.5777553,75.8273245 96.0863969,74.113675 98.7010766,72.453 C101.315756,70.792325 103.718399,69.0080095 105.909077,67.1 C108.099754,65.1919905 109.901736,63.1250111 111.315077,60.899 C112.728417,58.6729889 113.47041,56.1113478 113.541077,53.214 C113.541077,51.8713266 113.382078,50.4403409 113.064077,48.921 C112.746075,47.4016591 112.127748,45.9883399 111.209077,44.681 C110.290405,43.3736601 109.018418,42.2783377 107.393077,41.395 C105.767735,40.5116622 103.647756,40.07 101.033077,40.07 C98.6303979,40.07 96.6340846,40.5469952 95.0440766,41.501 C93.4540687,42.4550048 92.1820814,43.762325 91.2280766,45.423 C90.2740719,47.083675 89.5674123,49.0446554 89.1080766,51.306 C88.648741,53.5673446 88.3837436,56.0053203 88.3130766,58.62 L76.2290766,58.62 C76.2290766,54.5213128 76.7767378,50.7230175 77.8720766,47.225 C78.9674154,43.7269825 80.610399,40.7060127 82.8010766,38.162 C84.9917542,35.6179873 87.6593942,33.6216739 90.8040766,32.173 C93.948759,30.7243261 97.6057224,30 101.775077,30 C106.297766,30 110.078395,30.7419926 113.117077,32.226 C116.155758,33.7100074 118.611401,35.5826554 120.484077,37.844 C122.356753,40.1053446 123.681739,42.5609868 124.459077,45.211 C125.236414,47.8610133 125.625077,50.3873213 125.625077,52.79 C125.625077,55.7580148 125.165748,58.4433213 124.247077,60.846 C123.328405,63.2486787 122.091751,65.4569899 120.537077,67.471 C118.982402,69.4850101 117.215753,71.3399915 115.237077,73.036 C113.2584,74.7320085 111.209087,76.3219926 109.089077,77.806 C106.969066,79.2900074 104.849087,80.7033266 102.729077,82.046 C100.609066,83.3886734 98.6480856,84.7313266 96.8460766,86.074 C95.0440676,87.4166734 93.47175,88.8123261 92.1290766,90.261 C90.7864032,91.7096739 89.8677458,93.2466585 89.3730766,94.872 L125.519077,94.872 L125.519077,105.684 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/heading-3": { "title": "$:/core/images/heading-3", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-heading-3 tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M6,30 L19.25,30 L19.25,60.104 L53.7,60.104 L53.7,30 L66.95,30 L66.95,105.684 L53.7,105.684 L53.7,71.552 L19.25,71.552 L19.25,105.684 L6,105.684 L6,30 Z M94.8850766,62.224 C96.8637532,62.294667 98.8424001,62.1533351 100.821077,61.8 C102.799753,61.4466649 104.566402,60.8283378 106.121077,59.945 C107.675751,59.0616623 108.930072,57.8426744 109.884077,56.288 C110.838081,54.7333256 111.315077,52.8253446 111.315077,50.564 C111.315077,47.3839841 110.237421,44.8400095 108.082077,42.932 C105.926733,41.0239905 103.153094,40.07 99.7610766,40.07 C97.641066,40.07 95.8037511,40.4939958 94.2490766,41.342 C92.6944022,42.1900042 91.4047484,43.3383261 90.3800766,44.787 C89.3554048,46.2356739 88.5957458,47.860991 88.1010766,49.663 C87.6064075,51.465009 87.3944096,53.3199905 87.4650766,55.228 L75.3810766,55.228 C75.5224107,51.623982 76.1937373,48.2850154 77.3950766,45.211 C78.596416,42.1369846 80.2393995,39.4693446 82.3240766,37.208 C84.4087537,34.9466554 86.9350618,33.1800064 89.9030766,31.908 C92.8710915,30.6359936 96.2277246,30 99.9730766,30 C102.870424,30 105.714729,30.4239958 108.506077,31.272 C111.297424,32.1200042 113.806065,33.3566585 116.032077,34.982 C118.258088,36.6073415 120.042403,38.6743208 121.385077,41.183 C122.72775,43.6916792 123.399077,46.5713171 123.399077,49.822 C123.399077,53.5673521 122.551085,56.8356527 120.855077,59.627 C119.159068,62.4183473 116.509095,64.4499936 112.905077,65.722 L112.905077,65.934 C117.145098,66.7820042 120.448731,68.8843166 122.816077,72.241 C125.183422,75.5976835 126.367077,79.6786426 126.367077,84.484 C126.367077,88.017351 125.660417,91.1796527 124.247077,93.971 C122.833736,96.7623473 120.925755,99.129657 118.523077,101.073 C116.120398,103.016343 113.329093,104.517995 110.149077,105.578 C106.969061,106.638005 103.612428,107.168 100.079077,107.168 C95.7683884,107.168 92.005426,106.549673 88.7900766,105.313 C85.5747272,104.076327 82.8894207,102.327345 80.7340766,100.066 C78.5787325,97.8046554 76.9357489,95.0840159 75.8050766,91.904 C74.6744043,88.7239841 74.0737436,85.1906861 74.0030766,81.304 L86.0870766,81.304 C85.9457426,85.8266893 87.0587315,89.5896517 89.4260766,92.593 C91.7934218,95.5963483 95.3443863,97.098 100.079077,97.098 C104.107097,97.098 107.481396,95.9496782 110.202077,93.653 C112.922757,91.3563219 114.283077,88.0880212 114.283077,83.848 C114.283077,80.9506522 113.717749,78.6540085 112.587077,76.958 C111.456404,75.2619915 109.972419,73.9723378 108.135077,73.089 C106.297734,72.2056623 104.230755,71.6580011 101.934077,71.446 C99.6373985,71.2339989 97.2877553,71.163333 94.8850766,71.234 L94.8850766,62.224 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/heading-4": { "title": "$:/core/images/heading-4", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-heading-4 tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M8,30 L21.25,30 L21.25,60.104 L55.7,60.104 L55.7,30 L68.95,30 L68.95,105.684 L55.7,105.684 L55.7,71.552 L21.25,71.552 L21.25,105.684 L8,105.684 L8,30 Z M84.5890766,78.548 L107.061077,78.548 L107.061077,45.9 L106.849077,45.9 L84.5890766,78.548 Z M128.049077,88.088 L118.509077,88.088 L118.509077,105.684 L107.061077,105.684 L107.061077,88.088 L75.2610766,88.088 L75.2610766,76.11 L107.061077,31.484 L118.509077,31.484 L118.509077,78.548 L128.049077,78.548 L128.049077,88.088 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/heading-5": { "title": "$:/core/images/heading-5", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-heading-5 tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M6,30 L19.25,30 L19.25,60.104 L53.7,60.104 L53.7,30 L66.95,30 L66.95,105.684 L53.7,105.684 L53.7,71.552 L19.25,71.552 L19.25,105.684 L6,105.684 L6,30 Z M83.7550766,31.484 L122.127077,31.484 L122.127077,42.296 L92.7650766,42.296 L88.9490766,61.164 L89.1610766,61.376 C90.7864181,59.5386575 92.8533974,58.1430048 95.3620766,57.189 C97.8707558,56.2349952 100.361731,55.758 102.835077,55.758 C106.509762,55.758 109.795729,56.3763272 112.693077,57.613 C115.590424,58.8496729 118.0284,60.5809889 120.007077,62.807 C121.985753,65.0330111 123.487405,67.6653181 124.512077,70.704 C125.536748,73.7426819 126.049077,77.028649 126.049077,80.562 C126.049077,83.5300148 125.572081,86.5863176 124.618077,89.731 C123.664072,92.8756824 122.144754,95.7376538 120.060077,98.317 C117.9754,100.896346 115.30776,103.016325 112.057077,104.677 C108.806394,106.337675 104.919766,107.168 100.397077,107.168 C96.7930586,107.168 93.454092,106.691005 90.3800766,105.737 C87.3060613,104.782995 84.6030883,103.35201 82.2710766,101.444 C79.939065,99.5359905 78.0840835,97.1863473 76.7060766,94.395 C75.3280697,91.6036527 74.5684107,88.3353521 74.4270766,84.59 L86.5110766,84.59 C86.8644117,88.6180201 88.2423979,91.7096559 90.6450766,93.865 C93.0477553,96.0203441 96.2277235,97.098 100.185077,97.098 C102.729089,97.098 104.884401,96.6740042 106.651077,95.826 C108.417752,94.9779958 109.848738,93.8120074 110.944077,92.328 C112.039415,90.8439926 112.816741,89.1126766 113.276077,87.134 C113.735412,85.1553234 113.965077,83.0353446 113.965077,80.774 C113.965077,78.7246564 113.682413,76.763676 113.117077,74.891 C112.55174,73.018324 111.703749,71.3753404 110.573077,69.962 C109.442404,68.5486596 107.976086,67.4180042 106.174077,66.57 C104.372068,65.7219958 102.269755,65.298 99.8670766,65.298 C97.3230639,65.298 94.9380878,65.7749952 92.7120766,66.729 C90.4860655,67.6830048 88.8784149,69.4673203 87.8890766,72.082 L75.8050766,72.082 L83.7550766,31.484 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/heading-6": { "title": "$:/core/images/heading-6", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-heading-6 tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M6,30 L19.25,30 L19.25,60.104 L53.7,60.104 L53.7,30 L66.95,30 L66.95,105.684 L53.7,105.684 L53.7,71.552 L19.25,71.552 L19.25,105.684 L6,105.684 L6,30 Z M112.587077,50.246 C112.304409,47.2073181 111.226753,44.751676 109.354077,42.879 C107.481401,41.006324 104.955093,40.07 101.775077,40.07 C99.584399,40.07 97.6940846,40.4763293 96.1040766,41.289 C94.5140687,42.1016707 93.1714154,43.1793266 92.0760766,44.522 C90.9807378,45.8646734 90.0974133,47.401658 89.4260766,49.133 C88.7547399,50.864342 88.2070787,52.6839905 87.7830766,54.592 C87.3590745,56.5000095 87.0587442,58.390324 86.8820766,60.263 C86.7054091,62.135676 86.5464107,63.8846585 86.4050766,65.51 L86.6170766,65.722 C88.2424181,62.7539852 90.4860623,60.5456739 93.3480766,59.097 C96.2100909,57.6483261 99.3017267,56.924 102.623077,56.924 C106.297762,56.924 109.583729,57.5599936 112.481077,58.832 C115.378424,60.1040064 117.834067,61.8529889 119.848077,64.079 C121.862087,66.3050111 123.399071,68.9373181 124.459077,71.976 C125.519082,75.0146819 126.049077,78.300649 126.049077,81.834 C126.049077,85.438018 125.466082,88.7769846 124.300077,91.851 C123.134071,94.9250154 121.455754,97.6103219 119.265077,99.907 C117.074399,102.203678 114.459758,103.987994 111.421077,105.26 C108.382395,106.532006 105.025762,107.168 101.351077,107.168 C95.9097161,107.168 91.4400941,106.16101 87.9420766,104.147 C84.4440591,102.13299 81.6880867,99.3770175 79.6740766,95.879 C77.6600666,92.3809825 76.2644138,88.2823568 75.4870766,83.583 C74.7097394,78.8836432 74.3210766,73.8133605 74.3210766,68.372 C74.3210766,63.9199777 74.7980719,59.4326893 75.7520766,54.91 C76.7060814,50.3873107 78.278399,46.2710186 80.4690766,42.561 C82.6597542,38.8509815 85.5393921,35.8300117 89.1080766,33.498 C92.6767611,31.1659883 97.0757171,30 102.305077,30 C105.273091,30 108.064397,30.4946617 110.679077,31.484 C113.293756,32.4733383 115.608067,33.8513245 117.622077,35.618 C119.636087,37.3846755 121.27907,39.5046543 122.551077,41.978 C123.823083,44.4513457 124.529743,47.2073181 124.671077,50.246 L112.587077,50.246 Z M100.927077,97.098 C103.117754,97.098 105.025735,96.6563378 106.651077,95.773 C108.276418,94.8896623 109.636738,93.7413404 110.732077,92.328 C111.827415,90.9146596 112.640074,89.271676 113.170077,87.399 C113.700079,85.526324 113.965077,83.6006766 113.965077,81.622 C113.965077,79.6433234 113.700079,77.7353425 113.170077,75.898 C112.640074,74.0606575 111.827415,72.4530069 110.732077,71.075 C109.636738,69.6969931 108.276418,68.5840042 106.651077,67.736 C105.025735,66.8879958 103.117754,66.464 100.927077,66.464 C98.736399,66.464 96.8107516,66.8703293 95.1500766,67.683 C93.4894017,68.4956707 92.0937489,69.5909931 90.9630766,70.969 C89.8324043,72.3470069 88.9844128,73.9546575 88.4190766,75.792 C87.8537405,77.6293425 87.5710766,79.5726564 87.5710766,81.622 C87.5710766,83.6713436 87.8537405,85.6146575 88.4190766,87.452 C88.9844128,89.2893425 89.8324043,90.9323261 90.9630766,92.381 C92.0937489,93.8296739 93.4894017,94.9779958 95.1500766,95.826 C96.8107516,96.6740042 98.736399,97.098 100.927077,97.098 L100.927077,97.098 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/help": { "title": "$:/core/images/help", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-help tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M36.0548906,111.44117 C30.8157418,115.837088 20.8865444,118.803477 9.5,118.803477 C7.86465619,118.803477 6.25937294,118.742289 4.69372699,118.624467 C12.612543,115.984876 18.7559465,110.02454 21.0611049,102.609942 C8.74739781,92.845129 1.04940554,78.9359851 1.04940554,63.5 C1.04940554,33.9527659 29.2554663,10 64.0494055,10 C98.8433448,10 127.049406,33.9527659 127.049406,63.5 C127.049406,93.0472341 98.8433448,117 64.0494055,117 C53.9936953,117 44.48824,114.999337 36.0548906,111.44117 L36.0548906,111.44117 Z M71.4042554,77.5980086 C71.406883,77.2865764 71.4095079,76.9382011 71.4119569,76.5610548 C71.4199751,75.3262169 71.4242825,74.0811293 71.422912,72.9158546 C71.4215244,71.736154 71.4143321,70.709635 71.4001396,69.8743525 C71.4078362,68.5173028 71.9951951,67.7870427 75.1273009,65.6385471 C75.2388969,65.5619968 76.2124091,64.8981068 76.5126553,64.6910879 C79.6062455,62.5580654 81.5345849,60.9050204 83.2750652,58.5038955 C85.6146327,55.2762841 86.8327108,51.426982 86.8327108,46.8554323 C86.8327108,33.5625756 76.972994,24.9029551 65.3778484,24.9029551 C54.2752771,24.9029551 42.8794554,34.5115163 41.3121702,47.1975534 C40.9043016,50.4989536 43.2499725,53.50591 46.5513726,53.9137786 C49.8527728,54.3216471 52.8597292,51.9759763 53.2675978,48.6745761 C54.0739246,42.1479456 60.2395837,36.9492759 65.3778484,36.9492759 C70.6427674,36.9492759 74.78639,40.5885487 74.78639,46.8554323 C74.78639,50.4892974 73.6853224,52.008304 69.6746221,54.7736715 C69.4052605,54.9593956 68.448509,55.6118556 68.3131127,55.7047319 C65.6309785,57.5445655 64.0858213,58.803255 62.6123358,60.6352315 C60.5044618,63.2559399 59.3714208,66.3518252 59.3547527,69.9487679 C59.3684999,70.8407274 59.3752803,71.8084521 59.3765995,72.9300232 C59.3779294,74.0607297 59.3737237,75.2764258 59.36589,76.482835 C59.3634936,76.8518793 59.3609272,77.1924914 59.3583633,77.4963784 C59.3568319,77.6778944 59.3556368,77.8074256 59.3549845,77.8730928 C59.3219814,81.1994287 61.9917551,83.9227111 65.318091,83.9557142 C68.644427,83.9887173 71.3677093,81.3189435 71.4007124,77.9926076 C71.4014444,77.9187458 71.402672,77.7856841 71.4042554,77.5980086 Z M65.3778489,102.097045 C69.5359735,102.097045 72.9067994,98.7262189 72.9067994,94.5680944 C72.9067994,90.4099698 69.5359735,87.0391439 65.3778489,87.0391439 C61.2197243,87.0391439 57.8488984,90.4099698 57.8488984,94.5680944 C57.8488984,98.7262189 61.2197243,102.097045 65.3778489,102.097045 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/home-button": { "title": "$:/core/images/home-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-home-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <g fill-rule=\"evenodd\">\n <path d=\"M112.9847,119.501583 C112.99485,119.336814 113,119.170705 113,119.003406 L113,67.56802 C116.137461,70.5156358 121.076014,70.4518569 124.133985,67.3938855 C127.25818,64.2696912 127.260618,59.2068102 124.131541,56.0777326 L70.3963143,2.34250601 C68.8331348,0.779326498 66.7828947,-0.000743167069 64.7337457,1.61675364e-05 C62.691312,-0.00409949529 60.6426632,0.777559815 59.077717,2.34250601 L33,28.420223 L33,28.420223 L33,8.00697327 C33,3.58484404 29.4092877,0 25,0 C20.581722,0 17,3.59075293 17,8.00697327 L17,44.420223 L5.3424904,56.0777326 C2.21694607,59.2032769 2.22220878,64.2760483 5.34004601,67.3938855 C8.46424034,70.5180798 13.5271213,70.5205187 16.6561989,67.3914411 L17,67.04764 L17,119.993027 C17,119.994189 17.0000002,119.995351 17.0000007,119.996514 C17.0000002,119.997675 17,119.998838 17,120 C17,124.418278 20.5881049,128 24.9992458,128 L105.000754,128 C109.418616,128 113,124.409288 113,120 C113,119.832611 112.99485,119.666422 112.9847,119.501583 Z M97,112 L97,51.5736087 L97,51.5736087 L64.7370156,19.3106244 L33,51.04764 L33,112 L97,112 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/import-button": { "title": "$:/core/images/import-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-import-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M105.449437,94.2138951 C105.449437,94.2138951 110.049457,94.1897106 110.049457,99.4026111 C110.049457,104.615512 105.163246,104.615511 105.163246,104.615511 L45.0075072,105.157833 C45.0075072,105.157833 0.367531803,106.289842 0.367532368,66.6449212 C0.367532934,27.0000003 45.0428249,27.0000003 45.0428249,27.0000003 L105.532495,27.0000003 C105.532495,27.0000003 138.996741,25.6734987 138.996741,55.1771866 C138.996741,84.6808745 105.727102,82.8457535 105.727102,82.8457535 L56.1735087,82.8457535 C56.1735087,82.8457535 22.6899229,85.1500223 22.6899229,66.0913753 C22.6899229,47.0327282 56.1735087,49.3383013 56.1735087,49.3383013 L105.727102,49.3383013 C105.727102,49.3383013 111.245209,49.3383024 111.245209,54.8231115 C111.245209,60.3079206 105.727102,60.5074524 105.727102,60.5074524 L56.1735087,60.5074524 C56.1735087,60.5074524 37.48913,60.5074528 37.48913,66.6449195 C37.48913,72.7823862 56.1735087,71.6766023 56.1735087,71.6766023 L105.727102,71.6766029 C105.727102,71.6766029 127.835546,73.1411469 127.835546,55.1771866 C127.835546,35.5304025 105.727102,38.3035317 105.727102,38.3035317 L45.0428249,38.3035317 C45.0428249,38.3035317 11.5287276,38.3035313 11.5287276,66.6449208 C11.5287276,94.9863103 45.0428244,93.9579678 45.0428244,93.9579678 L105.449437,94.2138951 Z\" transform=\"translate(69.367532, 66.000000) rotate(-45.000000) translate(-69.367532, -66.000000) \"></path>\n </g>\n</svg>" }, "$:/core/images/info-button": { "title": "$:/core/images/info-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-info-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <g fill-rule=\"evenodd\">\n <g transform=\"translate(0.049406, 0.000000)\">\n <path d=\"M64,128 C99.346224,128 128,99.346224 128,64 C128,28.653776 99.346224,0 64,0 C28.653776,0 0,28.653776 0,64 C0,99.346224 28.653776,128 64,128 Z M64,112 C90.509668,112 112,90.509668 112,64 C112,37.490332 90.509668,16 64,16 C37.490332,16 16,37.490332 16,64 C16,90.509668 37.490332,112 64,112 Z\"></path>\n <circle cx=\"64\" cy=\"32\" r=\"8\"></circle>\n <rect x=\"56\" y=\"48\" width=\"16\" height=\"56\" rx=\"8\"></rect>\n </g>\n </g>\n</svg>" }, "$:/core/images/italic": { "title": "$:/core/images/italic", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-italic tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <polygon points=\"66.7114846 0 89.1204482 0 62.4089636 128 40 128\"></polygon>\n </g>\n</svg>" }, "$:/core/images/left-arrow": { "created": "20150315234410875", "modified": "20150315235324760", "tags": "$:/tags/Image", "title": "$:/core/images/left-arrow", "text": "<svg class=\"tc-image-left-arrow tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <path transform=\"rotate(135, 63.8945, 64.1752)\" d=\"m109.07576,109.35336c-1.43248,1.43361 -3.41136,2.32182 -5.59717,2.32182l-79.16816,0c-4.36519,0 -7.91592,-3.5444 -7.91592,-7.91666c0,-4.36337 3.54408,-7.91667 7.91592,-7.91667l71.25075,0l0,-71.25075c0,-4.3652 3.54442,-7.91592 7.91667,-7.91592c4.36336,0 7.91667,3.54408 7.91667,7.91592l0,79.16815c0,2.1825 -0.88602,4.16136 -2.3185,5.59467l-0.00027,-0.00056z\"/>\n</svg>\n" }, "$:/core/images/line-width": { "title": "$:/core/images/line-width", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-line-width tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M128,-97 L112.992786,-97 C112.452362,-97 112,-96.5522847 112,-96 C112,-95.4438648 112.444486,-95 112.992786,-95 L128,-95 L128,-97 Z M128,-78.6794919 L111.216185,-88.3696322 C110.748163,-88.6398444 110.132549,-88.4782926 109.856406,-88 C109.578339,-87.5183728 109.741342,-86.9117318 110.216185,-86.6375814 L128,-76.3700908 L128,-78.6794919 Z M78.6794919,-128 L88.3696322,-111.216185 C88.6437826,-110.741342 88.4816272,-110.134474 88,-109.856406 C87.5217074,-109.580264 86.9077936,-109.748163 86.6375814,-110.216185 L76.3700908,-128 L78.6794919,-128 Z M97,-128 L97,-112.992786 C97,-112.444486 96.5561352,-112 96,-112 C95.4477153,-112 95,-112.452362 95,-112.992786 L95,-128 L97,-128 Z M115.629909,-128 L105.362419,-110.216185 C105.088268,-109.741342 104.481627,-109.578339 104,-109.856406 C103.521707,-110.132549 103.360156,-110.748163 103.630368,-111.216185 L113.320508,-128 L115.629909,-128 Z M128,-113.320508 L111.216185,-103.630368 C110.741342,-103.356217 110.134474,-103.518373 109.856406,-104 C109.580264,-104.478293 109.748163,-105.092206 110.216185,-105.362419 L128,-115.629909 L128,-113.320508 Z M48,-96 C48,-96.5522847 48.4523621,-97 48.9927864,-97 L79.0072136,-97 C79.5555144,-97 80,-96.5561352 80,-96 C80,-95.4477153 79.5476379,-95 79.0072136,-95 L48.9927864,-95 C48.4444856,-95 48,-95.4438648 48,-96 Z M54.4307806,-120 C54.706923,-120.478293 55.3225377,-120.639844 55.7905589,-120.369632 L81.7838153,-105.362419 C82.2586577,-105.088268 82.4216611,-104.481627 82.1435935,-104 C81.8674512,-103.521707 81.2518365,-103.360156 80.7838153,-103.630368 L54.7905589,-118.637581 C54.3157165,-118.911732 54.152713,-119.518373 54.4307806,-120 Z M104,-82.1435935 C104.478293,-82.4197359 105.092206,-82.2518365 105.362419,-81.7838153 L120.369632,-55.7905589 C120.643783,-55.3157165 120.481627,-54.7088482 120,-54.4307806 C119.521707,-54.1546382 118.907794,-54.3225377 118.637581,-54.7905589 L103.630368,-80.7838153 C103.356217,-81.2586577 103.518373,-81.865526 104,-82.1435935 Z M96,-80 C96.5522847,-80 97,-79.5476379 97,-79.0072136 L97,-48.9927864 C97,-48.4444856 96.5561352,-48 96,-48 C95.4477153,-48 95,-48.4523621 95,-48.9927864 L95,-79.0072136 C95,-79.5555144 95.4438648,-80 96,-80 Z M88,-82.1435935 C88.4782926,-81.8674512 88.6398444,-81.2518365 88.3696322,-80.7838153 L73.3624186,-54.7905589 C73.0882682,-54.3157165 72.4816272,-54.152713 72,-54.4307806 C71.5217074,-54.706923 71.3601556,-55.3225377 71.6303678,-55.7905589 L86.6375814,-81.7838153 C86.9117318,-82.2586577 87.5183728,-82.4216611 88,-82.1435935 Z M82.1435935,-88 C82.4197359,-87.5217074 82.2518365,-86.9077936 81.7838153,-86.6375814 L55.7905589,-71.6303678 C55.3157165,-71.3562174 54.7088482,-71.5183728 54.4307806,-72 C54.1546382,-72.4782926 54.3225377,-73.0922064 54.7905589,-73.3624186 L80.7838153,-88.3696322 C81.2586577,-88.6437826 81.865526,-88.4816272 82.1435935,-88 Z M1.30626177e-08,-41.9868843 L15.0170091,-57.9923909 L20.7983821,-52.9749272 L44.7207091,-81.2095939 L73.4260467,-42.1002685 L85.984793,-56.6159488 L104.48741,-34.0310661 L127.969109,-47.4978019 L127.969109,7.99473128e-07 L1.30626177e-08,7.99473128e-07 L1.30626177e-08,-41.9868843 Z M96,-84 C102.627417,-84 108,-89.372583 108,-96 C108,-102.627417 102.627417,-108 96,-108 C89.372583,-108 84,-102.627417 84,-96 C84,-89.372583 89.372583,-84 96,-84 Z\"></path>\n <path d=\"M16,18 L112,18 C113.104569,18 114,17.1045695 114,16 C114,14.8954305 113.104569,14 112,14 L16,14 C14.8954305,14 14,14.8954305 14,16 C14,17.1045695 14.8954305,18 16,18 L16,18 Z M16,35 L112,35 C114.209139,35 116,33.209139 116,31 C116,28.790861 114.209139,27 112,27 L16,27 C13.790861,27 12,28.790861 12,31 C12,33.209139 13.790861,35 16,35 L16,35 Z M16,56 L112,56 C115.313708,56 118,53.3137085 118,50 C118,46.6862915 115.313708,44 112,44 L16,44 C12.6862915,44 10,46.6862915 10,50 C10,53.3137085 12.6862915,56 16,56 L16,56 Z M16,85 L112,85 C117.522847,85 122,80.5228475 122,75 C122,69.4771525 117.522847,65 112,65 L16,65 C10.4771525,65 6,69.4771525 6,75 C6,80.5228475 10.4771525,85 16,85 L16,85 Z M16,128 L112,128 C120.836556,128 128,120.836556 128,112 C128,103.163444 120.836556,96 112,96 L16,96 C7.163444,96 0,103.163444 0,112 C0,120.836556 7.163444,128 16,128 L16,128 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/link": { "title": "$:/core/images/link", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-link tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M128.719999,57.568543 C130.219553,53.8628171 131.045202,49.8121445 131.045202,45.5685425 C131.045202,27.8915447 116.718329,13.5685425 99.0452364,13.5685425 L67.0451674,13.5685425 C49.3655063,13.5685425 35.0452019,27.8954305 35.0452019,45.5685425 C35.0452019,63.2455403 49.3720745,77.5685425 67.0451674,77.5685425 L99.0452364,77.5685425 C100.406772,77.5685425 101.748384,77.4835732 103.065066,77.3186499 C96.4792444,73.7895096 91.1190212,68.272192 87.7873041,61.5685425 L67.0506214,61.5685425 C58.2110723,61.5685425 51.0452019,54.4070414 51.0452019,45.5685425 C51.0452019,36.7319865 58.2005234,29.5685425 67.0506214,29.5685425 L99.0397824,29.5685425 C107.879331,29.5685425 115.045202,36.7300436 115.045202,45.5685425 C115.045202,48.9465282 113.99957,52.0800164 112.21335,54.6623005 C114.314383,56.4735917 117.050039,57.5685425 120.041423,57.5685425 L128.720003,57.5685425 Z\" transform=\"translate(83.045202, 45.568542) rotate(-225.000000) translate(-83.045202, -45.568542)\"></path>\n <path d=\"M-0.106255113,71.0452019 C-1.60580855,74.7509276 -2.43145751,78.8016001 -2.43145751,83.0452019 C-2.43145751,100.7222 11.8954151,115.045202 29.568508,115.045202 L61.568577,115.045202 C79.2482381,115.045202 93.5685425,100.718314 93.5685425,83.0452019 C93.5685425,65.3682041 79.2416699,51.0452019 61.568577,51.0452019 L29.568508,51.0452019 C28.206973,51.0452019 26.8653616,51.1301711 25.5486799,51.2950943 C32.1345,54.8242347 37.4947231,60.3415524 40.8264403,67.0452019 L61.563123,67.0452019 C70.4026721,67.0452019 77.5685425,74.206703 77.5685425,83.0452019 C77.5685425,91.8817579 70.413221,99.0452019 61.563123,99.0452019 L29.573962,99.0452019 C20.7344129,99.0452019 13.5685425,91.8837008 13.5685425,83.0452019 C13.5685425,79.6672162 14.6141741,76.533728 16.4003949,73.9514439 C14.2993609,72.1401527 11.5637054,71.0452019 8.5723215,71.0452019 L-0.106255113,71.0452019 Z\" transform=\"translate(45.568542, 83.045202) rotate(-225.000000) translate(-45.568542, -83.045202)\"></path>\n </g>\n</svg>" }, "$:/core/images/list-bullet": { "title": "$:/core/images/list-bullet", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-list-bullet tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M11.6363636,40.2727273 C18.0629498,40.2727273 23.2727273,35.0629498 23.2727273,28.6363636 C23.2727273,22.2097775 18.0629498,17 11.6363636,17 C5.20977746,17 0,22.2097775 0,28.6363636 C0,35.0629498 5.20977746,40.2727273 11.6363636,40.2727273 Z M11.6363636,75.1818182 C18.0629498,75.1818182 23.2727273,69.9720407 23.2727273,63.5454545 C23.2727273,57.1188684 18.0629498,51.9090909 11.6363636,51.9090909 C5.20977746,51.9090909 0,57.1188684 0,63.5454545 C0,69.9720407 5.20977746,75.1818182 11.6363636,75.1818182 Z M11.6363636,110.090909 C18.0629498,110.090909 23.2727273,104.881132 23.2727273,98.4545455 C23.2727273,92.0279593 18.0629498,86.8181818 11.6363636,86.8181818 C5.20977746,86.8181818 0,92.0279593 0,98.4545455 C0,104.881132 5.20977746,110.090909 11.6363636,110.090909 Z M34.9090909,22.8181818 L128,22.8181818 L128,34.4545455 L34.9090909,34.4545455 L34.9090909,22.8181818 Z M34.9090909,57.7272727 L128,57.7272727 L128,69.3636364 L34.9090909,69.3636364 L34.9090909,57.7272727 Z M34.9090909,92.6363636 L128,92.6363636 L128,104.272727 L34.9090909,104.272727 L34.9090909,92.6363636 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/list-number": { "title": "$:/core/images/list-number", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-list-number tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M33.8390805,22.3563218 L128,22.3563218 L128,34.1264368 L33.8390805,34.1264368 L33.8390805,22.3563218 Z M33.8390805,57.6666667 L128,57.6666667 L128,69.4367816 L33.8390805,69.4367816 L33.8390805,57.6666667 Z M33.8390805,92.9770115 L128,92.9770115 L128,104.747126 L33.8390805,104.747126 L33.8390805,92.9770115 Z M0.379509711,42.6307008 L0.379509711,40.4082314 L1.37821948,40.4082314 C2.20382368,40.4082314 2.82301754,40.268077 3.23581964,39.9877642 C3.64862174,39.7074513 3.85501969,39.0400498 3.85501969,37.9855395 L3.85501969,22.7686318 C3.85501969,21.3270228 3.66193774,20.4327047 3.27576803,20.0856507 C2.88959832,19.7385967 1.79768657,19.5650723 0,19.5650723 L0,17.4226919 C3.50215975,17.2758613 6.25191314,16.4683055 8.24934266,15 L10.3666074,15 L10.3666074,37.865406 C10.3666074,38.786434 10.5164123,39.4404875 10.8160268,39.8275862 C11.1156412,40.2146849 11.764796,40.4082314 12.7635108,40.4082314 L13.7622206,40.4082314 L13.7622206,42.6307008 L0.379509711,42.6307008 Z M0.0798967812,77.9873934 L0.0798967812,76.0852799 C7.27064304,69.5312983 10.8659622,63.5046623 10.8659622,58.005191 C10.8659622,56.4434479 10.5397203,55.195407 9.88722667,54.2610308 C9.23473303,53.3266546 8.36253522,52.8594735 7.27060709,52.8594735 C6.3784219,52.8594735 5.61608107,53.1764892 4.98356173,53.8105302 C4.35104238,54.4445712 4.03478745,55.1753759 4.03478745,56.0029663 C4.03478745,56.9773871 4.28113339,57.8316611 4.77383268,58.5658139 C4.88036225,58.7259926 4.93362624,58.8461249 4.93362624,58.9262143 C4.93362624,59.0730449 4.77383427,59.2065252 4.45424555,59.3266593 C4.2411864,59.4067486 3.70188852,59.6336652 2.83633573,60.0074156 C1.99741533,60.3811661 1.47809145,60.5680386 1.2783485,60.5680386 C1.03865696,60.5680386 0.765679018,60.1976307 0.459406492,59.4568039 C0.153133966,58.715977 0,57.9184322 0,57.0641453 C0,55.1153036 0.848894811,53.5202138 2.5467099,52.2788283 C4.24452499,51.0374428 6.34512352,50.4167594 8.84856852,50.4167594 C11.3120649,50.4167594 13.3793735,51.0874979 15.0505562,52.4289952 C16.7217389,53.7704924 17.5573177,55.5224215 17.5573177,57.684835 C17.5573177,58.9662652 17.2743527,60.2076321 16.7084144,61.4089729 C16.142476,62.6103138 14.7875733,64.4623531 12.6436656,66.9651465 C10.4997579,69.4679398 8.40914641,71.7804862 6.3717683,73.902855 L17.8169822,73.902855 L16.7982982,79.6292176 L14.6810335,79.6292176 C14.7609307,79.3489048 14.8008787,79.0952922 14.8008787,78.8683723 C14.8008787,78.4812736 14.7010087,78.237672 14.5012658,78.1375603 C14.3015228,78.0374485 13.9020429,77.9873934 13.3028141,77.9873934 L0.0798967812,77.9873934 Z M12.2042333,97.1935484 C13.9486551,97.2335931 15.4400468,97.8309175 16.6784531,98.9855395 C17.9168594,100.140162 18.5360532,101.75861 18.5360532,103.840934 C18.5360532,106.830938 17.4041935,109.233584 15.14044,111.048943 C12.8766866,112.864303 10.1402492,113.771969 6.93104577,113.771969 C4.92030005,113.771969 3.26245842,113.388213 1.95747114,112.62069 C0.652483855,111.853166 0,110.848727 0,109.607341 C0,108.833144 0.26964894,108.209124 0.808954909,107.735261 C1.34826088,107.261399 1.93749375,107.024472 2.57667119,107.024472 C3.21584864,107.024472 3.73850152,107.224692 4.14464552,107.625139 C4.55078953,108.025586 4.92696644,108.67964 5.27318756,109.587319 C5.73925445,110.855401 6.51158227,111.489433 7.59019421,111.489433 C8.85523291,111.489433 9.87723568,111.012241 10.6562332,110.057842 C11.4352307,109.103444 11.8247236,107.371536 11.8247236,104.862069 C11.8247236,103.153495 11.7048796,101.838714 11.4651881,100.917686 C11.2254966,99.9966584 10.6728827,99.5361513 9.80732989,99.5361513 C9.22141723,99.5361513 8.62219737,99.843156 8.00965231,100.457175 C7.51695303,100.951059 7.07752513,101.197998 6.69135542,101.197998 C6.3584505,101.197998 6.08880156,101.051169 5.88240051,100.757508 C5.67599946,100.463847 5.57280049,100.183539 5.57280049,99.916574 C5.57280049,99.5962164 5.67599946,99.3225818 5.88240051,99.0956618 C6.08880156,98.8687419 6.57150646,98.5016711 7.33052967,97.9944383 C10.2068282,96.0722929 11.6449559,93.9766521 11.6449559,91.7074527 C11.6449559,90.5194601 11.3386879,89.615131 10.7261429,88.9944383 C10.1135978,88.3737455 9.37455999,88.0634038 8.5090072,88.0634038 C7.71003539,88.0634038 6.98431355,88.3270274 6.33181991,88.8542825 C5.67932627,89.3815377 5.35308434,90.0122321 5.35308434,90.7463849 C5.35308434,91.3871 5.60608828,91.9810874 6.11210376,92.5283648 C6.28521432,92.7285883 6.3717683,92.8954387 6.3717683,93.028921 C6.3717683,93.1490551 5.80250943,93.4560598 4.6639746,93.9499444 C3.52543978,94.4438289 2.80970494,94.6907675 2.51674861,94.6907675 C2.10394651,94.6907675 1.76771758,94.3570667 1.50805174,93.6896552 C1.24838591,93.0222436 1.11855494,92.4082342 1.11855494,91.8476085 C1.11855494,90.0989901 2.04734573,88.6240327 3.90495518,87.4226919 C5.76256463,86.2213511 7.86982116,85.6206897 10.226788,85.6206897 C12.2907985,85.6206897 14.0784711,86.0678487 15.5898594,86.9621802 C17.1012478,87.8565117 17.8569306,89.0778566 17.8569306,90.6262514 C17.8569306,91.987771 17.2876717,93.2491599 16.1491369,94.4104561 C15.0106021,95.5717522 13.6956474,96.4994404 12.2042333,97.1935484 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/list": { "title": "$:/core/images/list", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-list tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M0.719999312,185.568543 C2.21955287,181.862817 3.0452019,177.812144 3.0452019,173.568542 C3.0452019,155.891545 -11.2816707,141.568542 -28.9547636,141.568542 L-60.9548326,141.568542 C-78.6344937,141.568542 -92.9547981,155.895431 -92.9547981,173.568542 C-92.9547981,191.24554 -78.6279255,205.568542 -60.9548326,205.568542 L-28.9547636,205.568542 C-27.593228,205.568542 -26.2516158,205.483573 -24.9349335,205.31865 C-31.5207556,201.78951 -36.8809788,196.272192 -40.2126959,189.568542 L-60.9493786,189.568542 C-69.7889277,189.568542 -76.9547981,182.407041 -76.9547981,173.568542 C-76.9547981,164.731986 -69.7994766,157.568542 -60.9493786,157.568542 L-28.9602176,157.568542 C-20.1206685,157.568542 -12.9547981,164.730044 -12.9547981,173.568542 C-12.9547981,176.946528 -14.0004297,180.080016 -15.7866505,182.6623 C-13.6856165,184.473592 -10.949961,185.568542 -7.9585771,185.568542 L0.720002586,185.568542 Z\" transform=\"translate(-44.954798, 173.568542) rotate(-225.000000) translate(44.954798, -173.568542) \"></path>\n <path d=\"M87.7480315,128 L23.9992458,128 C19.5813843,128 16,124.409247 16,119.993027 L16,8.00697327 C16,3.58484404 19.5881049,0 23.9992458,0 L104.000754,0 C108.418616,0 112,3.59075293 112,8.00697327 L112,104 L91.2492027,104 C90.2848199,104 89.410573,104.391703 88.7768998,105.025201 C88.1373658,105.661376 87.7480315,106.53563 87.7480315,107.501171 L87.7480315,128 Z M95.7480315,127.879386 L111.627417,112 L95.7480315,112 L95.7480315,127.879386 Z M40,15.5089165 C40,13.5709954 41.5636015,12 43.4998101,12 L98.5001899,12 C100.433082,12 102,13.5614718 102,15.5089165 L102,16.4910835 C102,18.4290046 100.436399,20 98.5001899,20 L43.4998101,20 C41.5669183,20 40,18.4385282 40,16.4910835 L40,15.5089165 Z M32,22 C35.3137085,22 38,19.3137085 38,16 C38,12.6862915 35.3137085,10 32,10 C28.6862915,10 26,12.6862915 26,16 C26,19.3137085 28.6862915,22 32,22 Z M40,31.5089165 C40,29.5709954 41.5636015,28 43.4998101,28 L98.5001899,28 C100.433082,28 102,29.5614718 102,31.5089165 L102,32.4910835 C102,34.4290046 100.436399,36 98.5001899,36 L43.4998101,36 C41.5669183,36 40,34.4385282 40,32.4910835 L40,31.5089165 Z M40,47.5089165 C40,45.5709954 41.5636015,44 43.4998101,44 L98.5001899,44 C100.433082,44 102,45.5614718 102,47.5089165 L102,48.4910835 C102,50.4290046 100.436399,52 98.5001899,52 L43.4998101,52 C41.5669183,52 40,50.4385282 40,48.4910835 L40,47.5089165 Z M40,63.5089165 C40,61.5709954 41.5636015,60 43.4998101,60 L98.5001899,60 C100.433082,60 102,61.5614718 102,63.5089165 L102,64.4910835 C102,66.4290046 100.436399,68 98.5001899,68 L43.4998101,68 C41.5669183,68 40,66.4385282 40,64.4910835 L40,63.5089165 Z M40,79.5089165 C40,77.5709954 41.5636015,76 43.4998101,76 L98.5001899,76 C100.433082,76 102,77.5614718 102,79.5089165 L102,80.4910835 C102,82.4290046 100.436399,84 98.5001899,84 L43.4998101,84 C41.5669183,84 40,82.4385282 40,80.4910835 L40,79.5089165 Z M40,95.5089165 C40,93.5709954 41.5636015,92 43.4998101,92 L98.5001899,92 C100.433082,92 102,93.5614718 102,95.5089165 L102,96.4910835 C102,98.4290046 100.436399,100 98.5001899,100 L43.4998101,100 C41.5669183,100 40,98.4385282 40,96.4910835 L40,95.5089165 Z M40,111.508916 C40,109.570995 41.5680474,108 43.4972017,108 L76.5027983,108 C78.4342495,108 80,109.561472 80,111.508916 L80,112.491084 C80,114.429005 78.4319526,116 76.5027983,116 L43.4972017,116 C41.5657505,116 40,114.438528 40,112.491084 L40,111.508916 Z M32,38 C35.3137085,38 38,35.3137085 38,32 C38,28.6862915 35.3137085,26 32,26 C28.6862915,26 26,28.6862915 26,32 C26,35.3137085 28.6862915,38 32,38 Z M32,54 C35.3137085,54 38,51.3137085 38,48 C38,44.6862915 35.3137085,42 32,42 C28.6862915,42 26,44.6862915 26,48 C26,51.3137085 28.6862915,54 32,54 Z M32,70 C35.3137085,70 38,67.3137085 38,64 C38,60.6862915 35.3137085,58 32,58 C28.6862915,58 26,60.6862915 26,64 C26,67.3137085 28.6862915,70 32,70 Z M32,86 C35.3137085,86 38,83.3137085 38,80 C38,76.6862915 35.3137085,74 32,74 C28.6862915,74 26,76.6862915 26,80 C26,83.3137085 28.6862915,86 32,86 Z M32,102 C35.3137085,102 38,99.3137085 38,96 C38,92.6862915 35.3137085,90 32,90 C28.6862915,90 26,92.6862915 26,96 C26,99.3137085 28.6862915,102 32,102 Z M32,118 C35.3137085,118 38,115.313708 38,112 C38,108.686292 35.3137085,106 32,106 C28.6862915,106 26,108.686292 26,112 C26,115.313708 28.6862915,118 32,118 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/locked-padlock": { "title": "$:/core/images/locked-padlock", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-locked-padlock tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M96.4723753,64 L105,64 L105,96.0097716 C105,113.673909 90.6736461,128 73.001193,128 L55.998807,128 C38.3179793,128 24,113.677487 24,96.0097716 L24,64 L32.0000269,64 C32.0028554,48.2766389 32.3030338,16.2688026 64.1594984,16.2688041 C95.9543927,16.2688056 96.4648869,48.325931 96.4723753,64 Z M80.5749059,64 L48.4413579,64 C48.4426205,47.71306 48.5829272,31.9999996 64.1595001,31.9999996 C79.8437473,31.9999996 81.1369461,48.1359182 80.5749059,64 Z M67.7315279,92.3641717 C70.8232551,91.0923621 73,88.0503841 73,84.5 C73,79.8055796 69.1944204,76 64.5,76 C59.8055796,76 56,79.8055796 56,84.5 C56,87.947435 58.0523387,90.9155206 61.0018621,92.2491029 L55.9067479,115.020857 L72.8008958,115.020857 L67.7315279,92.3641717 L67.7315279,92.3641717 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/mail": { "title": "$:/core/images/mail", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-mail tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M122.826782,104.894066 C121.945525,105.22777 120.990324,105.41043 119.993027,105.41043 L8.00697327,105.41043 C7.19458381,105.41043 6.41045219,105.289614 5.67161357,105.064967 L5.67161357,105.064967 L39.8346483,70.9019325 L60.6765759,91.7438601 C61.6118278,92.679112 62.8865166,93.0560851 64.0946097,92.8783815 C65.2975108,93.0473238 66.5641085,92.6696979 67.4899463,91.7438601 L88.5941459,70.6396605 C88.6693095,70.7292352 88.7490098,70.8162939 88.8332479,70.9005321 L122.826782,104.894066 Z M127.903244,98.6568194 C127.966933,98.2506602 128,97.8343714 128,97.4103789 L128,33.410481 C128,32.7414504 127.917877,32.0916738 127.763157,31.4706493 L94.2292399,65.0045665 C94.3188145,65.0797417 94.4058701,65.1594458 94.4901021,65.2436778 L127.903244,98.6568194 Z M0.205060636,99.2178117 C0.0709009529,98.6370366 0,98.0320192 0,97.4103789 L0,33.410481 C0,32.694007 0.0944223363,31.9995312 0.27147538,31.3387595 L0.27147538,31.3387595 L34.1777941,65.2450783 L0.205060636,99.2178117 L0.205060636,99.2178117 Z M5.92934613,25.6829218 C6.59211333,25.5051988 7.28862283,25.4104299 8.00697327,25.4104299 L119.993027,25.4104299 C120.759109,25.4104299 121.500064,25.5178649 122.201605,25.7184927 L122.201605,25.7184927 L64.0832611,83.8368368 L5.92934613,25.6829218 L5.92934613,25.6829218 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/menu-button": { "title": "$:/core/images/menu-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-menu-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <rect x=\"0\" y=\"16\" width=\"128\" height=\"16\" rx=\"8\"></rect>\n <rect x=\"0\" y=\"56\" width=\"128\" height=\"16\" rx=\"8\"></rect>\n <rect x=\"0\" y=\"96\" width=\"128\" height=\"16\" rx=\"8\"></rect>\n</svg>" }, "$:/core/images/mono-block": { "title": "$:/core/images/mono-block", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-mono-block tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M23.9653488,32.9670593 L24.3217888,32.9670593 C25.0766067,32.9670593 25.6497006,33.1592554 26.0410876,33.5436534 C26.4324747,33.9280514 26.6281653,34.4906619 26.6281653,35.2315017 C26.6281653,36.0562101 26.4219913,36.6502709 26.009637,37.0137017 C25.5972828,37.3771326 24.9158602,37.5588453 23.9653488,37.5588453 L17.6542639,37.5588453 C16.6897744,37.5588453 16.0048573,37.380627 15.5994921,37.0241852 C15.1941269,36.6677435 14.9914474,36.0701882 14.9914474,35.2315017 C14.9914474,34.4207713 15.1941269,33.8406885 15.5994921,33.4912358 C16.0048573,33.141783 16.6897744,32.9670593 17.6542639,32.9670593 L18.388111,32.9670593 L17.5284616,30.5139133 L8.47069195,30.5139133 L7.5691084,32.9670593 L8.30295547,32.9670593 C9.25346691,32.9670593 9.93488953,33.1452775 10.3472438,33.5017193 C10.759598,33.8581611 10.965772,34.4347494 10.965772,35.2315017 C10.965772,36.0562101 10.759598,36.6502709 10.3472438,37.0137017 C9.93488953,37.3771326 9.25346691,37.5588453 8.30295547,37.5588453 L2.89345418,37.5588453 C1.92896463,37.5588453 1.24404754,37.3771326 0.838682371,37.0137017 C0.433317198,36.6502709 0.230637652,36.0562101 0.230637652,35.2315017 C0.230637652,34.4906619 0.426328248,33.9280514 0.817715312,33.5436534 C1.20910238,33.1592554 1.78219626,32.9670593 2.53701417,32.9670593 L2.89345418,32.9670593 L8.51262607,17.3256331 L6.83526132,17.3256331 C5.88474988,17.3256331 5.20332727,17.1439204 4.79097304,16.7804895 C4.37861882,16.4170587 4.1724448,15.8299869 4.1724448,15.0192565 C4.1724448,14.1945481 4.37861882,13.6004873 4.79097304,13.2370565 C5.20332727,12.8736257 5.88474988,12.691913 6.83526132,12.691913 L14.6979086,12.691913 C15.9419603,12.691913 16.815579,13.3628521 17.318791,14.7047506 L17.318791,14.7676518 L23.9653488,32.9670593 Z M12.9786097,17.3256331 L9.9383861,26.1737321 L16.0188333,26.1737321 L12.9786097,17.3256331 Z M35.3809383,26.6979086 L35.3809383,33.0928616 L38.5259972,33.0928616 C40.7485166,33.0928616 42.3140414,32.8482484 43.2226185,32.3590146 C44.1311956,31.8697807 44.5854773,31.0520736 44.5854773,29.9058686 C44.5854773,28.7456855 44.1521624,27.9209895 43.2855197,27.4317556 C42.4188769,26.9425218 40.9022748,26.6979086 38.7356678,26.6979086 L35.3809383,26.6979086 Z M46.0741385,24.370565 C47.5977525,24.9296893 48.7159844,25.6949794 49.428868,26.666458 C50.1417516,27.6379366 50.498188,28.8784752 50.498188,30.388111 C50.498188,31.6601189 50.1906743,32.8202846 49.5756374,33.8686428 C48.9606006,34.917001 48.0799929,35.7766419 46.933788,36.4475911 C46.2628387,36.8389782 45.5115266,37.1220307 44.6798291,37.296757 C43.8481316,37.4714834 42.6704935,37.5588453 41.1468796,37.5588453 L39.3856466,37.5588453 L30.2020747,37.5588453 C29.2795194,37.5588453 28.6190637,37.3771326 28.2206876,37.0137017 C27.8223114,36.6502709 27.6231264,36.0562101 27.6231264,35.2315017 C27.6231264,34.4906619 27.811828,33.9280514 28.189237,33.5436534 C28.5666459,33.1592554 29.118773,32.9670593 29.8456347,32.9670593 L30.2020747,32.9670593 L30.2020747,17.3256331 L29.8456347,17.3256331 C29.118773,17.3256331 28.5666459,17.1299425 28.189237,16.7385554 C27.811828,16.3471683 27.6231264,15.7740744 27.6231264,15.0192565 C27.6231264,14.2085262 27.8258059,13.6179599 28.2311711,13.24754 C28.6365363,12.8771201 29.2934976,12.691913 30.2020747,12.691913 L39.8469219,12.691913 C42.796303,12.691913 45.0362615,13.2650068 46.5668644,14.4112118 C48.0974674,15.5574168 48.8627574,17.2347648 48.8627574,19.443306 C48.8627574,20.5335986 48.6286276,21.4945792 48.1603609,22.3262767 C47.6920943,23.1579742 46.9966938,23.8393968 46.0741385,24.370565 L46.0741385,24.370565 Z M35.3809383,17.1998307 L35.3809383,22.4835296 L38.2114913,22.4835296 C39.9307988,22.4835296 41.1433816,22.2808501 41.8492761,21.8754849 C42.5551706,21.4701197 42.9081126,20.7852027 42.9081126,19.8207131 C42.9081126,18.912136 42.5901154,18.2481858 41.9541114,17.8288425 C41.3181074,17.4094992 40.2872373,17.1998307 38.8614701,17.1998307 L35.3809383,17.1998307 Z M71.244119,13.3838259 C71.5236812,12.880614 71.8102281,12.5241775 72.1037684,12.3145059 C72.3973087,12.1048342 72.7677231,12 73.2150226,12 C73.8999499,12 74.3856819,12.1817127 74.6722332,12.5451435 C74.9587844,12.9085744 75.1020579,13.5305909 75.1020579,14.4112118 L75.143992,19.8626472 C75.143992,20.8271368 74.9867406,21.4771091 74.6722332,21.8125837 C74.3577257,22.1480584 73.7881263,22.3157932 72.9634178,22.3157932 C72.3763372,22.3157932 71.92555,22.1760142 71.6110425,21.896452 C71.2965351,21.6168898 71.0274605,21.0997075 70.8038107,20.3448896 C70.4403799,19.0169692 69.8602971,18.0629775 69.0635448,17.482886 C68.2667926,16.9027945 67.1625385,16.612753 65.7507494,16.612753 C63.5981206,16.612753 61.9487284,17.3396038 60.8025235,18.7933272 C59.6563185,20.2470506 59.0832246,22.3507245 59.0832246,25.104412 C59.0832246,27.8441215 59.6633074,29.9477954 60.8234905,31.4154969 C61.9836736,32.8831984 63.6400547,33.6170381 65.7926836,33.6170381 C67.2603851,33.6170381 68.878327,33.1278116 70.6465578,32.149344 C72.4147886,31.1708763 73.5295261,30.6816498 73.9908037,30.6816498 C74.53595,30.6816498 74.9937262,30.9122852 75.3641461,31.3735628 C75.734566,31.8348404 75.9197732,32.4079343 75.9197732,33.0928616 C75.9197732,34.3229353 74.836486,35.4831009 72.669879,36.5733935 C70.5032721,37.663686 68.0641285,38.2088241 65.3523753,38.2088241 C61.6901107,38.2088241 58.7267959,36.9997358 56.4623422,34.5815228 C54.1978885,32.1633099 53.0656786,29.0043046 53.0656786,25.104412 C53.0656786,21.3443006 54.2118664,18.22024 56.5042763,15.7321366 C58.7966863,13.2440331 61.7040894,12 65.226573,12 C66.2190187,12 67.1974717,12.1118232 68.1619613,12.3354729 C69.1264508,12.5591227 70.1538264,12.9085702 71.244119,13.3838259 L71.244119,13.3838259 Z M81.4645862,32.9670593 L81.4645862,17.3256331 L81.1081461,17.3256331 C80.3533282,17.3256331 79.7802344,17.1299425 79.3888473,16.7385554 C78.9974602,16.3471683 78.8017696,15.7740744 78.8017696,15.0192565 C78.8017696,14.2085262 79.0114381,13.6179599 79.4307814,13.24754 C79.8501247,12.8771201 80.5280528,12.691913 81.4645862,12.691913 L85.4063933,12.691913 L86.6434498,12.691913 C89.5648747,12.691913 91.7034933,12.8177141 93.0593699,13.06932 C94.4152465,13.320926 95.5684233,13.740263 96.5189347,14.3273436 C98.210286,15.3337675 99.5067362,16.7699967 100.408324,18.6360743 C101.309912,20.5021519 101.7607,22.6582429 101.7607,25.104412 C101.7607,27.6903623 101.247012,29.9512876 100.219621,31.8872557 C99.1922296,33.8232239 97.7350336,35.2874089 95.8479888,36.2798546 C94.9953241,36.7271541 93.9959043,37.0521403 92.8496993,37.2548229 C91.7034944,37.4575055 89.9981906,37.5588453 87.7337369,37.5588453 L85.4063933,37.5588453 L81.4645862,37.5588453 C80.5000966,37.5588453 79.8151795,37.380627 79.4098143,37.0241852 C79.0044492,36.6677435 78.8017696,36.0701882 78.8017696,35.2315017 C78.8017696,34.4906619 78.9974602,33.9280514 79.3888473,33.5436534 C79.7802344,33.1592554 80.3533282,32.9670593 81.1081461,32.9670593 L81.4645862,32.9670593 Z M86.8740874,17.2417648 L86.8740874,32.9670593 L88.0692098,32.9670593 C90.7110725,32.9670593 92.6609895,32.3205814 93.9190194,31.0276063 C95.1770492,29.7346312 95.8060547,27.7462749 95.8060547,25.0624779 C95.8060547,22.4206153 95.1665658,20.4497314 93.8875688,19.1497672 C92.6085718,17.849803 90.6831161,17.1998307 88.1111439,17.1998307 C87.7756693,17.1998307 87.5205727,17.2033252 87.3458463,17.2103142 C87.1711199,17.2173033 87.0138685,17.2277867 86.8740874,17.2417648 L86.8740874,17.2417648 Z M121.94052,17.1159625 L112.190837,17.1159625 L112.190837,22.4835296 L115.88104,22.4835296 L115.88104,22.2319249 C115.88104,21.4351727 116.055763,20.841112 116.405216,20.4497249 C116.754669,20.0583378 117.285829,19.8626472 117.998713,19.8626472 C118.627728,19.8626472 119.141415,20.0408655 119.539792,20.3973072 C119.938168,20.753749 120.137353,21.2045363 120.137353,21.7496826 C120.137353,21.7776388 120.144342,21.8684951 120.15832,22.0222543 C120.172298,22.1760135 120.179287,22.3297704 120.179287,22.4835296 L120.179287,26.8237109 C120.179287,27.7602442 120.011552,28.4311834 119.676077,28.8365486 C119.340603,29.2419138 118.795465,29.4445933 118.040647,29.4445933 C117.327763,29.4445933 116.789614,29.2558917 116.426183,28.8784827 C116.062752,28.5010738 115.88104,27.9419578 115.88104,27.201118 L115.88104,26.8237109 L112.190837,26.8237109 L112.190837,33.0928616 L121.94052,33.0928616 L121.94052,30.5977816 C121.94052,29.6612482 122.118738,28.9903091 122.47518,28.5849439 C122.831622,28.1795787 123.415199,27.9768992 124.225929,27.9768992 C125.022682,27.9768992 125.592281,28.1760842 125.934745,28.5744604 C126.277208,28.9728365 126.448438,29.6472701 126.448438,30.5977816 L126.448438,35.6718099 C126.448438,36.4266278 126.30167,36.9298322 126.008129,37.1814382 C125.714589,37.4330442 125.134506,37.5588453 124.267863,37.5588453 L107.095842,37.5588453 C106.173287,37.5588453 105.512831,37.3771326 105.114455,37.0137017 C104.716079,36.6502709 104.516894,36.0562101 104.516894,35.2315017 C104.516894,34.4906619 104.705595,33.9280514 105.083004,33.5436534 C105.460413,33.1592554 106.01254,32.9670593 106.739402,32.9670593 L107.095842,32.9670593 L107.095842,17.3256331 L106.739402,17.3256331 C106.026518,17.3256331 105.477886,17.126448 105.093488,16.7280719 C104.70909,16.3296957 104.516894,15.7600963 104.516894,15.0192565 C104.516894,14.2085262 104.719573,13.6179599 105.124938,13.24754 C105.530304,12.8771201 106.187265,12.691913 107.095842,12.691913 L124.267863,12.691913 C125.120528,12.691913 125.697116,12.8212085 125.997646,13.0798036 C126.298175,13.3383986 126.448438,13.8520864 126.448438,14.6208824 L126.448438,19.3175037 C126.448438,20.2680151 126.273714,20.9494377 125.924261,21.361792 C125.574808,21.7741462 125.008703,21.9803202 124.225929,21.9803202 C123.415199,21.9803202 122.831622,21.7706517 122.47518,21.3513084 C122.118738,20.9319652 121.94052,20.254037 121.94052,19.3175037 L121.94052,17.1159625 Z M19.7719369,47.6405477 C20.037521,47.1373358 20.3205734,46.7808993 20.6211028,46.5712277 C20.9216322,46.361556 21.295541,46.2567218 21.7428405,46.2567218 C22.4277678,46.2567218 22.9134998,46.4384345 23.2000511,46.8018653 C23.4866023,47.1652962 23.6298758,47.7873127 23.6298758,48.6679336 L23.6718099,54.119369 C23.6718099,55.0838586 23.5145586,55.7338309 23.2000511,56.0693055 C22.8855436,56.4047802 22.3089553,56.572515 21.4702687,56.572515 C20.8831881,56.572515 20.4254119,56.4292415 20.0969263,56.1426902 C19.7684407,55.856139 19.4993662,55.3424512 19.2896945,54.6016114 C18.9122856,53.2597129 18.3322027,52.3022267 17.5494286,51.7291243 C16.7666545,51.1560218 15.6693894,50.8694748 14.2576003,50.8694748 C12.1049715,50.8694748 10.4590738,51.5963256 9.31985785,53.050049 C8.18064193,54.5037724 7.61104252,56.6074463 7.61104252,59.3611338 C7.61104252,62.1148214 8.20859773,64.2429566 9.40372609,65.7456034 C10.5988544,67.2482501 12.2936748,67.9995623 14.488238,67.9995623 C14.9914499,67.9995623 15.5645438,67.9401562 16.2075368,67.8213423 C16.8505299,67.7025283 17.6053364,67.5173212 18.4719792,67.2657152 L18.4719792,63.9529198 L16.1027015,63.9529198 C15.1521901,63.9529198 14.4777564,63.7781961 14.0793803,63.4287433 C13.6810042,63.0792906 13.4818191,62.4992078 13.4818191,61.6884774 C13.4818191,60.8497908 13.6810042,60.2522356 14.0793803,59.8957938 C14.4777564,59.5393521 15.1521901,59.3611338 16.1027015,59.3611338 L23.6718099,59.3611338 C24.6502776,59.3611338 25.3386891,59.5358576 25.7370653,59.8853103 C26.1354414,60.2347631 26.3346265,60.8218348 26.3346265,61.6465433 C26.3346265,62.3873831 26.1354414,62.9569825 25.7370653,63.3553586 C25.3386891,63.7537347 24.7621008,63.9529198 24.0072829,63.9529198 L23.6718099,63.9529198 L23.6718099,68.9430799 L23.6718099,69.1946846 C23.6718099,69.6419841 23.6228873,69.9529924 23.5250405,70.1277188 C23.4271937,70.3024451 23.2315031,70.4806634 22.9379628,70.6623788 C22.1412106,71.1376345 20.8762107,71.5569715 19.1429251,71.9204023 C17.4096396,72.2838332 15.6554131,72.4655459 13.8801932,72.4655459 C10.2179286,72.4655459 7.25461383,71.2564576 4.99016011,68.8382446 C2.72570638,66.4200317 1.59349651,63.2610264 1.59349651,59.3611338 C1.59349651,55.6010224 2.73968428,52.4769618 5.03209423,49.9888583 C7.32450417,47.5007549 10.2319073,46.2567218 13.7543909,46.2567218 C14.7328585,46.2567218 15.7078171,46.368545 16.6792957,46.5921947 C17.6507743,46.8158445 18.6816444,47.165292 19.7719369,47.6405477 L19.7719369,47.6405477 Z M35.611576,51.5823548 L35.611576,56.4047785 L42.4678043,56.4047785 L42.4678043,51.5823548 L42.1323314,51.5823548 C41.3775135,51.5823548 40.8009251,51.3866642 40.402549,50.9952772 C40.0041729,50.6038901 39.8049878,50.0307962 39.8049878,49.2759783 C39.8049878,48.4512699 40.0111618,47.8572091 40.4235161,47.4937783 C40.8358703,47.1303474 41.5172929,46.9486347 42.4678043,46.9486347 L47.8773056,46.9486347 C48.8278171,46.9486347 49.5022507,47.1303474 49.9006269,47.4937783 C50.299003,47.8572091 50.498188,48.4512699 50.498188,49.2759783 C50.498188,50.0307962 50.3059919,50.6038901 49.9215939,50.9952772 C49.5371959,51.3866642 48.9745854,51.5823548 48.2337456,51.5823548 L47.8773056,51.5823548 L47.8773056,67.2237811 L48.2337456,67.2237811 C48.9885636,67.2237811 49.5616574,67.4159772 49.9530445,67.8003752 C50.3444316,68.1847732 50.5401222,68.7473837 50.5401222,69.4882235 C50.5401222,70.3129319 50.3374426,70.9069927 49.9320774,71.2704235 C49.5267123,71.6338543 48.8417952,71.815567 47.8773056,71.815567 L42.4678043,71.815567 C41.5033148,71.815567 40.8183977,71.6373488 40.4130325,71.280907 C40.0076674,70.9244652 39.8049878,70.32691 39.8049878,69.4882235 C39.8049878,68.7473837 40.0041729,68.1847732 40.402549,67.8003752 C40.8009251,67.4159772 41.3775135,67.2237811 42.1323314,67.2237811 L42.4678043,67.2237811 L42.4678043,61.0384986 L35.611576,61.0384986 L35.611576,67.2237811 L35.9470489,67.2237811 C36.7018668,67.2237811 37.2784552,67.4159772 37.6768313,67.8003752 C38.0752074,68.1847732 38.2743925,68.7473837 38.2743925,69.4882235 C38.2743925,70.3129319 38.0682185,70.9069927 37.6558642,71.2704235 C37.24351,71.6338543 36.5620874,71.815567 35.611576,71.815567 L30.2020747,71.815567 C29.2375851,71.815567 28.552668,71.6373488 28.1473029,71.280907 C27.7419377,70.9244652 27.5392581,70.32691 27.5392581,69.4882235 C27.5392581,68.7473837 27.7349487,68.1847732 28.1263358,67.8003752 C28.5177229,67.4159772 29.0908168,67.2237811 29.8456347,67.2237811 L30.2020747,67.2237811 L30.2020747,51.5823548 L29.8456347,51.5823548 C29.1047949,51.5823548 28.5421844,51.3866642 28.1577864,50.9952772 C27.7733884,50.6038901 27.5811923,50.0307962 27.5811923,49.2759783 C27.5811923,48.4512699 27.7803773,47.8572091 28.1787534,47.4937783 C28.5771296,47.1303474 29.2515632,46.9486347 30.2020747,46.9486347 L35.611576,46.9486347 C36.5481093,46.9486347 37.2260374,47.1303474 37.6453807,47.4937783 C38.064724,47.8572091 38.2743925,48.4512699 38.2743925,49.2759783 C38.2743925,50.0307962 38.0752074,50.6038901 37.6768313,50.9952772 C37.2784552,51.3866642 36.7018668,51.5823548 35.9470489,51.5823548 L35.611576,51.5823548 Z M67.365213,51.5823548 L67.365213,67.2237811 L70.887679,67.2237811 C71.8381904,67.2237811 72.519613,67.4019993 72.9319673,67.7584411 C73.3443215,68.1148829 73.5504955,68.6914712 73.5504955,69.4882235 C73.5504955,70.2989538 73.340827,70.8895201 72.9214837,71.25994 C72.5021404,71.6303599 71.8242123,71.815567 70.887679,71.815567 L58.4332458,71.815567 C57.4827343,71.815567 56.8013117,71.6338543 56.3889575,71.2704235 C55.9766033,70.9069927 55.7704292,70.3129319 55.7704292,69.4882235 C55.7704292,68.6774931 55.9731088,68.0974103 56.378474,67.7479575 C56.7838391,67.3985048 57.4687562,67.2237811 58.4332458,67.2237811 L61.9557117,67.2237811 L61.9557117,51.5823548 L58.4332458,51.5823548 C57.4827343,51.5823548 56.8013117,51.4006421 56.3889575,51.0372113 C55.9766033,50.6737805 55.7704292,50.0867087 55.7704292,49.2759783 C55.7704292,48.4512699 55.9731088,47.8641981 56.378474,47.5147453 C56.7838391,47.1652926 57.4687562,46.9905689 58.4332458,46.9905689 L70.887679,46.9905689 C71.8801247,46.9905689 72.5720308,47.1652926 72.9634178,47.5147453 C73.3548049,47.8641981 73.5504955,48.4512699 73.5504955,49.2759783 C73.5504955,50.0867087 73.347816,50.6737805 72.9424508,51.0372113 C72.5370856,51.4006421 71.8521685,51.5823548 70.887679,51.5823548 L67.365213,51.5823548 Z M97.8608265,51.5823548 L97.8608265,63.1771386 L97.8608265,63.5755127 C97.8608265,65.4485794 97.7385199,66.8044357 97.493903,67.6431222 C97.2492861,68.4818088 96.8404325,69.2296264 96.26733,69.8865976 C95.5264902,70.7392623 94.4991146,71.3822457 93.1851723,71.815567 C91.87123,72.2488884 90.2917273,72.4655459 88.4466169,72.4655459 C87.1466527,72.4655459 85.8921362,72.3397448 84.6830298,72.0881388 C83.4739233,71.8365328 82.3102631,71.4591296 81.1920144,70.9559176 C80.5769776,70.6763554 80.175113,70.31293 79.9864085,69.8656305 C79.797704,69.418331 79.7033532,68.6914802 79.7033532,67.6850564 L79.7033532,63.3658422 C79.7033532,62.1637247 79.8780769,61.3250508 80.2275297,60.849795 C80.5769824,60.3745393 81.185021,60.136915 82.0516638,60.136915 C83.2957156,60.136915 83.9806326,61.0524675 84.1064356,62.8835998 C84.1204137,63.2050963 84.1413806,63.4497096 84.1693368,63.6174469 C84.3370741,65.2389076 84.7144774,66.3466561 85.301558,66.9407258 C85.8886386,67.5347954 86.8251579,67.8318258 88.1111439,67.8318258 C89.7046484,67.8318258 90.8263749,67.4089943 91.476357,66.5633187 C92.126339,65.7176431 92.4513252,64.1765796 92.4513252,61.9400821 L92.4513252,51.5823548 L88.9288593,51.5823548 C87.9783478,51.5823548 87.2969252,51.4006421 86.884571,51.0372113 C86.4722168,50.6737805 86.2660427,50.0867087 86.2660427,49.2759783 C86.2660427,48.4512699 86.4652278,47.8641981 86.8636039,47.5147453 C87.26198,47.1652926 87.9503916,46.9905689 88.9288593,46.9905689 L99.6220595,46.9905689 C100.600527,46.9905689 101.288939,47.1652926 101.687315,47.5147453 C102.085691,47.8641981 102.284876,48.4512699 102.284876,49.2759783 C102.284876,50.0867087 102.078702,50.6737805 101.666348,51.0372113 C101.253994,51.4006421 100.572571,51.5823548 99.6220595,51.5823548 L97.8608265,51.5823548 Z M112.505343,51.5823548 L112.505343,57.9353738 L118.984165,51.4565525 C118.257303,51.3726838 117.747109,51.1665098 117.453569,50.8380242 C117.160029,50.5095387 117.013261,49.9888619 117.013261,49.2759783 C117.013261,48.4512699 117.212446,47.8572091 117.610822,47.4937783 C118.009198,47.1303474 118.683632,46.9486347 119.634143,46.9486347 L124.771073,46.9486347 C125.721584,46.9486347 126.396018,47.1303474 126.794394,47.4937783 C127.19277,47.8572091 127.391955,48.4512699 127.391955,49.2759783 C127.391955,50.0447743 127.19277,50.6213627 126.794394,51.0057607 C126.396018,51.3901587 125.812441,51.5823548 125.043645,51.5823548 L124.561402,51.5823548 L118.459988,57.641835 C119.592215,58.4805215 120.626579,59.5812811 121.563113,60.9441468 C122.499646,62.3070125 123.596911,64.400203 124.854941,67.2237811 L125.127513,67.2237811 L125.546854,67.2237811 C126.371563,67.2237811 126.98659,67.4124827 127.391955,67.7898917 C127.79732,68.1673006 128,68.7334056 128,69.4882235 C128,70.3129319 127.793826,70.9069927 127.381472,71.2704235 C126.969118,71.6338543 126.287695,71.815567 125.337183,71.815567 L122.758235,71.815567 C121.626008,71.815567 120.710456,71.0537715 120.01155,69.5301576 C119.885747,69.2505954 119.787902,69.026949 119.718012,68.8592117 C118.795456,66.9022764 117.949793,65.3926632 117.180997,64.3303269 C116.412201,63.2679906 115.510627,62.2965265 114.476247,61.4159056 L112.505343,63.302941 L112.505343,67.2237811 L112.840816,67.2237811 C113.595634,67.2237811 114.172222,67.4159772 114.570599,67.8003752 C114.968975,68.1847732 115.16816,68.7473837 115.16816,69.4882235 C115.16816,70.3129319 114.961986,70.9069927 114.549631,71.2704235 C114.137277,71.6338543 113.455855,71.815567 112.505343,71.815567 L107.095842,71.815567 C106.131352,71.815567 105.446435,71.6373488 105.04107,71.280907 C104.635705,70.9244652 104.433025,70.32691 104.433025,69.4882235 C104.433025,68.7473837 104.628716,68.1847732 105.020103,67.8003752 C105.41149,67.4159772 105.984584,67.2237811 106.739402,67.2237811 L107.095842,67.2237811 L107.095842,51.5823548 L106.739402,51.5823548 C105.998562,51.5823548 105.435952,51.3866642 105.051554,50.9952772 C104.667156,50.6038901 104.474959,50.0307962 104.474959,49.2759783 C104.474959,48.4512699 104.674145,47.8572091 105.072521,47.4937783 C105.470897,47.1303474 106.14533,46.9486347 107.095842,46.9486347 L112.505343,46.9486347 C113.441877,46.9486347 114.119805,47.1303474 114.539148,47.4937783 C114.958491,47.8572091 115.16816,48.4512699 115.16816,49.2759783 C115.16816,50.0307962 114.968975,50.6038901 114.570599,50.9952772 C114.172222,51.3866642 113.595634,51.5823548 112.840816,51.5823548 L112.505343,51.5823548 Z M13.439885,96.325622 L17.4445933,84.4372993 C17.6961993,83.6545252 18.0456468,83.0849258 18.4929463,82.728484 C18.9402458,82.3720422 19.5343065,82.193824 20.2751463,82.193824 L23.5460076,82.193824 C24.496519,82.193824 25.1779416,82.3755367 25.5902958,82.7389675 C26.0026501,83.1023984 26.2088241,83.6964591 26.2088241,84.5211676 C26.2088241,85.2759855 26.009639,85.8490794 25.6112629,86.2404664 C25.2128868,86.6318535 24.6362984,86.8275441 23.8814805,86.8275441 L23.5460076,86.8275441 L24.1330852,102.46897 L24.4895252,102.46897 C25.2443431,102.46897 25.8104481,102.661166 26.187857,103.045564 C26.565266,103.429962 26.7539676,103.992573 26.7539676,104.733413 C26.7539676,105.558121 26.5547826,106.152182 26.1564064,106.515613 C25.7580303,106.879044 25.0835967,107.060756 24.1330852,107.060756 L19.4154969,107.060756 C18.4649855,107.060756 17.7905518,106.882538 17.3921757,106.526096 C16.9937996,106.169654 16.7946145,105.572099 16.7946145,104.733413 C16.7946145,103.992573 16.9868106,103.429962 17.3712086,103.045564 C17.7556066,102.661166 18.325206,102.46897 19.0800239,102.46897 L19.4154969,102.46897 L19.1219581,89.6790642 L16.0607674,99.1981091 C15.8371177,99.9109927 15.5191204,100.42468 15.1067662,100.739188 C14.694412,101.053695 14.1248126,101.210947 13.3979509,101.210947 C12.6710892,101.210947 12.0945008,101.053695 11.6681685,100.739188 C11.2418362,100.42468 10.91685,99.9109927 10.6932002,99.1981091 L7.65297664,89.6790642 L7.35943781,102.46897 L7.69491075,102.46897 C8.44972866,102.46897 9.01932808,102.661166 9.40372609,103.045564 C9.78812409,103.429962 9.98032022,103.992573 9.98032022,104.733413 C9.98032022,105.558121 9.77764067,106.152182 9.3722755,106.515613 C8.96691032,106.879044 8.29597114,107.060756 7.35943781,107.060756 L2.62088241,107.060756 C1.68434908,107.060756 1.01340989,106.879044 0.608044719,106.515613 C0.202679546,106.152182 0,105.558121 0,104.733413 C0,103.992573 0.192196121,103.429962 0.57659413,103.045564 C0.960992139,102.661166 1.53059155,102.46897 2.28540946,102.46897 L2.62088241,102.46897 L3.22892713,86.8275441 L2.89345418,86.8275441 C2.13863627,86.8275441 1.56204791,86.6318535 1.16367179,86.2404664 C0.765295672,85.8490794 0.5661106,85.2759855 0.5661106,84.5211676 C0.5661106,83.6964591 0.772284622,83.1023984 1.18463885,82.7389675 C1.59699308,82.3755367 2.27841569,82.193824 3.22892713,82.193824 L6.49978838,82.193824 C7.22665007,82.193824 7.81022738,82.3685477 8.25053783,82.7180005 C8.69084827,83.0674532 9.05077919,83.6405471 9.33034138,84.4372993 L13.439885,96.325622 Z M43.8935644,98.3803938 L43.8935644,86.8275441 L42.7403761,86.8275441 C41.8178209,86.8275441 41.1573651,86.6458314 40.758989,86.2824006 C40.3606129,85.9189697 40.1614278,85.3318979 40.1614278,84.5211676 C40.1614278,83.7104372 40.3606129,83.119871 40.758989,82.7494511 C41.1573651,82.3790312 41.8178209,82.193824 42.7403761,82.193824 L48.6950209,82.193824 C49.6035981,82.193824 50.2605593,82.3790312 50.6659245,82.7494511 C51.0712897,83.119871 51.2739692,83.7104372 51.2739692,84.5211676 C51.2739692,85.2620074 51.0817731,85.8316068 50.6973751,86.2299829 C50.3129771,86.628359 49.7643445,86.8275441 49.051461,86.8275441 L48.6950209,86.8275441 L48.6950209,105.865634 C48.6950209,106.522605 48.6251315,106.934953 48.4853504,107.10269 C48.3455693,107.270428 48.0310665,107.354295 47.5418327,107.354295 L45.4451268,107.354295 C44.7741775,107.354295 44.3024234,107.284406 44.0298503,107.144625 C43.7572771,107.004843 43.5231473,106.76023 43.3274538,106.410777 L34.6051571,91.0838571 L34.6051571,102.46897 L35.8212466,102.46897 C36.7298237,102.46897 37.379796,102.643694 37.7711831,102.993147 C38.1625701,103.3426 38.3582607,103.922682 38.3582607,104.733413 C38.3582607,105.558121 38.1590757,106.152182 37.7606995,106.515613 C37.3623234,106.879044 36.7158456,107.060756 35.8212466,107.060756 L29.8037005,107.060756 C28.8951234,107.060756 28.2381621,106.879044 27.832797,106.515613 C27.4274318,106.152182 27.2247522,105.558121 27.2247522,104.733413 C27.2247522,103.992573 27.4134539,103.429962 27.7908629,103.045564 C28.1682718,102.661166 28.7273878,102.46897 29.4682276,102.46897 L29.8037005,102.46897 L29.8037005,86.8275441 L29.4682276,86.8275441 C28.755344,86.8275441 28.203217,86.628359 27.8118299,86.2299829 C27.4204428,85.8316068 27.2247522,85.2620074 27.2247522,84.5211676 C27.2247522,83.7104372 27.4309263,83.119871 27.8432805,82.7494511 C28.2556347,82.3790312 28.9091015,82.193824 29.8037005,82.193824 L33.2422983,82.193824 C34.0670067,82.193824 34.6261227,82.3021527 34.919663,82.5188134 C35.2132033,82.7354741 35.5416839,83.1722835 35.9051148,83.8292546 L43.8935644,98.3803938 Z M64.6604624,86.3662688 C62.8572863,86.3662688 61.4420239,87.0931196 60.4146329,88.546843 C59.3872418,90.0005663 58.873554,92.0203728 58.873554,94.6063231 C58.873554,97.1922733 59.3907363,99.2190688 60.4251164,100.68677 C61.4594965,102.154472 62.8712644,102.888312 64.6604624,102.888312 C66.4636385,102.888312 67.8823953,102.157966 68.9167754,100.697254 C69.9511555,99.2365414 70.4683378,97.2062514 70.4683378,94.6063231 C70.4683378,92.0203728 69.95465,90.0005663 68.9272589,88.546843 C67.8998679,87.0931196 66.4776166,86.3662688 64.6604624,86.3662688 L64.6604624,86.3662688 Z M64.6604624,81.501911 C68.0990773,81.501911 70.929602,82.7319662 73.1521214,85.1921135 C75.3746408,87.6522607 76.4858838,90.7902992 76.4858838,94.6063231 C76.4858838,98.4503032 75.3816297,101.595331 73.1730884,104.0415 C70.9645471,106.487669 68.1270335,107.710735 64.6604624,107.710735 C61.2358256,107.710735 58.4053009,106.477185 56.1688034,104.010049 C53.9323059,101.542913 52.8140739,98.4083688 52.8140739,94.6063231 C52.8140739,90.7763211 53.9218224,87.6347881 56.1373528,85.1816299 C58.3528831,82.7284717 61.1938912,81.501911 64.6604624,81.501911 L64.6604624,81.501911 Z M87.4611651,98.1707232 L87.4611651,102.46897 L89.6207722,102.46897 C90.5293493,102.46897 91.1758272,102.643694 91.5602252,102.993147 C91.9446232,103.3426 92.1368193,103.922682 92.1368193,104.733413 C92.1368193,105.558121 91.9411287,106.152182 91.5497417,106.515613 C91.1583546,106.879044 90.5153712,107.060756 89.6207722,107.060756 L82.3661697,107.060756 C81.4436145,107.060756 80.7831587,106.879044 80.3847826,106.515613 C79.9864065,106.152182 79.7872214,105.558121 79.7872214,104.733413 C79.7872214,103.992573 79.9759231,103.429962 80.353332,103.045564 C80.730741,102.661166 81.282868,102.46897 82.0097297,102.46897 L82.3661697,102.46897 L82.3661697,86.8275441 L82.0097297,86.8275441 C81.2968461,86.8275441 80.7482136,86.628359 80.3638155,86.2299829 C79.9794175,85.8316068 79.7872214,85.2620074 79.7872214,84.5211676 C79.7872214,83.7104372 79.989901,83.119871 80.3952661,82.7494511 C80.8006313,82.3790312 81.4575926,82.193824 82.3661697,82.193824 L91.0255652,82.193824 C94.450202,82.193824 97.0396079,82.8507853 98.7938606,84.1647276 C100.548113,85.4786699 101.425227,87.414609 101.425227,89.972603 C101.425227,92.6703781 100.551608,94.7111515 98.8043442,96.0949843 C97.0570805,97.4788171 94.4641801,98.1707232 91.0255652,98.1707232 L87.4611651,98.1707232 Z M87.4611651,86.8275441 L87.4611651,93.4531348 L90.4384875,93.4531348 C92.0879044,93.4531348 93.328443,93.1735768 94.1601405,92.6144525 C94.9918381,92.0553281 95.4076806,91.2166541 95.4076806,90.0984053 C95.4076806,89.0500471 94.9778602,88.2428234 94.1182064,87.67671 C93.2585527,87.1105966 92.031992,86.8275441 90.4384875,86.8275441 L87.4611651,86.8275441 Z M114.727851,107.396229 L113.092421,109.03166 C113.69348,108.835966 114.284046,108.689198 114.864137,108.591352 C115.444229,108.493505 116.013828,108.444582 116.572953,108.444582 C117.677223,108.444582 118.840883,108.608823 120.063968,108.937308 C121.287053,109.265794 122.031376,109.430034 122.29696,109.430034 C122.744259,109.430034 123.327837,109.279772 124.047709,108.979242 C124.767582,108.678713 125.253314,108.52845 125.50492,108.52845 C126.02211,108.52845 126.45193,108.727636 126.794394,109.126012 C127.136858,109.524388 127.308087,110.024098 127.308087,110.625156 C127.308087,111.421909 126.836333,112.099837 125.892811,112.658961 C124.949288,113.218086 123.792617,113.497643 122.422762,113.497643 C121.486229,113.497643 120.28413,113.277492 118.816428,112.837181 C117.348727,112.396871 116.286406,112.176719 115.629435,112.176719 C114.636989,112.176719 113.518757,112.449288 112.274706,112.994434 C111.030654,113.53958 110.261869,113.812149 109.968329,113.812149 C109.36727,113.812149 108.857077,113.612964 108.437734,113.214588 C108.01839,112.816212 107.808722,112.337469 107.808722,111.778345 C107.808722,111.386958 107.941512,110.971115 108.207096,110.530805 C108.47268,110.090494 108.94094,109.520895 109.611889,108.821989 L111.729562,106.683349 C109.395218,105.830685 107.536157,104.29661 106.152324,102.08108 C104.768491,99.8655494 104.076585,97.3180772 104.076585,94.4385866 C104.076585,90.6365409 105.180839,87.5299526 107.389381,85.1187288 C109.597922,82.7075049 112.442425,81.501911 115.922974,81.501911 C119.389545,81.501911 122.227059,82.7109994 124.4356,85.1292123 C126.644141,87.5474252 127.748395,90.650519 127.748395,94.4385866 C127.748395,98.2126762 126.65113,101.322759 124.456567,103.768928 C122.262004,106.215097 119.480402,107.438163 116.111677,107.438163 C115.888028,107.438163 115.660887,107.434669 115.430248,107.42768 C115.199609,107.420691 114.965479,107.410207 114.727851,107.396229 L114.727851,107.396229 Z M115.922974,86.3662688 C114.119798,86.3662688 112.704535,87.0931196 111.677144,88.546843 C110.649753,90.0005663 110.136065,92.0203728 110.136065,94.6063231 C110.136065,97.1922733 110.653248,99.2190688 111.687628,100.68677 C112.722008,102.154472 114.133776,102.888312 115.922974,102.888312 C117.72615,102.888312 119.144907,102.157966 120.179287,100.697254 C121.213667,99.2365414 121.730849,97.2062514 121.730849,94.6063231 C121.730849,92.0203728 121.217161,90.0005663 120.18977,88.546843 C119.162379,87.0931196 117.740128,86.3662688 115.922974,86.3662688 L115.922974,86.3662688 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/mono-line": { "title": "$:/core/images/mono-line", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-mono-line tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M60.4374591,84.522627 L61.3450888,84.522627 C63.2671377,84.522627 64.7264493,85.0120303 65.7230673,85.9908515 C66.7196852,86.9696727 67.2179868,88.4022896 67.2179868,90.288745 C67.2179868,92.3887615 66.6929905,93.9014625 65.6429823,94.8268935 C64.5929741,95.7523244 62.857817,96.215033 60.4374591,96.215033 L44.3670747,96.215033 C41.9111232,96.215033 40.1670679,95.7612227 39.1348565,94.8535884 C38.102645,93.9459542 37.586547,92.424355 37.586547,90.288745 C37.586547,88.2243221 38.102645,86.747214 39.1348565,85.8573766 C40.1670679,84.9675391 41.9111232,84.522627 44.3670747,84.522627 L46.235724,84.522627 L44.0467348,78.2759992 L20.9822627,78.2759992 L18.6864935,84.522627 L20.5551429,84.522627 C22.9755008,84.522627 24.7106579,84.9764373 25.7606661,85.8840716 C26.8106743,86.7917058 27.3356705,88.2599156 27.3356705,90.288745 C27.3356705,92.3887615 26.8106743,93.9014625 25.7606661,94.8268935 C24.7106579,95.7523244 22.9755008,96.215033 20.5551429,96.215033 L6.78052766,96.215033 C4.32457622,96.215033 2.58052094,95.7523244 1.54830946,94.8268935 C0.516097994,93.9014625 0,92.3887615 0,90.288745 C0,88.4022896 0.498301511,86.9696727 1.49491948,85.9908515 C2.49153745,85.0120303 3.95084902,84.522627 5.87289797,84.522627 L6.78052766,84.522627 L21.0890427,44.6937008 L16.8178442,44.6937008 C14.3974863,44.6937008 12.6623292,44.2309922 11.612321,43.3055613 C10.5623128,42.3801303 10.0373165,40.8852258 10.0373165,38.8208028 C10.0373165,36.7207864 10.5623128,35.2080854 11.612321,34.2826544 C12.6623292,33.3572234 14.3974863,32.8945149 16.8178442,32.8945149 L36.8390873,32.8945149 C40.0069087,32.8945149 42.231469,34.6029772 43.512835,38.0199531 L43.512835,38.180123 L60.4374591,84.522627 Z M32.4611088,44.6937008 L24.7195615,67.224273 L40.2026561,67.224273 L32.4611088,44.6937008 Z M89.5058233,68.5590225 L89.5058233,84.8429669 L97.5143205,84.8429669 C103.173687,84.8429669 107.160099,84.22009 109.473676,82.9743176 C111.787254,81.7285451 112.944025,79.6463566 112.944025,76.7276897 C112.944025,73.7734293 111.840643,71.6734444 109.633846,70.4276719 C107.427049,69.1818994 103.565213,68.5590225 98.0482204,68.5590225 L89.5058233,68.5590225 Z M116.734714,62.6327346 C120.614405,64.0564746 123.461842,66.0051894 125.277111,68.4789376 C127.092379,70.9526857 128,74.1115614 128,77.9556593 C128,81.1946677 127.216955,84.1488838 125.650841,86.8183962 C124.084727,89.4879087 121.84237,91.676876 118.923703,93.385364 C117.215215,94.3819819 115.302093,95.1027395 113.18428,95.5476582 C111.066467,95.9925769 108.06776,96.215033 104.188068,96.215033 L99.7033098,96.215033 L76.3184979,96.215033 C73.9693269,96.215033 72.2875593,95.7523244 71.2731446,94.8268935 C70.2587299,93.9014625 69.7515301,92.3887615 69.7515301,90.288745 C69.7515301,88.4022896 70.2320352,86.9696727 71.1930596,85.9908515 C72.1540841,85.0120303 73.5600062,84.522627 75.4108682,84.522627 L76.3184979,84.522627 L76.3184979,44.6937008 L75.4108682,44.6937008 C73.5600062,44.6937008 72.1540841,44.1953993 71.1930596,43.1987813 C70.2320352,42.2021633 69.7515301,40.7428518 69.7515301,38.8208028 C69.7515301,36.7563799 70.2676281,35.2525771 71.2998396,34.3093494 C72.3320511,33.3661217 74.0049204,32.8945149 76.3184979,32.8945149 L100.877889,32.8945149 C108.388118,32.8945149 114.09189,34.3538264 117.989378,37.2724934 C121.886867,40.1911603 123.835581,44.4623161 123.835581,50.0860889 C123.835581,52.8623819 123.239399,55.3093982 122.047017,57.4272114 C120.854635,59.5450246 119.083885,61.2801816 116.734714,62.6327346 L116.734714,62.6327346 Z M89.5058233,44.3733609 L89.5058233,57.8276363 L96.7134708,57.8276363 C101.091471,57.8276363 104.179161,57.3115383 105.976633,56.2793268 C107.774104,55.2471153 108.672827,53.50306 108.672827,51.0471086 C108.672827,48.7335312 107.863087,47.0428653 106.243583,45.9750604 C104.624078,44.9072554 101.999097,44.3733609 98.3685602,44.3733609 L89.5058233,44.3733609 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/new-button": { "title": "$:/core/images/new-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-new-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <g fill-rule=\"evenodd\">\n <path d=\"M56,72 L8.00697327,72 C3.59075293,72 0,68.418278 0,64 C0,59.5907123 3.58484404,56 8.00697327,56 L56,56 L56,8.00697327 C56,3.59075293 59.581722,0 64,0 C68.4092877,0 72,3.58484404 72,8.00697327 L72,56 L119.993027,56 C124.409247,56 128,59.581722 128,64 C128,68.4092877 124.415156,72 119.993027,72 L72,72 L72,119.993027 C72,124.409247 68.418278,128 64,128 C59.5907123,128 56,124.415156 56,119.993027 L56,72 L56,72 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/new-here-button": { "title": "$:/core/images/new-here-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-new-here-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n \t<g transform=\"translate(52.233611, 64.389922) rotate(75.000000) translate(-52.233611, -64.389922) translate(-7.734417, 3.702450)\">\n\t <path d=\"M18.9270186,45.959338 L18.9080585,49.6521741 C18.8884833,53.4648378 21.0574548,58.7482162 23.7526408,61.4434022 L78.5671839,116.257945 C81.2617332,118.952495 85.6348701,118.950391 88.3334363,116.251825 L115.863237,88.7220241 C118.555265,86.0299959 118.564544,81.6509578 115.869358,78.9557717 L61.0548144,24.1412286 C58.3602652,21.4466794 53.0787224,19.2788426 49.2595808,19.3006519 L25.9781737,19.4336012 C22.1633003,19.4553862 19.0471195,22.5673232 19.0275223,26.3842526 L18.9871663,34.2443819 C19.0818862,34.255617 19.1779758,34.2665345 19.2754441,34.2771502 C22.6891275,34.6489512 27.0485594,34.2348566 31.513244,33.2285542 C31.7789418,32.8671684 32.075337,32.5211298 32.4024112,32.1940556 C34.8567584,29.7397084 38.3789778,29.0128681 41.4406288,30.0213822 C41.5958829,29.9543375 41.7503946,29.8866669 41.9041198,29.8183808 L42.1110981,30.2733467 C43.1114373,30.6972371 44.0473796,31.3160521 44.8614145,32.1300869 C48.2842088,35.5528813 48.2555691,41.130967 44.7974459,44.5890903 C41.4339531,47.952583 36.0649346,48.0717177 32.6241879,44.9262969 C27.8170558,45.8919233 23.0726921,46.2881596 18.9270186,45.959338 Z\"></path>\n\t <path d=\"M45.4903462,38.8768094 C36.7300141,42.6833154 26.099618,44.7997354 18.1909048,43.9383587 C7.2512621,42.7468685 1.50150083,35.8404432 4.66865776,24.7010202 C7.51507386,14.6896965 15.4908218,6.92103848 24.3842626,4.38423012 C34.1310219,1.60401701 42.4070208,6.15882777 42.4070209,16.3101169 L34.5379395,16.310117 C34.5379394,11.9285862 31.728784,10.3825286 26.5666962,11.8549876 C20.2597508,13.6540114 14.3453742,19.4148216 12.2444303,26.8041943 C10.4963869,32.9523565 12.6250796,35.5092726 19.0530263,36.2093718 C25.5557042,36.9176104 35.0513021,34.9907189 42.7038419,31.5913902 L42.7421786,31.6756595 C44.3874154,31.5384763 47.8846101,37.3706354 45.9274416,38.6772897 L45.9302799,38.6835285 C45.9166992,38.6895612 45.9031139,38.6955897 45.8895238,38.7016142 C45.8389288,38.7327898 45.7849056,38.7611034 45.7273406,38.7863919 C45.6506459,38.8200841 45.571574,38.8501593 45.4903462,38.8768094 Z\"></path>\n </g>\n <rect x=\"96\" y=\"80\" width=\"16\" height=\"48\" rx=\"8\"></rect>\n <rect x=\"80\" y=\"96\" width=\"48\" height=\"16\" rx=\"8\"></rect>\n </g>\n </g>\n</svg>" }, "$:/core/images/new-image-button": { "title": "$:/core/images/new-image-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-new-image-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <g fill-rule=\"evenodd\">\n <path d=\"M81.3619177,73.6270062 L97.1875317,46.2162388 C97.91364,44.9585822 97.4824378,43.3533085 96.2260476,42.6279312 L46.2162388,13.7547547 C44.9585822,13.0286463 43.3533085,13.4598485 42.6279312,14.7162388 L30.0575956,36.4886988 L40.0978909,31.2276186 C43.1404959,29.6333041 46.8692155,31.3421319 47.6479264,34.6877101 L51.2545483,52.3903732 L61.1353556,53.2399953 C63.2899974,53.4346096 65.1046382,54.9309951 65.706105,57.0091178 C65.7395572,57.1246982 65.8069154,57.3539875 65.9047035,57.6813669 C66.0696435,58.2335608 66.2581528,58.852952 66.4667073,59.5238092 C67.0618822,61.4383079 67.6960725,63.3742727 68.3393254,65.2021174 C68.5462918,65.7902259 68.7511789,66.3583016 68.953259,66.9034738 C69.5777086,68.5881157 70.1617856,70.0172008 70.6783305,71.110045 C70.9334784,71.6498566 71.1627732,72.0871602 71.4035746,72.5373068 C71.6178999,72.7492946 71.9508843,72.9623307 72.4151452,73.1586945 C73.5561502,73.6412938 75.1990755,73.899146 77.0720271,73.9171651 C77.9355886,73.9254732 78.7819239,73.8832103 79.5638842,73.8072782 C80.0123946,73.7637257 80.3172916,73.7224469 80.4352582,73.7027375 C80.7503629,73.6500912 81.0598053,73.6256267 81.3619177,73.6270062 L81.3619177,73.6270062 L81.3619177,73.6270062 L81.3619177,73.6270062 Z M37.4707881,2.64867269 C38.9217993,0.135447653 42.1388058,-0.723707984 44.6486727,0.725364314 L108.293614,37.4707881 C110.806839,38.9217993 111.665994,42.1388058 110.216922,44.6486727 L73.4714982,108.293614 C72.0204871,110.806839 68.8034805,111.665994 66.2936136,110.216922 L2.64867269,73.4714982 C0.135447653,72.0204871 -0.723707984,68.8034805 0.725364314,66.2936136 L37.4707881,2.64867269 L37.4707881,2.64867269 L37.4707881,2.64867269 L37.4707881,2.64867269 Z M80.3080975,53.1397764 C82.8191338,54.5895239 86.0299834,53.7291793 87.4797308,51.218143 C88.9294783,48.7071068 88.0691338,45.4962571 85.5580975,44.0465097 C83.0470612,42.5967622 79.8362116,43.4571068 78.3864641,45.968143 C76.9367166,48.4791793 77.7970612,51.6900289 80.3080975,53.1397764 L80.3080975,53.1397764 L80.3080975,53.1397764 L80.3080975,53.1397764 Z M96,112 L88.0070969,112 C83.5881712,112 80,108.418278 80,104 C80,99.5907123 83.5848994,96 88.0070969,96 L96,96 L96,88.0070969 C96,83.5881712 99.581722,80 104,80 C108.409288,80 112,83.5848994 112,88.0070969 L112,96 L119.992903,96 C124.411829,96 128,99.581722 128,104 C128,108.409288 124.415101,112 119.992903,112 L112,112 L112,119.992903 C112,124.411829 108.418278,128 104,128 C99.5907123,128 96,124.415101 96,119.992903 L96,112 L96,112 Z M33.3471097,51.7910932 C40.7754579,59.7394511 42.3564368,62.4818351 40.7958321,65.1848818 C39.2352273,67.8879286 26.9581062,62.8571718 24.7019652,66.7649227 C22.4458242,70.6726735 23.7947046,70.0228006 22.2648667,72.6725575 L41.9944593,84.0634431 C41.9944593,84.0634431 36.3904568,75.8079231 37.7602356,73.4353966 C40.2754811,69.0788636 46.5298923,72.1787882 48.1248275,69.4162793 C50.538989,65.234829 43.0222016,59.7770885 33.3471097,51.7910932 L33.3471097,51.7910932 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/new-journal-button": { "title": "$:/core/images/new-journal-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-new-journal-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M102.545455,112.818182 L102.545455,124.636364 L102.545455,124.636364 L102.545455,124.636364 C102.545455,125.941761 103.630828,127 104.969697,127 L111.030303,127 C112.369172,127 113.454545,125.941761 113.454545,124.636364 L113.454545,112.818182 L125.575758,112.818182 C126.914626,112.818182 128,111.759982 128,110.454545 L128,104.545455 C128,103.240018 126.914626,102.181818 125.575758,102.181818 L113.454545,102.181818 L113.454545,90.3636364 C113.454545,89.0582 112.369172,88 111.030303,88 L104.969697,88 L104.969697,88 C103.630828,88 102.545455,89.0582 102.545455,90.3636364 L102.545455,102.181818 L90.4242424,102.181818 L90.4242424,102.181818 C89.0853705,102.181818 88,103.240018 88,104.545455 L88,110.454545 L88,110.454545 L88,110.454545 C88,111.759982 89.0853705,112.818182 90.4242424,112.818182 L102.545455,112.818182 Z\"></path>\n <g transform=\"translate(59.816987, 64.316987) rotate(30.000000) translate(-59.816987, -64.316987) translate(20.316987, 12.816987)\">\n <g transform=\"translate(0.000000, 0.000000)\">\n <path d=\"M9.99631148,0 C4.4755011,0 -2.27373675e-13,4.48070044 -2.27373675e-13,9.99759461 L-2.27373675e-13,91.6128884 C-2.27373675e-13,97.1344074 4.46966773,101.610483 9.99631148,101.610483 L68.9318917,101.610483 C74.4527021,101.610483 78.9282032,97.1297826 78.9282032,91.6128884 L78.9282032,9.99759461 C78.9282032,4.47607557 74.4585355,0 68.9318917,0 L9.99631148,0 Z M20.8885263,26 C24.2022348,26 26.8885263,23.3137085 26.8885263,20 C26.8885263,16.6862915 24.2022348,14 20.8885263,14 C17.5748178,14 14.8885263,16.6862915 14.8885263,20 C14.8885263,23.3137085 17.5748178,26 20.8885263,26 Z M57.3033321,25.6783342 C60.6170406,25.6783342 63.3033321,22.9920427 63.3033321,19.6783342 C63.3033321,16.3646258 60.6170406,13.6783342 57.3033321,13.6783342 C53.9896236,13.6783342 51.3033321,16.3646258 51.3033321,19.6783342 C51.3033321,22.9920427 53.9896236,25.6783342 57.3033321,25.6783342 Z\"></path>\n <text font-family=\"Helvetica\" font-size=\"47.1724138\" font-weight=\"bold\" fill=\"#FFFFFF\">\n <tspan x=\"42\" y=\"77.4847912\" text-anchor=\"middle\"><<now \"DD\">></tspan>\n </text>\n </g>\n </g>\n </g>\n</svg>" }, "$:/core/images/opacity": { "title": "$:/core/images/opacity", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-opacity tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M102.361773,65 C101.833691,67.051742 101.183534,69.0544767 100.419508,71 L82.5835324,71 C83.7602504,69.1098924 84.7666304,67.1027366 85.581205,65 L102.361773,65 Z M102.834311,63 C103.256674,61.0388326 103.568427,59.0365486 103.762717,57 L87.6555706,57 C87.3692052,59.0609452 86.9083652,61.0660782 86.2884493,63 L102.834311,63 Z M99.5852583,73 C98.6682925,75.0747721 97.6196148,77.0783056 96.4498253,79 L75.8124196,79 C77.8387053,77.2115633 79.6621163,75.1985844 81.2437158,73 L99.5852583,73 Z M95.1689122,81 C93.7449202,83.1155572 92.1695234,85.1207336 90.458251,87 L60.4614747,87 C65.1836162,85.86248 69.5430327,83.794147 73.3347255,81 L95.1689122,81 Z M87.6555706,47 L103.762717,47 C101.246684,20.6269305 79.0321807,0 52,0 C23.281193,0 0,23.281193 0,52 C0,77.2277755 17.9651296,98.2595701 41.8000051,103 L62.1999949,103 C67.8794003,101.870444 73.2255333,99.8158975 78.074754,97 L39,97 L39,95 L81.2493857,95 C83.8589242,93.2215015 86.2981855,91.2116653 88.5376609,89 L39,89 L39,87 L43.5385253,87 C27.7389671,83.1940333 16,68.967908 16,52 C16,32.117749 32.117749,16 52,16 C70.1856127,16 85.2217929,29.4843233 87.6555706,47 Z M87.8767787,49 L103.914907,49 C103.971379,49.9928025 104,50.9930589 104,52 C104,53.0069411 103.971379,54.0071975 103.914907,55 L87.8767787,55 C87.958386,54.0107999 88,53.0102597 88,52 C88,50.9897403 87.958386,49.9892001 87.8767787,49 Z\"></path>\n <path d=\"M76,128 C104.718807,128 128,104.718807 128,76 C128,47.281193 104.718807,24 76,24 C47.281193,24 24,47.281193 24,76 C24,104.718807 47.281193,128 76,128 L76,128 Z M76,112 C95.882251,112 112,95.882251 112,76 C112,56.117749 95.882251,40 76,40 C56.117749,40 40,56.117749 40,76 C40,95.882251 56.117749,112 76,112 L76,112 Z\"></path>\n <path d=\"M37,58 L90,58 L90,62 L37,62 L37,58 L37,58 Z M40,50 L93,50 L93,54 L40,54 L40,50 L40,50 Z M40,42 L93,42 L93,46 L40,46 L40,42 L40,42 Z M32,66 L85,66 L85,70 L32,70 L32,66 L32,66 Z M30,74 L83,74 L83,78 L30,78 L30,74 L30,74 Z M27,82 L80,82 L80,86 L27,86 L27,82 L27,82 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/open-window": { "title": "$:/core/images/open-window", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-open-window tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M16,112 L104.993898,112 C108.863261,112 112,115.590712 112,120 C112,124.418278 108.858091,128 104.993898,128 L7.00610161,128 C3.13673853,128 0,124.409288 0,120 C0,119.998364 4.30952878e-07,119.996727 1.29273572e-06,119.995091 C4.89579306e-07,119.993456 0,119.99182 0,119.990183 L0,24.0098166 C0,19.586117 3.59071231,16 8,16 C12.418278,16 16,19.5838751 16,24.0098166 L16,112 Z\"></path>\n <path d=\"M96,43.1959595 L96,56 C96,60.418278 99.581722,64 104,64 C108.418278,64 112,60.418278 112,56 L112,24 C112,19.5907123 108.415101,16 103.992903,16 L72.0070969,16 C67.5881712,16 64,19.581722 64,24 C64,28.4092877 67.5848994,32 72.0070969,32 L84.5685425,32 L48.2698369,68.2987056 C45.1421332,71.4264093 45.1434327,76.4904296 48.267627,79.614624 C51.3854642,82.7324612 56.4581306,82.7378289 59.5835454,79.6124141 L96,43.1959595 Z M32,7.9992458 C32,3.58138434 35.5881049,0 39.9992458,0 L120.000754,0 C124.418616,0 128,3.5881049 128,7.9992458 L128,88.0007542 C128,92.4186157 124.411895,96 120.000754,96 L39.9992458,96 C35.5813843,96 32,92.4118951 32,88.0007542 L32,7.9992458 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/options-button": { "title": "$:/core/images/options-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-options-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M110.48779,76.0002544 C109.354214,80.4045063 107.611262,84.5641217 105.354171,88.3838625 L105.354171,88.3838625 L112.07833,95.1080219 C115.20107,98.2307613 115.210098,103.299824 112.089164,106.420759 L106.420504,112.089418 C103.301049,115.208874 98.2346851,115.205502 95.1077675,112.078585 L88.3836082,105.354425 C84.5638673,107.611516 80.4042519,109.354468 76,110.488045 L76,110.488045 L76,119.993281 C76,124.409501 72.4220153,128.000254 68.0083475,128.000254 L59.9916525,128.000254 C55.5800761,128.000254 52,124.41541 52,119.993281 L52,110.488045 C47.5957481,109.354468 43.4361327,107.611516 39.6163918,105.354425 L32.8922325,112.078585 C29.7694931,115.201324 24.7004301,115.210353 21.5794957,112.089418 L15.9108363,106.420759 C12.7913807,103.301303 12.7947522,98.2349395 15.9216697,95.1080219 L22.6458291,88.3838625 C20.3887383,84.5641217 18.6457859,80.4045063 17.5122098,76.0002544 L8.00697327,76.0002544 C3.59075293,76.0002544 2.19088375e-16,72.4222697 4.89347582e-16,68.0086019 L9.80228577e-16,59.9919069 C1.25035972e-15,55.5803305 3.58484404,52.0002544 8.00697327,52.0002544 L17.5122098,52.0002544 C18.6457859,47.5960025 20.3887383,43.4363871 22.6458291,39.6166462 L15.9216697,32.8924868 C12.7989304,29.7697475 12.7899019,24.7006845 15.9108363,21.5797501 L21.5794957,15.9110907 C24.6989513,12.7916351 29.7653149,12.7950065 32.8922325,15.9219241 L39.6163918,22.6460835 C43.4361327,20.3889927 47.5957481,18.6460403 52,17.5124642 L52,8.00722764 C52,3.5910073 55.5779847,0.000254375069 59.9916525,0.000254375069 L68.0083475,0.000254375069 C72.4199239,0.000254375069 76,3.58509841 76,8.00722764 L76,17.5124642 C80.4042519,18.6460403 84.5638673,20.3889927 88.3836082,22.6460835 L95.1077675,15.9219241 C98.2305069,12.7991848 103.29957,12.7901562 106.420504,15.9110907 L112.089164,21.5797501 C115.208619,24.6992057 115.205248,29.7655693 112.07833,32.8924868 L105.354171,39.6166462 L105.354171,39.6166462 C107.611262,43.4363871 109.354214,47.5960025 110.48779,52.0002544 L119.993027,52.0002544 C124.409247,52.0002544 128,55.5782391 128,59.9919069 L128,68.0086019 C128,72.4201783 124.415156,76.0002544 119.993027,76.0002544 L110.48779,76.0002544 L110.48779,76.0002544 Z M64,96.0002544 C81.673112,96.0002544 96,81.6733664 96,64.0002544 C96,46.3271424 81.673112,32.0002544 64,32.0002544 C46.326888,32.0002544 32,46.3271424 32,64.0002544 C32,81.6733664 46.326888,96.0002544 64,96.0002544 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/paint": { "title": "$:/core/images/paint", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-paint tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M83.5265806,76.1907935 C90.430962,69.2864121 91.8921169,59.0000433 87.9100453,50.6642209 L125.812763,12.7615036 C128.732035,9.84223095 128.72611,5.10322984 125.812796,2.18991592 C122.893542,-0.729338085 118.161775,-0.730617045 115.241209,2.18994966 L77.3384914,40.092667 C69.002669,36.1105954 58.7163002,37.5717503 51.8119188,44.4761317 L83.5265806,76.1907935 L83.5265806,76.1907935 L83.5265806,76.1907935 L83.5265806,76.1907935 Z M80.8836921,78.8336819 L49.1690303,47.1190201 C49.1690303,47.1190201 8.50573364,81.242543 0,80.2820711 C0,80.2820711 3.78222974,85.8744423 6.82737483,88.320684 C20.8514801,82.630792 44.1526049,63.720771 44.1526049,63.720771 L44.8144806,64.3803375 C44.8144806,64.3803375 19.450356,90.2231043 9.18040433,92.0477601 C10.4017154,93.4877138 13.5343883,96.1014812 15.4269991,97.8235871 C20.8439164,96.3356979 50.1595367,69.253789 50.1595367,69.253789 L50.8214124,69.9133555 L18.4136144,100.936036 L23.6993903,106.221812 L56.1060358,75.2002881 L56.7679115,75.8598546 C56.7679115,75.8598546 28.9040131,106.396168 28.0841366,108.291555 C28.0841366,108.291555 34.1159238,115.144621 35.6529617,116.115796 C36.3545333,113.280171 63.5365402,82.6307925 63.5365402,82.6307925 L64.1984159,83.290359 C64.1984159,83.290359 43.6013016,107.04575 39.2343772,120.022559 C42.443736,123.571575 46.7339155,125.159692 50.1595362,126.321151 C47.9699978,114.504469 80.8836921,78.8336819 80.8836921,78.8336819 L80.8836921,78.8336819 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/palette": { "title": "$:/core/images/palette", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-palette tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M80.2470434,39.1821571 C75.0645698,38.2680897 69.6261555,37.7814854 64.0193999,37.7814854 C28.6624616,37.7814854 0,57.1324214 0,81.0030106 C0,90.644534 4.67604329,99.5487133 12.5805659,106.738252 C23.5031767,91.1899067 26.3405471,72.3946229 36.8885698,63.5622337 C52.0716764,50.8486559 63.4268694,55.7343343 63.4268694,55.7343343 L80.2470434,39.1821571 Z M106.781666,48.8370714 C119.830962,56.749628 128.0388,68.229191 128.0388,81.0030106 C128.0388,90.3534932 128.557501,98.4142085 116.165191,106.082518 C105.367708,112.763955 112.341384,99.546808 104.321443,95.1851533 C96.3015017,90.8234987 84.3749007,96.492742 86.1084305,103.091059 C89.3087234,115.272303 105.529892,114.54645 92.4224435,119.748569 C79.3149955,124.950687 74.2201582,124.224536 64.0193999,124.224536 C56.1979176,124.224536 48.7040365,123.277578 41.7755684,121.544216 C51.620343,117.347916 69.6563669,109.006202 75.129737,102.088562 C82.7876655,92.4099199 87.3713218,80.0000002 83.3235694,72.4837191 C83.1303943,72.1250117 94.5392656,60.81569 106.781666,48.8370714 Z M1.13430476,123.866563 C0.914084026,123.867944 0.693884185,123.868637 0.473712455,123.868637 C33.9526848,108.928928 22.6351223,59.642592 59.2924543,59.6425917 C59.6085574,61.0606542 59.9358353,62.5865065 60.3541977,64.1372318 C34.4465025,59.9707319 36.7873124,112.168427 1.13429588,123.866563 L1.13430476,123.866563 Z M1.84669213,123.859694 C40.7185279,123.354338 79.9985412,101.513051 79.9985401,79.0466836 C70.7284906,79.0466835 65.9257264,75.5670082 63.1833375,71.1051511 C46.585768,64.1019718 32.81846,116.819636 1.84665952,123.859695 L1.84669213,123.859694 Z M67.1980193,59.8524981 C62.748213,63.9666823 72.0838429,76.2846822 78.5155805,71.1700593 C89.8331416,59.8524993 112.468264,37.2173758 123.785825,25.8998146 C135.103386,14.5822535 123.785825,3.26469247 112.468264,14.5822535 C101.150703,25.8998144 78.9500931,48.9868127 67.1980193,59.8524981 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/permalink-button": { "title": "$:/core/images/permalink-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-permalink-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M80.4834582,48 L73.0956761,80 L73.0956761,80 L47.5165418,80 L54.9043239,48 L80.4834582,48 Z M84.1773493,32 L89.8007299,7.64246248 C90.7941633,3.33942958 95.0918297,0.64641956 99.3968675,1.64031585 C103.693145,2.63218977 106.385414,6.93288901 105.390651,11.2416793 L100.598215,32 L104.000754,32 C108.411895,32 112,35.581722 112,40 C112,44.4092877 108.418616,48 104.000754,48 L96.9043239,48 L89.5165418,80 L104.000754,80 C108.411895,80 112,83.581722 112,88 C112,92.4092877 108.418616,96 104.000754,96 L85.8226507,96 L80.1992701,120.357538 C79.2058367,124.66057 74.9081703,127.35358 70.6031325,126.359684 C66.3068546,125.36781 63.6145865,121.067111 64.6093491,116.758321 L69.401785,96 L43.8226507,96 L38.1992701,120.357538 C37.2058367,124.66057 32.9081703,127.35358 28.6031325,126.359684 C24.3068546,125.36781 21.6145865,121.067111 22.6093491,116.758321 L27.401785,96 L23.9992458,96 C19.5881049,96 16,92.418278 16,88 C16,83.5907123 19.5813843,80 23.9992458,80 L31.0956761,80 L38.4834582,48 L23.9992458,48 C19.5881049,48 16,44.418278 16,40 C16,35.5907123 19.5813843,32 23.9992458,32 L42.1773493,32 L47.8007299,7.64246248 C48.7941633,3.33942958 53.0918297,0.64641956 57.3968675,1.64031585 C61.6931454,2.63218977 64.3854135,6.93288901 63.3906509,11.2416793 L58.598215,32 L84.1773493,32 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/permaview-button": { "title": "$:/core/images/permaview-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-permaview-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M81.4834582,48 L79.6365127,56 L79.6365127,56 L74.0573784,56 L75.9043239,48 L81.4834582,48 Z M85.1773493,32 L90.8007299,7.64246248 C91.7941633,3.33942958 96.0918297,0.64641956 100.396867,1.64031585 C104.693145,2.63218977 107.385414,6.93288901 106.390651,11.2416793 L101.598215,32 L104.000754,32 C108.411895,32 112,35.581722 112,40 C112,44.4092877 108.418616,48 104.000754,48 L97.9043239,48 L96.0573784,56 L104.000754,56 C108.411895,56 112,59.581722 112,64 C112,68.4092877 108.418616,72 104.000754,72 L92.3634873,72 L90.5165418,80 L104.000754,80 C108.411895,80 112,83.581722 112,88 C112,92.4092877 108.418616,96 104.000754,96 L86.8226507,96 L81.1992701,120.357538 C80.2058367,124.66057 75.9081703,127.35358 71.6031325,126.359684 C67.3068546,125.36781 64.6145865,121.067111 65.6093491,116.758321 L70.401785,96 L64.8226507,96 L59.1992701,120.357538 C58.2058367,124.66057 53.9081703,127.35358 49.6031325,126.359684 C45.3068546,125.36781 42.6145865,121.067111 43.6093491,116.758321 L48.401785,96 L42.8226507,96 L37.1992701,120.357538 C36.2058367,124.66057 31.9081703,127.35358 27.6031325,126.359684 C23.3068546,125.36781 20.6145865,121.067111 21.6093491,116.758321 L26.401785,96 L23.9992458,96 C19.5881049,96 16,92.418278 16,88 C16,83.5907123 19.5813843,80 23.9992458,80 L30.0956761,80 L31.9426216,72 L23.9992458,72 C19.5881049,72 16,68.418278 16,64 C16,59.5907123 19.5813843,56 23.9992458,56 L35.6365127,56 L37.4834582,48 L23.9992458,48 C19.5881049,48 16,44.418278 16,40 C16,35.5907123 19.5813843,32 23.9992458,32 L41.1773493,32 L46.8007299,7.64246248 C47.7941633,3.33942958 52.0918297,0.64641956 56.3968675,1.64031585 C60.6931454,2.63218977 63.3854135,6.93288901 62.3906509,11.2416793 L57.598215,32 L63.1773493,32 L68.8007299,7.64246248 C69.7941633,3.33942958 74.0918297,0.64641956 78.3968675,1.64031585 C82.6931454,2.63218977 85.3854135,6.93288901 84.3906509,11.2416793 L79.598215,32 L85.1773493,32 Z M53.9043239,48 L52.0573784,56 L57.6365127,56 L59.4834582,48 L53.9043239,48 Z M75.9426216,72 L74.0956761,80 L74.0956761,80 L68.5165418,80 L70.3634873,72 L75.9426216,72 L75.9426216,72 Z M48.3634873,72 L46.5165418,80 L52.0956761,80 L53.9426216,72 L48.3634873,72 L48.3634873,72 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/picture": { "title": "$:/core/images/picture", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-picture tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M112,68.2332211 L112,20.0027785 C112,17.7898769 110.207895,16 107.997221,16 L20.0027785,16 C17.7898769,16 16,17.792105 16,20.0027785 L16,58.312373 L25.2413115,43.7197989 C28.041793,39.297674 34.2643908,38.7118128 37.8410347,42.5335275 L56.0882845,63.1470817 L69.7748997,56.7400579 C72.766567,55.3552503 76.3013751,55.9473836 78.678437,58.2315339 C78.8106437,58.3585731 79.0742301,58.609836 79.4527088,58.9673596 C80.0910923,59.570398 80.8117772,60.2441563 81.598127,60.9705595 C83.8422198,63.043576 86.1541548,65.1151944 88.3956721,67.0372264 C89.1168795,67.6556396 89.8200801,68.2492007 90.5021258,68.8146755 C92.6097224,70.5620551 94.4693308,72.0029474 95.9836366,73.0515697 C96.7316295,73.5695379 97.3674038,73.9719282 98.0281481,74.3824999 C98.4724987,74.4989557 99.0742374,74.5263881 99.8365134,74.4317984 C101.709944,74.1993272 104.074502,73.2878514 106.559886,71.8846196 C107.705822,71.2376318 108.790494,70.5370325 109.764561,69.8410487 C110.323259,69.4418522 110.694168,69.1550757 110.834827,69.0391868 C111.210545,68.7296319 111.600264,68.4615815 112,68.2332211 L112,68.2332211 Z M0,8.00697327 C0,3.58484404 3.59075293,0 8.00697327,0 L119.993027,0 C124.415156,0 128,3.59075293 128,8.00697327 L128,119.993027 C128,124.415156 124.409247,128 119.993027,128 L8.00697327,128 C3.58484404,128 0,124.409247 0,119.993027 L0,8.00697327 L0,8.00697327 Z M95,42 C99.418278,42 103,38.418278 103,34 C103,29.581722 99.418278,26 95,26 C90.581722,26 87,29.581722 87,34 C87,38.418278 90.581722,42 95,42 L95,42 Z M32,76 C47.8587691,80.8294182 52.0345556,83.2438712 52.0345556,88 C52.0345556,92.7561288 32,95.4712486 32,102.347107 C32,109.222965 33.2849191,107.337637 33.2849191,112 L67.999999,112 C67.999999,112 54.3147136,105.375255 54.3147136,101.200691 C54.3147136,93.535181 64.9302432,92.860755 64.9302432,88 C64.9302432,80.6425555 50.8523779,79.167282 32,76 L32,76 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/plugin-generic-language": { "title": "$:/core/images/plugin-generic-language", "tags": "$:/tags/Image", "text": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M61.2072232,68.1369825 C56.8829239,70.9319564 54.2082892,74.793177 54.2082892,79.0581634 C54.2082892,86.9638335 63.3980995,93.4821994 75.2498076,94.3940006 C77.412197,98.2964184 83.8475284,101.178858 91.5684735,101.403106 C86.4420125,100.27851 82.4506393,97.6624107 80.9477167,94.3948272 C92.8046245,93.4861461 102,86.9662269 102,79.0581634 C102,70.5281905 91.3014611,63.6132813 78.1041446,63.6132813 C71.5054863,63.6132813 65.5315225,65.3420086 61.2072232,68.1369825 Z M74.001066,53.9793443 C69.6767667,56.7743182 63.7028029,58.5030456 57.1041446,58.5030456 C54.4851745,58.5030456 51.9646095,58.2307276 49.6065315,57.7275105 C46.2945155,59.9778212 41.2235699,61.4171743 35.5395922,61.4171743 C35.4545771,61.4171743 35.3696991,61.4168523 35.2849622,61.4162104 C39.404008,60.5235193 42.7961717,58.6691298 44.7630507,56.286533 C37.8379411,53.5817651 33.2082892,48.669413 33.2082892,43.0581634 C33.2082892,34.5281905 43.9068281,27.6132812 57.1041446,27.6132812 C70.3014611,27.6132812 81,34.5281905 81,43.0581634 C81,47.3231498 78.3253653,51.1843704 74.001066,53.9793443 Z M64,0 L118.5596,32 L118.5596,96 L64,128 L9.44039956,96 L9.44039956,32 L64,0 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/plugin-generic-plugin": { "title": "$:/core/images/plugin-generic-plugin", "tags": "$:/tags/Image", "text": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M40.3972881,76.4456988 L40.3972881,95.3404069 L54.5170166,95.3404069 L54.5170166,95.3404069 C54.5165526,95.3385183 54.516089,95.3366295 54.515626,95.3347404 C54.6093153,95.3385061 54.7034848,95.3404069 54.7980982,95.3404069 C58.6157051,95.3404069 61.710487,92.245625 61.710487,88.4280181 C61.710487,86.6197822 61.01617,84.9737128 59.8795929,83.7418666 L59.8795929,83.7418666 C59.8949905,83.7341665 59.9104102,83.7265043 59.925852,83.7188798 C58.8840576,82.5086663 58.2542926,80.9336277 58.2542926,79.2114996 C58.2542926,75.3938927 61.3490745,72.2991108 65.1666814,72.2991108 C68.9842884,72.2991108 72.0790703,75.3938927 72.0790703,79.2114996 C72.0790703,81.1954221 71.2432806,82.9841354 69.9045961,84.2447446 L69.9045961,84.2447446 C69.9333407,84.2629251 69.9619885,84.281245 69.9905383,84.2997032 L69.9905383,84.2997032 C69.1314315,85.4516923 68.6228758,86.8804654 68.6228758,88.4280181 C68.6228758,91.8584969 71.1218232,94.7053153 74.3986526,95.2474079 C74.3913315,95.2784624 74.3838688,95.3094624 74.3762652,95.3404069 L95.6963988,95.3404069 L95.6963988,75.5678578 L95.6963988,75.5678578 C95.6466539,75.5808558 95.5967614,75.5934886 95.5467242,75.6057531 C95.5504899,75.5120637 95.5523907,75.4178943 95.5523907,75.3232809 C95.5523907,71.505674 92.4576088,68.4108921 88.6400019,68.4108921 C86.831766,68.4108921 85.1856966,69.105209 83.9538504,70.2417862 L83.9538504,70.2417862 C83.9461503,70.2263886 83.938488,70.2109688 83.9308636,70.1955271 C82.7206501,71.2373215 81.1456115,71.8670865 79.4234834,71.8670865 C75.6058765,71.8670865 72.5110946,68.7723046 72.5110946,64.9546976 C72.5110946,61.1370907 75.6058765,58.0423088 79.4234834,58.0423088 C81.4074059,58.0423088 83.1961192,58.8780985 84.4567284,60.2167829 L84.4567284,60.2167829 C84.4749089,60.1880383 84.4932288,60.1593906 84.511687,60.1308407 L84.511687,60.1308407 C85.6636761,60.9899475 87.0924492,61.4985032 88.6400019,61.4985032 C92.0704807,61.4985032 94.9172991,58.9995558 95.4593917,55.7227265 C95.538755,55.7414363 95.6177614,55.761071 95.6963988,55.7816184 L95.6963988,40.0412962 L74.3762652,40.0412962 L74.3762652,40.0412962 C74.3838688,40.0103516 74.3913315,39.9793517 74.3986526,39.9482971 L74.3986526,39.9482971 C71.1218232,39.4062046 68.6228758,36.5593862 68.6228758,33.1289073 C68.6228758,31.5813547 69.1314315,30.1525815 69.9905383,29.0005925 C69.9619885,28.9821342 69.9333407,28.9638143 69.9045961,28.9456339 C71.2432806,27.6850247 72.0790703,25.8963113 72.0790703,23.9123888 C72.0790703,20.0947819 68.9842884,17 65.1666814,17 C61.3490745,17 58.2542926,20.0947819 58.2542926,23.9123888 C58.2542926,25.6345169 58.8840576,27.2095556 59.925852,28.419769 L59.925852,28.419769 C59.9104102,28.4273935 59.8949905,28.4350558 59.8795929,28.4427558 C61.01617,29.674602 61.710487,31.3206715 61.710487,33.1289073 C61.710487,36.9465143 58.6157051,40.0412962 54.7980982,40.0412962 C54.7034848,40.0412962 54.6093153,40.0393953 54.515626,40.0356296 L54.515626,40.0356296 C54.516089,40.0375187 54.5165526,40.0394075 54.5170166,40.0412962 L40.3972881,40.0412962 L40.3972881,52.887664 L40.3972881,52.887664 C40.4916889,53.3430132 40.5412962,53.8147625 40.5412962,54.2980982 C40.5412962,58.1157051 37.4465143,61.210487 33.6289073,61.210487 C32.0813547,61.210487 30.6525815,60.7019313 29.5005925,59.8428245 C29.4821342,59.8713744 29.4638143,59.9000221 29.4456339,59.9287667 C28.1850247,58.5900823 26.3963113,57.7542926 24.4123888,57.7542926 C20.5947819,57.7542926 17.5,60.8490745 17.5,64.6666814 C17.5,68.4842884 20.5947819,71.5790703 24.4123888,71.5790703 C26.134517,71.5790703 27.7095556,70.9493053 28.919769,69.9075109 L28.919769,69.9075109 C28.9273935,69.9229526 28.9350558,69.9383724 28.9427558,69.95377 C30.174602,68.8171928 31.8206715,68.1228758 33.6289073,68.1228758 C37.4465143,68.1228758 40.5412962,71.2176578 40.5412962,75.0352647 C40.5412962,75.5186004 40.4916889,75.9903496 40.3972881,76.4456988 Z M64,0 L118.5596,32 L118.5596,96 L64,128 L9.44039956,96 L9.44039956,32 L64,0 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/plugin-generic-theme": { "title": "$:/core/images/plugin-generic-theme", "tags": "$:/tags/Image", "text": "<svg width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M29.4078519,91.4716406 L51.4693474,69.4101451 L51.4646675,69.4054652 C50.5969502,68.5377479 50.5929779,67.1348725 51.4693474,66.2585029 C52.3396494,65.3882009 53.7499654,65.3874786 54.6163097,66.2538229 L64.0805963,75.7181095 C64.9483136,76.5858268 64.9522859,77.9887022 64.0759163,78.8650718 C63.2056143,79.7353737 61.7952984,79.736096 60.9289541,78.8697517 L60.9242741,78.8650718 L60.9242741,78.8650718 L38.8627786,100.926567 C36.2518727,103.537473 32.0187578,103.537473 29.4078519,100.926567 C26.796946,98.3156614 26.796946,94.0825465 29.4078519,91.4716406 Z M60.8017407,66.3810363 C58.3659178,63.6765806 56.3370667,61.2899536 54.9851735,59.5123615 C48.1295381,50.4979488 44.671561,55.2444054 40.7586738,59.5123614 C36.8457866,63.7803174 41.789473,67.2384487 38.0759896,70.2532832 C34.3625062,73.2681177 34.5917646,74.3131575 28.3243876,68.7977024 C22.0570105,63.2822473 21.6235306,61.7636888 24.5005999,58.6166112 C27.3776691,55.4695337 29.7823103,60.4247912 35.6595047,54.8320442 C41.5366991,49.2392972 36.5996215,44.2825646 36.5996215,44.2825646 C36.5996215,44.2825646 48.8365511,19.267683 65.1880231,21.1152173 C81.5394952,22.9627517 59.0022276,18.7228947 53.3962199,38.3410355 C50.9960082,46.7405407 53.8429162,44.7613399 58.3941742,48.3090467 C59.7875202,49.3951602 64.4244828,52.7100463 70.1884353,56.9943417 L90.8648751,36.3179019 L92.4795866,31.5515482 L100.319802,26.8629752 L103.471444,30.0146174 L98.782871,37.8548326 L94.0165173,39.4695441 L73.7934912,59.6925702 C86.4558549,69.2403631 102.104532,81.8392557 102.104532,86.4016913 C102.104533,93.6189834 99.0337832,97.9277545 92.5695848,95.5655717 C87.8765989,93.8506351 73.8015497,80.3744087 63.8173444,69.668717 L60.9242741,72.5617873 L57.7726319,69.4101451 L60.8017407,66.3810363 L60.8017407,66.3810363 Z M63.9533761,1.42108547e-13 L118.512977,32 L118.512977,96 L63.9533761,128 L9.39377563,96 L9.39377563,32 L63.9533761,1.42108547e-13 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/preview-closed": { "title": "$:/core/images/preview-closed", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-preview-closed tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M0.0881363238,64 C-0.210292223,65.8846266 0.249135869,67.8634737 1.4664206,69.4579969 C16.2465319,88.8184886 39.1692554,100.414336 64,100.414336 C88.8307446,100.414336 111.753468,88.8184886 126.533579,69.4579969 C127.750864,67.8634737 128.210292,65.8846266 127.911864,64 C110.582357,78.4158332 88.3036732,87.0858436 64,87.0858436 C39.6963268,87.0858436 17.4176431,78.4158332 0.0881363238,64 Z\"></path>\n <rect x=\"62\" y=\"96\" width=\"4\" height=\"16\" rx=\"4\"></rect>\n <rect transform=\"translate(80.000000, 101.000000) rotate(-5.000000) translate(-80.000000, -101.000000) \" x=\"78\" y=\"93\" width=\"4\" height=\"16\" rx=\"4\"></rect>\n <rect transform=\"translate(48.000000, 101.000000) rotate(-355.000000) translate(-48.000000, -101.000000) \" x=\"46\" y=\"93\" width=\"4\" height=\"16\" rx=\"4\"></rect>\n <rect transform=\"translate(32.000000, 96.000000) rotate(-350.000000) translate(-32.000000, -96.000000) \" x=\"30\" y=\"88\" width=\"4\" height=\"16\" rx=\"4\"></rect>\n <rect transform=\"translate(96.000000, 96.000000) rotate(-10.000000) translate(-96.000000, -96.000000) \" x=\"94\" y=\"88\" width=\"4\" height=\"16\" rx=\"4\"></rect>\n <rect transform=\"translate(112.000000, 88.000000) rotate(-20.000000) translate(-112.000000, -88.000000) \" x=\"110\" y=\"80\" width=\"4\" height=\"16\" rx=\"4\"></rect>\n <rect transform=\"translate(16.000000, 88.000000) rotate(-340.000000) translate(-16.000000, -88.000000) \" x=\"14\" y=\"80\" width=\"4\" height=\"16\" rx=\"4\"></rect>\n </g>\n</svg>" }, "$:/core/images/preview-open": { "title": "$:/core/images/preview-open", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-preview-open tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M64.1099282,99.5876785 C39.2791836,99.5876785 16.3564602,87.9918313 1.57634884,68.6313396 C-0.378878622,66.070184 -0.378878622,62.5174945 1.57634884,59.9563389 C16.3564602,40.5958472 39.2791836,29 64.1099282,29 C88.9406729,29 111.863396,40.5958472 126.643508,59.9563389 C128.598735,62.5174945 128.598735,66.070184 126.643508,68.6313396 C111.863396,87.9918313 88.9406729,99.5876785 64.1099282,99.5876785 Z M110.213805,67.5808331 C111.654168,66.0569335 111.654168,63.9430665 110.213805,62.4191669 C99.3257042,50.8995835 82.4391647,44 64.1470385,44 C45.8549124,44 28.9683729,50.8995835 18.0802717,62.4191669 C16.6399094,63.9430665 16.6399094,66.0569335 18.0802717,67.5808331 C28.9683729,79.1004165 45.8549124,86 64.1470385,86 C82.4391647,86 99.3257042,79.1004165 110.213805,67.5808331 Z\"></path>\n <path d=\"M63.5,88 C76.4786916,88 87,77.4786916 87,64.5 C87,51.5213084 76.4786916,41 63.5,41 C50.5213084,41 40,51.5213084 40,64.5 C40,77.4786916 50.5213084,88 63.5,88 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/print-button": { "title": "$:/core/images/print-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-print-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <g fill-rule=\"evenodd\">\n <path d=\"M112,71 L112,30.5 L111.96811,30.5 L111.96811,30.5 C111.932942,28.4998414 111.151676,26.510538 109.625176,24.9840387 L86.9982489,2.35711116 C85.3482153,0.707077645 83.1589869,-0.071534047 81,0.0201838424 L81,0 L23.9992458,0 C19.5808867,0 16,3.58213437 16,8.00092105 L16,71 L24,71 L24,8 L81,8 L81,22.4996539 C81,26.9216269 84.5818769,30.5 89.0003461,30.5 L104,30.5 L104,71 L112,71 Z\"></path>\n <rect x=\"32\" y=\"36\" width=\"64\" height=\"8\" rx=\"4\"></rect>\n <rect x=\"32\" y=\"52\" width=\"64\" height=\"8\" rx=\"4\"></rect>\n <rect x=\"32\" y=\"20\" width=\"40\" height=\"8\" rx=\"4\"></rect>\n <path d=\"M0,80.0054195 C0,71.1658704 7.15611005,64 16.0008841,64 L111.999116,64 C120.83616,64 128,71.1553215 128,80.0054195 L128,111.99458 C128,120.83413 120.84389,128 111.999116,128 L16.0008841,128 C7.16383982,128 0,120.844679 0,111.99458 L0,80.0054195 Z M104,96 C108.418278,96 112,92.418278 112,88 C112,83.581722 108.418278,80 104,80 C99.581722,80 96,83.581722 96,88 C96,92.418278 99.581722,96 104,96 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/quote": { "title": "$:/core/images/quote", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-quote tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M51.2188077,117.712501 L51.2188077,62.1993386 L27.4274524,62.1993386 C27.4274524,53.3075754 29.1096526,45.797753 32.4741035,39.669646 C35.8385544,33.541539 42.0867267,28.9154883 51.2188077,25.7913554 L51.2188077,2 C43.7689521,2.96127169 36.8599155,5.18417913 30.4914905,8.668789 C24.1230656,12.1533989 18.6559149,16.5391352 14.0898743,21.8261295 C9.52383382,27.1131238 5.97919764,33.2411389 3.45585945,40.2103586 C0.932521268,47.1795784 -0.208971741,54.6293222 0.0313461819,62.5598136 L0.0313461819,117.712501 L51.2188077,117.712501 Z M128,117.712501 L128,62.1993386 L104.208645,62.1993386 C104.208645,53.3075754 105.890845,45.797753 109.255296,39.669646 C112.619747,33.541539 118.867919,28.9154883 128,25.7913554 L128,2 C120.550144,2.96127169 113.641108,5.18417913 107.272683,8.668789 C100.904258,12.1533989 95.4371072,16.5391352 90.8710666,21.8261295 C86.3050261,27.1131238 82.7603899,33.2411389 80.2370517,40.2103586 C77.7137136,47.1795784 76.5722206,54.6293222 76.8125385,62.5598136 L76.8125385,117.712501 L128,117.712501 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/refresh-button": { "title": "$:/core/images/refresh-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-refresh-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M106.369002,39.4325143 C116.529932,60.3119371 112.939592,86.1974934 95.5979797,103.539105 C73.7286194,125.408466 38.2713806,125.408466 16.4020203,103.539105 C-5.46734008,81.6697449 -5.46734008,46.2125061 16.4020203,24.3431458 C19.5262146,21.2189514 24.5915344,21.2189514 27.7157288,24.3431458 C30.8399231,27.4673401 30.8399231,32.5326599 27.7157288,35.6568542 C12.0947571,51.2778259 12.0947571,76.6044251 27.7157288,92.2253967 C43.3367004,107.846368 68.6632996,107.846368 84.2842712,92.2253967 C97.71993,78.7897379 99.5995262,58.1740623 89.9230597,42.729491 L83.4844861,54.9932839 C81.4307001,58.9052072 76.5945372,60.4115251 72.682614,58.3577391 C68.7706907,56.3039532 67.2643728,51.4677903 69.3181587,47.555867 L84.4354914,18.7613158 C86.4966389,14.8353707 91.3577499,13.3347805 95.273202,15.415792 L124.145886,30.7612457 C128.047354,32.8348248 129.52915,37.6785572 127.455571,41.5800249 C125.381992,45.4814927 120.53826,46.9632892 116.636792,44.8897102 L106.369002,39.4325143 Z M98.1470904,27.0648707 C97.9798954,26.8741582 97.811187,26.6843098 97.6409651,26.4953413 L98.6018187,26.1987327 L98.1470904,27.0648707 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/right-arrow": { "title": "$:/core/images/right-arrow", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-right-arrow tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <path d=\"M80.3563798,109.353315 C78.9238993,110.786918 76.9450203,111.675144 74.7592239,111.675144 L-4.40893546,111.675144 C-8.77412698,111.675144 -12.3248558,108.130732 -12.3248558,103.758478 C-12.3248558,99.3951199 -8.78077754,95.8418109 -4.40893546,95.8418109 L66.8418109,95.8418109 L66.8418109,24.5910645 C66.8418109,20.225873 70.3862233,16.6751442 74.7584775,16.6751442 C79.1218352,16.6751442 82.6751442,20.2192225 82.6751442,24.5910645 L82.6751442,103.759224 C82.6751442,105.941695 81.7891419,107.920575 80.3566508,109.353886 Z\" transform=\"translate(35.175144, 64.175144) rotate(-45.000000) translate(-35.175144, -64.175144) \"></path>\n</svg>" }, "$:/core/images/save-button": { "title": "$:/core/images/save-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-save-button tc-image-button\" viewBox=\"0 0 128 128\" width=\"22pt\" height=\"22pt\">\n <g fill-rule=\"evenodd\">\n <path d=\"M120.78304,34.329058 C125.424287,43.1924006 128.049406,53.2778608 128.049406,63.9764502 C128.049406,99.3226742 99.3956295,127.97645 64.0494055,127.97645 C28.7031816,127.97645 0.0494055385,99.3226742 0.0494055385,63.9764502 C0.0494055385,28.6302262 28.7031816,-0.0235498012 64.0494055,-0.0235498012 C82.8568763,-0.0235498012 99.769563,8.08898558 111.479045,21.0056358 L114.159581,18.3250998 C117.289194,15.1954866 122.356036,15.1939641 125.480231,18.3181584 C128.598068,21.4359957 128.601317,26.5107804 125.473289,29.6388083 L120.78304,34.329058 Z M108.72451,46.3875877 C110.870571,51.8341374 112.049406,57.767628 112.049406,63.9764502 C112.049406,90.4861182 90.5590735,111.97645 64.0494055,111.97645 C37.5397375,111.97645 16.0494055,90.4861182 16.0494055,63.9764502 C16.0494055,37.4667822 37.5397375,15.9764502 64.0494055,15.9764502 C78.438886,15.9764502 91.3495036,22.308215 100.147097,32.3375836 L58.9411255,73.5435552 L41.975581,56.5780107 C38.8486152,53.4510448 33.7746915,53.4551552 30.6568542,56.5729924 C27.5326599,59.6971868 27.5372202,64.7670668 30.6618725,67.8917192 L53.279253,90.5090997 C54.8435723,92.073419 56.8951519,92.8541315 58.9380216,92.8558261 C60.987971,92.8559239 63.0389578,92.0731398 64.6049211,90.5071765 L108.72451,46.3875877 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/size": { "title": "$:/core/images/size", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-size tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <path d=\"M92.3431458,26 L83.1715729,35.1715729 C81.6094757,36.73367 81.6094757,39.26633 83.1715729,40.8284271 C84.73367,42.3905243 87.26633,42.3905243 88.8284271,40.8284271 L104.828427,24.8284271 C106.390524,23.26633 106.390524,20.73367 104.828427,19.1715729 L88.8284271,3.17157288 C87.26633,1.60947571 84.73367,1.60947571 83.1715729,3.17157288 C81.6094757,4.73367004 81.6094757,7.26632996 83.1715729,8.82842712 L92.3431457,18 L22,18 C19.790861,18 18,19.790861 18,22 L18,92.3431458 L8.82842712,83.1715729 C7.26632996,81.6094757 4.73367004,81.6094757 3.17157288,83.1715729 C1.60947571,84.73367 1.60947571,87.26633 3.17157288,88.8284271 L19.1715729,104.828427 C20.73367,106.390524 23.26633,106.390524 24.8284271,104.828427 L40.8284271,88.8284271 C42.3905243,87.26633 42.3905243,84.73367 40.8284271,83.1715729 C39.26633,81.6094757 36.73367,81.6094757 35.1715729,83.1715729 L26,92.3431458 L26,22 L22,26 L92.3431458,26 L92.3431458,26 Z M112,52 L112,116 L116,112 L52,112 C49.790861,112 48,113.790861 48,116 C48,118.209139 49.790861,120 52,120 L116,120 C118.209139,120 120,118.209139 120,116 L120,52 C120,49.790861 118.209139,48 116,48 C113.790861,48 112,49.790861 112,52 L112,52 Z\"></path>\n</svg>" }, "$:/core/images/spiral": { "title": "$:/core/images/spiral", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-spiral tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"nonzero\">\n <path d=\"M64.534 68.348c3.39 0 6.097-2.62 6.476-5.968l-4.755-.538 4.75.583c.377-3.07-1.194-6.054-3.89-7.78-2.757-1.773-6.34-2.01-9.566-.7-3.46 1.403-6.14 4.392-7.35 8.148l-.01.026c-1.3 4.08-.72 8.64 1.58 12.52 2.5 4.2 6.77 7.2 11.76 8.27 5.37 1.15 11.11-.05 15.83-3.31 5.04-3.51 8.46-9.02 9.45-15.3 1.05-6.7-.72-13.63-4.92-19.19l.02.02c-4.42-5.93-11.2-9.82-18.78-10.78-7.96-1.01-16.13 1.31-22.59 6.43-6.81 5.39-11.18 13.41-12.11 22.26-.98 9.27 1.87 18.65 7.93 26.02 6.32 7.69 15.6 12.56 25.74 13.48 10.54.96 21.15-2.42 29.45-9.4l.01-.01c8.58-7.25 13.94-17.78 14.86-29.21.94-11.84-2.96-23.69-10.86-32.9-8.19-9.5-19.95-15.36-32.69-16.27-13.16-.94-26.24 3.49-36.34 12.34l.01-.01c-10.41 9.08-16.78 22.1-17.68 36.15-.93 14.44 4.03 28.77 13.79 39.78 10.03 11.32 24.28 18.2 39.6 19.09 15.73.92 31.31-4.56 43.24-15.234 12.23-10.954 19.61-26.44 20.5-43.074.14-2.64-1.89-4.89-4.52-5.03-2.64-.14-4.89 1.88-5.03 4.52-.75 14.1-7 27.2-17.33 36.45-10.03 8.98-23.11 13.58-36.3 12.81-12.79-.75-24.67-6.48-33-15.89-8.07-9.11-12.17-20.94-11.41-32.827.74-11.52 5.942-22.15 14.43-29.54l.01-.01c8.18-7.17 18.74-10.75 29.35-9.998 10.21.726 19.6 5.41 26.11 12.96 6.24 7.273 9.32 16.61 8.573 25.894-.718 8.9-4.88 17.064-11.504 22.66l.01-.007c-6.36 5.342-14.44 7.92-22.425 7.19-7.604-.68-14.52-4.314-19.21-10.027-4.44-5.4-6.517-12.23-5.806-18.94.67-6.3 3.76-11.977 8.54-15.766 4.46-3.54 10.05-5.128 15.44-4.44 5.03.63 9.46 3.18 12.32 7.01l.02.024c2.65 3.5 3.75 7.814 3.1 11.92-.59 3.71-2.58 6.925-5.45 8.924-2.56 1.767-5.61 2.403-8.38 1.81-2.42-.516-4.42-1.92-5.53-3.79-.93-1.56-1.15-3.3-.69-4.75l-4.56-1.446L59.325 65c.36-1.12 1.068-1.905 1.84-2.22.25-.103.48-.14.668-.13.06.006.11.015.14.025.01 0 .01 0-.01-.01-.02-.015-.054-.045-.094-.088-.06-.064-.12-.145-.17-.244-.15-.29-.23-.678-.18-1.11l-.005.04c.15-1.332 1.38-2.523 3.035-2.523-2.65 0-4.79 2.144-4.79 4.787s2.14 4.785 4.78 4.785z\"></path>\n </g>\n</svg>" }, "$:/core/images/stamp": { "title": "$:/core/images/stamp", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-stamp tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M49.7334301,64 L16.0098166,64 C11.5838751,64 8,67.5829053 8,72.002643 L8,74.4986785 L8,97 L120,97 L120,74.4986785 L120,72.002643 C120,67.5737547 116.413883,64 111.990183,64 L78.2665699,64 C76.502049,60.7519149 75.5,57.0311962 75.5,53.0769231 C75.5,46.6017951 78.1869052,40.7529228 82.5087769,36.5800577 C85.3313113,32.7688808 87,28.0549983 87,22.952183 C87,10.2760423 76.7025492,0 64,0 C51.2974508,0 41,10.2760423 41,22.952183 C41,28.0549983 42.6686887,32.7688808 45.4912231,36.5800577 C49.8130948,40.7529228 52.5,46.6017951 52.5,53.0769231 C52.5,57.0311962 51.497951,60.7519149 49.7334301,64 Z M8,104 L120,104 L120,112 L8,112 L8,104 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/star-filled": { "title": "$:/core/images/star-filled", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-star-filled tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"nonzero\">\n <path d=\"M61.8361286,96.8228569 L99.1627704,124.110219 C101.883827,126.099427 105.541968,123.420868 104.505636,120.198072 L90.2895569,75.9887263 L89.0292911,79.8977279 L126.314504,52.5528988 C129.032541,50.5595011 127.635256,46.2255025 124.273711,46.2229134 L78.1610486,46.1873965 L81.4604673,48.6032923 L67.1773543,4.41589688 C66.1361365,1.19470104 61.6144265,1.19470104 60.5732087,4.41589688 L46.2900957,48.6032923 L49.5895144,46.1873965 L3.47685231,46.2229134 C0.115307373,46.2255025 -1.28197785,50.5595011 1.43605908,52.5528988 L38.7212719,79.8977279 L37.4610061,75.9887263 L23.2449266,120.198072 C22.2085954,123.420868 25.8667356,126.099427 28.5877926,124.110219 L65.9144344,96.8228569 L61.8361286,96.8228569 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/storyview-classic": { "title": "$:/core/images/storyview-classic", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-storyview-classic tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M8.00697327,0 C3.58484404,0 0,3.59075293 0,8.00697327 L0,119.993027 C0,124.415156 3.59075293,128 8.00697327,128 L119.993027,128 C124.415156,128 128,124.409247 128,119.993027 L128,8.00697327 C128,3.58484404 124.409247,0 119.993027,0 L8.00697327,0 L8.00697327,0 Z M23.9992458,16 C19.5813843,16 16,19.5776607 16,23.9924054 L16,40.0075946 C16,44.4216782 19.5881049,48 23.9992458,48 L104.000754,48 C108.418616,48 112,44.4223393 112,40.0075946 L112,23.9924054 C112,19.5783218 108.411895,16 104.000754,16 L23.9992458,16 L23.9992458,16 Z M23.9992458,64 C19.5813843,64 16,67.5907123 16,72 C16,76.418278 19.5881049,80 23.9992458,80 L104.000754,80 C108.418616,80 112,76.4092877 112,72 C112,67.581722 108.411895,64 104.000754,64 L23.9992458,64 L23.9992458,64 Z M23.9992458,96 C19.5813843,96 16,99.5907123 16,104 C16,108.418278 19.5881049,112 23.9992458,112 L104.000754,112 C108.418616,112 112,108.409288 112,104 C112,99.581722 108.411895,96 104.000754,96 L23.9992458,96 L23.9992458,96 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/storyview-pop": { "title": "$:/core/images/storyview-pop", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-storyview-pop tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M8.00697327,0 C3.58484404,0 0,3.59075293 0,8.00697327 L0,119.993027 C0,124.415156 3.59075293,128 8.00697327,128 L119.993027,128 C124.415156,128 128,124.409247 128,119.993027 L128,8.00697327 C128,3.58484404 124.409247,0 119.993027,0 L8.00697327,0 L8.00697327,0 Z M23.9992458,16 C19.5813843,16 16,19.5776607 16,23.9924054 L16,40.0075946 C16,44.4216782 19.5881049,48 23.9992458,48 L104.000754,48 C108.418616,48 112,44.4223393 112,40.0075946 L112,23.9924054 C112,19.5783218 108.411895,16 104.000754,16 L23.9992458,16 L23.9992458,16 Z M16.0098166,56 C11.586117,56 8,59.5776607 8,63.9924054 L8,80.0075946 C8,84.4216782 11.5838751,88 16.0098166,88 L111.990183,88 C116.413883,88 120,84.4223393 120,80.0075946 L120,63.9924054 C120,59.5783218 116.416125,56 111.990183,56 L16.0098166,56 L16.0098166,56 Z M23.9992458,96 C19.5813843,96 16,99.5907123 16,104 C16,108.418278 19.5881049,112 23.9992458,112 L104.000754,112 C108.418616,112 112,108.409288 112,104 C112,99.581722 108.411895,96 104.000754,96 L23.9992458,96 L23.9992458,96 Z M23.9992458,64 C19.5813843,64 16,67.5907123 16,72 C16,76.418278 19.5881049,80 23.9992458,80 L104.000754,80 C108.418616,80 112,76.4092877 112,72 C112,67.581722 108.411895,64 104.000754,64 L23.9992458,64 L23.9992458,64 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/storyview-zoomin": { "title": "$:/core/images/storyview-zoomin", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-storyview-zoomin tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M8.00697327,0 C3.58484404,0 0,3.59075293 0,8.00697327 L0,119.993027 C0,124.415156 3.59075293,128 8.00697327,128 L119.993027,128 C124.415156,128 128,124.409247 128,119.993027 L128,8.00697327 C128,3.58484404 124.409247,0 119.993027,0 L8.00697327,0 L8.00697327,0 Z M23.9992458,16 C19.5813843,16 16,19.578055 16,24.0085154 L16,71.9914846 C16,76.4144655 19.5881049,80 23.9992458,80 L104.000754,80 C108.418616,80 112,76.421945 112,71.9914846 L112,24.0085154 C112,19.5855345 108.411895,16 104.000754,16 L23.9992458,16 L23.9992458,16 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/strikethrough": { "title": "$:/core/images/strikethrough", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-strikethrough tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M92.793842,38.7255689 L108.215529,38.7255689 C107.987058,31.985687 106.70193,26.1883331 104.360107,21.3333333 C102.018284,16.4783336 98.8197436,12.4516001 94.7643909,9.25301205 C90.7090382,6.05442399 85.9969032,3.71263572 80.6278447,2.22757697 C75.2587862,0.742518233 69.4328739,0 63.1499331,0 C57.552404,0 52.0977508,0.713959839 46.7858099,2.14190094 C41.473869,3.56984203 36.7331757,5.74027995 32.5635877,8.65327979 C28.3939997,11.5662796 25.0526676,15.2788708 22.5394913,19.7911647 C20.026315,24.3034585 18.7697456,29.6438781 18.7697456,35.8125837 C18.7697456,41.4101128 19.883523,46.0651309 22.1111111,49.7777778 C24.3386992,53.4904246 27.3087722,56.5176144 31.021419,58.8594378 C34.7340659,61.2012612 38.9321497,63.0861151 43.6157965,64.5140562 C48.2994433,65.9419973 53.068695,67.1985666 57.9236948,68.2838019 C62.7786945,69.3690371 67.5479462,70.4256977 72.231593,71.4538153 C76.9152398,72.4819329 81.1133237,73.8241773 84.8259705,75.480589 C88.5386174,77.1370007 91.5086903,79.2788802 93.7362784,81.9062918 C95.9638666,84.5337035 97.0776439,87.9607107 97.0776439,92.1874163 C97.0776439,96.6425926 96.1637753,100.298067 94.3360107,103.153949 C92.5082461,106.009831 90.109341,108.265944 87.1392236,109.922356 C84.1691061,111.578768 80.827774,112.749662 77.1151272,113.435074 C73.4024803,114.120485 69.7184476,114.463186 66.0629183,114.463186 C61.4935068,114.463186 57.0383974,113.892018 52.6974565,112.749665 C48.3565156,111.607312 44.5582492,109.836692 41.3025435,107.437751 C38.0468378,105.03881 35.4194656,101.983062 33.4203481,98.270415 C31.4212305,94.5577681 30.4216867,90.1312171 30.4216867,84.9906292 L15,84.9906292 C15,92.4159229 16.3422445,98.8415614 19.0267738,104.267738 C21.711303,109.693914 25.3667774,114.149023 29.9933066,117.633199 C34.6198357,121.117376 39.9888137,123.71619 46.1004016,125.429719 C52.2119895,127.143248 58.6947448,128 65.5488621,128 C71.1463912,128 76.7723948,127.343157 82.4270415,126.029451 C88.0816882,124.715745 93.1936407,122.602424 97.7630522,119.689424 C102.332464,116.776425 106.073613,113.006717 108.986613,108.380187 C111.899613,103.753658 113.356091,98.1847715 113.356091,91.6733601 C113.356091,85.6188899 112.242314,80.5926126 110.014726,76.5943775 C107.787137,72.5961424 104.817065,69.2833688 101.104418,66.6559572 C97.3917708,64.0285455 93.193687,61.9437828 88.5100402,60.4016064 C83.8263934,58.85943 79.0571416,57.5171855 74.2021419,56.3748327 C69.3471422,55.2324798 64.5778904,54.1758192 59.8942436,53.2048193 C55.2105968,52.2338193 51.012513,51.0058084 47.2998661,49.5207497 C43.5872193,48.0356909 40.6171463,46.1222786 38.3895582,43.7804552 C36.1619701,41.4386318 35.0481928,38.3828836 35.0481928,34.6131191 C35.0481928,30.6148841 35.8192694,27.273552 37.3614458,24.5890228 C38.9036222,21.9044935 40.9598265,19.762614 43.5301205,18.1633199 C46.1004145,16.5640259 49.041929,15.4216902 52.3547523,14.7362784 C55.6675757,14.0508667 59.0374661,13.708166 62.4645248,13.708166 C70.9179361,13.708166 77.8576257,15.6786952 83.2838019,19.6198126 C88.709978,23.56093 91.8799597,29.9294518 92.793842,38.7255689 L92.793842,38.7255689 Z\"></path>\n <rect x=\"5\" y=\"54\" width=\"118\" height=\"16\"></rect>\n </g>\n</svg>" }, "$:/core/images/subscript": { "title": "$:/core/images/subscript", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-subscript tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M2.27170276,16 L22.1825093,16 L43.8305003,49.6746527 L66.4138983,16 L85.1220387,16 L53.5854592,61.9685735 L87.3937414,111.411516 L67.0820462,111.411516 L43.295982,74.9306422 L19.1090291,111.411516 L0,111.411516 L33.8082822,61.9685735 L2.27170276,16 Z M127.910914,128.411516 L85.3276227,128.411516 C85.3870139,123.24448 86.6342108,118.730815 89.0692508,114.870386 C91.5042907,111.009956 94.8301491,107.654403 99.0469256,104.803624 C101.066227,103.318844 103.174584,101.878629 105.372059,100.482935 C107.569534,99.0872413 109.588805,97.5876355 111.429933,95.9840726 C113.271061,94.3805097 114.785514,92.6433426 115.973338,90.7725192 C117.161163,88.9016958 117.784761,86.7487964 117.844152,84.3137564 C117.844152,83.1853233 117.710524,81.9826691 117.443264,80.7057579 C117.176003,79.4288467 116.656338,78.2410402 115.884252,77.1423026 C115.112166,76.0435651 114.04314,75.123015 112.677142,74.3806248 C111.311144,73.6382345 109.529434,73.267045 107.331959,73.267045 C105.312658,73.267045 103.634881,73.6679297 102.298579,74.4697112 C100.962276,75.2714926 99.8932503,76.3702137 99.0914688,77.7659073 C98.2896874,79.161601 97.6957841,80.8096826 97.3097412,82.7102016 C96.9236982,84.6107206 96.7009845,86.6596869 96.6415933,88.857162 L86.4857457,88.857162 C86.4857457,85.4124713 86.9460207,82.2202411 87.8665846,79.2803758 C88.7871485,76.3405105 90.1679736,73.801574 92.0091014,71.6634901 C93.8502292,69.5254062 96.092214,67.8476295 98.7351233,66.6301095 C101.378033,65.4125895 104.451482,64.8038386 107.955564,64.8038386 C111.756602,64.8038386 114.933984,65.4274371 117.487807,66.6746527 C120.041629,67.9218683 122.105443,69.4957119 123.67931,71.3962309 C125.253178,73.2967499 126.366746,75.3605638 127.02005,77.5877345 C127.673353,79.8149053 128,81.9381095 128,83.9574109 C128,86.4518421 127.613963,88.7086746 126.841877,90.727976 C126.069791,92.7472774 125.03046,94.6032252 123.723854,96.2958749 C122.417247,97.9885247 120.932489,99.5475208 119.269534,100.97291 C117.60658,102.398299 115.884261,103.734582 114.102524,104.981797 C112.320788,106.229013 110.539078,107.416819 108.757341,108.545253 C106.975605,109.673686 105.327523,110.802102 103.813047,111.930535 C102.298571,113.058968 100.977136,114.231927 99.8487031,115.449447 C98.7202699,116.666967 97.9481956,117.958707 97.5324571,119.324705 L127.910914,119.324705 L127.910914,128.411516 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/superscript": { "title": "$:/core/images/superscript", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-superscript tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M2.27170276,16 L22.1825093,16 L43.8305003,49.6746527 L66.4138983,16 L85.1220387,16 L53.5854592,61.9685735 L87.3937414,111.411516 L67.0820462,111.411516 L43.295982,74.9306422 L19.1090291,111.411516 L0,111.411516 L33.8082822,61.9685735 L2.27170276,16 Z M127.910914,63.4115159 L85.3276227,63.4115159 C85.3870139,58.2444799 86.6342108,53.7308149 89.0692508,49.8703857 C91.5042907,46.0099565 94.8301491,42.654403 99.0469256,39.8036245 C101.066227,38.318844 103.174584,36.8786285 105.372059,35.4829349 C107.569534,34.0872413 109.588805,32.5876355 111.429933,30.9840726 C113.271061,29.3805097 114.785514,27.6433426 115.973338,25.7725192 C117.161163,23.9016958 117.784761,21.7487964 117.844152,19.3137564 C117.844152,18.1853233 117.710524,16.9826691 117.443264,15.7057579 C117.176003,14.4288467 116.656338,13.2410402 115.884252,12.1423026 C115.112166,11.0435651 114.04314,10.123015 112.677142,9.38062477 C111.311144,8.63823453 109.529434,8.26704499 107.331959,8.26704499 C105.312658,8.26704499 103.634881,8.6679297 102.298579,9.46971115 C100.962276,10.2714926 99.8932503,11.3702137 99.0914688,12.7659073 C98.2896874,14.161601 97.6957841,15.8096826 97.3097412,17.7102016 C96.9236982,19.6107206 96.7009845,21.6596869 96.6415933,23.857162 L86.4857457,23.857162 C86.4857457,20.4124713 86.9460207,17.2202411 87.8665846,14.2803758 C88.7871485,11.3405105 90.1679736,8.80157397 92.0091014,6.6634901 C93.8502292,4.52540622 96.092214,2.84762946 98.7351233,1.63010947 C101.378033,0.412589489 104.451482,-0.196161372 107.955564,-0.196161372 C111.756602,-0.196161372 114.933984,0.427437071 117.487807,1.67465266 C120.041629,2.92186826 122.105443,4.49571195 123.67931,6.39623095 C125.253178,8.29674995 126.366746,10.3605638 127.02005,12.5877345 C127.673353,14.8149053 128,16.9381095 128,18.9574109 C128,21.4518421 127.613963,23.7086746 126.841877,25.727976 C126.069791,27.7472774 125.03046,29.6032252 123.723854,31.2958749 C122.417247,32.9885247 120.932489,34.5475208 119.269534,35.97291 C117.60658,37.3982993 115.884261,38.7345816 114.102524,39.9817972 C112.320788,41.2290128 110.539078,42.4168194 108.757341,43.5452525 C106.975605,44.6736857 105.327523,45.8021019 103.813047,46.9305351 C102.298571,48.0589682 100.977136,49.2319272 99.8487031,50.4494472 C98.7202699,51.6669672 97.9481956,52.9587068 97.5324571,54.3247048 L127.910914,54.3247048 L127.910914,63.4115159 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/tag-button": { "title": "$:/core/images/tag-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-tag-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M18.1643182,47.6600756 L18.1677196,51.7651887 C18.1708869,55.5878829 20.3581578,60.8623899 23.0531352,63.5573673 L84.9021823,125.406414 C87.5996731,128.103905 91.971139,128.096834 94.6717387,125.396234 L125.766905,94.3010679 C128.473612,91.5943612 128.472063,87.2264889 125.777085,84.5315115 L63.9280381,22.6824644 C61.2305472,19.9849735 55.9517395,17.801995 52.1318769,17.8010313 L25.0560441,17.7942007 C21.2311475,17.7932358 18.1421354,20.8872832 18.1452985,24.7049463 L18.1535504,34.6641936 C18.2481119,34.6754562 18.3439134,34.6864294 18.4409623,34.6971263 C22.1702157,35.1081705 26.9295004,34.6530132 31.806204,33.5444844 C32.1342781,33.0700515 32.5094815,32.6184036 32.9318197,32.1960654 C35.6385117,29.4893734 39.5490441,28.718649 42.94592,29.8824694 C43.0432142,29.8394357 43.1402334,29.7961748 43.2369683,29.7526887 L43.3646982,30.0368244 C44.566601,30.5115916 45.6933052,31.2351533 46.6655958,32.2074439 C50.4612154,36.0030635 50.4663097,42.1518845 46.6769742,45.94122 C43.0594074,49.5587868 37.2914155,49.7181264 33.4734256,46.422636 C28.1082519,47.5454734 22.7987486,48.0186448 18.1643182,47.6600756 Z\"></path>\n <path d=\"M47.6333528,39.5324628 L47.6562932,39.5834939 C37.9670934,43.9391617 26.0718874,46.3819521 17.260095,45.4107025 C5.27267473,44.0894301 -1.02778744,36.4307276 2.44271359,24.0779512 C5.56175386,12.9761516 14.3014034,4.36129832 24.0466405,1.54817001 C34.7269254,-1.53487574 43.7955833,3.51606438 43.7955834,14.7730751 L35.1728168,14.7730752 C35.1728167,9.91428944 32.0946059,8.19982862 26.4381034,9.83267419 C19.5270911,11.8276553 13.046247,18.2159574 10.7440788,26.4102121 C8.82861123,33.2280582 11.161186,36.0634845 18.2047888,36.8398415 C25.3302805,37.6252244 35.7353482,35.4884477 44.1208333,31.7188498 L44.1475077,31.7781871 C44.159701,31.7725635 44.1718402,31.7671479 44.1839238,31.7619434 C45.9448098,31.0035157 50.4503245,38.3109156 47.7081571,39.5012767 C47.6834429,39.512005 47.6585061,39.5223987 47.6333528,39.5324628 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/theme-button": { "title": "$:/core/images/theme-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-theme-button tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M55.854113,66.9453198 C54.3299482,65.1432292 53.0133883,63.518995 51.9542746,62.1263761 C40.8899947,47.578055 35.3091807,55.2383404 28.9941893,62.1263758 C22.6791979,69.0144112 30.6577916,74.5954741 24.6646171,79.4611023 C18.6714426,84.3267304 19.0414417,86.0133155 8.92654943,77.1119468 C-1.18834284,68.2105781 -1.88793412,65.7597832 2.7553553,60.6807286 C7.39864472,55.601674 11.2794845,63.5989423 20.7646627,54.5728325 C30.2498409,45.5467226 22.2819131,37.5470737 22.2819131,37.5470737 C22.2819131,37.5470737 42.0310399,-2.82433362 68.4206088,0.157393922 C94.8101776,3.13912147 58.4373806,-3.70356506 49.3898693,27.958066 C45.5161782,41.5139906 50.1107906,38.3197672 57.4560458,44.0453955 C59.1625767,45.3756367 63.8839488,48.777453 70.127165,53.3625321 C63.9980513,59.2416709 58.9704753,64.0315459 55.854113,66.9453198 Z M67.4952439,79.8919946 C83.5082212,96.9282402 105.237121,117.617674 112.611591,120.312493 C123.044132,124.12481 128.000001,117.170903 128,105.522947 C127.999999,98.3705516 104.170675,78.980486 84.0760493,63.7529565 C76.6683337,70.9090328 70.7000957,76.7055226 67.4952439,79.8919946 Z\"></path>\n <path d=\"M58.2852966,138.232794 L58.2852966,88.3943645 C56.318874,88.3923153 54.7254089,86.7952906 54.7254089,84.8344788 C54.7254089,82.8684071 56.3175932,81.2745911 58.2890859,81.2745911 L79.6408336,81.2745911 C81.608998,81.2745911 83.2045105,82.8724076 83.2045105,84.8344788 C83.2045105,86.7992907 81.614366,88.3923238 79.6446228,88.3943645 L79.6446228,88.3943646 L79.6446228,138.232794 C79.6446228,144.131009 74.8631748,148.912457 68.9649597,148.912457 C63.0667446,148.912457 58.2852966,144.131009 58.2852966,138.232794 Z M65.405072,-14.8423767 L72.5248474,-14.8423767 L76.0847351,-0.690681892 L72.5248474,6.51694947 L72.5248474,81.2745911 L65.405072,81.2745911 L65.405072,6.51694947 L61.8451843,-0.690681892 L65.405072,-14.8423767 Z\" transform=\"translate(68.964960, 67.035040) rotate(45.000000) translate(-68.964960, -67.035040) \"></path>\n </g>\n</svg>" }, "$:/core/images/timestamp-off": { "title": "$:/core/images/timestamp-off", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-timestamp-off tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M58.25 11C26.08 11 0 37.082 0 69.25s26.08 58.25 58.25 58.25c32.175 0 58.25-26.082 58.25-58.25S90.425 11 58.25 11zm0 100.5C34.914 111.5 16 92.586 16 69.25 16 45.92 34.914 27 58.25 27s42.25 18.92 42.25 42.25c0 23.336-18.914 42.25-42.25 42.25zM49.704 10c-2.762 0-5-2.24-5-5-.004-2.756 2.238-5 5-5H66.69c2.762 0 5.002 2.24 5 5 .006 2.757-2.238 5-5 5H49.705z\"/><path d=\"M58.25 35.88c-18.777 0-33.998 15.224-33.998 33.998 0 18.773 15.22 34.002 33.998 34.002 18.784 0 34.002-15.23 34.002-34.002 0-18.774-15.218-33.998-34.002-33.998zm-3.03 50.123H44.196v-34H55.22v34zm16.976 0H61.17v-34h11.025v34z\"/>\n </g>\n</svg>\n" }, "$:/core/images/timestamp-on": { "title": "$:/core/images/timestamp-on", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-timestamp-on tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M58.25 11C26.08 11 0 37.082 0 69.25s26.08 58.25 58.25 58.25c32.175 0 58.25-26.082 58.25-58.25S90.425 11 58.25 11zm0 100.5C34.914 111.5 16 92.586 16 69.25 16 45.92 34.914 27 58.25 27s42.25 18.92 42.25 42.25c0 23.336-18.914 42.25-42.25 42.25zM49.704 10c-2.762 0-5-2.24-5-5-.004-2.756 2.238-5 5-5H66.69c2.762 0 5.002 2.24 5 5 .006 2.757-2.238 5-5 5H49.705z\"/><path d=\"M13.41 27.178c-2.116 1.775-5.27 1.498-7.045-.613-1.772-2.11-1.498-5.27.616-7.047l9.95-8.348c2.115-1.774 5.27-1.5 7.045.618 1.775 2.108 1.498 5.27-.616 7.043l-9.95 8.348zM102.983 27.178c2.116 1.775 5.27 1.498 7.045-.613 1.772-2.11 1.498-5.27-.616-7.047l-9.95-8.348c-2.114-1.774-5.27-1.5-7.044.618-1.775 2.108-1.498 5.27.616 7.043l9.95 8.348zM65.097 71.072c0 3.826-3.09 6.928-6.897 6.928-3.804.006-6.9-3.102-6.903-6.928 0 0 4.76-39.072 6.903-39.072s6.897 39.072 6.897 39.072z\"/>\n </g>\n</svg>\n" }, "$:/core/images/tip": { "title": "$:/core/images/tip", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-tip tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M64,128.241818 C99.346224,128.241818 128,99.5880417 128,64.2418177 C128,28.8955937 99.346224,0.241817675 64,0.241817675 C28.653776,0.241817675 0,28.8955937 0,64.2418177 C0,99.5880417 28.653776,128.241818 64,128.241818 Z M75.9358659,91.4531941 C75.3115438,95.581915 70.2059206,98.8016748 64,98.8016748 C57.7940794,98.8016748 52.6884562,95.581915 52.0641341,91.4531941 C54.3299053,94.0502127 58.8248941,95.8192805 64,95.8192805 C69.1751059,95.8192805 73.6700947,94.0502127 75.9358659,91.4531941 L75.9358659,91.4531941 Z M75.9358659,95.9453413 C75.3115438,100.074062 70.2059206,103.293822 64,103.293822 C57.7940794,103.293822 52.6884562,100.074062 52.0641341,95.9453413 C54.3299053,98.5423599 58.8248941,100.311428 64,100.311428 C69.1751059,100.311428 73.6700947,98.5423599 75.9358659,95.9453413 L75.9358659,95.9453413 Z M75.9358659,100.40119 C75.3115438,104.529911 70.2059206,107.74967 64,107.74967 C57.7940794,107.74967 52.6884562,104.529911 52.0641341,100.40119 C54.3299053,102.998208 58.8248941,104.767276 64,104.767276 C69.1751059,104.767276 73.6700947,102.998208 75.9358659,100.40119 L75.9358659,100.40119 Z M75.9358659,104.893337 C75.3115438,109.022058 70.2059206,112.241818 64,112.241818 C57.7940794,112.241818 52.6884562,109.022058 52.0641341,104.893337 C54.3299053,107.490356 58.8248941,109.259423 64,109.259423 C69.1751059,109.259423 73.6700947,107.490356 75.9358659,104.893337 L75.9358659,104.893337 Z M64.3010456,24.2418177 C75.9193117,24.2418188 88.0000013,32.0619847 88,48.4419659 C87.9999987,64.8219472 75.9193018,71.7540963 75.9193021,83.5755932 C75.9193022,89.4486648 70.0521957,92.8368862 63.9999994,92.8368862 C57.947803,92.8368862 51.9731007,89.8295115 51.9731007,83.5755932 C51.9731007,71.1469799 39.9999998,65.4700602 40,48.4419647 C40.0000002,31.4138691 52.6827796,24.2418166 64.3010456,24.2418177 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/twitter": { "title": "$:/core/images/twitter", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-twitter tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M41.6263422,115.803477 C27.0279663,115.803477 13.4398394,111.540813 1.99987456,104.234833 C4.02221627,104.472643 6.08004574,104.594302 8.16644978,104.594302 C20.277456,104.594302 31.4238403,100.47763 40.270894,93.5715185 C28.9590538,93.3635501 19.4123842,85.9189246 16.1230832,75.6885328 C17.7011365,75.9892376 19.320669,76.1503787 20.9862896,76.1503787 C23.344152,76.1503787 25.6278127,75.8359011 27.7971751,75.247346 C15.9709927,72.8821073 7.06079851,62.4745062 7.06079851,49.9982394 C7.06079851,49.8898938 7.06079851,49.7820074 7.06264203,49.67458 C10.5482779,51.6032228 14.5339687,52.7615103 18.7717609,52.8951059 C11.8355159,48.277565 7.2714207,40.3958845 7.2714207,31.4624258 C7.2714207,26.7434257 8.54621495,22.3200804 10.7713439,18.5169676 C23.5211299,34.0957738 42.568842,44.3472839 64.0532269,45.4210985 C63.6126256,43.5365285 63.3835682,41.5711584 63.3835682,39.5529928 C63.3835682,25.3326379 74.95811,13.8034766 89.2347917,13.8034766 C96.6697089,13.8034766 103.387958,16.930807 108.103682,21.9353619 C113.991886,20.780288 119.52429,18.6372496 124.518847,15.6866694 C122.588682,21.6993889 118.490075,26.7457211 113.152623,29.9327334 C118.381769,29.3102055 123.363882,27.926045 127.999875,25.8780385 C124.534056,31.0418981 120.151087,35.5772616 115.100763,39.2077561 C115.150538,40.3118708 115.175426,41.4224128 115.175426,42.538923 C115.175426,76.5663154 89.1744164,115.803477 41.6263422,115.803477\"></path>\n </g>\n</svg>\n" }, "$:/core/images/underline": { "title": "$:/core/images/underline", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-underline tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M7,117.421488 L121.247934,117.421488 L121.247934,128 L7,128 L7,117.421488 Z M104.871212,98.8958333 L104.871212,0 L88.6117424,0 L88.6117424,55.8560606 C88.6117424,60.3194668 88.0060035,64.432115 86.7945076,68.1941288 C85.5830116,71.9561425 83.7657949,75.239885 81.342803,78.0454545 C78.9198111,80.8510241 75.8911167,83.0189317 72.2566288,84.5492424 C68.6221409,86.0795531 64.3182067,86.844697 59.344697,86.844697 C53.0959284,86.844697 48.1862552,85.0593613 44.6155303,81.4886364 C41.0448054,77.9179114 39.2594697,73.0720003 39.2594697,66.9507576 L39.2594697,0 L23,0 L23,65.0378788 C23,70.3939662 23.5419769,75.2717583 24.625947,79.6714015 C25.709917,84.0710447 27.5908957,87.864883 30.2689394,91.0530303 C32.9469831,94.2411776 36.4538925,96.6960141 40.7897727,98.4176136 C45.125653,100.139213 50.545422,101 57.0492424,101 C64.3182182,101 70.630655,99.5653553 75.9867424,96.6960227 C81.3428298,93.8266902 85.742407,89.33147 89.1856061,83.2102273 L89.5681818,83.2102273 L89.5681818,98.8958333 L104.871212,98.8958333 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/unfold-all-button": { "title": "$:/core/images/unfold-all-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-unfold-all tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <rect x=\"0\" y=\"0\" width=\"128\" height=\"16\" rx=\"8\"></rect>\n <rect x=\"0\" y=\"64\" width=\"128\" height=\"16\" rx=\"8\"></rect>\n <path d=\"M85.598226,8.34884273 C84.1490432,6.89863875 82.1463102,6 79.9340286,6 L47.9482224,6 C43.5292967,6 39.9411255,9.581722 39.9411255,14 C39.9411255,18.4092877 43.5260249,22 47.9482224,22 L71.9411255,22 L71.9411255,45.9929031 C71.9411255,50.4118288 75.5228475,54 79.9411255,54 C84.3504132,54 87.9411255,50.4151006 87.9411255,45.9929031 L87.9411255,14.0070969 C87.9411255,11.7964515 87.0447363,9.79371715 85.5956548,8.34412458 Z\" transform=\"translate(63.941125, 30.000000) scale(1, -1) rotate(-45.000000) translate(-63.941125, -30.000000) \"></path>\n <path d=\"M85.6571005,72.2899682 C84.2079177,70.8397642 82.2051847,69.9411255 79.9929031,69.9411255 L48.0070969,69.9411255 C43.5881712,69.9411255 40,73.5228475 40,77.9411255 C40,82.3504132 43.5848994,85.9411255 48.0070969,85.9411255 L72,85.9411255 L72,109.934029 C72,114.352954 75.581722,117.941125 80,117.941125 C84.4092877,117.941125 88,114.356226 88,109.934029 L88,77.9482224 C88,75.737577 87.1036108,73.7348426 85.6545293,72.2852501 Z\" transform=\"translate(64.000000, 93.941125) scale(1, -1) rotate(-45.000000) translate(-64.000000, -93.941125) \"></path>\n </g>\n</svg>" }, "$:/core/images/unfold-button": { "title": "$:/core/images/unfold-button", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-unfold tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <rect x=\"0\" y=\"0\" width=\"128\" height=\"16\" rx=\"8\"></rect>\n <path d=\"M85.598226,11.3488427 C84.1490432,9.89863875 82.1463102,9 79.9340286,9 L47.9482224,9 C43.5292967,9 39.9411255,12.581722 39.9411255,17 C39.9411255,21.4092877 43.5260249,25 47.9482224,25 L71.9411255,25 L71.9411255,48.9929031 C71.9411255,53.4118288 75.5228475,57 79.9411255,57 C84.3504132,57 87.9411255,53.4151006 87.9411255,48.9929031 L87.9411255,17.0070969 C87.9411255,14.7964515 87.0447363,12.7937171 85.5956548,11.3441246 Z\" transform=\"translate(63.941125, 33.000000) scale(1, -1) rotate(-45.000000) translate(-63.941125, -33.000000) \"></path>\n <path d=\"M85.6571005,53.4077172 C84.2079177,51.9575133 82.2051847,51.0588745 79.9929031,51.0588745 L48.0070969,51.0588745 C43.5881712,51.0588745 40,54.6405965 40,59.0588745 C40,63.4681622 43.5848994,67.0588745 48.0070969,67.0588745 L72,67.0588745 L72,91.0517776 C72,95.4707033 75.581722,99.0588745 80,99.0588745 C84.4092877,99.0588745 88,95.4739751 88,91.0517776 L88,59.0659714 C88,56.855326 87.1036108,54.8525917 85.6545293,53.4029991 Z\" transform=\"translate(64.000000, 75.058875) scale(1, -1) rotate(-45.000000) translate(-64.000000, -75.058875) \"></path>\n </g>\n</svg>" }, "$:/core/images/unlocked-padlock": { "title": "$:/core/images/unlocked-padlock", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-unlocked-padlock tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M48.6266053,64 L105,64 L105,96.0097716 C105,113.673909 90.6736461,128 73.001193,128 L55.998807,128 C38.3179793,128 24,113.677487 24,96.0097716 L24,64 L30.136303,64 C19.6806213,51.3490406 2.77158986,28.2115132 25.8366966,8.85759246 C50.4723026,-11.8141335 71.6711028,13.2108337 81.613302,25.0594855 C91.5555012,36.9081373 78.9368488,47.4964439 69.1559674,34.9513593 C59.375086,22.4062748 47.9893192,10.8049522 35.9485154,20.9083862 C23.9077117,31.0118202 34.192312,43.2685325 44.7624679,55.8655518 C47.229397,58.805523 48.403443,61.5979188 48.6266053,64 Z M67.7315279,92.3641717 C70.8232551,91.0923621 73,88.0503841 73,84.5 C73,79.8055796 69.1944204,76 64.5,76 C59.8055796,76 56,79.8055796 56,84.5 C56,87.947435 58.0523387,90.9155206 61.0018621,92.2491029 L55.9067479,115.020857 L72.8008958,115.020857 L67.7315279,92.3641717 L67.7315279,92.3641717 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/up-arrow": { "created": "20150316000544368", "modified": "20150316000831867", "tags": "$:/tags/Image", "title": "$:/core/images/up-arrow", "text": "<svg class=\"tc-image-up-arrow tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n<path transform=\"rotate(-135, 63.8945, 64.1752)\" d=\"m109.07576,109.35336c-1.43248,1.43361 -3.41136,2.32182 -5.59717,2.32182l-79.16816,0c-4.36519,0 -7.91592,-3.5444 -7.91592,-7.91666c0,-4.36337 3.54408,-7.91667 7.91592,-7.91667l71.25075,0l0,-71.25074c0,-4.3652 3.54442,-7.91592 7.91667,-7.91592c4.36336,0 7.91667,3.54408 7.91667,7.91592l0,79.16815c0,2.1825 -0.88602,4.16136 -2.3185,5.59467l-0.00027,-0.00056l0.00001,-0.00001z\" />\n</svg>\n \n" }, "$:/core/images/video": { "title": "$:/core/images/video", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-video tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M64,12 C29.0909091,12 8.72727273,14.9166667 5.81818182,17.8333333 C2.90909091,20.75 1.93784382e-15,41.1666667 0,64.5 C1.93784382e-15,87.8333333 2.90909091,108.25 5.81818182,111.166667 C8.72727273,114.083333 29.0909091,117 64,117 C98.9090909,117 119.272727,114.083333 122.181818,111.166667 C125.090909,108.25 128,87.8333333 128,64.5 C128,41.1666667 125.090909,20.75 122.181818,17.8333333 C119.272727,14.9166667 98.9090909,12 64,12 Z M54.9161194,44.6182253 C51.102648,42.0759111 48.0112186,43.7391738 48.0112186,48.3159447 L48.0112186,79.6840553 C48.0112186,84.2685636 51.109784,85.9193316 54.9161194,83.3817747 L77.0838806,68.6032672 C80.897352,66.0609529 80.890216,61.9342897 77.0838806,59.3967328 L54.9161194,44.6182253 Z\"></path>\n </g>\n</svg>" }, "$:/core/images/warning": { "title": "$:/core/images/warning", "tags": "$:/tags/Image", "text": "<svg class=\"tc-image-warning tc-image-button\" width=\"22pt\" height=\"22pt\" viewBox=\"0 0 128 128\">\n <g fill-rule=\"evenodd\">\n <path d=\"M57.0717968,11 C60.1509982,5.66666667 67.8490018,5.66666667 70.9282032,11 L126.353829,107 C129.433031,112.333333 125.584029,119 119.425626,119 L8.57437416,119 C2.41597129,119 -1.43303051,112.333333 1.64617093,107 L57.0717968,11 Z M64,37 C59.581722,37 56,40.5820489 56,44.9935776 L56,73.0064224 C56,77.4211534 59.5907123,81 64,81 C68.418278,81 72,77.4179511 72,73.0064224 L72,44.9935776 C72,40.5788466 68.4092877,37 64,37 Z M64,104 C68.418278,104 72,100.418278 72,96 C72,91.581722 68.418278,88 64,88 C59.581722,88 56,91.581722 56,96 C56,100.418278 59.581722,104 64,104 Z\"></path>\n </g>\n</svg>" }, "$:/language/Buttons/AdvancedSearch/Caption": { "title": "$:/language/Buttons/AdvancedSearch/Caption", "text": "advanced search" }, "$:/language/Buttons/AdvancedSearch/Hint": { "title": "$:/language/Buttons/AdvancedSearch/Hint", "text": "Advanced search" }, "$:/language/Buttons/Cancel/Caption": { "title": "$:/language/Buttons/Cancel/Caption", "text": "cancel" }, "$:/language/Buttons/Cancel/Hint": { "title": "$:/language/Buttons/Cancel/Hint", "text": "Discard changes to this tiddler" }, "$:/language/Buttons/Clone/Caption": { "title": "$:/language/Buttons/Clone/Caption", "text": "clone" }, "$:/language/Buttons/Clone/Hint": { "title": "$:/language/Buttons/Clone/Hint", "text": "Clone this tiddler" }, "$:/language/Buttons/Close/Caption": { "title": "$:/language/Buttons/Close/Caption", "text": "close" }, "$:/language/Buttons/Close/Hint": { "title": "$:/language/Buttons/Close/Hint", "text": "Close this tiddler" }, "$:/language/Buttons/CloseAll/Caption": { "title": "$:/language/Buttons/CloseAll/Caption", "text": "close all" }, "$:/language/Buttons/CloseAll/Hint": { "title": "$:/language/Buttons/CloseAll/Hint", "text": "Close all tiddlers" }, "$:/language/Buttons/CloseOthers/Caption": { "title": "$:/language/Buttons/CloseOthers/Caption", "text": "close others" }, "$:/language/Buttons/CloseOthers/Hint": { "title": "$:/language/Buttons/CloseOthers/Hint", "text": "Close other tiddlers" }, "$:/language/Buttons/ControlPanel/Caption": { "title": "$:/language/Buttons/ControlPanel/Caption", "text": "control panel" }, "$:/language/Buttons/ControlPanel/Hint": { "title": "$:/language/Buttons/ControlPanel/Hint", "text": "Open control panel" }, "$:/language/Buttons/Delete/Caption": { "title": "$:/language/Buttons/Delete/Caption", "text": "delete" }, "$:/language/Buttons/Delete/Hint": { "title": "$:/language/Buttons/Delete/Hint", "text": "Delete this tiddler" }, "$:/language/Buttons/Edit/Caption": { "title": "$:/language/Buttons/Edit/Caption", "text": "edit" }, "$:/language/Buttons/Edit/Hint": { "title": "$:/language/Buttons/Edit/Hint", "text": "Edit this tiddler" }, "$:/language/Buttons/Encryption/Caption": { "title": "$:/language/Buttons/Encryption/Caption", "text": "encryption" }, "$:/language/Buttons/Encryption/Hint": { "title": "$:/language/Buttons/Encryption/Hint", "text": "Set or clear a password for saving this wiki" }, "$:/language/Buttons/Encryption/ClearPassword/Caption": { "title": "$:/language/Buttons/Encryption/ClearPassword/Caption", "text": "clear password" }, "$:/language/Buttons/Encryption/ClearPassword/Hint": { "title": "$:/language/Buttons/Encryption/ClearPassword/Hint", "text": "Clear the password and save this wiki without encryption" }, "$:/language/Buttons/Encryption/SetPassword/Caption": { "title": "$:/language/Buttons/Encryption/SetPassword/Caption", "text": "set password" }, "$:/language/Buttons/Encryption/SetPassword/Hint": { "title": "$:/language/Buttons/Encryption/SetPassword/Hint", "text": "Set a password for saving this wiki with encryption" }, "$:/language/Buttons/ExportPage/Caption": { "title": "$:/language/Buttons/ExportPage/Caption", "text": "export all" }, "$:/language/Buttons/ExportPage/Hint": { "title": "$:/language/Buttons/ExportPage/Hint", "text": "Export all tiddlers" }, "$:/language/Buttons/ExportTiddler/Caption": { "title": "$:/language/Buttons/ExportTiddler/Caption", "text": "export tiddler" }, "$:/language/Buttons/ExportTiddler/Hint": { "title": "$:/language/Buttons/ExportTiddler/Hint", "text": "Export tiddler" }, "$:/language/Buttons/ExportTiddlers/Caption": { "title": "$:/language/Buttons/ExportTiddlers/Caption", "text": "export tiddlers" }, "$:/language/Buttons/ExportTiddlers/Hint": { "title": "$:/language/Buttons/ExportTiddlers/Hint", "text": "Export tiddlers" }, "$:/language/Buttons/Fold/Caption": { "title": "$:/language/Buttons/Fold/Caption", "text": "fold tiddler" }, "$:/language/Buttons/Fold/Hint": { "title": "$:/language/Buttons/Fold/Hint", "text": "Fold the body of this tiddler" }, "$:/language/Buttons/Fold/FoldBar/Caption": { "title": "$:/language/Buttons/Fold/FoldBar/Caption", "text": "fold-bar" }, "$:/language/Buttons/Fold/FoldBar/Hint": { "title": "$:/language/Buttons/Fold/FoldBar/Hint", "text": "Optional bars to fold and unfold tiddlers" }, "$:/language/Buttons/Unfold/Caption": { "title": "$:/language/Buttons/Unfold/Caption", "text": "unfold tiddler" }, "$:/language/Buttons/Unfold/Hint": { "title": "$:/language/Buttons/Unfold/Hint", "text": "Unfold the body of this tiddler" }, "$:/language/Buttons/FoldOthers/Caption": { "title": "$:/language/Buttons/FoldOthers/Caption", "text": "fold other tiddlers" }, "$:/language/Buttons/FoldOthers/Hint": { "title": "$:/language/Buttons/FoldOthers/Hint", "text": "Fold the bodies of other opened tiddlers" }, "$:/language/Buttons/FoldAll/Caption": { "title": "$:/language/Buttons/FoldAll/Caption", "text": "fold all tiddlers" }, "$:/language/Buttons/FoldAll/Hint": { "title": "$:/language/Buttons/FoldAll/Hint", "text": "Fold the bodies of all opened tiddlers" }, "$:/language/Buttons/UnfoldAll/Caption": { "title": "$:/language/Buttons/UnfoldAll/Caption", "text": "unfold all tiddlers" }, "$:/language/Buttons/UnfoldAll/Hint": { "title": "$:/language/Buttons/UnfoldAll/Hint", "text": "Unfold the bodies of all opened tiddlers" }, "$:/language/Buttons/FullScreen/Caption": { "title": "$:/language/Buttons/FullScreen/Caption", "text": "full-screen" }, "$:/language/Buttons/FullScreen/Hint": { "title": "$:/language/Buttons/FullScreen/Hint", "text": "Enter or leave full-screen mode" }, "$:/language/Buttons/Help/Caption": { "title": "$:/language/Buttons/Help/Caption", "text": "help" }, "$:/language/Buttons/Help/Hint": { "title": "$:/language/Buttons/Help/Hint", "text": "Show help panel" }, "$:/language/Buttons/Import/Caption": { "title": "$:/language/Buttons/Import/Caption", "text": "import" }, "$:/language/Buttons/Import/Hint": { "title": "$:/language/Buttons/Import/Hint", "text": "Import many types of file including text, image, TiddlyWiki or JSON" }, "$:/language/Buttons/Info/Caption": { "title": "$:/language/Buttons/Info/Caption", "text": "info" }, "$:/language/Buttons/Info/Hint": { "title": "$:/language/Buttons/Info/Hint", "text": "Show information for this tiddler" }, "$:/language/Buttons/Home/Caption": { "title": "$:/language/Buttons/Home/Caption", "text": "home" }, "$:/language/Buttons/Home/Hint": { "title": "$:/language/Buttons/Home/Hint", "text": "Open the default tiddlers" }, "$:/language/Buttons/Language/Caption": { "title": "$:/language/Buttons/Language/Caption", "text": "language" }, "$:/language/Buttons/Language/Hint": { "title": "$:/language/Buttons/Language/Hint", "text": "Choose the user interface language" }, "$:/language/Buttons/Manager/Caption": { "title": "$:/language/Buttons/Manager/Caption", "text": "tiddler manager" }, "$:/language/Buttons/Manager/Hint": { "title": "$:/language/Buttons/Manager/Hint", "text": "Open tiddler manager" }, "$:/language/Buttons/More/Caption": { "title": "$:/language/Buttons/More/Caption", "text": "more" }, "$:/language/Buttons/More/Hint": { "title": "$:/language/Buttons/More/Hint", "text": "More actions" }, "$:/language/Buttons/NewHere/Caption": { "title": "$:/language/Buttons/NewHere/Caption", "text": "new here" }, "$:/language/Buttons/NewHere/Hint": { "title": "$:/language/Buttons/NewHere/Hint", "text": "Create a new tiddler tagged with this one" }, "$:/language/Buttons/NewJournal/Caption": { "title": "$:/language/Buttons/NewJournal/Caption", "text": "new journal" }, "$:/language/Buttons/NewJournal/Hint": { "title": "$:/language/Buttons/NewJournal/Hint", "text": "Create a new journal tiddler" }, "$:/language/Buttons/NewJournalHere/Caption": { "title": "$:/language/Buttons/NewJournalHere/Caption", "text": "new journal here" }, "$:/language/Buttons/NewJournalHere/Hint": { "title": "$:/language/Buttons/NewJournalHere/Hint", "text": "Create a new journal tiddler tagged with this one" }, "$:/language/Buttons/NewImage/Caption": { "title": "$:/language/Buttons/NewImage/Caption", "text": "new image" }, "$:/language/Buttons/NewImage/Hint": { "title": "$:/language/Buttons/NewImage/Hint", "text": "Create a new image tiddler" }, "$:/language/Buttons/NewMarkdown/Caption": { "title": "$:/language/Buttons/NewMarkdown/Caption", "text": "new Markdown tiddler" }, "$:/language/Buttons/NewMarkdown/Hint": { "title": "$:/language/Buttons/NewMarkdown/Hint", "text": "Create a new Markdown tiddler" }, "$:/language/Buttons/NewTiddler/Caption": { "title": "$:/language/Buttons/NewTiddler/Caption", "text": "new tiddler" }, "$:/language/Buttons/NewTiddler/Hint": { "title": "$:/language/Buttons/NewTiddler/Hint", "text": "Create a new tiddler" }, "$:/language/Buttons/OpenWindow/Caption": { "title": "$:/language/Buttons/OpenWindow/Caption", "text": "open in new window" }, "$:/language/Buttons/OpenWindow/Hint": { "title": "$:/language/Buttons/OpenWindow/Hint", "text": "Open tiddler in new window" }, "$:/language/Buttons/Palette/Caption": { "title": "$:/language/Buttons/Palette/Caption", "text": "palette" }, "$:/language/Buttons/Palette/Hint": { "title": "$:/language/Buttons/Palette/Hint", "text": "Choose the colour palette" }, "$:/language/Buttons/Permalink/Caption": { "title": "$:/language/Buttons/Permalink/Caption", "text": "permalink" }, "$:/language/Buttons/Permalink/Hint": { "title": "$:/language/Buttons/Permalink/Hint", "text": "Set browser address bar to a direct link to this tiddler" }, "$:/language/Buttons/Permaview/Caption": { "title": "$:/language/Buttons/Permaview/Caption", "text": "permaview" }, "$:/language/Buttons/Permaview/Hint": { "title": "$:/language/Buttons/Permaview/Hint", "text": "Set browser address bar to a direct link to all the tiddlers in this story" }, "$:/language/Buttons/Print/Caption": { "title": "$:/language/Buttons/Print/Caption", "text": "print page" }, "$:/language/Buttons/Print/Hint": { "title": "$:/language/Buttons/Print/Hint", "text": "Print the current page" }, "$:/language/Buttons/Refresh/Caption": { "title": "$:/language/Buttons/Refresh/Caption", "text": "refresh" }, "$:/language/Buttons/Refresh/Hint": { "title": "$:/language/Buttons/Refresh/Hint", "text": "Perform a full refresh of the wiki" }, "$:/language/Buttons/Save/Caption": { "title": "$:/language/Buttons/Save/Caption", "text": "ok" }, "$:/language/Buttons/Save/Hint": { "title": "$:/language/Buttons/Save/Hint", "text": "Confirm changes to this tiddler" }, "$:/language/Buttons/SaveWiki/Caption": { "title": "$:/language/Buttons/SaveWiki/Caption", "text": "save changes" }, "$:/language/Buttons/SaveWiki/Hint": { "title": "$:/language/Buttons/SaveWiki/Hint", "text": "Save changes" }, "$:/language/Buttons/StoryView/Caption": { "title": "$:/language/Buttons/StoryView/Caption", "text": "storyview" }, "$:/language/Buttons/StoryView/Hint": { "title": "$:/language/Buttons/StoryView/Hint", "text": "Choose the story visualisation" }, "$:/language/Buttons/HideSideBar/Caption": { "title": "$:/language/Buttons/HideSideBar/Caption", "text": "hide sidebar" }, "$:/language/Buttons/HideSideBar/Hint": { "title": "$:/language/Buttons/HideSideBar/Hint", "text": "Hide sidebar" }, "$:/language/Buttons/ShowSideBar/Caption": { "title": "$:/language/Buttons/ShowSideBar/Caption", "text": "show sidebar" }, "$:/language/Buttons/ShowSideBar/Hint": { "title": "$:/language/Buttons/ShowSideBar/Hint", "text": "Show sidebar" }, "$:/language/Buttons/TagManager/Caption": { "title": "$:/language/Buttons/TagManager/Caption", "text": "tag manager" }, "$:/language/Buttons/TagManager/Hint": { "title": "$:/language/Buttons/TagManager/Hint", "text": "Open tag manager" }, "$:/language/Buttons/Timestamp/Caption": { "title": "$:/language/Buttons/Timestamp/Caption", "text": "timestamps" }, "$:/language/Buttons/Timestamp/Hint": { "title": "$:/language/Buttons/Timestamp/Hint", "text": "Choose whether modifications update timestamps" }, "$:/language/Buttons/Timestamp/On/Caption": { "title": "$:/language/Buttons/Timestamp/On/Caption", "text": "timestamps are on" }, "$:/language/Buttons/Timestamp/On/Hint": { "title": "$:/language/Buttons/Timestamp/On/Hint", "text": "Update timestamps when tiddlers are modified" }, "$:/language/Buttons/Timestamp/Off/Caption": { "title": "$:/language/Buttons/Timestamp/Off/Caption", "text": "timestamps are off" }, "$:/language/Buttons/Timestamp/Off/Hint": { "title": "$:/language/Buttons/Timestamp/Off/Hint", "text": "Don't update timestamps when tiddlers are modified" }, "$:/language/Buttons/Theme/Caption": { "title": "$:/language/Buttons/Theme/Caption", "text": "theme" }, "$:/language/Buttons/Theme/Hint": { "title": "$:/language/Buttons/Theme/Hint", "text": "Choose the display theme" }, "$:/language/Buttons/Bold/Caption": { "title": "$:/language/Buttons/Bold/Caption", "text": "bold" }, "$:/language/Buttons/Bold/Hint": { "title": "$:/language/Buttons/Bold/Hint", "text": "Apply bold formatting to selection" }, "$:/language/Buttons/Clear/Caption": { "title": "$:/language/Buttons/Clear/Caption", "text": "clear" }, "$:/language/Buttons/Clear/Hint": { "title": "$:/language/Buttons/Clear/Hint", "text": "Clear image to solid colour" }, "$:/language/Buttons/EditorHeight/Caption": { "title": "$:/language/Buttons/EditorHeight/Caption", "text": "editor height" }, "$:/language/Buttons/EditorHeight/Caption/Auto": { "title": "$:/language/Buttons/EditorHeight/Caption/Auto", "text": "Automatically adjust height to fit content" }, "$:/language/Buttons/EditorHeight/Caption/Fixed": { "title": "$:/language/Buttons/EditorHeight/Caption/Fixed", "text": "Fixed height:" }, "$:/language/Buttons/EditorHeight/Hint": { "title": "$:/language/Buttons/EditorHeight/Hint", "text": "Choose the height of the text editor" }, "$:/language/Buttons/Excise/Caption": { "title": "$:/language/Buttons/Excise/Caption", "text": "excise" }, "$:/language/Buttons/Excise/Caption/Excise": { "title": "$:/language/Buttons/Excise/Caption/Excise", "text": "Perform excision" }, "$:/language/Buttons/Excise/Caption/MacroName": { "title": "$:/language/Buttons/Excise/Caption/MacroName", "text": "Macro name:" }, "$:/language/Buttons/Excise/Caption/NewTitle": { "title": "$:/language/Buttons/Excise/Caption/NewTitle", "text": "Title of new tiddler:" }, "$:/language/Buttons/Excise/Caption/Replace": { "title": "$:/language/Buttons/Excise/Caption/Replace", "text": "Replace excised text with:" }, "$:/language/Buttons/Excise/Caption/Replace/Macro": { "title": "$:/language/Buttons/Excise/Caption/Replace/Macro", "text": "macro" }, "$:/language/Buttons/Excise/Caption/Replace/Link": { "title": "$:/language/Buttons/Excise/Caption/Replace/Link", "text": "link" }, "$:/language/Buttons/Excise/Caption/Replace/Transclusion": { "title": "$:/language/Buttons/Excise/Caption/Replace/Transclusion", "text": "transclusion" }, "$:/language/Buttons/Excise/Caption/Tag": { "title": "$:/language/Buttons/Excise/Caption/Tag", "text": "Tag new tiddler with the title of this tiddler" }, "$:/language/Buttons/Excise/Caption/TiddlerExists": { "title": "$:/language/Buttons/Excise/Caption/TiddlerExists", "text": "Warning: tiddler already exists" }, "$:/language/Buttons/Excise/Hint": { "title": "$:/language/Buttons/Excise/Hint", "text": "Excise the selected text into a new tiddler" }, "$:/language/Buttons/Heading1/Caption": { "title": "$:/language/Buttons/Heading1/Caption", "text": "heading 1" }, "$:/language/Buttons/Heading1/Hint": { "title": "$:/language/Buttons/Heading1/Hint", "text": "Apply heading level 1 formatting to lines containing selection" }, "$:/language/Buttons/Heading2/Caption": { "title": "$:/language/Buttons/Heading2/Caption", "text": "heading 2" }, "$:/language/Buttons/Heading2/Hint": { "title": "$:/language/Buttons/Heading2/Hint", "text": "Apply heading level 2 formatting to lines containing selection" }, "$:/language/Buttons/Heading3/Caption": { "title": "$:/language/Buttons/Heading3/Caption", "text": "heading 3" }, "$:/language/Buttons/Heading3/Hint": { "title": "$:/language/Buttons/Heading3/Hint", "text": "Apply heading level 3 formatting to lines containing selection" }, "$:/language/Buttons/Heading4/Caption": { "title": "$:/language/Buttons/Heading4/Caption", "text": "heading 4" }, "$:/language/Buttons/Heading4/Hint": { "title": "$:/language/Buttons/Heading4/Hint", "text": "Apply heading level 4 formatting to lines containing selection" }, "$:/language/Buttons/Heading5/Caption": { "title": "$:/language/Buttons/Heading5/Caption", "text": "heading 5" }, "$:/language/Buttons/Heading5/Hint": { "title": "$:/language/Buttons/Heading5/Hint", "text": "Apply heading level 5 formatting to lines containing selection" }, "$:/language/Buttons/Heading6/Caption": { "title": "$:/language/Buttons/Heading6/Caption", "text": "heading 6" }, "$:/language/Buttons/Heading6/Hint": { "title": "$:/language/Buttons/Heading6/Hint", "text": "Apply heading level 6 formatting to lines containing selection" }, "$:/language/Buttons/Italic/Caption": { "title": "$:/language/Buttons/Italic/Caption", "text": "italic" }, "$:/language/Buttons/Italic/Hint": { "title": "$:/language/Buttons/Italic/Hint", "text": "Apply italic formatting to selection" }, "$:/language/Buttons/LineWidth/Caption": { "title": "$:/language/Buttons/LineWidth/Caption", "text": "line width" }, "$:/language/Buttons/LineWidth/Hint": { "title": "$:/language/Buttons/LineWidth/Hint", "text": "Set line width for painting" }, "$:/language/Buttons/Link/Caption": { "title": "$:/language/Buttons/Link/Caption", "text": "link" }, "$:/language/Buttons/Link/Hint": { "title": "$:/language/Buttons/Link/Hint", "text": "Create wikitext link" }, "$:/language/Buttons/ListBullet/Caption": { "title": "$:/language/Buttons/ListBullet/Caption", "text": "bulleted list" }, "$:/language/Buttons/ListBullet/Hint": { "title": "$:/language/Buttons/ListBullet/Hint", "text": "Apply bulleted list formatting to lines containing selection" }, "$:/language/Buttons/ListNumber/Caption": { "title": "$:/language/Buttons/ListNumber/Caption", "text": "numbered list" }, "$:/language/Buttons/ListNumber/Hint": { "title": "$:/language/Buttons/ListNumber/Hint", "text": "Apply numbered list formatting to lines containing selection" }, "$:/language/Buttons/MonoBlock/Caption": { "title": "$:/language/Buttons/MonoBlock/Caption", "text": "monospaced block" }, "$:/language/Buttons/MonoBlock/Hint": { "title": "$:/language/Buttons/MonoBlock/Hint", "text": "Apply monospaced block formatting to lines containing selection" }, "$:/language/Buttons/MonoLine/Caption": { "title": "$:/language/Buttons/MonoLine/Caption", "text": "monospaced" }, "$:/language/Buttons/MonoLine/Hint": { "title": "$:/language/Buttons/MonoLine/Hint", "text": "Apply monospaced character formatting to selection" }, "$:/language/Buttons/Opacity/Caption": { "title": "$:/language/Buttons/Opacity/Caption", "text": "opacity" }, "$:/language/Buttons/Opacity/Hint": { "title": "$:/language/Buttons/Opacity/Hint", "text": "Set painting opacity" }, "$:/language/Buttons/Paint/Caption": { "title": "$:/language/Buttons/Paint/Caption", "text": "paint colour" }, "$:/language/Buttons/Paint/Hint": { "title": "$:/language/Buttons/Paint/Hint", "text": "Set painting colour" }, "$:/language/Buttons/Picture/Caption": { "title": "$:/language/Buttons/Picture/Caption", "text": "picture" }, "$:/language/Buttons/Picture/Hint": { "title": "$:/language/Buttons/Picture/Hint", "text": "Insert picture" }, "$:/language/Buttons/Preview/Caption": { "title": "$:/language/Buttons/Preview/Caption", "text": "preview" }, "$:/language/Buttons/Preview/Hint": { "title": "$:/language/Buttons/Preview/Hint", "text": "Show preview pane" }, "$:/language/Buttons/PreviewType/Caption": { "title": "$:/language/Buttons/PreviewType/Caption", "text": "preview type" }, "$:/language/Buttons/PreviewType/Hint": { "title": "$:/language/Buttons/PreviewType/Hint", "text": "Choose preview type" }, "$:/language/Buttons/Quote/Caption": { "title": "$:/language/Buttons/Quote/Caption", "text": "quote" }, "$:/language/Buttons/Quote/Hint": { "title": "$:/language/Buttons/Quote/Hint", "text": "Apply quoted text formatting to lines containing selection" }, "$:/language/Buttons/Size/Caption": { "title": "$:/language/Buttons/Size/Caption", "text": "image size" }, "$:/language/Buttons/Size/Caption/Height": { "title": "$:/language/Buttons/Size/Caption/Height", "text": "Height:" }, "$:/language/Buttons/Size/Caption/Resize": { "title": "$:/language/Buttons/Size/Caption/Resize", "text": "Resize image" }, "$:/language/Buttons/Size/Caption/Width": { "title": "$:/language/Buttons/Size/Caption/Width", "text": "Width:" }, "$:/language/Buttons/Size/Hint": { "title": "$:/language/Buttons/Size/Hint", "text": "Set image size" }, "$:/language/Buttons/Stamp/Caption": { "title": "$:/language/Buttons/Stamp/Caption", "text": "stamp" }, "$:/language/Buttons/Stamp/Caption/New": { "title": "$:/language/Buttons/Stamp/Caption/New", "text": "Add your own" }, "$:/language/Buttons/Stamp/Hint": { "title": "$:/language/Buttons/Stamp/Hint", "text": "Insert a preconfigured snippet of text" }, "$:/language/Buttons/Stamp/New/Title": { "title": "$:/language/Buttons/Stamp/New/Title", "text": "Name as shown in menu" }, "$:/language/Buttons/Stamp/New/Text": { "title": "$:/language/Buttons/Stamp/New/Text", "text": "Text of snippet. (Remember to add a descriptive title in the caption field)." }, "$:/language/Buttons/Strikethrough/Caption": { "title": "$:/language/Buttons/Strikethrough/Caption", "text": "strikethrough" }, "$:/language/Buttons/Strikethrough/Hint": { "title": "$:/language/Buttons/Strikethrough/Hint", "text": "Apply strikethrough formatting to selection" }, "$:/language/Buttons/Subscript/Caption": { "title": "$:/language/Buttons/Subscript/Caption", "text": "subscript" }, "$:/language/Buttons/Subscript/Hint": { "title": "$:/language/Buttons/Subscript/Hint", "text": "Apply subscript formatting to selection" }, "$:/language/Buttons/Superscript/Caption": { "title": "$:/language/Buttons/Superscript/Caption", "text": "superscript" }, "$:/language/Buttons/Superscript/Hint": { "title": "$:/language/Buttons/Superscript/Hint", "text": "Apply superscript formatting to selection" }, "$:/language/Buttons/Underline/Caption": { "title": "$:/language/Buttons/Underline/Caption", "text": "underline" }, "$:/language/Buttons/Underline/Hint": { "title": "$:/language/Buttons/Underline/Hint", "text": "Apply underline formatting to selection" }, "$:/language/ControlPanel/Advanced/Caption": { "title": "$:/language/ControlPanel/Advanced/Caption", "text": "Advanced" }, "$:/language/ControlPanel/Advanced/Hint": { "title": "$:/language/ControlPanel/Advanced/Hint", "text": "Internal information about this TiddlyWiki" }, "$:/language/ControlPanel/Appearance/Caption": { "title": "$:/language/ControlPanel/Appearance/Caption", "text": "Appearance" }, "$:/language/ControlPanel/Appearance/Hint": { "title": "$:/language/ControlPanel/Appearance/Hint", "text": "Ways to customise the appearance of your TiddlyWiki." }, "$:/language/ControlPanel/Basics/AnimDuration/Prompt": { "title": "$:/language/ControlPanel/Basics/AnimDuration/Prompt", "text": "Animation duration:" }, "$:/language/ControlPanel/Basics/Caption": { "title": "$:/language/ControlPanel/Basics/Caption", "text": "Basics" }, "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint": { "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint", "text": "Use [[double square brackets]] for titles with spaces. Or you can choose to <$button set=\"$:/DefaultTiddlers\" setTo=\"[list[$:/StoryList]]\">retain story ordering</$button>" }, "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt", "text": "Default tiddlers:" }, "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint": { "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint", "text": "Choose which tiddlers are displayed at startup:" }, "$:/language/ControlPanel/Basics/Language/Prompt": { "title": "$:/language/ControlPanel/Basics/Language/Prompt", "text": "Hello! Current language:" }, "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt": { "title": "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt", "text": "Title of new journal tiddlers" }, "$:/language/ControlPanel/Basics/NewJournal/Text/Prompt": { "title": "$:/language/ControlPanel/Basics/NewJournal/Text/Prompt", "text": "Text for new journal tiddlers" }, "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt": { "title": "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt", "text": "Tags for new journal tiddlers" }, "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt", "text": "Number of overridden shadow tiddlers:" }, "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt", "text": "Number of shadow tiddlers:" }, "$:/language/ControlPanel/Basics/Subtitle/Prompt": { "title": "$:/language/ControlPanel/Basics/Subtitle/Prompt", "text": "Subtitle:" }, "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt", "text": "Number of system tiddlers:" }, "$:/language/ControlPanel/Basics/Tags/Prompt": { "title": "$:/language/ControlPanel/Basics/Tags/Prompt", "text": "Number of tags:" }, "$:/language/ControlPanel/Basics/Tiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/Tiddlers/Prompt", "text": "Number of tiddlers:" }, "$:/language/ControlPanel/Basics/Title/Prompt": { "title": "$:/language/ControlPanel/Basics/Title/Prompt", "text": "Title of this ~TiddlyWiki:" }, "$:/language/ControlPanel/Basics/Username/Prompt": { "title": "$:/language/ControlPanel/Basics/Username/Prompt", "text": "Username for signing edits:" }, "$:/language/ControlPanel/Basics/Version/Prompt": { "title": "$:/language/ControlPanel/Basics/Version/Prompt", "text": "~TiddlyWiki version:" }, "$:/language/ControlPanel/EditorTypes/Caption": { "title": "$:/language/ControlPanel/EditorTypes/Caption", "text": "Editor Types" }, "$:/language/ControlPanel/EditorTypes/Editor/Caption": { "title": "$:/language/ControlPanel/EditorTypes/Editor/Caption", "text": "Editor" }, "$:/language/ControlPanel/EditorTypes/Hint": { "title": "$:/language/ControlPanel/EditorTypes/Hint", "text": "These tiddlers determine which editor is used to edit specific tiddler types." }, "$:/language/ControlPanel/EditorTypes/Type/Caption": { "title": "$:/language/ControlPanel/EditorTypes/Type/Caption", "text": "Type" }, "$:/language/ControlPanel/Info/Caption": { "title": "$:/language/ControlPanel/Info/Caption", "text": "Info" }, "$:/language/ControlPanel/Info/Hint": { "title": "$:/language/ControlPanel/Info/Hint", "text": "Information about this TiddlyWiki" }, "$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt", "text": "Type shortcut here" }, "$:/language/ControlPanel/KeyboardShortcuts/Add/Caption": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Add/Caption", "text": "add shortcut" }, "$:/language/ControlPanel/KeyboardShortcuts/Caption": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Caption", "text": "Keyboard Shortcuts" }, "$:/language/ControlPanel/KeyboardShortcuts/Hint": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Hint", "text": "Manage keyboard shortcut assignments" }, "$:/language/ControlPanel/KeyboardShortcuts/NoShortcuts/Caption": { "title": "$:/language/ControlPanel/KeyboardShortcuts/NoShortcuts/Caption", "text": "No keyboard shortcuts assigned" }, "$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint", "text": "remove keyboard shortcut" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/All": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/All", "text": "All platforms" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/Mac": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Mac", "text": "Macintosh platform only" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonMac": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonMac", "text": "Non-Macintosh platforms only" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/Linux": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Linux", "text": "Linux platform only" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonLinux": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonLinux", "text": "Non-Linux platforms only" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/Windows": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Windows", "text": "Windows platform only" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonWindows": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonWindows", "text": "Non-Windows platforms only" }, "$:/language/ControlPanel/LoadedModules/Caption": { "title": "$:/language/ControlPanel/LoadedModules/Caption", "text": "Loaded Modules" }, "$:/language/ControlPanel/LoadedModules/Hint": { "title": "$:/language/ControlPanel/LoadedModules/Hint", "text": "These are the currently loaded tiddler modules linked to their source tiddlers. Any italicised modules lack a source tiddler, typically because they were setup during the boot process." }, "$:/language/ControlPanel/Palette/Caption": { "title": "$:/language/ControlPanel/Palette/Caption", "text": "Palette" }, "$:/language/ControlPanel/Palette/Editor/Clone/Caption": { "title": "$:/language/ControlPanel/Palette/Editor/Clone/Caption", "text": "clone" }, "$:/language/ControlPanel/Palette/Editor/Clone/Prompt": { "title": "$:/language/ControlPanel/Palette/Editor/Clone/Prompt", "text": "It is recommended that you clone this shadow palette before editing it" }, "$:/language/ControlPanel/Palette/Editor/Prompt/Modified": { "title": "$:/language/ControlPanel/Palette/Editor/Prompt/Modified", "text": "This shadow palette has been modified" }, "$:/language/ControlPanel/Palette/Editor/Prompt": { "title": "$:/language/ControlPanel/Palette/Editor/Prompt", "text": "Editing" }, "$:/language/ControlPanel/Palette/Editor/Reset/Caption": { "title": "$:/language/ControlPanel/Palette/Editor/Reset/Caption", "text": "reset" }, "$:/language/ControlPanel/Palette/HideEditor/Caption": { "title": "$:/language/ControlPanel/Palette/HideEditor/Caption", "text": "hide editor" }, "$:/language/ControlPanel/Palette/Prompt": { "title": "$:/language/ControlPanel/Palette/Prompt", "text": "Current palette:" }, "$:/language/ControlPanel/Palette/ShowEditor/Caption": { "title": "$:/language/ControlPanel/Palette/ShowEditor/Caption", "text": "show editor" }, "$:/language/ControlPanel/Parsing/Caption": { "title": "$:/language/ControlPanel/Parsing/Caption", "text": "Parsing" }, "$:/language/ControlPanel/Parsing/Hint": { "title": "$:/language/ControlPanel/Parsing/Hint", "text": "Here you can globally disable/enable wiki parser rules. For changes to take effect, save and reload your wiki. Disabling certain parser rules can prevent <$text text=\"TiddlyWiki\"/> from functioning correctly. Use [[safe mode|http://tiddlywiki.com/#SafeMode]] to restore normal operation." }, "$:/language/ControlPanel/Parsing/Block/Caption": { "title": "$:/language/ControlPanel/Parsing/Block/Caption", "text": "Block Parse Rules" }, "$:/language/ControlPanel/Parsing/Inline/Caption": { "title": "$:/language/ControlPanel/Parsing/Inline/Caption", "text": "Inline Parse Rules" }, "$:/language/ControlPanel/Parsing/Pragma/Caption": { "title": "$:/language/ControlPanel/Parsing/Pragma/Caption", "text": "Pragma Parse Rules" }, "$:/language/ControlPanel/Plugins/Add/Caption": { "title": "$:/language/ControlPanel/Plugins/Add/Caption", "text": "Get more plugins" }, "$:/language/ControlPanel/Plugins/Add/Hint": { "title": "$:/language/ControlPanel/Plugins/Add/Hint", "text": "Install plugins from the official library" }, "$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint": { "title": "$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint", "text": "This plugin is already installed at version <$text text=<<installedVersion>>/>" }, "$:/language/ControlPanel/Plugins/Caption": { "title": "$:/language/ControlPanel/Plugins/Caption", "text": "Plugins" }, "$:/language/ControlPanel/Plugins/Disable/Caption": { "title": "$:/language/ControlPanel/Plugins/Disable/Caption", "text": "disable" }, "$:/language/ControlPanel/Plugins/Disable/Hint": { "title": "$:/language/ControlPanel/Plugins/Disable/Hint", "text": "Disable this plugin when reloading page" }, "$:/language/ControlPanel/Plugins/Disabled/Status": { "title": "$:/language/ControlPanel/Plugins/Disabled/Status", "text": "(disabled)" }, "$:/language/ControlPanel/Plugins/Empty/Hint": { "title": "$:/language/ControlPanel/Plugins/Empty/Hint", "text": "None" }, "$:/language/ControlPanel/Plugins/Enable/Caption": { "title": "$:/language/ControlPanel/Plugins/Enable/Caption", "text": "enable" }, "$:/language/ControlPanel/Plugins/Enable/Hint": { "title": "$:/language/ControlPanel/Plugins/Enable/Hint", "text": "Enable this plugin when reloading page" }, "$:/language/ControlPanel/Plugins/Install/Caption": { "title": "$:/language/ControlPanel/Plugins/Install/Caption", "text": "install" }, "$:/language/ControlPanel/Plugins/Installed/Hint": { "title": "$:/language/ControlPanel/Plugins/Installed/Hint", "text": "Currently installed plugins:" }, "$:/language/ControlPanel/Plugins/Languages/Caption": { "title": "$:/language/ControlPanel/Plugins/Languages/Caption", "text": "Languages" }, "$:/language/ControlPanel/Plugins/Languages/Hint": { "title": "$:/language/ControlPanel/Plugins/Languages/Hint", "text": "Language pack plugins" }, "$:/language/ControlPanel/Plugins/NoInfoFound/Hint": { "title": "$:/language/ControlPanel/Plugins/NoInfoFound/Hint", "text": "No ''\"<$text text=<<currentTab>>/>\"'' found" }, "$:/language/ControlPanel/Plugins/NoInformation/Hint": { "title": "$:/language/ControlPanel/Plugins/NoInformation/Hint", "text": "No information provided" }, "$:/language/ControlPanel/Plugins/NotInstalled/Hint": { "title": "$:/language/ControlPanel/Plugins/NotInstalled/Hint", "text": "This plugin is not currently installed" }, "$:/language/ControlPanel/Plugins/OpenPluginLibrary": { "title": "$:/language/ControlPanel/Plugins/OpenPluginLibrary", "text": "open plugin library" }, "$:/language/ControlPanel/Plugins/ClosePluginLibrary": { "title": "$:/language/ControlPanel/Plugins/ClosePluginLibrary", "text": "close plugin library" }, "$:/language/ControlPanel/Plugins/Plugins/Caption": { "title": "$:/language/ControlPanel/Plugins/Plugins/Caption", "text": "Plugins" }, "$:/language/ControlPanel/Plugins/Plugins/Hint": { "title": "$:/language/ControlPanel/Plugins/Plugins/Hint", "text": "Plugins" }, "$:/language/ControlPanel/Plugins/Reinstall/Caption": { "title": "$:/language/ControlPanel/Plugins/Reinstall/Caption", "text": "reinstall" }, "$:/language/ControlPanel/Plugins/Themes/Caption": { "title": "$:/language/ControlPanel/Plugins/Themes/Caption", "text": "Themes" }, "$:/language/ControlPanel/Plugins/Themes/Hint": { "title": "$:/language/ControlPanel/Plugins/Themes/Hint", "text": "Theme plugins" }, "$:/language/ControlPanel/Saving/Caption": { "title": "$:/language/ControlPanel/Saving/Caption", "text": "Saving" }, "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Description": { "title": "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Description", "text": "Permit automatic saving for the download saver" }, "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Hint": { "title": "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Hint", "text": "Enable Autosave for Download Saver" }, "$:/language/ControlPanel/Saving/DownloadSaver/Caption": { "title": "$:/language/ControlPanel/Saving/DownloadSaver/Caption", "text": "Download Saver" }, "$:/language/ControlPanel/Saving/DownloadSaver/Hint": { "title": "$:/language/ControlPanel/Saving/DownloadSaver/Hint", "text": "These settings apply to the HTML5-compatible download saver" }, "$:/language/ControlPanel/Saving/General/Caption": { "title": "$:/language/ControlPanel/Saving/General/Caption", "text": "General" }, "$:/language/ControlPanel/Saving/General/Hint": { "title": "$:/language/ControlPanel/Saving/General/Hint", "text": "These settings apply to all the loaded savers" }, "$:/language/ControlPanel/Saving/Hint": { "title": "$:/language/ControlPanel/Saving/Hint", "text": "Settings used for saving the entire TiddlyWiki as a single file via a saver module" }, "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading", "text": "Advanced Settings" }, "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir", "text": "Backup Directory" }, "$:/language/ControlPanel/Saving/TiddlySpot/Backups": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Backups", "text": "Backups" }, "$:/language/ControlPanel/Saving/TiddlySpot/Caption": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Caption", "text": "~TiddlySpot Saver" }, "$:/language/ControlPanel/Saving/TiddlySpot/Description": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Description", "text": "These settings are only used when saving to http://tiddlyspot.com or a compatible remote server" }, "$:/language/ControlPanel/Saving/TiddlySpot/Filename": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Filename", "text": "Upload Filename" }, "$:/language/ControlPanel/Saving/TiddlySpot/Heading": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Heading", "text": "~TiddlySpot" }, "$:/language/ControlPanel/Saving/TiddlySpot/Hint": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Hint", "text": "//The server URL defaults to `http://<wikiname>.tiddlyspot.com/store.cgi` and can be changed to use a custom server address, e.g. `http://example.com/store.php`.//" }, "$:/language/ControlPanel/Saving/TiddlySpot/Password": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Password", "text": "Password" }, "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL", "text": "Server URL" }, "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir", "text": "Upload Directory" }, "$:/language/ControlPanel/Saving/TiddlySpot/UserName": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/UserName", "text": "Wiki Name" }, "$:/language/ControlPanel/Settings/AutoSave/Caption": { "title": "$:/language/ControlPanel/Settings/AutoSave/Caption", "text": "Autosave" }, "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description": { "title": "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description", "text": "Do not save changes automatically" }, "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description": { "title": "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description", "text": "Save changes automatically" }, "$:/language/ControlPanel/Settings/AutoSave/Hint": { "title": "$:/language/ControlPanel/Settings/AutoSave/Hint", "text": "Attempt to automatically save changes during editing when using a supporting saver" }, "$:/language/ControlPanel/Settings/CamelCase/Caption": { "title": "$:/language/ControlPanel/Settings/CamelCase/Caption", "text": "Camel Case Wiki Links" }, "$:/language/ControlPanel/Settings/CamelCase/Hint": { "title": "$:/language/ControlPanel/Settings/CamelCase/Hint", "text": "You can globally disable automatic linking of ~CamelCase phrases. Requires reload to take effect" }, "$:/language/ControlPanel/Settings/CamelCase/Description": { "title": "$:/language/ControlPanel/Settings/CamelCase/Description", "text": "Enable automatic ~CamelCase linking" }, "$:/language/ControlPanel/Settings/Caption": { "title": "$:/language/ControlPanel/Settings/Caption", "text": "Settings" }, "$:/language/ControlPanel/Settings/EditorToolbar/Caption": { "title": "$:/language/ControlPanel/Settings/EditorToolbar/Caption", "text": "Editor Toolbar" }, "$:/language/ControlPanel/Settings/EditorToolbar/Hint": { "title": "$:/language/ControlPanel/Settings/EditorToolbar/Hint", "text": "Enable or disable the editor toolbar:" }, "$:/language/ControlPanel/Settings/EditorToolbar/Description": { "title": "$:/language/ControlPanel/Settings/EditorToolbar/Description", "text": "Show editor toolbar" }, "$:/language/ControlPanel/Settings/InfoPanelMode/Caption": { "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Caption", "text": "Tiddler Info Panel Mode" }, "$:/language/ControlPanel/Settings/InfoPanelMode/Hint": { "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Hint", "text": "Control when the tiddler info panel closes:" }, "$:/language/ControlPanel/Settings/InfoPanelMode/Popup/Description": { "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Popup/Description", "text": "Tiddler info panel closes automatically" }, "$:/language/ControlPanel/Settings/InfoPanelMode/Sticky/Description": { "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Sticky/Description", "text": "Tiddler info panel stays open until explicitly closed" }, "$:/language/ControlPanel/Settings/Hint": { "title": "$:/language/ControlPanel/Settings/Hint", "text": "These settings let you customise the behaviour of TiddlyWiki." }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption", "text": "Navigation Address Bar" }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint", "text": "Behaviour of the browser address bar when navigating to a tiddler:" }, "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description", "text": "Do not update the address bar" }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description", "text": "Include the target tiddler" }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description", "text": "Include the target tiddler and the current story sequence" }, "$:/language/ControlPanel/Settings/NavigationHistory/Caption": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/Caption", "text": "Navigation History" }, "$:/language/ControlPanel/Settings/NavigationHistory/Hint": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/Hint", "text": "Update browser history when navigating to a tiddler:" }, "$:/language/ControlPanel/Settings/NavigationHistory/No/Description": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/No/Description", "text": "Do not update history" }, "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description", "text": "Update history" }, "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption": { "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption", "text": "Performance Instrumentation" }, "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Hint": { "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Hint", "text": "Displays performance statistics in the browser developer console. Requires reload to take effect" }, "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Description": { "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Description", "text": "Enable performance instrumentation" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption", "text": "Toolbar Button Style" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint", "text": "Choose the style for toolbar buttons:" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless", "text": "Borderless" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed", "text": "Boxed" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded", "text": "Rounded" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Caption": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Caption", "text": "Toolbar Buttons" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Hint": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Hint", "text": "Default toolbar button appearance:" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description", "text": "Include icon" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description", "text": "Include text" }, "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption": { "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption", "text": "Default Sidebar Tab" }, "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint": { "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint", "text": "Specify which sidebar tab is displayed by default" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption", "text": "Tiddler Opening Behaviour" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint", "text": "Navigation from //within// the story river" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint", "text": "Navigation from //outside// the story river" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove", "text": "Open above the current tiddler" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow", "text": "Open below the current tiddler" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop", "text": "Open at the top of the story river" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom", "text": "Open at the bottom of the story river" }, "$:/language/ControlPanel/Settings/TitleLinks/Caption": { "title": "$:/language/ControlPanel/Settings/TitleLinks/Caption", "text": "Tiddler Titles" }, "$:/language/ControlPanel/Settings/TitleLinks/Hint": { "title": "$:/language/ControlPanel/Settings/TitleLinks/Hint", "text": "Optionally display tiddler titles as links" }, "$:/language/ControlPanel/Settings/TitleLinks/No/Description": { "title": "$:/language/ControlPanel/Settings/TitleLinks/No/Description", "text": "Do not display tiddler titles as links" }, "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description": { "title": "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description", "text": "Display tiddler titles as links" }, "$:/language/ControlPanel/Settings/MissingLinks/Caption": { "title": "$:/language/ControlPanel/Settings/MissingLinks/Caption", "text": "Wiki Links" }, "$:/language/ControlPanel/Settings/MissingLinks/Hint": { "title": "$:/language/ControlPanel/Settings/MissingLinks/Hint", "text": "Choose whether to link to tiddlers that do not exist yet" }, "$:/language/ControlPanel/Settings/MissingLinks/Description": { "title": "$:/language/ControlPanel/Settings/MissingLinks/Description", "text": "Enable links to missing tiddlers" }, "$:/language/ControlPanel/StoryView/Caption": { "title": "$:/language/ControlPanel/StoryView/Caption", "text": "Story View" }, "$:/language/ControlPanel/StoryView/Prompt": { "title": "$:/language/ControlPanel/StoryView/Prompt", "text": "Current view:" }, "$:/language/ControlPanel/Theme/Caption": { "title": "$:/language/ControlPanel/Theme/Caption", "text": "Theme" }, "$:/language/ControlPanel/Theme/Prompt": { "title": "$:/language/ControlPanel/Theme/Prompt", "text": "Current theme:" }, "$:/language/ControlPanel/TiddlerFields/Caption": { "title": "$:/language/ControlPanel/TiddlerFields/Caption", "text": "Tiddler Fields" }, "$:/language/ControlPanel/TiddlerFields/Hint": { "title": "$:/language/ControlPanel/TiddlerFields/Hint", "text": "This is the full set of TiddlerFields in use in this wiki (including system tiddlers but excluding shadow tiddlers)." }, "$:/language/ControlPanel/Toolbars/Caption": { "title": "$:/language/ControlPanel/Toolbars/Caption", "text": "Toolbars" }, "$:/language/ControlPanel/Toolbars/EditToolbar/Caption": { "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Caption", "text": "Edit Toolbar" }, "$:/language/ControlPanel/Toolbars/EditToolbar/Hint": { "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Hint", "text": "Choose which buttons are displayed for tiddlers in edit mode. Drag and drop to change the ordering" }, "$:/language/ControlPanel/Toolbars/Hint": { "title": "$:/language/ControlPanel/Toolbars/Hint", "text": "Select which toolbar buttons are displayed" }, "$:/language/ControlPanel/Toolbars/PageControls/Caption": { "title": "$:/language/ControlPanel/Toolbars/PageControls/Caption", "text": "Page Toolbar" }, "$:/language/ControlPanel/Toolbars/PageControls/Hint": { "title": "$:/language/ControlPanel/Toolbars/PageControls/Hint", "text": "Choose which buttons are displayed on the main page toolbar. Drag and drop to change the ordering" }, "$:/language/ControlPanel/Toolbars/EditorToolbar/Caption": { "title": "$:/language/ControlPanel/Toolbars/EditorToolbar/Caption", "text": "Editor Toolbar" }, "$:/language/ControlPanel/Toolbars/EditorToolbar/Hint": { "title": "$:/language/ControlPanel/Toolbars/EditorToolbar/Hint", "text": "Choose which buttons are displayed in the editor toolbar. Note that some buttons will only appear when editing tiddlers of a certain type. Drag and drop to change the ordering" }, "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption": { "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption", "text": "View Toolbar" }, "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint": { "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint", "text": "Choose which buttons are displayed for tiddlers in view mode. Drag and drop to change the ordering" }, "$:/language/ControlPanel/Tools/Download/Full/Caption": { "title": "$:/language/ControlPanel/Tools/Download/Full/Caption", "text": "Download full wiki" }, "$:/language/Date/DaySuffix/1": { "title": "$:/language/Date/DaySuffix/1", "text": "st" }, "$:/language/Date/DaySuffix/2": { "title": "$:/language/Date/DaySuffix/2", "text": "nd" }, "$:/language/Date/DaySuffix/3": { "title": "$:/language/Date/DaySuffix/3", "text": "rd" }, "$:/language/Date/DaySuffix/4": { "title": "$:/language/Date/DaySuffix/4", "text": "th" }, "$:/language/Date/DaySuffix/5": { "title": "$:/language/Date/DaySuffix/5", "text": "th" }, "$:/language/Date/DaySuffix/6": { "title": "$:/language/Date/DaySuffix/6", "text": "th" }, "$:/language/Date/DaySuffix/7": { "title": "$:/language/Date/DaySuffix/7", "text": "th" }, "$:/language/Date/DaySuffix/8": { "title": "$:/language/Date/DaySuffix/8", "text": "th" }, "$:/language/Date/DaySuffix/9": { "title": "$:/language/Date/DaySuffix/9", "text": "th" }, "$:/language/Date/DaySuffix/10": { "title": "$:/language/Date/DaySuffix/10", "text": "th" }, "$:/language/Date/DaySuffix/11": { "title": "$:/language/Date/DaySuffix/11", "text": "th" }, "$:/language/Date/DaySuffix/12": { "title": "$:/language/Date/DaySuffix/12", "text": "th" }, "$:/language/Date/DaySuffix/13": { "title": "$:/language/Date/DaySuffix/13", "text": "th" }, "$:/language/Date/DaySuffix/14": { "title": "$:/language/Date/DaySuffix/14", "text": "th" }, "$:/language/Date/DaySuffix/15": { "title": "$:/language/Date/DaySuffix/15", "text": "th" }, "$:/language/Date/DaySuffix/16": { "title": "$:/language/Date/DaySuffix/16", "text": "th" }, "$:/language/Date/DaySuffix/17": { "title": "$:/language/Date/DaySuffix/17", "text": "th" }, "$:/language/Date/DaySuffix/18": { "title": "$:/language/Date/DaySuffix/18", "text": "th" }, "$:/language/Date/DaySuffix/19": { "title": "$:/language/Date/DaySuffix/19", "text": "th" }, "$:/language/Date/DaySuffix/20": { "title": "$:/language/Date/DaySuffix/20", "text": "th" }, "$:/language/Date/DaySuffix/21": { "title": "$:/language/Date/DaySuffix/21", "text": "st" }, "$:/language/Date/DaySuffix/22": { "title": "$:/language/Date/DaySuffix/22", "text": "nd" }, "$:/language/Date/DaySuffix/23": { "title": "$:/language/Date/DaySuffix/23", "text": "rd" }, "$:/language/Date/DaySuffix/24": { "title": "$:/language/Date/DaySuffix/24", "text": "th" }, "$:/language/Date/DaySuffix/25": { "title": "$:/language/Date/DaySuffix/25", "text": "th" }, "$:/language/Date/DaySuffix/26": { "title": "$:/language/Date/DaySuffix/26", "text": "th" }, "$:/language/Date/DaySuffix/27": { "title": "$:/language/Date/DaySuffix/27", "text": "th" }, "$:/language/Date/DaySuffix/28": { "title": "$:/language/Date/DaySuffix/28", "text": "th" }, "$:/language/Date/DaySuffix/29": { "title": "$:/language/Date/DaySuffix/29", "text": "th" }, "$:/language/Date/DaySuffix/30": { "title": "$:/language/Date/DaySuffix/30", "text": "th" }, "$:/language/Date/DaySuffix/31": { "title": "$:/language/Date/DaySuffix/31", "text": "st" }, "$:/language/Date/Long/Day/0": { "title": "$:/language/Date/Long/Day/0", "text": "Sunday" }, "$:/language/Date/Long/Day/1": { "title": "$:/language/Date/Long/Day/1", "text": "Monday" }, "$:/language/Date/Long/Day/2": { "title": "$:/language/Date/Long/Day/2", "text": "Tuesday" }, "$:/language/Date/Long/Day/3": { "title": "$:/language/Date/Long/Day/3", "text": "Wednesday" }, "$:/language/Date/Long/Day/4": { "title": "$:/language/Date/Long/Day/4", "text": "Thursday" }, "$:/language/Date/Long/Day/5": { "title": "$:/language/Date/Long/Day/5", "text": "Friday" }, "$:/language/Date/Long/Day/6": { "title": "$:/language/Date/Long/Day/6", "text": "Saturday" }, "$:/language/Date/Long/Month/1": { "title": "$:/language/Date/Long/Month/1", "text": "January" }, "$:/language/Date/Long/Month/2": { "title": "$:/language/Date/Long/Month/2", "text": "February" }, "$:/language/Date/Long/Month/3": { "title": "$:/language/Date/Long/Month/3", "text": "March" }, "$:/language/Date/Long/Month/4": { "title": "$:/language/Date/Long/Month/4", "text": "April" }, "$:/language/Date/Long/Month/5": { "title": "$:/language/Date/Long/Month/5", "text": "May" }, "$:/language/Date/Long/Month/6": { "title": "$:/language/Date/Long/Month/6", "text": "June" }, "$:/language/Date/Long/Month/7": { "title": "$:/language/Date/Long/Month/7", "text": "July" }, "$:/language/Date/Long/Month/8": { "title": "$:/language/Date/Long/Month/8", "text": "August" }, "$:/language/Date/Long/Month/9": { "title": "$:/language/Date/Long/Month/9", "text": "September" }, "$:/language/Date/Long/Month/10": { "title": "$:/language/Date/Long/Month/10", "text": "October" }, "$:/language/Date/Long/Month/11": { "title": "$:/language/Date/Long/Month/11", "text": "November" }, "$:/language/Date/Long/Month/12": { "title": "$:/language/Date/Long/Month/12", "text": "December" }, "$:/language/Date/Period/am": { "title": "$:/language/Date/Period/am", "text": "am" }, "$:/language/Date/Period/pm": { "title": "$:/language/Date/Period/pm", "text": "pm" }, "$:/language/Date/Short/Day/0": { "title": "$:/language/Date/Short/Day/0", "text": "Sun" }, "$:/language/Date/Short/Day/1": { "title": "$:/language/Date/Short/Day/1", "text": "Mon" }, "$:/language/Date/Short/Day/2": { "title": "$:/language/Date/Short/Day/2", "text": "Tue" }, "$:/language/Date/Short/Day/3": { "title": "$:/language/Date/Short/Day/3", "text": "Wed" }, "$:/language/Date/Short/Day/4": { "title": "$:/language/Date/Short/Day/4", "text": "Thu" }, "$:/language/Date/Short/Day/5": { "title": "$:/language/Date/Short/Day/5", "text": "Fri" }, "$:/language/Date/Short/Day/6": { "title": "$:/language/Date/Short/Day/6", "text": "Sat" }, "$:/language/Date/Short/Month/1": { "title": "$:/language/Date/Short/Month/1", "text": "Jan" }, "$:/language/Date/Short/Month/2": { "title": "$:/language/Date/Short/Month/2", "text": "Feb" }, "$:/language/Date/Short/Month/3": { "title": "$:/language/Date/Short/Month/3", "text": "Mar" }, "$:/language/Date/Short/Month/4": { "title": "$:/language/Date/Short/Month/4", "text": "Apr" }, "$:/language/Date/Short/Month/5": { "title": "$:/language/Date/Short/Month/5", "text": "May" }, "$:/language/Date/Short/Month/6": { "title": "$:/language/Date/Short/Month/6", "text": "Jun" }, "$:/language/Date/Short/Month/7": { "title": "$:/language/Date/Short/Month/7", "text": "Jul" }, "$:/language/Date/Short/Month/8": { "title": "$:/language/Date/Short/Month/8", "text": "Aug" }, "$:/language/Date/Short/Month/9": { "title": "$:/language/Date/Short/Month/9", "text": "Sep" }, "$:/language/Date/Short/Month/10": { "title": "$:/language/Date/Short/Month/10", "text": "Oct" }, "$:/language/Date/Short/Month/11": { "title": "$:/language/Date/Short/Month/11", "text": "Nov" }, "$:/language/Date/Short/Month/12": { "title": "$:/language/Date/Short/Month/12", "text": "Dec" }, "$:/language/RelativeDate/Future/Days": { "title": "$:/language/RelativeDate/Future/Days", "text": "<<period>> days from now" }, "$:/language/RelativeDate/Future/Hours": { "title": "$:/language/RelativeDate/Future/Hours", "text": "<<period>> hours from now" }, "$:/language/RelativeDate/Future/Minutes": { "title": "$:/language/RelativeDate/Future/Minutes", "text": "<<period>> minutes from now" }, "$:/language/RelativeDate/Future/Months": { "title": "$:/language/RelativeDate/Future/Months", "text": "<<period>> months from now" }, "$:/language/RelativeDate/Future/Second": { "title": "$:/language/RelativeDate/Future/Second", "text": "1 second from now" }, "$:/language/RelativeDate/Future/Seconds": { "title": "$:/language/RelativeDate/Future/Seconds", "text": "<<period>> seconds from now" }, "$:/language/RelativeDate/Future/Years": { "title": "$:/language/RelativeDate/Future/Years", "text": "<<period>> years from now" }, "$:/language/RelativeDate/Past/Days": { "title": "$:/language/RelativeDate/Past/Days", "text": "<<period>> days ago" }, "$:/language/RelativeDate/Past/Hours": { "title": "$:/language/RelativeDate/Past/Hours", "text": "<<period>> hours ago" }, "$:/language/RelativeDate/Past/Minutes": { "title": "$:/language/RelativeDate/Past/Minutes", "text": "<<period>> minutes ago" }, "$:/language/RelativeDate/Past/Months": { "title": "$:/language/RelativeDate/Past/Months", "text": "<<period>> months ago" }, "$:/language/RelativeDate/Past/Second": { "title": "$:/language/RelativeDate/Past/Second", "text": "1 second ago" }, "$:/language/RelativeDate/Past/Seconds": { "title": "$:/language/RelativeDate/Past/Seconds", "text": "<<period>> seconds ago" }, "$:/language/RelativeDate/Past/Years": { "title": "$:/language/RelativeDate/Past/Years", "text": "<<period>> years ago" }, "$:/language/Docs/ModuleTypes/allfilteroperator": { "title": "$:/language/Docs/ModuleTypes/allfilteroperator", "text": "A sub-operator for the ''all'' filter operator." }, "$:/language/Docs/ModuleTypes/animation": { "title": "$:/language/Docs/ModuleTypes/animation", "text": "Animations that may be used with the RevealWidget." }, "$:/language/Docs/ModuleTypes/bitmapeditoroperation": { "title": "$:/language/Docs/ModuleTypes/bitmapeditoroperation", "text": "A bitmap editor toolbar operation." }, "$:/language/Docs/ModuleTypes/command": { "title": "$:/language/Docs/ModuleTypes/command", "text": "Commands that can be executed under Node.js." }, "$:/language/Docs/ModuleTypes/config": { "title": "$:/language/Docs/ModuleTypes/config", "text": "Data to be inserted into `$tw.config`." }, "$:/language/Docs/ModuleTypes/filteroperator": { "title": "$:/language/Docs/ModuleTypes/filteroperator", "text": "Individual filter operator methods." }, "$:/language/Docs/ModuleTypes/global": { "title": "$:/language/Docs/ModuleTypes/global", "text": "Global data to be inserted into `$tw`." }, "$:/language/Docs/ModuleTypes/info": { "title": "$:/language/Docs/ModuleTypes/info", "text": "Publishes system information via the [[$:/temp/info-plugin]] pseudo-plugin." }, "$:/language/Docs/ModuleTypes/isfilteroperator": { "title": "$:/language/Docs/ModuleTypes/isfilteroperator", "text": "Operands for the ''is'' filter operator." }, "$:/language/Docs/ModuleTypes/library": { "title": "$:/language/Docs/ModuleTypes/library", "text": "Generic module type for general purpose JavaScript modules." }, "$:/language/Docs/ModuleTypes/macro": { "title": "$:/language/Docs/ModuleTypes/macro", "text": "JavaScript macro definitions." }, "$:/language/Docs/ModuleTypes/parser": { "title": "$:/language/Docs/ModuleTypes/parser", "text": "Parsers for different content types." }, "$:/language/Docs/ModuleTypes/saver": { "title": "$:/language/Docs/ModuleTypes/saver", "text": "Savers handle different methods for saving files from the browser." }, "$:/language/Docs/ModuleTypes/startup": { "title": "$:/language/Docs/ModuleTypes/startup", "text": "Startup functions." }, "$:/language/Docs/ModuleTypes/storyview": { "title": "$:/language/Docs/ModuleTypes/storyview", "text": "Story views customise the animation and behaviour of list widgets." }, "$:/language/Docs/ModuleTypes/texteditoroperation": { "title": "$:/language/Docs/ModuleTypes/texteditoroperation", "text": "A text editor toolbar operation." }, "$:/language/Docs/ModuleTypes/tiddlerdeserializer": { "title": "$:/language/Docs/ModuleTypes/tiddlerdeserializer", "text": "Converts different content types into tiddlers." }, "$:/language/Docs/ModuleTypes/tiddlerfield": { "title": "$:/language/Docs/ModuleTypes/tiddlerfield", "text": "Defines the behaviour of an individual tiddler field." }, "$:/language/Docs/ModuleTypes/tiddlermethod": { "title": "$:/language/Docs/ModuleTypes/tiddlermethod", "text": "Adds methods to the `$tw.Tiddler` prototype." }, "$:/language/Docs/ModuleTypes/upgrader": { "title": "$:/language/Docs/ModuleTypes/upgrader", "text": "Applies upgrade processing to tiddlers during an upgrade/import." }, "$:/language/Docs/ModuleTypes/utils": { "title": "$:/language/Docs/ModuleTypes/utils", "text": "Adds methods to `$tw.utils`." }, "$:/language/Docs/ModuleTypes/utils-node": { "title": "$:/language/Docs/ModuleTypes/utils-node", "text": "Adds Node.js-specific methods to `$tw.utils`." }, "$:/language/Docs/ModuleTypes/widget": { "title": "$:/language/Docs/ModuleTypes/widget", "text": "Widgets encapsulate DOM rendering and refreshing." }, "$:/language/Docs/ModuleTypes/wikimethod": { "title": "$:/language/Docs/ModuleTypes/wikimethod", "text": "Adds methods to `$tw.Wiki`." }, "$:/language/Docs/ModuleTypes/wikirule": { "title": "$:/language/Docs/ModuleTypes/wikirule", "text": "Individual parser rules for the main WikiText parser." }, "$:/language/Docs/PaletteColours/alert-background": { "title": "$:/language/Docs/PaletteColours/alert-background", "text": "Alert background" }, "$:/language/Docs/PaletteColours/alert-border": { "title": "$:/language/Docs/PaletteColours/alert-border", "text": "Alert border" }, "$:/language/Docs/PaletteColours/alert-highlight": { "title": "$:/language/Docs/PaletteColours/alert-highlight", "text": "Alert highlight" }, "$:/language/Docs/PaletteColours/alert-muted-foreground": { "title": "$:/language/Docs/PaletteColours/alert-muted-foreground", "text": "Alert muted foreground" }, "$:/language/Docs/PaletteColours/background": { "title": "$:/language/Docs/PaletteColours/background", "text": "General background" }, "$:/language/Docs/PaletteColours/blockquote-bar": { "title": "$:/language/Docs/PaletteColours/blockquote-bar", "text": "Blockquote bar" }, "$:/language/Docs/PaletteColours/button-background": { "title": "$:/language/Docs/PaletteColours/button-background", "text": "Default button background" }, "$:/language/Docs/PaletteColours/button-border": { "title": "$:/language/Docs/PaletteColours/button-border", "text": "Default button border" }, "$:/language/Docs/PaletteColours/button-foreground": { "title": "$:/language/Docs/PaletteColours/button-foreground", "text": "Default button foreground" }, "$:/language/Docs/PaletteColours/dirty-indicator": { "title": "$:/language/Docs/PaletteColours/dirty-indicator", "text": "Unsaved changes indicator" }, "$:/language/Docs/PaletteColours/code-background": { "title": "$:/language/Docs/PaletteColours/code-background", "text": "Code background" }, "$:/language/Docs/PaletteColours/code-border": { "title": "$:/language/Docs/PaletteColours/code-border", "text": "Code border" }, "$:/language/Docs/PaletteColours/code-foreground": { "title": "$:/language/Docs/PaletteColours/code-foreground", "text": "Code foreground" }, "$:/language/Docs/PaletteColours/download-background": { "title": "$:/language/Docs/PaletteColours/download-background", "text": "Download button background" }, "$:/language/Docs/PaletteColours/download-foreground": { "title": "$:/language/Docs/PaletteColours/download-foreground", "text": "Download button foreground" }, "$:/language/Docs/PaletteColours/dragger-background": { "title": "$:/language/Docs/PaletteColours/dragger-background", "text": "Dragger background" }, "$:/language/Docs/PaletteColours/dragger-foreground": { "title": "$:/language/Docs/PaletteColours/dragger-foreground", "text": "Dragger foreground" }, "$:/language/Docs/PaletteColours/dropdown-background": { "title": "$:/language/Docs/PaletteColours/dropdown-background", "text": "Dropdown background" }, "$:/language/Docs/PaletteColours/dropdown-border": { "title": "$:/language/Docs/PaletteColours/dropdown-border", "text": "Dropdown border" }, "$:/language/Docs/PaletteColours/dropdown-tab-background-selected": { "title": "$:/language/Docs/PaletteColours/dropdown-tab-background-selected", "text": "Dropdown tab background for selected tabs" }, "$:/language/Docs/PaletteColours/dropdown-tab-background": { "title": "$:/language/Docs/PaletteColours/dropdown-tab-background", "text": "Dropdown tab background" }, "$:/language/Docs/PaletteColours/dropzone-background": { "title": "$:/language/Docs/PaletteColours/dropzone-background", "text": "Dropzone background" }, "$:/language/Docs/PaletteColours/external-link-background-hover": { "title": "$:/language/Docs/PaletteColours/external-link-background-hover", "text": "External link background hover" }, "$:/language/Docs/PaletteColours/external-link-background-visited": { "title": "$:/language/Docs/PaletteColours/external-link-background-visited", "text": "External link background visited" }, "$:/language/Docs/PaletteColours/external-link-background": { "title": "$:/language/Docs/PaletteColours/external-link-background", "text": "External link background" }, "$:/language/Docs/PaletteColours/external-link-foreground-hover": { "title": "$:/language/Docs/PaletteColours/external-link-foreground-hover", "text": "External link foreground hover" }, "$:/language/Docs/PaletteColours/external-link-foreground-visited": { "title": "$:/language/Docs/PaletteColours/external-link-foreground-visited", "text": "External link foreground visited" }, "$:/language/Docs/PaletteColours/external-link-foreground": { "title": "$:/language/Docs/PaletteColours/external-link-foreground", "text": "External link foreground" }, "$:/language/Docs/PaletteColours/foreground": { "title": "$:/language/Docs/PaletteColours/foreground", "text": "General foreground" }, "$:/language/Docs/PaletteColours/message-background": { "title": "$:/language/Docs/PaletteColours/message-background", "text": "Message box background" }, "$:/language/Docs/PaletteColours/message-border": { "title": "$:/language/Docs/PaletteColours/message-border", "text": "Message box border" }, "$:/language/Docs/PaletteColours/message-foreground": { "title": "$:/language/Docs/PaletteColours/message-foreground", "text": "Message box foreground" }, "$:/language/Docs/PaletteColours/modal-backdrop": { "title": "$:/language/Docs/PaletteColours/modal-backdrop", "text": "Modal backdrop" }, "$:/language/Docs/PaletteColours/modal-background": { "title": "$:/language/Docs/PaletteColours/modal-background", "text": "Modal background" }, "$:/language/Docs/PaletteColours/modal-border": { "title": "$:/language/Docs/PaletteColours/modal-border", "text": "Modal border" }, "$:/language/Docs/PaletteColours/modal-footer-background": { "title": "$:/language/Docs/PaletteColours/modal-footer-background", "text": "Modal footer background" }, "$:/language/Docs/PaletteColours/modal-footer-border": { "title": "$:/language/Docs/PaletteColours/modal-footer-border", "text": "Modal footer border" }, "$:/language/Docs/PaletteColours/modal-header-border": { "title": "$:/language/Docs/PaletteColours/modal-header-border", "text": "Modal header border" }, "$:/language/Docs/PaletteColours/muted-foreground": { "title": "$:/language/Docs/PaletteColours/muted-foreground", "text": "General muted foreground" }, "$:/language/Docs/PaletteColours/notification-background": { "title": "$:/language/Docs/PaletteColours/notification-background", "text": "Notification background" }, "$:/language/Docs/PaletteColours/notification-border": { "title": "$:/language/Docs/PaletteColours/notification-border", "text": "Notification border" }, "$:/language/Docs/PaletteColours/page-background": { "title": "$:/language/Docs/PaletteColours/page-background", "text": "Page background" }, "$:/language/Docs/PaletteColours/pre-background": { "title": "$:/language/Docs/PaletteColours/pre-background", "text": "Preformatted code background" }, "$:/language/Docs/PaletteColours/pre-border": { "title": "$:/language/Docs/PaletteColours/pre-border", "text": "Preformatted code border" }, "$:/language/Docs/PaletteColours/primary": { "title": "$:/language/Docs/PaletteColours/primary", "text": "General primary" }, "$:/language/Docs/PaletteColours/sidebar-button-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-button-foreground", "text": "Sidebar button foreground" }, "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover": { "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover", "text": "Sidebar controls foreground hover" }, "$:/language/Docs/PaletteColours/sidebar-controls-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground", "text": "Sidebar controls foreground" }, "$:/language/Docs/PaletteColours/sidebar-foreground-shadow": { "title": "$:/language/Docs/PaletteColours/sidebar-foreground-shadow", "text": "Sidebar foreground shadow" }, "$:/language/Docs/PaletteColours/sidebar-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-foreground", "text": "Sidebar foreground" }, "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover": { "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover", "text": "Sidebar muted foreground hover" }, "$:/language/Docs/PaletteColours/sidebar-muted-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground", "text": "Sidebar muted foreground" }, "$:/language/Docs/PaletteColours/sidebar-tab-background-selected": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-background-selected", "text": "Sidebar tab background for selected tabs" }, "$:/language/Docs/PaletteColours/sidebar-tab-background": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-background", "text": "Sidebar tab background" }, "$:/language/Docs/PaletteColours/sidebar-tab-border-selected": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-border-selected", "text": "Sidebar tab border for selected tabs" }, "$:/language/Docs/PaletteColours/sidebar-tab-border": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-border", "text": "Sidebar tab border" }, "$:/language/Docs/PaletteColours/sidebar-tab-divider": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-divider", "text": "Sidebar tab divider" }, "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected", "text": "Sidebar tab foreground for selected tabs" }, "$:/language/Docs/PaletteColours/sidebar-tab-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground", "text": "Sidebar tab foreground" }, "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover": { "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover", "text": "Sidebar tiddler link foreground hover" }, "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground", "text": "Sidebar tiddler link foreground" }, "$:/language/Docs/PaletteColours/site-title-foreground": { "title": "$:/language/Docs/PaletteColours/site-title-foreground", "text": "Site title foreground" }, "$:/language/Docs/PaletteColours/static-alert-foreground": { "title": "$:/language/Docs/PaletteColours/static-alert-foreground", "text": "Static alert foreground" }, "$:/language/Docs/PaletteColours/tab-background-selected": { "title": "$:/language/Docs/PaletteColours/tab-background-selected", "text": "Tab background for selected tabs" }, "$:/language/Docs/PaletteColours/tab-background": { "title": "$:/language/Docs/PaletteColours/tab-background", "text": "Tab background" }, "$:/language/Docs/PaletteColours/tab-border-selected": { "title": "$:/language/Docs/PaletteColours/tab-border-selected", "text": "Tab border for selected tabs" }, "$:/language/Docs/PaletteColours/tab-border": { "title": "$:/language/Docs/PaletteColours/tab-border", "text": "Tab border" }, "$:/language/Docs/PaletteColours/tab-divider": { "title": "$:/language/Docs/PaletteColours/tab-divider", "text": "Tab divider" }, "$:/language/Docs/PaletteColours/tab-foreground-selected": { "title": "$:/language/Docs/PaletteColours/tab-foreground-selected", "text": "Tab foreground for selected tabs" }, "$:/language/Docs/PaletteColours/tab-foreground": { "title": "$:/language/Docs/PaletteColours/tab-foreground", "text": "Tab foreground" }, "$:/language/Docs/PaletteColours/table-border": { "title": "$:/language/Docs/PaletteColours/table-border", "text": "Table border" }, "$:/language/Docs/PaletteColours/table-footer-background": { "title": "$:/language/Docs/PaletteColours/table-footer-background", "text": "Table footer background" }, "$:/language/Docs/PaletteColours/table-header-background": { "title": "$:/language/Docs/PaletteColours/table-header-background", "text": "Table header background" }, "$:/language/Docs/PaletteColours/tag-background": { "title": "$:/language/Docs/PaletteColours/tag-background", "text": "Tag background" }, "$:/language/Docs/PaletteColours/tag-foreground": { "title": "$:/language/Docs/PaletteColours/tag-foreground", "text": "Tag foreground" }, "$:/language/Docs/PaletteColours/tiddler-background": { "title": "$:/language/Docs/PaletteColours/tiddler-background", "text": "Tiddler background" }, "$:/language/Docs/PaletteColours/tiddler-border": { "title": "$:/language/Docs/PaletteColours/tiddler-border", "text": "Tiddler border" }, "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover": { "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover", "text": "Tiddler controls foreground hover" }, "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected": { "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected", "text": "Tiddler controls foreground for selected controls" }, "$:/language/Docs/PaletteColours/tiddler-controls-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground", "text": "Tiddler controls foreground" }, "$:/language/Docs/PaletteColours/tiddler-editor-background": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-background", "text": "Tiddler editor background" }, "$:/language/Docs/PaletteColours/tiddler-editor-border-image": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-border-image", "text": "Tiddler editor border image" }, "$:/language/Docs/PaletteColours/tiddler-editor-border": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-border", "text": "Tiddler editor border" }, "$:/language/Docs/PaletteColours/tiddler-editor-fields-even": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-even", "text": "Tiddler editor background for even fields" }, "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd", "text": "Tiddler editor background for odd fields" }, "$:/language/Docs/PaletteColours/tiddler-info-background": { "title": "$:/language/Docs/PaletteColours/tiddler-info-background", "text": "Tiddler info panel background" }, "$:/language/Docs/PaletteColours/tiddler-info-border": { "title": "$:/language/Docs/PaletteColours/tiddler-info-border", "text": "Tiddler info panel border" }, "$:/language/Docs/PaletteColours/tiddler-info-tab-background": { "title": "$:/language/Docs/PaletteColours/tiddler-info-tab-background", "text": "Tiddler info panel tab background" }, "$:/language/Docs/PaletteColours/tiddler-link-background": { "title": "$:/language/Docs/PaletteColours/tiddler-link-background", "text": "Tiddler link background" }, "$:/language/Docs/PaletteColours/tiddler-link-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-link-foreground", "text": "Tiddler link foreground" }, "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground", "text": "Tiddler subtitle foreground" }, "$:/language/Docs/PaletteColours/tiddler-title-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-title-foreground", "text": "Tiddler title foreground" }, "$:/language/Docs/PaletteColours/toolbar-new-button": { "title": "$:/language/Docs/PaletteColours/toolbar-new-button", "text": "Toolbar 'new tiddler' button foreground" }, "$:/language/Docs/PaletteColours/toolbar-options-button": { "title": "$:/language/Docs/PaletteColours/toolbar-options-button", "text": "Toolbar 'options' button foreground" }, "$:/language/Docs/PaletteColours/toolbar-save-button": { "title": "$:/language/Docs/PaletteColours/toolbar-save-button", "text": "Toolbar 'save' button foreground" }, "$:/language/Docs/PaletteColours/toolbar-info-button": { "title": "$:/language/Docs/PaletteColours/toolbar-info-button", "text": "Toolbar 'info' button foreground" }, "$:/language/Docs/PaletteColours/toolbar-edit-button": { "title": "$:/language/Docs/PaletteColours/toolbar-edit-button", "text": "Toolbar 'edit' button foreground" }, "$:/language/Docs/PaletteColours/toolbar-close-button": { "title": "$:/language/Docs/PaletteColours/toolbar-close-button", "text": "Toolbar 'close' button foreground" }, "$:/language/Docs/PaletteColours/toolbar-delete-button": { "title": "$:/language/Docs/PaletteColours/toolbar-delete-button", "text": "Toolbar 'delete' button foreground" }, "$:/language/Docs/PaletteColours/toolbar-cancel-button": { "title": "$:/language/Docs/PaletteColours/toolbar-cancel-button", "text": "Toolbar 'cancel' button foreground" }, "$:/language/Docs/PaletteColours/toolbar-done-button": { "title": "$:/language/Docs/PaletteColours/toolbar-done-button", "text": "Toolbar 'done' button foreground" }, "$:/language/Docs/PaletteColours/untagged-background": { "title": "$:/language/Docs/PaletteColours/untagged-background", "text": "Untagged pill background" }, "$:/language/Docs/PaletteColours/very-muted-foreground": { "title": "$:/language/Docs/PaletteColours/very-muted-foreground", "text": "Very muted foreground" }, "$:/language/EditTemplate/Body/External/Hint": { "title": "$:/language/EditTemplate/Body/External/Hint", "text": "This is an external tiddler stored outside of the main TiddlyWiki file. You can edit the tags and fields but cannot directly edit the content itself" }, "$:/language/EditTemplate/Body/Placeholder": { "title": "$:/language/EditTemplate/Body/Placeholder", "text": "Type the text for this tiddler" }, "$:/language/EditTemplate/Body/Preview/Type/Output": { "title": "$:/language/EditTemplate/Body/Preview/Type/Output", "text": "output" }, "$:/language/EditTemplate/Field/Remove/Caption": { "title": "$:/language/EditTemplate/Field/Remove/Caption", "text": "remove field" }, "$:/language/EditTemplate/Field/Remove/Hint": { "title": "$:/language/EditTemplate/Field/Remove/Hint", "text": "Remove field" }, "$:/language/EditTemplate/Fields/Add/Button": { "title": "$:/language/EditTemplate/Fields/Add/Button", "text": "add" }, "$:/language/EditTemplate/Fields/Add/Name/Placeholder": { "title": "$:/language/EditTemplate/Fields/Add/Name/Placeholder", "text": "field name" }, "$:/language/EditTemplate/Fields/Add/Prompt": { "title": "$:/language/EditTemplate/Fields/Add/Prompt", "text": "Add a new field:" }, "$:/language/EditTemplate/Fields/Add/Value/Placeholder": { "title": "$:/language/EditTemplate/Fields/Add/Value/Placeholder", "text": "field value" }, "$:/language/EditTemplate/Fields/Add/Dropdown/System": { "title": "$:/language/EditTemplate/Fields/Add/Dropdown/System", "text": "System fields" }, "$:/language/EditTemplate/Fields/Add/Dropdown/User": { "title": "$:/language/EditTemplate/Fields/Add/Dropdown/User", "text": "User fields" }, "$:/language/EditTemplate/Shadow/Warning": { "title": "$:/language/EditTemplate/Shadow/Warning", "text": "This is a shadow tiddler. Any changes you make will override the default version from the plugin <<pluginLink>>" }, "$:/language/EditTemplate/Shadow/OverriddenWarning": { "title": "$:/language/EditTemplate/Shadow/OverriddenWarning", "text": "This is a modified shadow tiddler. You can revert to the default version in the plugin <<pluginLink>> by deleting this tiddler" }, "$:/language/EditTemplate/Tags/Add/Button": { "title": "$:/language/EditTemplate/Tags/Add/Button", "text": "add" }, "$:/language/EditTemplate/Tags/Add/Placeholder": { "title": "$:/language/EditTemplate/Tags/Add/Placeholder", "text": "tag name" }, "$:/language/EditTemplate/Tags/Dropdown/Caption": { "title": "$:/language/EditTemplate/Tags/Dropdown/Caption", "text": "tag list" }, "$:/language/EditTemplate/Tags/Dropdown/Hint": { "title": "$:/language/EditTemplate/Tags/Dropdown/Hint", "text": "Show tag list" }, "$:/language/EditTemplate/Title/BadCharacterWarning": { "title": "$:/language/EditTemplate/Title/BadCharacterWarning", "text": "Warning: avoid using any of the characters <<bad-chars>> in tiddler titles" }, "$:/language/EditTemplate/Title/Exists/Prompt": { "title": "$:/language/EditTemplate/Title/Exists/Prompt", "text": "Target tiddler already exists" }, "$:/language/EditTemplate/Title/Relink/Prompt": { "title": "$:/language/EditTemplate/Title/Relink/Prompt", "text": "Update ''<$text text=<<fromTitle>>/>'' to ''<$text text=<<toTitle>>/>'' in the //tags// and //list// fields of other tiddlers" }, "$:/language/EditTemplate/Type/Dropdown/Caption": { "title": "$:/language/EditTemplate/Type/Dropdown/Caption", "text": "content type list" }, "$:/language/EditTemplate/Type/Dropdown/Hint": { "title": "$:/language/EditTemplate/Type/Dropdown/Hint", "text": "Show content type list" }, "$:/language/EditTemplate/Type/Delete/Caption": { "title": "$:/language/EditTemplate/Type/Delete/Caption", "text": "delete content type" }, "$:/language/EditTemplate/Type/Delete/Hint": { "title": "$:/language/EditTemplate/Type/Delete/Hint", "text": "Delete content type" }, "$:/language/EditTemplate/Type/Placeholder": { "title": "$:/language/EditTemplate/Type/Placeholder", "text": "content type" }, "$:/language/EditTemplate/Type/Prompt": { "title": "$:/language/EditTemplate/Type/Prompt", "text": "Type:" }, "$:/language/Exporters/StaticRiver": { "title": "$:/language/Exporters/StaticRiver", "text": "Static HTML" }, "$:/language/Exporters/JsonFile": { "title": "$:/language/Exporters/JsonFile", "text": "JSON file" }, "$:/language/Exporters/CsvFile": { "title": "$:/language/Exporters/CsvFile", "text": "CSV file" }, "$:/language/Exporters/TidFile": { "title": "$:/language/Exporters/TidFile", "text": "\".tid\" file" }, "$:/language/Docs/Fields/_canonical_uri": { "title": "$:/language/Docs/Fields/_canonical_uri", "text": "The full URI of an external image tiddler" }, "$:/language/Docs/Fields/bag": { "title": "$:/language/Docs/Fields/bag", "text": "The name of the bag from which a tiddler came" }, "$:/language/Docs/Fields/caption": { "title": "$:/language/Docs/Fields/caption", "text": "The text to be displayed on a tab or button" }, "$:/language/Docs/Fields/color": { "title": "$:/language/Docs/Fields/color", "text": "The CSS color value associated with a tiddler" }, "$:/language/Docs/Fields/component": { "title": "$:/language/Docs/Fields/component", "text": "The name of the component responsible for an [[alert tiddler|AlertMechanism]]" }, "$:/language/Docs/Fields/current-tiddler": { "title": "$:/language/Docs/Fields/current-tiddler", "text": "Used to cache the top tiddler in a [[history list|HistoryMechanism]]" }, "$:/language/Docs/Fields/created": { "title": "$:/language/Docs/Fields/created", "text": "The date a tiddler was created" }, "$:/language/Docs/Fields/creator": { "title": "$:/language/Docs/Fields/creator", "text": "The name of the person who created a tiddler" }, "$:/language/Docs/Fields/dependents": { "title": "$:/language/Docs/Fields/dependents", "text": "For a plugin, lists the dependent plugin titles" }, "$:/language/Docs/Fields/description": { "title": "$:/language/Docs/Fields/description", "text": "The descriptive text for a plugin, or a modal dialogue" }, "$:/language/Docs/Fields/draft.of": { "title": "$:/language/Docs/Fields/draft.of", "text": "For draft tiddlers, contains the title of the tiddler of which this is a draft" }, "$:/language/Docs/Fields/draft.title": { "title": "$:/language/Docs/Fields/draft.title", "text": "For draft tiddlers, contains the proposed new title of the tiddler" }, "$:/language/Docs/Fields/footer": { "title": "$:/language/Docs/Fields/footer", "text": "The footer text for a wizard" }, "$:/language/Docs/Fields/hack-to-give-us-something-to-compare-against": { "title": "$:/language/Docs/Fields/hack-to-give-us-something-to-compare-against", "text": "A temporary storage field used in [[$:/core/templates/static.content]]" }, "$:/language/Docs/Fields/icon": { "title": "$:/language/Docs/Fields/icon", "text": "The title of the tiddler containing the icon associated with a tiddler" }, "$:/language/Docs/Fields/library": { "title": "$:/language/Docs/Fields/library", "text": "If set to \"yes\" indicates that a tiddler should be saved as a JavaScript library" }, "$:/language/Docs/Fields/list": { "title": "$:/language/Docs/Fields/list", "text": "An ordered list of tiddler titles associated with a tiddler" }, "$:/language/Docs/Fields/list-before": { "title": "$:/language/Docs/Fields/list-before", "text": "If set, the title of a tiddler before which this tiddler should be added to the ordered list of tiddler titles, or at the start of the list if this field is present but empty" }, "$:/language/Docs/Fields/list-after": { "title": "$:/language/Docs/Fields/list-after", "text": "If set, the title of the tiddler after which this tiddler should be added to the ordered list of tiddler titles" }, "$:/language/Docs/Fields/modified": { "title": "$:/language/Docs/Fields/modified", "text": "The date and time at which a tiddler was last modified" }, "$:/language/Docs/Fields/modifier": { "title": "$:/language/Docs/Fields/modifier", "text": "The tiddler title associated with the person who last modified a tiddler" }, "$:/language/Docs/Fields/name": { "title": "$:/language/Docs/Fields/name", "text": "The human readable name associated with a plugin tiddler" }, "$:/language/Docs/Fields/plugin-priority": { "title": "$:/language/Docs/Fields/plugin-priority", "text": "A numerical value indicating the priority of a plugin tiddler" }, "$:/language/Docs/Fields/plugin-type": { "title": "$:/language/Docs/Fields/plugin-type", "text": "The type of plugin in a plugin tiddler" }, "$:/language/Docs/Fields/revision": { "title": "$:/language/Docs/Fields/revision", "text": "The revision of the tiddler held at the server" }, "$:/language/Docs/Fields/released": { "title": "$:/language/Docs/Fields/released", "text": "Date of a TiddlyWiki release" }, "$:/language/Docs/Fields/source": { "title": "$:/language/Docs/Fields/source", "text": "The source URL associated with a tiddler" }, "$:/language/Docs/Fields/subtitle": { "title": "$:/language/Docs/Fields/subtitle", "text": "The subtitle text for a wizard" }, "$:/language/Docs/Fields/tags": { "title": "$:/language/Docs/Fields/tags", "text": "A list of tags associated with a tiddler" }, "$:/language/Docs/Fields/text": { "title": "$:/language/Docs/Fields/text", "text": "The body text of a tiddler" }, "$:/language/Docs/Fields/title": { "title": "$:/language/Docs/Fields/title", "text": "The unique name of a tiddler" }, "$:/language/Docs/Fields/type": { "title": "$:/language/Docs/Fields/type", "text": "The content type of a tiddler" }, "$:/language/Docs/Fields/version": { "title": "$:/language/Docs/Fields/version", "text": "Version information for a plugin" }, "$:/language/Filters/AllTiddlers": { "title": "$:/language/Filters/AllTiddlers", "text": "All tiddlers except system tiddlers" }, "$:/language/Filters/RecentSystemTiddlers": { "title": "$:/language/Filters/RecentSystemTiddlers", "text": "Recently modified tiddlers, including system tiddlers" }, "$:/language/Filters/RecentTiddlers": { "title": "$:/language/Filters/RecentTiddlers", "text": "Recently modified tiddlers" }, "$:/language/Filters/AllTags": { "title": "$:/language/Filters/AllTags", "text": "All tags except system tags" }, "$:/language/Filters/Missing": { "title": "$:/language/Filters/Missing", "text": "Missing tiddlers" }, "$:/language/Filters/Drafts": { "title": "$:/language/Filters/Drafts", "text": "Draft tiddlers" }, "$:/language/Filters/Orphans": { "title": "$:/language/Filters/Orphans", "text": "Orphan tiddlers" }, "$:/language/Filters/SystemTiddlers": { "title": "$:/language/Filters/SystemTiddlers", "text": "System tiddlers" }, "$:/language/Filters/ShadowTiddlers": { "title": "$:/language/Filters/ShadowTiddlers", "text": "Shadow tiddlers" }, "$:/language/Filters/OverriddenShadowTiddlers": { "title": "$:/language/Filters/OverriddenShadowTiddlers", "text": "Overridden shadow tiddlers" }, "$:/language/Filters/SystemTags": { "title": "$:/language/Filters/SystemTags", "text": "System tags" }, "$:/language/Filters/StoryList": { "title": "$:/language/Filters/StoryList", "text": "Tiddlers in the story river, excluding <$text text=\"$:/AdvancedSearch\"/>" }, "$:/language/Filters/TypedTiddlers": { "title": "$:/language/Filters/TypedTiddlers", "text": "Non wiki-text tiddlers" }, "GettingStarted": { "title": "GettingStarted", "text": "\\define lingo-base() $:/language/ControlPanel/Basics/\nWelcome to ~TiddlyWiki and the ~TiddlyWiki community\n\nBefore you start storing important information in ~TiddlyWiki it is important to make sure that you can reliably save changes. See http://tiddlywiki.com/#GettingStarted for details\n\n!! Set up this ~TiddlyWiki\n\n<div class=\"tc-control-panel\">\n\n|<$link to=\"$:/SiteTitle\"><<lingo Title/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteTitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/SiteSubtitle\"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteSubtitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/DefaultTiddlers\"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit tag=\"textarea\" tiddler=\"$:/DefaultTiddlers\"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |\n</div>\n\nSee the [[control panel|$:/ControlPanel]] for more options.\n" }, "$:/language/Help/build": { "title": "$:/language/Help/build", "description": "Automatically run configured commands", "text": "Build the specified build targets for the current wiki. If no build targets are specified then all available targets will be built.\n\n```\n--build <target> [<target> ...]\n```\n\nBuild targets are defined in the `tiddlywiki.info` file of a wiki folder.\n\n" }, "$:/language/Help/clearpassword": { "title": "$:/language/Help/clearpassword", "description": "Clear a password for subsequent crypto operations", "text": "Clear the password for subsequent crypto operations\n\n```\n--clearpassword\n```\n" }, "$:/language/Help/default": { "title": "$:/language/Help/default", "text": "\\define commandTitle()\n$:/language/Help/$(command)$\n\\end\n```\nusage: tiddlywiki [<wikifolder>] [--<command> [<args>...]...]\n```\n\nAvailable commands:\n\n<ul>\n<$list filter=\"[commands[]sort[title]]\" variable=\"command\">\n<li><$link to=<<commandTitle>>><$macrocall $name=\"command\" $type=\"text/plain\" $output=\"text/plain\"/></$link>: <$transclude tiddler=<<commandTitle>> field=\"description\"/></li>\n</$list>\n</ul>\n\nTo get detailed help on a command:\n\n```\ntiddlywiki --help <command>\n```\n" }, "$:/language/Help/editions": { "title": "$:/language/Help/editions", "description": "Lists the available editions of TiddlyWiki", "text": "Lists the names and descriptions of the available editions. You can create a new wiki of a specified edition with the `--init` command.\n\n```\n--editions\n```\n" }, "$:/language/Help/fetch": { "title": "$:/language/Help/fetch", "description": "Fetch tiddlers from wiki by URL", "text": "Fetch one or more files over HTTP/HTTPS, and import the tiddlers matching a filter, optionally transforming the incoming titles.\n\n```\n--fetch file <url> <import-filter> <transform-filter>\n--fetch files <url-filter> <import-filter> <transform-filter>\n```\n\nWith the \"file\" variant only a single file is fetched and the first parameter is the URL of the file to read.\n\nWith the \"files\" variant, multiple files are fetched and the first parameter is a filter yielding a list of URLs of the files to read. For example, given a set of tiddlers tagged \"remote-server\" that have a field \"url\" the filter `[tag[remote-server]get[url]]` will retrieve all the available URLs.\n\nThe `<import-filter>` parameter specifies a filter determining which tiddlers are imported. It defaults to `[all[tiddlers]]` if not provided.\n\nThe `<transform-filter>` parameter specifies an optional filter that transforms the titles of the imported tiddlers. For example, `[addprefix[$:/myimports/]]` would add the prefix `$:/myimports/` to each title.\n\nPreceding the `--fetch` command with `--verbose` will output progress information during the import.\n\nNote that TiddlyWiki will not fetch an older version of an already loaded plugin.\n\nThe following example retrieves all the non-system tiddlers from http://tiddlywiki.com and saves them to a JSON file:\n\n```\ntiddlywiki --verbose --fetch file \"http://tiddlywiki.com/\" \"[!is[system]]\" \"\" --rendertiddler \"$:/core/templates/exporters/JsonFile\" output.json text/plain \"\" exportFilter \"[!is[system]]\"\n```\n\n" }, "$:/language/Help/help": { "title": "$:/language/Help/help", "description": "Display help for TiddlyWiki commands", "text": "Displays help text for a command:\n\n```\n--help [<command>]\n```\n\nIf the command name is omitted then a list of available commands is displayed.\n" }, "$:/language/Help/init": { "title": "$:/language/Help/init", "description": "Initialise a new wiki folder", "text": "Initialise an empty [[WikiFolder|WikiFolders]] with a copy of the specified edition.\n\n```\n--init <edition> [<edition> ...]\n```\n\nFor example:\n\n```\ntiddlywiki ./MyWikiFolder --init empty\n```\n\nNote:\n\n* The wiki folder directory will be created if necessary\n* The \"edition\" defaults to ''empty''\n* The init command will fail if the wiki folder is not empty\n* The init command removes any `includeWikis` definitions in the edition's `tiddlywiki.info` file\n* When multiple editions are specified, editions initialised later will overwrite any files shared with earlier editions (so, the final `tiddlywiki.info` file will be copied from the last edition)\n* `--editions` returns a list of available editions\n" }, "$:/language/Help/load": { "title": "$:/language/Help/load", "description": "Load tiddlers from a file", "text": "Load tiddlers from 2.x.x TiddlyWiki files (`.html`), `.tiddler`, `.tid`, `.json` or other files\n\n```\n--load <filepath>\n```\n\nTo load tiddlers from an encrypted TiddlyWiki file you should first specify the password with the PasswordCommand. For example:\n\n```\ntiddlywiki ./MyWiki --password pa55w0rd --load my_encrypted_wiki.html\n```\n\nNote that TiddlyWiki will not load an older version of an already loaded plugin.\n" }, "$:/language/Help/makelibrary": { "title": "$:/language/Help/makelibrary", "description": "Construct library plugin required by upgrade process", "text": "Constructs the `$:/UpgradeLibrary` tiddler for the upgrade process.\n\nThe upgrade library is formatted as an ordinary plugin tiddler with the plugin type `library`. It contains a copy of each of the plugins, themes and language packs available within the TiddlyWiki5 repository.\n\nThis command is intended for internal use; it is only relevant to users constructing a custom upgrade procedure.\n\n```\n--makelibrary <title>\n```\n\nThe title argument defaults to `$:/UpgradeLibrary`.\n" }, "$:/language/Help/notfound": { "title": "$:/language/Help/notfound", "text": "No such help item" }, "$:/language/Help/output": { "title": "$:/language/Help/output", "description": "Set the base output directory for subsequent commands", "text": "Sets the base output directory for subsequent commands. The default output directory is the `output` subdirectory of the edition directory.\n\n```\n--output <pathname>\n```\n\nIf the specified pathname is relative then it is resolved relative to the current working directory. For example `--output .` sets the output directory to the current working directory.\n\n" }, "$:/language/Help/password": { "title": "$:/language/Help/password", "description": "Set a password for subsequent crypto operations", "text": "Set a password for subsequent crypto operations\n\n```\n--password <password>\n```\n\n''Note'': This should not be used for serving TiddlyWiki with password protection. Instead, see the password option under the [[ServerCommand]].\n" }, "$:/language/Help/rendertiddler": { "title": "$:/language/Help/rendertiddler", "description": "Render an individual tiddler as a specified ContentType", "text": "Render an individual tiddler as a specified ContentType, defaulting to `text/html` and save it to the specified filename.\n\nOptionally the title of a template tiddler can be specified, in which case the template tiddler is rendered with the \"currentTiddler\" variable set to the tiddler that is being rendered (the first parameter value).\n\nA name and value for an additional variable may optionally also be specified.\n\n```\n--rendertiddler <title> <filename> [<type>] [<template>] [<name>] [<value>]\n```\n\nBy default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nAny missing directories in the path to the filename are automatically created.\n\nFor example, the following command saves all tiddlers matching the filter `[tag[done]]` to a JSON file titled `output.json` by employing the core template `$:/core/templates/exporters/JsonFile`.\n\n```\n--rendertiddler \"$:/core/templates/exporters/JsonFile\" output.json text/plain \"\" exportFilter \"[tag[done]]\"\n```\n" }, "$:/language/Help/rendertiddlers": { "title": "$:/language/Help/rendertiddlers", "description": "Render tiddlers matching a filter to a specified ContentType", "text": "Render a set of tiddlers matching a filter to separate files of a specified ContentType (defaults to `text/html`) and extension (defaults to `.html`).\n\n```\n--rendertiddlers <filter> <template> <pathname> [<type>] [<extension>] [\"noclean\"]\n```\n\nFor example:\n\n```\n--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html ./static text/plain\n```\n\nBy default, the pathname is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nAny files in the target directory are deleted unless the ''noclean'' flag is specified. The target directory is recursively created if it is missing.\n" }, "$:/language/Help/savetiddler": { "title": "$:/language/Help/savetiddler", "description": "Saves a raw tiddler to a file", "text": "Saves an individual tiddler in its raw text or binary format to the specified filename.\n\n```\n--savetiddler <title> <filename>\n```\n\nBy default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nAny missing directories in the path to the filename are automatically created.\n" }, "$:/language/Help/savetiddlers": { "title": "$:/language/Help/savetiddlers", "description": "Saves a group of raw tiddlers to a directory", "text": "Saves a group of tiddlers in their raw text or binary format to the specified directory.\n\n```\n--savetiddlers <filter> <pathname> [\"noclean\"]\n```\n\nBy default, the pathname is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.\n\nThe output directory is cleared of existing files before saving the specified files. The deletion can be disabled by specifying the ''noclean'' flag.\n\nAny missing directories in the pathname are automatically created.\n" }, "$:/language/Help/server": { "title": "$:/language/Help/server", "description": "Provides an HTTP server interface to TiddlyWiki", "text": "The server built in to TiddlyWiki5 is very simple. Although compatible with TiddlyWeb it doesn't support many of the features needed for robust Internet-facing usage.\n\nAt the root, it serves a rendering of a specified tiddler. Away from the root, it serves individual tiddlers encoded in JSON, and supports the basic HTTP operations for `GET`, `PUT` and `DELETE`.\n\n```\n--server <port> <roottiddler> <rendertype> <servetype> <username> <password> <host> <pathprefix>\n```\n\nThe parameters are:\n\n* ''port'' - port number to serve from (defaults to \"8080\")\n* ''roottiddler'' - the tiddler to serve at the root (defaults to \"$:/core/save/all\")\n* ''rendertype'' - the content type to which the root tiddler should be rendered (defaults to \"text/plain\")\n* ''servetype'' - the content type with which the root tiddler should be served (defaults to \"text/html\")\n* ''username'' - the default username for signing edits\n* ''password'' - optional password for basic authentication\n* ''host'' - optional hostname to serve from (defaults to \"127.0.0.1\" aka \"localhost\")\n* ''pathprefix'' - optional prefix for paths\n\nIf the password parameter is specified then the browser will prompt the user for the username and password. Note that the password is transmitted in plain text so this implementation isn't suitable for general use.\n\nFor example:\n\n```\n--server 8080 $:/core/save/all text/plain text/html MyUserName passw0rd\n```\n\nThe username and password can be specified as empty strings if you need to set the hostname or pathprefix and don't want to require a password:\n\n```\n--server 8080 $:/core/save/all text/plain text/html \"\" \"\" 192.168.0.245\n```\n\nTo run multiple TiddlyWiki servers at the same time you'll need to put each one on a different port.\n" }, "$:/language/Help/setfield": { "title": "$:/language/Help/setfield", "description": "Prepares external tiddlers for use", "text": "//Note that this command is experimental and may change or be replaced before being finalised//\n\nSets the specified field of a group of tiddlers to the result of wikifying a template tiddler with the `currentTiddler` variable set to the tiddler.\n\n```\n--setfield <filter> <fieldname> <templatetitle> <rendertype>\n```\n\nThe parameters are:\n\n* ''filter'' - filter identifying the tiddlers to be affected\n* ''fieldname'' - the field to modify (defaults to \"text\")\n* ''templatetitle'' - the tiddler to wikify into the specified field. If blank or missing then the specified field is deleted\n* ''rendertype'' - the text type to render (defaults to \"text/plain\"; \"text/html\" can be used to include HTML tags)\n" }, "$:/language/Help/unpackplugin": { "title": "$:/language/Help/unpackplugin", "description": "Unpack the payload tiddlers from a plugin", "text": "Extract the payload tiddlers from a plugin, creating them as ordinary tiddlers:\n\n```\n--unpackplugin <title>\n```\n" }, "$:/language/Help/verbose": { "title": "$:/language/Help/verbose", "description": "Triggers verbose output mode", "text": "Triggers verbose output, useful for debugging\n\n```\n--verbose\n```\n" }, "$:/language/Help/version": { "title": "$:/language/Help/version", "description": "Displays the version number of TiddlyWiki", "text": "Displays the version number of TiddlyWiki.\n\n```\n--version\n```\n" }, "$:/language/Import/Imported/Hint": { "title": "$:/language/Import/Imported/Hint", "text": "The following tiddlers were imported:" }, "$:/language/Import/Listing/Cancel/Caption": { "title": "$:/language/Import/Listing/Cancel/Caption", "text": "Cancel" }, "$:/language/Import/Listing/Hint": { "title": "$:/language/Import/Listing/Hint", "text": "These tiddlers are ready to import:" }, "$:/language/Import/Listing/Import/Caption": { "title": "$:/language/Import/Listing/Import/Caption", "text": "Import" }, "$:/language/Import/Listing/Select/Caption": { "title": "$:/language/Import/Listing/Select/Caption", "text": "Select" }, "$:/language/Import/Listing/Status/Caption": { "title": "$:/language/Import/Listing/Status/Caption", "text": "Status" }, "$:/language/Import/Listing/Title/Caption": { "title": "$:/language/Import/Listing/Title/Caption", "text": "Title" }, "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible": { "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible", "text": "Blocked incompatible or obsolete plugin" }, "$:/language/Import/Upgrader/Plugins/Suppressed/Version": { "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Version", "text": "Blocked plugin (due to incoming <<incoming>> being older than existing <<existing>>)" }, "$:/language/Import/Upgrader/Plugins/Upgraded": { "title": "$:/language/Import/Upgrader/Plugins/Upgraded", "text": "Upgraded plugin from <<incoming>> to <<upgraded>>" }, "$:/language/Import/Upgrader/State/Suppressed": { "title": "$:/language/Import/Upgrader/State/Suppressed", "text": "Blocked temporary state tiddler" }, "$:/language/Import/Upgrader/System/Suppressed": { "title": "$:/language/Import/Upgrader/System/Suppressed", "text": "Blocked system tiddler" }, "$:/language/Import/Upgrader/ThemeTweaks/Created": { "title": "$:/language/Import/Upgrader/ThemeTweaks/Created", "text": "Migrated theme tweak from <$text text=<<from>>/>" }, "$:/language/AboveStory/ClassicPlugin/Warning": { "title": "$:/language/AboveStory/ClassicPlugin/Warning", "text": "It looks like you are trying to load a plugin designed for ~TiddlyWiki Classic. Please note that [[these plugins do not work with TiddlyWiki version 5.x.x|http://tiddlywiki.com/#TiddlyWikiClassic]]. ~TiddlyWiki Classic plugins detected:" }, "$:/language/BinaryWarning/Prompt": { "title": "$:/language/BinaryWarning/Prompt", "text": "This tiddler contains binary data" }, "$:/language/ClassicWarning/Hint": { "title": "$:/language/ClassicWarning/Hint", "text": "This tiddler is written in TiddlyWiki Classic wiki text format, which is not fully compatible with TiddlyWiki version 5. See http://tiddlywiki.com/static/Upgrading.html for more details." }, "$:/language/ClassicWarning/Upgrade/Caption": { "title": "$:/language/ClassicWarning/Upgrade/Caption", "text": "upgrade" }, "$:/language/CloseAll/Button": { "title": "$:/language/CloseAll/Button", "text": "close all" }, "$:/language/ColourPicker/Recent": { "title": "$:/language/ColourPicker/Recent", "text": "Recent:" }, "$:/language/ConfirmCancelTiddler": { "title": "$:/language/ConfirmCancelTiddler", "text": "Do you wish to discard changes to the tiddler \"<$text text=<<title>>/>\"?" }, "$:/language/ConfirmDeleteTiddler": { "title": "$:/language/ConfirmDeleteTiddler", "text": "Do you wish to delete the tiddler \"<$text text=<<title>>/>\"?" }, "$:/language/ConfirmOverwriteTiddler": { "title": "$:/language/ConfirmOverwriteTiddler", "text": "Do you wish to overwrite the tiddler \"<$text text=<<title>>/>\"?" }, "$:/language/ConfirmEditShadowTiddler": { "title": "$:/language/ConfirmEditShadowTiddler", "text": "You are about to edit a ShadowTiddler. Any changes will override the default system making future upgrades non-trivial. Are you sure you want to edit \"<$text text=<<title>>/>\"?" }, "$:/language/Count": { "title": "$:/language/Count", "text": "count" }, "$:/language/DefaultNewTiddlerTitle": { "title": "$:/language/DefaultNewTiddlerTitle", "text": "New Tiddler" }, "$:/language/DropMessage": { "title": "$:/language/DropMessage", "text": "Drop here (or use the 'Escape' key to cancel)" }, "$:/language/Encryption/Cancel": { "title": "$:/language/Encryption/Cancel", "text": "Cancel" }, "$:/language/Encryption/ConfirmClearPassword": { "title": "$:/language/Encryption/ConfirmClearPassword", "text": "Do you wish to clear the password? This will remove the encryption applied when saving this wiki" }, "$:/language/Encryption/PromptSetPassword": { "title": "$:/language/Encryption/PromptSetPassword", "text": "Set a new password for this TiddlyWiki" }, "$:/language/Encryption/Username": { "title": "$:/language/Encryption/Username", "text": "Username" }, "$:/language/Encryption/Password": { "title": "$:/language/Encryption/Password", "text": "Password" }, "$:/language/Encryption/RepeatPassword": { "title": "$:/language/Encryption/RepeatPassword", "text": "Repeat password" }, "$:/language/Encryption/PasswordNoMatch": { "title": "$:/language/Encryption/PasswordNoMatch", "text": "Passwords do not match" }, "$:/language/Encryption/SetPassword": { "title": "$:/language/Encryption/SetPassword", "text": "Set password" }, "$:/language/Error/Caption": { "title": "$:/language/Error/Caption", "text": "Error" }, "$:/language/Error/EditConflict": { "title": "$:/language/Error/EditConflict", "text": "File changed on server" }, "$:/language/Error/Filter": { "title": "$:/language/Error/Filter", "text": "Filter error" }, "$:/language/Error/FilterSyntax": { "title": "$:/language/Error/FilterSyntax", "text": "Syntax error in filter expression" }, "$:/language/Error/IsFilterOperator": { "title": "$:/language/Error/IsFilterOperator", "text": "Filter Error: Unknown operand for the 'is' filter operator" }, "$:/language/Error/LoadingPluginLibrary": { "title": "$:/language/Error/LoadingPluginLibrary", "text": "Error loading plugin library" }, "$:/language/Error/RecursiveTransclusion": { "title": "$:/language/Error/RecursiveTransclusion", "text": "Recursive transclusion error in transclude widget" }, "$:/language/Error/RetrievingSkinny": { "title": "$:/language/Error/RetrievingSkinny", "text": "Error retrieving skinny tiddler list" }, "$:/language/Error/SavingToTWEdit": { "title": "$:/language/Error/SavingToTWEdit", "text": "Error saving to TWEdit" }, "$:/language/Error/WhileSaving": { "title": "$:/language/Error/WhileSaving", "text": "Error while saving" }, "$:/language/Error/XMLHttpRequest": { "title": "$:/language/Error/XMLHttpRequest", "text": "XMLHttpRequest error code" }, "$:/language/InternalJavaScriptError/Title": { "title": "$:/language/InternalJavaScriptError/Title", "text": "Internal JavaScript Error" }, "$:/language/InternalJavaScriptError/Hint": { "title": "$:/language/InternalJavaScriptError/Hint", "text": "Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser" }, "$:/language/InvalidFieldName": { "title": "$:/language/InvalidFieldName", "text": "Illegal characters in field name \"<$text text=<<fieldName>>/>\". Fields can only contain lowercase letters, digits and the characters underscore (`_`), hyphen (`-`) and period (`.`)" }, "$:/language/LazyLoadingWarning": { "title": "$:/language/LazyLoadingWarning", "text": "<p>Loading external text from ''<$text text={{!!_canonical_uri}}/>''</p><p>If this message doesn't disappear you may be using a browser that doesn't support external text in this configuration. See http://tiddlywiki.com/#ExternalText</p>" }, "$:/language/LoginToTiddlySpace": { "title": "$:/language/LoginToTiddlySpace", "text": "Login to TiddlySpace" }, "$:/language/Manager/Controls/FilterByTag/None": { "title": "$:/language/Manager/Controls/FilterByTag/None", "text": "(none)" }, "$:/language/Manager/Controls/FilterByTag/Prompt": { "title": "$:/language/Manager/Controls/FilterByTag/Prompt", "text": "Filter by tag:" }, "$:/language/Manager/Controls/Order/Prompt": { "title": "$:/language/Manager/Controls/Order/Prompt", "text": "Reverse order" }, "$:/language/Manager/Controls/Search/Placeholder": { "title": "$:/language/Manager/Controls/Search/Placeholder", "text": "Search" }, "$:/language/Manager/Controls/Search/Prompt": { "title": "$:/language/Manager/Controls/Search/Prompt", "text": "Search:" }, "$:/language/Manager/Controls/Show/Option/Tags": { "title": "$:/language/Manager/Controls/Show/Option/Tags", "text": "tags" }, "$:/language/Manager/Controls/Show/Option/Tiddlers": { "title": "$:/language/Manager/Controls/Show/Option/Tiddlers", "text": "tiddlers" }, "$:/language/Manager/Controls/Show/Prompt": { "title": "$:/language/Manager/Controls/Show/Prompt", "text": "Show:" }, "$:/language/Manager/Controls/Sort/Prompt": { "title": "$:/language/Manager/Controls/Sort/Prompt", "text": "Sort by:" }, "$:/language/Manager/Item/Colour": { "title": "$:/language/Manager/Item/Colour", "text": "Colour" }, "$:/language/Manager/Item/Fields": { "title": "$:/language/Manager/Item/Fields", "text": "Fields" }, "$:/language/Manager/Item/Icon/None": { "title": "$:/language/Manager/Item/Icon/None", "text": "(none)" }, "$:/language/Manager/Item/Icon": { "title": "$:/language/Manager/Item/Icon", "text": "Icon" }, "$:/language/Manager/Item/RawText": { "title": "$:/language/Manager/Item/RawText", "text": "Raw text" }, "$:/language/Manager/Item/Tags": { "title": "$:/language/Manager/Item/Tags", "text": "Tags" }, "$:/language/Manager/Item/Tools": { "title": "$:/language/Manager/Item/Tools", "text": "Tools" }, "$:/language/Manager/Item/WikifiedText": { "title": "$:/language/Manager/Item/WikifiedText", "text": "Wikified text" }, "$:/language/MissingTiddler/Hint": { "title": "$:/language/MissingTiddler/Hint", "text": "Missing tiddler \"<$text text=<<currentTiddler>>/>\" - click {{$:/core/images/edit-button}} to create" }, "$:/language/No": { "title": "$:/language/No", "text": "No" }, "$:/language/OfficialPluginLibrary": { "title": "$:/language/OfficialPluginLibrary", "text": "Official ~TiddlyWiki Plugin Library" }, "$:/language/OfficialPluginLibrary/Hint": { "title": "$:/language/OfficialPluginLibrary/Hint", "text": "The official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team." }, "$:/language/PluginReloadWarning": { "title": "$:/language/PluginReloadWarning", "text": "Please save {{$:/core/ui/Buttons/save-wiki}} and reload {{$:/core/ui/Buttons/refresh}} to allow changes to plugins to take effect" }, "$:/language/RecentChanges/DateFormat": { "title": "$:/language/RecentChanges/DateFormat", "text": "DDth MMM YYYY" }, "$:/language/SystemTiddler/Tooltip": { "title": "$:/language/SystemTiddler/Tooltip", "text": "This is a system tiddler" }, "$:/language/SystemTiddlers/Include/Prompt": { "title": "$:/language/SystemTiddlers/Include/Prompt", "text": "Include system tiddlers" }, "$:/language/TagManager/Colour/Heading": { "title": "$:/language/TagManager/Colour/Heading", "text": "Colour" }, "$:/language/TagManager/Count/Heading": { "title": "$:/language/TagManager/Count/Heading", "text": "Count" }, "$:/language/TagManager/Icon/Heading": { "title": "$:/language/TagManager/Icon/Heading", "text": "Icon" }, "$:/language/TagManager/Info/Heading": { "title": "$:/language/TagManager/Info/Heading", "text": "Info" }, "$:/language/TagManager/Tag/Heading": { "title": "$:/language/TagManager/Tag/Heading", "text": "Tag" }, "$:/language/Tiddler/DateFormat": { "title": "$:/language/Tiddler/DateFormat", "text": "DDth MMM YYYY at hh12:0mmam" }, "$:/language/UnsavedChangesWarning": { "title": "$:/language/UnsavedChangesWarning", "text": "You have unsaved changes in TiddlyWiki" }, "$:/language/Yes": { "title": "$:/language/Yes", "text": "Yes" }, "$:/language/Modals/Download": { "title": "$:/language/Modals/Download", "type": "text/vnd.tiddlywiki", "subtitle": "Download changes", "footer": "<$button message=\"tm-close-tiddler\">Close</$button>", "help": "http://tiddlywiki.com/static/DownloadingChanges.html", "text": "Your browser only supports manual saving.\n\nTo save your modified wiki, right click on the download link below and select \"Download file\" or \"Save file\", and then choose the folder and filename.\n\n//You can marginally speed things up by clicking the link with the control key (Windows) or the options/alt key (Mac OS X). You will not be prompted for the folder or filename, but your browser is likely to give it an unrecognisable name -- you may need to rename the file to include an `.html` extension before you can do anything useful with it.//\n\nOn smartphones that do not allow files to be downloaded you can instead bookmark the link, and then sync your bookmarks to a desktop computer from where the wiki can be saved normally.\n" }, "$:/language/Modals/SaveInstructions": { "title": "$:/language/Modals/SaveInstructions", "type": "text/vnd.tiddlywiki", "subtitle": "Save your work", "footer": "<$button message=\"tm-close-tiddler\">Close</$button>", "help": "http://tiddlywiki.com/static/SavingChanges.html", "text": "Your changes to this wiki need to be saved as a ~TiddlyWiki HTML file.\n\n!!! Desktop browsers\n\n# Select ''Save As'' from the ''File'' menu\n# Choose a filename and location\n#* Some browsers also require you to explicitly specify the file saving format as ''Webpage, HTML only'' or similar\n# Close this tab\n\n!!! Smartphone browsers\n\n# Create a bookmark to this page\n#* If you've got iCloud or Google Sync set up then the bookmark will automatically sync to your desktop where you can open it and save it as above\n# Close this tab\n\n//If you open the bookmark again in Mobile Safari you will see this message again. If you want to go ahead and use the file, just click the ''close'' button below//\n" }, "$:/config/NewJournal/Title": { "title": "$:/config/NewJournal/Title", "text": "DDth MMM YYYY" }, "$:/config/NewJournal/Text": { "title": "$:/config/NewJournal/Text", "text": "" }, "$:/config/NewJournal/Tags": { "title": "$:/config/NewJournal/Tags", "text": "Journal" }, "$:/language/Notifications/Save/Done": { "title": "$:/language/Notifications/Save/Done", "text": "Saved wiki" }, "$:/language/Notifications/Save/Starting": { "title": "$:/language/Notifications/Save/Starting", "text": "Starting to save wiki" }, "$:/language/Search/DefaultResults/Caption": { "title": "$:/language/Search/DefaultResults/Caption", "text": "List" }, "$:/language/Search/Filter/Caption": { "title": "$:/language/Search/Filter/Caption", "text": "Filter" }, "$:/language/Search/Filter/Hint": { "title": "$:/language/Search/Filter/Hint", "text": "Search via a [[filter expression|http://tiddlywiki.com/static/Filters.html]]" }, "$:/language/Search/Filter/Matches": { "title": "$:/language/Search/Filter/Matches", "text": "//<small><<resultCount>> matches</small>//" }, "$:/language/Search/Matches": { "title": "$:/language/Search/Matches", "text": "//<small><<resultCount>> matches</small>//" }, "$:/language/Search/Matches/All": { "title": "$:/language/Search/Matches/All", "text": "All matches:" }, "$:/language/Search/Matches/Title": { "title": "$:/language/Search/Matches/Title", "text": "Title matches:" }, "$:/language/Search/Search": { "title": "$:/language/Search/Search", "text": "Search" }, "$:/language/Search/Search/TooShort": { "title": "$:/language/Search/Search/TooShort", "text": "Search text too short" }, "$:/language/Search/Shadows/Caption": { "title": "$:/language/Search/Shadows/Caption", "text": "Shadows" }, "$:/language/Search/Shadows/Hint": { "title": "$:/language/Search/Shadows/Hint", "text": "Search for shadow tiddlers" }, "$:/language/Search/Shadows/Matches": { "title": "$:/language/Search/Shadows/Matches", "text": "//<small><<resultCount>> matches</small>//" }, "$:/language/Search/Standard/Caption": { "title": "$:/language/Search/Standard/Caption", "text": "Standard" }, "$:/language/Search/Standard/Hint": { "title": "$:/language/Search/Standard/Hint", "text": "Search for standard tiddlers" }, "$:/language/Search/Standard/Matches": { "title": "$:/language/Search/Standard/Matches", "text": "//<small><<resultCount>> matches</small>//" }, "$:/language/Search/System/Caption": { "title": "$:/language/Search/System/Caption", "text": "System" }, "$:/language/Search/System/Hint": { "title": "$:/language/Search/System/Hint", "text": "Search for system tiddlers" }, "$:/language/Search/System/Matches": { "title": "$:/language/Search/System/Matches", "text": "//<small><<resultCount>> matches</small>//" }, "$:/language/SideBar/All/Caption": { "title": "$:/language/SideBar/All/Caption", "text": "All" }, "$:/language/SideBar/Contents/Caption": { "title": "$:/language/SideBar/Contents/Caption", "text": "Contents" }, "$:/language/SideBar/Drafts/Caption": { "title": "$:/language/SideBar/Drafts/Caption", "text": "Drafts" }, "$:/language/SideBar/Missing/Caption": { "title": "$:/language/SideBar/Missing/Caption", "text": "Missing" }, "$:/language/SideBar/More/Caption": { "title": "$:/language/SideBar/More/Caption", "text": "More" }, "$:/language/SideBar/Open/Caption": { "title": "$:/language/SideBar/Open/Caption", "text": "Open" }, "$:/language/SideBar/Orphans/Caption": { "title": "$:/language/SideBar/Orphans/Caption", "text": "Orphans" }, "$:/language/SideBar/Recent/Caption": { "title": "$:/language/SideBar/Recent/Caption", "text": "Recent" }, "$:/language/SideBar/Shadows/Caption": { "title": "$:/language/SideBar/Shadows/Caption", "text": "Shadows" }, "$:/language/SideBar/System/Caption": { "title": "$:/language/SideBar/System/Caption", "text": "System" }, "$:/language/SideBar/Tags/Caption": { "title": "$:/language/SideBar/Tags/Caption", "text": "Tags" }, "$:/language/SideBar/Tags/Untagged/Caption": { "title": "$:/language/SideBar/Tags/Untagged/Caption", "text": "untagged" }, "$:/language/SideBar/Tools/Caption": { "title": "$:/language/SideBar/Tools/Caption", "text": "Tools" }, "$:/language/SideBar/Types/Caption": { "title": "$:/language/SideBar/Types/Caption", "text": "Types" }, "$:/SiteSubtitle": { "title": "$:/SiteSubtitle", "text": "a non-linear personal web notebook" }, "$:/SiteTitle": { "title": "$:/SiteTitle", "text": "My ~TiddlyWiki" }, "$:/language/Snippets/ListByTag": { "title": "$:/language/Snippets/ListByTag", "tags": "$:/tags/TextEditor/Snippet", "caption": "List of tiddlers by tag", "text": "<<list-links \"[tag[task]sort[title]]\">>\n" }, "$:/language/Snippets/MacroDefinition": { "title": "$:/language/Snippets/MacroDefinition", "tags": "$:/tags/TextEditor/Snippet", "caption": "Macro definition", "text": "\\define macroName(param1:\"default value\",param2)\nText of the macro\n\\end\n" }, "$:/language/Snippets/Table4x3": { "title": "$:/language/Snippets/Table4x3", "tags": "$:/tags/TextEditor/Snippet", "caption": "Table with 4 columns by 3 rows", "text": "|! |!Alpha |!Beta |!Gamma |!Delta |\n|!One | | | | |\n|!Two | | | | |\n|!Three | | | | |\n" }, "$:/language/Snippets/TableOfContents": { "title": "$:/language/Snippets/TableOfContents", "tags": "$:/tags/TextEditor/Snippet", "caption": "Table of Contents", "text": "<div class=\"tc-table-of-contents\">\n\n<<toc-selective-expandable 'TableOfContents'>>\n\n</div>" }, "$:/language/ThemeTweaks/ThemeTweaks": { "title": "$:/language/ThemeTweaks/ThemeTweaks", "text": "Theme Tweaks" }, "$:/language/ThemeTweaks/ThemeTweaks/Hint": { "title": "$:/language/ThemeTweaks/ThemeTweaks/Hint", "text": "You can tweak certain aspects of the ''Vanilla'' theme." }, "$:/language/ThemeTweaks/Options": { "title": "$:/language/ThemeTweaks/Options", "text": "Options" }, "$:/language/ThemeTweaks/Options/SidebarLayout": { "title": "$:/language/ThemeTweaks/Options/SidebarLayout", "text": "Sidebar layout" }, "$:/language/ThemeTweaks/Options/SidebarLayout/Fixed-Fluid": { "title": "$:/language/ThemeTweaks/Options/SidebarLayout/Fixed-Fluid", "text": "Fixed story, fluid sidebar" }, "$:/language/ThemeTweaks/Options/SidebarLayout/Fluid-Fixed": { "title": "$:/language/ThemeTweaks/Options/SidebarLayout/Fluid-Fixed", "text": "Fluid story, fixed sidebar" }, "$:/language/ThemeTweaks/Options/StickyTitles": { "title": "$:/language/ThemeTweaks/Options/StickyTitles", "text": "Sticky titles" }, "$:/language/ThemeTweaks/Options/StickyTitles/Hint": { "title": "$:/language/ThemeTweaks/Options/StickyTitles/Hint", "text": "Causes tiddler titles to \"stick\" to the top of the browser window. Caution: Does not work at all with Chrome, and causes some layout issues in Firefox" }, "$:/language/ThemeTweaks/Options/CodeWrapping": { "title": "$:/language/ThemeTweaks/Options/CodeWrapping", "text": "Wrap long lines in code blocks" }, "$:/language/ThemeTweaks/Settings": { "title": "$:/language/ThemeTweaks/Settings", "text": "Settings" }, "$:/language/ThemeTweaks/Settings/FontFamily": { "title": "$:/language/ThemeTweaks/Settings/FontFamily", "text": "Font family" }, "$:/language/ThemeTweaks/Settings/CodeFontFamily": { "title": "$:/language/ThemeTweaks/Settings/CodeFontFamily", "text": "Code font family" }, "$:/language/ThemeTweaks/Settings/BackgroundImage": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImage", "text": "Page background image" }, "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment", "text": "Page background image attachment" }, "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Scroll": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Scroll", "text": "Scroll with tiddlers" }, "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Fixed": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Fixed", "text": "Fixed to window" }, "$:/language/ThemeTweaks/Settings/BackgroundImageSize": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize", "text": "Page background image size" }, "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Auto": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Auto", "text": "Auto" }, "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Cover": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Cover", "text": "Cover" }, "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Contain": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Contain", "text": "Contain" }, "$:/language/ThemeTweaks/Metrics": { "title": "$:/language/ThemeTweaks/Metrics", "text": "Sizes" }, "$:/language/ThemeTweaks/Metrics/FontSize": { "title": "$:/language/ThemeTweaks/Metrics/FontSize", "text": "Font size" }, "$:/language/ThemeTweaks/Metrics/LineHeight": { "title": "$:/language/ThemeTweaks/Metrics/LineHeight", "text": "Line height" }, "$:/language/ThemeTweaks/Metrics/BodyFontSize": { "title": "$:/language/ThemeTweaks/Metrics/BodyFontSize", "text": "Font size for tiddler body" }, "$:/language/ThemeTweaks/Metrics/BodyLineHeight": { "title": "$:/language/ThemeTweaks/Metrics/BodyLineHeight", "text": "Line height for tiddler body" }, "$:/language/ThemeTweaks/Metrics/StoryLeft": { "title": "$:/language/ThemeTweaks/Metrics/StoryLeft", "text": "Story left position" }, "$:/language/ThemeTweaks/Metrics/StoryLeft/Hint": { "title": "$:/language/ThemeTweaks/Metrics/StoryLeft/Hint", "text": "how far the left margin of the story river<br>(tiddler area) is from the left of the page" }, "$:/language/ThemeTweaks/Metrics/StoryTop": { "title": "$:/language/ThemeTweaks/Metrics/StoryTop", "text": "Story top position" }, "$:/language/ThemeTweaks/Metrics/StoryTop/Hint": { "title": "$:/language/ThemeTweaks/Metrics/StoryTop/Hint", "text": "how far the top margin of the story river<br>is from the top of the page" }, "$:/language/ThemeTweaks/Metrics/StoryRight": { "title": "$:/language/ThemeTweaks/Metrics/StoryRight", "text": "Story right" }, "$:/language/ThemeTweaks/Metrics/StoryRight/Hint": { "title": "$:/language/ThemeTweaks/Metrics/StoryRight/Hint", "text": "how far the left margin of the sidebar <br>is from the left of the page" }, "$:/language/ThemeTweaks/Metrics/StoryWidth": { "title": "$:/language/ThemeTweaks/Metrics/StoryWidth", "text": "Story width" }, "$:/language/ThemeTweaks/Metrics/StoryWidth/Hint": { "title": "$:/language/ThemeTweaks/Metrics/StoryWidth/Hint", "text": "the overall width of the story river" }, "$:/language/ThemeTweaks/Metrics/TiddlerWidth": { "title": "$:/language/ThemeTweaks/Metrics/TiddlerWidth", "text": "Tiddler width" }, "$:/language/ThemeTweaks/Metrics/TiddlerWidth/Hint": { "title": "$:/language/ThemeTweaks/Metrics/TiddlerWidth/Hint", "text": "within the story river" }, "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint": { "title": "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint", "text": "Sidebar breakpoint" }, "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint/Hint": { "title": "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint/Hint", "text": "the minimum page width at which the story<br>river and sidebar will appear side by side" }, "$:/language/ThemeTweaks/Metrics/SidebarWidth": { "title": "$:/language/ThemeTweaks/Metrics/SidebarWidth", "text": "Sidebar width" }, "$:/language/ThemeTweaks/Metrics/SidebarWidth/Hint": { "title": "$:/language/ThemeTweaks/Metrics/SidebarWidth/Hint", "text": "the width of the sidebar in fluid-fixed layout" }, "$:/language/TiddlerInfo/Advanced/Caption": { "title": "$:/language/TiddlerInfo/Advanced/Caption", "text": "Advanced" }, "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint": { "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint", "text": "none" }, "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading": { "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading", "text": "Plugin Details" }, "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint": { "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint", "text": "This plugin contains the following shadow tiddlers:" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading", "text": "Shadow Status" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint", "text": "The tiddler <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> is not a shadow tiddler" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint", "text": "The tiddler <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> is a shadow tiddler" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source", "text": "It is defined in the plugin <$link to=<<pluginTiddler>>><$text text=<<pluginTiddler>>/></$link>" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint", "text": "It is overridden by an ordinary tiddler" }, "$:/language/TiddlerInfo/Fields/Caption": { "title": "$:/language/TiddlerInfo/Fields/Caption", "text": "Fields" }, "$:/language/TiddlerInfo/List/Caption": { "title": "$:/language/TiddlerInfo/List/Caption", "text": "List" }, "$:/language/TiddlerInfo/List/Empty": { "title": "$:/language/TiddlerInfo/List/Empty", "text": "This tiddler does not have a list" }, "$:/language/TiddlerInfo/Listed/Caption": { "title": "$:/language/TiddlerInfo/Listed/Caption", "text": "Listed" }, "$:/language/TiddlerInfo/Listed/Empty": { "title": "$:/language/TiddlerInfo/Listed/Empty", "text": "This tiddler is not listed by any others" }, "$:/language/TiddlerInfo/References/Caption": { "title": "$:/language/TiddlerInfo/References/Caption", "text": "References" }, "$:/language/TiddlerInfo/References/Empty": { "title": "$:/language/TiddlerInfo/References/Empty", "text": "No tiddlers link to this one" }, "$:/language/TiddlerInfo/Tagging/Caption": { "title": "$:/language/TiddlerInfo/Tagging/Caption", "text": "Tagging" }, "$:/language/TiddlerInfo/Tagging/Empty": { "title": "$:/language/TiddlerInfo/Tagging/Empty", "text": "No tiddlers are tagged with this one" }, "$:/language/TiddlerInfo/Tools/Caption": { "title": "$:/language/TiddlerInfo/Tools/Caption", "text": "Tools" }, "$:/language/Docs/Types/application/javascript": { "title": "$:/language/Docs/Types/application/javascript", "description": "JavaScript code", "name": "application/javascript", "group": "Developer", "group-sort": "2" }, "$:/language/Docs/Types/application/json": { "title": "$:/language/Docs/Types/application/json", "description": "JSON data", "name": "application/json", "group": "Developer", "group-sort": "2" }, "$:/language/Docs/Types/application/x-tiddler-dictionary": { "title": "$:/language/Docs/Types/application/x-tiddler-dictionary", "description": "Data dictionary", "name": "application/x-tiddler-dictionary", "group": "Developer", "group-sort": "2" }, "$:/language/Docs/Types/image/gif": { "title": "$:/language/Docs/Types/image/gif", "description": "GIF image", "name": "image/gif", "group": "Image", "group-sort": "1" }, "$:/language/Docs/Types/image/jpeg": { "title": "$:/language/Docs/Types/image/jpeg", "description": "JPEG image", "name": "image/jpeg", "group": "Image", "group-sort": "1" }, "$:/language/Docs/Types/image/png": { "title": "$:/language/Docs/Types/image/png", "description": "PNG image", "name": "image/png", "group": "Image", "group-sort": "1" }, "$:/language/Docs/Types/image/svg+xml": { "title": "$:/language/Docs/Types/image/svg+xml", "description": "Structured Vector Graphics image", "name": "image/svg+xml", "group": "Image", "group-sort": "1" }, "$:/language/Docs/Types/image/x-icon": { "title": "$:/language/Docs/Types/image/x-icon", "description": "ICO format icon file", "name": "image/x-icon", "group": "Image", "group-sort": "1" }, "$:/language/Docs/Types/text/css": { "title": "$:/language/Docs/Types/text/css", "description": "Static stylesheet", "name": "text/css", "group": "Developer", "group-sort": "2" }, "$:/language/Docs/Types/text/html": { "title": "$:/language/Docs/Types/text/html", "description": "HTML markup", "name": "text/html", "group": "Text", "group-sort": "0" }, "$:/language/Docs/Types/text/plain": { "title": "$:/language/Docs/Types/text/plain", "description": "Plain text", "name": "text/plain", "group": "Text", "group-sort": "0" }, "$:/language/Docs/Types/text/vnd.tiddlywiki": { "title": "$:/language/Docs/Types/text/vnd.tiddlywiki", "description": "TiddlyWiki 5", "name": "text/vnd.tiddlywiki", "group": "Text", "group-sort": "0" }, "$:/language/Docs/Types/text/x-tiddlywiki": { "title": "$:/language/Docs/Types/text/x-tiddlywiki", "description": "TiddlyWiki Classic", "name": "text/x-tiddlywiki", "group": "Text", "group-sort": "0" }, "$:/languages/en-GB/icon": { "title": "$:/languages/en-GB/icon", "type": "image/svg+xml", "text": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 60 30\" width=\"1200\" height=\"600\">\n<clipPath id=\"t\">\n\t<path d=\"M30,15 h30 v15 z v15 h-30 z h-30 v-15 z v-15 h30 z\"/>\n</clipPath>\n<path d=\"M0,0 v30 h60 v-30 z\" fill=\"#00247d\"/>\n<path d=\"M0,0 L60,30 M60,0 L0,30\" stroke=\"#fff\" stroke-width=\"6\"/>\n<path d=\"M0,0 L60,30 M60,0 L0,30\" clip-path=\"url(#t)\" stroke=\"#cf142b\" stroke-width=\"4\"/>\n<path d=\"M30,0 v30 M0,15 h60\" stroke=\"#fff\" stroke-width=\"10\"/>\n<path d=\"M30,0 v30 M0,15 h60\" stroke=\"#cf142b\" stroke-width=\"6\"/>\n</svg>\n" }, "$:/languages/en-GB": { "title": "$:/languages/en-GB", "name": "en-GB", "description": "English (British)", "author": "JeremyRuston", "core-version": ">=5.0.0\"", "text": "Stub pseudo-plugin for the default language" }, "$:/core/modules/commander.js": { "text": "/*\\\ntitle: $:/core/modules/commander.js\ntype: application/javascript\nmodule-type: global\n\nThe $tw.Commander class is a command interpreter\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nParse a sequence of commands\n\tcommandTokens: an array of command string tokens\n\twiki: reference to the wiki store object\n\tstreams: {output:, error:}, each of which has a write(string) method\n\tcallback: a callback invoked as callback(err) where err is null if there was no error\n*/\nvar Commander = function(commandTokens,callback,wiki,streams) {\n\tvar path = require(\"path\");\n\tthis.commandTokens = commandTokens;\n\tthis.nextToken = 0;\n\tthis.callback = callback;\n\tthis.wiki = wiki;\n\tthis.streams = streams;\n\tthis.outputPath = path.resolve($tw.boot.wikiPath,$tw.config.wikiOutputSubDir);\n};\n\n/*\nLog a string if verbose flag is set\n*/\nCommander.prototype.log = function(str) {\n\tif(this.verbose) {\n\t\tthis.streams.output.write(str + \"\\n\");\n\t}\n};\n\n/*\nWrite a string if verbose flag is set\n*/\nCommander.prototype.write = function(str) {\n\tif(this.verbose) {\n\t\tthis.streams.output.write(str);\n\t}\n};\n\n/*\nAdd a string of tokens to the command queue\n*/\nCommander.prototype.addCommandTokens = function(commandTokens) {\n\tvar params = commandTokens.slice(0);\n\tparams.unshift(0);\n\tparams.unshift(this.nextToken);\n\tArray.prototype.splice.apply(this.commandTokens,params);\n};\n\n/*\nExecute the sequence of commands and invoke a callback on completion\n*/\nCommander.prototype.execute = function() {\n\tthis.executeNextCommand();\n};\n\n/*\nExecute the next command in the sequence\n*/\nCommander.prototype.executeNextCommand = function() {\n\tvar self = this;\n\t// Invoke the callback if there are no more commands\n\tif(this.nextToken >= this.commandTokens.length) {\n\t\tthis.callback(null);\n\t} else {\n\t\t// Get and check the command token\n\t\tvar commandName = this.commandTokens[this.nextToken++];\n\t\tif(commandName.substr(0,2) !== \"--\") {\n\t\t\tthis.callback(\"Missing command: \" + commandName);\n\t\t} else {\n\t\t\tcommandName = commandName.substr(2); // Trim off the --\n\t\t\t// Accumulate the parameters to the command\n\t\t\tvar params = [];\n\t\t\twhile(this.nextToken < this.commandTokens.length && \n\t\t\t\tthis.commandTokens[this.nextToken].substr(0,2) !== \"--\") {\n\t\t\t\tparams.push(this.commandTokens[this.nextToken++]);\n\t\t\t}\n\t\t\t// Get the command info\n\t\t\tvar command = $tw.commands[commandName],\n\t\t\t\tc,err;\n\t\t\tif(!command) {\n\t\t\t\tthis.callback(\"Unknown command: \" + commandName);\n\t\t\t} else {\n\t\t\t\tif(this.verbose) {\n\t\t\t\t\tthis.streams.output.write(\"Executing command: \" + commandName + \" \" + params.join(\" \") + \"\\n\");\n\t\t\t\t}\n\t\t\t\tif(command.info.synchronous) {\n\t\t\t\t\t// Synchronous command\n\t\t\t\t\tc = new command.Command(params,this);\n\t\t\t\t\terr = c.execute();\n\t\t\t\t\tif(err) {\n\t\t\t\t\t\tthis.callback(err);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.executeNextCommand();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Asynchronous command\n\t\t\t\t\tc = new command.Command(params,this,function(err) {\n\t\t\t\t\t\tif(err) {\n\t\t\t\t\t\t\tself.callback(err);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.executeNextCommand();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\terr = c.execute();\n\t\t\t\t\tif(err) {\n\t\t\t\t\t\tthis.callback(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\nCommander.initCommands = function(moduleType) {\n\tmoduleType = moduleType || \"command\";\n\t$tw.commands = {};\n\t$tw.modules.forEachModuleOfType(moduleType,function(title,module) {\n\t\tvar c = $tw.commands[module.info.name] = {};\n\t\t// Add the methods defined by the module\n\t\tfor(var f in module) {\n\t\t\tif($tw.utils.hop(module,f)) {\n\t\t\t\tc[f] = module[f];\n\t\t\t}\n\t\t}\n\t});\n};\n\nexports.Commander = Commander;\n\n})();\n", "title": "$:/core/modules/commander.js", "type": "application/javascript", "module-type": "global" }, "$:/core/modules/commands/build.js": { "text": "/*\\\ntitle: $:/core/modules/commands/build.js\ntype: application/javascript\nmodule-type: command\n\nCommand to build a build target\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"build\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\t// Get the build targets defined in the wiki\n\tvar buildTargets = $tw.boot.wikiInfo.build;\n\tif(!buildTargets) {\n\t\treturn \"No build targets defined\";\n\t}\n\t// Loop through each of the specified targets\n\tvar targets;\n\tif(this.params.length > 0) {\n\t\ttargets = this.params;\n\t} else {\n\t\ttargets = Object.keys(buildTargets);\n\t}\n\tfor(var targetIndex=0; targetIndex<targets.length; targetIndex++) {\n\t\tvar target = targets[targetIndex],\n\t\t\tcommands = buildTargets[target];\n\t\tif(!commands) {\n\t\t\treturn \"Build target '\" + target + \"' not found\";\n\t\t}\n\t\t// Add the commands to the queue\n\t\tthis.commander.addCommandTokens(commands);\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/build.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/clearpassword.js": { "text": "/*\\\ntitle: $:/core/modules/commands/clearpassword.js\ntype: application/javascript\nmodule-type: command\n\nClear password for crypto operations\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"clearpassword\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\t$tw.crypto.setPassword(null);\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/clearpassword.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/editions.js": { "text": "/*\\\ntitle: $:/core/modules/commands/editions.js\ntype: application/javascript\nmodule-type: command\n\nCommand to list the available editions\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"editions\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tvar self = this;\n\t// Output the list\n\tthis.commander.streams.output.write(\"Available editions:\\n\\n\");\n\tvar editionInfo = $tw.utils.getEditionInfo();\n\t$tw.utils.each(editionInfo,function(info,name) {\n\t\tself.commander.streams.output.write(\" \" + name + \": \" + info.description + \"\\n\");\n\t});\n\tthis.commander.streams.output.write(\"\\n\");\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/editions.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/fetch.js": { "text": "/*\\\ntitle: $:/core/modules/commands/fetch.js\ntype: application/javascript\nmodule-type: command\n\nCommands to fetch external tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"fetch\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing subcommand and url\";\n\t}\n\tvar subcommand = this.params[0],\n\t\turl = this.params[1],\n\t\timportFilter = this.params[2] || \"[all[tiddlers]]\",\n\t\ttransformFilter = this.params[3] || \"\";\n\tswitch(subcommand) {\n\t\tcase \"file\":\n\t\t\treturn this.fetchFiles({\n\t\t\t\turl: url,\n\t\t\t\timportFilter: importFilter,\n\t\t\t\ttransformFilter: transformFilter,\n\t\t\t\tcallback: this.callback\n\t\t\t});\n\t\t\tbreak;\n\t\tcase \"files\":\n\t\t\treturn this.fetchFiles({\n\t\t\t\turlFilter: url,\n\t\t\t\timportFilter: importFilter,\n\t\t\t\ttransformFilter: transformFilter,\n\t\t\t\tcallback: this.callback\n\t\t\t});\n\t\t\tbreak;\n\t}\n\treturn null;\n};\n\nCommand.prototype.fetchFiles = function(options) {\n\tvar self = this;\n\t// Get the list of URLs\n\tvar urls;\n\tif(options.url) {\n\t\turls = [options.url]\n\t} else if(options.urlFilter) {\n\t\turls = $tw.wiki.filterTiddlers(options.urlFilter);\n\t} else {\n\t\treturn \"Missing URL\";\n\t}\n\t// Process each URL in turn\n\tvar next = 0;\n\tvar getNextFile = function(err) {\n\t\tif(err) {\n\t\t\treturn options.callback(err);\n\t\t}\n\t\tif(next < urls.length) {\n\t\t\tself.fetchFile(urls[next++],options,getNextFile);\n\t\t} else {\n\t\t\toptions.callback(null);\n\t\t}\n\t};\n\tgetNextFile(null);\n\t// Success\n\treturn null;\n};\n\nCommand.prototype.fetchFile = function(url,options,callback) {\n\tvar self = this,\n\t\tlib = url.substr(0,8) === \"https://\" ? require(\"https\") : require(\"http\");\n\tlib.get(url).on(\"response\",function(response) {\n\t var type = (response.headers[\"content-type\"] || \"\").split(\";\")[0],\n\t \tbody = \"\";\n\t self.commander.write(\"Reading \" + url + \": \");\n\t response.on(\"data\",function(chunk) {\n\t body += chunk;\n\t self.commander.write(\".\");\n\t });\n\t response.on(\"end\",function() {\n\t self.commander.write(\"\\n\");\n\t if(response.statusCode === 200) {\n\t\t self.processBody(body,type,options);\n\t\t callback(null);\n\t } else {\n\t \tcallback(\"Error \" + response.statusCode + \" retrieving \" + url)\n\t }\n\t \t});\n\t \tresponse.on(\"error\",function(e) {\n\t\t\tconsole.log(\"Error on GET request: \" + e);\n\t\t\tcallback(e);\n\t \t});\n\t});\n\treturn null;\n};\n\nCommand.prototype.processBody = function(body,type,options) {\n\t// Deserialise the HTML file and put the tiddlers in their own wiki\n\tvar self = this,\n\t\tincomingWiki = new $tw.Wiki(),\n\t\ttiddlers = this.commander.wiki.deserializeTiddlers(type || \"text/html\",body,{});\n\t$tw.utils.each(tiddlers,function(tiddler) {\n\t\tincomingWiki.addTiddler(new $tw.Tiddler(tiddler));\n\t});\n\t// Filter the tiddlers to select the ones we want\n\tvar filteredTitles = incomingWiki.filterTiddlers(options.importFilter);\n\t// Import the selected tiddlers\n\tvar count = 0;\n\tincomingWiki.each(function(tiddler,title) {\n\t\tif(filteredTitles.indexOf(title) !== -1) {\n\t\t\tvar newTiddler;\n\t\t\tif(options.transformFilter) {\n\t\t\t\tvar transformedTitle = (incomingWiki.filterTiddlers(options.transformFilter,null,self.commander.wiki.makeTiddlerIterator([title])) || [\"\"])[0];\n\t\t\t\tif(transformedTitle) {\n\t\t\t\t\tself.commander.log(\"Importing \" + title + \" as \" + transformedTitle)\n\t\t\t\t\tnewTiddler = new $tw.Tiddler(tiddler,{title: transformedTitle});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tself.commander.log(\"Importing \" + title)\n\t\t\t\tnewTiddler = tiddler;\n\t\t\t}\n\t\t\tself.commander.wiki.importTiddler(newTiddler);\n\t\t\tcount++;\n\t\t}\n\t});\n\tself.commander.log(\"Imported \" + count + \" tiddlers\")\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/fetch.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/help.js": { "text": "/*\\\ntitle: $:/core/modules/commands/help.js\ntype: application/javascript\nmodule-type: command\n\nHelp command\n\n\\*/\n(function(){\n\n/*jshint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"help\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tvar subhelp = this.params[0] || \"default\",\n\t\thelpBase = \"$:/language/Help/\",\n\t\ttext;\n\tif(!this.commander.wiki.getTiddler(helpBase + subhelp)) {\n\t\tsubhelp = \"notfound\";\n\t}\n\t// Wikify the help as formatted text (ie block elements generate newlines)\n\ttext = this.commander.wiki.renderTiddler(\"text/plain-formatted\",helpBase + subhelp);\n\t// Remove any leading linebreaks\n\ttext = text.replace(/^(\\r?\\n)*/g,\"\");\n\tthis.commander.streams.output.write(text);\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/help.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/init.js": { "text": "/*\\\ntitle: $:/core/modules/commands/init.js\ntype: application/javascript\nmodule-type: command\n\nCommand to initialise an empty wiki folder\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"init\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tvar fs = require(\"fs\"),\n\t\tpath = require(\"path\");\n\t// Check that we don't already have a valid wiki folder\n\tif($tw.boot.wikiTiddlersPath || ($tw.utils.isDirectory($tw.boot.wikiPath) && !$tw.utils.isDirectoryEmpty($tw.boot.wikiPath))) {\n\t\treturn \"Wiki folder is not empty\";\n\t}\n\t// Loop through each of the specified editions\n\tvar editions = this.params.length > 0 ? this.params : [\"empty\"];\n\tfor(var editionIndex=0; editionIndex<editions.length; editionIndex++) {\n\t\tvar editionName = editions[editionIndex];\n\t\t// Check the edition exists\n\t\tvar editionPath = $tw.findLibraryItem(editionName,$tw.getLibraryItemSearchPaths($tw.config.editionsPath,$tw.config.editionsEnvVar));\n\t\tif(!$tw.utils.isDirectory(editionPath)) {\n\t\t\treturn \"Edition '\" + editionName + \"' not found\";\n\t\t}\n\t\t// Copy the edition content\n\t\tvar err = $tw.utils.copyDirectory(editionPath,$tw.boot.wikiPath);\n\t\tif(!err) {\n\t\t\tthis.commander.streams.output.write(\"Copied edition '\" + editionName + \"' to \" + $tw.boot.wikiPath + \"\\n\");\n\t\t} else {\n\t\t\treturn err;\n\t\t}\n\t}\n\t// Tweak the tiddlywiki.info to remove any included wikis\n\tvar packagePath = $tw.boot.wikiPath + \"/tiddlywiki.info\",\n\t\tpackageJson = JSON.parse(fs.readFileSync(packagePath));\n\tdelete packageJson.includeWikis;\n\tfs.writeFileSync(packagePath,JSON.stringify(packageJson,null,$tw.config.preferences.jsonSpaces));\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/init.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/load.js": { "text": "/*\\\ntitle: $:/core/modules/commands/load.js\ntype: application/javascript\nmodule-type: command\n\nCommand to load tiddlers from a file\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"load\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\");\n\tif(this.params.length < 1) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar ext = path.extname(self.params[0]),\n\t\tstat = fs.statSync(self.params[0]),\n\t\ttiddlers = $tw.loadTiddlersFromPath(self.params[0]),\n\t\tcount = 0;\n\t$tw.utils.each(tiddlers,function(tiddlerInfo) {\n\t\t$tw.utils.each(tiddlerInfo.tiddlers,function(tiddler) {\n\t\t\tself.commander.wiki.importTiddler(new $tw.Tiddler(tiddler));\n\t\t\tcount++;\n\t\t});\n\t});\n\tif(!count) {\n\t\tself.callback(\"No tiddlers found in file \\\"\" + self.params[0] + \"\\\"\");\n\t} else {\n\t\tself.callback(null);\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/load.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/makelibrary.js": { "text": "/*\\\ntitle: $:/core/modules/commands/makelibrary.js\ntype: application/javascript\nmodule-type: command\n\nCommand to pack all of the plugins in the library into a plugin tiddler of type \"library\"\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"makelibrary\",\n\tsynchronous: true\n};\n\nvar UPGRADE_LIBRARY_TITLE = \"$:/UpgradeLibrary\";\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar wiki = this.commander.wiki,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\tupgradeLibraryTitle = this.params[0] || UPGRADE_LIBRARY_TITLE,\n\t\ttiddlers = {};\n\t// Collect up the library plugins\n\tvar collectPlugins = function(folder) {\n\t\t\tvar pluginFolders = fs.readdirSync(folder);\n\t\t\tfor(var p=0; p<pluginFolders.length; p++) {\n\t\t\t\tif(!$tw.boot.excludeRegExp.test(pluginFolders[p])) {\n\t\t\t\t\tpluginFields = $tw.loadPluginFolder(path.resolve(folder,\"./\" + pluginFolders[p]));\n\t\t\t\t\tif(pluginFields && pluginFields.title) {\n\t\t\t\t\t\ttiddlers[pluginFields.title] = pluginFields;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcollectPublisherPlugins = function(folder) {\n\t\t\tvar publisherFolders = fs.readdirSync(folder);\n\t\t\tfor(var t=0; t<publisherFolders.length; t++) {\n\t\t\t\tif(!$tw.boot.excludeRegExp.test(publisherFolders[t])) {\n\t\t\t\t\tcollectPlugins(path.resolve(folder,\"./\" + publisherFolders[t]));\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\tcollectPublisherPlugins(path.resolve($tw.boot.corePath,$tw.config.pluginsPath));\n\tcollectPublisherPlugins(path.resolve($tw.boot.corePath,$tw.config.themesPath));\n\tcollectPlugins(path.resolve($tw.boot.corePath,$tw.config.languagesPath));\n\t// Save the upgrade library tiddler\n\tvar pluginFields = {\n\t\ttitle: upgradeLibraryTitle,\n\t\ttype: \"application/json\",\n\t\t\"plugin-type\": \"library\",\n\t\t\"text\": JSON.stringify({tiddlers: tiddlers},null,$tw.config.preferences.jsonSpaces)\n\t};\n\twiki.addTiddler(new $tw.Tiddler(pluginFields));\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/makelibrary.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/output.js": { "text": "/*\\\ntitle: $:/core/modules/commands/output.js\ntype: application/javascript\nmodule-type: command\n\nCommand to set the default output location (defaults to current working directory)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"output\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tvar fs = require(\"fs\"),\n\t\tpath = require(\"path\");\n\tif(this.params.length < 1) {\n\t\treturn \"Missing output path\";\n\t}\n\tthis.commander.outputPath = path.resolve(process.cwd(),this.params[0]);\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/output.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/password.js": { "text": "/*\\\ntitle: $:/core/modules/commands/password.js\ntype: application/javascript\nmodule-type: command\n\nSave password for crypto operations\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"password\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing password\";\n\t}\n\t$tw.crypto.setPassword(this.params[0]);\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/password.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/rendertiddler.js": { "text": "/*\\\ntitle: $:/core/modules/commands/rendertiddler.js\ntype: application/javascript\nmodule-type: command\n\nCommand to render a tiddler and save it to a file\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"rendertiddler\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\ttitle = this.params[0],\n\t\tfilename = path.resolve(this.commander.outputPath,this.params[1]),\n\t\ttype = this.params[2] || \"text/html\",\n\t\ttemplate = this.params[3],\n\t\tname = this.params[4],\n\t\tvalue = this.params[5],\n\t\tvariables = {};\n\t$tw.utils.createFileDirectories(filename);\n\tif(template) {\n\t\tvariables.currentTiddler = title;\n\t\ttitle = template;\n\t}\n\tif(name && value) {\n\t\tvariables[name] = value;\n\t}\n\tfs.writeFile(filename,this.commander.wiki.renderTiddler(type,title,{variables: variables}),\"utf8\",function(err) {\n\t\tself.callback(err);\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/rendertiddler.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/rendertiddlers.js": { "text": "/*\\\ntitle: $:/core/modules/commands/rendertiddlers.js\ntype: application/javascript\nmodule-type: command\n\nCommand to render several tiddlers to a folder of files\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.info = {\n\tname: \"rendertiddlers\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\twiki = this.commander.wiki,\n\t\tfilter = this.params[0],\n\t\ttemplate = this.params[1],\n\t\toutputPath = this.commander.outputPath,\n\t\tpathname = path.resolve(outputPath,this.params[2]),\t\t\n\t\ttype = this.params[3] || \"text/html\",\n\t\textension = this.params[4] || \".html\",\n\t\tdeleteDirectory = (this.params[5] || \"\").toLowerCase() !== \"noclean\",\n\t\ttiddlers = wiki.filterTiddlers(filter);\n\tif(deleteDirectory) {\n\t\t$tw.utils.deleteDirectory(pathname);\n\t}\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar parser = wiki.parseTiddler(template),\n\t\t\twidgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}}),\n\t\t\tcontainer = $tw.fakeDocument.createElement(\"div\");\n\t\twidgetNode.render(container,null);\n\t\tvar text = type === \"text/html\" ? container.innerHTML : container.textContent,\n\t\t\texportPath = null;\n\t\tif($tw.utils.hop($tw.macros,\"tv-get-export-path\")) {\n\t\t\tvar macroPath = $tw.macros[\"tv-get-export-path\"].run.apply(self,[title]);\n\t\t\tif(macroPath) {\n\t\t\t\texportPath = path.resolve(outputPath,macroPath + extension);\n\t\t\t}\n\t\t}\n\t\tvar finalPath = exportPath || path.resolve(pathname,encodeURIComponent(title) + extension);\n\t\t$tw.utils.createFileDirectories(finalPath);\n\t\tfs.writeFileSync(finalPath,text,\"utf8\");\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/rendertiddlers.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/savelibrarytiddlers.js": { "text": "/*\\\ntitle: $:/core/modules/commands/savelibrarytiddlers.js\ntype: application/javascript\nmodule-type: command\n\nCommand to save the subtiddlers of a bundle tiddler as a series of JSON files\n\n--savelibrarytiddlers <tiddler> <pathname> <skinnylisting>\n\nThe tiddler identifies the bundle tiddler that contains the subtiddlers.\n\nThe pathname specifies the pathname to the folder in which the JSON files should be saved. The filename is the URL encoded title of the subtiddler.\n\nThe skinnylisting specifies the title of the tiddler to which a JSON catalogue of the subtiddlers will be saved. The JSON file contains the same data as the bundle tiddler but with the `text` field removed.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"savelibrarytiddlers\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\tcontainerTitle = this.params[0],\n\t\tfilter = this.params[1],\n\t\tbasepath = this.params[2],\n\t\tskinnyListTitle = this.params[3];\n\t// Get the container tiddler as data\n\tvar containerData = self.commander.wiki.getTiddlerDataCached(containerTitle,undefined);\n\tif(!containerData) {\n\t\treturn \"'\" + containerTitle + \"' is not a tiddler bundle\";\n\t}\n\t// Filter the list of plugins\n\tvar pluginList = [];\n\t$tw.utils.each(containerData.tiddlers,function(tiddler,title) {\n\t\tpluginList.push(title);\n\t});\n\tvar filteredPluginList;\n\tif(filter) {\n\t\tfilteredPluginList = self.commander.wiki.filterTiddlers(filter,null,self.commander.wiki.makeTiddlerIterator(pluginList));\n\t} else {\n\t\tfilteredPluginList = pluginList;\n\t}\n\t// Iterate through the plugins\n\tvar skinnyList = [];\n\t$tw.utils.each(filteredPluginList,function(title) {\n\t\tvar tiddler = containerData.tiddlers[title];\n\t\t// Save each JSON file and collect the skinny data\n\t\tvar pathname = path.resolve(self.commander.outputPath,basepath + encodeURIComponent(title) + \".json\");\n\t\t$tw.utils.createFileDirectories(pathname);\n\t\tfs.writeFileSync(pathname,JSON.stringify(tiddler,null,$tw.config.preferences.jsonSpaces),\"utf8\");\n\t\t// Collect the skinny list data\n\t\tvar pluginTiddlers = JSON.parse(tiddler.text),\n\t\t\treadmeContent = (pluginTiddlers.tiddlers[title + \"/readme\"] || {}).text,\n\t\t\ticonTiddler = pluginTiddlers.tiddlers[title + \"/icon\"] || {},\n\t\t\ticonType = iconTiddler.type,\n\t\t\ticonText = iconTiddler.text,\n\t\t\ticonContent;\n\t\tif(iconType && iconText) {\n\t\t\ticonContent = $tw.utils.makeDataUri(iconText,iconType);\n\t\t}\n\t\tskinnyList.push($tw.utils.extend({},tiddler,{text: undefined, readme: readmeContent, icon: iconContent}));\n\t});\n\t// Save the catalogue tiddler\n\tif(skinnyListTitle) {\n\t\tself.commander.wiki.setTiddlerData(skinnyListTitle,skinnyList);\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/savelibrarytiddlers.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/savetiddler.js": { "text": "/*\\\ntitle: $:/core/modules/commands/savetiddler.js\ntype: application/javascript\nmodule-type: command\n\nCommand to save the content of a tiddler to a file\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"savetiddler\",\n\tsynchronous: false\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 2) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\ttitle = this.params[0],\n\t\tfilename = path.resolve(this.commander.outputPath,this.params[1]),\n\t\ttiddler = this.commander.wiki.getTiddler(title);\n\tif(tiddler) {\n\t\tvar type = tiddler.fields.type || \"text/vnd.tiddlywiki\",\n\t\t\tcontentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: \"utf8\"};\n\t\t$tw.utils.createFileDirectories(filename);\n\t\tfs.writeFile(filename,tiddler.fields.text,contentTypeInfo.encoding,function(err) {\n\t\t\tself.callback(err);\n\t\t});\n\t} else {\n\t\treturn \"Missing tiddler: \" + title;\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/savetiddler.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/savetiddlers.js": { "text": "/*\\\ntitle: $:/core/modules/commands/savetiddlers.js\ntype: application/javascript\nmodule-type: command\n\nCommand to save several tiddlers to a folder of files\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.info = {\n\tname: \"savetiddlers\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing filename\";\n\t}\n\tvar self = this,\n\t\tfs = require(\"fs\"),\n\t\tpath = require(\"path\"),\n\t\twiki = this.commander.wiki,\n\t\tfilter = this.params[0],\n\t\tpathname = path.resolve(this.commander.outputPath,this.params[1]),\n\t\tdeleteDirectory = (this.params[2] || \"\").toLowerCase() !== \"noclean\",\n\t\ttiddlers = wiki.filterTiddlers(filter);\n\tif(deleteDirectory) {\n\t\t$tw.utils.deleteDirectory(pathname);\n\t}\n\t$tw.utils.createDirectory(pathname);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = self.commander.wiki.getTiddler(title),\n\t\t\ttype = tiddler.fields.type || \"text/vnd.tiddlywiki\",\n\t\t\tcontentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: \"utf8\"},\n\t\t\tfilename = path.resolve(pathname,encodeURIComponent(title));\n\t\tfs.writeFileSync(filename,tiddler.fields.text,contentTypeInfo.encoding);\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/savetiddlers.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/server.js": { "text": "/*\\\ntitle: $:/core/modules/commands/server.js\ntype: application/javascript\nmodule-type: command\n\nServe tiddlers over http\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nif($tw.node) {\n\tvar util = require(\"util\"),\n\t\tfs = require(\"fs\"),\n\t\turl = require(\"url\"),\n\t\tpath = require(\"path\"),\n\t\thttp = require(\"http\");\n}\n\nexports.info = {\n\tname: \"server\",\n\tsynchronous: true\n};\n\n/*\nA simple HTTP server with regexp-based routes\n*/\nfunction SimpleServer(options) {\n\tthis.routes = options.routes || [];\n\tthis.wiki = options.wiki;\n\tthis.variables = options.variables || {};\n}\n\nSimpleServer.prototype.set = function(obj) {\n\tvar self = this;\n\t$tw.utils.each(obj,function(value,name) {\n\t\tself.variables[name] = value;\n\t});\n};\n\nSimpleServer.prototype.get = function(name) {\n\treturn this.variables[name];\n};\n\nSimpleServer.prototype.addRoute = function(route) {\n\tthis.routes.push(route);\n};\n\nSimpleServer.prototype.findMatchingRoute = function(request,state) {\n\tvar pathprefix = this.get(\"pathprefix\") || \"\";\n\tfor(var t=0; t<this.routes.length; t++) {\n\t\tvar potentialRoute = this.routes[t],\n\t\t\tpathRegExp = potentialRoute.path,\n\t\t\tpathname = state.urlInfo.pathname,\n\t\t\tmatch;\n\t\tif(pathprefix) {\n\t\t\tif(pathname.substr(0,pathprefix.length) === pathprefix) {\n\t\t\t\tpathname = pathname.substr(pathprefix.length);\n\t\t\t\tmatch = potentialRoute.path.exec(pathname);\n\t\t\t} else {\n\t\t\t\tmatch = false;\n\t\t\t}\n\t\t} else {\n\t\t\tmatch = potentialRoute.path.exec(pathname);\n\t\t}\n\t\tif(match && request.method === potentialRoute.method) {\n\t\t\tstate.params = [];\n\t\t\tfor(var p=1; p<match.length; p++) {\n\t\t\t\tstate.params.push(match[p]);\n\t\t\t}\n\t\t\treturn potentialRoute;\n\t\t}\n\t}\n\treturn null;\n};\n\nSimpleServer.prototype.checkCredentials = function(request,incomingUsername,incomingPassword) {\n\tvar header = request.headers.authorization || \"\",\n\t\ttoken = header.split(/\\s+/).pop() || \"\",\n\t\tauth = $tw.utils.base64Decode(token),\n\t\tparts = auth.split(/:/),\n\t\tusername = parts[0],\n\t\tpassword = parts[1];\n\tif(incomingUsername === username && incomingPassword === password) {\n\t\treturn \"ALLOWED\";\n\t} else {\n\t\treturn \"DENIED\";\n\t}\n};\n\nSimpleServer.prototype.requestHandler = function(request,response) {\n\t// Compose the state object\n\tvar self = this;\n\tvar state = {};\n\tstate.wiki = self.wiki;\n\tstate.server = self;\n\tstate.urlInfo = url.parse(request.url);\n\t// Find the route that matches this path\n\tvar route = self.findMatchingRoute(request,state);\n\t// Check for the username and password if we've got one\n\tvar username = self.get(\"username\"),\n\t\tpassword = self.get(\"password\");\n\tif(username && password) {\n\t\t// Check they match\n\t\tif(self.checkCredentials(request,username,password) !== \"ALLOWED\") {\n\t\t\tvar servername = state.wiki.getTiddlerText(\"$:/SiteTitle\") || \"TiddlyWiki5\";\n\t\t\tresponse.writeHead(401,\"Authentication required\",{\n\t\t\t\t\"WWW-Authenticate\": 'Basic realm=\"Please provide your username and password to login to ' + servername + '\"'\n\t\t\t});\n\t\t\tresponse.end();\n\t\t\treturn;\n\t\t}\n\t}\n\t// Return a 404 if we didn't find a route\n\tif(!route) {\n\t\tresponse.writeHead(404);\n\t\tresponse.end();\n\t\treturn;\n\t}\n\t// Set the encoding for the incoming request\n\t// TODO: Presumably this would need tweaking if we supported PUTting binary tiddlers\n\trequest.setEncoding(\"utf8\");\n\t// Dispatch the appropriate method\n\tswitch(request.method) {\n\t\tcase \"GET\": // Intentional fall-through\n\t\tcase \"DELETE\":\n\t\t\troute.handler(request,response,state);\n\t\t\tbreak;\n\t\tcase \"PUT\":\n\t\t\tvar data = \"\";\n\t\t\trequest.on(\"data\",function(chunk) {\n\t\t\t\tdata += chunk.toString();\n\t\t\t});\n\t\t\trequest.on(\"end\",function() {\n\t\t\t\tstate.data = data;\n\t\t\t\troute.handler(request,response,state);\n\t\t\t});\n\t\t\tbreak;\n\t}\n};\n\t\nSimpleServer.prototype.listen = function(port,host) {\n\thttp.createServer(this.requestHandler.bind(this)).listen(port,host);\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n\t// Set up server\n\tthis.server = new SimpleServer({\n\t\twiki: this.commander.wiki\n\t});\n\t// Add route handlers\n\tthis.server.addRoute({\n\t\tmethod: \"PUT\",\n\t\tpath: /^\\/recipes\\/default\\/tiddlers\\/(.+)$/,\n\t\thandler: function(request,response,state) {\n\t\t\tvar title = decodeURIComponent(state.params[0]),\n\t\t\t\tfields = JSON.parse(state.data);\n\t\t\t// Pull up any subfields in the `fields` object\n\t\t\tif(fields.fields) {\n\t\t\t\t$tw.utils.each(fields.fields,function(field,name) {\n\t\t\t\t\tfields[name] = field;\n\t\t\t\t});\n\t\t\t\tdelete fields.fields;\n\t\t\t}\n\t\t\t// Remove any revision field\n\t\t\tif(fields.revision) {\n\t\t\t\tdelete fields.revision;\n\t\t\t}\n\t\t\tstate.wiki.addTiddler(new $tw.Tiddler(state.wiki.getCreationFields(),fields,{title: title},state.wiki.getModificationFields()));\n\t\t\tvar changeCount = state.wiki.getChangeCount(title).toString();\n\t\t\tresponse.writeHead(204, \"OK\",{\n\t\t\t\tEtag: \"\\\"default/\" + encodeURIComponent(title) + \"/\" + changeCount + \":\\\"\",\n\t\t\t\t\"Content-Type\": \"text/plain\"\n\t\t\t});\n\t\t\tresponse.end();\n\t\t}\n\t});\n\tthis.server.addRoute({\n\t\tmethod: \"DELETE\",\n\t\tpath: /^\\/bags\\/default\\/tiddlers\\/(.+)$/,\n\t\thandler: function(request,response,state) {\n\t\t\tvar title = decodeURIComponent(state.params[0]);\n\t\t\tstate.wiki.deleteTiddler(title);\n\t\t\tresponse.writeHead(204, \"OK\", {\n\t\t\t\t\"Content-Type\": \"text/plain\"\n\t\t\t});\n\t\t\tresponse.end();\n\t\t}\n\t});\n\tthis.server.addRoute({\n\t\tmethod: \"GET\",\n\t\tpath: /^\\/$/,\n\t\thandler: function(request,response,state) {\n\t\t\tresponse.writeHead(200, {\"Content-Type\": state.server.get(\"serveType\")});\n\t\t\tvar text = state.wiki.renderTiddler(state.server.get(\"renderType\"),state.server.get(\"rootTiddler\"));\n\t\t\tresponse.end(text,\"utf8\");\n\t\t}\n\t});\n\tthis.server.addRoute({\n\t\tmethod: \"GET\",\n\t\tpath: /^\\/status$/,\n\t\thandler: function(request,response,state) {\n\t\t\tresponse.writeHead(200, {\"Content-Type\": \"application/json\"});\n\t\t\tvar text = JSON.stringify({\n\t\t\t\tusername: state.server.get(\"username\"),\n\t\t\t\tspace: {\n\t\t\t\t\trecipe: \"default\"\n\t\t\t\t},\n\t\t\t\ttiddlywiki_version: $tw.version\n\t\t\t});\n\t\t\tresponse.end(text,\"utf8\");\n\t\t}\n\t});\n\tthis.server.addRoute({\n\t\tmethod: \"GET\",\n\t\tpath: /^\\/favicon.ico$/,\n\t\thandler: function(request,response,state) {\n\t\t\tresponse.writeHead(200, {\"Content-Type\": \"image/x-icon\"});\n\t\t\tvar buffer = state.wiki.getTiddlerText(\"$:/favicon.ico\",\"\");\n\t\t\tresponse.end(buffer,\"base64\");\n\t\t}\n\t});\n\tthis.server.addRoute({\n\t\tmethod: \"GET\",\n\t\tpath: /^\\/recipes\\/default\\/tiddlers.json$/,\n\t\thandler: function(request,response,state) {\n\t\t\tresponse.writeHead(200, {\"Content-Type\": \"application/json\"});\n\t\t\tvar tiddlers = [];\n\t\t\tstate.wiki.forEachTiddler({sortField: \"title\"},function(title,tiddler) {\n\t\t\t\tvar tiddlerFields = {};\n\t\t\t\t$tw.utils.each(tiddler.fields,function(field,name) {\n\t\t\t\t\tif(name !== \"text\") {\n\t\t\t\t\t\ttiddlerFields[name] = tiddler.getFieldString(name);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\ttiddlerFields.revision = state.wiki.getChangeCount(title);\n\t\t\t\ttiddlerFields.type = tiddlerFields.type || \"text/vnd.tiddlywiki\";\n\t\t\t\ttiddlers.push(tiddlerFields);\n\t\t\t});\n\t\t\tvar text = JSON.stringify(tiddlers);\n\t\t\tresponse.end(text,\"utf8\");\n\t\t}\n\t});\n\tthis.server.addRoute({\n\t\tmethod: \"GET\",\n\t\tpath: /^\\/recipes\\/default\\/tiddlers\\/(.+)$/,\n\t\thandler: function(request,response,state) {\n\t\t\tvar title = decodeURIComponent(state.params[0]),\n\t\t\t\ttiddler = state.wiki.getTiddler(title),\n\t\t\t\ttiddlerFields = {},\n\t\t\t\tknownFields = [\n\t\t\t\t\t\"bag\", \"created\", \"creator\", \"modified\", \"modifier\", \"permissions\", \"recipe\", \"revision\", \"tags\", \"text\", \"title\", \"type\", \"uri\"\n\t\t\t\t];\n\t\t\tif(tiddler) {\n\t\t\t\t$tw.utils.each(tiddler.fields,function(field,name) {\n\t\t\t\t\tvar value = tiddler.getFieldString(name);\n\t\t\t\t\tif(knownFields.indexOf(name) !== -1) {\n\t\t\t\t\t\ttiddlerFields[name] = value;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttiddlerFields.fields = tiddlerFields.fields || {};\n\t\t\t\t\t\ttiddlerFields.fields[name] = value;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\ttiddlerFields.revision = state.wiki.getChangeCount(title);\n\t\t\t\ttiddlerFields.type = tiddlerFields.type || \"text/vnd.tiddlywiki\";\n\t\t\t\tresponse.writeHead(200, {\"Content-Type\": \"application/json\"});\n\t\t\t\tresponse.end(JSON.stringify(tiddlerFields),\"utf8\");\n\t\t\t} else {\n\t\t\t\tresponse.writeHead(404);\n\t\t\t\tresponse.end();\n\t\t\t}\n\t\t}\n\t});\n};\n\nCommand.prototype.execute = function() {\n\tif(!$tw.boot.wikiTiddlersPath) {\n\t\t$tw.utils.warning(\"Warning: Wiki folder '\" + $tw.boot.wikiPath + \"' does not exist or is missing a tiddlywiki.info file\");\n\t}\n\tvar port = this.params[0] || \"8080\",\n\t\trootTiddler = this.params[1] || \"$:/core/save/all\",\n\t\trenderType = this.params[2] || \"text/plain\",\n\t\tserveType = this.params[3] || \"text/html\",\n\t\tusername = this.params[4],\n\t\tpassword = this.params[5],\n\t\thost = this.params[6] || \"127.0.0.1\",\n\t\tpathprefix = this.params[7];\n\tthis.server.set({\n\t\trootTiddler: rootTiddler,\n\t\trenderType: renderType,\n\t\tserveType: serveType,\n\t\tusername: username,\n\t\tpassword: password,\n\t\tpathprefix: pathprefix\n\t});\n\tthis.server.listen(port,host);\n\tconsole.log(\"Serving on \" + host + \":\" + port);\n\tconsole.log(\"(press ctrl-C to exit)\");\n\t// Warn if required plugins are missing\n\tif(!$tw.wiki.getTiddler(\"$:/plugins/tiddlywiki/tiddlyweb\") || !$tw.wiki.getTiddler(\"$:/plugins/tiddlywiki/filesystem\")) {\n\t\t$tw.utils.warning(\"Warning: Plugins required for client-server operation (\\\"tiddlywiki/filesystem\\\" and \\\"tiddlywiki/tiddlyweb\\\") are missing from tiddlywiki.info file\");\n\t}\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/server.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/setfield.js": { "text": "/*\\\ntitle: $:/core/modules/commands/setfield.js\ntype: application/javascript\nmodule-type: command\n\nCommand to modify selected tiddlers to set a field to the text of a template tiddler that has been wikified with the selected tiddler as the current tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.info = {\n\tname: \"setfield\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 4) {\n\t\treturn \"Missing parameters\";\n\t}\n\tvar self = this,\n\t\twiki = this.commander.wiki,\n\t\tfilter = this.params[0],\n\t\tfieldname = this.params[1] || \"text\",\n\t\ttemplatetitle = this.params[2],\n\t\trendertype = this.params[3] || \"text/plain\",\n\t\ttiddlers = wiki.filterTiddlers(filter);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar parser = wiki.parseTiddler(templatetitle),\n\t\t\tnewFields = {},\n\t\t\ttiddler = wiki.getTiddler(title);\n\t\tif(parser) {\n\t\t\tvar widgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}});\n\t\t\tvar container = $tw.fakeDocument.createElement(\"div\");\n\t\t\twidgetNode.render(container,null);\n\t\t\tnewFields[fieldname] = rendertype === \"text/html\" ? container.innerHTML : container.textContent;\n\t\t} else {\n\t\t\tnewFields[fieldname] = undefined;\n\t\t}\n\t\twiki.addTiddler(new $tw.Tiddler(tiddler,newFields));\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/setfield.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/unpackplugin.js": { "text": "/*\\\ntitle: $:/core/modules/commands/unpackplugin.js\ntype: application/javascript\nmodule-type: command\n\nCommand to extract the shadow tiddlers from within a plugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"unpackplugin\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander,callback) {\n\tthis.params = params;\n\tthis.commander = commander;\n\tthis.callback = callback;\n};\n\nCommand.prototype.execute = function() {\n\tif(this.params.length < 1) {\n\t\treturn \"Missing plugin name\";\n\t}\n\tvar self = this,\n\t\ttitle = this.params[0],\n\t\tpluginData = this.commander.wiki.getTiddlerDataCached(title);\n\tif(!pluginData) {\n\t\treturn \"Plugin '\" + title + \"' not found\";\n\t}\n\t$tw.utils.each(pluginData.tiddlers,function(tiddler) {\n\t\tself.commander.wiki.addTiddler(new $tw.Tiddler(tiddler));\n\t});\n\treturn null;\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/unpackplugin.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/verbose.js": { "text": "/*\\\ntitle: $:/core/modules/commands/verbose.js\ntype: application/javascript\nmodule-type: command\n\nVerbose command\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"verbose\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tthis.commander.verbose = true;\n\t// Output the boot message log\n\tthis.commander.streams.output.write(\"Boot log:\\n \" + $tw.boot.logMessages.join(\"\\n \") + \"\\n\");\n\treturn null; // No error\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/verbose.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/commands/version.js": { "text": "/*\\\ntitle: $:/core/modules/commands/version.js\ntype: application/javascript\nmodule-type: command\n\nVersion command\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.info = {\n\tname: \"version\",\n\tsynchronous: true\n};\n\nvar Command = function(params,commander) {\n\tthis.params = params;\n\tthis.commander = commander;\n};\n\nCommand.prototype.execute = function() {\n\tthis.commander.streams.output.write($tw.version + \"\\n\");\n\treturn null; // No error\n};\n\nexports.Command = Command;\n\n})();\n", "title": "$:/core/modules/commands/version.js", "type": "application/javascript", "module-type": "command" }, "$:/core/modules/config.js": { "text": "/*\\\ntitle: $:/core/modules/config.js\ntype: application/javascript\nmodule-type: config\n\nCore configuration constants\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.preferences = {};\n\nexports.preferences.notificationDuration = 3 * 1000;\nexports.preferences.jsonSpaces = 4;\n\nexports.textPrimitives = {\n\tupperLetter: \"[A-Z\\u00c0-\\u00d6\\u00d8-\\u00de\\u0150\\u0170]\",\n\tlowerLetter: \"[a-z\\u00df-\\u00f6\\u00f8-\\u00ff\\u0151\\u0171]\",\n\tanyLetter: \"[A-Za-z0-9\\u00c0-\\u00d6\\u00d8-\\u00de\\u00df-\\u00f6\\u00f8-\\u00ff\\u0150\\u0170\\u0151\\u0171]\",\n\tblockPrefixLetters:\t\"[A-Za-z0-9-_\\u00c0-\\u00d6\\u00d8-\\u00de\\u00df-\\u00f6\\u00f8-\\u00ff\\u0150\\u0170\\u0151\\u0171]\"\n};\n\nexports.textPrimitives.unWikiLink = \"~\";\nexports.textPrimitives.wikiLink = exports.textPrimitives.upperLetter + \"+\" +\n\texports.textPrimitives.lowerLetter + \"+\" +\n\texports.textPrimitives.upperLetter +\n\texports.textPrimitives.anyLetter + \"*\";\n\nexports.htmlEntities = {quot:34, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 };\n\nexports.htmlVoidElements = \"area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr\".split(\",\");\n\nexports.htmlBlockElements = \"address,article,aside,audio,blockquote,canvas,dd,div,dl,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,li,noscript,ol,output,p,pre,section,table,tfoot,ul,video\".split(\",\");\n\nexports.htmlUnsafeElements = \"script\".split(\",\");\n\n})();\n", "title": "$:/core/modules/config.js", "type": "application/javascript", "module-type": "config" }, "$:/core/modules/deserializers.js": { "text": "/*\\\ntitle: $:/core/modules/deserializers.js\ntype: application/javascript\nmodule-type: tiddlerdeserializer\n\nFunctions to deserialise tiddlers from a block of text\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nUtility function to parse an old-style tiddler DIV in a *.tid file. It looks like this:\n\n<div title=\"Title\" creator=\"JoeBloggs\" modifier=\"JoeBloggs\" created=\"201102111106\" modified=\"201102111310\" tags=\"myTag [[my long tag]]\">\n<pre>The text of the tiddler (without the expected HTML encoding).\n</pre>\n</div>\n\nNote that the field attributes are HTML encoded, but that the body of the <PRE> tag is not encoded.\n\nWhen these tiddler DIVs are encountered within a TiddlyWiki HTML file then the body is encoded in the usual way.\n*/\nvar parseTiddlerDiv = function(text /* [,fields] */) {\n\t// Slot together the default results\n\tvar result = {};\n\tif(arguments.length > 1) {\n\t\tfor(var f=1; f<arguments.length; f++) {\n\t\t\tvar fields = arguments[f];\n\t\t\tfor(var t in fields) {\n\t\t\t\tresult[t] = fields[t];\t\t\n\t\t\t}\n\t\t}\n\t}\n\t// Parse the DIV body\n\tvar startRegExp = /^\\s*<div\\s+([^>]*)>(\\s*<pre>)?/gi,\n\t\tendRegExp,\n\t\tmatch = startRegExp.exec(text);\n\tif(match) {\n\t\t// Old-style DIVs don't have the <pre> tag\n\t\tif(match[2]) {\n\t\t\tendRegExp = /<\\/pre>\\s*<\\/div>\\s*$/gi;\n\t\t} else {\n\t\t\tendRegExp = /<\\/div>\\s*$/gi;\n\t\t}\n\t\tvar endMatch = endRegExp.exec(text);\n\t\tif(endMatch) {\n\t\t\t// Extract the text\n\t\t\tresult.text = text.substring(match.index + match[0].length,endMatch.index);\n\t\t\t// Process the attributes\n\t\t\tvar attrRegExp = /\\s*([^=\\s]+)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)')/gi,\n\t\t\t\tattrMatch;\n\t\t\tdo {\n\t\t\t\tattrMatch = attrRegExp.exec(match[1]);\n\t\t\t\tif(attrMatch) {\n\t\t\t\t\tvar name = attrMatch[1];\n\t\t\t\t\tvar value = attrMatch[2] !== undefined ? attrMatch[2] : attrMatch[3];\n\t\t\t\t\tresult[name] = value;\n\t\t\t\t}\n\t\t\t} while(attrMatch);\n\t\t\treturn result;\n\t\t}\n\t}\n\treturn undefined;\n};\n\nexports[\"application/x-tiddler-html-div\"] = function(text,fields) {\n\treturn [parseTiddlerDiv(text,fields)];\n};\n\nexports[\"application/json\"] = function(text,fields) {\n\tvar incoming,\n\t\tresults = [];\n\ttry {\n\t\tincoming = JSON.parse(text);\n\t} catch(e) {\n\t\tincoming = [{\n\t\t\ttitle: \"JSON error: \" + e,\n\t\t\ttext: \"\"\n\t\t}]\n\t}\n\tif(!$tw.utils.isArray(incoming)) {\n\t\tincoming = [incoming];\n\t}\n\tfor(var t=0; t<incoming.length; t++) {\n\t\tvar incomingFields = incoming[t],\n\t\t\tfields = {};\n\t\tfor(var f in incomingFields) {\n\t\t\tif(typeof incomingFields[f] === \"string\") {\n\t\t\t\tfields[f] = incomingFields[f];\n\t\t\t}\n\t\t}\n\t\tresults.push(fields);\n\t}\n\treturn results;\n};\n\n/*\nParse an HTML file into tiddlers. There are three possibilities:\n# A TiddlyWiki classic HTML file containing `text/x-tiddlywiki` tiddlers\n# A TiddlyWiki5 HTML file containing `text/vnd.tiddlywiki` tiddlers\n# An ordinary HTML file\n*/\nexports[\"text/html\"] = function(text,fields) {\n\t// Check if we've got a store area\n\tvar storeAreaMarkerRegExp = /<div id=[\"']?storeArea['\"]?( style=[\"']?display:none;[\"']?)?>/gi,\n\t\tmatch = storeAreaMarkerRegExp.exec(text);\n\tif(match) {\n\t\t// If so, it's either a classic TiddlyWiki file or an unencrypted TW5 file\n\t\t// First read the normal tiddlers\n\t\tvar results = deserializeTiddlyWikiFile(text,storeAreaMarkerRegExp.lastIndex,!!match[1],fields);\n\t\t// Then any system tiddlers\n\t\tvar systemAreaMarkerRegExp = /<div id=[\"']?systemArea['\"]?( style=[\"']?display:none;[\"']?)?>/gi,\n\t\t\tsysMatch = systemAreaMarkerRegExp.exec(text);\n\t\tif(sysMatch) {\n\t\t\tresults.push.apply(results,deserializeTiddlyWikiFile(text,systemAreaMarkerRegExp.lastIndex,!!sysMatch[1],fields));\n\t\t}\n\t\treturn results;\n\t} else {\n\t\t// Check whether we've got an encrypted file\n\t\tvar encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);\n\t\tif(encryptedStoreArea) {\n\t\t\t// If so, attempt to decrypt it using the current password\n\t\t\treturn $tw.utils.decryptStoreArea(encryptedStoreArea);\n\t\t} else {\n\t\t\t// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler\n\t\t\treturn deserializeHtmlFile(text,fields);\n\t\t}\n\t}\n};\n\nfunction deserializeHtmlFile(text,fields) {\n\tvar result = {};\n\t$tw.utils.each(fields,function(value,name) {\n\t\tresult[name] = value;\n\t});\n\tresult.text = text;\n\tresult.type = \"text/html\";\n\treturn [result];\n}\n\nfunction deserializeTiddlyWikiFile(text,storeAreaEnd,isTiddlyWiki5,fields) {\n\tvar results = [],\n\t\tendOfDivRegExp = /(<\\/div>\\s*)/gi,\n\t\tstartPos = storeAreaEnd,\n\t\tdefaultType = isTiddlyWiki5 ? undefined : \"text/x-tiddlywiki\";\n\tendOfDivRegExp.lastIndex = startPos;\n\tvar match = endOfDivRegExp.exec(text);\n\twhile(match) {\n\t\tvar endPos = endOfDivRegExp.lastIndex,\n\t\t\ttiddlerFields = parseTiddlerDiv(text.substring(startPos,endPos),fields,{type: defaultType});\n\t\tif(!tiddlerFields) {\n\t\t\tbreak;\n\t\t}\n\t\t$tw.utils.each(tiddlerFields,function(value,name) {\n\t\t\tif(typeof value === \"string\") {\n\t\t\t\ttiddlerFields[name] = $tw.utils.htmlDecode(value);\n\t\t\t}\n\t\t});\n\t\tif(tiddlerFields.text !== null) {\n\t\t\tresults.push(tiddlerFields);\n\t\t}\n\t\tstartPos = endPos;\n\t\tmatch = endOfDivRegExp.exec(text);\n\t}\n\treturn results;\n}\n\n})();\n", "title": "$:/core/modules/deserializers.js", "type": "application/javascript", "module-type": "tiddlerdeserializer" }, "$:/core/modules/editor/engines/framed.js": { "text": "/*\\\ntitle: $:/core/modules/editor/engines/framed.js\ntype: application/javascript\nmodule-type: library\n\nText editor engine based on a simple input or textarea within an iframe. This is done so that the selection is preserved even when clicking away from the textarea\n\n\\*/\n(function(){\n\n/*jslint node: true,browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar HEIGHT_VALUE_TITLE = \"$:/config/TextEditor/EditorHeight/Height\";\n\nfunction FramedEngine(options) {\n\t// Save our options\n\toptions = options || {};\n\tthis.widget = options.widget;\n\tthis.value = options.value;\n\tthis.parentNode = options.parentNode;\n\tthis.nextSibling = options.nextSibling;\n\t// Create our hidden dummy text area for reading styles\n\tthis.dummyTextArea = this.widget.document.createElement(\"textarea\");\n\tif(this.widget.editClass) {\n\t\tthis.dummyTextArea.className = this.widget.editClass;\n\t}\n\tthis.dummyTextArea.setAttribute(\"hidden\",\"true\");\n\tthis.parentNode.insertBefore(this.dummyTextArea,this.nextSibling);\n\tthis.widget.domNodes.push(this.dummyTextArea);\n\t// Create the iframe\n\tthis.iframeNode = this.widget.document.createElement(\"iframe\");\n\tthis.parentNode.insertBefore(this.iframeNode,this.nextSibling);\n\tthis.iframeDoc = this.iframeNode.contentWindow.document;\n\t// (Firefox requires us to put some empty content in the iframe)\n\tthis.iframeDoc.open();\n\tthis.iframeDoc.write(\"\");\n\tthis.iframeDoc.close();\n\t// Style the iframe\n\tthis.iframeNode.className = this.dummyTextArea.className;\n\tthis.iframeNode.style.border = \"none\";\n\tthis.iframeNode.style.padding = \"0\";\n\tthis.iframeNode.style.resize = \"none\";\n\tthis.iframeDoc.body.style.margin = \"0\";\n\tthis.iframeDoc.body.style.padding = \"0\";\n\tthis.widget.domNodes.push(this.iframeNode);\n\t// Construct the textarea or input node\n\tvar tag = this.widget.editTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"input\";\n\t}\n\tthis.domNode = this.iframeDoc.createElement(tag);\n\t// Set the text\n\tif(this.widget.editTag === \"textarea\") {\n\t\tthis.domNode.appendChild(this.iframeDoc.createTextNode(this.value));\n\t} else {\n\t\tthis.domNode.value = this.value;\n\t}\n\t// Set the attributes\n\tif(this.widget.editType) {\n\t\tthis.domNode.setAttribute(\"type\",this.widget.editType);\n\t}\n\tif(this.widget.editPlaceholder) {\n\t\tthis.domNode.setAttribute(\"placeholder\",this.widget.editPlaceholder);\n\t}\n\tif(this.widget.editSize) {\n\t\tthis.domNode.setAttribute(\"size\",this.widget.editSize);\n\t}\n\tif(this.widget.editRows) {\n\t\tthis.domNode.setAttribute(\"rows\",this.widget.editRows);\n\t}\n\t// Copy the styles from the dummy textarea\n\tthis.copyStyles();\n\t// Add event listeners\n\t$tw.utils.addEventListeners(this.domNode,[\n\t\t{name: \"input\",handlerObject: this,handlerMethod: \"handleInputEvent\"},\n\t\t{name: \"keydown\",handlerObject: this.widget,handlerMethod: \"handleKeydownEvent\"}\n\t]);\n\t// Insert the element into the DOM\n\tthis.iframeDoc.body.appendChild(this.domNode);\n}\n\n/*\nCopy styles from the dummy text area to the textarea in the iframe\n*/\nFramedEngine.prototype.copyStyles = function() {\n\t// Copy all styles\n\t$tw.utils.copyStyles(this.dummyTextArea,this.domNode);\n\t// Override the ones that should not be set the same as the dummy textarea\n\tthis.domNode.style.display = \"block\";\n\tthis.domNode.style.width = \"100%\";\n\tthis.domNode.style.margin = \"0\";\n\t// In Chrome setting -webkit-text-fill-color overrides the placeholder text colour\n\tthis.domNode.style[\"-webkit-text-fill-color\"] = \"currentcolor\";\n};\n\n/*\nSet the text of the engine if it doesn't currently have focus\n*/\nFramedEngine.prototype.setText = function(text,type) {\n\tif(!this.domNode.isTiddlyWikiFakeDom) {\n\t\tif(this.domNode.ownerDocument.activeElement !== this.domNode) {\n\t\t\tthis.domNode.value = text;\n\t\t}\n\t\t// Fix the height if needed\n\t\tthis.fixHeight();\n\t}\n};\n\n/*\nGet the text of the engine\n*/\nFramedEngine.prototype.getText = function() {\n\treturn this.domNode.value;\n};\n\n/*\nFix the height of textarea to fit content\n*/\nFramedEngine.prototype.fixHeight = function() {\n\t// Make sure styles are updated\n\tthis.copyStyles();\n\t// Adjust height\n\tif(this.widget.editTag === \"textarea\") {\n\t\tif(this.widget.editAutoHeight) {\n\t\t\tif(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {\n\t\t\t\tvar newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);\n\t\t\t\tthis.iframeNode.style.height = (newHeight + 14) + \"px\"; // +14 for the border on the textarea\n\t\t\t}\n\t\t} else {\n\t\t\tvar fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,\"400px\"),10);\n\t\t\tfixedHeight = Math.max(fixedHeight,20);\n\t\t\tthis.domNode.style.height = fixedHeight + \"px\";\n\t\t\tthis.iframeNode.style.height = (fixedHeight + 14) + \"px\";\n\t\t}\n\t}\n};\n\n/*\nFocus the engine node\n*/\nFramedEngine.prototype.focus = function() {\n\tif(this.domNode.focus && this.domNode.select) {\n\t\tthis.domNode.focus();\n\t\tthis.domNode.select();\n\t}\n};\n\n/*\nHandle a dom \"input\" event which occurs when the text has changed\n*/\nFramedEngine.prototype.handleInputEvent = function(event) {\n\tthis.widget.saveChanges(this.getText());\n\tthis.fixHeight();\n\treturn true;\n};\n\n/*\nCreate a blank structure representing a text operation\n*/\nFramedEngine.prototype.createTextOperation = function() {\n\tvar operation = {\n\t\ttext: this.domNode.value,\n\t\tselStart: this.domNode.selectionStart,\n\t\tselEnd: this.domNode.selectionEnd,\n\t\tcutStart: null,\n\t\tcutEnd: null,\n\t\treplacement: null,\n\t\tnewSelStart: null,\n\t\tnewSelEnd: null\n\t};\n\toperation.selection = operation.text.substring(operation.selStart,operation.selEnd);\n\treturn operation;\n};\n\n/*\nExecute a text operation\n*/\nFramedEngine.prototype.executeTextOperation = function(operation) {\n\t// Perform the required changes to the text area and the underlying tiddler\n\tvar newText = operation.text;\n\tif(operation.replacement !== null) {\n\t\tnewText = operation.text.substring(0,operation.cutStart) + operation.replacement + operation.text.substring(operation.cutEnd);\n\t\t// Attempt to use a execCommand to modify the value of the control\n\t\tif(this.iframeDoc.queryCommandSupported(\"insertText\") && this.iframeDoc.queryCommandSupported(\"delete\") && !$tw.browser.isFirefox) {\n\t\t\tthis.domNode.focus();\n\t\t\tthis.domNode.setSelectionRange(operation.cutStart,operation.cutEnd);\n\t\t\tif(operation.replacement === \"\") {\n\t\t\t\tthis.iframeDoc.execCommand(\"delete\",false,\"\");\n\t\t\t} else {\n\t\t\t\tthis.iframeDoc.execCommand(\"insertText\",false,operation.replacement);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.domNode.value = newText;\n\t\t}\n\t\tthis.domNode.focus();\n\t\tthis.domNode.setSelectionRange(operation.newSelStart,operation.newSelEnd);\n\t}\n\tthis.domNode.focus();\n\treturn newText;\n};\n\nexports.FramedEngine = FramedEngine;\n\n})();\n", "title": "$:/core/modules/editor/engines/framed.js", "type": "application/javascript", "module-type": "library" }, "$:/core/modules/editor/engines/simple.js": { "text": "/*\\\ntitle: $:/core/modules/editor/engines/simple.js\ntype: application/javascript\nmodule-type: library\n\nText editor engine based on a simple input or textarea tag\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar HEIGHT_VALUE_TITLE = \"$:/config/TextEditor/EditorHeight/Height\";\n\nfunction SimpleEngine(options) {\n\t// Save our options\n\toptions = options || {};\n\tthis.widget = options.widget;\n\tthis.value = options.value;\n\tthis.parentNode = options.parentNode;\n\tthis.nextSibling = options.nextSibling;\n\t// Construct the textarea or input node\n\tvar tag = this.widget.editTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"input\";\n\t}\n\tthis.domNode = this.widget.document.createElement(tag);\n\t// Set the text\n\tif(this.widget.editTag === \"textarea\") {\n\t\tthis.domNode.appendChild(this.widget.document.createTextNode(this.value));\n\t} else {\n\t\tthis.domNode.value = this.value;\n\t}\n\t// Set the attributes\n\tif(this.widget.editType) {\n\t\tthis.domNode.setAttribute(\"type\",this.widget.editType);\n\t}\n\tif(this.widget.editPlaceholder) {\n\t\tthis.domNode.setAttribute(\"placeholder\",this.widget.editPlaceholder);\n\t}\n\tif(this.widget.editSize) {\n\t\tthis.domNode.setAttribute(\"size\",this.widget.editSize);\n\t}\n\tif(this.widget.editRows) {\n\t\tthis.domNode.setAttribute(\"rows\",this.widget.editRows);\n\t}\n\tif(this.widget.editClass) {\n\t\tthis.domNode.className = this.widget.editClass;\n\t}\n\t// Add an input event handler\n\t$tw.utils.addEventListeners(this.domNode,[\n\t\t{name: \"focus\", handlerObject: this, handlerMethod: \"handleFocusEvent\"},\n\t\t{name: \"input\", handlerObject: this, handlerMethod: \"handleInputEvent\"}\n\t]);\n\t// Insert the element into the DOM\n\tthis.parentNode.insertBefore(this.domNode,this.nextSibling);\n\tthis.widget.domNodes.push(this.domNode);\n}\n\n/*\nSet the text of the engine if it doesn't currently have focus\n*/\nSimpleEngine.prototype.setText = function(text,type) {\n\tif(!this.domNode.isTiddlyWikiFakeDom) {\n\t\tif(this.domNode.ownerDocument.activeElement !== this.domNode || text === \"\") {\n\t\t\tthis.domNode.value = text;\n\t\t}\n\t\t// Fix the height if needed\n\t\tthis.fixHeight();\n\t}\n};\n\n/*\nGet the text of the engine\n*/\nSimpleEngine.prototype.getText = function() {\n\treturn this.domNode.value;\n};\n\n/*\nFix the height of textarea to fit content\n*/\nSimpleEngine.prototype.fixHeight = function() {\n\tif(this.widget.editTag === \"textarea\") {\n\t\tif(this.widget.editAutoHeight) {\n\t\t\tif(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {\n\t\t\t\t$tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);\n\t\t\t}\n\t\t} else {\n\t\t\tvar fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,\"400px\"),10);\n\t\t\tfixedHeight = Math.max(fixedHeight,20);\n\t\t\tthis.domNode.style.height = fixedHeight + \"px\";\n\t\t}\n\t}\n};\n\n/*\nFocus the engine node\n*/\nSimpleEngine.prototype.focus = function() {\n\tif(this.domNode.focus && this.domNode.select) {\n\t\tthis.domNode.focus();\n\t\tthis.domNode.select();\n\t}\n};\n\n/*\nHandle a dom \"input\" event which occurs when the text has changed\n*/\nSimpleEngine.prototype.handleInputEvent = function(event) {\n\tthis.widget.saveChanges(this.getText());\n\tthis.fixHeight();\n\treturn true;\n};\n\n/*\nHandle a dom \"focus\" event\n*/\nSimpleEngine.prototype.handleFocusEvent = function(event) {\n\tif(this.widget.editFocusPopup) {\n\t\t$tw.popup.triggerPopup({\n\t\t\tdomNode: this.domNode,\n\t\t\ttitle: this.widget.editFocusPopup,\n\t\t\twiki: this.widget.wiki,\n\t\t\tforce: true\n\t\t});\n\t}\n\treturn true;\n};\n\n/*\nCreate a blank structure representing a text operation\n*/\nSimpleEngine.prototype.createTextOperation = function() {\n\treturn null;\n};\n\n/*\nExecute a text operation\n*/\nSimpleEngine.prototype.executeTextOperation = function(operation) {\n};\n\nexports.SimpleEngine = SimpleEngine;\n\n})();\n", "title": "$:/core/modules/editor/engines/simple.js", "type": "application/javascript", "module-type": "library" }, "$:/core/modules/editor/factory.js": { "text": "/*\\\ntitle: $:/core/modules/editor/factory.js\ntype: application/javascript\nmodule-type: library\n\nFactory for constructing text editor widgets with specified engines for the toolbar and non-toolbar cases\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar DEFAULT_MIN_TEXT_AREA_HEIGHT = \"100px\"; // Minimum height of textareas in pixels\n\n// Configuration tiddlers\nvar HEIGHT_MODE_TITLE = \"$:/config/TextEditor/EditorHeight/Mode\";\nvar ENABLE_TOOLBAR_TITLE = \"$:/config/TextEditor/EnableToolbar\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nfunction editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {\n\n\tvar EditTextWidget = function(parseTreeNode,options) {\n\t\t// Initialise the editor operations if they've not been done already\n\t\tif(!this.editorOperations) {\n\t\t\tEditTextWidget.prototype.editorOperations = {};\n\t\t\t$tw.modules.applyMethods(\"texteditoroperation\",this.editorOperations);\n\t\t}\n\t\tthis.initialise(parseTreeNode,options);\n\t};\n\n\t/*\n\tInherit from the base widget class\n\t*/\n\tEditTextWidget.prototype = new Widget();\n\n\t/*\n\tRender this widget into the DOM\n\t*/\n\tEditTextWidget.prototype.render = function(parent,nextSibling) {\n\t\t// Save the parent dom node\n\t\tthis.parentDomNode = parent;\n\t\t// Compute our attributes\n\t\tthis.computeAttributes();\n\t\t// Execute our logic\n\t\tthis.execute();\n\t\t// Create the wrapper for the toolbar and render its content\n\t\tif(this.editShowToolbar) {\n\t\t\tthis.toolbarNode = this.document.createElement(\"div\");\n\t\t\tthis.toolbarNode.className = \"tc-editor-toolbar\";\n\t\t\tparent.insertBefore(this.toolbarNode,nextSibling);\n\t\t\tthis.renderChildren(this.toolbarNode,null);\n\t\t\tthis.domNodes.push(this.toolbarNode);\n\t\t}\n\t\t// Create our element\n\t\tvar editInfo = this.getEditInfo(),\n\t\t\tEngine = this.editShowToolbar ? toolbarEngine : nonToolbarEngine;\n\t\tthis.engine = new Engine({\n\t\t\t\twidget: this,\n\t\t\t\tvalue: editInfo.value,\n\t\t\t\ttype: editInfo.type,\n\t\t\t\tparentNode: parent,\n\t\t\t\tnextSibling: nextSibling\n\t\t\t});\n\t\t// Call the postRender hook\n\t\tif(this.postRender) {\n\t\t\tthis.postRender();\n\t\t}\n\t\t// Fix height\n\t\tthis.engine.fixHeight();\n\t\t// Focus if required\n\t\tif(this.editFocus === \"true\" || this.editFocus === \"yes\") {\n\t\t\tthis.engine.focus();\n\t\t}\n\t\t// Add widget message listeners\n\t\tthis.addEventListeners([\n\t\t\t{type: \"tm-edit-text-operation\", handler: \"handleEditTextOperationMessage\"}\n\t\t]);\n\t};\n\n\t/*\n\tGet the tiddler being edited and current value\n\t*/\n\tEditTextWidget.prototype.getEditInfo = function() {\n\t\t// Get the edit value\n\t\tvar self = this,\n\t\t\tvalue,\n\t\t\ttype = \"text/plain\",\n\t\t\tupdate;\n\t\tif(this.editIndex) {\n\t\t\tvalue = this.wiki.extractTiddlerDataItem(this.editTitle,this.editIndex,this.editDefault);\n\t\t\tupdate = function(value) {\n\t\t\t\tvar data = self.wiki.getTiddlerData(self.editTitle,{});\n\t\t\t\tif(data[self.editIndex] !== value) {\n\t\t\t\t\tdata[self.editIndex] = value;\n\t\t\t\t\tself.wiki.setTiddlerData(self.editTitle,data);\n\t\t\t\t}\n\t\t\t};\n\t\t} else {\n\t\t\t// Get the current tiddler and the field name\n\t\t\tvar tiddler = this.wiki.getTiddler(this.editTitle);\n\t\t\tif(tiddler) {\n\t\t\t\t// If we've got a tiddler, the value to display is the field string value\n\t\t\t\tvalue = tiddler.getFieldString(this.editField);\n\t\t\t\tif(this.editField === \"text\") {\n\t\t\t\t\ttype = tiddler.fields.type || \"text/vnd.tiddlywiki\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Otherwise, we need to construct a default value for the editor\n\t\t\t\tswitch(this.editField) {\n\t\t\t\t\tcase \"text\":\n\t\t\t\t\t\tvalue = \"Type the text for the tiddler '\" + this.editTitle + \"'\";\n\t\t\t\t\t\ttype = \"text/vnd.tiddlywiki\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"title\":\n\t\t\t\t\t\tvalue = this.editTitle;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tvalue = \"\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif(this.editDefault !== undefined) {\n\t\t\t\t\tvalue = this.editDefault;\n\t\t\t\t}\n\t\t\t}\n\t\t\tupdate = function(value) {\n\t\t\t\tvar tiddler = self.wiki.getTiddler(self.editTitle),\n\t\t\t\t\tupdateFields = {\n\t\t\t\t\t\ttitle: self.editTitle\n\t\t\t\t\t};\n\t\t\t\tupdateFields[self.editField] = value;\n\t\t\t\tself.wiki.addTiddler(new $tw.Tiddler(self.wiki.getCreationFields(),tiddler,updateFields,self.wiki.getModificationFields()));\n\t\t\t};\n\t\t}\n\t\tif(this.editType) {\n\t\t\ttype = this.editType;\n\t\t}\n\t\treturn {value: value || \"\", type: type, update: update};\n\t};\n\n\t/*\n\tHandle an edit text operation message from the toolbar\n\t*/\n\tEditTextWidget.prototype.handleEditTextOperationMessage = function(event) {\n\t\t// Prepare information about the operation\n\t\tvar operation = this.engine.createTextOperation();\n\t\t// Invoke the handler for the selected operation\n\t\tvar handler = this.editorOperations[event.param];\n\t\tif(handler) {\n\t\t\thandler.call(this,event,operation);\n\t\t}\n\t\t// Execute the operation via the engine\n\t\tvar newText = this.engine.executeTextOperation(operation);\n\t\t// Fix the tiddler height and save changes\n\t\tthis.engine.fixHeight();\n\t\tthis.saveChanges(newText);\n\t};\n\n\t/*\n\tCompute the internal state of the widget\n\t*/\n\tEditTextWidget.prototype.execute = function() {\n\t\t// Get our parameters\n\t\tthis.editTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t\tthis.editField = this.getAttribute(\"field\",\"text\");\n\t\tthis.editIndex = this.getAttribute(\"index\");\n\t\tthis.editDefault = this.getAttribute(\"default\");\n\t\tthis.editClass = this.getAttribute(\"class\");\n\t\tthis.editPlaceholder = this.getAttribute(\"placeholder\");\n\t\tthis.editSize = this.getAttribute(\"size\");\n\t\tthis.editRows = this.getAttribute(\"rows\");\n\t\tthis.editAutoHeight = this.wiki.getTiddlerText(HEIGHT_MODE_TITLE,\"auto\");\n\t\tthis.editAutoHeight = this.getAttribute(\"autoHeight\",this.editAutoHeight === \"auto\" ? \"yes\" : \"no\") === \"yes\";\n\t\tthis.editMinHeight = this.getAttribute(\"minHeight\",DEFAULT_MIN_TEXT_AREA_HEIGHT);\n\t\tthis.editFocusPopup = this.getAttribute(\"focusPopup\");\n\t\tthis.editFocus = this.getAttribute(\"focus\");\n\t\t// Get the default editor element tag and type\n\t\tvar tag,type;\n\t\tif(this.editField === \"text\") {\n\t\t\ttag = \"textarea\";\n\t\t} else {\n\t\t\ttag = \"input\";\n\t\t\tvar fieldModule = $tw.Tiddler.fieldModules[this.editField];\n\t\t\tif(fieldModule && fieldModule.editTag) {\n\t\t\t\ttag = fieldModule.editTag;\n\t\t\t}\n\t\t\tif(fieldModule && fieldModule.editType) {\n\t\t\t\ttype = fieldModule.editType;\n\t\t\t}\n\t\t\ttype = type || \"text\";\n\t\t}\n\t\t// Get the rest of our parameters\n\t\tthis.editTag = this.getAttribute(\"tag\",tag);\n\t\tthis.editType = this.getAttribute(\"type\",type);\n\t\t// Make the child widgets\n\t\tthis.makeChildWidgets();\n\t\t// Determine whether to show the toolbar\n\t\tthis.editShowToolbar = this.wiki.getTiddlerText(ENABLE_TOOLBAR_TITLE,\"yes\");\n\t\tthis.editShowToolbar = (this.editShowToolbar === \"yes\") && !!(this.children && this.children.length > 0);\n\t};\n\n\t/*\n\tSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n\t*/\n\tEditTextWidget.prototype.refresh = function(changedTiddlers) {\n\t\tvar changedAttributes = this.computeAttributes();\n\t\t// Completely rerender if any of our attributes have changed\n\t\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes[\"default\"] || changedAttributes[\"class\"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE]) {\n\t\t\tthis.refreshSelf();\n\t\t\treturn true;\n\t\t} else if(changedTiddlers[this.editTitle]) {\n\t\t\tvar editInfo = this.getEditInfo();\n\t\t\tthis.updateEditor(editInfo.value,editInfo.type);\n\t\t}\n\t\tthis.engine.fixHeight();\n\t\tif(this.editShowToolbar) {\n\t\t\treturn this.refreshChildren(changedTiddlers);\t\t\t\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t};\n\n\t/*\n\tUpdate the editor with new text. This method is separate from updateEditorDomNode()\n\tso that subclasses can override updateEditor() and still use updateEditorDomNode()\n\t*/\n\tEditTextWidget.prototype.updateEditor = function(text,type) {\n\t\tthis.updateEditorDomNode(text,type);\n\t};\n\n\t/*\n\tUpdate the editor dom node with new text\n\t*/\n\tEditTextWidget.prototype.updateEditorDomNode = function(text,type) {\n\t\tthis.engine.setText(text,type);\n\t};\n\n\t/*\n\tSave changes back to the tiddler store\n\t*/\n\tEditTextWidget.prototype.saveChanges = function(text) {\n\t\tvar editInfo = this.getEditInfo();\n\t\tif(text !== editInfo.value) {\n\t\t\teditInfo.update(text);\n\t\t}\n\t};\n\n\t/*\n\tHandle a dom \"keydown\" event, which we'll bubble up to our container for the keyboard widgets benefit\n\t*/\n\tEditTextWidget.prototype.handleKeydownEvent = function(event) {\n\t\t// Check for a keyboard shortcut\n\t\tif(this.toolbarNode) {\n\t\t\tvar shortcutElements = this.toolbarNode.querySelectorAll(\"[data-tw-keyboard-shortcut]\");\n\t\t\tfor(var index=0; index<shortcutElements.length; index++) {\n\t\t\t\tvar el = shortcutElements[index],\n\t\t\t\t\tshortcutData = el.getAttribute(\"data-tw-keyboard-shortcut\"),\n\t\t\t\t\tkeyInfoArray = $tw.keyboardManager.parseKeyDescriptors(shortcutData,{\n\t\t\t\t\t\twiki: this.wiki\n\t\t\t\t\t});\n\t\t\t\tif($tw.keyboardManager.checkKeyDescriptors(event,keyInfoArray)) {\n\t\t\t\t\tvar clickEvent = this.document.createEvent(\"Events\");\n\t\t\t\t clickEvent.initEvent(\"click\",true,false);\n\t\t\t\t el.dispatchEvent(clickEvent);\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\treturn true;\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Propogate the event to the container\n\t\tif(this.propogateKeydownEvent(event)) {\n\t\t\t// Ignore the keydown if it was already handled\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\treturn true;\n\t\t}\n\t\t// Otherwise, process the keydown normally\n\t\treturn false;\n\t};\n\n\t/*\n\tPropogate keydown events to our container for the keyboard widgets benefit\n\t*/\n\tEditTextWidget.prototype.propogateKeydownEvent = function(event) {\n\t\tvar newEvent = this.document.createEventObject ? this.document.createEventObject() : this.document.createEvent(\"Events\");\n\t\tif(newEvent.initEvent) {\n\t\t\tnewEvent.initEvent(\"keydown\", true, true);\n\t\t}\n\t\tnewEvent.keyCode = event.keyCode;\n\t\tnewEvent.which = event.which;\n\t\tnewEvent.metaKey = event.metaKey;\n\t\tnewEvent.ctrlKey = event.ctrlKey;\n\t\tnewEvent.altKey = event.altKey;\n\t\tnewEvent.shiftKey = event.shiftKey;\n\t\treturn !this.parentDomNode.dispatchEvent(newEvent);\n\t};\n\n\treturn EditTextWidget;\n\n}\n\nexports.editTextWidgetFactory = editTextWidgetFactory;\n\n})();\n", "title": "$:/core/modules/editor/factory.js", "type": "application/javascript", "module-type": "library" }, "$:/core/modules/editor/operations/bitmap/clear.js": { "text": "/*\\\ntitle: $:/core/modules/editor/operations/bitmap/clear.js\ntype: application/javascript\nmodule-type: bitmapeditoroperation\n\nBitmap editor operation to clear the image\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"clear\"] = function(event) {\n\tvar ctx = this.canvasDomNode.getContext(\"2d\");\n\tctx.globalAlpha = 1;\n\tctx.fillStyle = event.paramObject.colour || \"white\";\n\tctx.fillRect(0,0,this.canvasDomNode.width,this.canvasDomNode.height);\n\t// Save changes\n\tthis.strokeEnd();\n};\n\n})();\n", "title": "$:/core/modules/editor/operations/bitmap/clear.js", "type": "application/javascript", "module-type": "bitmapeditoroperation" }, "$:/core/modules/editor/operations/bitmap/resize.js": { "text": "/*\\\ntitle: $:/core/modules/editor/operations/bitmap/resize.js\ntype: application/javascript\nmodule-type: bitmapeditoroperation\n\nBitmap editor operation to resize the image\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"resize\"] = function(event) {\n\t// Get the new width\n\tvar newWidth = parseInt(event.paramObject.width || this.canvasDomNode.width,10),\n\t\tnewHeight = parseInt(event.paramObject.height || this.canvasDomNode.height,10);\n\t// Update if necessary\n\tif(newWidth > 0 && newHeight > 0 && !(newWidth === this.currCanvas.width && newHeight === this.currCanvas.height)) {\n\t\tthis.changeCanvasSize(newWidth,newHeight);\n\t}\n\t// Update the input controls\n\tthis.refreshToolbar();\n\t// Save the image into the tiddler\n\tthis.saveChanges();\n};\n\n})();\n", "title": "$:/core/modules/editor/operations/bitmap/resize.js", "type": "application/javascript", "module-type": "bitmapeditoroperation" }, "$:/core/modules/editor/operations/text/excise.js": { "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/excise.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to excise the selection to a new tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"excise\"] = function(event,operation) {\n\tvar editTiddler = this.wiki.getTiddler(this.editTitle),\n\t\teditTiddlerTitle = this.editTitle;\n\tif(editTiddler && editTiddler.fields[\"draft.of\"]) {\n\t\teditTiddlerTitle = editTiddler.fields[\"draft.of\"];\n\t}\n\tvar excisionTitle = event.paramObject.title || this.wiki.generateNewTitle(\"New Excision\");\n\tthis.wiki.addTiddler(new $tw.Tiddler(\n\t\tthis.wiki.getCreationFields(),\n\t\tthis.wiki.getModificationFields(),\n\t\t{\n\t\t\ttitle: excisionTitle,\n\t\t\ttext: operation.selection,\n\t\t\ttags: event.paramObject.tagnew === \"yes\" ? [editTiddlerTitle] : []\n\t\t}\n\t));\n\toperation.replacement = excisionTitle;\n\tswitch(event.paramObject.type || \"transclude\") {\n\t\tcase \"transclude\":\n\t\t\toperation.replacement = \"{{\" + operation.replacement+ \"}}\";\n\t\t\tbreak;\n\t\tcase \"link\":\n\t\t\toperation.replacement = \"[[\" + operation.replacement+ \"]]\";\n\t\t\tbreak;\n\t\tcase \"macro\":\n\t\t\toperation.replacement = \"<<\" + (event.paramObject.macro || \"translink\") + \" \\\"\\\"\\\"\" + operation.replacement + \"\\\"\\\"\\\">>\";\n\t\t\tbreak;\n\t}\n\toperation.cutStart = operation.selStart;\n\toperation.cutEnd = operation.selEnd;\n\toperation.newSelStart = operation.selStart;\n\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n};\n\n})();\n", "title": "$:/core/modules/editor/operations/text/excise.js", "type": "application/javascript", "module-type": "texteditoroperation" }, "$:/core/modules/editor/operations/text/make-link.js": { "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/make-link.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to make a link\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"make-link\"] = function(event,operation) {\n\tif(operation.selection) {\n\t\toperation.replacement = \"[[\" + operation.selection + \"|\" + event.paramObject.text + \"]]\";\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t} else {\n\t\toperation.replacement = \"[[\" + event.paramObject.text + \"]]\";\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t}\n\toperation.newSelStart = operation.selStart + operation.replacement.length;\n\toperation.newSelEnd = operation.newSelStart;\n};\n\n})();\n", "title": "$:/core/modules/editor/operations/text/make-link.js", "type": "application/javascript", "module-type": "texteditoroperation" }, "$:/core/modules/editor/operations/text/prefix-lines.js": { "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/prefix-lines.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to add a prefix to the selected lines\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"prefix-lines\"] = function(event,operation) {\n\t// Cut just past the preceding line break, or the start of the text\n\toperation.cutStart = $tw.utils.findPrecedingLineBreak(operation.text,operation.selStart);\n\t// Cut to just past the following line break, or to the end of the text\n\toperation.cutEnd = $tw.utils.findFollowingLineBreak(operation.text,operation.selEnd);\n\t// Compose the required prefix\n\tvar prefix = $tw.utils.repeat(event.paramObject.character,event.paramObject.count);\n\t// Process each line\n\tvar lines = operation.text.substring(operation.cutStart,operation.cutEnd).split(/\\r?\\n/mg);\n\t$tw.utils.each(lines,function(line,index) {\n\t\t// Remove and count any existing prefix characters\n\t\tvar count = 0;\n\t\twhile(line.charAt(0) === event.paramObject.character) {\n\t\t\tline = line.substring(1);\n\t\t\tcount++;\n\t\t}\n\t\t// Remove any whitespace\n\t\twhile(line.charAt(0) === \" \") {\n\t\t\tline = line.substring(1);\n\t\t}\n\t\t// We're done if we removed the exact required prefix, otherwise add it\n\t\tif(count !== event.paramObject.count) {\n\t\t\t// Apply the prefix\n\t\t\tline = prefix + \" \" + line;\n\t\t}\n\t\t// Save the modified line\n\t\tlines[index] = line;\n\t});\n\t// Stitch the replacement text together and set the selection\n\toperation.replacement = lines.join(\"\\n\");\n\tif(lines.length === 1) {\n\t\toperation.newSelStart = operation.cutStart + operation.replacement.length;\n\t\toperation.newSelEnd = operation.newSelStart;\n\t} else {\n\t\toperation.newSelStart = operation.cutStart;\n\t\toperation.newSelEnd = operation.newSelStart + operation.replacement.length;\n\t}\n};\n\n})();\n", "title": "$:/core/modules/editor/operations/text/prefix-lines.js", "type": "application/javascript", "module-type": "texteditoroperation" }, "$:/core/modules/editor/operations/text/replace-all.js": { "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/replace-all.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to replace the entire text\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"replace-all\"] = function(event,operation) {\n\toperation.cutStart = 0;\n\toperation.cutEnd = operation.text.length;\n\toperation.replacement = event.paramObject.text;\n\toperation.newSelStart = 0;\n\toperation.newSelEnd = operation.replacement.length;\n};\n\n})();\n", "title": "$:/core/modules/editor/operations/text/replace-all.js", "type": "application/javascript", "module-type": "texteditoroperation" }, "$:/core/modules/editor/operations/text/replace-selection.js": { "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/replace-selection.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to replace the selection\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"replace-selection\"] = function(event,operation) {\n\toperation.replacement = event.paramObject.text;\n\toperation.cutStart = operation.selStart;\n\toperation.cutEnd = operation.selEnd;\n\toperation.newSelStart = operation.selStart;\n\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n};\n\n})();\n", "title": "$:/core/modules/editor/operations/text/replace-selection.js", "type": "application/javascript", "module-type": "texteditoroperation" }, "$:/core/modules/editor/operations/text/wrap-lines.js": { "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/wrap-lines.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to wrap the selected lines with a prefix and suffix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"wrap-lines\"] = function(event,operation) {\n\t// Cut just past the preceding line break, or the start of the text\n\toperation.cutStart = $tw.utils.findPrecedingLineBreak(operation.text,operation.selStart);\n\t// Cut to just past the following line break, or to the end of the text\n\toperation.cutEnd = $tw.utils.findFollowingLineBreak(operation.text,operation.selEnd);\n\t// Add the prefix and suffix\n\toperation.replacement = event.paramObject.prefix + \"\\n\" +\n\t\t\t\toperation.text.substring(operation.cutStart,operation.cutEnd) + \"\\n\" +\n\t\t\t\tevent.paramObject.suffix + \"\\n\";\n\toperation.newSelStart = operation.cutStart + event.paramObject.prefix.length + 1;\n\toperation.newSelEnd = operation.newSelStart + (operation.cutEnd - operation.cutStart);\n};\n\n})();\n", "title": "$:/core/modules/editor/operations/text/wrap-lines.js", "type": "application/javascript", "module-type": "texteditoroperation" }, "$:/core/modules/editor/operations/text/wrap-selection.js": { "text": "/*\\\ntitle: $:/core/modules/editor/operations/text/wrap-selection.js\ntype: application/javascript\nmodule-type: texteditoroperation\n\nText editor operation to wrap the selection with the specified prefix and suffix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports[\"wrap-selection\"] = function(event,operation) {\n\tif(operation.selStart === operation.selEnd) {\n\t\t// No selection; check if we're within the prefix/suffix\n\t\tif(operation.text.substring(operation.selStart - event.paramObject.prefix.length,operation.selStart + event.paramObject.suffix.length) === event.paramObject.prefix + event.paramObject.suffix) {\n\t\t\t// Remove the prefix and suffix unless they comprise the entire text\n\t\t\tif(operation.selStart > event.paramObject.prefix.length || (operation.selEnd + event.paramObject.suffix.length) < operation.text.length ) {\n\t\t\t\toperation.cutStart = operation.selStart - event.paramObject.prefix.length;\n\t\t\t\toperation.cutEnd = operation.selEnd + event.paramObject.suffix.length;\n\t\t\t\toperation.replacement = \"\";\n\t\t\t\toperation.newSelStart = operation.cutStart;\n\t\t\t\toperation.newSelEnd = operation.newSelStart;\n\t\t\t}\n\t\t} else {\n\t\t\t// Wrap the cursor instead\n\t\t\toperation.cutStart = operation.selStart;\n\t\t\toperation.cutEnd = operation.selEnd;\n\t\t\toperation.replacement = event.paramObject.prefix + event.paramObject.suffix;\n\t\t\toperation.newSelStart = operation.selStart + event.paramObject.prefix.length;\n\t\t\toperation.newSelEnd = operation.newSelStart;\n\t\t}\n\t} else if(operation.text.substring(operation.selStart,operation.selStart + event.paramObject.prefix.length) === event.paramObject.prefix && operation.text.substring(operation.selEnd - event.paramObject.suffix.length,operation.selEnd) === event.paramObject.suffix) {\n\t\t// Prefix and suffix are already present, so remove them\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t\toperation.replacement = operation.selection.substring(event.paramObject.prefix.length,operation.selection.length - event.paramObject.suffix.length);\n\t\toperation.newSelStart = operation.selStart;\n\t\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n\t} else {\n\t\t// Add the prefix and suffix\n\t\toperation.cutStart = operation.selStart;\n\t\toperation.cutEnd = operation.selEnd;\n\t\toperation.replacement = event.paramObject.prefix + operation.selection + event.paramObject.suffix;\n\t\toperation.newSelStart = operation.selStart;\n\t\toperation.newSelEnd = operation.selStart + operation.replacement.length;\n\t}\n};\n\n})();\n", "title": "$:/core/modules/editor/operations/text/wrap-selection.js", "type": "application/javascript", "module-type": "texteditoroperation" }, "$:/core/modules/filters/addprefix.js": { "text": "/*\\\ntitle: $:/core/modules/filters/addprefix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for adding a prefix to each title in the list. This is\nespecially useful in contexts where only a filter expression is allowed\nand macro substitution isn't available.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.addprefix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(operator.operand + title);\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/addprefix.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/addsuffix.js": { "text": "/*\\\ntitle: $:/core/modules/filters/addsuffix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for adding a suffix to each title in the list. This is\nespecially useful in contexts where only a filter expression is allowed\nand macro substitution isn't available.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.addsuffix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title + operator.operand);\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/addsuffix.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/after.js": { "text": "/*\\\ntitle: $:/core/modules/filters/after.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler from the current list that is after the tiddler named in the operand.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.after = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\tvar index = results.indexOf(operator.operand);\n\tif(index === -1 || index > (results.length - 2)) {\n\t\treturn [];\n\t} else {\n\t\treturn [results[index + 1]];\n\t}\n};\n\n})();\n", "title": "$:/core/modules/filters/after.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/all/current.js": { "text": "/*\\\ntitle: $:/core/modules/filters/all/current.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[current]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.current = function(source,prefix,options) {\n\tvar currTiddlerTitle = options.widget && options.widget.getVariable(\"currentTiddler\");\n\tif(currTiddlerTitle) {\n\t\treturn [currTiddlerTitle];\n\t} else {\n\t\treturn [];\n\t}\n};\n\n})();\n", "title": "$:/core/modules/filters/all/current.js", "type": "application/javascript", "module-type": "allfilteroperator" }, "$:/core/modules/filters/all/missing.js": { "text": "/*\\\ntitle: $:/core/modules/filters/all/missing.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[missing]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.missing = function(source,prefix,options) {\n\treturn options.wiki.getMissingTitles();\n};\n\n})();\n", "title": "$:/core/modules/filters/all/missing.js", "type": "application/javascript", "module-type": "allfilteroperator" }, "$:/core/modules/filters/all/orphans.js": { "text": "/*\\\ntitle: $:/core/modules/filters/all/orphans.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[orphans]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.orphans = function(source,prefix,options) {\n\treturn options.wiki.getOrphanTitles();\n};\n\n})();\n", "title": "$:/core/modules/filters/all/orphans.js", "type": "application/javascript", "module-type": "allfilteroperator" }, "$:/core/modules/filters/all/shadows.js": { "text": "/*\\\ntitle: $:/core/modules/filters/all/shadows.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[shadows]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.shadows = function(source,prefix,options) {\n\treturn options.wiki.allShadowTitles();\n};\n\n})();\n", "title": "$:/core/modules/filters/all/shadows.js", "type": "application/javascript", "module-type": "allfilteroperator" }, "$:/core/modules/filters/all/tags.js": { "text": "/*\\\ntitle: $:/core/modules/filters/all/tags.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[tags]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tags = function(source,prefix,options) {\n\treturn Object.keys(options.wiki.getTagMap());\n};\n\n})();\n", "title": "$:/core/modules/filters/all/tags.js", "type": "application/javascript", "module-type": "allfilteroperator" }, "$:/core/modules/filters/all/tiddlers.js": { "text": "/*\\\ntitle: $:/core/modules/filters/all/tiddlers.js\ntype: application/javascript\nmodule-type: allfilteroperator\n\nFilter function for [all[tiddlers]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tiddlers = function(source,prefix,options) {\n\treturn options.wiki.allTitles();\n};\n\n})();\n", "title": "$:/core/modules/filters/all/tiddlers.js", "type": "application/javascript", "module-type": "allfilteroperator" }, "$:/core/modules/filters/all.js": { "text": "/*\\\ntitle: $:/core/modules/filters/all.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for selecting tiddlers\n\n[all[shadows+tiddlers]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar allFilterOperators;\n\nfunction getAllFilterOperators() {\n\tif(!allFilterOperators) {\n\t\tallFilterOperators = {};\n\t\t$tw.modules.applyMethods(\"allfilteroperator\",allFilterOperators);\n\t}\n\treturn allFilterOperators;\n}\n\n/*\nExport our filter function\n*/\nexports.all = function(source,operator,options) {\n\t// Get our suboperators\n\tvar allFilterOperators = getAllFilterOperators();\n\t// Cycle through the suboperators accumulating their results\n\tvar results = [],\n\t\tsubops = operator.operand.split(\"+\");\n\t// Check for common optimisations\n\tif(subops.length === 1 && subops[0] === \"\") {\n\t\treturn source;\n\t} else if(subops.length === 1 && subops[0] === \"tiddlers\") {\n\t\treturn options.wiki.each;\n\t} else if(subops.length === 1 && subops[0] === \"shadows\") {\n\t\treturn options.wiki.eachShadow;\n\t} else if(subops.length === 2 && subops[0] === \"tiddlers\" && subops[1] === \"shadows\") {\n\t\treturn options.wiki.eachTiddlerPlusShadows;\n\t} else if(subops.length === 2 && subops[0] === \"shadows\" && subops[1] === \"tiddlers\") {\n\t\treturn options.wiki.eachShadowPlusTiddlers;\n\t}\n\t// Do it the hard way\n\tfor(var t=0; t<subops.length; t++) {\n\t\tvar subop = allFilterOperators[subops[t]];\n\t\tif(subop) {\n\t\t\t$tw.utils.pushTop(results,subop(source,operator.prefix,options));\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/all.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/backlinks.js": { "text": "/*\\\ntitle: $:/core/modules/filters/backlinks.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning all the backlinks from a tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.backlinks = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.getTiddlerBacklinks(title));\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/backlinks.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/before.js": { "text": "/*\\\ntitle: $:/core/modules/filters/before.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler from the current list that is before the tiddler named in the operand.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.before = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\tvar index = results.indexOf(operator.operand);\n\tif(index <= 0) {\n\t\treturn [];\n\t} else {\n\t\treturn [results[index - 1]];\n\t}\n};\n\n})();\n", "title": "$:/core/modules/filters/before.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/commands.js": { "text": "/*\\\ntitle: $:/core/modules/filters/commands.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the commands available in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.commands = function(source,operator,options) {\n\tvar results = [];\n\t$tw.utils.each($tw.commands,function(commandInfo,name) {\n\t\tresults.push(name);\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/commands.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/count.js": { "text": "/*\\\ntitle: $:/core/modules/filters/count.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the number of entries in the current list.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.count = function(source,operator,options) {\n\tvar count = 0;\n\tsource(function(tiddler,title) {\n\t\tcount++;\n\t});\n\treturn [count + \"\"];\n};\n\n})();\n", "title": "$:/core/modules/filters/count.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/days.js": { "text": "/*\\\ntitle: $:/core/modules/filters/days.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects tiddlers with a specified date field within a specified date interval.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.days = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldName = operator.suffix || \"modified\",\n\t\tdayInterval = (parseInt(operator.operand,10)||0),\n\t\tdayIntervalSign = $tw.utils.sign(dayInterval),\n\t\ttargetTimeStamp = (new Date()).setHours(0,0,0,0) + 1000*60*60*24*dayInterval,\n\t\tisWithinDays = function(dateField) {\n\t\t\tvar sign = $tw.utils.sign(targetTimeStamp - (new Date(dateField)).setHours(0,0,0,0));\n\t\t\treturn sign === 0 || sign === dayIntervalSign;\n\t\t};\n\n\tif(operator.prefix === \"!\") {\n\t\ttargetTimeStamp = targetTimeStamp - 1000*60*60*24*dayIntervalSign;\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && tiddler.fields[fieldName]) {\n\t\t\t\tif(!isWithinDays($tw.utils.parseDate(tiddler.fields[fieldName]))) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && tiddler.fields[fieldName]) {\n\t\t\t\tif(isWithinDays($tw.utils.parseDate(tiddler.fields[fieldName]))) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/days.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/each.js": { "text": "/*\\\ntitle: $:/core/modules/filters/each.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects one tiddler for each unique value of the specified field.\nWith suffix \"list\", selects all tiddlers that are values in a specified list field.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.each = function(source,operator,options) {\n\tvar results =[] ,\n\t\tvalue,values = {},\n\t\tfield = operator.operand || \"title\";\n\tif(operator.suffix !== \"list-item\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler) {\n\t\t\t\tvalue = (field === \"title\") ? title : tiddler.getFieldString(field);\n\t\t\t\tif(!$tw.utils.hop(values,value)) {\n\t\t\t\t\tvalues[value] = true;\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler) {\n\t\t\t\t$tw.utils.each(\n\t\t\t\t\toptions.wiki.getTiddlerList(title,field),\n\t\t\t\t\tfunction(value) {\n\t\t\t\t\t\tif(!$tw.utils.hop(values,value)) {\n\t\t\t\t\t\t\tvalues[value] = true;\n\t\t\t\t\t\t\tresults.push(value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/each.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/eachday.js": { "text": "/*\\\ntitle: $:/core/modules/filters/eachday.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects one tiddler for each unique day covered by the specified date field\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.eachday = function(source,operator,options) {\n\tvar results = [],\n\t\tvalues = [],\n\t\tfieldName = operator.operand || \"modified\";\n\t// Function to convert a date/time to a date integer\n\tvar toDate = function(value) {\n\t\tvalue = (new Date(value)).setHours(0,0,0,0);\n\t\treturn value+0;\n\t};\n\tsource(function(tiddler,title) {\n\t\tif(tiddler && tiddler.fields[fieldName]) {\n\t\t\tvar value = toDate($tw.utils.parseDate(tiddler.fields[fieldName]));\n\t\t\tif(values.indexOf(value) === -1) {\n\t\t\t\tvalues.push(value);\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/eachday.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/editiondescription.js": { "text": "/*\\\ntitle: $:/core/modules/filters/editiondescription.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the descriptions of the specified edition names\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.editiondescription = function(source,operator,options) {\n\tvar results = [],\n\t\teditionInfo = $tw.utils.getEditionInfo();\n\tif(editionInfo) {\n\t\tsource(function(tiddler,title) {\n\t\t\tif($tw.utils.hop(editionInfo,title)) {\n\t\t\t\tresults.push(editionInfo[title].description || \"\");\t\t\t\t\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/editiondescription.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/editions.js": { "text": "/*\\\ntitle: $:/core/modules/filters/editions.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the available editions in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.editions = function(source,operator,options) {\n\tvar results = [],\n\t\teditionInfo = $tw.utils.getEditionInfo();\n\tif(editionInfo) {\n\t\t$tw.utils.each(editionInfo,function(info,name) {\n\t\t\tresults.push(name);\n\t\t});\n\t}\n\tresults.sort();\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/editions.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/decodeuricomponent.js": { "text": "/*\\\ntitle: $:/core/modules/filters/decodeuricomponent.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for applying decodeURIComponent() to each item.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter functions\n*/\n\nexports.decodeuricomponent = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(decodeURIComponent(title));\n\t});\n\treturn results;\n};\n\nexports.encodeuricomponent = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(encodeURIComponent(title));\n\t});\n\treturn results;\n};\n\nexports.decodeuri = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(decodeURI(title));\n\t});\n\treturn results;\n};\n\nexports.encodeuri = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(encodeURI(title));\n\t});\n\treturn results;\n};\n\nexports.decodehtml = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.htmlDecode(title));\n\t});\n\treturn results;\n};\n\nexports.encodehtml = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.htmlEncode(title));\n\t});\n\treturn results;\n};\n\nexports.stringify = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.stringify(title));\n\t});\n\treturn results;\n};\n\nexports.escaperegexp = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push($tw.utils.escapeRegExp(title));\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/decodeuricomponent.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/enlist.js": { "text": "/*\\\ntitle: $:/core/modules/filters/enlist.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning its operand parsed as a list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.enlist = function(source,operator,options) {\n\tvar list = $tw.utils.parseStringArray(operator.operand);\n\tif(operator.prefix === \"!\") {\n\t\tvar results = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tif(list.indexOf(title) === -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t\treturn results;\n\t} else {\n\t\treturn list;\n\t}\n};\n\n})();\n", "title": "$:/core/modules/filters/enlist.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/field.js": { "text": "/*\\\ntitle: $:/core/modules/filters/field.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for comparing fields for equality\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.field = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldname = (operator.suffix || operator.operator || \"title\").toLowerCase();\n\tif(operator.prefix === \"!\") {\n\t\tif(operator.regexp) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && !operator.regexp.exec(text)) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && text !== operator.operand) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t} else {\n\t\tif(operator.regexp) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && !!operator.regexp.exec(text)) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler) {\n\t\t\t\t\tvar text = tiddler.getFieldString(fieldname);\n\t\t\t\t\tif(text !== null && text === operator.operand) {\n\t\t\t\t\t\tresults.push(title);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/field.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/fields.js": { "text": "/*\\\ntitle: $:/core/modules/filters/fields.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the fields on the selected tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.fields = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tif(tiddler) {\n\t\t\tfor(var fieldName in tiddler.fields) {\n\t\t\t\t$tw.utils.pushTop(results,fieldName);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/fields.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/get.js": { "text": "/*\\\ntitle: $:/core/modules/filters/get.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for replacing tiddler titles by the value of the field specified in the operand.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.get = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tif(tiddler) {\n\t\t\tvar value = tiddler.getFieldString(operator.operand);\n\t\t\tif(value) {\n\t\t\t\tresults.push(value);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/get.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/getindex.js": { "text": "/*\\\ntitle: $:/core/modules/filters/getindex.js\ntype: application/javascript\nmodule-type: filteroperator\n\nreturns the value at a given index of datatiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.getindex = function(source,operator,options) {\n\tvar data,title,results = [];\n\tif(operator.operand){\n\t\tsource(function(tiddler,title) {\n\t\t\ttitle = tiddler ? tiddler.fields.title : title;\n\t\t\tdata = options.wiki.extractTiddlerDataItem(tiddler,operator.operand);\n\t\t\tif(data) {\n\t\t\t\tresults.push(data);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/getindex.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/has.js": { "text": "/*\\\ntitle: $:/core/modules/filters/has.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking if a tiddler has the specified field\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.has = function(source,operator,options) {\n\tvar results = [],\n\t\tinvert = operator.prefix === \"!\";\n\n\tif(operator.suffix === \"field\") {\n\t\tif(invert) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(!tiddler || (tiddler && (!$tw.utils.hop(tiddler.fields,operator.operand)))) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && $tw.utils.hop(tiddler.fields,operator.operand)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t} else {\n\t\tif(invert) {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(!tiddler || !$tw.utils.hop(tiddler.fields,operator.operand) || (tiddler.fields[operator.operand] === \"\")) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && $tw.utils.hop(tiddler.fields,operator.operand) && !(tiddler.fields[operator.operand] === \"\" || tiddler.fields[operator.operand].length === 0)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/has.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/haschanged.js": { "text": "/*\\\ntitle: $:/core/modules/filters/haschanged.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returns tiddlers from the list that have a non-zero changecount.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.haschanged = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.getChangeCount(title) === 0) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.getChangeCount(title) > 0) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/haschanged.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/indexes.js": { "text": "/*\\\ntitle: $:/core/modules/filters/indexes.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the indexes of a data tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.indexes = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar data = options.wiki.getTiddlerDataCached(title);\n\t\tif(data) {\n\t\t\t$tw.utils.pushTop(results,Object.keys(data));\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/indexes.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/insertbefore.js": { "text": "/*\\\ntitle: $:/core/modules/filters/insertbefore.js\ntype: application/javascript\nmodule-type: filteroperator\n\nInsert an item before another item in a list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nOrder a list\n*/\nexports.insertbefore = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\tvar target = options.widget && options.widget.getVariable(operator.suffix || \"currentTiddler\");\n\tif(target !== operator.operand) {\n\t\t// Remove the entry from the list if it is present\n\t\tvar pos = results.indexOf(operator.operand);\n\t\tif(pos !== -1) {\n\t\t\tresults.splice(pos,1);\n\t\t}\n\t\t// Insert the entry before the target marker\n\t\tpos = results.indexOf(target);\n\t\tif(pos !== -1) {\n\t\t\tresults.splice(pos,0,operator.operand);\n\t\t} else {\n\t\t\tresults.push(operator.operand);\n\t\t}\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/insertbefore.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/is/current.js": { "text": "/*\\\ntitle: $:/core/modules/filters/is/current.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[current]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.current = function(source,prefix,options) {\n\tvar results = [],\n\t\tcurrTiddlerTitle = options.widget && options.widget.getVariable(\"currentTiddler\");\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title !== currTiddlerTitle) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title === currTiddlerTitle) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/is/current.js", "type": "application/javascript", "module-type": "isfilteroperator" }, "$:/core/modules/filters/is/image.js": { "text": "/*\\\ntitle: $:/core/modules/filters/is/image.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[image]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.image = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.isImageTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.isImageTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/is/image.js", "type": "application/javascript", "module-type": "isfilteroperator" }, "$:/core/modules/filters/is/missing.js": { "text": "/*\\\ntitle: $:/core/modules/filters/is/missing.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[missing]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.missing = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/is/missing.js", "type": "application/javascript", "module-type": "isfilteroperator" }, "$:/core/modules/filters/is/orphan.js": { "text": "/*\\\ntitle: $:/core/modules/filters/is/orphan.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[orphan]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.orphan = function(source,prefix,options) {\n\tvar results = [],\n\t\torphanTitles = options.wiki.getOrphanTitles();\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(orphanTitles.indexOf(title) === -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(orphanTitles.indexOf(title) !== -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/is/orphan.js", "type": "application/javascript", "module-type": "isfilteroperator" }, "$:/core/modules/filters/is/shadow.js": { "text": "/*\\\ntitle: $:/core/modules/filters/is/shadow.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[shadow]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.shadow = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.isShadowTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.isShadowTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/is/shadow.js", "type": "application/javascript", "module-type": "isfilteroperator" }, "$:/core/modules/filters/is/system.js": { "text": "/*\\\ntitle: $:/core/modules/filters/is/system.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[system]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.system = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.isSystemTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.isSystemTiddler(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/is/system.js", "type": "application/javascript", "module-type": "isfilteroperator" }, "$:/core/modules/filters/is/tag.js": { "text": "/*\\\ntitle: $:/core/modules/filters/is/tag.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[tag]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tag = function(source,prefix,options) {\n\tvar results = [],\n\t\ttagMap = options.wiki.getTagMap();\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!$tw.utils.hop(tagMap,title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif($tw.utils.hop(tagMap,title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/is/tag.js", "type": "application/javascript", "module-type": "isfilteroperator" }, "$:/core/modules/filters/is/tiddler.js": { "text": "/*\\\ntitle: $:/core/modules/filters/is/tiddler.js\ntype: application/javascript\nmodule-type: isfilteroperator\n\nFilter function for [is[tiddler]]\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tiddler = function(source,prefix,options) {\n\tvar results = [];\n\tif(prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(options.wiki.tiddlerExists(title)) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/is/tiddler.js", "type": "application/javascript", "module-type": "isfilteroperator" }, "$:/core/modules/filters/is.js": { "text": "/*\\\ntitle: $:/core/modules/filters/is.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking tiddler properties\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar isFilterOperators;\n\nfunction getIsFilterOperators() {\n\tif(!isFilterOperators) {\n\t\tisFilterOperators = {};\n\t\t$tw.modules.applyMethods(\"isfilteroperator\",isFilterOperators);\n\t}\n\treturn isFilterOperators;\n}\n\n/*\nExport our filter function\n*/\nexports.is = function(source,operator,options) {\n\t// Dispatch to the correct isfilteroperator\n\tvar isFilterOperators = getIsFilterOperators();\n\tif(operator.operand) {\n\t\tvar isFilterOperator = isFilterOperators[operator.operand];\n\t\tif(isFilterOperator) {\n\t\t\treturn isFilterOperator(source,operator.prefix,options);\n\t\t} else {\n\t\t\treturn [$tw.language.getString(\"Error/IsFilterOperator\")];\n\t\t}\n\t} else {\n\t\t// Return all tiddlers if the operand is missing\n\t\tvar results = [];\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.push(title);\n\t\t});\n\t\treturn results;\n\t}\n};\n\n})();\n", "title": "$:/core/modules/filters/is.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/limit.js": { "text": "/*\\\ntitle: $:/core/modules/filters/limit.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for chopping the results to a specified maximum number of entries\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.limit = function(source,operator,options) {\n\tvar results = [];\n\t// Convert to an array\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\t// Slice the array if necessary\n\tvar limit = Math.min(results.length,parseInt(operator.operand,10));\n\tif(operator.prefix === \"!\") {\n\t\tresults = results.slice(-limit);\n\t} else {\n\t\tresults = results.slice(0,limit);\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/limit.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/links.js": { "text": "/*\\\ntitle: $:/core/modules/filters/links.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning all the links from a tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.links = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.getTiddlerLinks(title));\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/links.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/list.js": { "text": "/*\\\ntitle: $:/core/modules/filters/list.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddlers whose title is listed in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.list = function(source,operator,options) {\n\tvar results = [],\n\t\ttr = $tw.utils.parseTextReference(operator.operand),\n\t\tcurrTiddlerTitle = options.widget && options.widget.getVariable(\"currentTiddler\"),\n\t\tlist = options.wiki.getTiddlerList(tr.title || currTiddlerTitle,tr.field,tr.index);\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(list.indexOf(title) === -1) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tresults = list;\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/list.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/listed.js": { "text": "/*\\\ntitle: $:/core/modules/filters/listed.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all tiddlers that have the selected tiddlers in a list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.listed = function(source,operator,options) {\n\tvar field = operator.operand || \"list\",\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.findListingsOfTiddler(title,field));\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/listed.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/listops.js": { "text": "/*\\\ntitle: $:/core/modules/filters/listops.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operators for manipulating the current selection list\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nOrder a list\n*/\nexports.order = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.operand.toLowerCase() === \"reverse\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.unshift(title);\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.push(title);\n\t\t});\t\t\n\t}\n\treturn results;\n};\n\n/*\nReverse list\n*/\nexports.reverse = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.unshift(title);\n\t});\n\treturn results;\n};\n\n/*\nFirst entry/entries in list\n*/\nexports.first = function(source,operator,options) {\n\tvar count = parseInt(operator.operand) || 1,\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(0,count);\n};\n\n/*\nLast entry/entries in list\n*/\nexports.last = function(source,operator,options) {\n\tvar count = parseInt(operator.operand) || 1,\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(-count);\n};\n\n/*\nAll but the first entry/entries of the list\n*/\nexports.rest = function(source,operator,options) {\n\tvar count = parseInt(operator.operand) || 1,\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(count);\n};\nexports.butfirst = exports.rest;\nexports.bf = exports.rest;\n\n/*\nAll but the last entry/entries of the list\n*/\nexports.butlast = function(source,operator,options) {\n\tvar count = parseInt(operator.operand) || 1,\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(0,-count);\n};\nexports.bl = exports.butlast;\n\n/*\nThe nth member of the list\n*/\nexports.nth = function(source,operator,options) {\n\tvar count = parseInt(operator.operand) || 1,\n\t\tresults = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results.slice(count - 1,count);\n};\n\n})();\n", "title": "$:/core/modules/filters/listops.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/minlength.js": { "text": "/*\\\ntitle: $:/core/modules/filters/minlength.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for filtering out titles that don't meet the minimum length in the operand\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.minlength = function(source,operator,options) {\n\tvar results = [],\n\t\tminLength = parseInt(operator.operand || \"\",10) || 0;\n\tsource(function(tiddler,title) {\n\t\tif(title.length >= minLength) {\n\t\t\tresults.push(title);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/minlength.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/modules.js": { "text": "/*\\\ntitle: $:/core/modules/filters/modules.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the titles of the modules of a given type in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.modules = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {\n\t\t\tresults.push(moduleName);\n\t\t});\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/modules.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/moduletypes.js": { "text": "/*\\\ntitle: $:/core/modules/filters/moduletypes.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the module types in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.moduletypes = function(source,operator,options) {\n\tvar results = [];\n\t$tw.utils.each($tw.modules.types,function(moduleInfo,type) {\n\t\tresults.push(type);\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/moduletypes.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/next.js": { "text": "/*\\\ntitle: $:/core/modules/filters/next.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler whose title occurs next in the list supplied in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.next = function(source,operator,options) {\n\tvar results = [],\n\t\tlist = options.wiki.getTiddlerList(operator.operand);\n\tsource(function(tiddler,title) {\n\t\tvar match = list.indexOf(title);\n\t\t// increment match and then test if result is in range\n\t\tmatch++;\n\t\tif(match > 0 && match < list.length) {\n\t\t\tresults.push(list[match]);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/next.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/plugintiddlers.js": { "text": "/*\\\ntitle: $:/core/modules/filters/plugintiddlers.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the titles of the shadow tiddlers within a plugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.plugintiddlers = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar pluginInfo = options.wiki.getPluginInfo(title) || options.wiki.getTiddlerDataCached(title,{tiddlers:[]});\n\t\tif(pluginInfo && pluginInfo.tiddlers) {\n\t\t\t$tw.utils.each(pluginInfo.tiddlers,function(fields,title) {\n\t\t\t\tresults.push(title);\n\t\t\t});\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/plugintiddlers.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/prefix.js": { "text": "/*\\\ntitle: $:/core/modules/filters/prefix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking if a title starts with a prefix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.prefix = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(0,operator.operand.length) !== operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(0,operator.operand.length) === operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/prefix.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/previous.js": { "text": "/*\\\ntitle: $:/core/modules/filters/previous.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning the tiddler whose title occurs immediately prior in the list supplied in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.previous = function(source,operator,options) {\n\tvar results = [],\n\t\tlist = options.wiki.getTiddlerList(operator.operand);\n\tsource(function(tiddler,title) {\n\t\tvar match = list.indexOf(title);\n\t\t// increment match and then test if result is in range\n\t\tmatch--;\n\t\tif(match >= 0) {\n\t\t\tresults.push(list[match]);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/previous.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/regexp.js": { "text": "/*\\\ntitle: $:/core/modules/filters/regexp.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for regexp matching\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.regexp = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldname = (operator.suffix || \"title\").toLowerCase(),\n\t\tregexpString, regexp, flags = \"\", match,\n\t\tgetFieldString = function(tiddler,title) {\n\t\t\tif(tiddler) {\n\t\t\t\treturn tiddler.getFieldString(fieldname);\n\t\t\t} else if(fieldname === \"title\") {\n\t\t\t\treturn title;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t};\n\t// Process flags and construct regexp\n\tregexpString = operator.operand;\n\tmatch = /^\\(\\?([gim]+)\\)/.exec(regexpString);\n\tif(match) {\n\t\tflags = match[1];\n\t\tregexpString = regexpString.substr(match[0].length);\n\t} else {\n\t\tmatch = /\\(\\?([gim]+)\\)$/.exec(regexpString);\n\t\tif(match) {\n\t\t\tflags = match[1];\n\t\t\tregexpString = regexpString.substr(0,regexpString.length - match[0].length);\n\t\t}\n\t}\n\ttry {\n\t\tregexp = new RegExp(regexpString,flags);\n\t} catch(e) {\n\t\treturn [\"\" + e];\n\t}\n\t// Process the incoming tiddlers\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tvar text = getFieldString(tiddler,title);\n\t\t\tif(text !== null) {\n\t\t\t\tif(!regexp.exec(text)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tvar text = getFieldString(tiddler,title);\n\t\t\tif(text !== null) {\n\t\t\t\tif(!!regexp.exec(text)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/regexp.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/removeprefix.js": { "text": "/*\\\ntitle: $:/core/modules/filters/removeprefix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for removing a prefix from each title in the list. Titles that do not start with the prefix are removed.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.removeprefix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tif(title.substr(0,operator.operand.length) === operator.operand) {\n\t\t\tresults.push(title.substr(operator.operand.length));\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/removeprefix.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/removesuffix.js": { "text": "/*\\\ntitle: $:/core/modules/filters/removesuffix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for removing a suffix from each title in the list. Titles that do not end with the suffix are removed.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.removesuffix = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tif(title.substr(-operator.operand.length) === operator.operand) {\n\t\t\tresults.push(title.substr(0,title.length - operator.operand.length));\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/removesuffix.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/sameday.js": { "text": "/*\\\ntitle: $:/core/modules/filters/sameday.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that selects tiddlers with a modified date field on the same day as the provided value.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.sameday = function(source,operator,options) {\n\tvar results = [],\n\t\tfieldName = operator.suffix || \"modified\",\n\t\ttargetDate = (new Date($tw.utils.parseDate(operator.operand))).setHours(0,0,0,0);\n\t// Function to convert a date/time to a date integer\n\tsource(function(tiddler,title) {\n\t\tif(tiddler) {\n\t\t\tif(tiddler.getFieldDay(fieldName) === targetDate) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/sameday.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/search.js": { "text": "/*\\\ntitle: $:/core/modules/filters/search.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for searching for the text in the operand tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.search = function(source,operator,options) {\n\tvar invert = operator.prefix === \"!\";\n\tif(operator.suffix) {\n\t\treturn options.wiki.search(operator.operand,{\n\t\t\tsource: source,\n\t\t\tinvert: invert,\n\t\t\tfield: operator.suffix\n\t\t});\n\t} else {\n\t\treturn options.wiki.search(operator.operand,{\n\t\t\tsource: source,\n\t\t\tinvert: invert\n\t\t});\n\t}\n};\n\n})();\n", "title": "$:/core/modules/filters/search.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/shadowsource.js": { "text": "/*\\\ntitle: $:/core/modules/filters/shadowsource.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the source plugins for shadow tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.shadowsource = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar source = options.wiki.getShadowSource(title);\n\t\tif(source) {\n\t\t\t$tw.utils.pushTop(results,source);\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/shadowsource.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/sort.js": { "text": "/*\\\ntitle: $:/core/modules/filters/sort.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for sorting\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.sort = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",false,false);\n\treturn results;\n};\n\nexports.nsort = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",false,true);\n\treturn results;\n};\n\nexports.sortcs = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",true,false);\n\treturn results;\n};\n\nexports.nsortcs = function(source,operator,options) {\n\tvar results = prepare_results(source);\n\toptions.wiki.sortTiddlers(results,operator.operand || \"title\",operator.prefix === \"!\",true,true);\n\treturn results;\n};\n\nvar prepare_results = function (source) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tresults.push(title);\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/sort.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/splitbefore.js": { "text": "/*\\\ntitle: $:/core/modules/filters/splitbefore.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator that splits each result on the first occurance of the specified separator and returns the unique values.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.splitbefore = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\tvar parts = title.split(operator.operand);\n\t\tif(parts.length === 1) {\n\t\t\t$tw.utils.pushTop(results,parts[0]);\n\t\t} else {\n\t\t\t$tw.utils.pushTop(results,parts[0] + operator.operand);\n\t\t}\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/splitbefore.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/storyviews.js": { "text": "/*\\\ntitle: $:/core/modules/filters/storyviews.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the story views in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.storyviews = function(source,operator,options) {\n\tvar results = [],\n\t\tstoryviews = {};\n\t$tw.modules.applyMethods(\"storyview\",storyviews);\n\t$tw.utils.each(storyviews,function(info,name) {\n\t\tresults.push(name);\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/storyviews.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/suffix.js": { "text": "/*\\\ntitle: $:/core/modules/filters/suffix.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking if a title ends with a suffix\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.suffix = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(-operator.operand.length) !== operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(title.substr(-operator.operand.length) === operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/suffix.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/tag.js": { "text": "/*\\\ntitle: $:/core/modules/filters/tag.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for checking for the presence of a tag\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tag = function(source,operator,options) {\n\tvar results = [];\n\tif((operator.suffix || \"\").toLowerCase() === \"strict\" && !operator.operand) {\n\t\t// New semantics:\n\t\t// Always return copy of input if operator.operand is missing\n\t\tsource(function(tiddler,title) {\n\t\t\tresults.push(title);\n\t\t});\n\t} else {\n\t\t// Old semantics:\n\t\tif(operator.prefix === \"!\") {\n\t\t\t// Returns a copy of the input if operator.operand is missing\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && !tiddler.hasTag(operator.operand)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\t// Returns empty results if operator.operand is missing\n\t\t\tsource(function(tiddler,title) {\n\t\t\t\tif(tiddler && tiddler.hasTag(operator.operand)) {\n\t\t\t\t\tresults.push(title);\n\t\t\t\t}\n\t\t\t});\n\t\t\tresults = options.wiki.sortByList(results,operator.operand);\n\t\t}\t\t\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/tag.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/tagging.js": { "text": "/*\\\ntitle: $:/core/modules/filters/tagging.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all tiddlers that are tagged with the selected tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tagging = function(source,operator,options) {\n\tvar results = [];\n\tsource(function(tiddler,title) {\n\t\t$tw.utils.pushTop(results,options.wiki.getTiddlersWithTag(title));\n\t});\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/tagging.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/tags.js": { "text": "/*\\\ntitle: $:/core/modules/filters/tags.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all the tags of the selected tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.tags = function(source,operator,options) {\n\tvar tags = {};\n\tsource(function(tiddler,title) {\n\t\tvar t, length;\n\t\tif(tiddler && tiddler.fields.tags) {\n\t\t\tfor(t=0, length=tiddler.fields.tags.length; t<length; t++) {\n\t\t\t\ttags[tiddler.fields.tags[t]] = true;\n\t\t\t}\n\t\t}\n\t});\n\treturn Object.keys(tags);\n};\n\n})();\n", "title": "$:/core/modules/filters/tags.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/title.js": { "text": "/*\\\ntitle: $:/core/modules/filters/title.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for comparing title fields for equality\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.title = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && tiddler.fields.title !== operator.operand) {\n\t\t\t\tresults.push(title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tresults.push(operator.operand);\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/title.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/untagged.js": { "text": "/*\\\ntitle: $:/core/modules/filters/untagged.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator returning all the selected tiddlers that are untagged\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.untagged = function(source,operator,options) {\n\tvar results = [];\n\tif(operator.prefix === \"!\") {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(tiddler && $tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length > 0) {\n\t\t\t\t$tw.utils.pushTop(results,title);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tsource(function(tiddler,title) {\n\t\t\tif(!tiddler || !tiddler.hasField(\"tags\") || ($tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length === 0)) {\n\t\t\t\t$tw.utils.pushTop(results,title);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/untagged.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/wikiparserrules.js": { "text": "/*\\\ntitle: $:/core/modules/filters/wikiparserrules.js\ntype: application/javascript\nmodule-type: filteroperator\n\nFilter operator for returning the names of the wiki parser rules in this wiki\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nExport our filter function\n*/\nexports.wikiparserrules = function(source,operator,options) {\n\tvar results = [],\n\t\toperand = operator.operand;\n\t$tw.utils.each($tw.modules.types.wikirule,function(mod) {\n\t\tvar exp = mod.exports;\n\t\tif(!operand || exp.types[operand]) {\n\t\t\tresults.push(exp.name);\n\t\t}\n\t});\n\tresults.sort();\n\treturn results;\n};\n\n})();\n", "title": "$:/core/modules/filters/wikiparserrules.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters/x-listops.js": { "text": "/*\\\ntitle: $:/core/modules/filters/x-listops.js\ntype: application/javascript\nmodule-type: filteroperator\n\nExtended filter operators to manipulate the current list.\n\n\\*/\n(function () {\n\n /*jslint node: true, browser: true */\n /*global $tw: false */\n \"use strict\";\n\n /*\n Fetch titles from the current list\n */\n var prepare_results = function (source) {\n var results = [];\n source(function (tiddler, title) {\n results.push(title);\n });\n return results;\n };\n\n /*\n Moves a number of items from the tail of the current list before the item named in the operand\n */\n exports.putbefore = function (source, operator) {\n var results = prepare_results(source),\n index = results.indexOf(operator.operand),\n count = parseInt(operator.suffix) || 1;\n return (index === -1) ?\n results.slice(0, -1) :\n results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index, -count));\n };\n\n /*\n Moves a number of items from the tail of the current list after the item named in the operand\n */\n exports.putafter = function (source, operator) {\n var results = prepare_results(source),\n index = results.indexOf(operator.operand),\n count = parseInt(operator.suffix) || 1;\n return (index === -1) ?\n results.slice(0, -1) :\n results.slice(0, index + 1).concat(results.slice(-count)).concat(results.slice(index + 1, -count));\n };\n\n /*\n Replaces the item named in the operand with a number of items from the tail of the current list\n */\n exports.replace = function (source, operator) {\n var results = prepare_results(source),\n index = results.indexOf(operator.operand),\n count = parseInt(operator.suffix) || 1;\n return (index === -1) ?\n results.slice(0, -count) :\n results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index + 1, -count));\n };\n\n /*\n Moves a number of items from the tail of the current list to the head of the list\n */\n exports.putfirst = function (source, operator) {\n var results = prepare_results(source),\n count = parseInt(operator.suffix) || 1;\n return results.slice(-count).concat(results.slice(0, -count));\n };\n\n /*\n Moves a number of items from the head of the current list to the tail of the list\n */\n exports.putlast = function (source, operator) {\n var results = prepare_results(source),\n count = parseInt(operator.suffix) || 1;\n return results.slice(count).concat(results.slice(0, count));\n };\n\n /*\n Moves the item named in the operand a number of places forward or backward in the list\n */\n exports.move = function (source, operator) {\n var results = prepare_results(source),\n index = results.indexOf(operator.operand),\n count = parseInt(operator.suffix) || 1,\n marker = results.splice(index, 1),\n offset = (index + count) > 0 ? index + count : 0;\n return results.slice(0, offset).concat(marker).concat(results.slice(offset));\n };\n\n /*\n Returns the items from the current list that are after the item named in the operand\n */\n exports.allafter = function (source, operator) {\n var results = prepare_results(source),\n index = results.indexOf(operator.operand);\n return (index === -1 || index > (results.length - 2)) ? [] :\n (operator.suffix) ? results.slice(index) :\n results.slice(index + 1);\n };\n\n /*\n Returns the items from the current list that are before the item named in the operand\n */\n exports.allbefore = function (source, operator) {\n var results = prepare_results(source),\n index = results.indexOf(operator.operand);\n return (index <= 0) ? [] :\n (operator.suffix) ? results.slice(0, index + 1) :\n results.slice(0, index);\n };\n\n /*\n Appends the items listed in the operand array to the tail of the current list\n */\n exports.append = function (source, operator) {\n var append = $tw.utils.parseStringArray(operator.operand, \"true\"),\n results = prepare_results(source),\n count = parseInt(operator.suffix) || append.length;\n return (append.length === 0) ? results :\n (operator.prefix) ? results.concat(append.slice(-count)) :\n results.concat(append.slice(0, count));\n };\n\n /*\n Prepends the items listed in the operand array to the head of the current list\n */\n exports.prepend = function (source, operator) {\n var prepend = $tw.utils.parseStringArray(operator.operand, \"true\"),\n results = prepare_results(source),\n count = parseInt(operator.suffix) || prepend.length;\n return (prepend.length === 0) ? results :\n (operator.prefix) ? prepend.slice(-count).concat(results) :\n prepend.slice(0, count).concat(results);\n };\n\n /*\n Returns all items from the current list except the items listed in the operand array\n */\n exports.remove = function (source, operator) {\n var array = $tw.utils.parseStringArray(operator.operand, \"true\"),\n results = prepare_results(source),\n count = parseInt(operator.suffix) || array.length,\n p,\n len,\n index;\n len = array.length - 1;\n for (p = 0; p < count; ++p) {\n if (operator.prefix) {\n index = results.indexOf(array[len - p]);\n } else {\n index = results.indexOf(array[p]);\n }\n if (index !== -1) {\n results.splice(index, 1);\n }\n }\n return results;\n };\n\n /*\n Returns all items from the current list sorted in the order of the items in the operand array\n */\n exports.sortby = function (source, operator) {\n var results = prepare_results(source);\n if (!results || results.length < 2) {\n return results;\n }\n var lookup = $tw.utils.parseStringArray(operator.operand, \"true\");\n results.sort(function (a, b) {\n return lookup.indexOf(a) - lookup.indexOf(b);\n });\n return results;\n };\n\n /*\n Removes all duplicate items from the current list\n */\n exports.unique = function (source, operator) {\n var results = prepare_results(source);\n var set = results.reduce(function (a, b) {\n if (a.indexOf(b) < 0) {\n a.push(b);\n }\n return a;\n }, []);\n return set;\n };\n})();\n", "title": "$:/core/modules/filters/x-listops.js", "type": "application/javascript", "module-type": "filteroperator" }, "$:/core/modules/filters.js": { "text": "/*\\\ntitle: $:/core/modules/filters.js\ntype: application/javascript\nmodule-type: wikimethod\n\nAdds tiddler filtering methods to the $tw.Wiki object.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nParses an operation (i.e. a run) within a filter string\n\toperators: Array of array of operator nodes into which results should be inserted\n\tfilterString: filter string\n\tp: start position within the string\nReturns the new start position, after the parsed operation\n*/\nfunction parseFilterOperation(operators,filterString,p) {\n\tvar nextBracketPos, operator;\n\t// Skip the starting square bracket\n\tif(filterString.charAt(p++) !== \"[\") {\n\t\tthrow \"Missing [ in filter expression\";\n\t}\n\t// Process each operator in turn\n\tdo {\n\t\toperator = {};\n\t\t// Check for an operator prefix\n\t\tif(filterString.charAt(p) === \"!\") {\n\t\t\toperator.prefix = filterString.charAt(p++);\n\t\t}\n\t\t// Get the operator name\n\t\tnextBracketPos = filterString.substring(p).search(/[\\[\\{<\\/]/);\n\t\tif(nextBracketPos === -1) {\n\t\t\tthrow \"Missing [ in filter expression\";\n\t\t}\n\t\tnextBracketPos += p;\n\t\tvar bracket = filterString.charAt(nextBracketPos);\n\t\toperator.operator = filterString.substring(p,nextBracketPos);\n\n\t\t// Any suffix?\n\t\tvar colon = operator.operator.indexOf(':');\n\t\tif(colon > -1) {\n\t\t\toperator.suffix = operator.operator.substring(colon + 1);\n\t\t\toperator.operator = operator.operator.substring(0,colon) || \"field\";\n\t\t}\n\t\t// Empty operator means: title\n\t\telse if(operator.operator === \"\") {\n\t\t\toperator.operator = \"title\";\n\t\t}\n\n\t\tp = nextBracketPos + 1;\n\t\tswitch (bracket) {\n\t\t\tcase \"{\": // Curly brackets\n\t\t\t\toperator.indirect = true;\n\t\t\t\tnextBracketPos = filterString.indexOf(\"}\",p);\n\t\t\t\tbreak;\n\t\t\tcase \"[\": // Square brackets\n\t\t\t\tnextBracketPos = filterString.indexOf(\"]\",p);\n\t\t\t\tbreak;\n\t\t\tcase \"<\": // Angle brackets\n\t\t\t\toperator.variable = true;\n\t\t\t\tnextBracketPos = filterString.indexOf(\">\",p);\n\t\t\t\tbreak;\n\t\t\tcase \"/\": // regexp brackets\n\t\t\t\tvar rex = /^((?:[^\\\\\\/]*|\\\\.)*)\\/(?:\\(([mygi]+)\\))?/g,\n\t\t\t\t\trexMatch = rex.exec(filterString.substring(p));\n\t\t\t\tif(rexMatch) {\n\t\t\t\t\toperator.regexp = new RegExp(rexMatch[1], rexMatch[2]);\n// DEPRECATION WARNING\nconsole.log(\"WARNING: Filter\",operator.operator,\"has a deprecated regexp operand\",operator.regexp);\n\t\t\t\t\tnextBracketPos = p + rex.lastIndex - 1;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthrow \"Unterminated regular expression in filter expression\";\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif(nextBracketPos === -1) {\n\t\t\tthrow \"Missing closing bracket in filter expression\";\n\t\t}\n\t\tif(!operator.regexp) {\n\t\t\toperator.operand = filterString.substring(p,nextBracketPos);\n\t\t}\n\t\tp = nextBracketPos + 1;\n\n\t\t// Push this operator\n\t\toperators.push(operator);\n\t} while(filterString.charAt(p) !== \"]\");\n\t// Skip the ending square bracket\n\tif(filterString.charAt(p++) !== \"]\") {\n\t\tthrow \"Missing ] in filter expression\";\n\t}\n\t// Return the parsing position\n\treturn p;\n}\n\n/*\nParse a filter string\n*/\nexports.parseFilter = function(filterString) {\n\tfilterString = filterString || \"\";\n\tvar results = [], // Array of arrays of operator nodes {operator:,operand:}\n\t\tp = 0, // Current position in the filter string\n\t\tmatch;\n\tvar whitespaceRegExp = /(\\s+)/mg,\n\t\toperandRegExp = /((?:\\+|\\-)?)(?:(\\[)|(?:\"([^\"]*)\")|(?:'([^']*)')|([^\\s\\[\\]]+))/mg;\n\twhile(p < filterString.length) {\n\t\t// Skip any whitespace\n\t\twhitespaceRegExp.lastIndex = p;\n\t\tmatch = whitespaceRegExp.exec(filterString);\n\t\tif(match && match.index === p) {\n\t\t\tp = p + match[0].length;\n\t\t}\n\t\t// Match the start of the operation\n\t\tif(p < filterString.length) {\n\t\t\toperandRegExp.lastIndex = p;\n\t\t\tmatch = operandRegExp.exec(filterString);\n\t\t\tif(!match || match.index !== p) {\n\t\t\t\tthrow $tw.language.getString(\"Error/FilterSyntax\");\n\t\t\t}\n\t\t\tvar operation = {\n\t\t\t\tprefix: \"\",\n\t\t\t\toperators: []\n\t\t\t};\n\t\t\tif(match[1]) {\n\t\t\t\toperation.prefix = match[1];\n\t\t\t\tp++;\n\t\t\t}\n\t\t\tif(match[2]) { // Opening square bracket\n\t\t\t\tp = parseFilterOperation(operation.operators,filterString,p);\n\t\t\t} else {\n\t\t\t\tp = match.index + match[0].length;\n\t\t\t}\n\t\t\tif(match[3] || match[4] || match[5]) { // Double quoted string, single quoted string or unquoted title\n\t\t\t\toperation.operators.push(\n\t\t\t\t\t{operator: \"title\", operand: match[3] || match[4] || match[5]}\n\t\t\t\t);\n\t\t\t}\n\t\t\tresults.push(operation);\n\t\t}\n\t}\n\treturn results;\n};\n\nexports.getFilterOperators = function() {\n\tif(!this.filterOperators) {\n\t\t$tw.Wiki.prototype.filterOperators = {};\n\t\t$tw.modules.applyMethods(\"filteroperator\",this.filterOperators);\n\t}\n\treturn this.filterOperators;\n};\n\nexports.filterTiddlers = function(filterString,widget,source) {\n\tvar fn = this.compileFilter(filterString);\n\treturn fn.call(this,source,widget);\n};\n\n/*\nCompile a filter into a function with the signature fn(source,widget) where:\nsource: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title)\nwidget: an optional widget node for retrieving the current tiddler etc.\n*/\nexports.compileFilter = function(filterString) {\n\tvar filterParseTree;\n\ttry {\n\t\tfilterParseTree = this.parseFilter(filterString);\n\t} catch(e) {\n\t\treturn function(source,widget) {\n\t\t\treturn [$tw.language.getString(\"Error/Filter\") + \": \" + e];\n\t\t};\n\t}\n\t// Get the hashmap of filter operator functions\n\tvar filterOperators = this.getFilterOperators();\n\t// Assemble array of functions, one for each operation\n\tvar operationFunctions = [];\n\t// Step through the operations\n\tvar self = this;\n\t$tw.utils.each(filterParseTree,function(operation) {\n\t\t// Create a function for the chain of operators in the operation\n\t\tvar operationSubFunction = function(source,widget) {\n\t\t\tvar accumulator = source,\n\t\t\t\tresults = [],\n\t\t\t\tcurrTiddlerTitle = widget && widget.getVariable(\"currentTiddler\");\n\t\t\t$tw.utils.each(operation.operators,function(operator) {\n\t\t\t\tvar operand = operator.operand,\n\t\t\t\t\toperatorFunction;\n\t\t\t\tif(!operator.operator) {\n\t\t\t\t\toperatorFunction = filterOperators.title;\n\t\t\t\t} else if(!filterOperators[operator.operator]) {\n\t\t\t\t\toperatorFunction = filterOperators.field;\n\t\t\t\t} else {\n\t\t\t\t\toperatorFunction = filterOperators[operator.operator];\n\t\t\t\t}\n\t\t\t\tif(operator.indirect) {\n\t\t\t\t\toperand = self.getTextReference(operator.operand,\"\",currTiddlerTitle);\n\t\t\t\t}\n\t\t\t\tif(operator.variable) {\n\t\t\t\t\toperand = widget.getVariable(operator.operand,{defaultValue: \"\"});\n\t\t\t\t}\n\t\t\t\t// Invoke the appropriate filteroperator module\n\t\t\t\tresults = operatorFunction(accumulator,{\n\t\t\t\t\t\t\toperator: operator.operator,\n\t\t\t\t\t\t\toperand: operand,\n\t\t\t\t\t\t\tprefix: operator.prefix,\n\t\t\t\t\t\t\tsuffix: operator.suffix,\n\t\t\t\t\t\t\tregexp: operator.regexp\n\t\t\t\t\t\t},{\n\t\t\t\t\t\t\twiki: self,\n\t\t\t\t\t\t\twidget: widget\n\t\t\t\t\t\t});\n\t\t\t\tif($tw.utils.isArray(results)) {\n\t\t\t\t\taccumulator = self.makeTiddlerIterator(results);\n\t\t\t\t} else {\n\t\t\t\t\taccumulator = results;\n\t\t\t\t}\n\t\t\t});\n\t\t\tif($tw.utils.isArray(results)) {\n\t\t\t\treturn results;\n\t\t\t} else {\n\t\t\t\tvar resultArray = [];\n\t\t\t\tresults(function(tiddler,title) {\n\t\t\t\t\tresultArray.push(title);\n\t\t\t\t});\n\t\t\t\treturn resultArray;\n\t\t\t}\n\t\t};\n\t\t// Wrap the operator functions in a wrapper function that depends on the prefix\n\t\toperationFunctions.push((function() {\n\t\t\tswitch(operation.prefix || \"\") {\n\t\t\t\tcase \"\": // No prefix means that the operation is unioned into the result\n\t\t\t\t\treturn function(results,source,widget) {\n\t\t\t\t\t\t$tw.utils.pushTop(results,operationSubFunction(source,widget));\n\t\t\t\t\t};\n\t\t\t\tcase \"-\": // The results of this operation are removed from the main result\n\t\t\t\t\treturn function(results,source,widget) {\n\t\t\t\t\t\t$tw.utils.removeArrayEntries(results,operationSubFunction(source,widget));\n\t\t\t\t\t};\n\t\t\t\tcase \"+\": // This operation is applied to the main results so far\n\t\t\t\t\treturn function(results,source,widget) {\n\t\t\t\t\t\t// This replaces all the elements of the array, but keeps the actual array so that references to it are preserved\n\t\t\t\t\t\tsource = self.makeTiddlerIterator(results);\n\t\t\t\t\t\tresults.splice(0,results.length);\n\t\t\t\t\t\t$tw.utils.pushTop(results,operationSubFunction(source,widget));\n\t\t\t\t\t};\n\t\t\t}\n\t\t})());\n\t});\n\t// Return a function that applies the operations to a source iterator of tiddler titles\n\treturn $tw.perf.measure(\"filter\",function filterFunction(source,widget) {\n\t\tif(!source) {\n\t\t\tsource = self.each;\n\t\t} else if(typeof source === \"object\") { // Array or hashmap\n\t\t\tsource = self.makeTiddlerIterator(source);\n\t\t}\n\t\tvar results = [];\n\t\t$tw.utils.each(operationFunctions,function(operationFunction) {\n\t\t\toperationFunction(results,source,widget);\n\t\t});\n\t\treturn results;\n\t});\n};\n\n})();\n", "title": "$:/core/modules/filters.js", "type": "application/javascript", "module-type": "wikimethod" }, "$:/core/modules/info/platform.js": { "text": "/*\\\ntitle: $:/core/modules/info/platform.js\ntype: application/javascript\nmodule-type: info\n\nInitialise basic platform $:/info/ tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.getInfoTiddlerFields = function() {\n\tvar mapBoolean = function(value) {return value ? \"yes\" : \"no\";},\n\t\tinfoTiddlerFields = [];\n\t// Basics\n\tinfoTiddlerFields.push({title: \"$:/info/browser\", text: mapBoolean(!!$tw.browser)});\n\tinfoTiddlerFields.push({title: \"$:/info/node\", text: mapBoolean(!!$tw.node)});\n\t// Document location\n\tif($tw.browser) {\n\t\tvar setLocationProperty = function(name,value) {\n\t\t\t\tinfoTiddlerFields.push({title: \"$:/info/url/\" + name, text: value});\t\t\t\n\t\t\t},\n\t\t\tlocation = document.location;\n\t\tsetLocationProperty(\"full\", (location.toString()).split(\"#\")[0]);\n\t\tsetLocationProperty(\"host\", location.host);\n\t\tsetLocationProperty(\"hostname\", location.hostname);\n\t\tsetLocationProperty(\"protocol\", location.protocol);\n\t\tsetLocationProperty(\"port\", location.port);\n\t\tsetLocationProperty(\"pathname\", location.pathname);\n\t\tsetLocationProperty(\"search\", location.search);\n\t\tsetLocationProperty(\"origin\", location.origin);\n\t}\n\treturn infoTiddlerFields;\n};\n\n})();\n", "title": "$:/core/modules/info/platform.js", "type": "application/javascript", "module-type": "info" }, "$:/core/modules/keyboard.js": { "text": "/*\\\ntitle: $:/core/modules/keyboard.js\ntype: application/javascript\nmodule-type: global\n\nKeyboard handling utilities\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar namedKeys = {\n\t\"cancel\": 3,\n\t\"help\": 6,\n\t\"backspace\": 8,\n\t\"tab\": 9,\n\t\"clear\": 12,\n\t\"return\": 13,\n\t\"enter\": 13,\n\t\"pause\": 19,\n\t\"escape\": 27,\n\t\"space\": 32,\n\t\"page_up\": 33,\n\t\"page_down\": 34,\n\t\"end\": 35,\n\t\"home\": 36,\n\t\"left\": 37,\n\t\"up\": 38,\n\t\"right\": 39,\n\t\"down\": 40,\n\t\"printscreen\": 44,\n\t\"insert\": 45,\n\t\"delete\": 46,\n\t\"0\": 48,\n\t\"1\": 49,\n\t\"2\": 50,\n\t\"3\": 51,\n\t\"4\": 52,\n\t\"5\": 53,\n\t\"6\": 54,\n\t\"7\": 55,\n\t\"8\": 56,\n\t\"9\": 57,\n\t\"firefoxsemicolon\": 59,\n\t\"firefoxequals\": 61,\n\t\"a\": 65,\n\t\"b\": 66,\n\t\"c\": 67,\n\t\"d\": 68,\n\t\"e\": 69,\n\t\"f\": 70,\n\t\"g\": 71,\n\t\"h\": 72,\n\t\"i\": 73,\n\t\"j\": 74,\n\t\"k\": 75,\n\t\"l\": 76,\n\t\"m\": 77,\n\t\"n\": 78,\n\t\"o\": 79,\n\t\"p\": 80,\n\t\"q\": 81,\n\t\"r\": 82,\n\t\"s\": 83,\n\t\"t\": 84,\n\t\"u\": 85,\n\t\"v\": 86,\n\t\"w\": 87,\n\t\"x\": 88,\n\t\"y\": 89,\n\t\"z\": 90,\n\t\"numpad0\": 96,\n\t\"numpad1\": 97,\n\t\"numpad2\": 98,\n\t\"numpad3\": 99,\n\t\"numpad4\": 100,\n\t\"numpad5\": 101,\n\t\"numpad6\": 102,\n\t\"numpad7\": 103,\n\t\"numpad8\": 104,\n\t\"numpad9\": 105,\n\t\"multiply\": 106,\n\t\"add\": 107,\n\t\"separator\": 108,\n\t\"subtract\": 109,\n\t\"decimal\": 110,\n\t\"divide\": 111,\n\t\"f1\": 112,\n\t\"f2\": 113,\n\t\"f3\": 114,\n\t\"f4\": 115,\n\t\"f5\": 116,\n\t\"f6\": 117,\n\t\"f7\": 118,\n\t\"f8\": 119,\n\t\"f9\": 120,\n\t\"f10\": 121,\n\t\"f11\": 122,\n\t\"f12\": 123,\n\t\"f13\": 124,\n\t\"f14\": 125,\n\t\"f15\": 126,\n\t\"f16\": 127,\n\t\"f17\": 128,\n\t\"f18\": 129,\n\t\"f19\": 130,\n\t\"f20\": 131,\n\t\"f21\": 132,\n\t\"f22\": 133,\n\t\"f23\": 134,\n\t\"f24\": 135,\n\t\"firefoxminus\": 173,\n\t\"semicolon\": 186,\n\t\"equals\": 187,\n\t\"comma\": 188,\n\t\"dash\": 189,\n\t\"period\": 190,\n\t\"slash\": 191,\n\t\"backquote\": 192,\n\t\"openbracket\": 219,\n\t\"backslash\": 220,\n\t\"closebracket\": 221,\n\t\"quote\": 222\n};\n\nfunction KeyboardManager(options) {\n\tvar self = this;\n\toptions = options || \"\";\n\t// Save the named key hashmap\n\tthis.namedKeys = namedKeys;\n\t// Create a reverse mapping of code to keyname\n\tthis.keyNames = [];\n\t$tw.utils.each(namedKeys,function(keyCode,name) {\n\t\tself.keyNames[keyCode] = name.substr(0,1).toUpperCase() + name.substr(1);\n\t});\n\t// Save the platform-specific name of the \"meta\" key\n\tthis.metaKeyName = $tw.platform.isMac ? \"cmd-\" : \"win-\";\n}\n\n/*\nReturn an array of keycodes for the modifier keys ctrl, shift, alt, meta\n*/\nKeyboardManager.prototype.getModifierKeys = function() {\n\treturn [\n\t\t16, // Shift\n\t\t17, // Ctrl\n\t\t18, // Alt\n\t\t20, // CAPS LOCK\n\t\t91, // Meta (left)\n\t\t93, // Meta (right)\n\t\t224 // Meta (Firefox)\n\t]\n};\n\n/*\nParses a key descriptor into the structure:\n{\n\tkeyCode: numeric keycode\n\tshiftKey: boolean\n\taltKey: boolean\n\tctrlKey: boolean\n\tmetaKey: boolean\n}\nKey descriptors have the following format:\n\tctrl+enter\n\tctrl+shift+alt+A\n*/\nKeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor) {\n\tvar components = keyDescriptor.split(/\\+|\\-/),\n\t\tinfo = {\n\t\t\tkeyCode: 0,\n\t\t\tshiftKey: false,\n\t\t\taltKey: false,\n\t\t\tctrlKey: false,\n\t\t\tmetaKey: false\n\t\t};\n\tfor(var t=0; t<components.length; t++) {\n\t\tvar s = components[t].toLowerCase(),\n\t\t\tc = s.charCodeAt(0);\n\t\t// Look for modifier keys\n\t\tif(s === \"ctrl\") {\n\t\t\tinfo.ctrlKey = true;\n\t\t} else if(s === \"shift\") {\n\t\t\tinfo.shiftKey = true;\n\t\t} else if(s === \"alt\") {\n\t\t\tinfo.altKey = true;\n\t\t} else if(s === \"meta\" || s === \"cmd\" || s === \"win\") {\n\t\t\tinfo.metaKey = true;\n\t\t}\n\t\t// Replace named keys with their code\n\t\tif(this.namedKeys[s]) {\n\t\t\tinfo.keyCode = this.namedKeys[s];\n\t\t}\n\t}\n\tif(info.keyCode) {\n\t\treturn info;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nParse a list of key descriptors into an array of keyInfo objects. The key descriptors can be passed as an array of strings or a space separated string\n*/\nKeyboardManager.prototype.parseKeyDescriptors = function(keyDescriptors,options) {\n\tvar self = this;\n\toptions = options || {};\n\toptions.stack = options.stack || [];\n\tvar wiki = options.wiki || $tw.wiki;\n\tif(typeof keyDescriptors === \"string\" && keyDescriptors === \"\") {\n\t\treturn [];\n\t}\n\tif(!$tw.utils.isArray(keyDescriptors)) {\n\t\tkeyDescriptors = keyDescriptors.split(\" \");\n\t}\n\tvar result = [];\n\t$tw.utils.each(keyDescriptors,function(keyDescriptor) {\n\t\t// Look for a named shortcut\n\t\tif(keyDescriptor.substr(0,2) === \"((\" && keyDescriptor.substr(-2,2) === \"))\") {\n\t\t\tif(options.stack.indexOf(keyDescriptor) === -1) {\n\t\t\t\toptions.stack.push(keyDescriptor);\n\t\t\t\tvar name = keyDescriptor.substring(2,keyDescriptor.length - 2),\n\t\t\t\t\tlookupName = function(configName) {\n\t\t\t\t\t\tvar keyDescriptors = wiki.getTiddlerText(\"$:/config/\" + configName + \"/\" + name);\n\t\t\t\t\t\tif(keyDescriptors) {\n\t\t\t\t\t\t\tresult.push.apply(result,self.parseKeyDescriptors(keyDescriptors,options));\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\tlookupName(\"shortcuts\");\n\t\t\t\tlookupName($tw.platform.isMac ? \"shortcuts-mac\" : \"shortcuts-not-mac\");\n\t\t\t\tlookupName($tw.platform.isWindows ? \"shortcuts-windows\" : \"shortcuts-not-windows\");\n\t\t\t\tlookupName($tw.platform.isLinux ? \"shortcuts-linux\" : \"shortcuts-not-linux\");\n\t\t\t}\n\t\t} else {\n\t\t\tresult.push(self.parseKeyDescriptor(keyDescriptor));\n\t\t}\n\t});\n\treturn result;\n};\n\nKeyboardManager.prototype.getPrintableShortcuts = function(keyInfoArray) {\n\tvar self = this,\n\t\tresult = [];\n\t$tw.utils.each(keyInfoArray,function(keyInfo) {\n\t\tif(keyInfo) {\n\t\t\tresult.push((keyInfo.ctrlKey ? \"ctrl-\" : \"\") + \n\t\t\t\t (keyInfo.shiftKey ? \"shift-\" : \"\") + \n\t\t\t\t (keyInfo.altKey ? \"alt-\" : \"\") + \n\t\t\t\t (keyInfo.metaKey ? self.metaKeyName : \"\") + \n\t\t\t\t (self.keyNames[keyInfo.keyCode]));\n\t\t}\n\t});\n\treturn result;\n}\n\nKeyboardManager.prototype.checkKeyDescriptor = function(event,keyInfo) {\n\treturn keyInfo &&\n\t\t\tevent.keyCode === keyInfo.keyCode && \n\t\t\tevent.shiftKey === keyInfo.shiftKey && \n\t\t\tevent.altKey === keyInfo.altKey && \n\t\t\tevent.ctrlKey === keyInfo.ctrlKey && \n\t\t\tevent.metaKey === keyInfo.metaKey;\n};\n\nKeyboardManager.prototype.checkKeyDescriptors = function(event,keyInfoArray) {\n\tfor(var t=0; t<keyInfoArray.length; t++) {\n\t\tif(this.checkKeyDescriptor(event,keyInfoArray[t])) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\nexports.KeyboardManager = KeyboardManager;\n\n})();\n", "title": "$:/core/modules/keyboard.js", "type": "application/javascript", "module-type": "global" }, "$:/core/modules/language.js": { "text": "/*\\\ntitle: $:/core/modules/language.js\ntype: application/javascript\nmodule-type: global\n\nThe $tw.Language() manages translateable strings\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nCreate an instance of the language manager. Options include:\nwiki: wiki from which to retrieve translation tiddlers\n*/\nfunction Language(options) {\n\toptions = options || \"\";\n\tthis.wiki = options.wiki || $tw.wiki;\n}\n\n/*\nReturn a wikified translateable string. The title is automatically prefixed with \"$:/language/\"\nOptions include:\nvariables: optional hashmap of variables to supply to the language wikification\n*/\nLanguage.prototype.getString = function(title,options) {\n\toptions = options || {};\n\ttitle = \"$:/language/\" + title;\n\treturn this.wiki.renderTiddler(\"text/plain\",title,{variables: options.variables});\n};\n\n/*\nReturn a raw, unwikified translateable string. The title is automatically prefixed with \"$:/language/\"\n*/\nLanguage.prototype.getRawString = function(title) {\n\ttitle = \"$:/language/\" + title;\n\treturn this.wiki.getTiddlerText(title);\n};\n\nexports.Language = Language;\n\n})();\n", "title": "$:/core/modules/language.js", "type": "application/javascript", "module-type": "global" }, "$:/core/modules/macros/changecount.js": { "text": "/*\\\ntitle: $:/core/modules/macros/changecount.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to return the changecount for the current tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"changecount\";\n\nexports.params = [];\n\n/*\nRun the macro\n*/\nexports.run = function() {\n\treturn this.wiki.getChangeCount(this.getVariable(\"currentTiddler\")) + \"\";\n};\n\n})();\n", "title": "$:/core/modules/macros/changecount.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/macros/contrastcolour.js": { "text": "/*\\\ntitle: $:/core/modules/macros/contrastcolour.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to choose which of two colours has the highest contrast with a base colour\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"contrastcolour\";\n\nexports.params = [\n\t{name: \"target\"},\n\t{name: \"fallbackTarget\"},\n\t{name: \"colourA\"},\n\t{name: \"colourB\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(target,fallbackTarget,colourA,colourB) {\n\tvar rgbTarget = $tw.utils.parseCSSColor(target) || $tw.utils.parseCSSColor(fallbackTarget);\n\tif(!rgbTarget) {\n\t\treturn colourA;\n\t}\n\tvar rgbColourA = $tw.utils.parseCSSColor(colourA),\n\t\trgbColourB = $tw.utils.parseCSSColor(colourB);\n\tif(rgbColourA && !rgbColourB) {\n\t\treturn rgbColourA;\n\t}\n\tif(rgbColourB && !rgbColourA) {\n\t\treturn rgbColourB;\n\t}\n\tif(!rgbColourA && !rgbColourB) {\n\t\t// If neither colour is readable, return a crude inverse of the target\n\t\treturn [255 - rgbTarget[0],255 - rgbTarget[1],255 - rgbTarget[2],rgbTarget[3]];\n\t}\n\t// Colour brightness formula derived from http://www.w3.org/WAI/ER/WD-AERT/#color-contrast\n\tvar brightnessTarget = rgbTarget[0] * 0.299 + rgbTarget[1] * 0.587 + rgbTarget[2] * 0.114,\n\t\tbrightnessA = rgbColourA[0] * 0.299 + rgbColourA[1] * 0.587 + rgbColourA[2] * 0.114,\n\t\tbrightnessB = rgbColourB[0] * 0.299 + rgbColourB[1] * 0.587 + rgbColourB[2] * 0.114;\n\treturn Math.abs(brightnessTarget - brightnessA) > Math.abs(brightnessTarget - brightnessB) ? colourA : colourB;\n};\n\n})();\n", "title": "$:/core/modules/macros/contrastcolour.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/macros/csvtiddlers.js": { "text": "/*\\\ntitle: $:/core/modules/macros/csvtiddlers.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to output tiddlers matching a filter to CSV\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"csvtiddlers\";\n\nexports.params = [\n\t{name: \"filter\"},\n\t{name: \"format\"},\n];\n\n/*\nRun the macro\n*/\nexports.run = function(filter,format) {\n\tvar self = this,\n\t\ttiddlers = this.wiki.filterTiddlers(filter),\n\t\ttiddler,\n\t\tfields = [],\n\t\tt,f;\n\t// Collect all the fields\n\tfor(t=0;t<tiddlers.length; t++) {\n\t\ttiddler = this.wiki.getTiddler(tiddlers[t]);\n\t\tfor(f in tiddler.fields) {\n\t\t\tif(fields.indexOf(f) === -1) {\n\t\t\t\tfields.push(f);\n\t\t\t}\n\t\t}\n\t}\n\t// Sort the fields and bring the standard ones to the front\n\tfields.sort();\n\t\"title text modified modifier created creator\".split(\" \").reverse().forEach(function(value,index) {\n\t\tvar p = fields.indexOf(value);\n\t\tif(p !== -1) {\n\t\t\tfields.splice(p,1);\n\t\t\tfields.unshift(value)\n\t\t}\n\t});\n\t// Output the column headings\n\tvar output = [], row = [];\n\tfields.forEach(function(value) {\n\t\trow.push(quoteAndEscape(value))\n\t});\n\toutput.push(row.join(\",\"));\n\t// Output each tiddler\n\tfor(var t=0;t<tiddlers.length; t++) {\n\t\trow = [];\n\t\ttiddler = this.wiki.getTiddler(tiddlers[t]);\n\t\t\tfor(f=0; f<fields.length; f++) {\n\t\t\t\trow.push(quoteAndEscape(tiddler ? tiddler.getFieldString(fields[f]) || \"\" : \"\"));\n\t\t\t}\n\t\toutput.push(row.join(\",\"));\n\t}\n\treturn output.join(\"\\n\");\n};\n\nfunction quoteAndEscape(value) {\n\treturn \"\\\"\" + value.replace(/\"/mg,\"\\\"\\\"\") + \"\\\"\";\n}\n\n})();\n", "title": "$:/core/modules/macros/csvtiddlers.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/macros/displayshortcuts.js": { "text": "/*\\\ntitle: $:/core/modules/macros/displayshortcuts.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to display a list of keyboard shortcuts in human readable form. Notably, it resolves named shortcuts like `((bold))` to the underlying keystrokes.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"displayshortcuts\";\n\nexports.params = [\n\t{name: \"shortcuts\"},\n\t{name: \"prefix\"},\n\t{name: \"separator\"},\n\t{name: \"suffix\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(shortcuts,prefix,separator,suffix) {\n\tvar shortcutArray = $tw.keyboardManager.getPrintableShortcuts($tw.keyboardManager.parseKeyDescriptors(shortcuts,{\n\t\twiki: this.wiki\n\t}));\n\tif(shortcutArray.length > 0) {\n\t\tshortcutArray.sort(function(a,b) {\n\t\t return a.toLowerCase().localeCompare(b.toLowerCase());\n\t\t})\n\t\treturn prefix + shortcutArray.join(separator) + suffix;\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\n})();\n", "title": "$:/core/modules/macros/displayshortcuts.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/macros/dumpvariables.js": { "text": "/*\\\ntitle: $:/core/modules/macros/dumpvariables.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to dump all active variable values\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"dumpvariables\";\n\nexports.params = [\n];\n\n/*\nRun the macro\n*/\nexports.run = function() {\n\tvar output = [\"|!Variable |!Value |\"],\n\t\tvariables = [], variable;\n\tfor(variable in this.variables) {\n\t\tvariables.push(variable);\n\t}\n\tvariables.sort();\n\tfor(var index=0; index<variables.length; index++) {\n\t\tvar variable = variables[index];\n\t\toutput.push(\"|\" + variable + \" |<input size=50 value=<<\" + variable + \">>/> |\")\n\t}\n\treturn output.join(\"\\n\");\n};\n\n})();\n", "title": "$:/core/modules/macros/dumpvariables.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/macros/jsontiddler.js": { "text": "/*\\\ntitle: $:/core/modules/macros/jsontiddler.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to output a single tiddler to JSON\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"jsontiddler\";\n\nexports.params = [\n\t{name: \"title\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(title) {\n\ttitle = title || this.getVariable(\"currentTiddler\");\n\tvar tiddler = !!title && this.wiki.getTiddler(title),\n\t\tfields = new Object();\n\tif(tiddler) {\n\t\tfor(var field in tiddler.fields) {\n\t\t\tfields[field] = tiddler.getFieldString(field);\n\t\t}\n\t}\n\treturn JSON.stringify(fields,null,$tw.config.preferences.jsonSpaces);\n};\n\n})();\n", "title": "$:/core/modules/macros/jsontiddler.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/macros/jsontiddlers.js": { "text": "/*\\\ntitle: $:/core/modules/macros/jsontiddlers.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to output tiddlers matching a filter to JSON\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"jsontiddlers\";\n\nexports.params = [\n\t{name: \"filter\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(filter) {\n\tvar tiddlers = this.wiki.filterTiddlers(filter),\n\t\tdata = [];\n\tfor(var t=0;t<tiddlers.length; t++) {\n\t\tvar tiddler = this.wiki.getTiddler(tiddlers[t]);\n\t\tif(tiddler) {\n\t\t\tvar fields = new Object();\n\t\t\tfor(var field in tiddler.fields) {\n\t\t\t\tfields[field] = tiddler.getFieldString(field);\n\t\t\t}\n\t\t\tdata.push(fields);\n\t\t}\n\t}\n\treturn JSON.stringify(data,null,$tw.config.preferences.jsonSpaces);\n};\n\n})();\n", "title": "$:/core/modules/macros/jsontiddlers.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/macros/makedatauri.js": { "text": "/*\\\ntitle: $:/core/modules/macros/makedatauri.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to convert a string of text to a data URI\n\n<<makedatauri text:\"Text to be converted\" type:\"text/vnd.tiddlywiki\">>\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"makedatauri\";\n\nexports.params = [\n\t{name: \"text\"},\n\t{name: \"type\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(text,type) {\n\treturn $tw.utils.makeDataUri(text,type);\n};\n\n})();\n", "title": "$:/core/modules/macros/makedatauri.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/macros/now.js": { "text": "/*\\\ntitle: $:/core/modules/macros/now.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to return a formatted version of the current time\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"now\";\n\nexports.params = [\n\t{name: \"format\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(format) {\n\treturn $tw.utils.formatDateString(new Date(),format || \"0hh:0mm, DDth MMM YYYY\");\n};\n\n})();\n", "title": "$:/core/modules/macros/now.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/macros/qualify.js": { "text": "/*\\\ntitle: $:/core/modules/macros/qualify.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to qualify a state tiddler title according\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"qualify\";\n\nexports.params = [\n\t{name: \"title\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(title) {\n\treturn title + \"-\" + this.getStateQualifier();\n};\n\n})();\n", "title": "$:/core/modules/macros/qualify.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/macros/resolvepath.js": { "text": "/*\\\ntitle: $:/core/modules/macros/resolvepath.js\ntype: application/javascript\nmodule-type: macro\n\nResolves a relative path for an absolute rootpath.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"resolvepath\";\n\nexports.params = [\n\t{name: \"source\"},\n\t{name: \"root\"}\n];\n\n/*\nRun the macro\n*/\nexports.run = function(source, root) {\n\treturn $tw.utils.resolvePath(source, root);\n};\n\n})();\n", "title": "$:/core/modules/macros/resolvepath.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/macros/version.js": { "text": "/*\\\ntitle: $:/core/modules/macros/version.js\ntype: application/javascript\nmodule-type: macro\n\nMacro to return the TiddlyWiki core version number\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInformation about this macro\n*/\n\nexports.name = \"version\";\n\nexports.params = [];\n\n/*\nRun the macro\n*/\nexports.run = function() {\n\treturn $tw.version;\n};\n\n})();\n", "title": "$:/core/modules/macros/version.js", "type": "application/javascript", "module-type": "macro" }, "$:/core/modules/parsers/audioparser.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/audioparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe audio parser parses an audio tiddler into an embeddable HTML element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar AudioParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"audio\",\n\t\t\tattributes: {\n\t\t\t\tcontrols: {type: \"string\", value: \"controls\"}\n\t\t\t}\n\t\t},\n\t\tsrc;\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\telement.attributes.src = {type: \"string\", value: \"data:\" + type + \";base64,\" + text};\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"audio/ogg\"] = AudioParser;\nexports[\"audio/mpeg\"] = AudioParser;\nexports[\"audio/mp3\"] = AudioParser;\nexports[\"audio/mp4\"] = AudioParser;\n\n})();\n\n", "title": "$:/core/modules/parsers/audioparser.js", "type": "application/javascript", "module-type": "parser" }, "$:/core/modules/parsers/csvparser.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/csvparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe CSV text parser processes CSV files into a table wrapped in a scrollable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar CsvParser = function(type,text,options) {\n\t// Table framework\n\tthis.tree = [{\n\t\t\"type\": \"scrollable\", \"children\": [{\n\t\t\t\"type\": \"element\", \"tag\": \"table\", \"children\": [{\n\t\t\t\t\"type\": \"element\", \"tag\": \"tbody\", \"children\": []\n\t\t\t}], \"attributes\": {\n\t\t\t\t\"class\": {\"type\": \"string\", \"value\": \"tc-csv-table\"}\n\t\t\t}\n\t\t}]\n\t}];\n\t// Split the text into lines\n\tvar lines = text.split(/\\r?\\n/mg),\n\t\ttag = \"th\";\n\tfor(var line=0; line<lines.length; line++) {\n\t\tvar lineText = lines[line];\n\t\tif(lineText) {\n\t\t\tvar row = {\n\t\t\t\t\t\"type\": \"element\", \"tag\": \"tr\", \"children\": []\n\t\t\t\t};\n\t\t\tvar columns = lineText.split(\",\");\n\t\t\tfor(var column=0; column<columns.length; column++) {\n\t\t\t\trow.children.push({\n\t\t\t\t\t\t\"type\": \"element\", \"tag\": tag, \"children\": [{\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": columns[column]\n\t\t\t\t\t\t}]\n\t\t\t\t\t});\n\t\t\t}\n\t\t\ttag = \"td\";\n\t\t\tthis.tree[0].children[0].children[0].children.push(row);\n\t\t}\n\t}\n};\n\nexports[\"text/csv\"] = CsvParser;\n\n})();\n\n", "title": "$:/core/modules/parsers/csvparser.js", "type": "application/javascript", "module-type": "parser" }, "$:/core/modules/parsers/htmlparser.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/htmlparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe HTML parser displays text as raw HTML\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar HtmlParser = function(type,text,options) {\n\tvar src;\n\tif(options._canonical_uri) {\n\t\tsrc = options._canonical_uri;\n\t} else if(text) {\n\t\tsrc = \"data:text/html;charset=utf-8,\" + encodeURIComponent(text);\n\t}\n\tthis.tree = [{\n\t\ttype: \"element\",\n\t\ttag: \"iframe\",\n\t\tattributes: {\n\t\t\tsrc: {type: \"string\", value: src},\n\t\t\tsandbox: {type: \"string\", value: \"\"}\n\t\t}\n\t}];\n};\n\nexports[\"text/html\"] = HtmlParser;\n\n})();\n\n", "title": "$:/core/modules/parsers/htmlparser.js", "type": "application/javascript", "module-type": "parser" }, "$:/core/modules/parsers/imageparser.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/imageparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe image parser parses an image into an embeddable HTML element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar ImageParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"img\",\n\t\t\tattributes: {}\n\t\t},\n\t\tsrc;\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\tif(type === \"image/svg+xml\" || type === \".svg\") {\n\t\t\telement.attributes.src = {type: \"string\", value: \"data:image/svg+xml,\" + encodeURIComponent(text)};\n\t\t} else {\n\t\t\telement.attributes.src = {type: \"string\", value: \"data:\" + type + \";base64,\" + text};\n\t\t}\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"image/svg+xml\"] = ImageParser;\nexports[\"image/jpg\"] = ImageParser;\nexports[\"image/jpeg\"] = ImageParser;\nexports[\"image/png\"] = ImageParser;\nexports[\"image/gif\"] = ImageParser;\nexports[\"image/x-icon\"] = ImageParser;\n\n})();\n\n", "title": "$:/core/modules/parsers/imageparser.js", "type": "application/javascript", "module-type": "parser" }, "$:/core/modules/utils/parseutils.js": { "text": "/*\\\ntitle: $:/core/modules/utils/parseutils.js\ntype: application/javascript\nmodule-type: utils\n\nUtility functions concerned with parsing text into tokens.\n\nMost functions have the following pattern:\n\n* The parameters are:\n** `source`: the source string being parsed\n** `pos`: the current parse position within the string\n** Any further parameters are used to identify the token that is being parsed\n* The return value is:\n** null if the token was not found at the specified position\n** an object representing the token with the following standard fields:\n*** `type`: string indicating the type of the token\n*** `start`: start position of the token in the source string\n*** `end`: end position of the token in the source string\n*** Any further fields required to describe the token\n\nThe exception is `skipWhiteSpace`, which just returns the position after the whitespace.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nLook for a whitespace token. Returns null if not found, otherwise returns {type: \"whitespace\", start:, end:,}\n*/\nexports.parseWhiteSpace = function(source,pos) {\n\tvar p = pos,c;\n\twhile(true) {\n\t\tc = source.charAt(p);\n\t\tif((c === \" \") || (c === \"\\f\") || (c === \"\\n\") || (c === \"\\r\") || (c === \"\\t\") || (c === \"\\v\") || (c === \"\\u00a0\")) { // Ignores some obscure unicode spaces\n\t\t\tp++;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\tif(p === pos) {\n\t\treturn null;\n\t} else {\n\t\treturn {\n\t\t\ttype: \"whitespace\",\n\t\t\tstart: pos,\n\t\t\tend: p\n\t\t}\n\t}\n};\n\n/*\nConvenience wrapper for parseWhiteSpace. Returns the position after the whitespace\n*/\nexports.skipWhiteSpace = function(source,pos) {\n\tvar c;\n\twhile(true) {\n\t\tc = source.charAt(pos);\n\t\tif((c === \" \") || (c === \"\\f\") || (c === \"\\n\") || (c === \"\\r\") || (c === \"\\t\") || (c === \"\\v\") || (c === \"\\u00a0\")) { // Ignores some obscure unicode spaces\n\t\t\tpos++;\n\t\t} else {\n\t\t\treturn pos;\n\t\t}\n\t}\n};\n\n/*\nLook for a given string token. Returns null if not found, otherwise returns {type: \"token\", value:, start:, end:,}\n*/\nexports.parseTokenString = function(source,pos,token) {\n\tvar match = source.indexOf(token,pos) === pos;\n\tif(match) {\n\t\treturn {\n\t\t\ttype: \"token\",\n\t\t\tvalue: token,\n\t\t\tstart: pos,\n\t\t\tend: pos + token.length\n\t\t};\n\t}\n\treturn null;\n};\n\n/*\nLook for a token matching a regex. Returns null if not found, otherwise returns {type: \"regexp\", match:, start:, end:,}\n*/\nexports.parseTokenRegExp = function(source,pos,reToken) {\n\tvar node = {\n\t\ttype: \"regexp\",\n\t\tstart: pos\n\t};\n\treToken.lastIndex = pos;\n\tnode.match = reToken.exec(source);\n\tif(node.match && node.match.index === pos) {\n\t\tnode.end = pos + node.match[0].length;\n\t\treturn node;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nLook for a string literal. Returns null if not found, otherwise returns {type: \"string\", value:, start:, end:,}\n*/\nexports.parseStringLiteral = function(source,pos) {\n\tvar node = {\n\t\ttype: \"string\",\n\t\tstart: pos\n\t};\n\tvar reString = /(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\")|(?:'([^']*)')/g;\n\treString.lastIndex = pos;\n\tvar match = reString.exec(source);\n\tif(match && match.index === pos) {\n\t\tnode.value = match[1] !== undefined ? match[1] :(\n\t\t\tmatch[2] !== undefined ? match[2] : match[3] \n\t\t\t\t\t);\n\t\tnode.end = pos + match[0].length;\n\t\treturn node;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nLook for a macro invocation parameter. Returns null if not found, or {type: \"macro-parameter\", name:, value:, start:, end:}\n*/\nexports.parseMacroParameter = function(source,pos) {\n\tvar node = {\n\t\ttype: \"macro-parameter\",\n\t\tstart: pos\n\t};\n\t// Define our regexp\n\tvar reMacroParameter = /(?:([A-Za-z0-9\\-_]+)\\s*:)?(?:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\\s>\"'=]+)))/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the parameter\n\tvar token = $tw.utils.parseTokenRegExp(source,pos,reMacroParameter);\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Get the parameter details\n\tnode.value = token.match[2] !== undefined ? token.match[2] : (\n\t\t\t\t\ttoken.match[3] !== undefined ? token.match[3] : (\n\t\t\t\t\t\ttoken.match[4] !== undefined ? token.match[4] : (\n\t\t\t\t\t\t\ttoken.match[5] !== undefined ? token.match[5] : (\n\t\t\t\t\t\t\t\ttoken.match[6] !== undefined ? token.match[6] : (\n\t\t\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t);\n\tif(token.match[1]) {\n\t\tnode.name = token.match[1];\n\t}\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n/*\nLook for a macro invocation. Returns null if not found, or {type: \"macrocall\", name:, parameters:, start:, end:}\n*/\nexports.parseMacroInvocation = function(source,pos) {\n\tvar node = {\n\t\ttype: \"macrocall\",\n\t\tstart: pos,\n\t\tparams: []\n\t};\n\t// Define our regexps\n\tvar reMacroName = /([^\\s>\"'=]+)/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a double less than sign\n\tvar token = $tw.utils.parseTokenString(source,pos,\"<<\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Get the macro name\n\tvar name = $tw.utils.parseTokenRegExp(source,pos,reMacroName);\n\tif(!name) {\n\t\treturn null;\n\t}\n\tnode.name = name.match[1];\n\tpos = name.end;\n\t// Process parameters\n\tvar parameter = $tw.utils.parseMacroParameter(source,pos);\n\twhile(parameter) {\n\t\tnode.params.push(parameter);\n\t\tpos = parameter.end;\n\t\t// Get the next parameter\n\t\tparameter = $tw.utils.parseMacroParameter(source,pos);\n\t}\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a double greater than sign\n\ttoken = $tw.utils.parseTokenString(source,pos,\">>\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n/*\nLook for an HTML attribute definition. Returns null if not found, otherwise returns {type: \"attribute\", name:, valueType: \"string|indirect|macro\", value:, start:, end:,}\n*/\nexports.parseAttribute = function(source,pos) {\n\tvar node = {\n\t\tstart: pos\n\t};\n\t// Define our regexps\n\tvar reAttributeName = /([^\\/\\s>\"'=]+)/g,\n\t\treUnquotedAttribute = /([^\\/\\s<>\"'=]+)/g,\n\t\treFilteredValue = /\\{\\{\\{(.+?)\\}\\}\\}/g,\n\t\treIndirectValue = /\\{\\{([^\\}]+)\\}\\}/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Get the attribute name\n\tvar name = $tw.utils.parseTokenRegExp(source,pos,reAttributeName);\n\tif(!name) {\n\t\treturn null;\n\t}\n\tnode.name = name.match[1];\n\tpos = name.end;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for an equals sign\n\tvar token = $tw.utils.parseTokenString(source,pos,\"=\");\n\tif(token) {\n\t\tpos = token.end;\n\t\t// Skip whitespace\n\t\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t\t// Look for a string literal\n\t\tvar stringLiteral = $tw.utils.parseStringLiteral(source,pos);\n\t\tif(stringLiteral) {\n\t\t\tpos = stringLiteral.end;\n\t\t\tnode.type = \"string\";\n\t\t\tnode.value = stringLiteral.value;\n\t\t} else {\n\t\t\t// Look for a filtered value\n\t\t\tvar filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);\n\t\t\tif(filteredValue) {\n\t\t\t\tpos = filteredValue.end;\n\t\t\t\tnode.type = \"filtered\";\n\t\t\t\tnode.filter = filteredValue.match[1];\n\t\t\t} else {\n\t\t\t\t// Look for an indirect value\n\t\t\t\tvar indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);\n\t\t\t\tif(indirectValue) {\n\t\t\t\t\tpos = indirectValue.end;\n\t\t\t\t\tnode.type = \"indirect\";\n\t\t\t\t\tnode.textReference = indirectValue.match[1];\n\t\t\t\t} else {\n\t\t\t\t\t// Look for a unquoted value\n\t\t\t\t\tvar unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);\n\t\t\t\t\tif(unquotedValue) {\n\t\t\t\t\t\tpos = unquotedValue.end;\n\t\t\t\t\t\tnode.type = \"string\";\n\t\t\t\t\t\tnode.value = unquotedValue.match[1];\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Look for a macro invocation value\n\t\t\t\t\t\tvar macroInvocation = $tw.utils.parseMacroInvocation(source,pos);\n\t\t\t\t\t\tif(macroInvocation) {\n\t\t\t\t\t\t\tpos = macroInvocation.end;\n\t\t\t\t\t\t\tnode.type = \"macro\";\n\t\t\t\t\t\t\tnode.value = macroInvocation;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnode.type = \"string\";\n\t\t\t\t\t\t\tnode.value = \"true\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tnode.type = \"string\";\n\t\tnode.value = \"true\";\n\t}\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n})();\n", "title": "$:/core/modules/utils/parseutils.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/parsers/pdfparser.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/pdfparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe PDF parser embeds a PDF viewer\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar ImageParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"embed\",\n\t\t\tattributes: {}\n\t\t},\n\t\tsrc;\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\telement.attributes.src = {type: \"string\", value: \"data:application/pdf;base64,\" + text};\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"application/pdf\"] = ImageParser;\n\n})();\n\n", "title": "$:/core/modules/parsers/pdfparser.js", "type": "application/javascript", "module-type": "parser" }, "$:/core/modules/parsers/textparser.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/textparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe plain text parser processes blocks of source text into a degenerate parse tree consisting of a single text node\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar TextParser = function(type,text,options) {\n\tthis.tree = [{\n\t\ttype: \"codeblock\",\n\t\tattributes: {\n\t\t\tcode: {type: \"string\", value: text},\n\t\t\tlanguage: {type: \"string\", value: type}\n\t\t}\n\t}];\n};\n\nexports[\"text/plain\"] = TextParser;\nexports[\"text/x-tiddlywiki\"] = TextParser;\nexports[\"application/javascript\"] = TextParser;\nexports[\"application/json\"] = TextParser;\nexports[\"text/css\"] = TextParser;\nexports[\"application/x-tiddler-dictionary\"] = TextParser;\n\n})();\n\n", "title": "$:/core/modules/parsers/textparser.js", "type": "application/javascript", "module-type": "parser" }, "$:/core/modules/parsers/videoparser.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/videoparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe video parser parses a video tiddler into an embeddable HTML element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar VideoParser = function(type,text,options) {\n\tvar element = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"video\",\n\t\t\tattributes: {\n\t\t\t\tcontrols: {type: \"string\", value: \"controls\"}\n\t\t\t}\n\t\t},\n\t\tsrc;\n\tif(options._canonical_uri) {\n\t\telement.attributes.src = {type: \"string\", value: options._canonical_uri};\n\t} else if(text) {\n\t\telement.attributes.src = {type: \"string\", value: \"data:\" + type + \";base64,\" + text};\n\t}\n\tthis.tree = [element];\n};\n\nexports[\"video/mp4\"] = VideoParser;\nexports[\"video/quicktime\"] = VideoParser;\n\n})();\n\n", "title": "$:/core/modules/parsers/videoparser.js", "type": "application/javascript", "module-type": "parser" }, "$:/core/modules/parsers/wikiparser/rules/codeblock.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/codeblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for code blocks. For example:\n\n```\n\t```\n\tThis text will not be //wikified//\n\t```\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"codeblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match and get language if defined\n\tthis.matchRegExp = /```([\\w-]*)\\r?\\n/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /(\\r?\\n```$)/mg;\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Look for the end of the block\n\treEnd.lastIndex = this.parser.pos;\n\tvar match = reEnd.exec(this.parser.source),\n\t\ttext;\n\t// Process the block\n\tif(match) {\n\t\ttext = this.parser.source.substring(this.parser.pos,match.index);\n\t\tthis.parser.pos = match.index + match[0].length;\n\t} else {\n\t\ttext = this.parser.source.substr(this.parser.pos);\n\t\tthis.parser.pos = this.parser.sourceLength;\n\t}\n\t// Return the $codeblock widget\n\treturn [{\n\t\t\ttype: \"codeblock\",\n\t\t\tattributes: {\n\t\t\t\t\tcode: {type: \"string\", value: text},\n\t\t\t\t\tlanguage: {type: \"string\", value: this.match[1]}\n\t\t\t}\n\t}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/codeblock.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/codeinline.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/codeinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for code runs. For example:\n\n```\n\tThis is a `code run`.\n\tThis is another ``code run``\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"codeinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(``?)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar reEnd = new RegExp(this.match[1], \"mg\");\n\t// Look for the end marker\n\treEnd.lastIndex = this.parser.pos;\n\tvar match = reEnd.exec(this.parser.source),\n\t\ttext;\n\t// Process the text\n\tif(match) {\n\t\ttext = this.parser.source.substring(this.parser.pos,match.index);\n\t\tthis.parser.pos = match.index + match[0].length;\n\t} else {\n\t\ttext = this.parser.source.substr(this.parser.pos);\n\t\tthis.parser.pos = this.parser.sourceLength;\n\t}\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"code\",\n\t\tchildren: [{\n\t\t\ttype: \"text\",\n\t\t\ttext: text\n\t\t}]\n\t}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/codeinline.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/commentblock.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/commentblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for HTML comments. For example:\n\n```\n<!-- This is a comment -->\n```\n\nNote that the syntax for comments is simplified to an opening \"<!--\" sequence and a closing \"-->\" sequence -- HTML itself implements a more complex format (see http://ostermiller.org/findhtmlcomment.html)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"commentblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\tthis.matchRegExp = /<!--/mg;\n\tthis.endMatchRegExp = /-->/mg;\n};\n\nexports.findNextMatch = function(startPos) {\n\tthis.matchRegExp.lastIndex = startPos;\n\tthis.match = this.matchRegExp.exec(this.parser.source);\n\tif(this.match) {\n\t\tthis.endMatchRegExp.lastIndex = startPos + this.match[0].length;\n\t\tthis.endMatch = this.endMatchRegExp.exec(this.parser.source);\n\t\tif(this.endMatch) {\n\t\t\treturn this.match.index;\n\t\t}\n\t}\n\treturn undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.endMatchRegExp.lastIndex;\n\t// Don't return any elements\n\treturn [];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/commentblock.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/commentinline.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/commentinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for HTML comments. For example:\n\n```\n<!-- This is a comment -->\n```\n\nNote that the syntax for comments is simplified to an opening \"<!--\" sequence and a closing \"-->\" sequence -- HTML itself implements a more complex format (see http://ostermiller.org/findhtmlcomment.html)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"commentinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\tthis.matchRegExp = /<!--/mg;\n\tthis.endMatchRegExp = /-->/mg;\n};\n\nexports.findNextMatch = function(startPos) {\n\tthis.matchRegExp.lastIndex = startPos;\n\tthis.match = this.matchRegExp.exec(this.parser.source);\n\tif(this.match) {\n\t\tthis.endMatchRegExp.lastIndex = startPos + this.match[0].length;\n\t\tthis.endMatch = this.endMatchRegExp.exec(this.parser.source);\n\t\tif(this.endMatch) {\n\t\t\treturn this.match.index;\n\t\t}\n\t}\n\treturn undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.endMatchRegExp.lastIndex;\n\t// Don't return any elements\n\treturn [];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/commentinline.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/dash.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/dash.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for dashes. For example:\n\n```\nThis is an en-dash: --\n\nThis is an em-dash: ---\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"dash\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /-{2,3}(?!-)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar dash = this.match[0].length === 2 ? \"–\" : \"—\";\n\treturn [{\n\t\ttype: \"entity\",\n\t\tentity: dash\n\t}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/dash.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/emphasis/bold.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/bold.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - bold. For example:\n\n```\n\tThis is ''bold'' text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except bold \n\\rules only bold \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"bold\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /''/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/''/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"strong\",\n\t\tchildren: tree\n\t}];\n};\n\n})();", "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/bold.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/emphasis/italic.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/italic.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - italic. For example:\n\n```\n\tThis is //italic// text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except italic\n\\rules only italic\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"italic\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\/\\//mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/\\/\\//mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"em\",\n\t\tchildren: tree\n\t}];\n};\n\n})();", "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/italic.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - strikethrough. For example:\n\n```\n\tThis is ~~strikethrough~~ text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except strikethrough \n\\rules only strikethrough \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"strikethrough\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /~~/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/~~/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"strike\",\n\t\tchildren: tree\n\t}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/emphasis/subscript.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/subscript.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - subscript. For example:\n\n```\n\tThis is ,,subscript,, text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except subscript \n\\rules only subscript \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"subscript\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /,,/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/,,/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"sub\",\n\t\tchildren: tree\n\t}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/subscript.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/emphasis/superscript.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/superscript.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - superscript. For example:\n\n```\n\tThis is ^^superscript^^ text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except superscript \n\\rules only superscript \n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"superscript\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\^\\^/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/\\^\\^/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"sup\",\n\t\tchildren: tree\n\t}];\n};\n\n})();", "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/superscript.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/emphasis/underscore.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/emphasis/underscore.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for emphasis - underscore. For example:\n\n```\n\tThis is __underscore__ text\n```\n\nThis wikiparser can be modified using the rules eg:\n\n```\n\\rules except underscore \n\\rules only underscore\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"underscore\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /__/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\n\t// Parse the run including the terminator\n\tvar tree = this.parser.parseInlineRun(/__/mg,{eatTerminator: true});\n\n\t// Return the classed span\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"u\",\n\t\tchildren: tree\n\t}];\n};\n\n})();", "title": "$:/core/modules/parsers/wikiparser/rules/emphasis/underscore.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/entity.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/entity.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for HTML entities. For example:\n\n```\n\tThis is a copyright symbol: ©\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"entity\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(&#?[a-zA-Z0-9]{2,8};)/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar entityString = this.match[1];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Return the entity\n\treturn [{type: \"entity\", entity: this.match[0]}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/entity.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/extlink.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/extlink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for external links. For example:\n\n```\nAn external link: http://www.tiddlywiki.com/\n\nA suppressed external link: ~http://www.tiddlyspace.com/\n```\n\nExternal links can be suppressed by preceding them with `~`.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"extlink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /~?(?:file|http|https|mailto|ftp|irc|news|data|skype):[^\\s<>{}\\[\\]`|\"\\\\^]+(?:\\/|\\b)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Create the link unless it is suppressed\n\tif(this.match[0].substr(0,1) === \"~\") {\n\t\treturn [{type: \"text\", text: this.match[0].substr(1)}];\n\t} else {\n\t\treturn [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"a\",\n\t\t\tattributes: {\n\t\t\t\thref: {type: \"string\", value: this.match[0]},\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-tiddlylink-external\"},\n\t\t\t\ttarget: {type: \"string\", value: \"_blank\"},\n\t\t\t\trel: {type: \"string\", value: \"noopener noreferrer\"}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\", text: this.match[0]\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/extlink.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for block-level filtered transclusion. For example:\n\n```\n{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"filteredtranscludeblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{\\{([^\\|]+?)(?:\\|([^\\|\\{\\}]+))?(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}([^\\}]*)\\}(?:\\.(\\S+))?(?:\\r?\\n|$)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar filter = this.match[1],\n\t\ttooltip = this.match[2],\n\t\ttemplate = $tw.utils.trim(this.match[3]),\n\t\tstyle = this.match[4],\n\t\tclasses = this.match[5];\n\t// Return the list widget\n\tvar node = {\n\t\ttype: \"list\",\n\t\tattributes: {\n\t\t\tfilter: {type: \"string\", value: filter}\n\t\t},\n\t\tisBlock: true\n\t};\n\tif(tooltip) {\n\t\tnode.attributes.tooltip = {type: \"string\", value: tooltip};\n\t}\n\tif(template) {\n\t\tnode.attributes.template = {type: \"string\", value: template};\n\t}\n\tif(style) {\n\t\tnode.attributes.style = {type: \"string\", value: style};\n\t}\n\tif(classes) {\n\t\tnode.attributes.itemClass = {type: \"string\", value: classes.split(\".\").join(\" \")};\n\t}\n\treturn [node];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for inline filtered transclusion. For example:\n\n```\n{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"filteredtranscludeinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{\\{([^\\|]+?)(?:\\|([^\\|\\{\\}]+))?(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}([^\\}]*)\\}(?:\\.(\\S+))?/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar filter = this.match[1],\n\t\ttooltip = this.match[2],\n\t\ttemplate = $tw.utils.trim(this.match[3]),\n\t\tstyle = this.match[4],\n\t\tclasses = this.match[5];\n\t// Return the list widget\n\tvar node = {\n\t\ttype: \"list\",\n\t\tattributes: {\n\t\t\tfilter: {type: \"string\", value: filter}\n\t\t}\n\t};\n\tif(tooltip) {\n\t\tnode.attributes.tooltip = {type: \"string\", value: tooltip};\n\t}\n\tif(template) {\n\t\tnode.attributes.template = {type: \"string\", value: template};\n\t}\n\tif(style) {\n\t\tnode.attributes.style = {type: \"string\", value: style};\n\t}\n\tif(classes) {\n\t\tnode.attributes.itemClass = {type: \"string\", value: classes.split(\".\").join(\" \")};\n\t}\n\treturn [node];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/hardlinebreaks.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/hardlinebreaks.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for marking areas with hard line breaks. For example:\n\n```\n\"\"\"\nThis is some text\nThat is set like\nIt is a Poem\nWhen it is\nClearly\nNot\n\"\"\"\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"hardlinebreaks\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\"\"\"(?:\\r?\\n)?/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /(\"\"\")|(\\r?\\n)/mg,\n\t\ttree = [],\n\t\tmatch;\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tdo {\n\t\t// Parse the run up to the terminator\n\t\ttree.push.apply(tree,this.parser.parseInlineRun(reEnd,{eatTerminator: false}));\n\t\t// Redo the terminator match\n\t\treEnd.lastIndex = this.parser.pos;\n\t\tmatch = reEnd.exec(this.parser.source);\n\t\tif(match) {\n\t\t\tthis.parser.pos = reEnd.lastIndex;\n\t\t\t// Add a line break if the terminator was a line break\n\t\t\tif(match[2]) {\n\t\t\t\ttree.push({type: \"element\", tag: \"br\"});\n\t\t\t}\n\t\t}\n\t} while(match && !match[1]);\n\t// Return the nodes\n\treturn tree;\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/hardlinebreaks.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/heading.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/heading.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for headings\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"heading\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(!{1,6})/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar headingLevel = this.match[1].length;\n\t// Move past the !s\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse any classes, whitespace and then the heading itself\n\tvar classes = this.parser.parseClasses();\n\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\tvar tree = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t// Return the heading\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"h\" + headingLevel, \n\t\tattributes: {\n\t\t\t\"class\": {type: \"string\", value: classes.join(\" \")}\n\t\t},\n\t\tchildren: tree\n\t}];\n};\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/heading.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/horizrule.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/horizrule.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for rules. For example:\n\n```\n---\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"horizrule\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /-{3,}\\r?(?:\\n|$)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\treturn [{type: \"element\", tag: \"hr\"}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/horizrule.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/html.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/html.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki rule for HTML elements and widgets. For example:\n\n{{{\n<aside>\nThis is an HTML5 aside element\n</aside>\n\n<$slider target=\"MyTiddler\">\nThis is a widget invocation\n</$slider>\n\n}}}\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"html\";\nexports.types = {inline: true, block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n};\n\nexports.findNextMatch = function(startPos) {\n\t// Find the next tag\n\tthis.nextTag = this.findNextTag(this.parser.source,startPos,{\n\t\trequireLineBreak: this.is.block\n\t});\n\treturn this.nextTag ? this.nextTag.start : undefined;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Retrieve the most recent match so that recursive calls don't overwrite it\n\tvar tag = this.nextTag;\n\tthis.nextTag = null;\n\t// Advance the parser position to past the tag\n\tthis.parser.pos = tag.end;\n\t// Check for an immediately following double linebreak\n\tvar hasLineBreak = !tag.isSelfClosing && !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\\S\\n\\r]*\\r?\\n(?:[^\\S\\n\\r]*\\r?\\n|$))/g);\n\t// Set whether we're in block mode\n\ttag.isBlock = this.is.block || hasLineBreak;\n\t// Parse the body if we need to\n\tif(!tag.isSelfClosing && $tw.config.htmlVoidElements.indexOf(tag.tag) === -1) {\n\t\t\tvar reEndString = \"</\" + $tw.utils.escapeRegExp(tag.tag) + \">\",\n\t\t\t\treEnd = new RegExp(\"(\" + reEndString + \")\",\"mg\");\n\t\tif(hasLineBreak) {\n\t\t\ttag.children = this.parser.parseBlocks(reEndString);\n\t\t} else {\n\t\t\ttag.children = this.parser.parseInlineRun(reEnd);\n\t\t}\n\t\treEnd.lastIndex = this.parser.pos;\n\t\tvar endMatch = reEnd.exec(this.parser.source);\n\t\tif(endMatch && endMatch.index === this.parser.pos) {\n\t\t\tthis.parser.pos = endMatch.index + endMatch[0].length;\n\t\t}\n\t}\n\t// Return the tag\n\treturn [tag];\n};\n\n/*\nLook for an HTML tag. Returns null if not found, otherwise returns {type: \"element\", name:, attributes: [], isSelfClosing:, start:, end:,}\n*/\nexports.parseTag = function(source,pos,options) {\n\toptions = options || {};\n\tvar token,\n\t\tnode = {\n\t\t\ttype: \"element\",\n\t\t\tstart: pos,\n\t\t\tattributes: {}\n\t\t};\n\t// Define our regexps\n\tvar reTagName = /([a-zA-Z0-9\\-\\$]+)/g;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a less than sign\n\ttoken = $tw.utils.parseTokenString(source,pos,\"<\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Get the tag name\n\ttoken = $tw.utils.parseTokenRegExp(source,pos,reTagName);\n\tif(!token) {\n\t\treturn null;\n\t}\n\tnode.tag = token.match[1];\n\tif(node.tag.charAt(0) === \"$\") {\n\t\tnode.type = node.tag.substr(1);\n\t}\n\tpos = token.end;\n\t// Check that the tag is terminated by a space, / or >\n\tif(!$tw.utils.parseWhiteSpace(source,pos) && !(source.charAt(pos) === \"/\") && !(source.charAt(pos) === \">\") ) {\n\t\treturn null;\n\t}\n\t// Process attributes\n\tvar attribute = $tw.utils.parseAttribute(source,pos);\n\twhile(attribute) {\n\t\tnode.attributes[attribute.name] = attribute;\n\t\tpos = attribute.end;\n\t\t// Get the next attribute\n\t\tattribute = $tw.utils.parseAttribute(source,pos);\n\t}\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for a closing slash\n\ttoken = $tw.utils.parseTokenString(source,pos,\"/\");\n\tif(token) {\n\t\tpos = token.end;\n\t\tnode.isSelfClosing = true;\n\t}\n\t// Look for a greater than sign\n\ttoken = $tw.utils.parseTokenString(source,pos,\">\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Check for a required line break\n\tif(options.requireLineBreak) {\n\t\ttoken = $tw.utils.parseTokenRegExp(source,pos,/([^\\S\\n\\r]*\\r?\\n(?:[^\\S\\n\\r]*\\r?\\n|$))/g);\n\t\tif(!token) {\n\t\t\treturn null;\n\t\t}\n\t}\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\nexports.findNextTag = function(source,pos,options) {\n\t// A regexp for finding candidate HTML tags\n\tvar reLookahead = /<([a-zA-Z\\-\\$]+)/g;\n\t// Find the next candidate\n\treLookahead.lastIndex = pos;\n\tvar match = reLookahead.exec(source);\n\twhile(match) {\n\t\t// Try to parse the candidate as a tag\n\t\tvar tag = this.parseTag(source,match.index,options);\n\t\t// Return success\n\t\tif(tag && this.isLegalTag(tag)) {\n\t\t\treturn tag;\n\t\t}\n\t\t// Look for the next match\n\t\treLookahead.lastIndex = match.index + 1;\n\t\tmatch = reLookahead.exec(source);\n\t}\n\t// Failed\n\treturn null;\n};\n\nexports.isLegalTag = function(tag) {\n\t// Widgets are always OK\n\tif(tag.type !== \"element\") {\n\t\treturn true;\n\t// If it's an HTML tag that starts with a dash then it's not legal\n\t} else if(tag.tag.charAt(0) === \"-\") {\n\t\treturn false;\n\t} else {\n\t\t// Otherwise it's OK\n\t\treturn true;\n\t}\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/html.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/image.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/image.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for embedding images. For example:\n\n```\n[img[http://tiddlywiki.com/fractalveg.jpg]]\n[img width=23 height=24 [http://tiddlywiki.com/fractalveg.jpg]]\n[img width={{!!width}} height={{!!height}} [http://tiddlywiki.com/fractalveg.jpg]]\n[img[Description of image|http://tiddlywiki.com/fractalveg.jpg]]\n[img[TiddlerTitle]]\n[img[Description of image|TiddlerTitle]]\n```\n\nGenerates the `<$image>` widget.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"image\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n};\n\nexports.findNextMatch = function(startPos) {\n\t// Find the next tag\n\tthis.nextImage = this.findNextImage(this.parser.source,startPos);\n\treturn this.nextImage ? this.nextImage.start : undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.nextImage.end;\n\tvar node = {\n\t\ttype: \"image\",\n\t\tattributes: this.nextImage.attributes\n\t};\n\treturn [node];\n};\n\n/*\nFind the next image from the current position\n*/\nexports.findNextImage = function(source,pos) {\n\t// A regexp for finding candidate HTML tags\n\tvar reLookahead = /(\\[img)/g;\n\t// Find the next candidate\n\treLookahead.lastIndex = pos;\n\tvar match = reLookahead.exec(source);\n\twhile(match) {\n\t\t// Try to parse the candidate as a tag\n\t\tvar tag = this.parseImage(source,match.index);\n\t\t// Return success\n\t\tif(tag) {\n\t\t\treturn tag;\n\t\t}\n\t\t// Look for the next match\n\t\treLookahead.lastIndex = match.index + 1;\n\t\tmatch = reLookahead.exec(source);\n\t}\n\t// Failed\n\treturn null;\n};\n\n/*\nLook for an image at the specified position. Returns null if not found, otherwise returns {type: \"image\", attributes: [], isSelfClosing:, start:, end:,}\n*/\nexports.parseImage = function(source,pos) {\n\tvar token,\n\t\tnode = {\n\t\t\ttype: \"image\",\n\t\t\tstart: pos,\n\t\t\tattributes: {}\n\t\t};\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the `[img`\n\ttoken = $tw.utils.parseTokenString(source,pos,\"[img\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Process attributes\n\tif(source.charAt(pos) !== \"[\") {\n\t\tvar attribute = $tw.utils.parseAttribute(source,pos);\n\t\twhile(attribute) {\n\t\t\tnode.attributes[attribute.name] = attribute;\n\t\t\tpos = attribute.end;\n\t\t\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t\t\tif(source.charAt(pos) !== \"[\") {\n\t\t\t\t// Get the next attribute\n\t\t\t\tattribute = $tw.utils.parseAttribute(source,pos);\n\t\t\t} else {\n\t\t\t\tattribute = null;\n\t\t\t}\n\t\t}\n\t}\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the `[` after the attributes\n\ttoken = $tw.utils.parseTokenString(source,pos,\"[\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Get the source up to the terminating `]]`\n\ttoken = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\\]]*?)\\|)?([^\\]]+?)\\]\\]/g);\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\tif(token.match[1]) {\n\t\tnode.attributes.tooltip = {type: \"string\", value: token.match[1].trim()};\n\t}\n\tnode.attributes.source = {type: \"string\", value: (token.match[2] || \"\").trim()};\n\t// Update the end position\n\tnode.end = pos;\n\treturn node;\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/image.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/list.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/list.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for lists. For example:\n\n```\n* This is an unordered list\n* It has two items\n\n# This is a numbered list\n## With a subitem\n# And a third item\n\n; This is a term that is being defined\n: This is the definition of that term\n```\n\nNote that lists can be nested arbitrarily:\n\n```\n#** One\n#* Two\n#** Three\n#**** Four\n#**# Five\n#**## Six\n## Seven\n### Eight\n## Nine\n```\n\nA CSS class can be applied to a list item as follows:\n\n```\n* List item one\n*.active List item two has the class `active`\n* List item three\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"list\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /([\\*#;:>]+)/mg;\n};\n\nvar listTypes = {\n\t\"*\": {listTag: \"ul\", itemTag: \"li\"},\n\t\"#\": {listTag: \"ol\", itemTag: \"li\"},\n\t\";\": {listTag: \"dl\", itemTag: \"dt\"},\n\t\":\": {listTag: \"dl\", itemTag: \"dd\"},\n\t\">\": {listTag: \"blockquote\", itemTag: \"p\"}\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Array of parse tree nodes for the previous row of the list\n\tvar listStack = [];\n\t// Cycle through the items in the list\n\twhile(true) {\n\t\t// Match the list marker\n\t\tvar reMatch = /([\\*#;:>]+)/mg;\n\t\treMatch.lastIndex = this.parser.pos;\n\t\tvar match = reMatch.exec(this.parser.source);\n\t\tif(!match || match.index !== this.parser.pos) {\n\t\t\tbreak;\n\t\t}\n\t\t// Check whether the list type of the top level matches\n\t\tvar listInfo = listTypes[match[0].charAt(0)];\n\t\tif(listStack.length > 0 && listStack[0].tag !== listInfo.listTag) {\n\t\t\tbreak;\n\t\t}\n\t\t// Move past the list marker\n\t\tthis.parser.pos = match.index + match[0].length;\n\t\t// Walk through the list markers for the current row\n\t\tfor(var t=0; t<match[0].length; t++) {\n\t\t\tlistInfo = listTypes[match[0].charAt(t)];\n\t\t\t// Remove any stacked up element if we can't re-use it because the list type doesn't match\n\t\t\tif(listStack.length > t && listStack[t].tag !== listInfo.listTag) {\n\t\t\t\tlistStack.splice(t,listStack.length - t);\n\t\t\t}\n\t\t\t// Construct the list element or reuse the previous one at this level\n\t\t\tif(listStack.length <= t) {\n\t\t\t\tvar listElement = {type: \"element\", tag: listInfo.listTag, children: [\n\t\t\t\t\t{type: \"element\", tag: listInfo.itemTag, children: []}\n\t\t\t\t]};\n\t\t\t\t// Link this list element into the last child item of the parent list item\n\t\t\t\tif(t) {\n\t\t\t\t\tvar prevListItem = listStack[t-1].children[listStack[t-1].children.length-1];\n\t\t\t\t\tprevListItem.children.push(listElement);\n\t\t\t\t}\n\t\t\t\t// Save this element in the stack\n\t\t\t\tlistStack[t] = listElement;\n\t\t\t} else if(t === (match[0].length - 1)) {\n\t\t\t\tlistStack[t].children.push({type: \"element\", tag: listInfo.itemTag, children: []});\n\t\t\t}\n\t\t}\n\t\tif(listStack.length > match[0].length) {\n\t\t\tlistStack.splice(match[0].length,listStack.length - match[0].length);\n\t\t}\n\t\t// Process the body of the list item into the last list item\n\t\tvar lastListChildren = listStack[listStack.length-1].children,\n\t\t\tlastListItem = lastListChildren[lastListChildren.length-1],\n\t\t\tclasses = this.parser.parseClasses();\n\t\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\t\tvar tree = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t\tlastListItem.children.push.apply(lastListItem.children,tree);\n\t\tif(classes.length > 0) {\n\t\t\t$tw.utils.addClassToParseTreeNode(lastListItem,classes.join(\" \"));\n\t\t}\n\t\t// Consume any whitespace following the list item\n\t\tthis.parser.skipWhitespace();\n\t}\n\t// Return the root element of the list\n\treturn [listStack[0]];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/list.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/macrocallblock.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/macrocallblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki rule for block macro calls\n\n```\n<<name value value2>>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"macrocallblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /<<([^>\\s]+)(?:\\s*)((?:[^>]|(?:>(?!>)))*?)>>(?:\\r?\\n|$)/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar macroName = this.match[1],\n\t\tparamString = this.match[2];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar params = [],\n\t\treParam = /\\s*(?:([A-Za-z0-9\\-_]+)\\s*:)?(?:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\"'\\s]+)))/mg,\n\t\tparamMatch = reParam.exec(paramString);\n\twhile(paramMatch) {\n\t\t// Process this parameter\n\t\tvar paramInfo = {\n\t\t\tvalue: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5] || paramMatch[6]\n\t\t};\n\t\tif(paramMatch[1]) {\n\t\t\tparamInfo.name = paramMatch[1];\n\t\t}\n\t\tparams.push(paramInfo);\n\t\t// Find the next match\n\t\tparamMatch = reParam.exec(paramString);\n\t}\n\treturn [{\n\t\ttype: \"macrocall\",\n\t\tname: macroName,\n\t\tparams: params,\n\t\tisBlock: true\n\t}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/macrocallblock.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/macrocallinline.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/macrocallinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki rule for macro calls\n\n```\n<<name value value2>>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"macrocallinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /<<([^\\s>]+)\\s*([\\s\\S]*?)>>/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get all the details of the match\n\tvar macroName = this.match[1],\n\t\tparamString = this.match[2];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\tvar params = [],\n\t\treParam = /\\s*(?:([A-Za-z0-9\\-_]+)\\s*:)?(?:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\"'\\s]+)))/mg,\n\t\tparamMatch = reParam.exec(paramString);\n\twhile(paramMatch) {\n\t\t// Process this parameter\n\t\tvar paramInfo = {\n\t\t\tvalue: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5]|| paramMatch[6]\n\t\t};\n\t\tif(paramMatch[1]) {\n\t\t\tparamInfo.name = paramMatch[1];\n\t\t}\n\t\tparams.push(paramInfo);\n\t\t// Find the next match\n\t\tparamMatch = reParam.exec(paramString);\n\t}\n\treturn [{\n\t\ttype: \"macrocall\",\n\t\tname: macroName,\n\t\tparams: params\n\t}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/macrocallinline.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/macrodef.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/macrodef.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki pragma rule for macro definitions\n\n```\n\\define name(param:defaultvalue,param2:defaultvalue)\ndefinition text, including $param$ markers\n\\end\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"macrodef\";\nexports.types = {pragma: true};\n\n/*\nInstantiate parse rule\n*/\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\\\define\\s+([^(\\s]+)\\(\\s*([^)]*)\\)(\\s*\\r?\\n)?/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Move past the macro name and parameters\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse the parameters\n\tvar paramString = this.match[2],\n\t\tparams = [];\n\tif(paramString !== \"\") {\n\t\tvar reParam = /\\s*([A-Za-z0-9\\-_]+)(?:\\s*:\\s*(?:\"\"\"([\\s\\S]*?)\"\"\"|\"([^\"]*)\"|'([^']*)'|\\[\\[([^\\]]*)\\]\\]|([^\"'\\s]+)))?/mg,\n\t\t\tparamMatch = reParam.exec(paramString);\n\t\twhile(paramMatch) {\n\t\t\t// Save the parameter details\n\t\t\tvar paramInfo = {name: paramMatch[1]},\n\t\t\t\tdefaultValue = paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5] || paramMatch[6];\n\t\t\tif(defaultValue) {\n\t\t\t\tparamInfo[\"default\"] = defaultValue;\n\t\t\t}\n\t\t\tparams.push(paramInfo);\n\t\t\t// Look for the next parameter\n\t\t\tparamMatch = reParam.exec(paramString);\n\t\t}\n\t}\n\t// Is this a multiline definition?\n\tvar reEnd;\n\tif(this.match[3]) {\n\t\t// If so, the end of the body is marked with \\end\n\t\treEnd = /(\\r?\\n\\\\end[^\\S\\n\\r]*(?:$|\\r?\\n))/mg;\n\t} else {\n\t\t// Otherwise, the end of the definition is marked by the end of the line\n\t\treEnd = /($|\\r?\\n)/mg;\n\t\t// Move past any whitespace\n\t\tthis.parser.pos = $tw.utils.skipWhiteSpace(this.parser.source,this.parser.pos);\n\t}\n\t// Find the end of the definition\n\treEnd.lastIndex = this.parser.pos;\n\tvar text,\n\t\tendMatch = reEnd.exec(this.parser.source);\n\tif(endMatch) {\n\t\ttext = this.parser.source.substring(this.parser.pos,endMatch.index);\n\t\tthis.parser.pos = endMatch.index + endMatch[0].length;\n\t} else {\n\t\t// We didn't find the end of the definition, so we'll make it blank\n\t\ttext = \"\";\n\t}\n\t// Save the macro definition\n\treturn [{\n\t\ttype: \"set\",\n\t\tattributes: {\n\t\t\tname: {type: \"string\", value: this.match[1]},\n\t\t\tvalue: {type: \"string\", value: text}\n\t\t},\n\t\tchildren: [],\n\t\tparams: params\n\t}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/macrodef.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/prettyextlink.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/prettyextlink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for external links. For example:\n\n```\n[ext[http://tiddlywiki.com/fractalveg.jpg]]\n[ext[Tooltip|http://tiddlywiki.com/fractalveg.jpg]]\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"prettyextlink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n};\n\nexports.findNextMatch = function(startPos) {\n\t// Find the next tag\n\tthis.nextLink = this.findNextLink(this.parser.source,startPos);\n\treturn this.nextLink ? this.nextLink.start : undefined;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.nextLink.end;\n\treturn [this.nextLink];\n};\n\n/*\nFind the next link from the current position\n*/\nexports.findNextLink = function(source,pos) {\n\t// A regexp for finding candidate links\n\tvar reLookahead = /(\\[ext\\[)/g;\n\t// Find the next candidate\n\treLookahead.lastIndex = pos;\n\tvar match = reLookahead.exec(source);\n\twhile(match) {\n\t\t// Try to parse the candidate as a link\n\t\tvar link = this.parseLink(source,match.index);\n\t\t// Return success\n\t\tif(link) {\n\t\t\treturn link;\n\t\t}\n\t\t// Look for the next match\n\t\treLookahead.lastIndex = match.index + 1;\n\t\tmatch = reLookahead.exec(source);\n\t}\n\t// Failed\n\treturn null;\n};\n\n/*\nLook for an link at the specified position. Returns null if not found, otherwise returns {type: \"element\", tag: \"a\", attributes: [], isSelfClosing:, start:, end:,}\n*/\nexports.parseLink = function(source,pos) {\n\tvar token,\n\t\ttextNode = {\n\t\t\ttype: \"text\"\n\t\t},\n\t\tnode = {\n\t\t\ttype: \"element\",\n\t\t\ttag: \"a\",\n\t\t\tstart: pos,\n\t\t\tattributes: {\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-tiddlylink-external\"},\n\t\t\t},\n\t\t\tchildren: [textNode]\n\t\t};\n\t// Skip whitespace\n\tpos = $tw.utils.skipWhiteSpace(source,pos);\n\t// Look for the `[ext[`\n\ttoken = $tw.utils.parseTokenString(source,pos,\"[ext[\");\n\tif(!token) {\n\t\treturn null;\n\t}\n\tpos = token.end;\n\t// Look ahead for the terminating `]]`\n\tvar closePos = source.indexOf(\"]]\",pos);\n\tif(closePos === -1) {\n\t\treturn null;\n\t}\n\t// Look for a `|` separating the tooltip\n\tvar splitPos = source.indexOf(\"|\",pos);\n\tif(splitPos === -1 || splitPos > closePos) {\n\t\tsplitPos = null;\n\t}\n\t// Pull out the tooltip and URL\n\tvar tooltip, URL;\n\tif(splitPos) {\n\t\tURL = source.substring(splitPos + 1,closePos).trim();\n\t\ttextNode.text = source.substring(pos,splitPos).trim();\n\t} else {\n\t\tURL = source.substring(pos,closePos).trim();\n\t\ttextNode.text = URL;\n\t}\n\tnode.attributes.href = {type: \"string\", value: URL};\n\tnode.attributes.target = {type: \"string\", value: \"_blank\"};\n\tnode.attributes.rel = {type: \"string\", value: \"noopener noreferrer\"};\n\t// Update the end position\n\tnode.end = closePos + 2;\n\treturn node;\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/prettyextlink.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/prettylink.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/prettylink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for pretty links. For example:\n\n```\n[[Introduction]]\n\n[[Link description|TiddlerTitle]]\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"prettylink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\[\\[(.*?)(?:\\|(.*?))?\\]\\]/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Process the link\n\tvar text = this.match[1],\n\t\tlink = this.match[2] || text;\n\tif($tw.utils.isLinkExternal(link)) {\n\t\treturn [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"a\",\n\t\t\tattributes: {\n\t\t\t\thref: {type: \"string\", value: link},\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-tiddlylink-external\"},\n\t\t\t\ttarget: {type: \"string\", value: \"_blank\"},\n\t\t\t\trel: {type: \"string\", value: \"noopener noreferrer\"}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\", text: text\n\t\t\t}]\n\t\t}];\n\t} else {\n\t\treturn [{\n\t\t\ttype: \"link\",\n\t\t\tattributes: {\n\t\t\t\tto: {type: \"string\", value: link}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\", text: text\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/prettylink.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/quoteblock.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/quoteblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for quote blocks. For example:\n\n```\n\t<<<.optionalClass(es) optional cited from\n\ta quote\n\t<<<\n\t\n\t<<<.optionalClass(es)\n\ta quote\n\t<<< optional cited from\n```\n\nQuotes can be quoted by putting more <s\n\n```\n\t<<<\n\tQuote Level 1\n\t\n\t<<<<\n\tQuoteLevel 2\n\t<<<<\n\t\n\t<<<\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"quoteblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /(<<<+)/mg;\n};\n\nexports.parse = function() {\n\tvar classes = [\"tc-quote\"];\n\t// Get all the details of the match\n\tvar reEndString = \"^\" + this.match[1] + \"(?!<)\";\n\t// Move past the <s\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t\n\t// Parse any classes, whitespace and then the optional cite itself\n\tclasses.push.apply(classes, this.parser.parseClasses());\n\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\tvar cite = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t// before handling the cite, parse the body of the quote\n\tvar tree= this.parser.parseBlocks(reEndString);\n\t// If we got a cite, put it before the text\n\tif(cite.length > 0) {\n\t\ttree.unshift({\n\t\t\ttype: \"element\",\n\t\t\ttag: \"cite\",\n\t\t\tchildren: cite\n\t\t});\n\t}\n\t// Parse any optional cite\n\tthis.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});\n\tcite = this.parser.parseInlineRun(/(\\r?\\n)/mg);\n\t// If we got a cite, push it\n\tif(cite.length > 0) {\n\t\ttree.push({\n\t\t\ttype: \"element\",\n\t\t\ttag: \"cite\",\n\t\t\tchildren: cite\n\t\t});\n\t}\n\t// Return the blockquote element\n\treturn [{\n\t\ttype: \"element\",\n\t\ttag: \"blockquote\",\n\t\tattributes: {\n\t\t\tclass: { type: \"string\", value: classes.join(\" \") },\n\t\t},\n\t\tchildren: tree\n\t}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/quoteblock.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/rules.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/rules.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki pragma rule for rules specifications\n\n```\n\\rules except ruleone ruletwo rulethree\n\\rules only ruleone ruletwo rulethree\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"rules\";\nexports.types = {pragma: true};\n\n/*\nInstantiate parse rule\n*/\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\\\rules[^\\S\\n]/mg;\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Move past the pragma invocation\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse whitespace delimited tokens terminated by a line break\n\tvar reMatch = /[^\\S\\n]*(\\S+)|(\\r?\\n)/mg,\n\t\ttokens = [];\n\treMatch.lastIndex = this.parser.pos;\n\tvar match = reMatch.exec(this.parser.source);\n\twhile(match && match.index === this.parser.pos) {\n\t\tthis.parser.pos = reMatch.lastIndex;\n\t\t// Exit if we've got the line break\n\t\tif(match[2]) {\n\t\t\tbreak;\n\t\t}\n\t\t// Process the token\n\t\tif(match[1]) {\n\t\t\ttokens.push(match[1]);\n\t\t}\n\t\t// Match the next token\n\t\tmatch = reMatch.exec(this.parser.source);\n\t}\n\t// Process the tokens\n\tif(tokens.length > 0) {\n\t\tthis.parser.amendRules(tokens[0],tokens.slice(1));\n\t}\n\t// No parse tree nodes to return\n\treturn [];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/rules.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/styleblock.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/styleblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for assigning styles and classes to paragraphs and other blocks. For example:\n\n```\n@@.myClass\n@@background-color:red;\nThis paragraph will have the CSS class `myClass`.\n\n* The `<ul>` around this list will also have the class `myClass`\n* List item 2\n\n@@\n```\n\nNote that classes and styles can be mixed subject to the rule that styles must precede classes. For example\n\n```\n@@.myFirstClass.mySecondClass\n@@width:100px;.myThirdClass\nThis is a paragraph\n@@\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"styleblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /@@((?:[^\\.\\r\\n\\s:]+:[^\\r\\n;]+;)+)?(?:\\.([^\\r\\n\\s]+))?\\r?\\n/mg;\n};\n\nexports.parse = function() {\n\tvar reEndString = \"^@@(?:\\\\r?\\\\n)?\";\n\tvar classes = [], styles = [];\n\tdo {\n\t\t// Get the class and style\n\t\tif(this.match[1]) {\n\t\t\tstyles.push(this.match[1]);\n\t\t}\n\t\tif(this.match[2]) {\n\t\t\tclasses.push(this.match[2].split(\".\").join(\" \"));\n\t\t}\n\t\t// Move past the match\n\t\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t\t// Look for another line of classes and styles\n\t\tthis.match = this.matchRegExp.exec(this.parser.source);\n\t} while(this.match && this.match.index === this.parser.pos);\n\t// Parse the body\n\tvar tree = this.parser.parseBlocks(reEndString);\n\tfor(var t=0; t<tree.length; t++) {\n\t\tif(classes.length > 0) {\n\t\t\t$tw.utils.addClassToParseTreeNode(tree[t],classes.join(\" \"));\n\t\t}\n\t\tif(styles.length > 0) {\n\t\t\t$tw.utils.addAttributeToParseTreeNode(tree[t],\"style\",styles.join(\"\"));\n\t\t}\n\t}\n\treturn tree;\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/styleblock.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/styleinline.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/styleinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for assigning styles and classes to inline runs. For example:\n\n```\n@@.myClass This is some text with a class@@\n@@background-color:red;This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@\n```\n\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"styleinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /@@((?:[^\\.\\r\\n\\s:]+:[^\\r\\n;]+;)+)?(\\.(?:[^\\r\\n\\s]+)\\s+)?/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /@@/g;\n\t// Get the styles and class\n\tvar stylesString = this.match[1],\n\t\tclassString = this.match[2] ? this.match[2].split(\".\").join(\" \") : undefined;\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Parse the run up to the terminator\n\tvar tree = this.parser.parseInlineRun(reEnd,{eatTerminator: true});\n\t// Return the classed span\n\tvar node = {\n\t\ttype: \"element\",\n\t\ttag: \"span\",\n\t\tattributes: {\n\t\t\t\"class\": {type: \"string\", value: \"tc-inline-style\"}\n\t\t},\n\t\tchildren: tree\n\t};\n\tif(classString) {\n\t\t$tw.utils.addClassToParseTreeNode(node,classString);\n\t}\n\tif(stylesString) {\n\t\t$tw.utils.addAttributeToParseTreeNode(node,\"style\",stylesString);\n\t}\n\treturn [node];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/styleinline.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/syslink.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/syslink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for system tiddler links.\nCan be suppressed preceding them with `~`.\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"syslink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = new RegExp(\n\t\t\"~?\\\\$:\\\\/[\" +\n\t\t$tw.config.textPrimitives.anyLetter.substr(1,$tw.config.textPrimitives.anyLetter.length - 2) +\n\t\t\"\\/._-]+\",\n\t\t\"mg\"\n\t);\n};\n\nexports.parse = function() {\n\tvar match = this.match[0];\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Create the link unless it is suppressed\n\tif(match.substr(0,1) === \"~\") {\n\t\treturn [{type: \"text\", text: match.substr(1)}];\n\t} else {\n\t\treturn [{\n\t\t\ttype: \"link\",\n\t\t\tattributes: {\n\t\t\t\tto: {type: \"string\", value: match}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: match\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();", "title": "$:/core/modules/parsers/wikiparser/rules/syslink.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/table.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/table.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text block rule for tables.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"table\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /^\\|(?:[^\\n]*)\\|(?:[fhck]?)\\r?(?:\\n|$)/mg;\n};\n\nvar processRow = function(prevColumns) {\n\tvar cellRegExp = /(?:\\|([^\\n\\|]*)\\|)|(\\|[fhck]?\\r?(?:\\n|$))/mg,\n\t\tcellTermRegExp = /((?:\\x20*)\\|)/mg,\n\t\ttree = [],\n\t\tcol = 0,\n\t\tcolSpanCount = 1,\n\t\tprevCell,\n\t\tvAlign;\n\t// Match a single cell\n\tcellRegExp.lastIndex = this.parser.pos;\n\tvar cellMatch = cellRegExp.exec(this.parser.source);\n\twhile(cellMatch && cellMatch.index === this.parser.pos) {\n\t\tif(cellMatch[1] === \"~\") {\n\t\t\t// Rowspan\n\t\t\tvar last = prevColumns[col];\n\t\t\tif(last) {\n\t\t\t\tlast.rowSpanCount++;\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(last.element,\"rowspan\",last.rowSpanCount);\n\t\t\t\tvAlign = $tw.utils.getAttributeValueFromParseTreeNode(last.element,\"valign\",\"center\");\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(last.element,\"valign\",vAlign);\n\t\t\t\tif(colSpanCount > 1) {\n\t\t\t\t\t$tw.utils.addAttributeToParseTreeNode(last.element,\"colspan\",colSpanCount);\n\t\t\t\t\tcolSpanCount = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Move to just before the `|` terminating the cell\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t} else if(cellMatch[1] === \">\") {\n\t\t\t// Colspan\n\t\t\tcolSpanCount++;\n\t\t\t// Move to just before the `|` terminating the cell\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t} else if(cellMatch[1] === \"<\" && prevCell) {\n\t\t\tcolSpanCount = 1 + $tw.utils.getAttributeValueFromParseTreeNode(prevCell,\"colspan\",1);\n\t\t\t$tw.utils.addAttributeToParseTreeNode(prevCell,\"colspan\",colSpanCount);\n\t\t\tcolSpanCount = 1;\n\t\t\t// Move to just before the `|` terminating the cell\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t} else if(cellMatch[2]) {\n\t\t\t// End of row\n\t\t\tif(prevCell && colSpanCount > 1) {\n\t\t\t\tif(prevCell.attributes && prevCell.attributes && prevCell.attributes.colspan) {\n\t\t\t\t\t\tcolSpanCount += prevCell.attributes.colspan.value;\n\t\t\t\t} else {\n\t\t\t\t\tcolSpanCount -= 1;\n\t\t\t\t}\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(prevCell,\"colspan\",colSpanCount);\n\t\t\t}\n\t\t\tthis.parser.pos = cellRegExp.lastIndex - 1;\n\t\t\tbreak;\n\t\t} else {\n\t\t\t// For ordinary cells, step beyond the opening `|`\n\t\t\tthis.parser.pos++;\n\t\t\t// Look for a space at the start of the cell\n\t\t\tvar spaceLeft = false;\n\t\t\tvAlign = null;\n\t\t\tif(this.parser.source.substr(this.parser.pos).search(/^\\^([^\\^]|\\^\\^)/) === 0) {\n\t\t\t\tvAlign = \"top\";\n\t\t\t} else if(this.parser.source.substr(this.parser.pos).search(/^,([^,]|,,)/) === 0) {\n\t\t\t\tvAlign = \"bottom\";\n\t\t\t}\n\t\t\tif(vAlign) {\n\t\t\t\tthis.parser.pos++;\n\t\t\t}\n\t\t\tvar chr = this.parser.source.substr(this.parser.pos,1);\n\t\t\twhile(chr === \" \") {\n\t\t\t\tspaceLeft = true;\n\t\t\t\tthis.parser.pos++;\n\t\t\t\tchr = this.parser.source.substr(this.parser.pos,1);\n\t\t\t}\n\t\t\t// Check whether this is a heading cell\n\t\t\tvar cell;\n\t\t\tif(chr === \"!\") {\n\t\t\t\tthis.parser.pos++;\n\t\t\t\tcell = {type: \"element\", tag: \"th\", children: []};\n\t\t\t} else {\n\t\t\t\tcell = {type: \"element\", tag: \"td\", children: []};\n\t\t\t}\n\t\t\ttree.push(cell);\n\t\t\t// Record information about this cell\n\t\t\tprevCell = cell;\n\t\t\tprevColumns[col] = {rowSpanCount:1,element:cell};\n\t\t\t// Check for a colspan\n\t\t\tif(colSpanCount > 1) {\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"colspan\",colSpanCount);\n\t\t\t\tcolSpanCount = 1;\n\t\t\t}\n\t\t\t// Parse the cell\n\t\t\tcell.children = this.parser.parseInlineRun(cellTermRegExp,{eatTerminator: true});\n\t\t\t// Set the alignment for the cell\n\t\t\tif(vAlign) {\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"valign\",vAlign);\n\t\t\t}\n\t\t\tif(this.parser.source.substr(this.parser.pos - 2,1) === \" \") { // spaceRight\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"align\",spaceLeft ? \"center\" : \"left\");\n\t\t\t} else if(spaceLeft) {\n\t\t\t\t$tw.utils.addAttributeToParseTreeNode(cell,\"align\",\"right\");\n\t\t\t}\n\t\t\t// Move back to the closing `|`\n\t\t\tthis.parser.pos--;\n\t\t}\n\t\tcol++;\n\t\tcellRegExp.lastIndex = this.parser.pos;\n\t\tcellMatch = cellRegExp.exec(this.parser.source);\n\t}\n\treturn tree;\n};\n\nexports.parse = function() {\n\tvar rowContainerTypes = {\"c\":\"caption\", \"h\":\"thead\", \"\":\"tbody\", \"f\":\"tfoot\"},\n\t\ttable = {type: \"element\", tag: \"table\", children: []},\n\t\trowRegExp = /^\\|([^\\n]*)\\|([fhck]?)\\r?(?:\\n|$)/mg,\n\t\trowTermRegExp = /(\\|(?:[fhck]?)\\r?(?:\\n|$))/mg,\n\t\tprevColumns = [],\n\t\tcurrRowType,\n\t\trowContainer,\n\t\trowCount = 0;\n\t// Match the row\n\trowRegExp.lastIndex = this.parser.pos;\n\tvar rowMatch = rowRegExp.exec(this.parser.source);\n\twhile(rowMatch && rowMatch.index === this.parser.pos) {\n\t\tvar rowType = rowMatch[2];\n\t\t// Check if it is a class assignment\n\t\tif(rowType === \"k\") {\n\t\t\t$tw.utils.addClassToParseTreeNode(table,rowMatch[1]);\n\t\t\tthis.parser.pos = rowMatch.index + rowMatch[0].length;\n\t\t} else {\n\t\t\t// Otherwise, create a new row if this one is of a different type\n\t\t\tif(rowType !== currRowType) {\n\t\t\t\trowContainer = {type: \"element\", tag: rowContainerTypes[rowType], children: []};\n\t\t\t\ttable.children.push(rowContainer);\n\t\t\t\tcurrRowType = rowType;\n\t\t\t}\n\t\t\t// Is this a caption row?\n\t\t\tif(currRowType === \"c\") {\n\t\t\t\t// If so, move past the opening `|` of the row\n\t\t\t\tthis.parser.pos++;\n\t\t\t\t// Move the caption to the first row if it isn't already\n\t\t\t\tif(table.children.length !== 1) {\n\t\t\t\t\ttable.children.pop(); // Take rowContainer out of the children array\n\t\t\t\t\ttable.children.splice(0,0,rowContainer); // Insert it at the bottom\t\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t// Set the alignment - TODO: figure out why TW did this\n//\t\t\t\trowContainer.attributes.align = rowCount === 0 ? \"top\" : \"bottom\";\n\t\t\t\t// Parse the caption\n\t\t\t\trowContainer.children = this.parser.parseInlineRun(rowTermRegExp,{eatTerminator: true});\n\t\t\t} else {\n\t\t\t\t// Create the row\n\t\t\t\tvar theRow = {type: \"element\", tag: \"tr\", children: []};\n\t\t\t\t$tw.utils.addClassToParseTreeNode(theRow,rowCount%2 ? \"oddRow\" : \"evenRow\");\n\t\t\t\trowContainer.children.push(theRow);\n\t\t\t\t// Process the row\n\t\t\t\ttheRow.children = processRow.call(this,prevColumns);\n\t\t\t\tthis.parser.pos = rowMatch.index + rowMatch[0].length;\n\t\t\t\t// Increment the row count\n\t\t\t\trowCount++;\n\t\t\t}\n\t\t}\n\t\trowMatch = rowRegExp.exec(this.parser.source);\n\t}\n\treturn [table];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/table.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/transcludeblock.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/transcludeblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for block-level transclusion. For example:\n\n```\n{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"transcludeblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{([^\\{\\}\\|]*)(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}(?:\\r?\\n|$)/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar template = $tw.utils.trim(this.match[2]),\n\t\ttextRef = $tw.utils.trim(this.match[1]);\n\t// Prepare the transclude widget\n\tvar transcludeNode = {\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {},\n\t\t\tisBlock: true\n\t\t};\n\t// Prepare the tiddler widget\n\tvar tr, targetTitle, targetField, targetIndex, tiddlerNode;\n\tif(textRef) {\n\t\ttr = $tw.utils.parseTextReference(textRef);\n\t\ttargetTitle = tr.title;\n\t\ttargetField = tr.field;\n\t\ttargetIndex = tr.index;\n\t\ttiddlerNode = {\n\t\t\ttype: \"tiddler\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: targetTitle}\n\t\t\t},\n\t\t\tisBlock: true,\n\t\t\tchildren: [transcludeNode]\n\t\t};\n\t}\n\tif(template) {\n\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: template};\n\t\tif(textRef) {\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t} else {\n\t\tif(textRef) {\n\t\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: targetTitle};\n\t\t\tif(targetField) {\n\t\t\t\ttranscludeNode.attributes.field = {type: \"string\", value: targetField};\n\t\t\t}\n\t\t\tif(targetIndex) {\n\t\t\t\ttranscludeNode.attributes.index = {type: \"string\", value: targetIndex};\n\t\t\t}\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t}\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/transcludeblock.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/transcludeinline.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/transcludeinline.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for inline-level transclusion. For example:\n\n```\n{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"transcludeinline\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\{\\{([^\\{\\}\\|]*)(?:\\|\\|([^\\|\\{\\}]+))?\\}\\}/mg;\n};\n\nexports.parse = function() {\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Get the match details\n\tvar template = $tw.utils.trim(this.match[2]),\n\t\ttextRef = $tw.utils.trim(this.match[1]);\n\t// Prepare the transclude widget\n\tvar transcludeNode = {\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {}\n\t\t};\n\t// Prepare the tiddler widget\n\tvar tr, targetTitle, targetField, targetIndex, tiddlerNode;\n\tif(textRef) {\n\t\ttr = $tw.utils.parseTextReference(textRef);\n\t\ttargetTitle = tr.title;\n\t\ttargetField = tr.field;\n\t\ttargetIndex = tr.index;\n\t\ttiddlerNode = {\n\t\t\ttype: \"tiddler\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {type: \"string\", value: targetTitle}\n\t\t\t},\n\t\t\tchildren: [transcludeNode]\n\t\t};\n\t}\n\tif(template) {\n\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: template};\n\t\tif(textRef) {\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t} else {\n\t\tif(textRef) {\n\t\t\ttranscludeNode.attributes.tiddler = {type: \"string\", value: targetTitle};\n\t\t\tif(targetField) {\n\t\t\t\ttranscludeNode.attributes.field = {type: \"string\", value: targetField};\n\t\t\t}\n\t\t\tif(targetIndex) {\n\t\t\t\ttranscludeNode.attributes.index = {type: \"string\", value: targetIndex};\n\t\t\t}\n\t\t\treturn [tiddlerNode];\n\t\t} else {\n\t\t\treturn [transcludeNode];\n\t\t}\n\t}\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/transcludeinline.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/typedblock.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/typedblock.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text rule for typed blocks. For example:\n\n```\n$$$.js\nThis will be rendered as JavaScript\n$$$\n\n$$$.svg\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"150\" height=\"100\">\n <circle cx=\"100\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"2\" fill=\"red\" />\n</svg>\n$$$\n\n$$$text/vnd.tiddlywiki>text/html\nThis will be rendered as an //HTML representation// of WikiText\n$$$\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.name = \"typedblock\";\nexports.types = {block: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = /\\$\\$\\$([^ >\\r\\n]*)(?: *> *([^ \\r\\n]+))?\\r?\\n/mg;\n};\n\nexports.parse = function() {\n\tvar reEnd = /\\r?\\n\\$\\$\\$\\r?(?:\\n|$)/mg;\n\t// Save the type\n\tvar parseType = this.match[1],\n\t\trenderType = this.match[2];\n\t// Move past the match\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// Look for the end of the block\n\treEnd.lastIndex = this.parser.pos;\n\tvar match = reEnd.exec(this.parser.source),\n\t\ttext;\n\t// Process the block\n\tif(match) {\n\t\ttext = this.parser.source.substring(this.parser.pos,match.index);\n\t\tthis.parser.pos = match.index + match[0].length;\n\t} else {\n\t\ttext = this.parser.source.substr(this.parser.pos);\n\t\tthis.parser.pos = this.parser.sourceLength;\n\t}\n\t// Parse the block according to the specified type\n\tvar parser = this.parser.wiki.parseText(parseType,text,{defaultType: \"text/plain\"});\n\t// If there's no render type, just return the parse tree\n\tif(!renderType) {\n\t\treturn parser.tree;\n\t} else {\n\t\t// Otherwise, render to the rendertype and return in a <PRE> tag\n\t\tvar widgetNode = this.parser.wiki.makeWidget(parser),\n\t\t\tcontainer = $tw.fakeDocument.createElement(\"div\");\n\t\twidgetNode.render(container,null);\n\t\ttext = renderType === \"text/html\" ? container.innerHTML : container.textContent;\n\t\treturn [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"pre\",\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: text\n\t\t\t}]\n\t\t}];\n\t}\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/typedblock.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/rules/wikilink.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/wikilink.js\ntype: application/javascript\nmodule-type: wikirule\n\nWiki text inline rule for wiki links. For example:\n\n```\nAWikiLink\nAnotherLink\n~SuppressedLink\n```\n\nPrecede a camel case word with `~` to prevent it from being recognised as a link.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.name = \"wikilink\";\nexports.types = {inline: true};\n\nexports.init = function(parser) {\n\tthis.parser = parser;\n\t// Regexp to match\n\tthis.matchRegExp = new RegExp($tw.config.textPrimitives.unWikiLink + \"?\" + $tw.config.textPrimitives.wikiLink,\"mg\");\n};\n\n/*\nParse the most recent match\n*/\nexports.parse = function() {\n\t// Get the details of the match\n\tvar linkText = this.match[0];\n\t// Move past the macro call\n\tthis.parser.pos = this.matchRegExp.lastIndex;\n\t// If the link starts with the unwikilink character then just output it as plain text\n\tif(linkText.substr(0,1) === $tw.config.textPrimitives.unWikiLink) {\n\t\treturn [{type: \"text\", text: linkText.substr(1)}];\n\t}\n\t// If the link has been preceded with a blocked letter then don't treat it as a link\n\tif(this.match.index > 0) {\n\t\tvar preRegExp = new RegExp($tw.config.textPrimitives.blockPrefixLetters,\"mg\");\n\t\tpreRegExp.lastIndex = this.match.index-1;\n\t\tvar preMatch = preRegExp.exec(this.parser.source);\n\t\tif(preMatch && preMatch.index === this.match.index-1) {\n\t\t\treturn [{type: \"text\", text: linkText}];\n\t\t}\n\t}\n\treturn [{\n\t\ttype: \"link\",\n\t\tattributes: {\n\t\t\tto: {type: \"string\", value: linkText}\n\t\t},\n\t\tchildren: [{\n\t\t\ttype: \"text\",\n\t\t\ttext: linkText\n\t\t}]\n\t}];\n};\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/wikilink.js", "type": "application/javascript", "module-type": "wikirule" }, "$:/core/modules/parsers/wikiparser/wikiparser.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/wikiparser.js\ntype: application/javascript\nmodule-type: parser\n\nThe wiki text parser processes blocks of source text into a parse tree.\n\nThe parse tree is made up of nested arrays of these JavaScript objects:\n\n\t{type: \"element\", tag: <string>, attributes: {}, children: []} - an HTML element\n\t{type: \"text\", text: <string>} - a text node\n\t{type: \"entity\", value: <string>} - an entity\n\t{type: \"raw\", html: <string>} - raw HTML\n\nAttributes are stored as hashmaps of the following objects:\n\n\t{type: \"string\", value: <string>} - literal string\n\t{type: \"indirect\", textReference: <textReference>} - indirect through a text reference\n\t{type: \"macro\", macro: <TBD>} - indirect through a macro invocation\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar WikiParser = function(type,text,options) {\n\tthis.wiki = options.wiki;\n\tvar self = this;\n\t// Check for an externally linked tiddler\n\tif($tw.browser && (text || \"\") === \"\" && options._canonical_uri) {\n\t\tthis.loadRemoteTiddler(options._canonical_uri);\n\t\ttext = $tw.language.getRawString(\"LazyLoadingWarning\");\n\t}\n\t// Initialise the classes if we don't have them already\n\tif(!this.pragmaRuleClasses) {\n\t\tWikiParser.prototype.pragmaRuleClasses = $tw.modules.createClassesFromModules(\"wikirule\",\"pragma\",$tw.WikiRuleBase);\n\t\tthis.setupRules(WikiParser.prototype.pragmaRuleClasses,\"$:/config/WikiParserRules/Pragmas/\");\n\t}\n\tif(!this.blockRuleClasses) {\n\t\tWikiParser.prototype.blockRuleClasses = $tw.modules.createClassesFromModules(\"wikirule\",\"block\",$tw.WikiRuleBase);\n\t\tthis.setupRules(WikiParser.prototype.blockRuleClasses,\"$:/config/WikiParserRules/Block/\");\n\t}\n\tif(!this.inlineRuleClasses) {\n\t\tWikiParser.prototype.inlineRuleClasses = $tw.modules.createClassesFromModules(\"wikirule\",\"inline\",$tw.WikiRuleBase);\n\t\tthis.setupRules(WikiParser.prototype.inlineRuleClasses,\"$:/config/WikiParserRules/Inline/\");\n\t}\n\t// Save the parse text\n\tthis.type = type || \"text/vnd.tiddlywiki\";\n\tthis.source = text || \"\";\n\tthis.sourceLength = this.source.length;\n\t// Set current parse position\n\tthis.pos = 0;\n\t// Instantiate the pragma parse rules\n\tthis.pragmaRules = this.instantiateRules(this.pragmaRuleClasses,\"pragma\",0);\n\t// Instantiate the parser block and inline rules\n\tthis.blockRules = this.instantiateRules(this.blockRuleClasses,\"block\",0);\n\tthis.inlineRules = this.instantiateRules(this.inlineRuleClasses,\"inline\",0);\n\t// Parse any pragmas\n\tthis.tree = [];\n\tvar topBranch = this.parsePragmas();\n\t// Parse the text into inline runs or blocks\n\tif(options.parseAsInline) {\n\t\ttopBranch.push.apply(topBranch,this.parseInlineRun());\n\t} else {\n\t\ttopBranch.push.apply(topBranch,this.parseBlocks());\n\t}\n\t// Return the parse tree\n};\n\n/*\n*/\nWikiParser.prototype.loadRemoteTiddler = function(url) {\n\tvar self = this;\n\t$tw.utils.httpRequest({\n\t\turl: url,\n\t\ttype: \"GET\",\n\t\tcallback: function(err,data) {\n\t\t\tif(!err) {\n\t\t\t\tvar tiddlers = self.wiki.deserializeTiddlers(\".tid\",data,self.wiki.getCreationFields());\n\t\t\t\t$tw.utils.each(tiddlers,function(tiddler) {\n\t\t\t\t\ttiddler[\"_canonical_uri\"] = url;\n\t\t\t\t});\n\t\t\t\tif(tiddlers) {\n\t\t\t\t\tself.wiki.addTiddlers(tiddlers);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\n*/\nWikiParser.prototype.setupRules = function(proto,configPrefix) {\n\tvar self = this;\n\tif(!$tw.safemode) {\n\t\t$tw.utils.each(proto,function(object,name) {\n\t\t\tif(self.wiki.getTiddlerText(configPrefix + name,\"enable\") !== \"enable\") {\n\t\t\t\tdelete proto[name];\n\t\t\t}\n\t\t});\n\t}\n};\n\n/*\nInstantiate an array of parse rules\n*/\nWikiParser.prototype.instantiateRules = function(classes,type,startPos) {\n\tvar rulesInfo = [],\n\t\tself = this;\n\t$tw.utils.each(classes,function(RuleClass) {\n\t\t// Instantiate the rule\n\t\tvar rule = new RuleClass(self);\n\t\trule.is = {};\n\t\trule.is[type] = true;\n\t\trule.init(self);\n\t\tvar matchIndex = rule.findNextMatch(startPos);\n\t\tif(matchIndex !== undefined) {\n\t\t\trulesInfo.push({\n\t\t\t\trule: rule,\n\t\t\t\tmatchIndex: matchIndex\n\t\t\t});\n\t\t}\n\t});\n\treturn rulesInfo;\n};\n\n/*\nSkip any whitespace at the current position. Options are:\n\ttreatNewlinesAsNonWhitespace: true if newlines are NOT to be treated as whitespace\n*/\nWikiParser.prototype.skipWhitespace = function(options) {\n\toptions = options || {};\n\tvar whitespaceRegExp = options.treatNewlinesAsNonWhitespace ? /([^\\S\\n]+)/mg : /(\\s+)/mg;\n\twhitespaceRegExp.lastIndex = this.pos;\n\tvar whitespaceMatch = whitespaceRegExp.exec(this.source);\n\tif(whitespaceMatch && whitespaceMatch.index === this.pos) {\n\t\tthis.pos = whitespaceRegExp.lastIndex;\n\t}\n};\n\n/*\nGet the next match out of an array of parse rule instances\n*/\nWikiParser.prototype.findNextMatch = function(rules,startPos) {\n\t// Find the best matching rule by finding the closest match position\n\tvar matchingRule,\n\t\tmatchingRulePos = this.sourceLength;\n\t// Step through each rule\n\tfor(var t=0; t<rules.length; t++) {\n\t\tvar ruleInfo = rules[t];\n\t\t// Ask the rule to get the next match if we've moved past the current one\n\t\tif(ruleInfo.matchIndex !== undefined && ruleInfo.matchIndex < startPos) {\n\t\t\truleInfo.matchIndex = ruleInfo.rule.findNextMatch(startPos);\n\t\t}\n\t\t// Adopt this match if it's closer than the current best match\n\t\tif(ruleInfo.matchIndex !== undefined && ruleInfo.matchIndex <= matchingRulePos) {\n\t\t\tmatchingRule = ruleInfo;\n\t\t\tmatchingRulePos = ruleInfo.matchIndex;\n\t\t}\n\t}\n\treturn matchingRule;\n};\n\n/*\nParse any pragmas at the beginning of a block of parse text\n*/\nWikiParser.prototype.parsePragmas = function() {\n\tvar currentTreeBranch = this.tree;\n\twhile(true) {\n\t\t// Skip whitespace\n\t\tthis.skipWhitespace();\n\t\t// Check for the end of the text\n\t\tif(this.pos >= this.sourceLength) {\n\t\t\tbreak;\n\t\t}\n\t\t// Check if we've arrived at a pragma rule match\n\t\tvar nextMatch = this.findNextMatch(this.pragmaRules,this.pos);\n\t\t// If not, just exit\n\t\tif(!nextMatch || nextMatch.matchIndex !== this.pos) {\n\t\t\tbreak;\n\t\t}\n\t\t// Process the pragma rule\n\t\tvar subTree = nextMatch.rule.parse();\n\t\tif(subTree.length > 0) {\n\t\t\t// Quick hack; we only cope with a single parse tree node being returned, which is true at the moment\n\t\t\tcurrentTreeBranch.push.apply(currentTreeBranch,subTree);\n\t\t\tsubTree[0].children = [];\n\t\t\tcurrentTreeBranch = subTree[0].children;\n\t\t}\n\t}\n\treturn currentTreeBranch;\n};\n\n/*\nParse a block from the current position\n\tterminatorRegExpString: optional regular expression string that identifies the end of plain paragraphs. Must not include capturing parenthesis\n*/\nWikiParser.prototype.parseBlock = function(terminatorRegExpString) {\n\tvar terminatorRegExp = terminatorRegExpString ? new RegExp(\"(\" + terminatorRegExpString + \"|\\\\r?\\\\n\\\\r?\\\\n)\",\"mg\") : /(\\r?\\n\\r?\\n)/mg;\n\tthis.skipWhitespace();\n\tif(this.pos >= this.sourceLength) {\n\t\treturn [];\n\t}\n\t// Look for a block rule that applies at the current position\n\tvar nextMatch = this.findNextMatch(this.blockRules,this.pos);\n\tif(nextMatch && nextMatch.matchIndex === this.pos) {\n\t\treturn nextMatch.rule.parse();\n\t}\n\t// Treat it as a paragraph if we didn't find a block rule\n\treturn [{type: \"element\", tag: \"p\", children: this.parseInlineRun(terminatorRegExp)}];\n};\n\n/*\nParse a series of blocks of text until a terminating regexp is encountered or the end of the text\n\tterminatorRegExpString: terminating regular expression\n*/\nWikiParser.prototype.parseBlocks = function(terminatorRegExpString) {\n\tif(terminatorRegExpString) {\n\t\treturn this.parseBlocksTerminated(terminatorRegExpString);\n\t} else {\n\t\treturn this.parseBlocksUnterminated();\n\t}\n};\n\n/*\nParse a block from the current position to the end of the text\n*/\nWikiParser.prototype.parseBlocksUnterminated = function() {\n\tvar tree = [];\n\twhile(this.pos < this.sourceLength) {\n\t\ttree.push.apply(tree,this.parseBlock());\n\t}\n\treturn tree;\n};\n\n/*\nParse blocks of text until a terminating regexp is encountered\n*/\nWikiParser.prototype.parseBlocksTerminated = function(terminatorRegExpString) {\n\tvar terminatorRegExp = new RegExp(\"(\" + terminatorRegExpString + \")\",\"mg\"),\n\t\ttree = [];\n\t// Skip any whitespace\n\tthis.skipWhitespace();\n\t// Check if we've got the end marker\n\tterminatorRegExp.lastIndex = this.pos;\n\tvar match = terminatorRegExp.exec(this.source);\n\t// Parse the text into blocks\n\twhile(this.pos < this.sourceLength && !(match && match.index === this.pos)) {\n\t\tvar blocks = this.parseBlock(terminatorRegExpString);\n\t\ttree.push.apply(tree,blocks);\n\t\t// Skip any whitespace\n\t\tthis.skipWhitespace();\n\t\t// Check if we've got the end marker\n\t\tterminatorRegExp.lastIndex = this.pos;\n\t\tmatch = terminatorRegExp.exec(this.source);\n\t}\n\tif(match && match.index === this.pos) {\n\t\tthis.pos = match.index + match[0].length;\n\t}\n\treturn tree;\n};\n\n/*\nParse a run of text at the current position\n\tterminatorRegExp: a regexp at which to stop the run\n\toptions: see below\nOptions available:\n\teatTerminator: move the parse position past any encountered terminator (default false)\n*/\nWikiParser.prototype.parseInlineRun = function(terminatorRegExp,options) {\n\tif(terminatorRegExp) {\n\t\treturn this.parseInlineRunTerminated(terminatorRegExp,options);\n\t} else {\n\t\treturn this.parseInlineRunUnterminated(options);\n\t}\n};\n\nWikiParser.prototype.parseInlineRunUnterminated = function(options) {\n\tvar tree = [];\n\t// Find the next occurrence of an inline rule\n\tvar nextMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t// Loop around the matches until we've reached the end of the text\n\twhile(this.pos < this.sourceLength && nextMatch) {\n\t\t// Process the text preceding the run rule\n\t\tif(nextMatch.matchIndex > this.pos) {\n\t\t\ttree.push({type: \"text\", text: this.source.substring(this.pos,nextMatch.matchIndex)});\n\t\t\tthis.pos = nextMatch.matchIndex;\n\t\t}\n\t\t// Process the run rule\n\t\ttree.push.apply(tree,nextMatch.rule.parse());\n\t\t// Look for the next run rule\n\t\tnextMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t}\n\t// Process the remaining text\n\tif(this.pos < this.sourceLength) {\n\t\ttree.push({type: \"text\", text: this.source.substr(this.pos)});\n\t}\n\tthis.pos = this.sourceLength;\n\treturn tree;\n};\n\nWikiParser.prototype.parseInlineRunTerminated = function(terminatorRegExp,options) {\n\toptions = options || {};\n\tvar tree = [];\n\t// Find the next occurrence of the terminator\n\tterminatorRegExp.lastIndex = this.pos;\n\tvar terminatorMatch = terminatorRegExp.exec(this.source);\n\t// Find the next occurrence of a inlinerule\n\tvar inlineRuleMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t// Loop around until we've reached the end of the text\n\twhile(this.pos < this.sourceLength && (terminatorMatch || inlineRuleMatch)) {\n\t\t// Return if we've found the terminator, and it precedes any inline rule match\n\t\tif(terminatorMatch) {\n\t\t\tif(!inlineRuleMatch || inlineRuleMatch.matchIndex >= terminatorMatch.index) {\n\t\t\t\tif(terminatorMatch.index > this.pos) {\n\t\t\t\t\ttree.push({type: \"text\", text: this.source.substring(this.pos,terminatorMatch.index)});\n\t\t\t\t}\n\t\t\t\tthis.pos = terminatorMatch.index;\n\t\t\t\tif(options.eatTerminator) {\n\t\t\t\t\tthis.pos += terminatorMatch[0].length;\n\t\t\t\t}\n\t\t\t\treturn tree;\n\t\t\t}\n\t\t}\n\t\t// Process any inline rule, along with the text preceding it\n\t\tif(inlineRuleMatch) {\n\t\t\t// Preceding text\n\t\t\tif(inlineRuleMatch.matchIndex > this.pos) {\n\t\t\t\ttree.push({type: \"text\", text: this.source.substring(this.pos,inlineRuleMatch.matchIndex)});\n\t\t\t\tthis.pos = inlineRuleMatch.matchIndex;\n\t\t\t}\n\t\t\t// Process the inline rule\n\t\t\ttree.push.apply(tree,inlineRuleMatch.rule.parse());\n\t\t\t// Look for the next inline rule\n\t\t\tinlineRuleMatch = this.findNextMatch(this.inlineRules,this.pos);\n\t\t\t// Look for the next terminator match\n\t\t\tterminatorRegExp.lastIndex = this.pos;\n\t\t\tterminatorMatch = terminatorRegExp.exec(this.source);\n\t\t}\n\t}\n\t// Process the remaining text\n\tif(this.pos < this.sourceLength) {\n\t\ttree.push({type: \"text\", text: this.source.substr(this.pos)});\n\t}\n\tthis.pos = this.sourceLength;\n\treturn tree;\n};\n\n/*\nParse zero or more class specifiers `.classname`\n*/\nWikiParser.prototype.parseClasses = function() {\n\tvar classRegExp = /\\.([^\\s\\.]+)/mg,\n\t\tclassNames = [];\n\tclassRegExp.lastIndex = this.pos;\n\tvar match = classRegExp.exec(this.source);\n\twhile(match && match.index === this.pos) {\n\t\tthis.pos = match.index + match[0].length;\n\t\tclassNames.push(match[1]);\n\t\tmatch = classRegExp.exec(this.source);\n\t}\n\treturn classNames;\n};\n\n/*\nAmend the rules used by this instance of the parser\n\ttype: `only` keeps just the named rules, `except` keeps all but the named rules\n\tnames: array of rule names\n*/\nWikiParser.prototype.amendRules = function(type,names) {\n\tnames = names || [];\n\t// Define the filter function\n\tvar keepFilter;\n\tif(type === \"only\") {\n\t\tkeepFilter = function(name) {\n\t\t\treturn names.indexOf(name) !== -1;\n\t\t};\n\t} else if(type === \"except\") {\n\t\tkeepFilter = function(name) {\n\t\t\treturn names.indexOf(name) === -1;\n\t\t};\n\t} else {\n\t\treturn;\n\t}\n\t// Define a function to process each of our rule arrays\n\tvar processRuleArray = function(ruleArray) {\n\t\tfor(var t=ruleArray.length-1; t>=0; t--) {\n\t\t\tif(!keepFilter(ruleArray[t].rule.name)) {\n\t\t\t\truleArray.splice(t,1);\n\t\t\t}\n\t\t}\n\t};\n\t// Process each rule array\n\tprocessRuleArray(this.pragmaRules);\n\tprocessRuleArray(this.blockRules);\n\tprocessRuleArray(this.inlineRules);\n};\n\nexports[\"text/vnd.tiddlywiki\"] = WikiParser;\n\n})();\n\n", "title": "$:/core/modules/parsers/wikiparser/wikiparser.js", "type": "application/javascript", "module-type": "parser" }, "$:/core/modules/parsers/wikiparser/rules/wikirulebase.js": { "text": "/*\\\ntitle: $:/core/modules/parsers/wikiparser/rules/wikirulebase.js\ntype: application/javascript\nmodule-type: global\n\nBase class for wiki parser rules\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nThis constructor is always overridden with a blank constructor, and so shouldn't be used\n*/\nvar WikiRuleBase = function() {\n};\n\n/*\nTo be overridden by individual rules\n*/\nWikiRuleBase.prototype.init = function(parser) {\n\tthis.parser = parser;\n};\n\n/*\nDefault implementation of findNextMatch uses RegExp matching\n*/\nWikiRuleBase.prototype.findNextMatch = function(startPos) {\n\tthis.matchRegExp.lastIndex = startPos;\n\tthis.match = this.matchRegExp.exec(this.parser.source);\n\treturn this.match ? this.match.index : undefined;\n};\n\nexports.WikiRuleBase = WikiRuleBase;\n\n})();\n", "title": "$:/core/modules/parsers/wikiparser/rules/wikirulebase.js", "type": "application/javascript", "module-type": "global" }, "$:/core/modules/pluginswitcher.js": { "text": "/*\\\ntitle: $:/core/modules/pluginswitcher.js\ntype: application/javascript\nmodule-type: global\n\nManages switching plugins for themes and languages.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\noptions:\nwiki: wiki store to be used\npluginType: type of plugin to be switched\ncontrollerTitle: title of tiddler used to control switching of this resource\ndefaultPlugins: array of default plugins to be used if nominated plugin isn't found\nonSwitch: callback when plugin is switched (single parameter is array of plugin titles)\n*/\nfunction PluginSwitcher(options) {\n\tthis.wiki = options.wiki;\n\tthis.pluginType = options.pluginType;\n\tthis.controllerTitle = options.controllerTitle;\n\tthis.defaultPlugins = options.defaultPlugins || [];\n\tthis.onSwitch = options.onSwitch;\n\t// Switch to the current plugin\n\tthis.switchPlugins();\n\t// Listen for changes to the selected plugin\n\tvar self = this;\n\tthis.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.utils.hop(changes,self.controllerTitle)) {\n\t\t\tself.switchPlugins();\n\t\t}\n\t});\n}\n\nPluginSwitcher.prototype.switchPlugins = function() {\n\t// Get the name of the current theme\n\tvar selectedPluginTitle = this.wiki.getTiddlerText(this.controllerTitle);\n\t// If it doesn't exist, then fallback to one of the default themes\n\tvar index = 0;\n\twhile(!this.wiki.getTiddler(selectedPluginTitle) && index < this.defaultPlugins.length) {\n\t\tselectedPluginTitle = this.defaultPlugins[index++];\n\t}\n\t// Accumulate the titles of the plugins that we need to load\n\tvar plugins = [],\n\t\tself = this,\n\t\taccumulatePlugin = function(title) {\n\t\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\t\tif(tiddler && tiddler.isPlugin() && plugins.indexOf(title) === -1) {\n\t\t\t\tplugins.push(title);\n\t\t\t\tvar pluginInfo = JSON.parse(self.wiki.getTiddlerText(title)),\n\t\t\t\t\tdependents = $tw.utils.parseStringArray(tiddler.fields.dependents || \"\");\n\t\t\t\t$tw.utils.each(dependents,function(title) {\n\t\t\t\t\taccumulatePlugin(title);\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\taccumulatePlugin(selectedPluginTitle);\n\t// Unregister any existing theme tiddlers\n\tvar unregisteredTiddlers = $tw.wiki.unregisterPluginTiddlers(this.pluginType);\n\t// Register any new theme tiddlers\n\tvar registeredTiddlers = $tw.wiki.registerPluginTiddlers(this.pluginType,plugins);\n\t// Unpack the current theme tiddlers\n\t$tw.wiki.unpackPluginTiddlers();\n\t// Call the switch handler\n\tif(this.onSwitch) {\n\t\tthis.onSwitch(plugins);\n\t}\n};\n\nexports.PluginSwitcher = PluginSwitcher;\n\n})();\n", "title": "$:/core/modules/pluginswitcher.js", "type": "application/javascript", "module-type": "global" }, "$:/core/modules/saver-handler.js": { "text": "/*\\\ntitle: $:/core/modules/saver-handler.js\ntype: application/javascript\nmodule-type: global\n\nThe saver handler tracks changes to the store and handles saving the entire wiki via saver modules.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nInstantiate the saver handler with the following options:\nwiki: wiki to be synced\ndirtyTracking: true if dirty tracking should be performed\n*/\nfunction SaverHandler(options) {\n\tvar self = this;\n\tthis.wiki = options.wiki;\n\tthis.dirtyTracking = options.dirtyTracking;\n\tthis.pendingAutoSave = false;\n\t// Make a logger\n\tthis.logger = new $tw.utils.Logger(\"saver-handler\");\n\t// Initialise our savers\n\tif($tw.browser) {\n\t\tthis.initSavers();\n\t}\n\t// Only do dirty tracking if required\n\tif($tw.browser && this.dirtyTracking) {\n\t\t// Compile the dirty tiddler filter\n\t\tthis.filterFn = this.wiki.compileFilter(this.wiki.getTiddlerText(this.titleSyncFilter));\n\t\t// Count of changes that have not yet been saved\n\t\tthis.numChanges = 0;\n\t\t// Listen out for changes to tiddlers\n\t\tthis.wiki.addEventListener(\"change\",function(changes) {\n\t\t\t// Filter the changes so that we only count changes to tiddlers that we care about\n\t\t\tvar filteredChanges = self.filterFn.call(self.wiki,function(iterator) {\n\t\t\t\t$tw.utils.each(changes,function(change,title) {\n\t\t\t\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\t\t\t\titerator(tiddler,title);\n\t\t\t\t});\n\t\t\t});\n\t\t\t// Adjust the number of changes\n\t\t\tself.numChanges += filteredChanges.length;\n\t\t\tself.updateDirtyStatus();\n\t\t\t// Do any autosave if one is pending and there's no more change events\n\t\t\tif(self.pendingAutoSave && self.wiki.getSizeOfTiddlerEventQueue() === 0) {\n\t\t\t\t// Check if we're dirty\n\t\t\t\tif(self.numChanges > 0) {\n\t\t\t\t\tself.saveWiki({\n\t\t\t\t\t\tmethod: \"autosave\",\n\t\t\t\t\t\tdownloadType: \"text/plain\"\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tself.pendingAutoSave = false;\n\t\t\t}\n\t\t});\n\t\t// Listen for the autosave event\n\t\t$tw.rootWidget.addEventListener(\"tm-auto-save-wiki\",function(event) {\n\t\t\t// Do the autosave unless there are outstanding tiddler change events\n\t\t\tif(self.wiki.getSizeOfTiddlerEventQueue() === 0) {\n\t\t\t\t// Check if we're dirty\n\t\t\t\tif(self.numChanges > 0) {\n\t\t\t\t\tself.saveWiki({\n\t\t\t\t\t\tmethod: \"autosave\",\n\t\t\t\t\t\tdownloadType: \"text/plain\"\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Otherwise put ourselves in the \"pending autosave\" state and wait for the change event before we do the autosave\n\t\t\t\tself.pendingAutoSave = true;\n\t\t\t}\n\t\t});\n\t\t// Set up our beforeunload handler\n\t\t$tw.addUnloadTask(function(event) {\n\t\t\tvar confirmationMessage;\n\t\t\tif(self.isDirty()) {\n\t\t\t\tconfirmationMessage = $tw.language.getString(\"UnsavedChangesWarning\");\n\t\t\t\tevent.returnValue = confirmationMessage; // Gecko\n\t\t\t}\n\t\t\treturn confirmationMessage;\n\t\t});\n\t}\n\t// Install the save action handlers\n\tif($tw.browser) {\n\t\t$tw.rootWidget.addEventListener(\"tm-save-wiki\",function(event) {\n\t\t\tself.saveWiki({\n\t\t\t\ttemplate: event.param,\n\t\t\t\tdownloadType: \"text/plain\",\n\t\t\t\tvariables: event.paramObject\n\t\t\t});\n\t\t});\n\t\t$tw.rootWidget.addEventListener(\"tm-download-file\",function(event) {\n\t\t\tself.saveWiki({\n\t\t\t\tmethod: \"download\",\n\t\t\t\ttemplate: event.param,\n\t\t\t\tdownloadType: \"text/plain\",\n\t\t\t\tvariables: event.paramObject\n\t\t\t});\n\t\t});\n\t}\n}\n\nSaverHandler.prototype.titleSyncFilter = \"$:/config/SaverFilter\";\nSaverHandler.prototype.titleAutoSave = \"$:/config/AutoSave\";\nSaverHandler.prototype.titleSavedNotification = \"$:/language/Notifications/Save/Done\";\n\n/*\nSelect the appropriate saver modules and set them up\n*/\nSaverHandler.prototype.initSavers = function(moduleType) {\n\tmoduleType = moduleType || \"saver\";\n\t// Instantiate the available savers\n\tthis.savers = [];\n\tvar self = this;\n\t$tw.modules.forEachModuleOfType(moduleType,function(title,module) {\n\t\tif(module.canSave(self)) {\n\t\t\tself.savers.push(module.create(self.wiki));\n\t\t}\n\t});\n\t// Sort the savers into priority order\n\tthis.savers.sort(function(a,b) {\n\t\tif(a.info.priority < b.info.priority) {\n\t\t\treturn -1;\n\t\t} else {\n\t\t\tif(a.info.priority > b.info.priority) {\n\t\t\t\treturn +1;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\nSave the wiki contents. Options are:\n\tmethod: \"save\", \"autosave\" or \"download\"\n\ttemplate: the tiddler containing the template to save\n\tdownloadType: the content type for the saved file\n*/\nSaverHandler.prototype.saveWiki = function(options) {\n\toptions = options || {};\n\tvar self = this,\n\t\tmethod = options.method || \"save\",\n\t\tvariables = options.variables || {},\n\t\ttemplate = options.template || \"$:/core/save/all\",\n\t\tdownloadType = options.downloadType || \"text/plain\",\n\t\ttext = this.wiki.renderTiddler(downloadType,template,options),\n\t\tcallback = function(err) {\n\t\t\tif(err) {\n\t\t\t\talert($tw.language.getString(\"Error/WhileSaving\") + \":\\n\\n\" + err);\n\t\t\t} else {\n\t\t\t\t// Clear the task queue if we're saving (rather than downloading)\n\t\t\t\tif(method !== \"download\") {\n\t\t\t\t\tself.numChanges = 0;\n\t\t\t\t\tself.updateDirtyStatus();\n\t\t\t\t}\n\t\t\t\t$tw.notifier.display(self.titleSavedNotification);\n\t\t\t\tif(options.callback) {\n\t\t\t\t\toptions.callback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t// Ignore autosave if disabled\n\tif(method === \"autosave\" && this.wiki.getTiddlerText(this.titleAutoSave,\"yes\") !== \"yes\") {\n\t\treturn false;\n\t}\n\t// Call the highest priority saver that supports this method\n\tfor(var t=this.savers.length-1; t>=0; t--) {\n\t\tvar saver = this.savers[t];\n\t\tif(saver.info.capabilities.indexOf(method) !== -1 && saver.save(text,method,callback,{variables: {filename: variables.filename}})) {\n\t\t\tthis.logger.log(\"Saving wiki with method\",method,\"through saver\",saver.info.name);\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\n/*\nChecks whether the wiki is dirty (ie the window shouldn't be closed)\n*/\nSaverHandler.prototype.isDirty = function() {\n\treturn this.numChanges > 0;\n};\n\n/*\nUpdate the document body with the class \"tc-dirty\" if the wiki has unsaved/unsynced changes\n*/\nSaverHandler.prototype.updateDirtyStatus = function() {\n\tif($tw.browser) {\n\t\t$tw.utils.toggleClass(document.body,\"tc-dirty\",this.isDirty());\n\t}\n};\n\nexports.SaverHandler = SaverHandler;\n\n})();\n", "title": "$:/core/modules/saver-handler.js", "type": "application/javascript", "module-type": "global" }, "$:/core/modules/savers/andtidwiki.js": { "text": "/*\\\ntitle: $:/core/modules/savers/andtidwiki.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via the AndTidWiki Android app\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false, netscape: false, Components: false */\n\"use strict\";\n\nvar AndTidWiki = function(wiki) {\n};\n\nAndTidWiki.prototype.save = function(text,method,callback) {\n\t// Get the pathname of this document\n\tvar pathname = decodeURIComponent(document.location.toString().split(\"#\")[0]);\n\t// Strip the file://\n\tif(pathname.indexOf(\"file://\") === 0) {\n\t\tpathname = pathname.substr(7);\n\t}\n\t// Strip any query or location part\n\tvar p = pathname.indexOf(\"?\");\n\tif(p !== -1) {\n\t\tpathname = pathname.substr(0,p);\n\t}\n\tp = pathname.indexOf(\"#\");\n\tif(p !== -1) {\n\t\tpathname = pathname.substr(0,p);\n\t}\n\t// Save the file\n\twindow.twi.saveFile(pathname,text);\n\t// Call the callback\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nAndTidWiki.prototype.info = {\n\tname: \"andtidwiki\",\n\tpriority: 1600,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn !!window.twi && !!window.twi.saveFile;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new AndTidWiki(wiki);\n};\n\n})();\n", "title": "$:/core/modules/savers/andtidwiki.js", "type": "application/javascript", "module-type": "saver" }, "$:/core/modules/savers/beaker.js": { "text": "/*\\\ntitle: $:/core/modules/savers/beaker.js\ntype: application/javascript\nmodule-type: saver\n\nSaves files using the Beaker browser's (https://beakerbrowser.com) Dat protocol (https://datproject.org/)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSet up the saver\n*/\nvar BeakerSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nBeakerSaver.prototype.save = function(text,method,callback) {\n\tvar url = (location.toString()).split(\"#\")[0];\n\tdat.stat(url).then(function(value) {\n\t\tif(value.type === \"directory\") {\n\t\t\turl = url + \"/index.html\";\n\t\t}\n\t\tdat.writeFile(url,text,\"utf8\").then(function(value) {\n\t\t\tcallback(null);\n\t\t},function(reason) {\n\t\t\tcallback(\"Beaker Saver Write Error: \" + reason);\n\t\t});\t\t\n\t},function(reason) {\n\t\tcallback(\"Beaker Saver Stat Error: \" + reason);\n\t});\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nBeakerSaver.prototype.info = {\n\tname: \"beaker\",\n\tpriority: 3000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn !!window.dat;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new BeakerSaver(wiki);\n};\n\n})();\n", "title": "$:/core/modules/savers/beaker.js", "type": "application/javascript", "module-type": "saver" }, "$:/core/modules/savers/download.js": { "text": "/*\\\ntitle: $:/core/modules/savers/download.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via HTML5's download APIs\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar DownloadSaver = function(wiki) {\n};\n\nDownloadSaver.prototype.save = function(text,method,callback,options) {\n\toptions = options || {};\n\t// Get the current filename\n\tvar filename = options.variables.filename;\n\tif(!filename) {\n\t\tvar p = document.location.pathname.lastIndexOf(\"/\");\n\t\tif(p !== -1) {\n\t\t\tfilename = document.location.pathname.substr(p+1);\n\t\t}\n\t}\n\tif(!filename) {\n\t\tfilename = \"tiddlywiki.html\";\n\t}\n\t// Set up the link\n\tvar link = document.createElement(\"a\");\n\tif(Blob !== undefined) {\n\t\tvar blob = new Blob([text], {type: \"text/html\"});\n\t\tlink.setAttribute(\"href\", URL.createObjectURL(blob));\n\t} else {\n\t\tlink.setAttribute(\"href\",\"data:text/html,\" + encodeURIComponent(text));\n\t}\n\tlink.setAttribute(\"download\",filename);\n\tdocument.body.appendChild(link);\n\tlink.click();\n\tdocument.body.removeChild(link);\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nDownloadSaver.prototype.info = {\n\tname: \"download\",\n\tpriority: 100\n};\n\nObject.defineProperty(DownloadSaver.prototype.info, \"capabilities\", {\n\tget: function() {\n\t\tvar capabilities = [\"save\", \"download\"];\n\t\tif(($tw.wiki.getTextReference(\"$:/config/DownloadSaver/AutoSave\") || \"\").toLowerCase() === \"yes\") {\n\t\t\tcapabilities.push(\"autosave\");\n\t\t}\n\t\treturn capabilities;\n\t}\n});\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn document.createElement(\"a\").download !== undefined;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new DownloadSaver(wiki);\n};\n\n})();\n", "title": "$:/core/modules/savers/download.js", "type": "application/javascript", "module-type": "saver" }, "$:/core/modules/savers/fsosaver.js": { "text": "/*\\\ntitle: $:/core/modules/savers/fsosaver.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via MS FileSystemObject ActiveXObject\n\nNote: Since TiddlyWiki's markup contains the MOTW, the FileSystemObject normally won't be available. \nHowever, if the wiki is loaded as an .HTA file (Windows HTML Applications) then the FSO can be used.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar FSOSaver = function(wiki) {\n};\n\nFSOSaver.prototype.save = function(text,method,callback) {\n\t// Get the pathname of this document\n\tvar pathname = unescape(document.location.pathname);\n\t// Test for a Windows path of the form /x:\\blah...\n\tif(/^\\/[A-Z]\\:\\\\[^\\\\]+/i.test(pathname)) {\t// ie: ^/[a-z]:/[^/]+\n\t\t// Remove the leading slash\n\t\tpathname = pathname.substr(1);\n\t} else if(document.location.hostname !== \"\" && /^\\/\\\\[^\\\\]+\\\\[^\\\\]+/i.test(pathname)) {\t// test for \\\\server\\share\\blah... - ^/[^/]+/[^/]+\n\t\t// Remove the leading slash\n\t\tpathname = pathname.substr(1);\n\t\t// reconstruct UNC path\n\t\tpathname = \"\\\\\\\\\" + document.location.hostname + pathname;\n\t} else {\n\t\treturn false;\n\t}\n\t// Save the file (as UTF-16)\n\tvar fso = new ActiveXObject(\"Scripting.FileSystemObject\");\n\tvar file = fso.OpenTextFile(pathname,2,-1,-1);\n\tfile.Write(text);\n\tfile.Close();\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nFSOSaver.prototype.info = {\n\tname: \"FSOSaver\",\n\tpriority: 120,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\ttry {\n\t\treturn (window.location.protocol === \"file:\") && !!(new ActiveXObject(\"Scripting.FileSystemObject\"));\n\t} catch(e) { return false; }\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new FSOSaver(wiki);\n};\n\n})();\n", "title": "$:/core/modules/savers/fsosaver.js", "type": "application/javascript", "module-type": "saver" }, "$:/core/modules/savers/manualdownload.js": { "text": "/*\\\ntitle: $:/core/modules/savers/manualdownload.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via HTML5's download APIs\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Title of the tiddler containing the download message\nvar downloadInstructionsTitle = \"$:/language/Modals/Download\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar ManualDownloadSaver = function(wiki) {\n};\n\nManualDownloadSaver.prototype.save = function(text,method,callback) {\n\t$tw.modal.display(downloadInstructionsTitle,{\n\t\tdownloadLink: \"data:text/html,\" + encodeURIComponent(text)\n\t});\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nManualDownloadSaver.prototype.info = {\n\tname: \"manualdownload\",\n\tpriority: 0,\n\tcapabilities: [\"save\", \"download\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new ManualDownloadSaver(wiki);\n};\n\n})();\n", "title": "$:/core/modules/savers/manualdownload.js", "type": "application/javascript", "module-type": "saver" }, "$:/core/modules/savers/msdownload.js": { "text": "/*\\\ntitle: $:/core/modules/savers/msdownload.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via window.navigator.msSaveBlob()\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar MsDownloadSaver = function(wiki) {\n};\n\nMsDownloadSaver.prototype.save = function(text,method,callback) {\n\t// Get the current filename\n\tvar filename = \"tiddlywiki.html\",\n\t\tp = document.location.pathname.lastIndexOf(\"/\");\n\tif(p !== -1) {\n\t\tfilename = document.location.pathname.substr(p+1);\n\t}\n\t// Set up the link\n\tvar blob = new Blob([text], {type: \"text/html\"});\n\twindow.navigator.msSaveBlob(blob,filename);\n\t// Callback that we succeeded\n\tcallback(null);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nMsDownloadSaver.prototype.info = {\n\tname: \"msdownload\",\n\tpriority: 110,\n\tcapabilities: [\"save\", \"download\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn !!window.navigator.msSaveBlob;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new MsDownloadSaver(wiki);\n};\n\n})();\n", "title": "$:/core/modules/savers/msdownload.js", "type": "application/javascript", "module-type": "saver" }, "$:/core/modules/savers/put.js": { "text": "/*\\\ntitle: $:/core/modules/savers/put.js\ntype: application/javascript\nmodule-type: saver\n\nSaves wiki by performing a PUT request to the server\n\nWorks with any server which accepts a PUT request\nto the current URL, such as a WebDAV server.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar PutSaver = function(wiki) {\n\tthis.wiki = wiki;\n\tvar self = this;\n\tvar uri = this.uri();\n\t// Async server probe. Until probe finishes, save will fail fast\n\t// See also https://github.com/Jermolene/TiddlyWiki5/issues/2276\n\t$tw.utils.httpRequest({\n\t\turl: uri,\n\t\ttype: \"OPTIONS\",\n\t\tcallback: function(err, data, xhr) {\n\t\t\t// Check DAV header http://www.webdav.org/specs/rfc2518.html#rfc.section.9.1\n\t\t\tif(!err) {\n\t\t\t\tself.serverAcceptsPuts = xhr.status === 200 && !!xhr.getResponseHeader(\"dav\");\n\t\t\t}\n\t\t}\n\t});\n\t// Retrieve ETag if available\n\t$tw.utils.httpRequest({\n\t\turl: uri,\n\t\ttype: \"HEAD\",\n\t\tcallback: function(err, data, xhr) {\n\t\t\tif(!err) {\n\t\t\t\tself.etag = xhr.getResponseHeader(\"ETag\");\n\t\t\t}\n\t\t}\n\t});\n};\n\nPutSaver.prototype.uri = function() {\n\treturn encodeURI(document.location.toString().split(\"#\")[0]);\n};\n\n// TODO: in case of edit conflict\n// Prompt: Do you want to save over this? Y/N\n// Merging would be ideal, and may be possible using future generic merge flow\nPutSaver.prototype.save = function(text, method, callback) {\n\tif(!this.serverAcceptsPuts) {\n\t\treturn false;\n\t}\n\tvar self = this;\n\tvar headers = { \"Content-Type\": \"text/html;charset=UTF-8\" };\n\tif(this.etag) {\n\t\theaders[\"If-Match\"] = this.etag;\n\t}\n\t$tw.utils.httpRequest({\n\t\turl: this.uri(),\n\t\ttype: \"PUT\",\n\t\theaders: headers,\n\t\tdata: text,\n\t\tcallback: function(err, data, xhr) {\n\t\t\tif(err) {\n\t\t\t\tcallback(err);\n\t\t\t} if(xhr.status === 200 || xhr.status === 201) {\n\t\t\t\tself.etag = xhr.getResponseHeader(\"ETag\");\n\t\t\t\tcallback(null); // success\n\t\t\t} else if(xhr.status === 412) { // edit conflict\n\t\t\t\tvar message = $tw.language.getString(\"Error/EditConflict\");\n\t\t\t\tcallback(message);\n\t\t\t} else {\n\t\t\t\tcallback(xhr.responseText); // fail\n\t\t\t}\n\t\t}\n\t});\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nPutSaver.prototype.info = {\n\tname: \"put\",\n\tpriority: 2000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn /^https?:/.test(location.protocol);\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new PutSaver(wiki);\n};\n\n})();\n", "title": "$:/core/modules/savers/put.js", "type": "application/javascript", "module-type": "saver" }, "$:/core/modules/savers/tiddlyfox.js": { "text": "/*\\\ntitle: $:/core/modules/savers/tiddlyfox.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via the TiddlyFox file extension\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false, netscape: false, Components: false */\n\"use strict\";\n\nvar TiddlyFoxSaver = function(wiki) {\n};\n\nTiddlyFoxSaver.prototype.save = function(text,method,callback) {\n\tvar messageBox = document.getElementById(\"tiddlyfox-message-box\");\n\tif(messageBox) {\n\t\t// Get the pathname of this document\n\t\tvar pathname = document.location.toString().split(\"#\")[0];\n\t\t// Replace file://localhost/ with file:///\n\t\tif(pathname.indexOf(\"file://localhost/\") === 0) {\n\t\t\tpathname = \"file://\" + pathname.substr(16);\n\t\t}\n\t\t// Windows path file:///x:/blah/blah --> x:\\blah\\blah\n\t\tif(/^file\\:\\/\\/\\/[A-Z]\\:\\//i.test(pathname)) {\n\t\t\t// Remove the leading slash and convert slashes to backslashes\n\t\t\tpathname = pathname.substr(8).replace(/\\//g,\"\\\\\");\n\t\t// Firefox Windows network path file://///server/share/blah/blah --> //server/share/blah/blah\n\t\t} else if(pathname.indexOf(\"file://///\") === 0) {\n\t\t\tpathname = \"\\\\\\\\\" + unescape(pathname.substr(10)).replace(/\\//g,\"\\\\\");\n\t\t// Mac/Unix local path file:///path/path --> /path/path\n\t\t} else if(pathname.indexOf(\"file:///\") === 0) {\n\t\t\tpathname = unescape(pathname.substr(7));\n\t\t// Mac/Unix local path file:/path/path --> /path/path\n\t\t} else if(pathname.indexOf(\"file:/\") === 0) {\n\t\t\tpathname = unescape(pathname.substr(5));\n\t\t// Otherwise Windows networth path file://server/share/path/path --> \\\\server\\share\\path\\path\n\t\t} else {\n\t\t\tpathname = \"\\\\\\\\\" + unescape(pathname.substr(7)).replace(new RegExp(\"/\",\"g\"),\"\\\\\");\n\t\t}\n\t\t// Create the message element and put it in the message box\n\t\tvar message = document.createElement(\"div\");\n\t\tmessage.setAttribute(\"data-tiddlyfox-path\",decodeURIComponent(pathname));\n\t\tmessage.setAttribute(\"data-tiddlyfox-content\",text);\n\t\tmessageBox.appendChild(message);\n\t\t// Add an event handler for when the file has been saved\n\t\tmessage.addEventListener(\"tiddlyfox-have-saved-file\",function(event) {\n\t\t\tcallback(null);\n\t\t}, false);\n\t\t// Create and dispatch the custom event to the extension\n\t\tvar event = document.createEvent(\"Events\");\n\t\tevent.initEvent(\"tiddlyfox-save-file\",true,false);\n\t\tmessage.dispatchEvent(event);\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\nInformation about this saver\n*/\nTiddlyFoxSaver.prototype.info = {\n\tname: \"tiddlyfox\",\n\tpriority: 1500,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new TiddlyFoxSaver(wiki);\n};\n\n})();\n", "title": "$:/core/modules/savers/tiddlyfox.js", "type": "application/javascript", "module-type": "saver" }, "$:/core/modules/savers/tiddlyie.js": { "text": "/*\\\ntitle: $:/core/modules/savers/tiddlyie.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via Internet Explorer BHO extenion (TiddlyIE)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar TiddlyIESaver = function(wiki) {\n};\n\nTiddlyIESaver.prototype.save = function(text,method,callback) {\n\t// Check existence of TiddlyIE BHO extension (note: only works after document is complete)\n\tif(typeof(window.TiddlyIE) != \"undefined\") {\n\t\t// Get the pathname of this document\n\t\tvar pathname = unescape(document.location.pathname);\n\t\t// Test for a Windows path of the form /x:/blah...\n\t\tif(/^\\/[A-Z]\\:\\/[^\\/]+/i.test(pathname)) {\t// ie: ^/[a-z]:/[^/]+ (is this better?: ^/[a-z]:/[^/]+(/[^/]+)*\\.[^/]+ )\n\t\t\t// Remove the leading slash\n\t\t\tpathname = pathname.substr(1);\n\t\t\t// Convert slashes to backslashes\n\t\t\tpathname = pathname.replace(/\\//g,\"\\\\\");\n\t\t} else if(document.hostname !== \"\" && /^\\/[^\\/]+\\/[^\\/]+/i.test(pathname)) {\t// test for \\\\server\\share\\blah... - ^/[^/]+/[^/]+\n\t\t\t// Convert slashes to backslashes\n\t\t\tpathname = pathname.replace(/\\//g,\"\\\\\");\n\t\t\t// reconstruct UNC path\n\t\t\tpathname = \"\\\\\\\\\" + document.location.hostname + pathname;\n\t\t} else return false;\n\t\t// Prompt the user to save the file\n\t\twindow.TiddlyIE.save(pathname, text);\n\t\t// Callback that we succeeded\n\t\tcallback(null);\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\nInformation about this saver\n*/\nTiddlyIESaver.prototype.info = {\n\tname: \"tiddlyiesaver\",\n\tpriority: 1500,\n\tcapabilities: [\"save\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn (window.location.protocol === \"file:\");\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new TiddlyIESaver(wiki);\n};\n\n})();\n", "title": "$:/core/modules/savers/tiddlyie.js", "type": "application/javascript", "module-type": "saver" }, "$:/core/modules/savers/twedit.js": { "text": "/*\\\ntitle: $:/core/modules/savers/twedit.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via the TWEdit iOS app\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false, netscape: false, Components: false */\n\"use strict\";\n\nvar TWEditSaver = function(wiki) {\n};\n\nTWEditSaver.prototype.save = function(text,method,callback) {\n\t// Bail if we're not running under TWEdit\n\tif(typeof DeviceInfo !== \"object\") {\n\t\treturn false;\n\t}\n\t// Get the pathname of this document\n\tvar pathname = decodeURIComponent(document.location.pathname);\n\t// Strip any query or location part\n\tvar p = pathname.indexOf(\"?\");\n\tif(p !== -1) {\n\t\tpathname = pathname.substr(0,p);\n\t}\n\tp = pathname.indexOf(\"#\");\n\tif(p !== -1) {\n\t\tpathname = pathname.substr(0,p);\n\t}\n\t// Remove the leading \"/Documents\" from path\n\tvar prefix = \"/Documents\";\n\tif(pathname.indexOf(prefix) === 0) {\n\t\tpathname = pathname.substr(prefix.length);\n\t}\n\t// Error handler\n\tvar errorHandler = function(event) {\n\t\t// Error\n\t\tcallback($tw.language.getString(\"Error/SavingToTWEdit\") + \": \" + event.target.error.code);\n\t};\n\t// Get the file system\n\twindow.requestFileSystem(LocalFileSystem.PERSISTENT,0,function(fileSystem) {\n\t\t// Now we've got the filesystem, get the fileEntry\n\t\tfileSystem.root.getFile(pathname, {create: true}, function(fileEntry) {\n\t\t\t// Now we've got the fileEntry, create the writer\n\t\t\tfileEntry.createWriter(function(writer) {\n\t\t\t\twriter.onerror = errorHandler;\n\t\t\t\twriter.onwrite = function() {\n\t\t\t\t\tcallback(null);\n\t\t\t\t};\n\t\t\t\twriter.position = 0;\n\t\t\t\twriter.write(text);\n\t\t\t},errorHandler);\n\t\t}, errorHandler);\n\t}, errorHandler);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nTWEditSaver.prototype.info = {\n\tname: \"twedit\",\n\tpriority: 1600,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new TWEditSaver(wiki);\n};\n\n/////////////////////////// Hack\n// HACK: This ensures that TWEdit recognises us as a TiddlyWiki document\nif($tw.browser) {\n\twindow.version = {title: \"TiddlyWiki\"};\n}\n\n})();\n", "title": "$:/core/modules/savers/twedit.js", "type": "application/javascript", "module-type": "saver" }, "$:/core/modules/savers/upload.js": { "text": "/*\\\ntitle: $:/core/modules/savers/upload.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes via upload to a server.\n\nDesigned to be compatible with BidiX's UploadPlugin at http://tiddlywiki.bidix.info/#UploadPlugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSelect the appropriate saver module and set it up\n*/\nvar UploadSaver = function(wiki) {\n\tthis.wiki = wiki;\n};\n\nUploadSaver.prototype.save = function(text,method,callback) {\n\t// Get the various parameters we need\n\tvar backupDir = this.wiki.getTextReference(\"$:/UploadBackupDir\") || \".\",\n\t\tusername = this.wiki.getTextReference(\"$:/UploadName\"),\n\t\tpassword = $tw.utils.getPassword(\"upload\"),\n\t\tuploadDir = this.wiki.getTextReference(\"$:/UploadDir\") || \".\",\n\t\tuploadFilename = this.wiki.getTextReference(\"$:/UploadFilename\") || \"index.html\",\n\t\turl = this.wiki.getTextReference(\"$:/UploadURL\");\n\t// Bail out if we don't have the bits we need\n\tif(!username || username.toString().trim() === \"\" || !password || password.toString().trim() === \"\") {\n\t\treturn false;\n\t}\n\t// Construct the url if not provided\n\tif(!url) {\n\t\turl = \"http://\" + username + \".tiddlyspot.com/store.cgi\";\n\t}\n\t// Assemble the header\n\tvar boundary = \"---------------------------\" + \"AaB03x\";\t\n\tvar uploadFormName = \"UploadPlugin\";\n\tvar head = [];\n\thead.push(\"--\" + boundary + \"\\r\\nContent-disposition: form-data; name=\\\"UploadPlugin\\\"\\r\\n\");\n\thead.push(\"backupDir=\" + backupDir + \";user=\" + username + \";password=\" + password + \";uploaddir=\" + uploadDir + \";;\"); \n\thead.push(\"\\r\\n\" + \"--\" + boundary);\n\thead.push(\"Content-disposition: form-data; name=\\\"userfile\\\"; filename=\\\"\" + uploadFilename + \"\\\"\");\n\thead.push(\"Content-Type: text/html;charset=UTF-8\");\n\thead.push(\"Content-Length: \" + text.length + \"\\r\\n\");\n\thead.push(\"\");\n\t// Assemble the tail and the data itself\n\tvar tail = \"\\r\\n--\" + boundary + \"--\\r\\n\",\n\t\tdata = head.join(\"\\r\\n\") + text + tail;\n\t// Do the HTTP post\n\tvar http = new XMLHttpRequest();\n\thttp.open(\"POST\",url,true,username,password);\n\thttp.setRequestHeader(\"Content-Type\",\"multipart/form-data; charset=UTF-8; boundary=\" + boundary);\n\thttp.onreadystatechange = function() {\n\t\tif(http.readyState == 4 && http.status == 200) {\n\t\t\tif(http.responseText.substr(0,4) === \"0 - \") {\n\t\t\t\tcallback(null);\n\t\t\t} else {\n\t\t\t\tcallback(http.responseText);\n\t\t\t}\n\t\t}\n\t};\n\ttry {\n\t\thttp.send(data);\n\t} catch(ex) {\n\t\treturn callback($tw.language.getString(\"Error/Caption\") + \":\" + ex);\n\t}\n\t$tw.notifier.display(\"$:/language/Notifications/Save/Starting\");\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nUploadSaver.prototype.info = {\n\tname: \"upload\",\n\tpriority: 2000,\n\tcapabilities: [\"save\", \"autosave\"]\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\treturn true;\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new UploadSaver(wiki);\n};\n\n})();\n", "title": "$:/core/modules/savers/upload.js", "type": "application/javascript", "module-type": "saver" }, "$:/core/modules/browser-messaging.js": { "text": "/*\\\ntitle: $:/core/modules/browser-messaging.js\ntype: application/javascript\nmodule-type: startup\n\nBrowser message handling\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"browser-messaging\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\n/*\nLoad a specified url as an iframe and call the callback when it is loaded. If the url is already loaded then the existing iframe instance is used\n*/\nfunction loadIFrame(url,callback) {\n\t// Check if iframe already exists\n\tvar iframeInfo = $tw.browserMessaging.iframeInfoMap[url];\n\tif(iframeInfo) {\n\t\t// We've already got the iframe\n\t\tcallback(null,iframeInfo);\n\t} else {\n\t\t// Create the iframe and save it in the list\n\t\tvar iframe = document.createElement(\"iframe\");\n\t\tiframeInfo = {\n\t\t\turl: url,\n\t\t\tstatus: \"loading\",\n\t\t\tdomNode: iframe\n\t\t};\n\t\t$tw.browserMessaging.iframeInfoMap[url] = iframeInfo;\n\t\tsaveIFrameInfoTiddler(iframeInfo);\n\t\t// Add the iframe to the DOM and hide it\n\t\tiframe.style.display = \"none\";\n\t\tiframe.setAttribute(\"library\",\"true\");\n\t\tdocument.body.appendChild(iframe);\n\t\t// Set up onload\n\t\tiframe.onload = function() {\n\t\t\tiframeInfo.status = \"loaded\";\n\t\t\tsaveIFrameInfoTiddler(iframeInfo);\n\t\t\tcallback(null,iframeInfo);\n\t\t};\n\t\tiframe.onerror = function() {\n\t\t\tcallback(\"Cannot load iframe\");\n\t\t};\n\t\ttry {\n\t\t\tiframe.src = url;\n\t\t} catch(ex) {\n\t\t\tcallback(ex);\n\t\t}\n\t}\n}\n\n/*\nUnload library iframe for given url\n*/\nfunction unloadIFrame(url){\n\t$tw.utils.each(document.getElementsByTagName('iframe'), function(iframe) {\n\t\tif(iframe.getAttribute(\"library\") === \"true\" &&\n\t\t iframe.getAttribute(\"src\") === url) {\n\t\t\tiframe.parentNode.removeChild(iframe);\n\t\t}\n\t});\n}\n\nfunction saveIFrameInfoTiddler(iframeInfo) {\n\t$tw.wiki.addTiddler(new $tw.Tiddler($tw.wiki.getCreationFields(),{\n\t\ttitle: \"$:/temp/ServerConnection/\" + iframeInfo.url,\n\t\ttext: iframeInfo.status,\n\t\ttags: [\"$:/tags/ServerConnection\"],\n\t\turl: iframeInfo.url\n\t},$tw.wiki.getModificationFields()));\n}\n\nexports.startup = function() {\n\t// Initialise the store of iframes we've created\n\t$tw.browserMessaging = {\n\t\tiframeInfoMap: {} // Hashmap by URL of {url:,status:\"loading/loaded\",domNode:}\n\t};\n\t// Listen for widget messages to control loading the plugin library\n\t$tw.rootWidget.addEventListener(\"tm-load-plugin-library\",function(event) {\n\t\tvar paramObject = event.paramObject || {},\n\t\t\turl = paramObject.url;\n\t\tif(url) {\n\t\t\tloadIFrame(url,function(err,iframeInfo) {\n\t\t\t\tif(err) {\n\t\t\t\t\talert($tw.language.getString(\"Error/LoadingPluginLibrary\") + \": \" + url);\n\t\t\t\t} else {\n\t\t\t\t\tiframeInfo.domNode.contentWindow.postMessage({\n\t\t\t\t\t\tverb: \"GET\",\n\t\t\t\t\t\turl: \"recipes/library/tiddlers.json\",\n\t\t\t\t\t\tcookies: {\n\t\t\t\t\t\t\ttype: \"save-info\",\n\t\t\t\t\t\t\tinfoTitlePrefix: paramObject.infoTitlePrefix || \"$:/temp/RemoteAssetInfo/\",\n\t\t\t\t\t\t\turl: url\n\t\t\t\t\t\t}\n\t\t\t\t\t},\"*\");\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t// Listen for widget messages to control unloading the plugin library\n\t$tw.rootWidget.addEventListener(\"tm-unload-plugin-library\",function(event) {\n\t\tvar paramObject = event.paramObject || {},\n\t\t\turl = paramObject.url;\n\t\t$tw.browserMessaging.iframeInfoMap[url] = undefined;\n\t\tif(url) {\n\t\t\tunloadIFrame(url);\n\t\t\t$tw.utils.each(\n\t\t\t\t$tw.wiki.filterTiddlers(\"[[$:/temp/ServerConnection/\" + url + \"]] [prefix[$:/temp/RemoteAssetInfo/\" + url + \"/]]\"),\n\t\t\t\tfunction(title) {\n\t\t\t\t\t$tw.wiki.deleteTiddler(title);\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t});\n\t$tw.rootWidget.addEventListener(\"tm-load-plugin-from-library\",function(event) {\n\t\tvar paramObject = event.paramObject || {},\n\t\t\turl = paramObject.url,\n\t\t\ttitle = paramObject.title;\n\t\tif(url && title) {\n\t\t\tloadIFrame(url,function(err,iframeInfo) {\n\t\t\t\tif(err) {\n\t\t\t\t\talert($tw.language.getString(\"Error/LoadingPluginLibrary\") + \": \" + url);\n\t\t\t\t} else {\n\t\t\t\t\tiframeInfo.domNode.contentWindow.postMessage({\n\t\t\t\t\t\tverb: \"GET\",\n\t\t\t\t\t\turl: \"recipes/library/tiddlers/\" + encodeURIComponent(title) + \".json\",\n\t\t\t\t\t\tcookies: {\n\t\t\t\t\t\t\ttype: \"save-tiddler\",\n\t\t\t\t\t\t\turl: url\n\t\t\t\t\t\t}\n\t\t\t\t\t},\"*\");\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t// Listen for window messages from other windows\n\twindow.addEventListener(\"message\",function listener(event){\n\t\tconsole.log(\"browser-messaging: \",document.location.toString())\n\t\tconsole.log(\"browser-messaging: Received message from\",event.origin);\n\t\tconsole.log(\"browser-messaging: Message content\",event.data);\n\t\tswitch(event.data.verb) {\n\t\t\tcase \"GET-RESPONSE\":\n\t\t\t\tif(event.data.status.charAt(0) === \"2\") {\n\t\t\t\t\tif(event.data.cookies) {\n\t\t\t\t\t\tif(event.data.cookies.type === \"save-info\") {\n\t\t\t\t\t\t\tvar tiddlers = JSON.parse(event.data.body);\n\t\t\t\t\t\t\t$tw.utils.each(tiddlers,function(tiddler) {\n\t\t\t\t\t\t\t\t$tw.wiki.addTiddler(new $tw.Tiddler($tw.wiki.getCreationFields(),tiddler,{\n\t\t\t\t\t\t\t\t\ttitle: event.data.cookies.infoTitlePrefix + event.data.cookies.url + \"/\" + tiddler.title,\n\t\t\t\t\t\t\t\t\t\"original-title\": tiddler.title,\n\t\t\t\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\t\t\t\ttype: \"text/vnd.tiddlywiki\",\n\t\t\t\t\t\t\t\t\t\"original-type\": tiddler.type,\n\t\t\t\t\t\t\t\t\t\"plugin-type\": undefined,\n\t\t\t\t\t\t\t\t\t\"original-plugin-type\": tiddler[\"plugin-type\"],\n\t\t\t\t\t\t\t\t\t\"module-type\": undefined,\n\t\t\t\t\t\t\t\t\t\"original-module-type\": tiddler[\"module-type\"],\n\t\t\t\t\t\t\t\t\ttags: [\"$:/tags/RemoteAssetInfo\"],\n\t\t\t\t\t\t\t\t\t\"original-tags\": $tw.utils.stringifyList(tiddler.tags || []),\n\t\t\t\t\t\t\t\t\t\"server-url\": event.data.cookies.url\n\t\t\t\t\t\t\t\t},$tw.wiki.getModificationFields()));\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if(event.data.cookies.type === \"save-tiddler\") {\n\t\t\t\t\t\t\tvar tiddler = JSON.parse(event.data.body);\n\t\t\t\t\t\t\t$tw.wiki.addTiddler(new $tw.Tiddler(tiddler));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t},false);\n};\n\n})();\n", "title": "$:/core/modules/browser-messaging.js", "type": "application/javascript", "module-type": "startup" }, "$:/core/modules/startup/commands.js": { "text": "/*\\\ntitle: $:/core/modules/startup/commands.js\ntype: application/javascript\nmodule-type: startup\n\nCommand processing\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"commands\";\nexports.platforms = [\"node\"];\nexports.after = [\"story\"];\nexports.synchronous = false;\n\nexports.startup = function(callback) {\n\t// On the server, start a commander with the command line arguments\n\tvar commander = new $tw.Commander(\n\t\t$tw.boot.argv,\n\t\tfunction(err) {\n\t\t\tif(err) {\n\t\t\t\treturn $tw.utils.error(\"Error: \" + err);\n\t\t\t}\n\t\t\tcallback();\n\t\t},\n\t\t$tw.wiki,\n\t\t{output: process.stdout, error: process.stderr}\n\t);\n\tcommander.execute();\n};\n\n})();\n", "title": "$:/core/modules/startup/commands.js", "type": "application/javascript", "module-type": "startup" }, "$:/core/modules/startup/favicon.js": { "text": "/*\\\ntitle: $:/core/modules/startup/favicon.js\ntype: application/javascript\nmodule-type: startup\n\nFavicon handling\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"favicon\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\t\t\n// Favicon tiddler\nvar FAVICON_TITLE = \"$:/favicon.ico\";\n\nexports.startup = function() {\n\t// Set up the favicon\n\tsetFavicon();\n\t// Reset the favicon when the tiddler changes\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.utils.hop(changes,FAVICON_TITLE)) {\n\t\t\tsetFavicon();\n\t\t}\n\t});\n};\n\nfunction setFavicon() {\n\tvar tiddler = $tw.wiki.getTiddler(FAVICON_TITLE);\n\tif(tiddler) {\n\t\tvar faviconLink = document.getElementById(\"faviconLink\");\n\t\tfaviconLink.setAttribute(\"href\",\"data:\" + tiddler.fields.type + \";base64,\" + tiddler.fields.text);\n\t}\n}\n\n})();\n", "title": "$:/core/modules/startup/favicon.js", "type": "application/javascript", "module-type": "startup" }, "$:/core/modules/startup/info.js": { "text": "/*\\\ntitle: $:/core/modules/startup/info.js\ntype: application/javascript\nmodule-type: startup\n\nInitialise $:/info tiddlers via $:/temp/info-plugin pseudo-plugin\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"info\";\nexports.before = [\"startup\"];\nexports.after = [\"load-modules\"];\nexports.synchronous = true;\n\nexports.startup = function() {\n\t// Collect up the info tiddlers\n\tvar infoTiddlerFields = {};\n\t// Give each info module a chance to fill in as many info tiddlers as they want\n\t$tw.modules.forEachModuleOfType(\"info\",function(title,moduleExports) {\n\t\tif(moduleExports && moduleExports.getInfoTiddlerFields) {\n\t\t\tvar tiddlerFieldsArray = moduleExports.getInfoTiddlerFields(infoTiddlerFields);\n\t\t\t$tw.utils.each(tiddlerFieldsArray,function(fields) {\n\t\t\t\tif(fields) {\n\t\t\t\t\tinfoTiddlerFields[fields.title] = fields;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\t// Bake the info tiddlers into a plugin\n\tvar fields = {\n\t\ttitle: \"$:/temp/info-plugin\",\n\t\ttype: \"application/json\",\n\t\t\"plugin-type\": \"info\",\n\t\ttext: JSON.stringify({tiddlers: infoTiddlerFields},null,$tw.config.preferences.jsonSpaces)\n\t};\n\t$tw.wiki.addTiddler(new $tw.Tiddler(fields));\n\t$tw.wiki.readPluginInfo();\n\t$tw.wiki.registerPluginTiddlers(\"info\");\n\t$tw.wiki.unpackPluginTiddlers();\n};\n\n})();\n", "title": "$:/core/modules/startup/info.js", "type": "application/javascript", "module-type": "startup" }, "$:/core/modules/startup/load-modules.js": { "text": "/*\\\ntitle: $:/core/modules/startup/load-modules.js\ntype: application/javascript\nmodule-type: startup\n\nLoad core modules\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"load-modules\";\nexports.synchronous = true;\n\nexports.startup = function() {\n\t// Load modules\n\t$tw.modules.applyMethods(\"utils\",$tw.utils);\n\tif($tw.node) {\n\t\t$tw.modules.applyMethods(\"utils-node\",$tw.utils);\n\t}\n\t$tw.modules.applyMethods(\"global\",$tw);\n\t$tw.modules.applyMethods(\"config\",$tw.config);\n\t$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap(\"tiddlerfield\");\n\t$tw.modules.applyMethods(\"tiddlermethod\",$tw.Tiddler.prototype);\n\t$tw.modules.applyMethods(\"wikimethod\",$tw.Wiki.prototype);\n\t$tw.modules.applyMethods(\"tiddlerdeserializer\",$tw.Wiki.tiddlerDeserializerModules);\n\t$tw.macros = $tw.modules.getModulesByTypeAsHashmap(\"macro\");\n\t$tw.wiki.initParsers();\n\t$tw.Commander.initCommands();\n};\n\n})();\n", "title": "$:/core/modules/startup/load-modules.js", "type": "application/javascript", "module-type": "startup" }, "$:/core/modules/startup/password.js": { "text": "/*\\\ntitle: $:/core/modules/startup/password.js\ntype: application/javascript\nmodule-type: startup\n\nPassword handling\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"password\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\nexports.startup = function() {\n\t$tw.rootWidget.addEventListener(\"tm-set-password\",function(event) {\n\t\t$tw.passwordPrompt.createPrompt({\n\t\t\tserviceName: $tw.language.getString(\"Encryption/PromptSetPassword\"),\n\t\t\tnoUserName: true,\n\t\t\tsubmitText: $tw.language.getString(\"Encryption/SetPassword\"),\n\t\t\tcanCancel: true,\n\t\t\trepeatPassword: true,\n\t\t\tcallback: function(data) {\n\t\t\t\tif(data) {\n\t\t\t\t\t$tw.crypto.setPassword(data.password);\n\t\t\t\t}\n\t\t\t\treturn true; // Get rid of the password prompt\n\t\t\t}\n\t\t});\n\t});\n\t$tw.rootWidget.addEventListener(\"tm-clear-password\",function(event) {\n\t\tif($tw.browser) {\n\t\t\tif(!confirm($tw.language.getString(\"Encryption/ConfirmClearPassword\"))) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t$tw.crypto.setPassword(null);\n\t});\n\t// Ensure that $:/isEncrypted is maintained properly\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.utils.hop(changes,\"$:/isEncrypted\")) {\n\t\t\t$tw.crypto.updateCryptoStateTiddler();\n\t\t}\n\t});\n};\n\n})();\n", "title": "$:/core/modules/startup/password.js", "type": "application/javascript", "module-type": "startup" }, "$:/core/modules/startup/render.js": { "text": "/*\\\ntitle: $:/core/modules/startup/render.js\ntype: application/javascript\nmodule-type: startup\n\nTitle, stylesheet and page rendering\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"render\";\nexports.platforms = [\"browser\"];\nexports.after = [\"story\"];\nexports.synchronous = true;\n\n// Default story and history lists\nvar PAGE_TITLE_TITLE = \"$:/core/wiki/title\";\nvar PAGE_STYLESHEET_TITLE = \"$:/core/ui/PageStylesheet\";\nvar PAGE_TEMPLATE_TITLE = \"$:/core/ui/PageTemplate\";\n\n// Time (in ms) that we defer refreshing changes to draft tiddlers\nvar DRAFT_TIDDLER_TIMEOUT_TITLE = \"$:/config/Drafts/TypingTimeout\";\nvar DRAFT_TIDDLER_TIMEOUT = 400;\n\nexports.startup = function() {\n\t// Set up the title\n\t$tw.titleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TITLE_TITLE,{document: $tw.fakeDocument, parseAsInline: true});\n\t$tw.titleContainer = $tw.fakeDocument.createElement(\"div\");\n\t$tw.titleWidgetNode.render($tw.titleContainer,null);\n\tdocument.title = $tw.titleContainer.textContent;\n\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\tif($tw.titleWidgetNode.refresh(changes,$tw.titleContainer,null)) {\n\t\t\tdocument.title = $tw.titleContainer.textContent;\n\t\t}\n\t});\n\t// Set up the styles\n\t$tw.styleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_STYLESHEET_TITLE,{document: $tw.fakeDocument});\n\t$tw.styleContainer = $tw.fakeDocument.createElement(\"style\");\n\t$tw.styleWidgetNode.render($tw.styleContainer,null);\n\t$tw.styleElement = document.createElement(\"style\");\n\t$tw.styleElement.innerHTML = $tw.styleContainer.textContent;\n\tdocument.head.insertBefore($tw.styleElement,document.head.firstChild);\n\t$tw.wiki.addEventListener(\"change\",$tw.perf.report(\"styleRefresh\",function(changes) {\n\t\tif($tw.styleWidgetNode.refresh(changes,$tw.styleContainer,null)) {\n\t\t\t$tw.styleElement.innerHTML = $tw.styleContainer.textContent;\n\t\t}\n\t}));\n\t// Display the $:/core/ui/PageTemplate tiddler to kick off the display\n\t$tw.perf.report(\"mainRender\",function() {\n\t\t$tw.pageWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TEMPLATE_TITLE,{document: document, parentWidget: $tw.rootWidget});\n\t\t$tw.pageContainer = document.createElement(\"div\");\n\t\t$tw.utils.addClass($tw.pageContainer,\"tc-page-container-wrapper\");\n\t\tdocument.body.insertBefore($tw.pageContainer,document.body.firstChild);\n\t\t$tw.pageWidgetNode.render($tw.pageContainer,null);\n\t})();\n\t// Prepare refresh mechanism\n\tvar deferredChanges = Object.create(null),\n\t\ttimerId;\n\tfunction refresh() {\n\t\t// Process the refresh\n\t\t$tw.pageWidgetNode.refresh(deferredChanges);\n\t\tdeferredChanges = Object.create(null);\n\t}\n\t// Add the change event handler\n\t$tw.wiki.addEventListener(\"change\",$tw.perf.report(\"mainRefresh\",function(changes) {\n\t\t// Check if only drafts have changed\n\t\tvar onlyDraftsHaveChanged = true;\n\t\tfor(var title in changes) {\n\t\t\tvar tiddler = $tw.wiki.getTiddler(title);\n\t\t\tif(!tiddler || !tiddler.hasField(\"draft.of\")) {\n\t\t\t\tonlyDraftsHaveChanged = false;\n\t\t\t}\n\t\t}\n\t\t// Defer the change if only drafts have changed\n\t\tif(timerId) {\n\t\t\tclearTimeout(timerId);\n\t\t}\n\t\ttimerId = null;\n\t\tif(onlyDraftsHaveChanged) {\n\t\t\tvar timeout = parseInt($tw.wiki.getTiddlerText(DRAFT_TIDDLER_TIMEOUT_TITLE,\"\"),10);\n\t\t\tif(isNaN(timeout)) {\n\t\t\t\ttimeout = DRAFT_TIDDLER_TIMEOUT;\n\t\t\t}\n\t\t\ttimerId = setTimeout(refresh,timeout);\n\t\t\t$tw.utils.extend(deferredChanges,changes);\n\t\t} else {\n\t\t\t$tw.utils.extend(deferredChanges,changes);\n\t\t\trefresh();\n\t\t}\n\t}));\n\t// Fix up the link between the root widget and the page container\n\t$tw.rootWidget.domNodes = [$tw.pageContainer];\n\t$tw.rootWidget.children = [$tw.pageWidgetNode];\n};\n\n})();\n", "title": "$:/core/modules/startup/render.js", "type": "application/javascript", "module-type": "startup" }, "$:/core/modules/startup/rootwidget.js": { "text": "/*\\\ntitle: $:/core/modules/startup/rootwidget.js\ntype: application/javascript\nmodule-type: startup\n\nSetup the root widget and the core root widget handlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"rootwidget\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.before = [\"story\"];\nexports.synchronous = true;\n\nexports.startup = function() {\n\t// Install the modal message mechanism\n\t$tw.modal = new $tw.utils.Modal($tw.wiki);\n\t$tw.rootWidget.addEventListener(\"tm-modal\",function(event) {\n\t\t$tw.modal.display(event.param,{variables: event.paramObject});\n\t});\n\t// Install the notification mechanism\n\t$tw.notifier = new $tw.utils.Notifier($tw.wiki);\n\t$tw.rootWidget.addEventListener(\"tm-notify\",function(event) {\n\t\t$tw.notifier.display(event.param,{variables: event.paramObject});\n\t});\n\t// Install the scroller\n\t$tw.pageScroller = new $tw.utils.PageScroller();\n\t$tw.rootWidget.addEventListener(\"tm-scroll\",function(event) {\n\t\t$tw.pageScroller.handleEvent(event);\n\t});\n\tvar fullscreen = $tw.utils.getFullScreenApis();\n\tif(fullscreen) {\n\t\t$tw.rootWidget.addEventListener(\"tm-full-screen\",function(event) {\n\t\t\tif(document[fullscreen._fullscreenElement]) {\n\t\t\t\tdocument[fullscreen._exitFullscreen]();\n\t\t\t} else {\n\t\t\t\tdocument.documentElement[fullscreen._requestFullscreen](Element.ALLOW_KEYBOARD_INPUT);\n\t\t\t}\n\t\t});\n\t}\n\t// If we're being viewed on a data: URI then give instructions for how to save\n\tif(document.location.protocol === \"data:\") {\n\t\t$tw.rootWidget.dispatchEvent({\n\t\t\ttype: \"tm-modal\",\n\t\t\tparam: \"$:/language/Modals/SaveInstructions\"\n\t\t});\n\t}\n};\n\n})();\n", "title": "$:/core/modules/startup/rootwidget.js", "type": "application/javascript", "module-type": "startup" }, "$:/core/modules/startup.js": { "text": "/*\\\ntitle: $:/core/modules/startup.js\ntype: application/javascript\nmodule-type: startup\n\nMiscellaneous startup logic for both the client and server.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"startup\";\nexports.after = [\"load-modules\"];\nexports.synchronous = true;\n\n// Set to `true` to enable performance instrumentation\nvar PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE = \"$:/config/Performance/Instrumentation\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nexports.startup = function() {\n\tvar modules,n,m,f;\n\t// Minimal browser detection\n\tif($tw.browser) {\n\t\t$tw.browser.isIE = (/msie|trident/i.test(navigator.userAgent));\n\t\t$tw.browser.isFirefox = !!document.mozFullScreenEnabled;\n\t}\n\t// Platform detection\n\t$tw.platform = {};\n\tif($tw.browser) {\n\t\t$tw.platform.isMac = /Mac/.test(navigator.platform);\n\t\t$tw.platform.isWindows = /win/i.test(navigator.platform);\n\t\t$tw.platform.isLinux = /Linux/i.test(navigator.appVersion);\n\t} else {\n\t\tswitch(require(\"os\").platform()) {\n\t\t\tcase \"darwin\":\n\t\t\t\t$tw.platform.isMac = true;\n\t\t\t\tbreak;\n\t\t\tcase \"win32\":\n\t\t\t\t$tw.platform.isWindows = true;\n\t\t\t\tbreak;\n\t\t\tcase \"freebsd\":\n\t\t\t\t$tw.platform.isLinux = true;\n\t\t\t\tbreak;\n\t\t\tcase \"linux\":\n\t\t\t\t$tw.platform.isLinux = true;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\t// Initialise version\n\t$tw.version = $tw.utils.extractVersionInfo();\n\t// Set up the performance framework\n\t$tw.perf = new $tw.Performance($tw.wiki.getTiddlerText(PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE,\"no\") === \"yes\");\n\t// Kick off the language manager and switcher\n\t$tw.language = new $tw.Language();\n\t$tw.languageSwitcher = new $tw.PluginSwitcher({\n\t\twiki: $tw.wiki,\n\t\tpluginType: \"language\",\n\t\tcontrollerTitle: \"$:/language\",\n\t\tdefaultPlugins: [\n\t\t\t\"$:/languages/en-US\"\n\t\t],\n\t\tonSwitch: function(plugins) {\n\t\t\tif($tw.browser) {\n\t\t\t\tvar pluginTiddler = $tw.wiki.getTiddler(plugins[0]);\n\t\t\t\tif(pluginTiddler) {\n\t\t\t\t\tdocument.documentElement.setAttribute(\"dir\",pluginTiddler.getFieldString(\"text-direction\") || \"auto\");\n\t\t\t\t} else {\n\t\t\t\t\tdocument.documentElement.removeAttribute(\"dir\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\t// Kick off the theme manager\n\t$tw.themeManager = new $tw.PluginSwitcher({\n\t\twiki: $tw.wiki,\n\t\tpluginType: \"theme\",\n\t\tcontrollerTitle: \"$:/theme\",\n\t\tdefaultPlugins: [\n\t\t\t\"$:/themes/tiddlywiki/snowwhite\",\n\t\t\t\"$:/themes/tiddlywiki/vanilla\"\n\t\t]\n\t});\n\t// Kick off the keyboard manager\n\t$tw.keyboardManager = new $tw.KeyboardManager();\n\t// Clear outstanding tiddler store change events to avoid an unnecessary refresh cycle at startup\n\t$tw.wiki.clearTiddlerEventQueue();\n\t// Create a root widget for attaching event handlers. By using it as the parentWidget for another widget tree, one can reuse the event handlers\n\tif($tw.browser) {\n\t\t$tw.rootWidget = new widget.widget({\n\t\t\ttype: \"widget\",\n\t\t\tchildren: []\n\t\t},{\n\t\t\twiki: $tw.wiki,\n\t\t\tdocument: document\n\t\t});\n\t}\n\t// Find a working syncadaptor\n\t$tw.syncadaptor = undefined;\n\t$tw.modules.forEachModuleOfType(\"syncadaptor\",function(title,module) {\n\t\tif(!$tw.syncadaptor && module.adaptorClass) {\n\t\t\t$tw.syncadaptor = new module.adaptorClass({wiki: $tw.wiki});\n\t\t}\n\t});\n\t// Set up the syncer object if we've got a syncadaptor\n\tif($tw.syncadaptor) {\n\t\t$tw.syncer = new $tw.Syncer({wiki: $tw.wiki, syncadaptor: $tw.syncadaptor});\n\t} \n\t// Setup the saver handler\n\t$tw.saverHandler = new $tw.SaverHandler({wiki: $tw.wiki, dirtyTracking: !$tw.syncadaptor});\n\t// Host-specific startup\n\tif($tw.browser) {\n\t\t// Install the popup manager\n\t\t$tw.popup = new $tw.utils.Popup();\n\t\t// Install the animator\n\t\t$tw.anim = new $tw.utils.Animator();\n\t}\n};\n\n})();\n", "title": "$:/core/modules/startup.js", "type": "application/javascript", "module-type": "startup" }, "$:/core/modules/startup/story.js": { "text": "/*\\\ntitle: $:/core/modules/startup/story.js\ntype: application/javascript\nmodule-type: startup\n\nLoad core modules\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"story\";\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\n// Default story and history lists\nvar DEFAULT_STORY_TITLE = \"$:/StoryList\";\nvar DEFAULT_HISTORY_TITLE = \"$:/HistoryList\";\n\n// Default tiddlers\nvar DEFAULT_TIDDLERS_TITLE = \"$:/DefaultTiddlers\";\n\n// Config\nvar CONFIG_UPDATE_ADDRESS_BAR = \"$:/config/Navigation/UpdateAddressBar\"; // Can be \"no\", \"permalink\", \"permaview\"\nvar CONFIG_UPDATE_HISTORY = \"$:/config/Navigation/UpdateHistory\"; // Can be \"yes\" or \"no\"\n\nexports.startup = function() {\n\t// Open startup tiddlers\n\topenStartupTiddlers();\n\tif($tw.browser) {\n\t\t// Set up location hash update\n\t\t$tw.wiki.addEventListener(\"change\",function(changes) {\n\t\t\tif($tw.utils.hop(changes,DEFAULT_STORY_TITLE) || $tw.utils.hop(changes,DEFAULT_HISTORY_TITLE)) {\n\t\t\t\tupdateLocationHash({\n\t\t\t\t\tupdateAddressBar: $tw.wiki.getTiddlerText(CONFIG_UPDATE_ADDRESS_BAR,\"permaview\").trim(),\n\t\t\t\t\tupdateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,\"no\").trim()\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\t// Listen for changes to the browser location hash\n\t\twindow.addEventListener(\"hashchange\",function() {\n\t\t\tvar hash = $tw.utils.getLocationHash();\n\t\t\tif(hash !== $tw.locationHash) {\n\t\t\t\t$tw.locationHash = hash;\n\t\t\t\topenStartupTiddlers({defaultToCurrentStory: true});\n\t\t\t}\n\t\t},false);\n\t\t// Listen for the tm-browser-refresh message\n\t\t$tw.rootWidget.addEventListener(\"tm-browser-refresh\",function(event) {\n\t\t\twindow.location.reload(true);\n\t\t});\n\t\t// Listen for the tm-print message\n\t\t$tw.rootWidget.addEventListener(\"tm-print\",function(event) {\n\t\t\t(event.event.view || window).print();\n\t\t});\n\t\t// Listen for the tm-home message\n\t\t$tw.rootWidget.addEventListener(\"tm-home\",function(event) {\n\t\t\twindow.location.hash = \"\";\n\t\t\tvar storyFilter = $tw.wiki.getTiddlerText(DEFAULT_TIDDLERS_TITLE),\n\t\t\t\tstoryList = $tw.wiki.filterTiddlers(storyFilter);\n\t\t\t//invoke any hooks that might change the default story list\n\t\t\tstoryList = $tw.hooks.invokeHook(\"th-opening-default-tiddlers-list\",storyList);\n\t\t\t$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: \"\", list: storyList},$tw.wiki.getModificationFields());\n\t\t\tif(storyList[0]) {\n\t\t\t\t$tw.wiki.addToHistory(storyList[0]);\t\t\t\t\n\t\t\t}\n\t\t});\n\t\t// Listen for the tm-permalink message\n\t\t$tw.rootWidget.addEventListener(\"tm-permalink\",function(event) {\n\t\t\tupdateLocationHash({\n\t\t\t\tupdateAddressBar: \"permalink\",\n\t\t\t\tupdateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,\"no\").trim(),\n\t\t\t\ttargetTiddler: event.param || event.tiddlerTitle\n\t\t\t});\n\t\t});\n\t\t// Listen for the tm-permaview message\n\t\t$tw.rootWidget.addEventListener(\"tm-permaview\",function(event) {\n\t\t\tupdateLocationHash({\n\t\t\t\tupdateAddressBar: \"permaview\",\n\t\t\t\tupdateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,\"no\").trim(),\n\t\t\t\ttargetTiddler: event.param || event.tiddlerTitle\n\t\t\t});\n\t\t});\n\t}\n};\n\n/*\nProcess the location hash to open the specified tiddlers. Options:\ndefaultToCurrentStory: If true, the current story is retained as the default, instead of opening the default tiddlers\n*/\nfunction openStartupTiddlers(options) {\n\toptions = options || {};\n\t// Work out the target tiddler and the story filter. \"null\" means \"unspecified\"\n\tvar target = null,\n\t\tstoryFilter = null;\n\tif($tw.locationHash.length > 1) {\n\t\tvar hash = $tw.locationHash.substr(1),\n\t\t\tsplit = hash.indexOf(\":\");\n\t\tif(split === -1) {\n\t\t\ttarget = decodeURIComponent(hash.trim());\n\t\t} else {\n\t\t\ttarget = decodeURIComponent(hash.substr(0,split).trim());\n\t\t\tstoryFilter = decodeURIComponent(hash.substr(split + 1).trim());\n\t\t}\n\t}\n\t// If the story wasn't specified use the current tiddlers or a blank story\n\tif(storyFilter === null) {\n\t\tif(options.defaultToCurrentStory) {\n\t\t\tvar currStoryList = $tw.wiki.getTiddlerList(DEFAULT_STORY_TITLE);\n\t\t\tstoryFilter = $tw.utils.stringifyList(currStoryList);\n\t\t} else {\n\t\t\tif(target && target !== \"\") {\n\t\t\t\tstoryFilter = \"\";\n\t\t\t} else {\n\t\t\t\tstoryFilter = $tw.wiki.getTiddlerText(DEFAULT_TIDDLERS_TITLE);\n\t\t\t}\n\t\t}\n\t}\n\t// Process the story filter to get the story list\n\tvar storyList = $tw.wiki.filterTiddlers(storyFilter);\n\t// Invoke any hooks that want to change the default story list\n\tstoryList = $tw.hooks.invokeHook(\"th-opening-default-tiddlers-list\",storyList);\n\t// If the target tiddler isn't included then splice it in at the top\n\tif(target && storyList.indexOf(target) === -1) {\n\t\tstoryList.unshift(target);\n\t}\n\t// Save the story list\n\t$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: \"\", list: storyList},$tw.wiki.getModificationFields());\n\t// If a target tiddler was specified add it to the history stack\n\tif(target && target !== \"\") {\n\t\t// The target tiddler doesn't need double square brackets, but we'll silently remove them if they're present\n\t\tif(target.indexOf(\"[[\") === 0 && target.substr(-2) === \"]]\") {\n\t\t\ttarget = target.substr(2,target.length - 4);\n\t\t}\n\t\t$tw.wiki.addToHistory(target);\n\t} else if(storyList.length > 0) {\n\t\t$tw.wiki.addToHistory(storyList[0]);\n\t}\n}\n\n/*\noptions: See below\noptions.updateAddressBar: \"permalink\", \"permaview\" or \"no\" (defaults to \"permaview\")\noptions.updateHistory: \"yes\" or \"no\" (defaults to \"no\")\noptions.targetTiddler: optional title of target tiddler for permalink\n*/\nfunction updateLocationHash(options) {\n\tif(options.updateAddressBar !== \"no\") {\n\t\t// Get the story and the history stack\n\t\tvar storyList = $tw.wiki.getTiddlerList(DEFAULT_STORY_TITLE),\n\t\t\thistoryList = $tw.wiki.getTiddlerData(DEFAULT_HISTORY_TITLE,[]),\n\t\t\ttargetTiddler = \"\";\n\t\tif(options.targetTiddler) {\n\t\t\ttargetTiddler = options.targetTiddler;\n\t\t} else {\n\t\t\t// The target tiddler is the one at the top of the stack\n\t\t\tif(historyList.length > 0) {\n\t\t\t\ttargetTiddler = historyList[historyList.length-1].title;\n\t\t\t}\n\t\t\t// Blank the target tiddler if it isn't present in the story\n\t\t\tif(storyList.indexOf(targetTiddler) === -1) {\n\t\t\t\ttargetTiddler = \"\";\n\t\t\t}\n\t\t}\n\t\t// Assemble the location hash\n\t\tif(options.updateAddressBar === \"permalink\") {\n\t\t\t$tw.locationHash = \"#\" + encodeURIComponent(targetTiddler);\n\t\t} else {\n\t\t\t$tw.locationHash = \"#\" + encodeURIComponent(targetTiddler) + \":\" + encodeURIComponent($tw.utils.stringifyList(storyList));\n\t\t}\n\t\t// Only change the location hash if we must, thus avoiding unnecessary onhashchange events\n\t\tif($tw.utils.getLocationHash() !== $tw.locationHash) {\n\t\t\tif(options.updateHistory === \"yes\") {\n\t\t\t\t// Assign the location hash so that history is updated\n\t\t\t\twindow.location.hash = $tw.locationHash;\n\t\t\t} else {\n\t\t\t\t// We use replace so that browser history isn't affected\n\t\t\t\twindow.location.replace(window.location.toString().split(\"#\")[0] + $tw.locationHash);\n\t\t\t}\n\t\t}\n\t}\n}\n\n})();\n", "title": "$:/core/modules/startup/story.js", "type": "application/javascript", "module-type": "startup" }, "$:/core/modules/startup/windows.js": { "text": "/*\\\ntitle: $:/core/modules/startup/windows.js\ntype: application/javascript\nmodule-type: startup\n\nSetup root widget handlers for the messages concerned with opening external browser windows\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"windows\";\nexports.platforms = [\"browser\"];\nexports.after = [\"startup\"];\nexports.synchronous = true;\n\n// Global to keep track of open windows (hashmap by title)\nvar windows = {};\n\nexports.startup = function() {\n\t// Handle open window message\n\t$tw.rootWidget.addEventListener(\"tm-open-window\",function(event) {\n\t\t// Get the parameters\n\t\tvar refreshHandler,\n\t\t\ttitle = event.param || event.tiddlerTitle,\n\t\t\tparamObject = event.paramObject || {},\n\t\t\ttemplate = paramObject.template || \"$:/core/templates/single.tiddler.window\",\n\t\t\twidth = paramObject.width || \"700\",\n\t\t\theight = paramObject.height || \"600\",\n\t\t\tvariables = $tw.utils.extend({},paramObject,{currentTiddler: title});\n\t\t// Open the window\n\t\tvar srcWindow = window.open(\"\",\"external-\" + title,\"scrollbars,width=\" + width + \",height=\" + height),\n\t\t\tsrcDocument = srcWindow.document;\n\t\twindows[title] = srcWindow;\n\t\t// Check for reopening the same window\n\t\tif(srcWindow.haveInitialisedWindow) {\n\t\t\treturn;\n\t\t}\n\t\t// Initialise the document\n\t\tsrcDocument.write(\"<html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>\");\n\t\tsrcDocument.close();\n\t\tsrcDocument.title = title;\n\t\tsrcWindow.addEventListener(\"beforeunload\",function(event) {\n\t\t\tdelete windows[title];\n\t\t\t$tw.wiki.removeEventListener(\"change\",refreshHandler);\n\t\t},false);\n\t\t// Set up the styles\n\t\tvar styleWidgetNode = $tw.wiki.makeTranscludeWidget(\"$:/core/ui/PageStylesheet\",{\n\t\t\t\tdocument: $tw.fakeDocument,\n\t\t\t\tvariables: variables,\n\t\t\t\timportPageMacros: true}),\n\t\t\tstyleContainer = $tw.fakeDocument.createElement(\"style\");\n\t\tstyleWidgetNode.render(styleContainer,null);\n\t\tvar styleElement = srcDocument.createElement(\"style\");\n\t\tstyleElement.innerHTML = styleContainer.textContent;\n\t\tsrcDocument.head.insertBefore(styleElement,srcDocument.head.firstChild);\n\t\t// Render the text of the tiddler\n\t\tvar parser = $tw.wiki.parseTiddler(template),\n\t\t\twidgetNode = $tw.wiki.makeWidget(parser,{document: srcDocument, parentWidget: $tw.rootWidget, variables: variables});\n\t\twidgetNode.render(srcDocument.body,srcDocument.body.firstChild);\n\t\t// Function to handle refreshes\n\t\trefreshHandler = function(changes) {\n\t\t\tif(styleWidgetNode.refresh(changes,styleContainer,null)) {\n\t\t\t\tstyleElement.innerHTML = styleContainer.textContent;\n\t\t\t}\n\t\t\twidgetNode.refresh(changes);\n\t\t};\n\t\t$tw.wiki.addEventListener(\"change\",refreshHandler);\n\t\tsrcWindow.haveInitialisedWindow = true;\n\t});\n\t// Close open windows when unloading main window\n\t$tw.addUnloadTask(function() {\n\t\t$tw.utils.each(windows,function(win) {\n\t\t\twin.close();\n\t\t});\n\t});\n\n};\n\n})();\n", "title": "$:/core/modules/startup/windows.js", "type": "application/javascript", "module-type": "startup" }, "$:/core/modules/story.js": { "text": "/*\\\ntitle: $:/core/modules/story.js\ntype: application/javascript\nmodule-type: global\n\nLightweight object for managing interactions with the story and history lists.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nConstruct Story object with options:\nwiki: reference to wiki object to use to resolve tiddler titles\nstoryTitle: title of story list tiddler\nhistoryTitle: title of history list tiddler\n*/\nfunction Story(options) {\n\toptions = options || {};\n\tthis.wiki = options.wiki || $tw.wiki;\n\tthis.storyTitle = options.storyTitle || \"$:/StoryList\";\n\tthis.historyTitle = options.historyTitle || \"$:/HistoryList\";\n};\n\nStory.prototype.navigateTiddler = function(navigateTo,navigateFromTitle,navigateFromClientRect) {\n\tthis.addToStory(navigateTo,navigateFromTitle);\n\tthis.addToHistory(navigateTo,navigateFromClientRect);\n};\n\nStory.prototype.getStoryList = function() {\n\treturn this.wiki.getTiddlerList(this.storyTitle) || [];\n};\n\nStory.prototype.addToStory = function(navigateTo,navigateFromTitle,options) {\n\toptions = options || {};\n\tvar storyList = this.getStoryList();\n\t// See if the tiddler is already there\n\tvar slot = storyList.indexOf(navigateTo);\n\t// Quit if it already exists in the story river\n\tif(slot >= 0) {\n\t\treturn;\n\t}\n\t// First we try to find the position of the story element we navigated from\n\tvar fromIndex = storyList.indexOf(navigateFromTitle);\n\tif(fromIndex >= 0) {\n\t\t// The tiddler is added from inside the river\n\t\t// Determine where to insert the tiddler; Fallback is \"below\"\n\t\tswitch(options.openLinkFromInsideRiver) {\n\t\t\tcase \"top\":\n\t\t\t\tslot = 0;\n\t\t\t\tbreak;\n\t\t\tcase \"bottom\":\n\t\t\t\tslot = storyList.length;\n\t\t\t\tbreak;\n\t\t\tcase \"above\":\n\t\t\t\tslot = fromIndex;\n\t\t\t\tbreak;\n\t\t\tcase \"below\": // Intentional fall-through\n\t\t\tdefault:\n\t\t\t\tslot = fromIndex + 1;\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\t// The tiddler is opened from outside the river. Determine where to insert the tiddler; default is \"top\"\n\t\tif(options.openLinkFromOutsideRiver === \"bottom\") {\n\t\t\t// Insert at bottom\n\t\t\tslot = storyList.length;\n\t\t} else {\n\t\t\t// Insert at top\n\t\t\tslot = 0;\n\t\t}\n\t}\n\t// Add the tiddler\n\tstoryList.splice(slot,0,navigateTo);\n\t// Save the story\n\tthis.saveStoryList(storyList);\n};\n\nStory.prototype.saveStoryList = function(storyList) {\n\tvar storyTiddler = this.wiki.getTiddler(this.storyTitle);\n\tthis.wiki.addTiddler(new $tw.Tiddler(\n\t\tthis.wiki.getCreationFields(),\n\t\t{title: this.storyTitle},\n\t\tstoryTiddler,\n\t\t{list: storyList},\n\t\tthis.wiki.getModificationFields()\n\t));\n};\n\nStory.prototype.addToHistory = function(navigateTo,navigateFromClientRect) {\n\tvar titles = $tw.utils.isArray(navigateTo) ? navigateTo : [navigateTo];\n\t// Add a new record to the top of the history stack\n\tvar historyList = this.wiki.getTiddlerData(this.historyTitle,[]);\n\t$tw.utils.each(titles,function(title) {\n\t\thistoryList.push({title: title, fromPageRect: navigateFromClientRect});\n\t});\n\tthis.wiki.setTiddlerData(this.historyTitle,historyList,{\"current-tiddler\": titles[titles.length-1]});\n};\n\nStory.prototype.storyCloseTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyCloseAllTiddlers = function() {\n// TBD\n};\n\nStory.prototype.storyCloseOtherTiddlers = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyEditTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyDeleteTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storySaveTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyCancelTiddler = function(targetTitle) {\n// TBD\n};\n\nStory.prototype.storyNewTiddler = function(targetTitle) {\n// TBD\n};\n\nexports.Story = Story;\n\n\n})();\n", "title": "$:/core/modules/story.js", "type": "application/javascript", "module-type": "global" }, "$:/core/modules/storyviews/classic.js": { "text": "/*\\\ntitle: $:/core/modules/storyviews/classic.js\ntype: application/javascript\nmodule-type: storyview\n\nViews the story as a linear sequence\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar easing = \"cubic-bezier(0.645, 0.045, 0.355, 1)\"; // From http://easings.net/#easeInOutCubic\n\nvar ClassicStoryView = function(listWidget) {\n\tthis.listWidget = listWidget;\n};\n\nClassicStoryView.prototype.navigateTo = function(historyInfo) {\n\tvar listElementIndex = this.listWidget.findListItem(0,historyInfo.title);\n\tif(listElementIndex === undefined) {\n\t\treturn;\n\t}\n\tvar listItemWidget = this.listWidget.children[listElementIndex],\n\t\ttargetElement = listItemWidget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Scroll the node into view\n\tthis.listWidget.dispatchEvent({type: \"tm-scroll\", target: targetElement});\n};\n\nClassicStoryView.prototype.insert = function(widget) {\n\tvar targetElement = widget.findFirstDomNode(),\n\t\tduration = $tw.utils.getAnimationDuration();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Get the current height of the tiddler\n\tvar computedStyle = window.getComputedStyle(targetElement),\n\t\tcurrMarginBottom = parseInt(computedStyle.marginBottom,10),\n\t\tcurrMarginTop = parseInt(computedStyle.marginTop,10),\n\t\tcurrHeight = targetElement.offsetHeight + currMarginTop;\n\t// Reset the margin once the transition is over\n\tsetTimeout(function() {\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: \"none\"},\n\t\t\t{marginBottom: \"\"}\n\t\t]);\n\t},duration);\n\t// Set up the initial position of the element\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: \"none\"},\n\t\t{marginBottom: (-currHeight) + \"px\"},\n\t\t{opacity: \"0.0\"}\n\t]);\n\t$tw.utils.forceLayout(targetElement);\n\t// Transition to the final position\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: \"opacity \" + duration + \"ms \" + easing + \", \" +\n\t\t\t\t\t\"margin-bottom \" + duration + \"ms \" + easing},\n\t\t{marginBottom: currMarginBottom + \"px\"},\n\t\t{opacity: \"1.0\"}\n\t]);\n};\n\nClassicStoryView.prototype.remove = function(widget) {\n\tvar targetElement = widget.findFirstDomNode(),\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\tremoveElement = function() {\n\t\t\twidget.removeChildDomNodes();\n\t\t};\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\tremoveElement();\n\t\treturn;\n\t}\n\t// Get the current height of the tiddler\n\tvar currWidth = targetElement.offsetWidth,\n\t\tcomputedStyle = window.getComputedStyle(targetElement),\n\t\tcurrMarginBottom = parseInt(computedStyle.marginBottom,10),\n\t\tcurrMarginTop = parseInt(computedStyle.marginTop,10),\n\t\tcurrHeight = targetElement.offsetHeight + currMarginTop;\n\t// Remove the dom nodes of the widget at the end of the transition\n\tsetTimeout(removeElement,duration);\n\t// Animate the closure\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: \"none\"},\n\t\t{transform: \"translateX(0px)\"},\n\t\t{marginBottom: currMarginBottom + \"px\"},\n\t\t{opacity: \"1.0\"}\n\t]);\n\t$tw.utils.forceLayout(targetElement);\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms \" + easing + \", \" +\n\t\t\t\t\t\"margin-bottom \" + duration + \"ms \" + easing},\n\t\t{transform: \"translateX(-\" + currWidth + \"px)\"},\n\t\t{marginBottom: (-currHeight) + \"px\"},\n\t\t{opacity: \"0.0\"}\n\t]);\n};\n\nexports.classic = ClassicStoryView;\n\n})();", "title": "$:/core/modules/storyviews/classic.js", "type": "application/javascript", "module-type": "storyview" }, "$:/core/modules/storyviews/pop.js": { "text": "/*\\\ntitle: $:/core/modules/storyviews/pop.js\ntype: application/javascript\nmodule-type: storyview\n\nAnimates list insertions and removals\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar PopStoryView = function(listWidget) {\n\tthis.listWidget = listWidget;\n};\n\nPopStoryView.prototype.navigateTo = function(historyInfo) {\n\tvar listElementIndex = this.listWidget.findListItem(0,historyInfo.title);\n\tif(listElementIndex === undefined) {\n\t\treturn;\n\t}\n\tvar listItemWidget = this.listWidget.children[listElementIndex],\n\t\ttargetElement = listItemWidget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Scroll the node into view\n\tthis.listWidget.dispatchEvent({type: \"tm-scroll\", target: targetElement});\n};\n\nPopStoryView.prototype.insert = function(widget) {\n\tvar targetElement = widget.findFirstDomNode(),\n\t\tduration = $tw.utils.getAnimationDuration();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Reset once the transition is over\n\tsetTimeout(function() {\n\t\t$tw.utils.setStyle(targetElement,[\n\t\t\t{transition: \"none\"},\n\t\t\t{transform: \"none\"}\n\t\t]);\n\t},duration);\n\t// Set up the initial position of the element\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: \"none\"},\n\t\t{transform: \"scale(2)\"},\n\t\t{opacity: \"0.0\"}\n\t]);\n\t$tw.utils.forceLayout(targetElement);\n\t// Transition to the final position\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{transform: \"scale(1)\"},\n\t\t{opacity: \"1.0\"}\n\t]);\n};\n\nPopStoryView.prototype.remove = function(widget) {\n\tvar targetElement = widget.findFirstDomNode(),\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\tremoveElement = function() {\n\t\t\tif(targetElement.parentNode) {\n\t\t\t\twidget.removeChildDomNodes();\n\t\t\t}\n\t\t};\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\tremoveElement();\n\t\treturn;\n\t}\n\t// Remove the element at the end of the transition\n\tsetTimeout(removeElement,duration);\n\t// Animate the closure\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: \"none\"},\n\t\t{transform: \"scale(1)\"},\n\t\t{opacity: \"1.0\"}\n\t]);\n\t$tw.utils.forceLayout(targetElement);\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{transform: \"scale(0.1)\"},\n\t\t{opacity: \"0.0\"}\n\t]);\n};\n\nexports.pop = PopStoryView;\n\n})();\n", "title": "$:/core/modules/storyviews/pop.js", "type": "application/javascript", "module-type": "storyview" }, "$:/core/modules/storyviews/zoomin.js": { "text": "/*\\\ntitle: $:/core/modules/storyviews/zoomin.js\ntype: application/javascript\nmodule-type: storyview\n\nZooms between individual tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar easing = \"cubic-bezier(0.645, 0.045, 0.355, 1)\"; // From http://easings.net/#easeInOutCubic\n\nvar ZoominListView = function(listWidget) {\n\tvar self = this;\n\tthis.listWidget = listWidget;\n\t// Get the index of the tiddler that is at the top of the history\n\tvar history = this.listWidget.wiki.getTiddlerDataCached(this.listWidget.historyTitle,[]),\n\t\ttargetTiddler;\n\tif(history.length > 0) {\n\t\ttargetTiddler = history[history.length-1].title;\n\t}\n\t// Make all the tiddlers position absolute, and hide all but the top (or first) one\n\t$tw.utils.each(this.listWidget.children,function(itemWidget,index) {\n\t\tvar domNode = itemWidget.findFirstDomNode();\n\t\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\t\tif(!(domNode instanceof Element)) {\n\t\t\treturn;\n\t\t}\n\t\tif((targetTiddler && targetTiddler !== itemWidget.parseTreeNode.itemTitle) || (!targetTiddler && index)) {\n\t\t\tdomNode.style.display = \"none\";\n\t\t} else {\n\t\t\tself.currentTiddlerDomNode = domNode;\n\t\t}\n\t\t$tw.utils.addClass(domNode,\"tc-storyview-zoomin-tiddler\");\n\t});\n};\n\nZoominListView.prototype.navigateTo = function(historyInfo) {\n\tvar duration = $tw.utils.getAnimationDuration(),\n\t\tlistElementIndex = this.listWidget.findListItem(0,historyInfo.title);\n\tif(listElementIndex === undefined) {\n\t\treturn;\n\t}\n\tvar listItemWidget = this.listWidget.children[listElementIndex],\n\t\ttargetElement = listItemWidget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Make the new tiddler be position absolute and visible so that we can measure it\n\t$tw.utils.addClass(targetElement,\"tc-storyview-zoomin-tiddler\");\n\t$tw.utils.setStyle(targetElement,[\n\t\t{display: \"block\"},\n\t\t{transformOrigin: \"0 0\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t{transition: \"none\"},\n\t\t{opacity: \"0.0\"}\n\t]);\n\t// Get the position of the source node, or use the centre of the window as the source position\n\tvar sourceBounds = historyInfo.fromPageRect || {\n\t\t\tleft: window.innerWidth/2 - 2,\n\t\t\ttop: window.innerHeight/2 - 2,\n\t\t\twidth: window.innerWidth/8,\n\t\t\theight: window.innerHeight/8\n\t\t};\n\t// Try to find the title node in the target tiddler\n\tvar titleDomNode = findTitleDomNode(listItemWidget) || listItemWidget.findFirstDomNode(),\n\t\tzoomBounds = titleDomNode.getBoundingClientRect();\n\t// Compute the transform for the target tiddler to make the title lie over the source rectange\n\tvar targetBounds = targetElement.getBoundingClientRect(),\n\t\tscale = sourceBounds.width / zoomBounds.width,\n\t\tx = sourceBounds.left - targetBounds.left - (zoomBounds.left - targetBounds.left) * scale,\n\t\ty = sourceBounds.top - targetBounds.top - (zoomBounds.top - targetBounds.top) * scale;\n\t// Transform the target tiddler to its starting position\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transform: \"translateX(\" + x + \"px) translateY(\" + y + \"px) scale(\" + scale + \")\"}\n\t]);\n\t// Force layout\n\t$tw.utils.forceLayout(targetElement);\n\t// Apply the ending transitions with a timeout to ensure that the previously applied transformations are applied first\n\tvar self = this,\n\t\tprevCurrentTiddler = this.currentTiddlerDomNode;\n\tthis.currentTiddlerDomNode = targetElement;\n\t// Transform the target tiddler to its natural size\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t{opacity: \"1.0\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t{zIndex: \"500\"},\n\t]);\n\t// Transform the previous tiddler out of the way and then hide it\n\tif(prevCurrentTiddler && prevCurrentTiddler !== targetElement) {\n\t\tscale = zoomBounds.width / sourceBounds.width;\n\t\tx = zoomBounds.left - targetBounds.left - (sourceBounds.left - targetBounds.left) * scale;\n\t\ty = zoomBounds.top - targetBounds.top - (sourceBounds.top - targetBounds.top) * scale;\n\t\t$tw.utils.setStyle(prevCurrentTiddler,[\n\t\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t\t{opacity: \"0.0\"},\n\t\t\t{transformOrigin: \"0 0\"},\n\t\t\t{transform: \"translateX(\" + x + \"px) translateY(\" + y + \"px) scale(\" + scale + \")\"},\n\t\t\t{zIndex: \"0\"}\n\t\t]);\n\t\t// Hide the tiddler when the transition has finished\n\t\tsetTimeout(function() {\n\t\t\tif(self.currentTiddlerDomNode !== prevCurrentTiddler) {\n\t\t\t\tprevCurrentTiddler.style.display = \"none\";\n\t\t\t}\n\t\t},duration);\n\t}\n\t// Scroll the target into view\n//\t$tw.pageScroller.scrollIntoView(targetElement);\n};\n\n/*\nFind the first child DOM node of a widget that has the class \"tc-title\"\n*/\nfunction findTitleDomNode(widget,targetClass) {\n\ttargetClass = targetClass || \"tc-title\";\n\tvar domNode = widget.findFirstDomNode();\n\tif(domNode && domNode.querySelector) {\n\t\treturn domNode.querySelector(\".\" + targetClass);\n\t}\n\treturn null;\n}\n\nZoominListView.prototype.insert = function(widget) {\n\tvar targetElement = widget.findFirstDomNode();\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\treturn;\n\t}\n\t// Make the newly inserted node position absolute and hidden\n\t$tw.utils.addClass(targetElement,\"tc-storyview-zoomin-tiddler\");\n\t$tw.utils.setStyle(targetElement,[\n\t\t{display: \"none\"}\n\t]);\n};\n\nZoominListView.prototype.remove = function(widget) {\n\tvar targetElement = widget.findFirstDomNode(),\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\tremoveElement = function() {\n\t\t\twidget.removeChildDomNodes();\n\t\t};\n\t// Abandon if the list entry isn't a DOM element (it might be a text node)\n\tif(!(targetElement instanceof Element)) {\n\t\tremoveElement();\n\t\treturn;\n\t}\n\t// Abandon if hidden\n\tif(targetElement.style.display != \"block\" ) {\n\t\tremoveElement();\n\t\treturn;\n\t}\n\t// Set up the tiddler that is being closed\n\t$tw.utils.addClass(targetElement,\"tc-storyview-zoomin-tiddler\");\n\t$tw.utils.setStyle(targetElement,[\n\t\t{display: \"block\"},\n\t\t{transformOrigin: \"50% 50%\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t{transition: \"none\"},\n\t\t{zIndex: \"0\"}\n\t]);\n\t// We'll move back to the previous or next element in the story\n\tvar toWidget = widget.previousSibling();\n\tif(!toWidget) {\n\t\ttoWidget = widget.nextSibling();\n\t}\n\tvar toWidgetDomNode = toWidget && toWidget.findFirstDomNode();\n\t// Set up the tiddler we're moving back in\n\tif(toWidgetDomNode) {\n\t\t$tw.utils.addClass(toWidgetDomNode,\"tc-storyview-zoomin-tiddler\");\n\t\t$tw.utils.setStyle(toWidgetDomNode,[\n\t\t\t{display: \"block\"},\n\t\t\t{transformOrigin: \"50% 50%\"},\n\t\t\t{transform: \"translateX(0px) translateY(0px) scale(10)\"},\n\t\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t\t{opacity: \"0\"},\n\t\t\t{zIndex: \"500\"}\n\t\t]);\n\t\tthis.currentTiddlerDomNode = toWidgetDomNode;\n\t}\n\t// Animate them both\n\t// Force layout\n\t$tw.utils.forceLayout(this.listWidget.parentDomNode);\n\t// First, the tiddler we're closing\n\t$tw.utils.setStyle(targetElement,[\n\t\t{transformOrigin: \"50% 50%\"},\n\t\t{transform: \"translateX(0px) translateY(0px) scale(0.1)\"},\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms \" + easing + \", opacity \" + duration + \"ms \" + easing},\n\t\t{opacity: \"0\"},\n\t\t{zIndex: \"0\"}\n\t]);\n\tsetTimeout(removeElement,duration);\n\t// Now the tiddler we're going back to\n\tif(toWidgetDomNode) {\n\t\t$tw.utils.setStyle(toWidgetDomNode,[\n\t\t\t{transform: \"translateX(0px) translateY(0px) scale(1)\"},\n\t\t\t{opacity: \"1\"}\n\t\t]);\n\t}\n\treturn true; // Indicate that we'll delete the DOM node\n};\n\nexports.zoomin = ZoominListView;\n\n})();\n", "title": "$:/core/modules/storyviews/zoomin.js", "type": "application/javascript", "module-type": "storyview" }, "$:/core/modules/syncer.js": { "text": "/*\\\ntitle: $:/core/modules/syncer.js\ntype: application/javascript\nmodule-type: global\n\nThe syncer tracks changes to the store. If a syncadaptor is used then individual tiddlers are synchronised through it. If there is no syncadaptor then the entire wiki is saved via saver modules.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nDefaults\n*/\nSyncer.prototype.titleIsLoggedIn = \"$:/status/IsLoggedIn\";\nSyncer.prototype.titleUserName = \"$:/status/UserName\";\nSyncer.prototype.titleSyncFilter = \"$:/config/SyncFilter\";\nSyncer.prototype.titleSavedNotification = \"$:/language/Notifications/Save/Done\";\nSyncer.prototype.taskTimerInterval = 1 * 1000; // Interval for sync timer\nSyncer.prototype.throttleInterval = 1 * 1000; // Defer saving tiddlers if they've changed in the last 1s...\nSyncer.prototype.fallbackInterval = 10 * 1000; // Unless the task is older than 10s\nSyncer.prototype.pollTimerInterval = 60 * 1000; // Interval for polling for changes from the adaptor\n\n/*\nInstantiate the syncer with the following options:\nsyncadaptor: reference to syncadaptor to be used\nwiki: wiki to be synced\n*/\nfunction Syncer(options) {\n\tvar self = this;\n\tthis.wiki = options.wiki;\n\tthis.syncadaptor = options.syncadaptor;\n\tthis.titleIsLoggedIn = options.titleIsLoggedIn || this.titleIsLoggedIn;\n\tthis.titleUserName = options.titleUserName || this.titleUserName;\n\tthis.titleSyncFilter = options.titleSyncFilter || this.titleSyncFilter;\n\tthis.titleSavedNotification = options.titleSavedNotification || this.titleSavedNotification;\n\tthis.taskTimerInterval = options.taskTimerInterval || this.taskTimerInterval;\n\tthis.throttleInterval = options.throttleInterval || this.throttleInterval;\n\tthis.fallbackInterval = options.fallbackInterval || this.fallbackInterval;\n\tthis.pollTimerInterval = options.pollTimerInterval || this.pollTimerInterval;\n\t// Make a logger\n\tthis.logger = new $tw.utils.Logger(\"syncer\" + ($tw.browser ? \"-browser\" : \"\") + ($tw.node ? \"-server\" : \"\") + (this.syncadaptor.name ? (\"-\" + this.syncadaptor.name) : \"\"));\n\t// Compile the dirty tiddler filter\n\tthis.filterFn = this.wiki.compileFilter(this.wiki.getTiddlerText(this.titleSyncFilter));\n\t// Record information for known tiddlers\n\tthis.readTiddlerInfo();\n\t// Tasks are {type: \"load\"/\"save\"/\"delete\", title:, queueTime:, lastModificationTime:}\n\tthis.taskQueue = {}; // Hashmap of tasks yet to be performed\n\tthis.taskInProgress = {}; // Hash of tasks in progress\n\tthis.taskTimerId = null; // Timer for task dispatch\n\tthis.pollTimerId = null; // Timer for polling server\n\t// Listen out for changes to tiddlers\n\tthis.wiki.addEventListener(\"change\",function(changes) {\n\t\tself.syncToServer(changes);\n\t});\n\t// Browser event handlers\n\tif($tw.browser) {\n\t\t// Set up our beforeunload handler\n\t\t$tw.addUnloadTask(function(event) {\n\t\t\tvar confirmationMessage;\n\t\t\tif(self.isDirty()) {\n\t\t\t\tconfirmationMessage = $tw.language.getString(\"UnsavedChangesWarning\");\n\t\t\t\tevent.returnValue = confirmationMessage; // Gecko\n\t\t\t}\n\t\t\treturn confirmationMessage;\n\t\t});\n\t\t// Listen out for login/logout/refresh events in the browser\n\t\t$tw.rootWidget.addEventListener(\"tm-login\",function() {\n\t\t\tself.handleLoginEvent();\n\t\t});\n\t\t$tw.rootWidget.addEventListener(\"tm-logout\",function() {\n\t\t\tself.handleLogoutEvent();\n\t\t});\n\t\t$tw.rootWidget.addEventListener(\"tm-server-refresh\",function() {\n\t\t\tself.handleRefreshEvent();\n\t\t});\n\t}\n\t// Listen out for lazyLoad events\n\tthis.wiki.addEventListener(\"lazyLoad\",function(title) {\n\t\tself.handleLazyLoadEvent(title);\n\t});\n\t// Get the login status\n\tthis.getStatus(function(err,isLoggedIn) {\n\t\t// Do a sync from the server\n\t\tself.syncFromServer();\n\t});\n}\n\n/*\nRead (or re-read) the latest tiddler info from the store\n*/\nSyncer.prototype.readTiddlerInfo = function() {\n\t// Hashmap by title of {revision:,changeCount:,adaptorInfo:}\n\tthis.tiddlerInfo = {};\n\t// Record information for known tiddlers\n\tvar self = this,\n\t\ttiddlers = this.filterFn.call(this.wiki);\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\tself.tiddlerInfo[title] = {\n\t\t\trevision: tiddler.fields.revision,\n\t\t\tadaptorInfo: self.syncadaptor && self.syncadaptor.getTiddlerInfo(tiddler),\n\t\t\tchangeCount: self.wiki.getChangeCount(title),\n\t\t\thasBeenLazyLoaded: false\n\t\t};\n\t});\n};\n\n/*\nCreate an tiddlerInfo structure if it doesn't already exist\n*/\nSyncer.prototype.createTiddlerInfo = function(title) {\n\tif(!$tw.utils.hop(this.tiddlerInfo,title)) {\n\t\tthis.tiddlerInfo[title] = {\n\t\t\trevision: null,\n\t\t\tadaptorInfo: {},\n\t\t\tchangeCount: -1,\n\t\t\thasBeenLazyLoaded: false\n\t\t};\n\t}\n};\n\n/*\nChecks whether the wiki is dirty (ie the window shouldn't be closed)\n*/\nSyncer.prototype.isDirty = function() {\n\treturn (this.numTasksInQueue() > 0) || (this.numTasksInProgress() > 0);\n};\n\n/*\nUpdate the document body with the class \"tc-dirty\" if the wiki has unsaved/unsynced changes\n*/\nSyncer.prototype.updateDirtyStatus = function() {\n\tif($tw.browser) {\n\t\t$tw.utils.toggleClass(document.body,\"tc-dirty\",this.isDirty());\n\t}\n};\n\n/*\nSave an incoming tiddler in the store, and updates the associated tiddlerInfo\n*/\nSyncer.prototype.storeTiddler = function(tiddlerFields,hasBeenLazyLoaded) {\n\t// Save the tiddler\n\tvar tiddler = new $tw.Tiddler(this.wiki.getTiddler(tiddlerFields.title),tiddlerFields);\n\tthis.wiki.addTiddler(tiddler);\n\t// Save the tiddler revision and changeCount details\n\tthis.tiddlerInfo[tiddlerFields.title] = {\n\t\trevision: tiddlerFields.revision,\n\t\tadaptorInfo: this.syncadaptor.getTiddlerInfo(tiddler),\n\t\tchangeCount: this.wiki.getChangeCount(tiddlerFields.title),\n\t\thasBeenLazyLoaded: hasBeenLazyLoaded !== undefined ? hasBeenLazyLoaded : true\n\t};\n};\n\nSyncer.prototype.getStatus = function(callback) {\n\tvar self = this;\n\t// Check if the adaptor supports getStatus()\n\tif(this.syncadaptor && this.syncadaptor.getStatus) {\n\t\t// Mark us as not logged in\n\t\tthis.wiki.addTiddler({title: this.titleIsLoggedIn,text: \"no\"});\n\t\t// Get login status\n\t\tthis.syncadaptor.getStatus(function(err,isLoggedIn,username) {\n\t\t\tif(err) {\n\t\t\t\tself.logger.alert(err);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Set the various status tiddlers\n\t\t\tself.wiki.addTiddler({title: self.titleIsLoggedIn,text: isLoggedIn ? \"yes\" : \"no\"});\n\t\t\tif(isLoggedIn) {\n\t\t\t\tself.wiki.addTiddler({title: self.titleUserName,text: username || \"\"});\n\t\t\t} else {\n\t\t\t\tself.wiki.deleteTiddler(self.titleUserName);\n\t\t\t}\n\t\t\t// Invoke the callback\n\t\t\tif(callback) {\n\t\t\t\tcallback(err,isLoggedIn,username);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tcallback(null,true,\"UNAUTHENTICATED\");\n\t}\n};\n\n/*\nSynchronise from the server by reading the skinny tiddler list and queuing up loads for any tiddlers that we don't already have up to date\n*/\nSyncer.prototype.syncFromServer = function() {\n\tif(this.syncadaptor && this.syncadaptor.getSkinnyTiddlers) {\n\t\tthis.logger.log(\"Retrieving skinny tiddler list\");\n\t\tvar self = this;\n\t\tif(this.pollTimerId) {\n\t\t\tclearTimeout(this.pollTimerId);\n\t\t\tthis.pollTimerId = null;\n\t\t}\n\t\tthis.syncadaptor.getSkinnyTiddlers(function(err,tiddlers) {\n\t\t\t// Trigger the next sync\n\t\t\tself.pollTimerId = setTimeout(function() {\n\t\t\t\tself.pollTimerId = null;\n\t\t\t\tself.syncFromServer.call(self);\n\t\t\t},self.pollTimerInterval);\n\t\t\t// Check for errors\n\t\t\tif(err) {\n\t\t\t\tself.logger.alert($tw.language.getString(\"Error/RetrievingSkinny\") + \":\",err);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Process each incoming tiddler\n\t\t\tfor(var t=0; t<tiddlers.length; t++) {\n\t\t\t\t// Get the incoming tiddler fields, and the existing tiddler\n\t\t\t\tvar tiddlerFields = tiddlers[t],\n\t\t\t\t\tincomingRevision = tiddlerFields.revision + \"\",\n\t\t\t\t\ttiddler = self.wiki.getTiddler(tiddlerFields.title),\n\t\t\t\t\ttiddlerInfo = self.tiddlerInfo[tiddlerFields.title],\n\t\t\t\t\tcurrRevision = tiddlerInfo ? tiddlerInfo.revision : null;\n\t\t\t\t// Ignore the incoming tiddler if it's the same as the revision we've already got\n\t\t\t\tif(currRevision !== incomingRevision) {\n\t\t\t\t\t// Do a full load if we've already got a fat version of the tiddler\n\t\t\t\t\tif(tiddler && tiddler.fields.text !== undefined) {\n\t\t\t\t\t\t// Do a full load of this tiddler\n\t\t\t\t\t\tself.enqueueSyncTask({\n\t\t\t\t\t\t\ttype: \"load\",\n\t\t\t\t\t\t\ttitle: tiddlerFields.title\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Load the skinny version of the tiddler\n\t\t\t\t\t\tself.storeTiddler(tiddlerFields,false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n};\n\n/*\nSynchronise a set of changes to the server\n*/\nSyncer.prototype.syncToServer = function(changes) {\n\tvar self = this,\n\t\tnow = Date.now(),\n\t\tfilteredChanges = this.filterFn.call(this.wiki,function(callback) {\n\t\t\t$tw.utils.each(changes,function(change,title) {\n\t\t\t\tvar tiddler = self.wiki.getTiddler(title);\n\t\t\t\tcallback(tiddler,title);\n\t\t\t});\n\t\t});\n\t$tw.utils.each(changes,function(change,title,object) {\n\t\t// Process the change if it is a deletion of a tiddler we're already syncing, or is on the filtered change list\n\t\tif((change.deleted && $tw.utils.hop(self.tiddlerInfo,title)) || filteredChanges.indexOf(title) !== -1) {\n\t\t\t// Queue a task to sync this tiddler\n\t\t\tself.enqueueSyncTask({\n\t\t\t\ttype: change.deleted ? \"delete\" : \"save\",\n\t\t\t\ttitle: title\n\t\t\t});\n\t\t}\n\t});\n};\n\n/*\nLazily load a skinny tiddler if we can\n*/\nSyncer.prototype.handleLazyLoadEvent = function(title) {\n\t// Don't lazy load the same tiddler twice\n\tvar info = this.tiddlerInfo[title];\n\tif(!info || !info.hasBeenLazyLoaded) {\n\t\tthis.createTiddlerInfo(title);\n\t\tthis.tiddlerInfo[title].hasBeenLazyLoaded = true;\n\t\t// Queue up a sync task to load this tiddler\n\t\tthis.enqueueSyncTask({\n\t\t\ttype: \"load\",\n\t\t\ttitle: title\n\t\t});\t\t\n\t}\n};\n\n/*\nDispay a password prompt and allow the user to login\n*/\nSyncer.prototype.handleLoginEvent = function() {\n\tvar self = this;\n\tthis.getStatus(function(err,isLoggedIn,username) {\n\t\tif(!isLoggedIn) {\n\t\t\t$tw.passwordPrompt.createPrompt({\n\t\t\t\tserviceName: $tw.language.getString(\"LoginToTiddlySpace\"),\n\t\t\t\tcallback: function(data) {\n\t\t\t\t\tself.login(data.username,data.password,function(err,isLoggedIn) {\n\t\t\t\t\t\tself.syncFromServer();\n\t\t\t\t\t});\n\t\t\t\t\treturn true; // Get rid of the password prompt\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n};\n\n/*\nAttempt to login to TiddlyWeb.\n\tusername: username\n\tpassword: password\n\tcallback: invoked with arguments (err,isLoggedIn)\n*/\nSyncer.prototype.login = function(username,password,callback) {\n\tthis.logger.log(\"Attempting to login as\",username);\n\tvar self = this;\n\tif(this.syncadaptor.login) {\n\t\tthis.syncadaptor.login(username,password,function(err) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tself.getStatus(function(err,isLoggedIn,username) {\n\t\t\t\tif(callback) {\n\t\t\t\t\tcallback(null,isLoggedIn);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t} else {\n\t\tcallback(null,true);\n\t}\n};\n\n/*\nAttempt to log out of TiddlyWeb\n*/\nSyncer.prototype.handleLogoutEvent = function() {\n\tthis.logger.log(\"Attempting to logout\");\n\tvar self = this;\n\tif(this.syncadaptor.logout) {\n\t\tthis.syncadaptor.logout(function(err) {\n\t\t\tif(err) {\n\t\t\t\tself.logger.alert(err);\n\t\t\t} else {\n\t\t\t\tself.getStatus();\n\t\t\t}\n\t\t});\n\t}\n};\n\n/*\nImmediately refresh from the server\n*/\nSyncer.prototype.handleRefreshEvent = function() {\n\tthis.syncFromServer();\n};\n\n/*\nQueue up a sync task. If there is already a pending task for the tiddler, just update the last modification time\n*/\nSyncer.prototype.enqueueSyncTask = function(task) {\n\tvar self = this,\n\t\tnow = Date.now();\n\t// Set the timestamps on this task\n\ttask.queueTime = now;\n\ttask.lastModificationTime = now;\n\t// Fill in some tiddlerInfo if the tiddler is one we haven't seen before\n\tthis.createTiddlerInfo(task.title);\n\t// Bail if this is a save and the tiddler is already at the changeCount that the server has\n\tif(task.type === \"save\" && this.wiki.getChangeCount(task.title) <= this.tiddlerInfo[task.title].changeCount) {\n\t\treturn;\n\t}\n\t// Check if this tiddler is already in the queue\n\tif($tw.utils.hop(this.taskQueue,task.title)) {\n\t\t// this.logger.log(\"Re-queueing up sync task with type:\",task.type,\"title:\",task.title);\n\t\tvar existingTask = this.taskQueue[task.title];\n\t\t// If so, just update the last modification time\n\t\texistingTask.lastModificationTime = task.lastModificationTime;\n\t\t// If the new task is a save then we upgrade the existing task to a save. Thus a pending load is turned into a save if the tiddler changes locally in the meantime. But a pending save is not modified to become a load\n\t\tif(task.type === \"save\" || task.type === \"delete\") {\n\t\t\texistingTask.type = task.type;\n\t\t}\n\t} else {\n\t\t// this.logger.log(\"Queuing up sync task with type:\",task.type,\"title:\",task.title);\n\t\t// If it is not in the queue, insert it\n\t\tthis.taskQueue[task.title] = task;\n\t\tthis.updateDirtyStatus();\n\t}\n\t// Process the queue\n\t$tw.utils.nextTick(function() {self.processTaskQueue.call(self);});\n};\n\n/*\nReturn the number of tasks in progress\n*/\nSyncer.prototype.numTasksInProgress = function() {\n\treturn $tw.utils.count(this.taskInProgress);\n};\n\n/*\nReturn the number of tasks in the queue\n*/\nSyncer.prototype.numTasksInQueue = function() {\n\treturn $tw.utils.count(this.taskQueue);\n};\n\n/*\nTrigger a timeout if one isn't already outstanding\n*/\nSyncer.prototype.triggerTimeout = function() {\n\tvar self = this;\n\tif(!this.taskTimerId) {\n\t\tthis.taskTimerId = setTimeout(function() {\n\t\t\tself.taskTimerId = null;\n\t\t\tself.processTaskQueue.call(self);\n\t\t},self.taskTimerInterval);\n\t}\n};\n\n/*\nProcess the task queue, performing the next task if appropriate\n*/\nSyncer.prototype.processTaskQueue = function() {\n\tvar self = this;\n\t// Only process a task if the sync adaptor is fully initialised and we're not already performing a task. If we are already performing a task then we'll dispatch the next one when it completes\n\tif((!this.syncadaptor.isReady || this.syncadaptor.isReady()) && this.numTasksInProgress() === 0) {\n\t\t// Choose the next task to perform\n\t\tvar task = this.chooseNextTask();\n\t\t// Perform the task if we had one\n\t\tif(task) {\n\t\t\t// Remove the task from the queue and add it to the in progress list\n\t\t\tdelete this.taskQueue[task.title];\n\t\t\tthis.taskInProgress[task.title] = task;\n\t\t\tthis.updateDirtyStatus();\n\t\t\t// Dispatch the task\n\t\t\tthis.dispatchTask(task,function(err) {\n\t\t\t\tif(err) {\n\t\t\t\t\tself.logger.alert(\"Sync error while processing '\" + task.title + \"':\\n\" + err);\n\t\t\t\t}\n\t\t\t\t// Mark that this task is no longer in progress\n\t\t\t\tdelete self.taskInProgress[task.title];\n\t\t\t\tself.updateDirtyStatus();\n\t\t\t\t// Process the next task\n\t\t\t\tself.processTaskQueue.call(self);\n\t\t\t});\n\t\t} else {\n\t\t\t// Make sure we've set a time if there wasn't a task to perform, but we've still got tasks in the queue\n\t\t\tif(this.numTasksInQueue() > 0) {\n\t\t\t\tthis.triggerTimeout();\n\t\t\t}\n\t\t}\n\t}\n};\n\n/*\nChoose the next applicable task\n*/\nSyncer.prototype.chooseNextTask = function() {\n\tvar self = this,\n\t\tcandidateTask = null,\n\t\tnow = Date.now();\n\t// Select the best candidate task\n\t$tw.utils.each(this.taskQueue,function(task,title) {\n\t\t// Exclude the task if there's one of the same name in progress\n\t\tif($tw.utils.hop(self.taskInProgress,title)) {\n\t\t\treturn;\n\t\t}\n\t\t// Exclude the task if it is a save and the tiddler has been modified recently, but not hit the fallback time\n\t\tif(task.type === \"save\" && (now - task.lastModificationTime) < self.throttleInterval &&\n\t\t\t(now - task.queueTime) < self.fallbackInterval) {\n\t\t\treturn;\n\t\t}\n\t\t// Exclude the task if it is newer than the current best candidate\n\t\tif(candidateTask && candidateTask.queueTime < task.queueTime) {\n\t\t\treturn;\n\t\t}\n\t\t// Now this is our best candidate\n\t\tcandidateTask = task;\n\t});\n\treturn candidateTask;\n};\n\n/*\nDispatch a task and invoke the callback\n*/\nSyncer.prototype.dispatchTask = function(task,callback) {\n\tvar self = this;\n\tif(task.type === \"save\") {\n\t\tvar changeCount = this.wiki.getChangeCount(task.title),\n\t\t\ttiddler = this.wiki.getTiddler(task.title);\n\t\tthis.logger.log(\"Dispatching 'save' task:\",task.title);\n\t\tif(tiddler) {\n\t\t\tthis.syncadaptor.saveTiddler(tiddler,function(err,adaptorInfo,revision) {\n\t\t\t\tif(err) {\n\t\t\t\t\treturn callback(err);\n\t\t\t\t}\n\t\t\t\t// Adjust the info stored about this tiddler\n\t\t\t\tself.tiddlerInfo[task.title] = {\n\t\t\t\t\tchangeCount: changeCount,\n\t\t\t\t\tadaptorInfo: adaptorInfo,\n\t\t\t\t\trevision: revision\n\t\t\t\t};\n\t\t\t\t// Invoke the callback\n\t\t\t\tcallback(null);\n\t\t\t},{\n\t\t\t\ttiddlerInfo: self.tiddlerInfo[task.title]\n\t\t\t});\n\t\t} else {\n\t\t\tthis.logger.log(\" Not Dispatching 'save' task:\",task.title,\"tiddler does not exist\");\n\t\t\treturn callback(null);\n\t\t}\n\t} else if(task.type === \"load\") {\n\t\t// Load the tiddler\n\t\tthis.logger.log(\"Dispatching 'load' task:\",task.title);\n\t\tthis.syncadaptor.loadTiddler(task.title,function(err,tiddlerFields) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\t// Store the tiddler\n\t\t\tif(tiddlerFields) {\n\t\t\t\tself.storeTiddler(tiddlerFields,true);\n\t\t\t}\n\t\t\t// Invoke the callback\n\t\t\tcallback(null);\n\t\t});\n\t} else if(task.type === \"delete\") {\n\t\t// Delete the tiddler\n\t\tthis.logger.log(\"Dispatching 'delete' task:\",task.title);\n\t\tthis.syncadaptor.deleteTiddler(task.title,function(err) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tdelete self.tiddlerInfo[task.title];\n\t\t\t// Invoke the callback\n\t\t\tcallback(null);\n\t\t},{\n\t\t\ttiddlerInfo: self.tiddlerInfo[task.title]\n\t\t});\n\t}\n};\n\nexports.Syncer = Syncer;\n\n})();\n", "title": "$:/core/modules/syncer.js", "type": "application/javascript", "module-type": "global" }, "$:/core/modules/tiddler.js": { "text": "/*\\\ntitle: $:/core/modules/tiddler.js\ntype: application/javascript\nmodule-type: tiddlermethod\n\nExtension methods for the $tw.Tiddler object (constructor and methods required at boot time are in boot/boot.js)\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.hasTag = function(tag) {\n\treturn this.fields.tags && this.fields.tags.indexOf(tag) !== -1;\n};\n\nexports.isPlugin = function() {\n\treturn this.fields.type === \"application/json\" && this.hasField(\"plugin-type\");\n};\n\nexports.isDraft = function() {\n\treturn this.hasField(\"draft.of\");\n};\n\nexports.getFieldString = function(field) {\n\tvar value = this.fields[field];\n\t// Check for a missing field\n\tif(value === undefined || value === null) {\n\t\treturn \"\";\n\t}\n\t// Parse the field with the associated module (if any)\n\tvar fieldModule = $tw.Tiddler.fieldModules[field];\n\tif(fieldModule && fieldModule.stringify) {\n\t\treturn fieldModule.stringify.call(this,value);\n\t} else {\n\t\treturn value.toString();\n\t}\n};\n\n/*\nGet all the fields as a hashmap of strings. Options:\n\texclude: an array of field names to exclude\n*/\nexports.getFieldStrings = function(options) {\n\toptions = options || {};\n\tvar exclude = options.exclude || [];\n\tvar fields = {};\n\tfor(var field in this.fields) {\n\t\tif($tw.utils.hop(this.fields,field)) {\n\t\t\tif(exclude.indexOf(field) === -1) {\n\t\t\t\tfields[field] = this.getFieldString(field);\n\t\t\t}\n\t\t}\n\t}\n\treturn fields;\n};\n\n/*\nGet all the fields as a name:value block. Options:\n\texclude: an array of field names to exclude\n*/\nexports.getFieldStringBlock = function(options) {\n\toptions = options || {};\n\tvar exclude = options.exclude || [];\n\tvar fields = [];\n\tfor(var field in this.fields) {\n\t\tif($tw.utils.hop(this.fields,field)) {\n\t\t\tif(exclude.indexOf(field) === -1) {\n\t\t\t\tfields.push(field + \": \" + this.getFieldString(field));\n\t\t\t}\n\t\t}\n\t}\n\treturn fields.join(\"\\n\");\n};\n\n/*\nCompare two tiddlers for equality\ntiddler: the tiddler to compare\nexcludeFields: array of field names to exclude from the comparison\n*/\nexports.isEqual = function(tiddler,excludeFields) {\n\tif(!(tiddler instanceof $tw.Tiddler)) {\n\t\treturn false;\n\t}\n\texcludeFields = excludeFields || [];\n\tvar self = this,\n\t\tdifferences = []; // Fields that have differences\n\t// Add to the differences array\n\tfunction addDifference(fieldName) {\n\t\t// Check for this field being excluded\n\t\tif(excludeFields.indexOf(fieldName) === -1) {\n\t\t\t// Save the field as a difference\n\t\t\t$tw.utils.pushTop(differences,fieldName);\n\t\t}\n\t}\n\t// Returns true if the two values of this field are equal\n\tfunction isFieldValueEqual(fieldName) {\n\t\tvar valueA = self.fields[fieldName],\n\t\t\tvalueB = tiddler.fields[fieldName];\n\t\t// Check for identical string values\n\t\tif(typeof(valueA) === \"string\" && typeof(valueB) === \"string\" && valueA === valueB) {\n\t\t\treturn true;\n\t\t}\n\t\t// Check for identical array values\n\t\tif($tw.utils.isArray(valueA) && $tw.utils.isArray(valueB) && $tw.utils.isArrayEqual(valueA,valueB)) {\n\t\t\treturn true;\n\t\t}\n\t\t// Otherwise the fields must be different\n\t\treturn false;\n\t}\n\t// Compare our fields\n\tfor(var fieldName in this.fields) {\n\t\tif(!isFieldValueEqual(fieldName)) {\n\t\t\taddDifference(fieldName);\n\t\t}\n\t}\n\t// There's a difference for every field in the other tiddler that we don't have\n\tfor(fieldName in tiddler.fields) {\n\t\tif(!(fieldName in this.fields)) {\n\t\t\taddDifference(fieldName);\n\t\t}\n\t}\n\t// Return whether there were any differences\n\treturn differences.length === 0;\n};\n\nexports.getFieldDay = function(field) {\n\tif(this.cache && this.cache.day && $tw.utils.hop(this.cache.day,field) ) {\n\t\treturn this.cache.day[field];\n\t}\n\tvar day = \"\";\n\tif(this.fields[field]) {\n\t\tday = (new Date($tw.utils.parseDate(this.fields[field]))).setHours(0,0,0,0);\n\t}\n\tthis.cache.day = this.cache.day || {};\n\tthis.cache.day[field] = day;\n\treturn day;\n};\n\n})();\n", "title": "$:/core/modules/tiddler.js", "type": "application/javascript", "module-type": "tiddlermethod" }, "$:/core/modules/upgraders/plugins.js": { "text": "/*\\\ntitle: $:/core/modules/upgraders/plugins.js\ntype: application/javascript\nmodule-type: upgrader\n\nUpgrader module that checks that plugins are newer than any already installed version\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar UPGRADE_LIBRARY_TITLE = \"$:/UpgradeLibrary\";\n\nvar BLOCKED_PLUGINS = {\n\t\"$:/themes/tiddlywiki/stickytitles\": {\n\t\tversions: [\"*\"]\n\t},\n\t\"$:/plugins/tiddlywiki/fullscreen\": {\n\t\tversions: [\"*\"]\n\t}\n};\n\nexports.upgrade = function(wiki,titles,tiddlers) {\n\tvar self = this,\n\t\tmessages = {},\n\t\tupgradeLibrary,\n\t\tgetLibraryTiddler = function(title) {\n\t\t\tif(!upgradeLibrary) {\n\t\t\t\tupgradeLibrary = wiki.getTiddlerData(UPGRADE_LIBRARY_TITLE,{});\n\t\t\t\tupgradeLibrary.tiddlers = upgradeLibrary.tiddlers || {};\n\t\t\t}\n\t\t\treturn upgradeLibrary.tiddlers[title];\n\t\t};\n\n\t// Go through all the incoming tiddlers\n\t$tw.utils.each(titles,function(title) {\n\t\tvar incomingTiddler = tiddlers[title];\n\t\t// Check if we're dealing with a plugin\n\t\tif(incomingTiddler && incomingTiddler[\"plugin-type\"] && incomingTiddler.version) {\n\t\t\t// Upgrade the incoming plugin if it is in the upgrade library\n\t\t\tvar libraryTiddler = getLibraryTiddler(title);\n\t\t\tif(libraryTiddler && libraryTiddler[\"plugin-type\"] && libraryTiddler.version) {\n\t\t\t\ttiddlers[title] = libraryTiddler;\n\t\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/Plugins/Upgraded\",{variables: {incoming: incomingTiddler.version, upgraded: libraryTiddler.version}});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Suppress the incoming plugin if it is older than the currently installed one\n\t\t\tvar existingTiddler = wiki.getTiddler(title);\n\t\t\tif(existingTiddler && existingTiddler.hasField(\"plugin-type\") && existingTiddler.hasField(\"version\")) {\n\t\t\t\t// Reject the incoming plugin by blanking all its fields\n\t\t\t\tif($tw.utils.checkVersions(existingTiddler.fields.version,incomingTiddler.version)) {\n\t\t\t\t\ttiddlers[title] = Object.create(null);\n\t\t\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/Plugins/Suppressed/Version\",{variables: {incoming: incomingTiddler.version, existing: existingTiddler.fields.version}});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(incomingTiddler && incomingTiddler[\"plugin-type\"]) {\n\t\t\t// Check whether the plugin is on the blocked list\n\t\t\tvar blockInfo = BLOCKED_PLUGINS[title];\n\t\t\tif(blockInfo) {\n\t\t\t\tif(blockInfo.versions.indexOf(\"*\") !== -1 || (incomingTiddler.version && blockInfo.versions.indexOf(incomingTiddler.version) !== -1)) {\n\t\t\t\t\ttiddlers[title] = Object.create(null);\n\t\t\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/Plugins/Suppressed/Incompatible\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\treturn messages;\n};\n\n})();\n", "title": "$:/core/modules/upgraders/plugins.js", "type": "application/javascript", "module-type": "upgrader" }, "$:/core/modules/upgraders/system.js": { "text": "/*\\\ntitle: $:/core/modules/upgraders/system.js\ntype: application/javascript\nmodule-type: upgrader\n\nUpgrader module that suppresses certain system tiddlers that shouldn't be imported\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar DONT_IMPORT_LIST = [\"$:/StoryList\",\"$:/HistoryList\"],\n\tDONT_IMPORT_PREFIX_LIST = [\"$:/temp/\",\"$:/state/\"];\n\nexports.upgrade = function(wiki,titles,tiddlers) {\n\tvar self = this,\n\t\tmessages = {};\n\t// Check for tiddlers on our list\n\t$tw.utils.each(titles,function(title) {\n\t\tif(DONT_IMPORT_LIST.indexOf(title) !== -1) {\n\t\t\ttiddlers[title] = Object.create(null);\n\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/System/Suppressed\");\n\t\t} else {\n\t\t\tfor(var t=0; t<DONT_IMPORT_PREFIX_LIST.length; t++) {\n\t\t\t\tvar prefix = DONT_IMPORT_PREFIX_LIST[t];\n\t\t\t\tif(title.substr(0,prefix.length) === prefix) {\n\t\t\t\t\ttiddlers[title] = Object.create(null);\n\t\t\t\t\tmessages[title] = $tw.language.getString(\"Import/Upgrader/State/Suppressed\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\treturn messages;\n};\n\n})();\n", "title": "$:/core/modules/upgraders/system.js", "type": "application/javascript", "module-type": "upgrader" }, "$:/core/modules/upgraders/themetweaks.js": { "text": "/*\\\ntitle: $:/core/modules/upgraders/themetweaks.js\ntype: application/javascript\nmodule-type: upgrader\n\nUpgrader module that handles the change in theme tweak storage introduced in 5.0.14-beta.\n\nPreviously, theme tweaks were stored in two data tiddlers:\n\n* $:/themes/tiddlywiki/vanilla/metrics\n* $:/themes/tiddlywiki/vanilla/settings\n\nNow, each tweak is stored in its own separate tiddler.\n\nThis upgrader copies any values from the old format to the new. The old data tiddlers are not deleted in case they have been used to store additional indexes.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar MAPPINGS = {\n\t\"$:/themes/tiddlywiki/vanilla/metrics\": {\n\t\t\"fontsize\": \"$:/themes/tiddlywiki/vanilla/metrics/fontsize\",\n\t\t\"lineheight\": \"$:/themes/tiddlywiki/vanilla/metrics/lineheight\",\n\t\t\"storyleft\": \"$:/themes/tiddlywiki/vanilla/metrics/storyleft\",\n\t\t\"storytop\": \"$:/themes/tiddlywiki/vanilla/metrics/storytop\",\n\t\t\"storyright\": \"$:/themes/tiddlywiki/vanilla/metrics/storyright\",\n\t\t\"storywidth\": \"$:/themes/tiddlywiki/vanilla/metrics/storywidth\",\n\t\t\"tiddlerwidth\": \"$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth\"\n\t},\n\t\"$:/themes/tiddlywiki/vanilla/settings\": {\n\t\t\"fontfamily\": \"$:/themes/tiddlywiki/vanilla/settings/fontfamily\"\n\t}\n};\n\nexports.upgrade = function(wiki,titles,tiddlers) {\n\tvar self = this,\n\t\tmessages = {};\n\t// Check for tiddlers on our list\n\t$tw.utils.each(titles,function(title) {\n\t\tvar mapping = MAPPINGS[title];\n\t\tif(mapping) {\n\t\t\tvar tiddler = new $tw.Tiddler(tiddlers[title]),\n\t\t\t\ttiddlerData = wiki.getTiddlerDataCached(tiddler,{});\n\t\t\tfor(var index in mapping) {\n\t\t\t\tvar mappedTitle = mapping[index];\n\t\t\t\tif(!tiddlers[mappedTitle] || tiddlers[mappedTitle].title !== mappedTitle) {\n\t\t\t\t\ttiddlers[mappedTitle] = {\n\t\t\t\t\t\ttitle: mappedTitle,\n\t\t\t\t\t\ttext: tiddlerData[index]\n\t\t\t\t\t};\n\t\t\t\t\tmessages[mappedTitle] = $tw.language.getString(\"Import/Upgrader/ThemeTweaks/Created\",{variables: {\n\t\t\t\t\t\tfrom: title + \"##\" + index\n\t\t\t\t\t}});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\treturn messages;\n};\n\n})();\n", "title": "$:/core/modules/upgraders/themetweaks.js", "type": "application/javascript", "module-type": "upgrader" }, "$:/core/modules/utils/crypto.js": { "text": "/*\\\ntitle: $:/core/modules/utils/crypto.js\ntype: application/javascript\nmodule-type: utils\n\nUtility functions related to crypto.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nLook for an encrypted store area in the text of a TiddlyWiki file\n*/\nexports.extractEncryptedStoreArea = function(text) {\n\tvar encryptedStoreAreaStartMarker = \"<pre id=\\\"encryptedStoreArea\\\" type=\\\"text/plain\\\" style=\\\"display:none;\\\">\",\n\t\tencryptedStoreAreaStart = text.indexOf(encryptedStoreAreaStartMarker);\n\tif(encryptedStoreAreaStart !== -1) {\n\t\tvar encryptedStoreAreaEnd = text.indexOf(\"</pre>\",encryptedStoreAreaStart);\n\t\tif(encryptedStoreAreaEnd !== -1) {\n\t\t\treturn $tw.utils.htmlDecode(text.substring(encryptedStoreAreaStart + encryptedStoreAreaStartMarker.length,encryptedStoreAreaEnd-1));\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nAttempt to extract the tiddlers from an encrypted store area using the current password. If the password is not provided then the password in the password store will be used\n*/\nexports.decryptStoreArea = function(encryptedStoreArea,password) {\n\tvar decryptedText = $tw.crypto.decrypt(encryptedStoreArea,password);\n\tif(decryptedText) {\n\t\tvar json = JSON.parse(decryptedText),\n\t\t\ttiddlers = [];\n\t\tfor(var title in json) {\n\t\t\tif(title !== \"$:/isEncrypted\") {\n\t\t\t\ttiddlers.push(json[title]);\n\t\t\t}\n\t\t}\n\t\treturn tiddlers;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n\n/*\nAttempt to extract the tiddlers from an encrypted store area using the current password. If that fails, the user is prompted for a password.\nencryptedStoreArea: text of the TiddlyWiki encrypted store area\ncallback: function(tiddlers) called with the array of decrypted tiddlers\n\nThe following configuration settings are supported:\n\n$tw.config.usePasswordVault: causes any password entered by the user to also be put into the system password vault\n*/\nexports.decryptStoreAreaInteractive = function(encryptedStoreArea,callback,options) {\n\t// Try to decrypt with the current password\n\tvar tiddlers = $tw.utils.decryptStoreArea(encryptedStoreArea);\n\tif(tiddlers) {\n\t\tcallback(tiddlers);\n\t} else {\n\t\t// Prompt for a new password and keep trying\n\t\t$tw.passwordPrompt.createPrompt({\n\t\t\tserviceName: \"Enter a password to decrypt the imported TiddlyWiki\",\n\t\t\tnoUserName: true,\n\t\t\tcanCancel: true,\n\t\t\tsubmitText: \"Decrypt\",\n\t\t\tcallback: function(data) {\n\t\t\t\t// Exit if the user cancelled\n\t\t\t\tif(!data) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t// Attempt to decrypt the tiddlers\n\t\t\t\tvar tiddlers = $tw.utils.decryptStoreArea(encryptedStoreArea,data.password);\n\t\t\t\tif(tiddlers) {\n\t\t\t\t\tif($tw.config.usePasswordVault) {\n\t\t\t\t\t\t$tw.crypto.setPassword(data.password);\n\t\t\t\t\t}\n\t\t\t\t\tcallback(tiddlers);\n\t\t\t\t\t// Exit and remove the password prompt\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\t// We didn't decrypt everything, so continue to prompt for password\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n};\n\n})();\n", "title": "$:/core/modules/utils/crypto.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/dom/animations/slide.js": { "text": "/*\\\ntitle: $:/core/modules/utils/dom/animations/slide.js\ntype: application/javascript\nmodule-type: animation\n\nA simple slide animation that varies the height of the element\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nfunction slideOpen(domNode,options) {\n\toptions = options || {};\n\tvar duration = options.duration || $tw.utils.getAnimationDuration();\n\t// Get the current height of the domNode\n\tvar computedStyle = window.getComputedStyle(domNode),\n\t\tcurrMarginBottom = parseInt(computedStyle.marginBottom,10),\n\t\tcurrMarginTop = parseInt(computedStyle.marginTop,10),\n\t\tcurrPaddingBottom = parseInt(computedStyle.paddingBottom,10),\n\t\tcurrPaddingTop = parseInt(computedStyle.paddingTop,10),\n\t\tcurrHeight = domNode.offsetHeight;\n\t// Reset the margin once the transition is over\n\tsetTimeout(function() {\n\t\t$tw.utils.setStyle(domNode,[\n\t\t\t{transition: \"none\"},\n\t\t\t{marginBottom: \"\"},\n\t\t\t{marginTop: \"\"},\n\t\t\t{paddingBottom: \"\"},\n\t\t\t{paddingTop: \"\"},\n\t\t\t{height: \"auto\"},\n\t\t\t{opacity: \"\"}\n\t\t]);\n\t\tif(options.callback) {\n\t\t\toptions.callback();\n\t\t}\n\t},duration);\n\t// Set up the initial position of the element\n\t$tw.utils.setStyle(domNode,[\n\t\t{transition: \"none\"},\n\t\t{marginTop: \"0px\"},\n\t\t{marginBottom: \"0px\"},\n\t\t{paddingTop: \"0px\"},\n\t\t{paddingBottom: \"0px\"},\n\t\t{height: \"0px\"},\n\t\t{opacity: \"0\"}\n\t]);\n\t$tw.utils.forceLayout(domNode);\n\t// Transition to the final position\n\t$tw.utils.setStyle(domNode,[\n\t\t{transition: \"margin-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"margin-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"height \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{marginBottom: currMarginBottom + \"px\"},\n\t\t{marginTop: currMarginTop + \"px\"},\n\t\t{paddingBottom: currPaddingBottom + \"px\"},\n\t\t{paddingTop: currPaddingTop + \"px\"},\n\t\t{height: currHeight + \"px\"},\n\t\t{opacity: \"1\"}\n\t]);\n}\n\nfunction slideClosed(domNode,options) {\n\toptions = options || {};\n\tvar duration = options.duration || $tw.utils.getAnimationDuration(),\n\t\tcurrHeight = domNode.offsetHeight;\n\t// Clear the properties we've set when the animation is over\n\tsetTimeout(function() {\n\t\t$tw.utils.setStyle(domNode,[\n\t\t\t{transition: \"none\"},\n\t\t\t{marginBottom: \"\"},\n\t\t\t{marginTop: \"\"},\n\t\t\t{paddingBottom: \"\"},\n\t\t\t{paddingTop: \"\"},\n\t\t\t{height: \"auto\"},\n\t\t\t{opacity: \"\"}\n\t\t]);\n\t\tif(options.callback) {\n\t\t\toptions.callback();\n\t\t}\n\t},duration);\n\t// Set up the initial position of the element\n\t$tw.utils.setStyle(domNode,[\n\t\t{height: currHeight + \"px\"},\n\t\t{opacity: \"1\"}\n\t]);\n\t$tw.utils.forceLayout(domNode);\n\t// Transition to the final position\n\t$tw.utils.setStyle(domNode,[\n\t\t{transition: \"margin-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"margin-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-top \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"padding-bottom \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"height \" + duration + \"ms ease-in-out, \" +\n\t\t\t\t\t\"opacity \" + duration + \"ms ease-in-out\"},\n\t\t{marginTop: \"0px\"},\n\t\t{marginBottom: \"0px\"},\n\t\t{paddingTop: \"0px\"},\n\t\t{paddingBottom: \"0px\"},\n\t\t{height: \"0px\"},\n\t\t{opacity: \"0\"}\n\t]);\n}\n\nexports.slide = {\n\topen: slideOpen,\n\tclose: slideClosed\n};\n\n})();\n", "title": "$:/core/modules/utils/dom/animations/slide.js", "type": "application/javascript", "module-type": "animation" }, "$:/core/modules/utils/dom/animator.js": { "text": "/*\\\ntitle: $:/core/modules/utils/dom/animator.js\ntype: application/javascript\nmodule-type: utils\n\nOrchestrates animations and transitions\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nfunction Animator() {\n\t// Get the registered animation modules\n\tthis.animations = {};\n\t$tw.modules.applyMethods(\"animation\",this.animations);\n}\n\nAnimator.prototype.perform = function(type,domNode,options) {\n\toptions = options || {};\n\t// Find an animation that can handle this type\n\tvar chosenAnimation;\n\t$tw.utils.each(this.animations,function(animation,name) {\n\t\tif($tw.utils.hop(animation,type)) {\n\t\t\tchosenAnimation = animation[type];\n\t\t}\n\t});\n\tif(!chosenAnimation) {\n\t\tchosenAnimation = function(domNode,options) {\n\t\t\tif(options.callback) {\n\t\t\t\toptions.callback();\n\t\t\t}\n\t\t};\n\t}\n\t// Call the animation\n\tchosenAnimation(domNode,options);\n};\n\nexports.Animator = Animator;\n\n})();\n", "title": "$:/core/modules/utils/dom/animator.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/dom/browser.js": { "text": "/*\\\ntitle: $:/core/modules/utils/dom/browser.js\ntype: application/javascript\nmodule-type: utils\n\nBrowser feature detection\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nSet style properties of an element\n\telement: dom node\n\tstyles: ordered array of {name: value} pairs\n*/\nexports.setStyle = function(element,styles) {\n\tif(element.nodeType === 1) { // Element.ELEMENT_NODE\n\t\tfor(var t=0; t<styles.length; t++) {\n\t\t\tfor(var styleName in styles[t]) {\n\t\t\t\telement.style[$tw.utils.convertStyleNameToPropertyName(styleName)] = styles[t][styleName];\n\t\t\t}\n\t\t}\n\t}\n};\n\n/*\nConverts a standard CSS property name into the local browser-specific equivalent. For example:\n\t\"background-color\" --> \"backgroundColor\"\n\t\"transition\" --> \"webkitTransition\"\n*/\n\nvar styleNameCache = {}; // We'll cache the style name conversions\n\nexports.convertStyleNameToPropertyName = function(styleName) {\n\t// Return from the cache if we can\n\tif(styleNameCache[styleName]) {\n\t\treturn styleNameCache[styleName];\n\t}\n\t// Convert it by first removing any hyphens\n\tvar propertyName = $tw.utils.unHyphenateCss(styleName);\n\t// Then check if it needs a prefix\n\tif($tw.browser && document.body.style[propertyName] === undefined) {\n\t\tvar prefixes = [\"O\",\"MS\",\"Moz\",\"webkit\"];\n\t\tfor(var t=0; t<prefixes.length; t++) {\n\t\t\tvar prefixedName = prefixes[t] + propertyName.substr(0,1).toUpperCase() + propertyName.substr(1);\n\t\t\tif(document.body.style[prefixedName] !== undefined) {\n\t\t\t\tpropertyName = prefixedName;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t// Put it in the cache too\n\tstyleNameCache[styleName] = propertyName;\n\treturn propertyName;\n};\n\n/*\nConverts a JS format CSS property name back into the dashed form used in CSS declarations. For example:\n\t\"backgroundColor\" --> \"background-color\"\n\t\"webkitTransform\" --> \"-webkit-transform\"\n*/\nexports.convertPropertyNameToStyleName = function(propertyName) {\n\t// Rehyphenate the name\n\tvar styleName = $tw.utils.hyphenateCss(propertyName);\n\t// If there's a webkit prefix, add a dash (other browsers have uppercase prefixes, and so get the dash automatically)\n\tif(styleName.indexOf(\"webkit\") === 0) {\n\t\tstyleName = \"-\" + styleName;\n\t} else if(styleName.indexOf(\"-m-s\") === 0) {\n\t\tstyleName = \"-ms\" + styleName.substr(4);\n\t}\n\treturn styleName;\n};\n\n/*\nRound trip a stylename to a property name and back again. For example:\n\t\"transform\" --> \"webkitTransform\" --> \"-webkit-transform\"\n*/\nexports.roundTripPropertyName = function(propertyName) {\n\treturn $tw.utils.convertPropertyNameToStyleName($tw.utils.convertStyleNameToPropertyName(propertyName));\n};\n\n/*\nConverts a standard event name into the local browser specific equivalent. For example:\n\t\"animationEnd\" --> \"webkitAnimationEnd\"\n*/\n\nvar eventNameCache = {}; // We'll cache the conversions\n\nvar eventNameMappings = {\n\t\"transitionEnd\": {\n\t\tcorrespondingCssProperty: \"transition\",\n\t\tmappings: {\n\t\t\ttransition: \"transitionend\",\n\t\t\tOTransition: \"oTransitionEnd\",\n\t\t\tMSTransition: \"msTransitionEnd\",\n\t\t\tMozTransition: \"transitionend\",\n\t\t\twebkitTransition: \"webkitTransitionEnd\"\n\t\t}\n\t},\n\t\"animationEnd\": {\n\t\tcorrespondingCssProperty: \"animation\",\n\t\tmappings: {\n\t\t\tanimation: \"animationend\",\n\t\t\tOAnimation: \"oAnimationEnd\",\n\t\t\tMSAnimation: \"msAnimationEnd\",\n\t\t\tMozAnimation: \"animationend\",\n\t\t\twebkitAnimation: \"webkitAnimationEnd\"\n\t\t}\n\t}\n};\n\nexports.convertEventName = function(eventName) {\n\tif(eventNameCache[eventName]) {\n\t\treturn eventNameCache[eventName];\n\t}\n\tvar newEventName = eventName,\n\t\tmappings = eventNameMappings[eventName];\n\tif(mappings) {\n\t\tvar convertedProperty = $tw.utils.convertStyleNameToPropertyName(mappings.correspondingCssProperty);\n\t\tif(mappings.mappings[convertedProperty]) {\n\t\t\tnewEventName = mappings.mappings[convertedProperty];\n\t\t}\n\t}\n\t// Put it in the cache too\n\teventNameCache[eventName] = newEventName;\n\treturn newEventName;\n};\n\n/*\nReturn the names of the fullscreen APIs\n*/\nexports.getFullScreenApis = function() {\n\tvar d = document,\n\t\tdb = d.body,\n\t\tresult = {\n\t\t\"_requestFullscreen\": db.webkitRequestFullscreen !== undefined ? \"webkitRequestFullscreen\" :\n\t\t\t\t\t\t\tdb.mozRequestFullScreen !== undefined ? \"mozRequestFullScreen\" :\n\t\t\t\t\t\t\tdb.msRequestFullscreen !== undefined ? \"msRequestFullscreen\" :\n\t\t\t\t\t\t\tdb.requestFullscreen !== undefined ? \"requestFullscreen\" : \"\",\n\t\t\"_exitFullscreen\": d.webkitExitFullscreen !== undefined ? \"webkitExitFullscreen\" :\n\t\t\t\t\t\t\td.mozCancelFullScreen !== undefined ? \"mozCancelFullScreen\" :\n\t\t\t\t\t\t\td.msExitFullscreen !== undefined ? \"msExitFullscreen\" :\n\t\t\t\t\t\t\td.exitFullscreen !== undefined ? \"exitFullscreen\" : \"\",\n\t\t\"_fullscreenElement\": d.webkitFullscreenElement !== undefined ? \"webkitFullscreenElement\" :\n\t\t\t\t\t\t\td.mozFullScreenElement !== undefined ? \"mozFullScreenElement\" :\n\t\t\t\t\t\t\td.msFullscreenElement !== undefined ? \"msFullscreenElement\" :\n\t\t\t\t\t\t\td.fullscreenElement !== undefined ? \"fullscreenElement\" : \"\",\n\t\t\"_fullscreenChange\": d.webkitFullscreenElement !== undefined ? \"webkitfullscreenchange\" :\n\t\t\t\t\t\t\td.mozFullScreenElement !== undefined ? \"mozfullscreenchange\" :\n\t\t\t\t\t\t\td.msFullscreenElement !== undefined ? \"MSFullscreenChange\" :\n\t\t\t\t\t\t\td.fullscreenElement !== undefined ? \"fullscreenchange\" : \"\"\n\t};\n\tif(!result._requestFullscreen || !result._exitFullscreen || !result._fullscreenElement || !result._fullscreenChange) {\n\t\treturn null;\n\t} else {\n\t\treturn result;\n\t}\n};\n\n})();\n", "title": "$:/core/modules/utils/dom/browser.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/dom/csscolorparser.js": { "text": "// (c) Dean McNamee <dean@gmail.com>, 2012.\n//\n// https://github.com/deanm/css-color-parser-js\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n// IN THE SOFTWARE.\n\n// http://www.w3.org/TR/css3-color/\nvar kCSSColorTable = {\n \"transparent\": [0,0,0,0], \"aliceblue\": [240,248,255,1],\n \"antiquewhite\": [250,235,215,1], \"aqua\": [0,255,255,1],\n \"aquamarine\": [127,255,212,1], \"azure\": [240,255,255,1],\n \"beige\": [245,245,220,1], \"bisque\": [255,228,196,1],\n \"black\": [0,0,0,1], \"blanchedalmond\": [255,235,205,1],\n \"blue\": [0,0,255,1], \"blueviolet\": [138,43,226,1],\n \"brown\": [165,42,42,1], \"burlywood\": [222,184,135,1],\n \"cadetblue\": [95,158,160,1], \"chartreuse\": [127,255,0,1],\n \"chocolate\": [210,105,30,1], \"coral\": [255,127,80,1],\n \"cornflowerblue\": [100,149,237,1], \"cornsilk\": [255,248,220,1],\n \"crimson\": [220,20,60,1], \"cyan\": [0,255,255,1],\n \"darkblue\": [0,0,139,1], \"darkcyan\": [0,139,139,1],\n \"darkgoldenrod\": [184,134,11,1], \"darkgray\": [169,169,169,1],\n \"darkgreen\": [0,100,0,1], \"darkgrey\": [169,169,169,1],\n \"darkkhaki\": [189,183,107,1], \"darkmagenta\": [139,0,139,1],\n \"darkolivegreen\": [85,107,47,1], \"darkorange\": [255,140,0,1],\n \"darkorchid\": [153,50,204,1], \"darkred\": [139,0,0,1],\n \"darksalmon\": [233,150,122,1], \"darkseagreen\": [143,188,143,1],\n \"darkslateblue\": [72,61,139,1], \"darkslategray\": [47,79,79,1],\n \"darkslategrey\": [47,79,79,1], \"darkturquoise\": [0,206,209,1],\n \"darkviolet\": [148,0,211,1], \"deeppink\": [255,20,147,1],\n \"deepskyblue\": [0,191,255,1], \"dimgray\": [105,105,105,1],\n \"dimgrey\": [105,105,105,1], \"dodgerblue\": [30,144,255,1],\n \"firebrick\": [178,34,34,1], \"floralwhite\": [255,250,240,1],\n \"forestgreen\": [34,139,34,1], \"fuchsia\": [255,0,255,1],\n \"gainsboro\": [220,220,220,1], \"ghostwhite\": [248,248,255,1],\n \"gold\": [255,215,0,1], \"goldenrod\": [218,165,32,1],\n \"gray\": [128,128,128,1], \"green\": [0,128,0,1],\n \"greenyellow\": [173,255,47,1], \"grey\": [128,128,128,1],\n \"honeydew\": [240,255,240,1], \"hotpink\": [255,105,180,1],\n \"indianred\": [205,92,92,1], \"indigo\": [75,0,130,1],\n \"ivory\": [255,255,240,1], \"khaki\": [240,230,140,1],\n \"lavender\": [230,230,250,1], \"lavenderblush\": [255,240,245,1],\n \"lawngreen\": [124,252,0,1], \"lemonchiffon\": [255,250,205,1],\n \"lightblue\": [173,216,230,1], \"lightcoral\": [240,128,128,1],\n \"lightcyan\": [224,255,255,1], \"lightgoldenrodyellow\": [250,250,210,1],\n \"lightgray\": [211,211,211,1], \"lightgreen\": [144,238,144,1],\n \"lightgrey\": [211,211,211,1], \"lightpink\": [255,182,193,1],\n \"lightsalmon\": [255,160,122,1], \"lightseagreen\": [32,178,170,1],\n \"lightskyblue\": [135,206,250,1], \"lightslategray\": [119,136,153,1],\n \"lightslategrey\": [119,136,153,1], \"lightsteelblue\": [176,196,222,1],\n \"lightyellow\": [255,255,224,1], \"lime\": [0,255,0,1],\n \"limegreen\": [50,205,50,1], \"linen\": [250,240,230,1],\n \"magenta\": [255,0,255,1], \"maroon\": [128,0,0,1],\n \"mediumaquamarine\": [102,205,170,1], \"mediumblue\": [0,0,205,1],\n \"mediumorchid\": [186,85,211,1], \"mediumpurple\": [147,112,219,1],\n \"mediumseagreen\": [60,179,113,1], \"mediumslateblue\": [123,104,238,1],\n \"mediumspringgreen\": [0,250,154,1], \"mediumturquoise\": [72,209,204,1],\n \"mediumvioletred\": [199,21,133,1], \"midnightblue\": [25,25,112,1],\n \"mintcream\": [245,255,250,1], \"mistyrose\": [255,228,225,1],\n \"moccasin\": [255,228,181,1], \"navajowhite\": [255,222,173,1],\n \"navy\": [0,0,128,1], \"oldlace\": [253,245,230,1],\n \"olive\": [128,128,0,1], \"olivedrab\": [107,142,35,1],\n \"orange\": [255,165,0,1], \"orangered\": [255,69,0,1],\n \"orchid\": [218,112,214,1], \"palegoldenrod\": [238,232,170,1],\n \"palegreen\": [152,251,152,1], \"paleturquoise\": [175,238,238,1],\n \"palevioletred\": [219,112,147,1], \"papayawhip\": [255,239,213,1],\n \"peachpuff\": [255,218,185,1], \"peru\": [205,133,63,1],\n \"pink\": [255,192,203,1], \"plum\": [221,160,221,1],\n \"powderblue\": [176,224,230,1], \"purple\": [128,0,128,1],\n \"red\": [255,0,0,1], \"rosybrown\": [188,143,143,1],\n \"royalblue\": [65,105,225,1], \"saddlebrown\": [139,69,19,1],\n \"salmon\": [250,128,114,1], \"sandybrown\": [244,164,96,1],\n \"seagreen\": [46,139,87,1], \"seashell\": [255,245,238,1],\n \"sienna\": [160,82,45,1], \"silver\": [192,192,192,1],\n \"skyblue\": [135,206,235,1], \"slateblue\": [106,90,205,1],\n \"slategray\": [112,128,144,1], \"slategrey\": [112,128,144,1],\n \"snow\": [255,250,250,1], \"springgreen\": [0,255,127,1],\n \"steelblue\": [70,130,180,1], \"tan\": [210,180,140,1],\n \"teal\": [0,128,128,1], \"thistle\": [216,191,216,1],\n \"tomato\": [255,99,71,1], \"turquoise\": [64,224,208,1],\n \"violet\": [238,130,238,1], \"wheat\": [245,222,179,1],\n \"white\": [255,255,255,1], \"whitesmoke\": [245,245,245,1],\n \"yellow\": [255,255,0,1], \"yellowgreen\": [154,205,50,1]}\n\nfunction clamp_css_byte(i) { // Clamp to integer 0 .. 255.\n i = Math.round(i); // Seems to be what Chrome does (vs truncation).\n return i < 0 ? 0 : i > 255 ? 255 : i;\n}\n\nfunction clamp_css_float(f) { // Clamp to float 0.0 .. 1.0.\n return f < 0 ? 0 : f > 1 ? 1 : f;\n}\n\nfunction parse_css_int(str) { // int or percentage.\n if (str[str.length - 1] === '%')\n return clamp_css_byte(parseFloat(str) / 100 * 255);\n return clamp_css_byte(parseInt(str));\n}\n\nfunction parse_css_float(str) { // float or percentage.\n if (str[str.length - 1] === '%')\n return clamp_css_float(parseFloat(str) / 100);\n return clamp_css_float(parseFloat(str));\n}\n\nfunction css_hue_to_rgb(m1, m2, h) {\n if (h < 0) h += 1;\n else if (h > 1) h -= 1;\n\n if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;\n if (h * 2 < 1) return m2;\n if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6;\n return m1;\n}\n\nfunction parseCSSColor(css_str) {\n // Remove all whitespace, not compliant, but should just be more accepting.\n var str = css_str.replace(/ /g, '').toLowerCase();\n\n // Color keywords (and transparent) lookup.\n if (str in kCSSColorTable) return kCSSColorTable[str].slice(); // dup.\n\n // #abc and #abc123 syntax.\n if (str[0] === '#') {\n if (str.length === 4) {\n var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.\n if (!(iv >= 0 && iv <= 0xfff)) return null; // Covers NaN.\n return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),\n (iv & 0xf0) | ((iv & 0xf0) >> 4),\n (iv & 0xf) | ((iv & 0xf) << 4),\n 1];\n } else if (str.length === 7) {\n var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.\n if (!(iv >= 0 && iv <= 0xffffff)) return null; // Covers NaN.\n return [(iv & 0xff0000) >> 16,\n (iv & 0xff00) >> 8,\n iv & 0xff,\n 1];\n }\n\n return null;\n }\n\n var op = str.indexOf('('), ep = str.indexOf(')');\n if (op !== -1 && ep + 1 === str.length) {\n var fname = str.substr(0, op);\n var params = str.substr(op+1, ep-(op+1)).split(',');\n var alpha = 1; // To allow case fallthrough.\n switch (fname) {\n case 'rgba':\n if (params.length !== 4) return null;\n alpha = parse_css_float(params.pop());\n // Fall through.\n case 'rgb':\n if (params.length !== 3) return null;\n return [parse_css_int(params[0]),\n parse_css_int(params[1]),\n parse_css_int(params[2]),\n alpha];\n case 'hsla':\n if (params.length !== 4) return null;\n alpha = parse_css_float(params.pop());\n // Fall through.\n case 'hsl':\n if (params.length !== 3) return null;\n var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360; // 0 .. 1\n // NOTE(deanm): According to the CSS spec s/l should only be\n // percentages, but we don't bother and let float or percentage.\n var s = parse_css_float(params[1]);\n var l = parse_css_float(params[2]);\n var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;\n var m1 = l * 2 - m2;\n return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255),\n clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255),\n clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255),\n alpha];\n default:\n return null;\n }\n }\n\n return null;\n}\n\ntry { exports.parseCSSColor = parseCSSColor } catch(e) { }\n", "title": "$:/core/modules/utils/dom/csscolorparser.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/dom.js": { "text": "/*\\\ntitle: $:/core/modules/utils/dom.js\ntype: application/javascript\nmodule-type: utils\n\nVarious static DOM-related utility functions.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nDetermines whether element 'a' contains element 'b'\nCode thanks to John Resig, http://ejohn.org/blog/comparing-document-position/\n*/\nexports.domContains = function(a,b) {\n\treturn a.contains ?\n\t\ta !== b && a.contains(b) :\n\t\t!!(a.compareDocumentPosition(b) & 16);\n};\n\nexports.removeChildren = function(node) {\n\twhile(node.hasChildNodes()) {\n\t\tnode.removeChild(node.firstChild);\n\t}\n};\n\nexports.hasClass = function(el,className) {\n\treturn el && el.className && el.className.toString().split(\" \").indexOf(className) !== -1;\n};\n\nexports.addClass = function(el,className) {\n\tvar c = el.className.split(\" \");\n\tif(c.indexOf(className) === -1) {\n\t\tc.push(className);\n\t}\n\tel.className = c.join(\" \");\n};\n\nexports.removeClass = function(el,className) {\n\tvar c = el.className.split(\" \"),\n\t\tp = c.indexOf(className);\n\tif(p !== -1) {\n\t\tc.splice(p,1);\n\t\tel.className = c.join(\" \");\n\t}\n};\n\nexports.toggleClass = function(el,className,status) {\n\tif(status === undefined) {\n\t\tstatus = !exports.hasClass(el,className);\n\t}\n\tif(status) {\n\t\texports.addClass(el,className);\n\t} else {\n\t\texports.removeClass(el,className);\n\t}\n};\n\n/*\nGet the first parent element that has scrollbars or use the body as fallback.\n*/\nexports.getScrollContainer = function(el) {\n\tvar doc = el.ownerDocument;\n\twhile(el.parentNode) {\t\n\t\tel = el.parentNode;\n\t\tif(el.scrollTop) {\n\t\t\treturn el;\n\t\t}\n\t}\n\treturn doc.body;\n};\n\n/*\nGet the scroll position of the viewport\nReturns:\n\t{\n\t\tx: horizontal scroll position in pixels,\n\t\ty: vertical scroll position in pixels\n\t}\n*/\nexports.getScrollPosition = function() {\n\tif(\"scrollX\" in window) {\n\t\treturn {x: window.scrollX, y: window.scrollY};\n\t} else {\n\t\treturn {x: document.documentElement.scrollLeft, y: document.documentElement.scrollTop};\n\t}\n};\n\n/*\nAdjust the height of a textarea to fit its content, preserving scroll position, and return the height\n*/\nexports.resizeTextAreaToFit = function(domNode,minHeight) {\n\t// Get the scroll container and register the current scroll position\n\tvar container = $tw.utils.getScrollContainer(domNode),\n\t\tscrollTop = container.scrollTop;\n // Measure the specified minimum height\n\tdomNode.style.height = minHeight;\n\tvar measuredHeight = domNode.offsetHeight;\n\t// Set its height to auto so that it snaps to the correct height\n\tdomNode.style.height = \"auto\";\n\t// Calculate the revised height\n\tvar newHeight = Math.max(domNode.scrollHeight + domNode.offsetHeight - domNode.clientHeight,measuredHeight);\n\t// Only try to change the height if it has changed\n\tif(newHeight !== domNode.offsetHeight) {\n\t\tdomNode.style.height = newHeight + \"px\";\n\t\t// Make sure that the dimensions of the textarea are recalculated\n\t\t$tw.utils.forceLayout(domNode);\n\t\t// Set the container to the position we registered at the beginning\n\t\tcontainer.scrollTop = scrollTop;\n\t}\n\treturn newHeight;\n};\n\n/*\nGets the bounding rectangle of an element in absolute page coordinates\n*/\nexports.getBoundingPageRect = function(element) {\n\tvar scrollPos = $tw.utils.getScrollPosition(),\n\t\tclientRect = element.getBoundingClientRect();\n\treturn {\n\t\tleft: clientRect.left + scrollPos.x,\n\t\twidth: clientRect.width,\n\t\tright: clientRect.right + scrollPos.x,\n\t\ttop: clientRect.top + scrollPos.y,\n\t\theight: clientRect.height,\n\t\tbottom: clientRect.bottom + scrollPos.y\n\t};\n};\n\n/*\nSaves a named password in the browser\n*/\nexports.savePassword = function(name,password) {\n\ttry {\n\t\tif(window.localStorage) {\n\t\t\tlocalStorage.setItem(\"tw5-password-\" + name,password);\n\t\t}\n\t} catch(e) {\n\t}\n};\n\n/*\nRetrieve a named password from the browser\n*/\nexports.getPassword = function(name) {\n\ttry {\n\t\treturn window.localStorage ? localStorage.getItem(\"tw5-password-\" + name) : \"\";\n\t} catch(e) {\n\t\treturn \"\";\n\t}\n};\n\n/*\nForce layout of a dom node and its descendents\n*/\nexports.forceLayout = function(element) {\n\tvar dummy = element.offsetWidth;\n};\n\n/*\nPulse an element for debugging purposes\n*/\nexports.pulseElement = function(element) {\n\t// Event handler to remove the class at the end\n\telement.addEventListener($tw.browser.animationEnd,function handler(event) {\n\t\telement.removeEventListener($tw.browser.animationEnd,handler,false);\n\t\t$tw.utils.removeClass(element,\"pulse\");\n\t},false);\n\t// Apply the pulse class\n\t$tw.utils.removeClass(element,\"pulse\");\n\t$tw.utils.forceLayout(element);\n\t$tw.utils.addClass(element,\"pulse\");\n};\n\n/*\nAttach specified event handlers to a DOM node\ndomNode: where to attach the event handlers\nevents: array of event handlers to be added (see below)\nEach entry in the events array is an object with these properties:\nhandlerFunction: optional event handler function\nhandlerObject: optional event handler object\nhandlerMethod: optionally specifies object handler method name (defaults to `handleEvent`)\n*/\nexports.addEventListeners = function(domNode,events) {\n\t$tw.utils.each(events,function(eventInfo) {\n\t\tvar handler;\n\t\tif(eventInfo.handlerFunction) {\n\t\t\thandler = eventInfo.handlerFunction;\n\t\t} else if(eventInfo.handlerObject) {\n\t\t\tif(eventInfo.handlerMethod) {\n\t\t\t\thandler = function(event) {\n\t\t\t\t\teventInfo.handlerObject[eventInfo.handlerMethod].call(eventInfo.handlerObject,event);\n\t\t\t\t};\t\n\t\t\t} else {\n\t\t\t\thandler = eventInfo.handlerObject;\n\t\t\t}\n\t\t}\n\t\tdomNode.addEventListener(eventInfo.name,handler,false);\n\t});\n};\n\n/*\nGet the computed styles applied to an element as an array of strings of individual CSS properties\n*/\nexports.getComputedStyles = function(domNode) {\n\tvar textAreaStyles = window.getComputedStyle(domNode,null),\n\t\tstyleDefs = [],\n\t\tname;\n\tfor(var t=0; t<textAreaStyles.length; t++) {\n\t\tname = textAreaStyles[t];\n\t\tstyleDefs.push(name + \": \" + textAreaStyles.getPropertyValue(name) + \";\");\n\t}\n\treturn styleDefs;\n};\n\n/*\nApply a set of styles passed as an array of strings of individual CSS properties\n*/\nexports.setStyles = function(domNode,styleDefs) {\n\tdomNode.style.cssText = styleDefs.join(\"\");\n};\n\n/*\nCopy the computed styles from a source element to a destination element\n*/\nexports.copyStyles = function(srcDomNode,dstDomNode) {\n\t$tw.utils.setStyles(dstDomNode,$tw.utils.getComputedStyles(srcDomNode));\n};\n\n})();\n", "title": "$:/core/modules/utils/dom.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/dom/dragndrop.js": { "text": "/*\\\ntitle: $:/core/modules/utils/dom/dragndrop.js\ntype: application/javascript\nmodule-type: utils\n\nBrowser data transfer utilities, used with the clipboard and drag and drop\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nOptions:\n\ndomNode: dom node to make draggable\ndragImageType: \"pill\" or \"dom\"\ndragTiddlerFn: optional function to retrieve the title of tiddler to drag\ndragFilterFn: optional function to retreive the filter defining a list of tiddlers to drag\nwidget: widget to use as the contect for the filter\n*/\nexports.makeDraggable = function(options) {\n\tvar dragImageType = options.dragImageType || \"dom\",\n\t\tdragImage,\n\t\tdomNode = options.domNode;\n\t// Make the dom node draggable (not necessary for anchor tags)\n\tif((domNode.tagName || \"\").toLowerCase() !== \"a\") {\n\t\tdomNode.setAttribute(\"draggable\",\"true\");\t\t\n\t}\n\t// Add event handlers\n\t$tw.utils.addEventListeners(domNode,[\n\t\t{name: \"dragstart\", handlerFunction: function(event) {\n\t\t\t// Collect the tiddlers being dragged\n\t\t\tvar dragTiddler = options.dragTiddlerFn && options.dragTiddlerFn(),\n\t\t\t\tdragFilter = options.dragFilterFn && options.dragFilterFn(),\n\t\t\t\ttitles = dragTiddler ? [dragTiddler] : [];\n\t\t\tif(dragFilter) {\n\t\t\t\ttitles.push.apply(titles,options.widget.wiki.filterTiddlers(dragFilter,options.widget));\n\t\t\t}\n\t\t\tvar titleString = $tw.utils.stringifyList(titles);\n\t\t\t// Check that we've something to drag\n\t\t\tif(titles.length > 0 && event.target === domNode) {\n\t\t\t\t// Mark the drag in progress\n\t\t\t\t$tw.dragInProgress = domNode;\n\t\t\t\t// Set the dragging class on the element being dragged\n\t\t\t\t$tw.utils.addClass(event.target,\"tc-dragging\");\n\t\t\t\t// Create the drag image elements\n\t\t\t\tdragImage = options.widget.document.createElement(\"div\");\n\t\t\t\tdragImage.className = \"tc-tiddler-dragger\";\n\t\t\t\tvar inner = options.widget.document.createElement(\"div\");\n\t\t\t\tinner.className = \"tc-tiddler-dragger-inner\";\n\t\t\t\tinner.appendChild(options.widget.document.createTextNode(\n\t\t\t\t\ttitles.length === 1 ? \n\t\t\t\t\t\ttitles[0] :\n\t\t\t\t\t\ttitles.length + \" tiddlers\"\n\t\t\t\t));\n\t\t\t\tdragImage.appendChild(inner);\n\t\t\t\toptions.widget.document.body.appendChild(dragImage);\n\t\t\t\t// Set the data transfer properties\n\t\t\t\tvar dataTransfer = event.dataTransfer;\n\t\t\t\t// Set up the image\n\t\t\t\tdataTransfer.effectAllowed = \"all\";\n\t\t\t\tif(dataTransfer.setDragImage) {\n\t\t\t\t\tif(dragImageType === \"pill\") {\n\t\t\t\t\t\tdataTransfer.setDragImage(dragImage.firstChild,-16,-16);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar r = domNode.getBoundingClientRect();\n\t\t\t\t\t\tdataTransfer.setDragImage(domNode,event.clientX-r.left,event.clientY-r.top);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Set up the data transfer\n\t\t\t\tif(dataTransfer.clearData) {\n\t\t\t\t\tdataTransfer.clearData();\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\tvar jsonData = [];\n\t\t\t\tif(titles.length > 1) {\n\t\t\t\t\ttitles.forEach(function(title) {\n\t\t\t\t\t\tjsonData.push(options.widget.wiki.getTiddlerAsJson(title));\n\t\t\t\t\t});\n\t\t\t\t\tjsonData = \"[\" + jsonData.join(\",\") + \"]\";\n\t\t\t\t} else {\n\t\t\t\t\tjsonData = options.widget.wiki.getTiddlerAsJson(titles[0]);\n\t\t\t\t}\n\t\t\t\t// IE doesn't like these content types\n\t\t\t\tif(!$tw.browser.isIE) {\n\t\t\t\t\tdataTransfer.setData(\"text/vnd.tiddler\",jsonData);\n\t\t\t\t\tdataTransfer.setData(\"text/plain\",titleString);\n\t\t\t\t\tdataTransfer.setData(\"text/x-moz-url\",\"data:text/vnd.tiddler,\" + encodeURIComponent(jsonData));\n\t\t\t\t}\n\t\t\t\tdataTransfer.setData(\"URL\",\"data:text/vnd.tiddler,\" + encodeURIComponent(jsonData));\n\t\t\t\tdataTransfer.setData(\"Text\",titleString);\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\t\t\treturn false;\n\t\t}},\n\t\t{name: \"dragend\", handlerFunction: function(event) {\n\t\t\tif(event.target === domNode) {\n\t\t\t\t$tw.dragInProgress = null;\n\t\t\t\t// Remove the dragging class on the element being dragged\n\t\t\t\t$tw.utils.removeClass(event.target,\"tc-dragging\");\n\t\t\t\t// Delete the drag image element\n\t\t\t\tif(dragImage) {\n\t\t\t\t\tdragImage.parentNode.removeChild(dragImage);\n\t\t\t\t\tdragImage = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}}\n\t]);\n};\n\nexports.importDataTransfer = function(dataTransfer,fallbackTitle,callback) {\n\t// Try each provided data type in turn\n\tfor(var t=0; t<importDataTypes.length; t++) {\n\t\tif(!$tw.browser.isIE || importDataTypes[t].IECompatible) {\n\t\t\t// Get the data\n\t\t\tvar dataType = importDataTypes[t];\n\t\t\t\tvar data = dataTransfer.getData(dataType.type);\n\t\t\t// Import the tiddlers in the data\n\t\t\tif(data !== \"\" && data !== null) {\n\t\t\t\tif($tw.log.IMPORT) {\n\t\t\t\t\tconsole.log(\"Importing data type '\" + dataType.type + \"', data: '\" + data + \"'\")\n\t\t\t\t}\n\t\t\t\tvar tiddlerFields = dataType.toTiddlerFieldsArray(data,fallbackTitle);\n\t\t\t\tcallback(tiddlerFields);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar importDataTypes = [\n\t{type: \"text/vnd.tiddler\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn parseJSONTiddlers(data,fallbackTitle);\n\t}},\n\t{type: \"URL\", IECompatible: true, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\t// Check for tiddler data URI\n\t\tvar match = decodeURIComponent(data).match(/^data\\:text\\/vnd\\.tiddler,(.*)/i);\n\t\tif(match) {\n\t\t\treturn parseJSONTiddlers(match[1],fallbackTitle);\n\t\t} else {\n\t\t\treturn [{title: fallbackTitle, text: data}]; // As URL string\n\t\t}\n\t}},\n\t{type: \"text/x-moz-url\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\t// Check for tiddler data URI\n\t\tvar match = decodeURIComponent(data).match(/^data\\:text\\/vnd\\.tiddler,(.*)/i);\n\t\tif(match) {\n\t\t\treturn parseJSONTiddlers(match[1],fallbackTitle);\n\t\t} else {\n\t\t\treturn [{title: fallbackTitle, text: data}]; // As URL string\n\t\t}\n\t}},\n\t{type: \"text/html\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}},\n\t{type: \"text/plain\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}},\n\t{type: \"Text\", IECompatible: true, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}},\n\t{type: \"text/uri-list\", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {\n\t\treturn [{title: fallbackTitle, text: data}];\n\t}}\n];\n\nfunction parseJSONTiddlers(json,fallbackTitle) {\n\tvar data = JSON.parse(json);\n\tif(!$tw.utils.isArray(data)) {\n\t\tdata = [data];\n\t}\n\tdata.forEach(function(fields) {\n\t\tfields.title = fields.title || fallbackTitle;\n\t});\n\treturn data;\n};\n\n})();\n", "title": "$:/core/modules/utils/dom/dragndrop.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/dom/http.js": { "text": "/*\\\ntitle: $:/core/modules/utils/dom/http.js\ntype: application/javascript\nmodule-type: utils\n\nBrowser HTTP support\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nA quick and dirty HTTP function; to be refactored later. Options are:\n\turl: URL to retrieve\n\ttype: GET, PUT, POST etc\n\tcallback: function invoked with (err,data)\n\treturnProp: string name of the property to return as first argument of callback\n*/\nexports.httpRequest = function(options) {\n\tvar type = options.type || \"GET\",\n\t\theaders = options.headers || {accept: \"application/json\"},\n\t\treturnProp = options.returnProp || \"responseText\",\n\t\trequest = new XMLHttpRequest(),\n\t\tdata = \"\",\n\t\tf,results;\n\t// Massage the data hashmap into a string\n\tif(options.data) {\n\t\tif(typeof options.data === \"string\") { // Already a string\n\t\t\tdata = options.data;\n\t\t} else { // A hashmap of strings\n\t\t\tresults = [];\n\t\t\t$tw.utils.each(options.data,function(dataItem,dataItemTitle) {\n\t\t\t\tresults.push(dataItemTitle + \"=\" + encodeURIComponent(dataItem));\n\t\t\t});\n\t\t\tdata = results.join(\"&\");\n\t\t}\n\t}\n\t// Set up the state change handler\n\trequest.onreadystatechange = function() {\n\t\tif(this.readyState === 4) {\n\t\t\tif(this.status === 200 || this.status === 201 || this.status === 204) {\n\t\t\t\t// Success!\n\t\t\t\toptions.callback(null,this[returnProp],this);\n\t\t\t\treturn;\n\t\t\t}\n\t\t// Something went wrong\n\t\toptions.callback($tw.language.getString(\"Error/XMLHttpRequest\") + \": \" + this.status);\n\t\t}\n\t};\n\t// Make the request\n\trequest.open(type,options.url,true);\n\tif(headers) {\n\t\t$tw.utils.each(headers,function(header,headerTitle,object) {\n\t\t\trequest.setRequestHeader(headerTitle,header);\n\t\t});\n\t}\n\tif(data && !$tw.utils.hop(headers,\"Content-type\")) {\n\t\trequest.setRequestHeader(\"Content-type\",\"application/x-www-form-urlencoded; charset=UTF-8\");\n\t}\n\ttry {\n\t\trequest.send(data);\n\t} catch(e) {\n\t\toptions.callback(e);\n\t}\n\treturn request;\n};\n\n})();\n", "title": "$:/core/modules/utils/dom/http.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/dom/keyboard.js": { "text": "/*\\\ntitle: $:/core/modules/utils/dom/keyboard.js\ntype: application/javascript\nmodule-type: utils\n\nKeyboard utilities; now deprecated. Instead, use $tw.keyboardManager\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n[\"parseKeyDescriptor\",\"checkKeyDescriptor\"].forEach(function(method) {\n\texports[method] = function() {\n\t\tif($tw.keyboardManager) {\n\t\t\treturn $tw.keyboardManager[method].apply($tw.keyboardManager,Array.prototype.slice.call(arguments,0));\n\t\t} else {\n\t\t\treturn null\n\t\t}\n\t};\n});\n\n})();\n", "title": "$:/core/modules/utils/dom/keyboard.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/dom/modal.js": { "text": "/*\\\ntitle: $:/core/modules/utils/dom/modal.js\ntype: application/javascript\nmodule-type: utils\n\nModal message mechanism\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nvar Modal = function(wiki) {\n\tthis.wiki = wiki;\n\tthis.modalCount = 0;\n};\n\n/*\nDisplay a modal dialogue\n\ttitle: Title of tiddler to display\n\toptions: see below\nOptions include:\n\tdownloadLink: Text of a big download link to include\n*/\nModal.prototype.display = function(title,options) {\n\toptions = options || {};\n\tvar self = this,\n\t\trefreshHandler,\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\ttiddler = this.wiki.getTiddler(title);\n\t// Don't do anything if the tiddler doesn't exist\n\tif(!tiddler) {\n\t\treturn;\n\t}\n\t// Create the variables\n\tvar variables = $tw.utils.extend({currentTiddler: title},options.variables);\n\t// Create the wrapper divs\n\tvar wrapper = document.createElement(\"div\"),\n\t\tmodalBackdrop = document.createElement(\"div\"),\n\t\tmodalWrapper = document.createElement(\"div\"),\n\t\tmodalHeader = document.createElement(\"div\"),\n\t\theaderTitle = document.createElement(\"h3\"),\n\t\tmodalBody = document.createElement(\"div\"),\n\t\tmodalLink = document.createElement(\"a\"),\n\t\tmodalFooter = document.createElement(\"div\"),\n\t\tmodalFooterHelp = document.createElement(\"span\"),\n\t\tmodalFooterButtons = document.createElement(\"span\");\n\t// Up the modal count and adjust the body class\n\tthis.modalCount++;\n\tthis.adjustPageClass();\n\t// Add classes\n\t$tw.utils.addClass(wrapper,\"tc-modal-wrapper\");\n\t$tw.utils.addClass(modalBackdrop,\"tc-modal-backdrop\");\n\t$tw.utils.addClass(modalWrapper,\"tc-modal\");\n\t$tw.utils.addClass(modalHeader,\"tc-modal-header\");\n\t$tw.utils.addClass(modalBody,\"tc-modal-body\");\n\t$tw.utils.addClass(modalFooter,\"tc-modal-footer\");\n\t// Join them together\n\twrapper.appendChild(modalBackdrop);\n\twrapper.appendChild(modalWrapper);\n\tmodalHeader.appendChild(headerTitle);\n\tmodalWrapper.appendChild(modalHeader);\n\tmodalWrapper.appendChild(modalBody);\n\tmodalFooter.appendChild(modalFooterHelp);\n\tmodalFooter.appendChild(modalFooterButtons);\n\tmodalWrapper.appendChild(modalFooter);\n\t// Render the title of the message\n\tvar headerWidgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tfield: \"subtitle\",\n\t\tmode: \"inline\",\n\t\tchildren: [{\n\t\t\ttype: \"text\",\n\t\t\tattributes: {\n\t\t\t\ttext: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalue: title\n\t\t}}}],\n\t\tparentWidget: $tw.rootWidget,\n\t\tdocument: document,\n\t\tvariables: variables,\n\t\timportPageMacros: true\n\t});\n\theaderWidgetNode.render(headerTitle,null);\n\t// Render the body of the message\n\tvar bodyWidgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tparentWidget: $tw.rootWidget,\n\t\tdocument: document,\n\t\tvariables: variables,\n\t\timportPageMacros: true\n\t});\n\tbodyWidgetNode.render(modalBody,null);\n\t// Setup the link if present\n\tif(options.downloadLink) {\n\t\tmodalLink.href = options.downloadLink;\n\t\tmodalLink.appendChild(document.createTextNode(\"Right-click to save changes\"));\n\t\tmodalBody.appendChild(modalLink);\n\t}\n\t// Render the footer of the message\n\tif(tiddler && tiddler.fields && tiddler.fields.help) {\n\t\tvar link = document.createElement(\"a\");\n\t\tlink.setAttribute(\"href\",tiddler.fields.help);\n\t\tlink.setAttribute(\"target\",\"_blank\");\n\t\tlink.setAttribute(\"rel\",\"noopener noreferrer\");\n\t\tlink.appendChild(document.createTextNode(\"Help\"));\n\t\tmodalFooterHelp.appendChild(link);\n\t\tmodalFooterHelp.style.float = \"left\";\n\t}\n\tvar footerWidgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tfield: \"footer\",\n\t\tmode: \"inline\",\n\t\tchildren: [{\n\t\t\ttype: \"button\",\n\t\t\tattributes: {\n\t\t\t\tmessage: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalue: \"tm-close-tiddler\"\n\t\t\t\t}\n\t\t\t},\n\t\t\tchildren: [{\n\t\t\t\ttype: \"text\",\n\t\t\t\tattributes: {\n\t\t\t\t\ttext: {\n\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\tvalue: $tw.language.getString(\"Buttons/Close/Caption\")\n\t\t\t}}}\n\t\t]}],\n\t\tparentWidget: $tw.rootWidget,\n\t\tdocument: document,\n\t\tvariables: variables,\n\t\timportPageMacros: true\n\t});\n\tfooterWidgetNode.render(modalFooterButtons,null);\n\t// Set up the refresh handler\n\trefreshHandler = function(changes) {\n\t\theaderWidgetNode.refresh(changes,modalHeader,null);\n\t\tbodyWidgetNode.refresh(changes,modalBody,null);\n\t\tfooterWidgetNode.refresh(changes,modalFooterButtons,null);\n\t};\n\tthis.wiki.addEventListener(\"change\",refreshHandler);\n\t// Add the close event handler\n\tvar closeHandler = function(event) {\n\t\t// Remove our refresh handler\n\t\tself.wiki.removeEventListener(\"change\",refreshHandler);\n\t\t// Decrease the modal count and adjust the body class\n\t\tself.modalCount--;\n\t\tself.adjustPageClass();\n\t\t// Force layout and animate the modal message away\n\t\t$tw.utils.forceLayout(modalBackdrop);\n\t\t$tw.utils.forceLayout(modalWrapper);\n\t\t$tw.utils.setStyle(modalBackdrop,[\n\t\t\t{opacity: \"0\"}\n\t\t]);\n\t\t$tw.utils.setStyle(modalWrapper,[\n\t\t\t{transform: \"translateY(\" + window.innerHeight + \"px)\"}\n\t\t]);\n\t\t// Set up an event for the transition end\n\t\twindow.setTimeout(function() {\n\t\t\tif(wrapper.parentNode) {\n\t\t\t\t// Remove the modal message from the DOM\n\t\t\t\tdocument.body.removeChild(wrapper);\n\t\t\t}\n\t\t},duration);\n\t\t// Don't let anyone else handle the tm-close-tiddler message\n\t\treturn false;\n\t};\n\theaderWidgetNode.addEventListener(\"tm-close-tiddler\",closeHandler,false);\n\tbodyWidgetNode.addEventListener(\"tm-close-tiddler\",closeHandler,false);\n\tfooterWidgetNode.addEventListener(\"tm-close-tiddler\",closeHandler,false);\n\t// Set the initial styles for the message\n\t$tw.utils.setStyle(modalBackdrop,[\n\t\t{opacity: \"0\"}\n\t]);\n\t$tw.utils.setStyle(modalWrapper,[\n\t\t{transformOrigin: \"0% 0%\"},\n\t\t{transform: \"translateY(\" + (-window.innerHeight) + \"px)\"}\n\t]);\n\t// Put the message into the document\n\tdocument.body.appendChild(wrapper);\n\t// Set up animation for the styles\n\t$tw.utils.setStyle(modalBackdrop,[\n\t\t{transition: \"opacity \" + duration + \"ms ease-out\"}\n\t]);\n\t$tw.utils.setStyle(modalWrapper,[\n\t\t{transition: $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out\"}\n\t]);\n\t// Force layout\n\t$tw.utils.forceLayout(modalBackdrop);\n\t$tw.utils.forceLayout(modalWrapper);\n\t// Set final animated styles\n\t$tw.utils.setStyle(modalBackdrop,[\n\t\t{opacity: \"0.7\"}\n\t]);\n\t$tw.utils.setStyle(modalWrapper,[\n\t\t{transform: \"translateY(0px)\"}\n\t]);\n};\n\nModal.prototype.adjustPageClass = function() {\n\tif($tw.pageContainer) {\n\t\t$tw.utils.toggleClass($tw.pageContainer,\"tc-modal-displayed\",this.modalCount > 0);\n\t}\n};\n\nexports.Modal = Modal;\n\n})();\n", "title": "$:/core/modules/utils/dom/modal.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/dom/notifier.js": { "text": "/*\\\ntitle: $:/core/modules/utils/dom/notifier.js\ntype: application/javascript\nmodule-type: utils\n\nNotifier mechanism\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nvar Notifier = function(wiki) {\n\tthis.wiki = wiki;\n};\n\n/*\nDisplay a notification\n\ttitle: Title of tiddler containing the notification text\n\toptions: see below\nOptions include:\n*/\nNotifier.prototype.display = function(title,options) {\n\toptions = options || {};\n\t// Create the wrapper divs\n\tvar self = this,\n\t\tnotification = document.createElement(\"div\"),\n\t\ttiddler = this.wiki.getTiddler(title),\n\t\tduration = $tw.utils.getAnimationDuration(),\n\t\trefreshHandler;\n\t// Don't do anything if the tiddler doesn't exist\n\tif(!tiddler) {\n\t\treturn;\n\t}\n\t// Add classes\n\t$tw.utils.addClass(notification,\"tc-notification\");\n\t// Create the variables\n\tvar variables = $tw.utils.extend({currentTiddler: title},options.variables);\n\t// Render the body of the notification\n\tvar widgetNode = this.wiki.makeTranscludeWidget(title,{\n\t\tparentWidget: $tw.rootWidget,\n\t\tdocument: document,\n\t\tvariables: variables,\n\t\timportPageMacros: true});\n\twidgetNode.render(notification,null);\n\trefreshHandler = function(changes) {\n\t\twidgetNode.refresh(changes,notification,null);\n\t};\n\tthis.wiki.addEventListener(\"change\",refreshHandler);\n\t// Set the initial styles for the notification\n\t$tw.utils.setStyle(notification,[\n\t\t{opacity: \"0\"},\n\t\t{transformOrigin: \"0% 0%\"},\n\t\t{transform: \"translateY(\" + (-window.innerHeight) + \"px)\"},\n\t\t{transition: \"opacity \" + duration + \"ms ease-out, \" + $tw.utils.roundTripPropertyName(\"transform\") + \" \" + duration + \"ms ease-in-out\"}\n\t]);\n\t// Add the notification to the DOM\n\tdocument.body.appendChild(notification);\n\t// Force layout\n\t$tw.utils.forceLayout(notification);\n\t// Set final animated styles\n\t$tw.utils.setStyle(notification,[\n\t\t{opacity: \"1.0\"},\n\t\t{transform: \"translateY(0px)\"}\n\t]);\n\t// Set a timer to remove the notification\n\twindow.setTimeout(function() {\n\t\t// Remove our change event handler\n\t\tself.wiki.removeEventListener(\"change\",refreshHandler);\n\t\t// Force layout and animate the notification away\n\t\t$tw.utils.forceLayout(notification);\n\t\t$tw.utils.setStyle(notification,[\n\t\t\t{opacity: \"0.0\"},\n\t\t\t{transform: \"translateX(\" + (notification.offsetWidth) + \"px)\"}\n\t\t]);\n\t\t// Remove the modal message from the DOM once the transition ends\n\t\tsetTimeout(function() {\n\t\t\tif(notification.parentNode) {\n\t\t\t\tdocument.body.removeChild(notification);\n\t\t\t}\n\t\t},duration);\n\t},$tw.config.preferences.notificationDuration);\n};\n\nexports.Notifier = Notifier;\n\n})();\n", "title": "$:/core/modules/utils/dom/notifier.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/dom/popup.js": { "text": "/*\\\ntitle: $:/core/modules/utils/dom/popup.js\ntype: application/javascript\nmodule-type: utils\n\nModule that creates a $tw.utils.Popup object prototype that manages popups in the browser\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nCreates a Popup object with these options:\n\trootElement: the DOM element to which the popup zapper should be attached\n*/\nvar Popup = function(options) {\n\toptions = options || {};\n\tthis.rootElement = options.rootElement || document.documentElement;\n\tthis.popups = []; // Array of {title:,wiki:,domNode:} objects\n};\n\n/*\nTrigger a popup open or closed. Parameters are in a hashmap:\n\ttitle: title of the tiddler where the popup details are stored\n\tdomNode: dom node to which the popup will be positioned\n\twiki: wiki\n\tforce: if specified, forces the popup state to true or false (instead of toggling it)\n*/\nPopup.prototype.triggerPopup = function(options) {\n\t// Check if this popup is already active\n\tvar index = this.findPopup(options.title);\n\t// Compute the new state\n\tvar state = index === -1;\n\tif(options.force !== undefined) {\n\t\tstate = options.force;\n\t}\n\t// Show or cancel the popup according to the new state\n\tif(state) {\n\t\tthis.show(options);\n\t} else {\n\t\tthis.cancel(index);\n\t}\n};\n\nPopup.prototype.findPopup = function(title) {\n\tvar index = -1;\n\tfor(var t=0; t<this.popups.length; t++) {\n\t\tif(this.popups[t].title === title) {\n\t\t\tindex = t;\n\t\t}\n\t}\n\treturn index;\n};\n\nPopup.prototype.handleEvent = function(event) {\n\tif(event.type === \"click\") {\n\t\t// Find out what was clicked on\n\t\tvar info = this.popupInfo(event.target),\n\t\t\tcancelLevel = info.popupLevel - 1;\n\t\t// Don't remove the level that was clicked on if we clicked on a handle\n\t\tif(info.isHandle) {\n\t\t\tcancelLevel++;\n\t\t}\n\t\t// Cancel\n\t\tthis.cancel(cancelLevel);\n\t}\n};\n\n/*\nFind the popup level containing a DOM node. Returns:\npopupLevel: count of the number of nested popups containing the specified element\nisHandle: true if the specified element is within a popup handle\n*/\nPopup.prototype.popupInfo = function(domNode) {\n\tvar isHandle = false,\n\t\tpopupCount = 0,\n\t\tnode = domNode;\n\t// First check ancestors to see if we're within a popup handle\n\twhile(node) {\n\t\tif($tw.utils.hasClass(node,\"tc-popup-handle\")) {\n\t\t\tisHandle = true;\n\t\t\tpopupCount++;\n\t\t}\n\t\tif($tw.utils.hasClass(node,\"tc-popup-keep\")) {\n\t\t\tisHandle = true;\n\t\t}\n\t\tnode = node.parentNode;\n\t}\n\t// Then count the number of ancestor popups\n\tnode = domNode;\n\twhile(node) {\n\t\tif($tw.utils.hasClass(node,\"tc-popup\")) {\n\t\t\tpopupCount++;\n\t\t}\n\t\tnode = node.parentNode;\n\t}\n\tvar info = {\n\t\tpopupLevel: popupCount,\n\t\tisHandle: isHandle\n\t};\n\treturn info;\n};\n\n/*\nDisplay a popup by adding it to the stack\n*/\nPopup.prototype.show = function(options) {\n\t// Find out what was clicked on\n\tvar info = this.popupInfo(options.domNode);\n\t// Cancel any higher level popups\n\tthis.cancel(info.popupLevel);\n\t// Store the popup details if not already there\n\tif(this.findPopup(options.title) === -1) {\n\t\tthis.popups.push({\n\t\t\ttitle: options.title,\n\t\t\twiki: options.wiki,\n\t\t\tdomNode: options.domNode\n\t\t});\n\t}\n\t// Set the state tiddler\n\toptions.wiki.setTextReference(options.title,\n\t\t\t\"(\" + options.domNode.offsetLeft + \",\" + options.domNode.offsetTop + \",\" + \n\t\t\t\toptions.domNode.offsetWidth + \",\" + options.domNode.offsetHeight + \")\");\n\t// Add the click handler if we have any popups\n\tif(this.popups.length > 0) {\n\t\tthis.rootElement.addEventListener(\"click\",this,true);\t\t\n\t}\n};\n\n/*\nCancel all popups at or above a specified level or DOM node\nlevel: popup level to cancel (0 cancels all popups)\n*/\nPopup.prototype.cancel = function(level) {\n\tvar numPopups = this.popups.length;\n\tlevel = Math.max(0,Math.min(level,numPopups));\n\tfor(var t=level; t<numPopups; t++) {\n\t\tvar popup = this.popups.pop();\n\t\tif(popup.title) {\n\t\t\tpopup.wiki.deleteTiddler(popup.title);\n\t\t}\n\t}\n\tif(this.popups.length === 0) {\n\t\tthis.rootElement.removeEventListener(\"click\",this,false);\n\t}\n};\n\n/*\nReturns true if the specified title and text identifies an active popup\n*/\nPopup.prototype.readPopupState = function(text) {\n\tvar popupLocationRegExp = /^\\((-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+)\\)$/;\n\treturn popupLocationRegExp.test(text);\n};\n\nexports.Popup = Popup;\n\n})();\n", "title": "$:/core/modules/utils/dom/popup.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/dom/scroller.js": { "text": "/*\\\ntitle: $:/core/modules/utils/dom/scroller.js\ntype: application/javascript\nmodule-type: utils\n\nModule that creates a $tw.utils.Scroller object prototype that manages scrolling in the browser\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nEvent handler for when the `tm-scroll` event hits the document body\n*/\nvar PageScroller = function() {\n\tthis.idRequestFrame = null;\n\tthis.requestAnimationFrame = window.requestAnimationFrame ||\n\t\twindow.webkitRequestAnimationFrame ||\n\t\twindow.mozRequestAnimationFrame ||\n\t\tfunction(callback) {\n\t\t\treturn window.setTimeout(callback, 1000/60);\n\t\t};\n\tthis.cancelAnimationFrame = window.cancelAnimationFrame ||\n\t\twindow.webkitCancelAnimationFrame ||\n\t\twindow.webkitCancelRequestAnimationFrame ||\n\t\twindow.mozCancelAnimationFrame ||\n\t\twindow.mozCancelRequestAnimationFrame ||\n\t\tfunction(id) {\n\t\t\twindow.clearTimeout(id);\n\t\t};\n};\n\nPageScroller.prototype.cancelScroll = function() {\n\tif(this.idRequestFrame) {\n\t\tthis.cancelAnimationFrame.call(window,this.idRequestFrame);\n\t\tthis.idRequestFrame = null;\n\t}\n};\n\n/*\nHandle an event\n*/\nPageScroller.prototype.handleEvent = function(event) {\n\tif(event.type === \"tm-scroll\") {\n\t\treturn this.scrollIntoView(event.target);\n\t}\n\treturn true;\n};\n\n/*\nHandle a scroll event hitting the page document\n*/\nPageScroller.prototype.scrollIntoView = function(element) {\n\tvar duration = $tw.utils.getAnimationDuration();\n\t// Now get ready to scroll the body\n\tthis.cancelScroll();\n\tthis.startTime = Date.now();\n\tvar scrollPosition = $tw.utils.getScrollPosition();\n\t// Get the client bounds of the element and adjust by the scroll position\n\tvar clientBounds = element.getBoundingClientRect(),\n\t\tbounds = {\n\t\t\tleft: clientBounds.left + scrollPosition.x,\n\t\t\ttop: clientBounds.top + scrollPosition.y,\n\t\t\twidth: clientBounds.width,\n\t\t\theight: clientBounds.height\n\t\t};\n\t// We'll consider the horizontal and vertical scroll directions separately via this function\n\t// targetPos/targetSize - position and size of the target element\n\t// currentPos/currentSize - position and size of the current scroll viewport\n\t// returns: new position of the scroll viewport\n\tvar getEndPos = function(targetPos,targetSize,currentPos,currentSize) {\n\t\t\tvar newPos = currentPos;\n\t\t\t// If the target is above/left of the current view, then scroll to it's top/left\n\t\t\tif(targetPos <= currentPos) {\n\t\t\t\tnewPos = targetPos;\n\t\t\t// If the target is smaller than the window and the scroll position is too far up, then scroll till the target is at the bottom of the window\n\t\t\t} else if(targetSize < currentSize && currentPos < (targetPos + targetSize - currentSize)) {\n\t\t\t\tnewPos = targetPos + targetSize - currentSize;\n\t\t\t// If the target is big, then just scroll to the top\n\t\t\t} else if(currentPos < targetPos) {\n\t\t\t\tnewPos = targetPos;\n\t\t\t// Otherwise, stay where we are\n\t\t\t} else {\n\t\t\t\tnewPos = currentPos;\n\t\t\t}\n\t\t\t// If we are scrolling within 50 pixels of the top/left then snap to zero\n\t\t\tif(newPos < 50) {\n\t\t\t\tnewPos = 0;\n\t\t\t}\n\t\t\treturn newPos;\n\t\t},\n\t\tendX = getEndPos(bounds.left,bounds.width,scrollPosition.x,window.innerWidth),\n\t\tendY = getEndPos(bounds.top,bounds.height,scrollPosition.y,window.innerHeight);\n\t// Only scroll if the position has changed\n\tif(endX !== scrollPosition.x || endY !== scrollPosition.y) {\n\t\tvar self = this,\n\t\t\tdrawFrame;\n\t\tdrawFrame = function () {\n\t\t\tvar t;\n\t\t\tif(duration <= 0) {\n\t\t\t\tt = 1;\n\t\t\t} else {\n\t\t\t\tt = ((Date.now()) - self.startTime) / duration;\t\n\t\t\t}\n\t\t\tif(t >= 1) {\n\t\t\t\tself.cancelScroll();\n\t\t\t\tt = 1;\n\t\t\t}\n\t\t\tt = $tw.utils.slowInSlowOut(t);\n\t\t\twindow.scrollTo(scrollPosition.x + (endX - scrollPosition.x) * t,scrollPosition.y + (endY - scrollPosition.y) * t);\n\t\t\tif(t < 1) {\n\t\t\t\tself.idRequestFrame = self.requestAnimationFrame.call(window,drawFrame);\n\t\t\t}\n\t\t};\n\t\tdrawFrame();\n\t}\n};\n\nexports.PageScroller = PageScroller;\n\n})();\n", "title": "$:/core/modules/utils/dom/scroller.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/edition-info.js": { "text": "/*\\\ntitle: $:/core/modules/utils/edition-info.js\ntype: application/javascript\nmodule-type: utils-node\n\nInformation about the available editions\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar fs = require(\"fs\"),\n\tpath = require(\"path\");\n\nvar editionInfo;\n\nexports.getEditionInfo = function() {\n\tif(!editionInfo) {\n\t\t// Enumerate the edition paths\n\t\tvar editionPaths = $tw.getLibraryItemSearchPaths($tw.config.editionsPath,$tw.config.editionsEnvVar);\n\t\teditionInfo = {};\n\t\tfor(var editionIndex=0; editionIndex<editionPaths.length; editionIndex++) {\n\t\t\tvar editionPath = editionPaths[editionIndex];\n\t\t\t// Enumerate the folders\n\t\t\tvar entries = fs.readdirSync(editionPath);\n\t\t\tfor(var entryIndex=0; entryIndex<entries.length; entryIndex++) {\n\t\t\t\tvar entry = entries[entryIndex];\n\t\t\t\t// Check if directories have a valid tiddlywiki.info\n\t\t\t\tif(!editionInfo[entry] && $tw.utils.isDirectory(path.resolve(editionPath,entry))) {\n\t\t\t\t\tvar info;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tinfo = JSON.parse(fs.readFileSync(path.resolve(editionPath,entry,\"tiddlywiki.info\"),\"utf8\"));\n\t\t\t\t\t} catch(ex) {\n\t\t\t\t\t}\n\t\t\t\t\tif(info) {\n\t\t\t\t\t\teditionInfo[entry] = info;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn editionInfo;\n};\n\n})();\n", "title": "$:/core/modules/utils/edition-info.js", "type": "application/javascript", "module-type": "utils-node" }, "$:/core/modules/utils/fakedom.js": { "text": "/*\\\ntitle: $:/core/modules/utils/fakedom.js\ntype: application/javascript\nmodule-type: global\n\nA barebones implementation of DOM interfaces needed by the rendering mechanism.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Sequence number used to enable us to track objects for testing\nvar sequenceNumber = null;\n\nvar bumpSequenceNumber = function(object) {\n\tif(sequenceNumber !== null) {\n\t\tobject.sequenceNumber = sequenceNumber++;\n\t}\n};\n\nvar TW_TextNode = function(text) {\n\tbumpSequenceNumber(this);\n\tthis.textContent = text + \"\";\n};\n\nObject.defineProperty(TW_TextNode.prototype, \"nodeType\", {\n\tget: function() {\n\t\treturn 3;\n\t}\n});\n\nObject.defineProperty(TW_TextNode.prototype, \"formattedTextContent\", {\n\tget: function() {\n\t\treturn this.textContent.replace(/(\\r?\\n)/g,\"\");\n\t}\n});\n\nvar TW_Element = function(tag,namespace) {\n\tbumpSequenceNumber(this);\n\tthis.isTiddlyWikiFakeDom = true;\n\tthis.tag = tag;\n\tthis.attributes = {};\n\tthis.isRaw = false;\n\tthis.children = [];\n\tthis.style = {};\n\tthis.namespaceURI = namespace || \"http://www.w3.org/1999/xhtml\";\n};\n\nObject.defineProperty(TW_Element.prototype, \"nodeType\", {\n\tget: function() {\n\t\treturn 1;\n\t}\n});\n\nTW_Element.prototype.getAttribute = function(name) {\n\tif(this.isRaw) {\n\t\tthrow \"Cannot getAttribute on a raw TW_Element\";\n\t}\n\treturn this.attributes[name];\n};\n\nTW_Element.prototype.setAttribute = function(name,value) {\n\tif(this.isRaw) {\n\t\tthrow \"Cannot setAttribute on a raw TW_Element\";\n\t}\n\tthis.attributes[name] = value + \"\";\n};\n\nTW_Element.prototype.setAttributeNS = function(namespace,name,value) {\n\tthis.setAttribute(name,value);\n};\n\nTW_Element.prototype.removeAttribute = function(name) {\n\tif(this.isRaw) {\n\t\tthrow \"Cannot removeAttribute on a raw TW_Element\";\n\t}\n\tif($tw.utils.hop(this.attributes,name)) {\n\t\tdelete this.attributes[name];\n\t}\n};\n\nTW_Element.prototype.appendChild = function(node) {\n\tthis.children.push(node);\n\tnode.parentNode = this;\n};\n\nTW_Element.prototype.insertBefore = function(node,nextSibling) {\n\tif(nextSibling) {\n\t\tvar p = this.children.indexOf(nextSibling);\n\t\tif(p !== -1) {\n\t\t\tthis.children.splice(p,0,node);\n\t\t\tnode.parentNode = this;\n\t\t} else {\n\t\t\tthis.appendChild(node);\n\t\t}\n\t} else {\n\t\tthis.appendChild(node);\n\t}\n};\n\nTW_Element.prototype.removeChild = function(node) {\n\tvar p = this.children.indexOf(node);\n\tif(p !== -1) {\n\t\tthis.children.splice(p,1);\n\t}\n};\n\nTW_Element.prototype.hasChildNodes = function() {\n\treturn !!this.children.length;\n};\n\nObject.defineProperty(TW_Element.prototype, \"childNodes\", {\n\tget: function() {\n\t\treturn this.children;\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"firstChild\", {\n\tget: function() {\n\t\treturn this.children[0];\n\t}\n});\n\nTW_Element.prototype.addEventListener = function(type,listener,useCapture) {\n\t// Do nothing\n};\n\nObject.defineProperty(TW_Element.prototype, \"tagName\", {\n\tget: function() {\n\t\treturn this.tag || \"\";\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"className\", {\n\tget: function() {\n\t\treturn this.attributes[\"class\"] || \"\";\n\t},\n\tset: function(value) {\n\t\tthis.attributes[\"class\"] = value + \"\";\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"value\", {\n\tget: function() {\n\t\treturn this.attributes.value || \"\";\n\t},\n\tset: function(value) {\n\t\tthis.attributes.value = value + \"\";\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"outerHTML\", {\n\tget: function() {\n\t\tvar output = [],attr,a,v;\n\t\toutput.push(\"<\",this.tag);\n\t\tif(this.attributes) {\n\t\t\tattr = [];\n\t\t\tfor(a in this.attributes) {\n\t\t\t\tattr.push(a);\n\t\t\t}\n\t\t\tattr.sort();\n\t\t\tfor(a=0; a<attr.length; a++) {\n\t\t\t\tv = this.attributes[attr[a]];\n\t\t\t\tif(v !== undefined) {\n\t\t\t\t\toutput.push(\" \",attr[a],\"=\\\"\",$tw.utils.htmlEncode(v),\"\\\"\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(this.style) {\n\t\t\tvar style = [];\n\t\t\tfor(var s in this.style) {\n\t\t\t\tstyle.push(s + \":\" + this.style[s] + \";\");\n\t\t\t}\n\t\t\tif(style.length > 0) {\n\t\t\t\toutput.push(\" style=\\\"\",style.join(\"\"),\"\\\"\")\n\t\t\t}\n\t\t}\n\t\toutput.push(\">\");\n\t\tif($tw.config.htmlVoidElements.indexOf(this.tag) === -1) {\n\t\t\toutput.push(this.innerHTML);\n\t\t\toutput.push(\"</\",this.tag,\">\");\n\t\t}\n\t\treturn output.join(\"\");\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"innerHTML\", {\n\tget: function() {\n\t\tif(this.isRaw) {\n\t\t\treturn this.rawHTML;\n\t\t} else {\n\t\t\tvar b = [];\n\t\t\t$tw.utils.each(this.children,function(node) {\n\t\t\t\tif(node instanceof TW_Element) {\n\t\t\t\t\tb.push(node.outerHTML);\n\t\t\t\t} else if(node instanceof TW_TextNode) {\n\t\t\t\t\tb.push($tw.utils.htmlEncode(node.textContent));\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn b.join(\"\");\n\t\t}\n\t},\n\tset: function(value) {\n\t\tthis.isRaw = true;\n\t\tthis.rawHTML = value;\n\t\tthis.rawTextContent = null;\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"textInnerHTML\", {\n\tset: function(value) {\n\t\tif(this.isRaw) {\n\t\t\tthis.rawTextContent = value;\n\t\t} else {\n\t\t\tthrow \"Cannot set textInnerHTML of a non-raw TW_Element\";\n\t\t}\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"textContent\", {\n\tget: function() {\n\t\tif(this.isRaw) {\n\t\t\tif(this.rawTextContent === null) {\n\t\t\t\tconsole.log(booboo)\n\t\t\t\tthrow \"Cannot get textContent on a raw TW_Element\";\t\t\t\t\n\t\t\t} else {\n\t\t\t\treturn this.rawTextContent;\n\t\t\t}\n\t\t} else {\n\t\t\tvar b = [];\n\t\t\t$tw.utils.each(this.children,function(node) {\n\t\t\t\tb.push(node.textContent);\n\t\t\t});\n\t\t\treturn b.join(\"\");\n\t\t}\n\t},\n\tset: function(value) {\n\t\tthis.children = [new TW_TextNode(value)];\n\t}\n});\n\nObject.defineProperty(TW_Element.prototype, \"formattedTextContent\", {\n\tget: function() {\n\t\tif(this.isRaw) {\n\t\t\tthrow \"Cannot get formattedTextContent on a raw TW_Element\";\n\t\t} else {\n\t\t\tvar b = [],\n\t\t\t\tisBlock = $tw.config.htmlBlockElements.indexOf(this.tag) !== -1;\n\t\t\tif(isBlock) {\n\t\t\t\tb.push(\"\\n\");\n\t\t\t}\n\t\t\tif(this.tag === \"li\") {\n\t\t\t\tb.push(\"* \");\n\t\t\t}\n\t\t\t$tw.utils.each(this.children,function(node) {\n\t\t\t\tb.push(node.formattedTextContent);\n\t\t\t});\n\t\t\tif(isBlock) {\n\t\t\t\tb.push(\"\\n\");\n\t\t\t}\n\t\t\treturn b.join(\"\");\n\t\t}\n\t}\n});\n\nvar document = {\n\tsetSequenceNumber: function(value) {\n\t\tsequenceNumber = value;\n\t},\n\tcreateElementNS: function(namespace,tag) {\n\t\treturn new TW_Element(tag,namespace);\n\t},\n\tcreateElement: function(tag) {\n\t\treturn new TW_Element(tag);\n\t},\n\tcreateTextNode: function(text) {\n\t\treturn new TW_TextNode(text);\n\t},\n\tcompatMode: \"CSS1Compat\", // For KaTeX to know that we're not a browser in quirks mode\n\tisTiddlyWikiFakeDom: true\n};\n\nexports.fakeDocument = document;\n\n})();\n", "title": "$:/core/modules/utils/fakedom.js", "type": "application/javascript", "module-type": "global" }, "$:/core/modules/utils/filesystem.js": { "text": "/*\\\ntitle: $:/core/modules/utils/filesystem.js\ntype: application/javascript\nmodule-type: utils-node\n\nFile system utilities\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar fs = require(\"fs\"),\n\tpath = require(\"path\");\n\n/*\nRecursively (and synchronously) copy a directory and all its content\n*/\nexports.copyDirectory = function(srcPath,dstPath) {\n\t// Remove any trailing path separators\n\tsrcPath = $tw.utils.removeTrailingSeparator(srcPath);\n\tdstPath = $tw.utils.removeTrailingSeparator(dstPath);\n\t// Create the destination directory\n\tvar err = $tw.utils.createDirectory(dstPath);\n\tif(err) {\n\t\treturn err;\n\t}\n\t// Function to copy a folder full of files\n\tvar copy = function(srcPath,dstPath) {\n\t\tvar srcStats = fs.lstatSync(srcPath),\n\t\t\tdstExists = fs.existsSync(dstPath);\n\t\tif(srcStats.isFile()) {\n\t\t\t$tw.utils.copyFile(srcPath,dstPath);\n\t\t} else if(srcStats.isDirectory()) {\n\t\t\tvar items = fs.readdirSync(srcPath);\n\t\t\tfor(var t=0; t<items.length; t++) {\n\t\t\t\tvar item = items[t],\n\t\t\t\t\terr = copy(srcPath + path.sep + item,dstPath + path.sep + item);\n\t\t\t\tif(err) {\n\t\t\t\t\treturn err;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\tcopy(srcPath,dstPath);\n\treturn null;\n};\n\n/*\nCopy a file\n*/\nvar FILE_BUFFER_LENGTH = 64 * 1024,\n\tfileBuffer;\n\nexports.copyFile = function(srcPath,dstPath) {\n\t// Create buffer if required\n\tif(!fileBuffer) {\n\t\tfileBuffer = new Buffer(FILE_BUFFER_LENGTH);\n\t}\n\t// Create any directories in the destination\n\t$tw.utils.createDirectory(path.dirname(dstPath));\n\t// Copy the file\n\tvar srcFile = fs.openSync(srcPath,\"r\"),\n\t\tdstFile = fs.openSync(dstPath,\"w\"),\n\t\tbytesRead = 1,\n\t\tpos = 0;\n\twhile (bytesRead > 0) {\n\t\tbytesRead = fs.readSync(srcFile,fileBuffer,0,FILE_BUFFER_LENGTH,pos);\n\t\tfs.writeSync(dstFile,fileBuffer,0,bytesRead);\n\t\tpos += bytesRead;\n\t}\n\tfs.closeSync(srcFile);\n\tfs.closeSync(dstFile);\n\treturn null;\n};\n\n/*\nRemove trailing path separator\n*/\nexports.removeTrailingSeparator = function(dirPath) {\n\tvar len = dirPath.length;\n\tif(dirPath.charAt(len-1) === path.sep) {\n\t\tdirPath = dirPath.substr(0,len-1);\n\t}\n\treturn dirPath;\n};\n\n/*\nRecursively create a directory\n*/\nexports.createDirectory = function(dirPath) {\n\tif(dirPath.substr(dirPath.length-1,1) !== path.sep) {\n\t\tdirPath = dirPath + path.sep;\n\t}\n\tvar pos = 1;\n\tpos = dirPath.indexOf(path.sep,pos);\n\twhile(pos !== -1) {\n\t\tvar subDirPath = dirPath.substr(0,pos);\n\t\tif(!$tw.utils.isDirectory(subDirPath)) {\n\t\t\ttry {\n\t\t\t\tfs.mkdirSync(subDirPath);\n\t\t\t} catch(e) {\n\t\t\t\treturn \"Error creating directory '\" + subDirPath + \"'\";\n\t\t\t}\n\t\t}\n\t\tpos = dirPath.indexOf(path.sep,pos + 1);\n\t}\n\treturn null;\n};\n\n/*\nRecursively create directories needed to contain a specified file\n*/\nexports.createFileDirectories = function(filePath) {\n\treturn $tw.utils.createDirectory(path.dirname(filePath));\n};\n\n/*\nRecursively delete a directory\n*/\nexports.deleteDirectory = function(dirPath) {\n\tif(fs.existsSync(dirPath)) {\n\t\tvar entries = fs.readdirSync(dirPath);\n\t\tfor(var entryIndex=0; entryIndex<entries.length; entryIndex++) {\n\t\t\tvar currPath = dirPath + path.sep + entries[entryIndex];\n\t\t\tif(fs.lstatSync(currPath).isDirectory()) {\n\t\t\t\t$tw.utils.deleteDirectory(currPath);\n\t\t\t} else {\n\t\t\t\tfs.unlinkSync(currPath);\n\t\t\t}\n\t\t}\n\tfs.rmdirSync(dirPath);\n\t}\n\treturn null;\n};\n\n/*\nCheck if a path identifies a directory\n*/\nexports.isDirectory = function(dirPath) {\n\treturn fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory();\n};\n\n/*\nCheck if a path identifies a directory that is empty\n*/\nexports.isDirectoryEmpty = function(dirPath) {\n\tif(!$tw.utils.isDirectory(dirPath)) {\n\t\treturn false;\n\t}\n\tvar files = fs.readdirSync(dirPath),\n\t\tempty = true;\n\t$tw.utils.each(files,function(file,index) {\n\t\tif(file.charAt(0) !== \".\") {\n\t\t\tempty = false;\n\t\t}\n\t});\n\treturn empty;\n};\n\n/*\nRecursively delete a tree of empty directories\n*/\nexports.deleteEmptyDirs = function(dirpath,callback) {\n\tvar self = this;\n\tfs.readdir(dirpath,function(err,files) {\n\t\tif(err) {\n\t\t\treturn callback(err);\n\t\t}\n\t\tif(files.length > 0) {\n\t\t\treturn callback(null);\n\t\t}\n\t\tfs.rmdir(dirpath,function(err) {\n\t\t\tif(err) {\n\t\t\t\treturn callback(err);\n\t\t\t}\n\t\t\tself.deleteEmptyDirs(path.dirname(dirpath),callback);\n\t\t});\n\t});\n};\n\n})();\n", "title": "$:/core/modules/utils/filesystem.js", "type": "application/javascript", "module-type": "utils-node" }, "$:/core/modules/utils/logger.js": { "text": "/*\\\ntitle: $:/core/modules/utils/logger.js\ntype: application/javascript\nmodule-type: utils\n\nA basic logging implementation\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar ALERT_TAG = \"$:/tags/Alert\";\n\n/*\nMake a new logger\n*/\nfunction Logger(componentName) {\n\tthis.componentName = componentName || \"\";\n}\n\n/*\nLog a message\n*/\nLogger.prototype.log = function(/* args */) {\n\tif(console !== undefined && console.log !== undefined) {\n\t\treturn Function.apply.call(console.log, console, [this.componentName + \":\"].concat(Array.prototype.slice.call(arguments,0)));\n\t}\n};\n\n/*\nAlert a message\n*/\nLogger.prototype.alert = function(/* args */) {\n\t// Prepare the text of the alert\n\tvar text = Array.prototype.join.call(arguments,\" \");\n\t// Create alert tiddlers in the browser\n\tif($tw.browser) {\n\t\t// Check if there is an existing alert with the same text and the same component\n\t\tvar existingAlerts = $tw.wiki.getTiddlersWithTag(ALERT_TAG),\n\t\t\talertFields,\n\t\t\texistingCount,\n\t\t\tself = this;\n\t\t$tw.utils.each(existingAlerts,function(title) {\n\t\t\tvar tiddler = $tw.wiki.getTiddler(title);\n\t\t\tif(tiddler.fields.text === text && tiddler.fields.component === self.componentName && tiddler.fields.modified && (!alertFields || tiddler.fields.modified < alertFields.modified)) {\n\t\t\t\t\talertFields = $tw.utils.extend({},tiddler.fields);\n\t\t\t}\n\t\t});\n\t\tif(alertFields) {\n\t\t\texistingCount = alertFields.count || 1;\n\t\t} else {\n\t\t\talertFields = {\n\t\t\t\ttitle: $tw.wiki.generateNewTitle(\"$:/temp/alerts/alert\",{prefix: \"\"}),\n\t\t\t\ttext: text,\n\t\t\t\ttags: [ALERT_TAG],\n\t\t\t\tcomponent: this.componentName\n\t\t\t};\n\t\t\texistingCount = 0;\n\t\t}\n\t\talertFields.modified = new Date();\n\t\tif(++existingCount > 1) {\n\t\t\talertFields.count = existingCount;\n\t\t} else {\n\t\t\talertFields.count = undefined;\n\t\t}\n\t\t$tw.wiki.addTiddler(new $tw.Tiddler(alertFields));\n\t\t// Log the alert as well\n\t\tthis.log.apply(this,Array.prototype.slice.call(arguments,0));\n\t} else {\n\t\t// Print an orange message to the console if not in the browser\n\t\tconsole.error(\"\\x1b[1;33m\" + text + \"\\x1b[0m\");\n\t}\n};\n\nexports.Logger = Logger;\n\n})();\n", "title": "$:/core/modules/utils/logger.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/parsetree.js": { "text": "/*\\\ntitle: $:/core/modules/utils/parsetree.js\ntype: application/javascript\nmodule-type: utils\n\nParse tree utility functions.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nexports.addAttributeToParseTreeNode = function(node,name,value) {\n\tnode.attributes = node.attributes || {};\n\tnode.attributes[name] = {type: \"string\", value: value};\n};\n\nexports.getAttributeValueFromParseTreeNode = function(node,name,defaultValue) {\n\tif(node.attributes && node.attributes[name] && node.attributes[name].value !== undefined) {\n\t\treturn node.attributes[name].value;\n\t}\n\treturn defaultValue;\n};\n\nexports.addClassToParseTreeNode = function(node,classString) {\n\tvar classes = [];\n\tnode.attributes = node.attributes || {};\n\tnode.attributes[\"class\"] = node.attributes[\"class\"] || {type: \"string\", value: \"\"};\n\tif(node.attributes[\"class\"].type === \"string\") {\n\t\tif(node.attributes[\"class\"].value !== \"\") {\n\t\t\tclasses = node.attributes[\"class\"].value.split(\" \");\n\t\t}\n\t\tif(classString !== \"\") {\n\t\t\t$tw.utils.pushTop(classes,classString.split(\" \"));\n\t\t}\n\t\tnode.attributes[\"class\"].value = classes.join(\" \");\n\t}\n};\n\nexports.addStyleToParseTreeNode = function(node,name,value) {\n\t\tnode.attributes = node.attributes || {};\n\t\tnode.attributes.style = node.attributes.style || {type: \"string\", value: \"\"};\n\t\tif(node.attributes.style.type === \"string\") {\n\t\t\tnode.attributes.style.value += name + \":\" + value + \";\";\n\t\t}\n};\n\nexports.findParseTreeNode = function(nodeArray,search) {\n\tfor(var t=0; t<nodeArray.length; t++) {\n\t\tif(nodeArray[t].type === search.type && nodeArray[t].tag === search.tag) {\n\t\t\treturn nodeArray[t];\n\t\t}\n\t}\n\treturn undefined;\n};\n\n/*\nHelper to get the text of a parse tree node or array of nodes\n*/\nexports.getParseTreeText = function getParseTreeText(tree) {\n\tvar output = [];\n\tif($tw.utils.isArray(tree)) {\n\t\t$tw.utils.each(tree,function(node) {\n\t\t\toutput.push(getParseTreeText(node));\n\t\t});\n\t} else {\n\t\tif(tree.type === \"text\") {\n\t\t\toutput.push(tree.text);\n\t\t}\n\t\tif(tree.children) {\n\t\t\treturn getParseTreeText(tree.children);\n\t\t}\n\t}\n\treturn output.join(\"\");\n};\n\n})();\n", "title": "$:/core/modules/utils/parsetree.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/performance.js": { "text": "/*\\\ntitle: $:/core/modules/utils/performance.js\ntype: application/javascript\nmodule-type: global\n\nPerformance measurement.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nfunction Performance(enabled) {\n\tthis.enabled = !!enabled;\n\tthis.measures = {}; // Hashmap of current values of measurements\n\tthis.logger = new $tw.utils.Logger(\"performance\");\n}\n\n/*\nWrap performance reporting around a top level function\n*/\nPerformance.prototype.report = function(name,fn) {\n\tvar self = this;\n\tif(this.enabled) {\n\t\treturn function() {\n\t\t\tself.measures = {};\n\t\t\tvar startTime = $tw.utils.timer(),\n\t\t\t\tresult = fn.apply(this,arguments);\n\t\t\tself.logger.log(name + \": \" + $tw.utils.timer(startTime).toFixed(2) + \"ms\");\n\t\t\tfor(var m in self.measures) {\n\t\t\t\tself.logger.log(\"+\" + m + \": \" + self.measures[m].toFixed(2) + \"ms\");\n\t\t\t}\n\t\t\treturn result;\n\t\t};\n\t} else {\n\t\treturn fn;\n\t}\n};\n\n/*\nWrap performance measurements around a subfunction\n*/\nPerformance.prototype.measure = function(name,fn) {\n\tvar self = this;\n\tif(this.enabled) {\n\t\treturn function() {\n\t\t\tvar startTime = $tw.utils.timer(),\n\t\t\t\tresult = fn.apply(this,arguments),\n\t\t\t\tvalue = self.measures[name] || 0;\n\t\t\tself.measures[name] = value + $tw.utils.timer(startTime);\n\t\t\treturn result;\n\t\t};\n\t} else {\n\t\treturn fn;\n\t}\n};\n\nexports.Performance = Performance;\n\n})();\n", "title": "$:/core/modules/utils/performance.js", "type": "application/javascript", "module-type": "global" }, "$:/core/modules/utils/pluginmaker.js": { "text": "/*\\\ntitle: $:/core/modules/utils/pluginmaker.js\ntype: application/javascript\nmodule-type: utils\n\nA quick and dirty way to pack up plugins within the browser.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nRepack a plugin, and then delete any non-shadow payload tiddlers\n*/\nexports.repackPlugin = function(title,additionalTiddlers,excludeTiddlers) {\n\tadditionalTiddlers = additionalTiddlers || [];\n\texcludeTiddlers = excludeTiddlers || [];\n\t// Get the plugin tiddler\n\tvar pluginTiddler = $tw.wiki.getTiddler(title);\n\tif(!pluginTiddler) {\n\t\tthrow \"No such tiddler as \" + title;\n\t}\n\t// Extract the JSON\n\tvar jsonPluginTiddler;\n\ttry {\n\t\tjsonPluginTiddler = JSON.parse(pluginTiddler.fields.text);\n\t} catch(e) {\n\t\tthrow \"Cannot parse plugin tiddler \" + title + \"\\n\" + $tw.language.getString(\"Error/Caption\") + \": \" + e;\n\t}\n\t// Get the list of tiddlers\n\tvar tiddlers = Object.keys(jsonPluginTiddler.tiddlers);\n\t// Add the additional tiddlers\n\t$tw.utils.pushTop(tiddlers,additionalTiddlers);\n\t// Remove any excluded tiddlers\n\tfor(var t=tiddlers.length-1; t>=0; t--) {\n\t\tif(excludeTiddlers.indexOf(tiddlers[t]) !== -1) {\n\t\t\ttiddlers.splice(t,1);\n\t\t}\n\t}\n\t// Pack up the tiddlers into a block of JSON\n\tvar plugins = {};\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = $tw.wiki.getTiddler(title),\n\t\t\tfields = {};\n\t\t$tw.utils.each(tiddler.fields,function (value,name) {\n\t\t\tfields[name] = tiddler.getFieldString(name);\n\t\t});\n\t\tplugins[title] = fields;\n\t});\n\t// Retrieve and bump the version number\n\tvar pluginVersion = $tw.utils.parseVersion(pluginTiddler.getFieldString(\"version\") || \"0.0.0\") || {\n\t\t\tmajor: \"0\",\n\t\t\tminor: \"0\",\n\t\t\tpatch: \"0\"\n\t\t};\n\tpluginVersion.patch++;\n\tvar version = pluginVersion.major + \".\" + pluginVersion.minor + \".\" + pluginVersion.patch;\n\tif(pluginVersion.prerelease) {\n\t\tversion += \"-\" + pluginVersion.prerelease;\n\t}\n\tif(pluginVersion.build) {\n\t\tversion += \"+\" + pluginVersion.build;\n\t}\n\t// Save the tiddler\n\t$tw.wiki.addTiddler(new $tw.Tiddler(pluginTiddler,{text: JSON.stringify({tiddlers: plugins},null,4), version: version}));\n\t// Delete any non-shadow constituent tiddlers\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tif($tw.wiki.tiddlerExists(title)) {\n\t\t\t$tw.wiki.deleteTiddler(title);\n\t\t}\n\t});\n\t// Trigger an autosave\n\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n\t// Return a heartwarming confirmation\n\treturn \"Plugin \" + title + \" successfully saved\";\n};\n\n})();\n", "title": "$:/core/modules/utils/pluginmaker.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/utils/utils.js": { "text": "/*\\\ntitle: $:/core/modules/utils/utils.js\ntype: application/javascript\nmodule-type: utils\n\nVarious static utility functions.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nDisplay a warning, in colour if we're on a terminal\n*/\nexports.warning = function(text) {\n\tconsole.log($tw.node ? \"\\x1b[1;33m\" + text + \"\\x1b[0m\" : text);\n};\n\n/*\nRepeatedly replaces a substring within a string. Like String.prototype.replace, but without any of the default special handling of $ sequences in the replace string\n*/\nexports.replaceString = function(text,search,replace) {\n\treturn text.replace(search,function() {\n\t\treturn replace;\n\t});\n};\n\n/*\nRepeats a string\n*/\nexports.repeat = function(str,count) {\n\tvar result = \"\";\n\tfor(var t=0;t<count;t++) {\n\t\tresult += str;\n\t}\n\treturn result;\n};\n\n/*\nTrim whitespace from the start and end of a string\nThanks to Steven Levithan, http://blog.stevenlevithan.com/archives/faster-trim-javascript\n*/\nexports.trim = function(str) {\n\tif(typeof str === \"string\") {\n\t\treturn str.replace(/^\\s\\s*/, '').replace(/\\s\\s*$/, '');\n\t} else {\n\t\treturn str;\n\t}\n};\n\n/*\nFind the line break preceding a given position in a string\nReturns position immediately after that line break, or the start of the string\n*/\nexports.findPrecedingLineBreak = function(text,pos) {\n\tvar result = text.lastIndexOf(\"\\n\",pos - 1);\n\tif(result === -1) {\n\t\tresult = 0;\n\t} else {\n\t\tresult++;\n\t\tif(text.charAt(result) === \"\\r\") {\n\t\t\tresult++;\n\t\t}\n\t}\n\treturn result;\n};\n\n/*\nFind the line break following a given position in a string\n*/\nexports.findFollowingLineBreak = function(text,pos) {\n\t// Cut to just past the following line break, or to the end of the text\n\tvar result = text.indexOf(\"\\n\",pos);\n\tif(result === -1) {\n\t\tresult = text.length;\n\t} else {\n\t\tif(text.charAt(result) === \"\\r\") {\n\t\t\tresult++;\n\t\t}\n\t}\n\treturn result;\n};\n\n/*\nReturn the number of keys in an object\n*/\nexports.count = function(object) {\n\treturn Object.keys(object || {}).length;\n};\n\n/*\nCheck if an array is equal by value and by reference.\n*/\nexports.isArrayEqual = function(array1,array2) {\n\tif(array1 === array2) {\n\t\treturn true;\n\t}\n\tarray1 = array1 || [];\n\tarray2 = array2 || [];\n\tif(array1.length !== array2.length) {\n\t\treturn false;\n\t}\n\treturn array1.every(function(value,index) {\n\t\treturn value === array2[index];\n\t});\n};\n\n/*\nPush entries onto an array, removing them first if they already exist in the array\n\tarray: array to modify (assumed to be free of duplicates)\n\tvalue: a single value to push or an array of values to push\n*/\nexports.pushTop = function(array,value) {\n\tvar t,p;\n\tif($tw.utils.isArray(value)) {\n\t\t// Remove any array entries that are duplicated in the new values\n\t\tif(value.length !== 0) {\n\t\t\tif(array.length !== 0) {\n\t\t\t\tif(value.length < array.length) {\n\t\t\t\t\tfor(t=0; t<value.length; t++) {\n\t\t\t\t\t\tp = array.indexOf(value[t]);\n\t\t\t\t\t\tif(p !== -1) {\n\t\t\t\t\t\t\tarray.splice(p,1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfor(t=array.length-1; t>=0; t--) {\n\t\t\t\t\t\tp = value.indexOf(array[t]);\n\t\t\t\t\t\tif(p !== -1) {\n\t\t\t\t\t\t\tarray.splice(t,1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Push the values on top of the main array\n\t\t\tarray.push.apply(array,value);\n\t\t}\n\t} else {\n\t\tp = array.indexOf(value);\n\t\tif(p !== -1) {\n\t\t\tarray.splice(p,1);\n\t\t}\n\t\tarray.push(value);\n\t}\n\treturn array;\n};\n\n/*\nRemove entries from an array\n\tarray: array to modify\n\tvalue: a single value to remove, or an array of values to remove\n*/\nexports.removeArrayEntries = function(array,value) {\n\tvar t,p;\n\tif($tw.utils.isArray(value)) {\n\t\tfor(t=0; t<value.length; t++) {\n\t\t\tp = array.indexOf(value[t]);\n\t\t\tif(p !== -1) {\n\t\t\t\tarray.splice(p,1);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tp = array.indexOf(value);\n\t\tif(p !== -1) {\n\t\t\tarray.splice(p,1);\n\t\t}\n\t}\n};\n\n/*\nCheck whether any members of a hashmap are present in another hashmap\n*/\nexports.checkDependencies = function(dependencies,changes) {\n\tvar hit = false;\n\t$tw.utils.each(changes,function(change,title) {\n\t\tif($tw.utils.hop(dependencies,title)) {\n\t\t\thit = true;\n\t\t}\n\t});\n\treturn hit;\n};\n\nexports.extend = function(object /* [, src] */) {\n\t$tw.utils.each(Array.prototype.slice.call(arguments, 1), function(source) {\n\t\tif(source) {\n\t\t\tfor(var property in source) {\n\t\t\t\tobject[property] = source[property];\n\t\t\t}\n\t\t}\n\t});\n\treturn object;\n};\n\nexports.deepCopy = function(object) {\n\tvar result,t;\n\tif($tw.utils.isArray(object)) {\n\t\t// Copy arrays\n\t\tresult = object.slice(0);\n\t} else if(typeof object === \"object\") {\n\t\tresult = {};\n\t\tfor(t in object) {\n\t\t\tif(object[t] !== undefined) {\n\t\t\t\tresult[t] = $tw.utils.deepCopy(object[t]);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tresult = object;\n\t}\n\treturn result;\n};\n\nexports.extendDeepCopy = function(object,extendedProperties) {\n\tvar result = $tw.utils.deepCopy(object),t;\n\tfor(t in extendedProperties) {\n\t\tif(extendedProperties[t] !== undefined) {\n\t\t\tresult[t] = $tw.utils.deepCopy(extendedProperties[t]);\n\t\t}\n\t}\n\treturn result;\n};\n\nexports.deepFreeze = function deepFreeze(object) {\n\tvar property, key;\n\tif(object) {\n\t\tObject.freeze(object);\n\t\tfor(key in object) {\n\t\t\tproperty = object[key];\n\t\t\tif($tw.utils.hop(object,key) && (typeof property === \"object\") && !Object.isFrozen(property)) {\n\t\t\t\tdeepFreeze(property);\n\t\t\t}\n\t\t}\n\t}\n};\n\nexports.slowInSlowOut = function(t) {\n\treturn (1 - ((Math.cos(t * Math.PI) + 1) / 2));\n};\n\nexports.formatDateString = function(date,template) {\n\tvar result = \"\",\n\t\tt = template,\n\t\tmatches = [\n\t\t\t[/^0hh12/, function() {\n\t\t\t\treturn $tw.utils.pad($tw.utils.getHours12(date));\n\t\t\t}],\n\t\t\t[/^wYYYY/, function() {\n\t\t\t\treturn $tw.utils.getYearForWeekNo(date);\n\t\t\t}],\n\t\t\t[/^hh12/, function() {\n\t\t\t\treturn $tw.utils.getHours12(date);\n\t\t\t}],\n\t\t\t[/^DDth/, function() {\n\t\t\t\treturn date.getDate() + $tw.utils.getDaySuffix(date);\n\t\t\t}],\n\t\t\t[/^YYYY/, function() {\n\t\t\t\treturn date.getFullYear();\n\t\t\t}],\n\t\t\t[/^0hh/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getHours());\n\t\t\t}],\n\t\t\t[/^0mm/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getMinutes());\n\t\t\t}],\n\t\t\t[/^0ss/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getSeconds());\n\t\t\t}],\n\t\t\t[/^0DD/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getDate());\n\t\t\t}],\n\t\t\t[/^0MM/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getMonth()+1);\n\t\t\t}],\n\t\t\t[/^0WW/, function() {\n\t\t\t\treturn $tw.utils.pad($tw.utils.getWeek(date));\n\t\t\t}],\n\t\t\t[/^ddd/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Short/Day/\" + date.getDay());\n\t\t\t}],\n\t\t\t[/^mmm/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Short/Month/\" + (date.getMonth() + 1));\n\t\t\t}],\n\t\t\t[/^DDD/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Long/Day/\" + date.getDay());\n\t\t\t}],\n\t\t\t[/^MMM/, function() {\n\t\t\t\treturn $tw.language.getString(\"Date/Long/Month/\" + (date.getMonth() + 1));\n\t\t\t}],\n\t\t\t[/^TZD/, function() {\n\t\t\t\tvar tz = date.getTimezoneOffset(),\n\t\t\t\tatz = Math.abs(tz);\n\t\t\t\treturn (tz < 0 ? '+' : '-') + $tw.utils.pad(Math.floor(atz / 60)) + ':' + $tw.utils.pad(atz % 60);\n\t\t\t}],\n\t\t\t[/^wYY/, function() {\n\t\t\t\treturn $tw.utils.pad($tw.utils.getYearForWeekNo(date) - 2000);\n\t\t\t}],\n\t\t\t[/^[ap]m/, function() {\n\t\t\t\treturn $tw.utils.getAmPm(date).toLowerCase();\n\t\t\t}],\n\t\t\t[/^hh/, function() {\n\t\t\t\treturn date.getHours();\n\t\t\t}],\n\t\t\t[/^mm/, function() {\n\t\t\t\treturn date.getMinutes();\n\t\t\t}],\n\t\t\t[/^ss/, function() {\n\t\t\t\treturn date.getSeconds();\n\t\t\t}],\n\t\t\t[/^[AP]M/, function() {\n\t\t\t\treturn $tw.utils.getAmPm(date).toUpperCase();\n\t\t\t}],\n\t\t\t[/^DD/, function() {\n\t\t\t\treturn date.getDate();\n\t\t\t}],\n\t\t\t[/^MM/, function() {\n\t\t\t\treturn date.getMonth() + 1;\n\t\t\t}],\n\t\t\t[/^WW/, function() {\n\t\t\t\treturn $tw.utils.getWeek(date);\n\t\t\t}],\n\t\t\t[/^YY/, function() {\n\t\t\t\treturn $tw.utils.pad(date.getFullYear() - 2000);\n\t\t\t}]\n\t\t];\n\twhile(t.length){\n\t\tvar matchString = \"\";\n\t\t$tw.utils.each(matches, function(m) {\n\t\t\tvar match = m[0].exec(t);\n\t\t\tif(match) {\n\t\t\t\tmatchString = m[1].call();\n\t\t\t\tt = t.substr(match[0].length);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif(matchString) {\n\t\t\tresult += matchString;\n\t\t} else {\n\t\t\tresult += t.charAt(0);\n\t\t\tt = t.substr(1);\n\t\t}\n\t}\n\tresult = result.replace(/\\\\(.)/g,\"$1\");\n\treturn result;\n};\n\nexports.getAmPm = function(date) {\n\treturn $tw.language.getString(\"Date/Period/\" + (date.getHours() >= 12 ? \"pm\" : \"am\"));\n};\n\nexports.getDaySuffix = function(date) {\n\treturn $tw.language.getString(\"Date/DaySuffix/\" + date.getDate());\n};\n\nexports.getWeek = function(date) {\n\tvar dt = new Date(date.getTime());\n\tvar d = dt.getDay();\n\tif(d === 0) {\n\t\td = 7; // JavaScript Sun=0, ISO Sun=7\n\t}\n\tdt.setTime(dt.getTime() + (4 - d) * 86400000);// shift day to Thurs of same week to calculate weekNo\n\tvar x = new Date(dt.getFullYear(),0,1);\n\tvar n = Math.floor((dt.getTime() - x.getTime()) / 86400000);\n\treturn Math.floor(n / 7) + 1;\n};\n\nexports.getYearForWeekNo = function(date) {\n\tvar dt = new Date(date.getTime());\n\tvar d = dt.getDay();\n\tif(d === 0) {\n\t\td = 7; // JavaScript Sun=0, ISO Sun=7\n\t}\n\tdt.setTime(dt.getTime() + (4 - d) * 86400000);// shift day to Thurs of same week\n\treturn dt.getFullYear();\n};\n\nexports.getHours12 = function(date) {\n\tvar h = date.getHours();\n\treturn h > 12 ? h-12 : ( h > 0 ? h : 12 );\n};\n\n/*\nConvert a date delta in milliseconds into a string representation of \"23 seconds ago\", \"27 minutes ago\" etc.\n\tdelta: delta in milliseconds\nReturns an object with these members:\n\tdescription: string describing the delta period\n\tupdatePeriod: time in millisecond until the string will be inaccurate\n*/\nexports.getRelativeDate = function(delta) {\n\tvar futurep = false;\n\tif(delta < 0) {\n\t\tdelta = -1 * delta;\n\t\tfuturep = true;\n\t}\n\tvar units = [\n\t\t{name: \"Years\", duration: 365 * 24 * 60 * 60 * 1000},\n\t\t{name: \"Months\", duration: (365/12) * 24 * 60 * 60 * 1000},\n\t\t{name: \"Days\", duration: 24 * 60 * 60 * 1000},\n\t\t{name: \"Hours\", duration: 60 * 60 * 1000},\n\t\t{name: \"Minutes\", duration: 60 * 1000},\n\t\t{name: \"Seconds\", duration: 1000}\n\t];\n\tfor(var t=0; t<units.length; t++) {\n\t\tvar result = Math.floor(delta / units[t].duration);\n\t\tif(result >= 2) {\n\t\t\treturn {\n\t\t\t\tdelta: delta,\n\t\t\t\tdescription: $tw.language.getString(\n\t\t\t\t\t\"RelativeDate/\" + (futurep ? \"Future\" : \"Past\") + \"/\" + units[t].name,\n\t\t\t\t\t{variables:\n\t\t\t\t\t\t{period: result.toString()}\n\t\t\t\t\t}\n\t\t\t\t),\n\t\t\t\tupdatePeriod: units[t].duration\n\t\t\t};\n\t\t}\n\t}\n\treturn {\n\t\tdelta: delta,\n\t\tdescription: $tw.language.getString(\n\t\t\t\"RelativeDate/\" + (futurep ? \"Future\" : \"Past\") + \"/Second\",\n\t\t\t{variables:\n\t\t\t\t{period: \"1\"}\n\t\t\t}\n\t\t),\n\t\tupdatePeriod: 1000\n\t};\n};\n\n// Convert & to \"&\", < to \"<\", > to \">\", \" to \""\"\nexports.htmlEncode = function(s) {\n\tif(s) {\n\t\treturn s.toString().replace(/&/mg,\"&\").replace(/</mg,\"<\").replace(/>/mg,\">\").replace(/\\\"/mg,\""\");\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\n// Converts all HTML entities to their character equivalents\nexports.entityDecode = function(s) {\n\tvar converter = String.fromCodePoint || String.fromCharCode,\n\t\te = s.substr(1,s.length-2); // Strip the & and the ;\n\tif(e.charAt(0) === \"#\") {\n\t\tif(e.charAt(1) === \"x\" || e.charAt(1) === \"X\") {\n\t\t\treturn converter(parseInt(e.substr(2),16));\t\n\t\t} else {\n\t\t\treturn converter(parseInt(e.substr(1),10));\n\t\t}\n\t} else {\n\t\tvar c = $tw.config.htmlEntities[e];\n\t\tif(c) {\n\t\t\treturn converter(c);\n\t\t} else {\n\t\t\treturn s; // Couldn't convert it as an entity, just return it raw\n\t\t}\n\t}\n};\n\nexports.unescapeLineBreaks = function(s) {\n\treturn s.replace(/\\\\n/mg,\"\\n\").replace(/\\\\b/mg,\" \").replace(/\\\\s/mg,\"\\\\\").replace(/\\r/mg,\"\");\n};\n\n/*\n * Returns an escape sequence for given character. Uses \\x for characters <=\n * 0xFF to save space, \\u for the rest.\n *\n * The code needs to be in sync with th code template in the compilation\n * function for \"action\" nodes.\n */\n// Copied from peg.js, thanks to David Majda\nexports.escape = function(ch) {\n\tvar charCode = ch.charCodeAt(0);\n\tif(charCode <= 0xFF) {\n\t\treturn '\\\\x' + $tw.utils.pad(charCode.toString(16).toUpperCase());\n\t} else {\n\t\treturn '\\\\u' + $tw.utils.pad(charCode.toString(16).toUpperCase(),4);\n\t}\n};\n\n// Turns a string into a legal JavaScript string\n// Copied from peg.js, thanks to David Majda\nexports.stringify = function(s) {\n\t/*\n\t* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string\n\t* literal except for the closing quote character, backslash, carriage return,\n\t* line separator, paragraph separator, and line feed. Any character may\n\t* appear in the form of an escape sequence.\n\t*\n\t* For portability, we also escape all non-ASCII characters.\n\t*/\n\treturn (s || \"\")\n\t\t.replace(/\\\\/g, '\\\\\\\\') // backslash\n\t\t.replace(/\"/g, '\\\\\"') // double quote character\n\t\t.replace(/'/g, \"\\\\'\") // single quote character\n\t\t.replace(/\\r/g, '\\\\r') // carriage return\n\t\t.replace(/\\n/g, '\\\\n') // line feed\n\t\t.replace(/[\\x80-\\uFFFF]/g, exports.escape); // non-ASCII characters\n};\n\n/*\nEscape the RegExp special characters with a preceding backslash\n*/\nexports.escapeRegExp = function(s) {\n return s.replace(/[\\-\\/\\\\\\^\\$\\*\\+\\?\\.\\(\\)\\|\\[\\]\\{\\}]/g, '\\\\$&');\n};\n\n// Checks whether a link target is external, i.e. not a tiddler title\nexports.isLinkExternal = function(to) {\n\tvar externalRegExp = /^(?:file|http|https|mailto|ftp|irc|news|data|skype):[^\\s<>{}\\[\\]`|\"\\\\^]+(?:\\/|\\b)/i;\n\treturn externalRegExp.test(to);\n};\n\nexports.nextTick = function(fn) {\n/*global window: false */\n\tif(typeof process === \"undefined\") {\n\t\t// Apparently it would be faster to use postMessage - http://dbaron.org/log/20100309-faster-timeouts\n\t\twindow.setTimeout(fn,4);\n\t} else {\n\t\tprocess.nextTick(fn);\n\t}\n};\n\n/*\nConvert a hyphenated CSS property name into a camel case one\n*/\nexports.unHyphenateCss = function(propName) {\n\treturn propName.replace(/-([a-z])/gi, function(match0,match1) {\n\t\treturn match1.toUpperCase();\n\t});\n};\n\n/*\nConvert a camelcase CSS property name into a dashed one (\"backgroundColor\" --> \"background-color\")\n*/\nexports.hyphenateCss = function(propName) {\n\treturn propName.replace(/([A-Z])/g, function(match0,match1) {\n\t\treturn \"-\" + match1.toLowerCase();\n\t});\n};\n\n/*\nParse a text reference of one of these forms:\n* title\n* !!field\n* title!!field\n* title##index\n* etc\nReturns an object with the following fields, all optional:\n* title: tiddler title\n* field: tiddler field name\n* index: JSON property index\n*/\nexports.parseTextReference = function(textRef) {\n\t// Separate out the title, field name and/or JSON indices\n\tvar reTextRef = /(?:(.*?)!!(.+))|(?:(.*?)##(.+))|(.*)/mg,\n\t\tmatch = reTextRef.exec(textRef),\n\t\tresult = {};\n\tif(match && reTextRef.lastIndex === textRef.length) {\n\t\t// Return the parts\n\t\tif(match[1]) {\n\t\t\tresult.title = match[1];\n\t\t}\n\t\tif(match[2]) {\n\t\t\tresult.field = match[2];\n\t\t}\n\t\tif(match[3]) {\n\t\t\tresult.title = match[3];\n\t\t}\n\t\tif(match[4]) {\n\t\t\tresult.index = match[4];\n\t\t}\n\t\tif(match[5]) {\n\t\t\tresult.title = match[5];\n\t\t}\n\t} else {\n\t\t// If we couldn't parse it\n\t\tresult.title = textRef\n\t}\n\treturn result;\n};\n\n/*\nChecks whether a string is a valid fieldname\n*/\nexports.isValidFieldName = function(name) {\n\tif(!name || typeof name !== \"string\") {\n\t\treturn false;\n\t}\n\tname = name.toLowerCase().trim();\n\tvar fieldValidatorRegEx = /^[a-z0-9\\-\\._]+$/mg;\n\treturn fieldValidatorRegEx.test(name);\n};\n\n/*\nExtract the version number from the meta tag or from the boot file\n*/\n\n// Browser version\nexports.extractVersionInfo = function() {\n\tif($tw.packageInfo) {\n\t\treturn $tw.packageInfo.version;\n\t} else {\n\t\tvar metatags = document.getElementsByTagName(\"meta\");\n\t\tfor(var t=0; t<metatags.length; t++) {\n\t\t\tvar m = metatags[t];\n\t\t\tif(m.name === \"tiddlywiki-version\") {\n\t\t\t\treturn m.content;\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nGet the animation duration in ms\n*/\nexports.getAnimationDuration = function() {\n\treturn parseInt($tw.wiki.getTiddlerText(\"$:/config/AnimationDuration\",\"400\"),10);\n};\n\n/*\nHash a string to a number\nDerived from http://stackoverflow.com/a/15710692\n*/\nexports.hashString = function(str) {\n\treturn str.split(\"\").reduce(function(a,b) {\n\t\ta = ((a << 5) - a) + b.charCodeAt(0);\n\t\treturn a & a;\n\t},0);\n};\n\n/*\nDecode a base64 string\n*/\nexports.base64Decode = function(string64) {\n\tif($tw.browser) {\n\t\t// TODO\n\t\tthrow \"$tw.utils.base64Decode() doesn't work in the browser\";\n\t} else {\n\t\treturn (new Buffer(string64,\"base64\")).toString();\n\t}\n};\n\n/*\nConvert a hashmap into a tiddler dictionary format sequence of name:value pairs\n*/\nexports.makeTiddlerDictionary = function(data) {\n\tvar output = [];\n\tfor(var name in data) {\n\t\toutput.push(name + \": \" + data[name]);\n\t}\n\treturn output.join(\"\\n\");\n};\n\n/*\nHigh resolution microsecond timer for profiling\n*/\nexports.timer = function(base) {\n\tvar m;\n\tif($tw.node) {\n\t\tvar r = process.hrtime();\t\t\n\t\tm = r[0] * 1e3 + (r[1] / 1e6);\n\t} else if(window.performance) {\n\t\tm = performance.now();\n\t} else {\n\t\tm = Date.now();\n\t}\n\tif(typeof base !== \"undefined\") {\n\t\tm = m - base;\n\t}\n\treturn m;\n};\n\n/*\nConvert text and content type to a data URI\n*/\nexports.makeDataUri = function(text,type) {\n\ttype = type || \"text/vnd.tiddlywiki\";\n\tvar typeInfo = $tw.config.contentTypeInfo[type] || $tw.config.contentTypeInfo[\"text/plain\"],\n\t\tisBase64 = typeInfo.encoding === \"base64\",\n\t\tparts = [];\n\tparts.push(\"data:\");\n\tparts.push(type);\n\tparts.push(isBase64 ? \";base64\" : \"\");\n\tparts.push(\",\");\n\tparts.push(isBase64 ? text : encodeURIComponent(text));\n\treturn parts.join(\"\");\n};\n\n/*\nUseful for finding out the fully escaped CSS selector equivalent to a given tag. For example:\n\n$tw.utils.tagToCssSelector(\"$:/tags/Stylesheet\") --> tc-tagged-\\%24\\%3A\\%2Ftags\\%2FStylesheet\n*/\nexports.tagToCssSelector = function(tagName) {\n\treturn \"tc-tagged-\" + encodeURIComponent(tagName).replace(/[!\"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^`{\\|}~,]/mg,function(c) {\n\t\treturn \"\\\\\" + c;\n\t});\n};\n\n/*\nIE does not have sign function\n*/\nexports.sign = Math.sign || function(x) {\n\tx = +x; // convert to a number\n\tif (x === 0 || isNaN(x)) {\n\t\treturn x;\n\t}\n\treturn x > 0 ? 1 : -1;\n};\n\n/*\nIE does not have an endsWith function\n*/\nexports.strEndsWith = function(str,ending,position) {\n\tif(str.endsWith) {\n\t\treturn str.endsWith(ending,position);\n\t} else {\n\t\tif (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > str.length) {\n\t\t\tposition = str.length;\n\t\t}\n\t\tposition -= ending.length;\n\t\tvar lastIndex = str.indexOf(ending, position);\n\t\treturn lastIndex !== -1 && lastIndex === position;\n\t}\n};\n\n/*\nTransliterate string from eg. Cyrillic Russian to Latin\n*/\nvar transliterationPairs = {\n\t\"Ё\":\"YO\",\n\t\"Й\":\"I\",\n\t\"Ц\":\"TS\",\n\t\"У\":\"U\",\n\t\"К\":\"K\",\n\t\"Е\":\"E\",\n\t\"Н\":\"N\",\n\t\"Г\":\"G\",\n\t\"Ш\":\"SH\",\n\t\"Щ\":\"SCH\",\n\t\"З\":\"Z\",\n\t\"Х\":\"H\",\n\t\"Ъ\":\"'\",\n\t\"ё\":\"yo\",\n\t\"й\":\"i\",\n\t\"ц\":\"ts\",\n\t\"у\":\"u\",\n\t\"к\":\"k\",\n\t\"е\":\"e\",\n\t\"н\":\"n\",\n\t\"г\":\"g\",\n\t\"ш\":\"sh\",\n\t\"щ\":\"sch\",\n\t\"з\":\"z\",\n\t\"х\":\"h\",\n\t\"ъ\":\"'\",\n\t\"Ф\":\"F\",\n\t\"Ы\":\"I\",\n\t\"В\":\"V\",\n\t\"А\":\"a\",\n\t\"П\":\"P\",\n\t\"Р\":\"R\",\n\t\"О\":\"O\",\n\t\"Л\":\"L\",\n\t\"Д\":\"D\",\n\t\"Ж\":\"ZH\",\n\t\"Э\":\"E\",\n\t\"ф\":\"f\",\n\t\"ы\":\"i\",\n\t\"в\":\"v\",\n\t\"а\":\"a\",\n\t\"п\":\"p\",\n\t\"р\":\"r\",\n\t\"о\":\"o\",\n\t\"л\":\"l\",\n\t\"д\":\"d\",\n\t\"ж\":\"zh\",\n\t\"э\":\"e\",\n\t\"Я\":\"Ya\",\n\t\"Ч\":\"CH\",\n\t\"С\":\"S\",\n\t\"М\":\"M\",\n\t\"И\":\"I\",\n\t\"Т\":\"T\",\n\t\"Ь\":\"'\",\n\t\"Б\":\"B\",\n\t\"Ю\":\"YU\",\n\t\"я\":\"ya\",\n\t\"ч\":\"ch\",\n\t\"с\":\"s\",\n\t\"м\":\"m\",\n\t\"и\":\"i\",\n\t\"т\":\"t\",\n\t\"ь\":\"'\",\n\t\"б\":\"b\",\n\t\"ю\":\"yu\"\n};\n\nexports.transliterate = function(str) {\n\treturn str.split(\"\").map(function(char) {\n\t\treturn transliterationPairs[char] || char;\n\t}).join(\"\");\n};\n\n})();\n", "title": "$:/core/modules/utils/utils.js", "type": "application/javascript", "module-type": "utils" }, "$:/core/modules/widgets/action-createtiddler.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/action-createtiddler.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to create a new tiddler with a unique name and specified fields.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CreateTiddlerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCreateTiddlerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCreateTiddlerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nCreateTiddlerWidget.prototype.execute = function() {\n\tthis.actionBaseTitle = this.getAttribute(\"$basetitle\");\n\tthis.actionSaveTitle = this.getAttribute(\"$savetitle\");\n\tthis.actionTimestamp = this.getAttribute(\"$timestamp\",\"yes\") === \"yes\";\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nCreateTiddlerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif($tw.utils.count(changedAttributes) > 0) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nCreateTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar title = this.wiki.generateNewTitle(this.actionBaseTitle),\n\t\tfields = {},\n\t\tcreationFields,\n\t\tmodificationFields;\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tfields[name] = attribute;\n\t\t}\n\t});\n\tif(this.actionTimestamp) {\n\t\tcreationFields = this.wiki.getCreationFields();\n\t\tmodificationFields = this.wiki.getModificationFields();\n\t}\n\tvar tiddler = this.wiki.addTiddler(new $tw.Tiddler(creationFields,fields,modificationFields,{title: title}));\n\tif(this.actionSaveTitle) {\n\t\tthis.wiki.setTextReference(this.actionSaveTitle,title,this.getVariable(\"currentTiddler\"));\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-createtiddler\"] = CreateTiddlerWidget;\n\n})();\n", "title": "$:/core/modules/widgets/action-createtiddler.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/action-deletefield.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/action-deletefield.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to delete fields of a tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DeleteFieldWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDeleteFieldWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDeleteFieldWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nDeleteFieldWidget.prototype.execute = function() {\n\tthis.actionTiddler = this.getAttribute(\"$tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.actionField = this.getAttribute(\"$field\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nDeleteFieldWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$tiddler\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nDeleteFieldWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar self = this,\n\t\ttiddler = this.wiki.getTiddler(self.actionTiddler),\n\t\tremoveFields = {},\n\t\thasChanged = false;\n\tif(this.actionField) {\n\t\tremoveFields[this.actionField] = undefined;\n\t\tif(this.actionField in tiddler.fields) {\n\t\t\thasChanged = true;\n\t\t}\n\t}\n\tif(tiddler) {\n\t\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\t\tif(name.charAt(0) !== \"$\" && name !== \"title\") {\n\t\t\t\tremoveFields[name] = undefined;\n\t\t\t\thasChanged = true;\n\t\t\t}\n\t\t});\n\t\tif(hasChanged) {\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,removeFields,this.wiki.getModificationFields()));\t\t\t\n\t\t}\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-deletefield\"] = DeleteFieldWidget;\n\n})();\n", "title": "$:/core/modules/widgets/action-deletefield.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/action-deletetiddler.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/action-deletetiddler.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to delete a tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DeleteTiddlerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDeleteTiddlerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDeleteTiddlerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nDeleteTiddlerWidget.prototype.execute = function() {\n\tthis.actionFilter = this.getAttribute(\"$filter\");\n\tthis.actionTiddler = this.getAttribute(\"$tiddler\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nDeleteTiddlerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$filter\"] || changedAttributes[\"$tiddler\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nDeleteTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar tiddlers = [];\n\tif(this.actionFilter) {\n\t\ttiddlers = this.wiki.filterTiddlers(this.actionFilter,this);\n\t}\n\tif(this.actionTiddler) {\n\t\ttiddlers.push(this.actionTiddler);\n\t}\n\tfor(var t=0; t<tiddlers.length; t++) {\n\t\tthis.wiki.deleteTiddler(tiddlers[t]);\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-deletetiddler\"] = DeleteTiddlerWidget;\n\n})();\n", "title": "$:/core/modules/widgets/action-deletetiddler.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/action-listops.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/action-listops.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to apply list operations to any tiddler field (defaults to the 'list' field of the current tiddler)\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\nvar ActionListopsWidget = function(parseTreeNode, options) {\n\tthis.initialise(parseTreeNode, options);\n};\n/**\n * Inherit from the base widget class\n */\nActionListopsWidget.prototype = new Widget();\n/**\n * Render this widget into the DOM\n */\nActionListopsWidget.prototype.render = function(parent, nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n/**\n * Compute the internal state of the widget\n */\nActionListopsWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.target = this.getAttribute(\"$tiddler\", this.getVariable(\n\t\t\"currentTiddler\"));\n\tthis.filter = this.getAttribute(\"$filter\");\n\tthis.subfilter = this.getAttribute(\"$subfilter\");\n\tthis.listField = this.getAttribute(\"$field\", \"list\");\n\tthis.listIndex = this.getAttribute(\"$index\");\n\tthis.filtertags = this.getAttribute(\"$tags\");\n};\n/**\n * \tRefresh the widget by ensuring our attributes are up to date\n */\nActionListopsWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.$tiddler || changedAttributes.$filter ||\n\t\tchangedAttributes.$subfilter || changedAttributes.$field ||\n\t\tchangedAttributes.$index || changedAttributes.$tags) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n/**\n * \tInvoke the action associated with this widget\n */\nActionListopsWidget.prototype.invokeAction = function(triggeringWidget,\n\tevent) {\n\t//Apply the specified filters to the lists\n\tvar field = this.listField,\n\t\tindex,\n\t\ttype = \"!!\",\n\t\tlist = this.listField;\n\tif(this.listIndex) {\n\t\tfield = undefined;\n\t\tindex = this.listIndex;\n\t\ttype = \"##\";\n\t\tlist = this.listIndex;\n\t}\n\tif(this.filter) {\n\t\tthis.wiki.setText(this.target, field, index, $tw.utils.stringifyList(\n\t\t\tthis.wiki\n\t\t\t.filterTiddlers(this.filter, this)));\n\t}\n\tif(this.subfilter) {\n\t\tvar subfilter = \"[list[\" + this.target + type + list + \"]] \" + this.subfilter;\n\t\tthis.wiki.setText(this.target, field, index, $tw.utils.stringifyList(\n\t\t\tthis.wiki\n\t\t\t.filterTiddlers(subfilter, this)));\n\t}\n\tif(this.filtertags) {\n\t\tvar tiddler = this.wiki.getTiddler(this.target),\n\t\t\toldtags = tiddler ? (tiddler.fields.tags || []).slice(0) : [],\n\t\t\ttagfilter = \"[list[\" + this.target + \"!!tags]] \" + this.filtertags,\n\t\t\tnewtags = this.wiki.filterTiddlers(tagfilter,this);\n\t\tif($tw.utils.stringifyList(oldtags.sort()) !== $tw.utils.stringifyList(newtags.sort())) {\n\t\t\tthis.wiki.setText(this.target,\"tags\",undefined,$tw.utils.stringifyList(newtags));\t\t\t\n\t\t}\n\t}\n\treturn true; // Action was invoked\n};\n\nexports[\"action-listops\"] = ActionListopsWidget;\n\n})();\n", "title": "$:/core/modules/widgets/action-listops.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/action-navigate.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/action-navigate.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to navigate to a tiddler\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar NavigateWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nNavigateWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nNavigateWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nNavigateWidget.prototype.execute = function() {\n\tthis.actionTo = this.getAttribute(\"$to\");\n\tthis.actionScroll = this.getAttribute(\"$scroll\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nNavigateWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$to\"] || changedAttributes[\"$scroll\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nNavigateWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar bounds = triggeringWidget && triggeringWidget.getBoundingClientRect && triggeringWidget.getBoundingClientRect(),\n\t\tsuppressNavigation = event.metaKey || event.ctrlKey || (event.button === 1);\n\tif(this.actionScroll === \"yes\") {\n\t\tsuppressNavigation = false;\n\t} else if(this.actionScroll === \"no\") {\n\t\tsuppressNavigation = true;\n\t}\n\tthis.dispatchEvent({\n\t\ttype: \"tm-navigate\",\n\t\tnavigateTo: this.actionTo === undefined ? this.getVariable(\"currentTiddler\") : this.actionTo,\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tnavigateFromNode: triggeringWidget,\n\t\tnavigateFromClientRect: bounds && { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height\n\t\t},\n\t\tnavigateSuppressNavigation: suppressNavigation\n\t});\n\treturn true; // Action was invoked\n};\n\nexports[\"action-navigate\"] = NavigateWidget;\n\n})();\n", "title": "$:/core/modules/widgets/action-navigate.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/action-sendmessage.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/action-sendmessage.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to send a message\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SendMessageWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSendMessageWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSendMessageWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nSendMessageWidget.prototype.execute = function() {\n\tthis.actionMessage = this.getAttribute(\"$message\");\n\tthis.actionParam = this.getAttribute(\"$param\");\n\tthis.actionName = this.getAttribute(\"$name\");\n\tthis.actionValue = this.getAttribute(\"$value\",\"\");\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nSendMessageWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(Object.keys(changedAttributes).length) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nSendMessageWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\t// Get the string parameter\n\tvar param = this.actionParam;\n\t// Assemble the attributes as a hashmap\n\tvar paramObject = Object.create(null);\n\tvar count = 0;\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tparamObject[name] = attribute;\n\t\t\tcount++;\n\t\t}\n\t});\n\t// Add name/value pair if present\n\tif(this.actionName) {\n\t\tparamObject[this.actionName] = this.actionValue;\n\t}\n\t// Dispatch the message\n\tthis.dispatchEvent({\n\t\ttype: this.actionMessage,\n\t\tparam: param,\n\t\tparamObject: paramObject,\n\t\ttiddlerTitle: this.getVariable(\"currentTiddler\"),\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tevent: event\n\t});\n\treturn true; // Action was invoked\n};\n\nexports[\"action-sendmessage\"] = SendMessageWidget;\n\n})();\n", "title": "$:/core/modules/widgets/action-sendmessage.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/action-setfield.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/action-setfield.js\ntype: application/javascript\nmodule-type: widget\n\nAction widget to set a single field or index on a tiddler.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SetFieldWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSetFieldWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSetFieldWidget.prototype.render = function(parent,nextSibling) {\n\tthis.computeAttributes();\n\tthis.execute();\n};\n\n/*\nCompute the internal state of the widget\n*/\nSetFieldWidget.prototype.execute = function() {\n\tthis.actionTiddler = this.getAttribute(\"$tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.actionField = this.getAttribute(\"$field\");\n\tthis.actionIndex = this.getAttribute(\"$index\");\n\tthis.actionValue = this.getAttribute(\"$value\");\n\tthis.actionTimestamp = this.getAttribute(\"$timestamp\",\"yes\") === \"yes\";\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nSetFieldWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"$tiddler\"] || changedAttributes[\"$field\"] || changedAttributes[\"$index\"] || changedAttributes[\"$value\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nInvoke the action associated with this widget\n*/\nSetFieldWidget.prototype.invokeAction = function(triggeringWidget,event) {\n\tvar self = this,\n\t\toptions = {};\n\toptions.suppressTimestamp = !this.actionTimestamp;\n\tif((typeof this.actionField == \"string\") || (typeof this.actionIndex == \"string\") || (typeof this.actionValue == \"string\")) {\n\t\tthis.wiki.setText(this.actionTiddler,this.actionField,this.actionIndex,this.actionValue,options);\n\t}\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tself.wiki.setText(self.actionTiddler,name,undefined,attribute,options);\n\t\t}\n\t});\n\treturn true; // Action was invoked\n};\n\nexports[\"action-setfield\"] = SetFieldWidget;\n\n})();\n", "title": "$:/core/modules/widgets/action-setfield.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/browse.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/browse.js\ntype: application/javascript\nmodule-type: widget\n\nBrowse widget for browsing for files to import\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar BrowseWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nBrowseWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nBrowseWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\tvar domNode = this.document.createElement(\"input\");\n\tdomNode.setAttribute(\"type\",\"file\");\n\tif(this.browseMultiple) {\n\t\tdomNode.setAttribute(\"multiple\",\"multiple\");\n\t}\n\tif(this.tooltip) {\n\t\tdomNode.setAttribute(\"title\",this.tooltip);\n\t}\n\t// Nw.js supports \"nwsaveas\" to force a \"save as\" dialogue that allows a new or existing file to be selected\n\tif(this.nwsaveas) {\n\t\tdomNode.setAttribute(\"nwsaveas\",this.nwsaveas);\n\t}\n\t// Nw.js supports \"webkitdirectory\" to allow a directory to be selected\n\tif(this.webkitdirectory) {\n\t\tdomNode.setAttribute(\"webkitdirectory\",this.webkitdirectory);\n\t}\n\t// Add a click event handler\n\tdomNode.addEventListener(\"change\",function (event) {\n\t\tif(self.message) {\n\t\t\tself.dispatchEvent({type: self.message, param: self.param, files: event.target.files});\n\t\t} else {\n\t\t\tself.wiki.readFiles(event.target.files,function(tiddlerFieldsArray) {\n\t\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify(tiddlerFieldsArray)});\n\t\t\t});\n\t\t}\n\t\treturn false;\n\t},false);\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nBrowseWidget.prototype.execute = function() {\n\tthis.browseMultiple = this.getAttribute(\"multiple\");\n\tthis.message = this.getAttribute(\"message\");\n\tthis.param = this.getAttribute(\"param\");\n\tthis.tooltip = this.getAttribute(\"tooltip\");\n\tthis.nwsaveas = this.getAttribute(\"nwsaveas\");\n\tthis.webkitdirectory = this.getAttribute(\"webkitdirectory\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nBrowseWidget.prototype.refresh = function(changedTiddlers) {\n\treturn false;\n};\n\nexports.browse = BrowseWidget;\n\n})();\n", "title": "$:/core/modules/widgets/browse.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/button.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/button.js\ntype: application/javascript\nmodule-type: widget\n\nButton widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ButtonWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nButtonWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nButtonWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\tvar tag = \"button\";\n\tif(this.buttonTag && $tw.config.htmlUnsafeElements.indexOf(this.buttonTag) === -1) {\n\t\ttag = this.buttonTag;\n\t}\n\tvar domNode = this.document.createElement(tag);\n\t// Assign classes\n\tvar classes = this[\"class\"].split(\" \") || [],\n\t\tisPoppedUp = this.popup && this.isPoppedUp();\n\tif(this.selectedClass) {\n\t\tif(this.set && this.setTo && this.isSelected()) {\n\t\t\t$tw.utils.pushTop(classes,this.selectedClass.split(\" \"));\n\t\t}\n\t\tif(isPoppedUp) {\n\t\t\t$tw.utils.pushTop(classes,this.selectedClass.split(\" \"));\n\t\t}\n\t}\n\tif(isPoppedUp) {\n\t\t$tw.utils.pushTop(classes,\"tc-popup-handle\");\n\t}\n\tdomNode.className = classes.join(\" \");\n\t// Assign other attributes\n\tif(this.style) {\n\t\tdomNode.setAttribute(\"style\",this.style);\n\t}\n\tif(this.tooltip) {\n\t\tdomNode.setAttribute(\"title\",this.tooltip);\n\t}\n\tif(this[\"aria-label\"]) {\n\t\tdomNode.setAttribute(\"aria-label\",this[\"aria-label\"]);\n\t}\n\t// Add a click event handler\n\tdomNode.addEventListener(\"click\",function (event) {\n\t\tvar handled = false;\n\t\tif(self.invokeActions(this,event)) {\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.to) {\n\t\t\tself.navigateTo(event);\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.message) {\n\t\t\tself.dispatchMessage(event);\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.popup) {\n\t\t\tself.triggerPopup(event);\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.set) {\n\t\t\tself.setTiddler();\n\t\t\thandled = true;\n\t\t}\n\t\tif(self.actions) {\n\t\t\tself.invokeActionString(self.actions,self,event);\n\t\t}\n\t\tif(handled) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t\treturn handled;\n\t},false);\n\t// Make it draggable if required\n\tif(this.dragTiddler || this.dragFilter) {\n\t\t$tw.utils.makeDraggable({\n\t\t\tdomNode: domNode,\n\t\t\tdragTiddlerFn: function() {return self.dragTiddler;},\n\t\t\tdragFilterFn: function() {return self.dragFilter;},\n\t\t\twidget: this\n\t\t});\n\t}\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nWe don't allow actions to propagate because we trigger actions ourselves\n*/\nButtonWidget.prototype.allowActionPropagation = function() {\n\treturn false;\n};\n\nButtonWidget.prototype.getBoundingClientRect = function() {\n\treturn this.domNodes[0].getBoundingClientRect();\n};\n\nButtonWidget.prototype.isSelected = function() {\n return this.wiki.getTextReference(this.set,this.defaultSetValue,this.getVariable(\"currentTiddler\")) === this.setTo;\n};\n\nButtonWidget.prototype.isPoppedUp = function() {\n\tvar tiddler = this.wiki.getTiddler(this.popup);\n\tvar result = tiddler && tiddler.fields.text ? $tw.popup.readPopupState(tiddler.fields.text) : false;\n\treturn result;\n};\n\nButtonWidget.prototype.navigateTo = function(event) {\n\tvar bounds = this.getBoundingClientRect();\n\tthis.dispatchEvent({\n\t\ttype: \"tm-navigate\",\n\t\tnavigateTo: this.to,\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tnavigateFromNode: this,\n\t\tnavigateFromClientRect: { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height\n\t\t},\n\t\tnavigateSuppressNavigation: event.metaKey || event.ctrlKey || (event.button === 1),\n\t\tevent: event\n\t});\n};\n\nButtonWidget.prototype.dispatchMessage = function(event) {\n\tthis.dispatchEvent({type: this.message, param: this.param, tiddlerTitle: this.getVariable(\"currentTiddler\"), event: event});\n};\n\nButtonWidget.prototype.triggerPopup = function(event) {\n\t$tw.popup.triggerPopup({\n\t\tdomNode: this.domNodes[0],\n\t\ttitle: this.popup,\n\t\twiki: this.wiki\n\t});\n};\n\nButtonWidget.prototype.setTiddler = function() {\n\tthis.wiki.setTextReference(this.set,this.setTo,this.getVariable(\"currentTiddler\"));\n};\n\n/*\nCompute the internal state of the widget\n*/\nButtonWidget.prototype.execute = function() {\n\t// Get attributes\n\tthis.actions = this.getAttribute(\"actions\");\n\tthis.to = this.getAttribute(\"to\");\n\tthis.message = this.getAttribute(\"message\");\n\tthis.param = this.getAttribute(\"param\");\n\tthis.set = this.getAttribute(\"set\");\n\tthis.setTo = this.getAttribute(\"setTo\");\n\tthis.popup = this.getAttribute(\"popup\");\n\tthis.hover = this.getAttribute(\"hover\");\n\tthis[\"class\"] = this.getAttribute(\"class\",\"\");\n\tthis[\"aria-label\"] = this.getAttribute(\"aria-label\");\n\tthis.tooltip = this.getAttribute(\"tooltip\");\n\tthis.style = this.getAttribute(\"style\");\n\tthis.selectedClass = this.getAttribute(\"selectedClass\");\n\tthis.defaultSetValue = this.getAttribute(\"default\",\"\");\n\tthis.buttonTag = this.getAttribute(\"tag\");\n\tthis.dragTiddler = this.getAttribute(\"dragTiddler\");\n\tthis.dragFilter = this.getAttribute(\"dragFilter\");\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nButtonWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes[\"class\"] || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup])) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.button = ButtonWidget;\n\n})();\n", "title": "$:/core/modules/widgets/button.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/checkbox.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/checkbox.js\ntype: application/javascript\nmodule-type: widget\n\nCheckbox widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CheckboxWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCheckboxWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCheckboxWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Create our elements\n\tthis.labelDomNode = this.document.createElement(\"label\");\n\tthis.labelDomNode.setAttribute(\"class\",this.checkboxClass);\n\tthis.inputDomNode = this.document.createElement(\"input\");\n\tthis.inputDomNode.setAttribute(\"type\",\"checkbox\");\n\tif(this.getValue()) {\n\t\tthis.inputDomNode.setAttribute(\"checked\",\"true\");\n\t}\n\tthis.labelDomNode.appendChild(this.inputDomNode);\n\tthis.spanDomNode = this.document.createElement(\"span\");\n\tthis.labelDomNode.appendChild(this.spanDomNode);\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(this.inputDomNode,[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n\t// Insert the label into the DOM and render any children\n\tparent.insertBefore(this.labelDomNode,nextSibling);\n\tthis.renderChildren(this.spanDomNode,null);\n\tthis.domNodes.push(this.labelDomNode);\n};\n\nCheckboxWidget.prototype.getValue = function() {\n\tvar tiddler = this.wiki.getTiddler(this.checkboxTitle);\n\tif(tiddler) {\n\t\tif(this.checkboxTag) {\n\t\t\tif(this.checkboxInvertTag) {\n\t\t\t\treturn !tiddler.hasTag(this.checkboxTag);\n\t\t\t} else {\n\t\t\t\treturn tiddler.hasTag(this.checkboxTag);\n\t\t\t}\n\t\t}\n\t\tif(this.checkboxField) {\n\t\t\tvar value;\n\t\t\tif($tw.utils.hop(tiddler.fields,this.checkboxField)) {\n\t\t\t\tvalue = tiddler.fields[this.checkboxField] || \"\";\n\t\t\t} else {\n\t\t\t\tvalue = this.checkboxDefault || \"\";\n\t\t\t}\n\t\t\tif(value === this.checkboxChecked) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(value === this.checkboxUnchecked) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\tif(this.checkboxIndex) {\n\t\t\tvar value = this.wiki.extractTiddlerDataItem(tiddler,this.checkboxIndex,this.checkboxDefault || \"\");\n\t\t\tif(value === this.checkboxChecked) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(value === this.checkboxUnchecked) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif(this.checkboxTag) {\n\t\t\treturn false;\n\t\t}\n\t\tif(this.checkboxField) {\n\t\t\tif(this.checkboxDefault === this.checkboxChecked) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(this.checkboxDefault === this.checkboxUnchecked) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n};\n\nCheckboxWidget.prototype.handleChangeEvent = function(event) {\n\tvar checked = this.inputDomNode.checked,\n\t\ttiddler = this.wiki.getTiddler(this.checkboxTitle),\n\t\tfallbackFields = {text: \"\"},\n\t\tnewFields = {title: this.checkboxTitle},\n\t\thasChanged = false,\n\t\ttagCheck = false,\n\t\thasTag = tiddler && tiddler.hasTag(this.checkboxTag),\n\t\tvalue = checked ? this.checkboxChecked : this.checkboxUnchecked;\n\tif(this.checkboxTag && this.checkboxInvertTag === \"yes\") {\n\t\ttagCheck = hasTag === checked;\n\t} else {\n\t\ttagCheck = hasTag !== checked;\n\t}\n\t// Set the tag if specified\n\tif(this.checkboxTag && (!tiddler || tagCheck)) {\n\t\tnewFields.tags = tiddler ? (tiddler.fields.tags || []).slice(0) : [];\n\t\tvar pos = newFields.tags.indexOf(this.checkboxTag);\n\t\tif(pos !== -1) {\n\t\t\tnewFields.tags.splice(pos,1);\n\t\t}\n\t\tif(this.checkboxInvertTag === \"yes\" && !checked) {\n\t\t\tnewFields.tags.push(this.checkboxTag);\n\t\t} else if(this.checkboxInvertTag !== \"yes\" && checked) {\n\t\t\tnewFields.tags.push(this.checkboxTag);\n\t\t}\n\t\thasChanged = true;\n\t}\n\t// Set the field if specified\n\tif(this.checkboxField) {\n\t\tif(!tiddler || tiddler.fields[this.checkboxField] !== value) {\n\t\t\tnewFields[this.checkboxField] = value;\n\t\t\thasChanged = true;\n\t\t}\n\t}\n\t// Set the index if specified\n\tif(this.checkboxIndex) {\n\t\tvar indexValue = this.wiki.extractTiddlerDataItem(this.checkboxTitle,this.checkboxIndex);\n\t\tif(!tiddler || indexValue !== value) {\n\t\t\thasChanged = true;\n\t\t}\n\t}\n\tif(hasChanged) {\n\t\tif(this.checkboxIndex) {\n\t\t\tthis.wiki.setText(this.checkboxTitle,\"\",this.checkboxIndex,value);\n\t\t} else {\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),fallbackFields,tiddler,newFields,this.wiki.getModificationFields()));\n\t\t}\n\t}\n\t// Trigger actions\n\tif(this.checkboxActions) {\n\t\tthis.invokeActionString(this.checkboxActions,this,event);\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nCheckboxWidget.prototype.execute = function() {\n\t// Get the parameters from the attributes\n\tthis.checkboxActions = this.getAttribute(\"actions\");\n\tthis.checkboxTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.checkboxTag = this.getAttribute(\"tag\");\n\tthis.checkboxField = this.getAttribute(\"field\");\n\tthis.checkboxIndex = this.getAttribute(\"index\");\n\tthis.checkboxChecked = this.getAttribute(\"checked\");\n\tthis.checkboxUnchecked = this.getAttribute(\"unchecked\");\n\tthis.checkboxDefault = this.getAttribute(\"default\");\n\tthis.checkboxClass = this.getAttribute(\"class\",\"\");\n\tthis.checkboxInvertTag = this.getAttribute(\"invertTag\",\"\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nCheckboxWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.tag || changedAttributes.invertTag || changedAttributes.field || changedAttributes.index || changedAttributes.checked || changedAttributes.unchecked || changedAttributes[\"default\"] || changedAttributes[\"class\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\tvar refreshed = false;\n\t\tif(changedTiddlers[this.checkboxTitle]) {\n\t\t\tthis.inputDomNode.checked = this.getValue();\n\t\t\trefreshed = true;\n\t\t}\n\t\treturn this.refreshChildren(changedTiddlers) || refreshed;\n\t}\n};\n\nexports.checkbox = CheckboxWidget;\n\n})();", "title": "$:/core/modules/widgets/checkbox.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/codeblock.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/codeblock.js\ntype: application/javascript\nmodule-type: widget\n\nCode block node widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CodeBlockWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCodeBlockWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCodeBlockWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar codeNode = this.document.createElement(\"code\"),\n\t\tdomNode = this.document.createElement(\"pre\");\n\tcodeNode.appendChild(this.document.createTextNode(this.getAttribute(\"code\")));\n\tdomNode.appendChild(codeNode);\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.domNodes.push(domNode);\n\tif(this.postRender) {\n\t\tthis.postRender();\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nCodeBlockWidget.prototype.execute = function() {\n\tthis.language = this.getAttribute(\"language\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nCodeBlockWidget.prototype.refresh = function(changedTiddlers) {\n\treturn false;\n};\n\nexports.codeblock = CodeBlockWidget;\n\n})();\n", "title": "$:/core/modules/widgets/codeblock.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/count.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/count.js\ntype: application/javascript\nmodule-type: widget\n\nCount widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar CountWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nCountWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nCountWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar textNode = this.document.createTextNode(this.currentCount);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nCountWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.filter = this.getAttribute(\"filter\");\n\t// Execute the filter\n\tif(this.filter) {\n\t\tthis.currentCount = this.wiki.filterTiddlers(this.filter,this).length;\n\t} else {\n\t\tthis.currentCount = undefined;\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nCountWidget.prototype.refresh = function(changedTiddlers) {\n\t// Re-execute the filter to get the count\n\tthis.computeAttributes();\n\tvar oldCount = this.currentCount;\n\tthis.execute();\n\tif(this.currentCount !== oldCount) {\n\t\t// Regenerate and rerender the widget and replace the existing DOM node\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n\n};\n\nexports.count = CountWidget;\n\n})();\n", "title": "$:/core/modules/widgets/count.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/draggable.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/draggable.js\ntype: application/javascript\nmodule-type: widget\n\nDraggable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DraggableWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDraggableWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDraggableWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Sanitise the specified tag\n\tvar tag = this.draggableTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"div\";\n\t}\n\t// Create our element\n\tvar domNode = this.document.createElement(tag);\n\t// Assign classes\n\tvar classes = [\"tc-draggable\"];\n\tif(this.draggableClasses) {\n\t\tclasses.push(this.draggableClasses);\n\t}\n\tdomNode.setAttribute(\"class\",classes.join(\" \"));\n\t// Add event handlers\n\t$tw.utils.makeDraggable({\n\t\tdomNode: domNode,\n\t\tdragTiddlerFn: function() {return self.getAttribute(\"tiddler\");},\n\t\tdragFilterFn: function() {return self.getAttribute(\"filter\");},\n\t\twidget: this\n\t});\n\t// Insert the link into the DOM and render any children\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nDraggableWidget.prototype.execute = function() {\n\t// Pick up our attributes\n\tthis.draggableTag = this.getAttribute(\"tag\",\"div\");\n\tthis.draggableClasses = this.getAttribute(\"class\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nDraggableWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedTiddlers.tag || changedTiddlers[\"class\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.draggable = DraggableWidget;\n\n})();\n", "title": "$:/core/modules/widgets/draggable.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/droppable.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/droppable.js\ntype: application/javascript\nmodule-type: widget\n\nDroppable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DroppableWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDroppableWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDroppableWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar tag = this.parseTreeNode.isBlock ? \"div\" : \"span\";\n\tif(this.droppableTag && $tw.config.htmlUnsafeElements.indexOf(this.droppableTag) === -1) {\n\t\ttag = this.droppableTag;\n\t}\n\t// Create element and assign classes\n\tvar domNode = this.document.createElement(tag),\n\t\tclasses = (this[\"class\"] || \"\").split(\" \");\n\tclasses.push(\"tc-droppable\");\n\tdomNode.className = classes.join(\" \");\n\t// Add event handlers\n\t$tw.utils.addEventListeners(domNode,[\n\t\t{name: \"dragenter\", handlerObject: this, handlerMethod: \"handleDragEnterEvent\"},\n\t\t{name: \"dragover\", handlerObject: this, handlerMethod: \"handleDragOverEvent\"},\n\t\t{name: \"dragleave\", handlerObject: this, handlerMethod: \"handleDragLeaveEvent\"},\n\t\t{name: \"drop\", handlerObject: this, handlerMethod: \"handleDropEvent\"}\n\t]);\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n\t// Stack of outstanding enter/leave events\n\tthis.currentlyEntered = [];\n};\n\nDroppableWidget.prototype.enterDrag = function(event) {\n\tif(this.currentlyEntered.indexOf(event.target) === -1) {\n\t\tthis.currentlyEntered.push(event.target);\n\t}\n\t// If we're entering for the first time we need to apply highlighting\n\t$tw.utils.addClass(this.domNodes[0],\"tc-dragover\");\n};\n\nDroppableWidget.prototype.leaveDrag = function(event) {\n\tvar pos = this.currentlyEntered.indexOf(event.target);\n\tif(pos !== -1) {\n\t\tthis.currentlyEntered.splice(pos,1);\n\t}\n\t// Remove highlighting if we're leaving externally. The hacky second condition is to resolve a problem with Firefox whereby there is an erroneous dragenter event if the node being dragged is within the dropzone\n\tif(this.currentlyEntered.length === 0 || (this.currentlyEntered.length === 1 && this.currentlyEntered[0] === $tw.dragInProgress)) {\n\t\tthis.currentlyEntered = [];\n\t\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t}\n};\n\nDroppableWidget.prototype.handleDragEnterEvent = function(event) {\n\tthis.enterDrag(event);\n\t// Tell the browser that we're ready to handle the drop\n\tevent.preventDefault();\n\t// Tell the browser not to ripple the drag up to any parent drop handlers\n\tevent.stopPropagation();\n\treturn false;\n};\n\nDroppableWidget.prototype.handleDragOverEvent = function(event) {\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\t// Tell the browser that we're still interested in the drop\n\tevent.preventDefault();\n\t// Set the drop effect\n\tevent.dataTransfer.dropEffect = this.droppableEffect;\n\treturn false;\n};\n\nDroppableWidget.prototype.handleDragLeaveEvent = function(event) {\n\tthis.leaveDrag(event);\n\treturn false;\n};\n\nDroppableWidget.prototype.handleDropEvent = function(event) {\n\tvar self = this;\n\tthis.leaveDrag(event);\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\tvar dataTransfer = event.dataTransfer;\n\t// Remove highlighting\n\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t// Try to import the various data types we understand\n\t$tw.utils.importDataTransfer(dataTransfer,null,function(fieldsArray) {\n\t\tfieldsArray.forEach(function(fields) {\n\t\t\tself.performActions(fields.title || fields.text,event);\n\t\t});\n\t});\n\t// Tell the browser that we handled the drop\n\tevent.preventDefault();\n\t// Stop the drop ripple up to any parent handlers\n\tevent.stopPropagation();\n\treturn false;\n};\n\nDroppableWidget.prototype.performActions = function(title,event) {\n\tif(this.droppableActions) {\n\t\tthis.invokeActionString(this.droppableActions,this,event,{actionTiddler: title});\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nDroppableWidget.prototype.execute = function() {\n\tthis.droppableActions = this.getAttribute(\"actions\");\n\tthis.droppableEffect = this.getAttribute(\"effect\",\"copy\");\n\tthis.droppableTag = this.getAttribute(\"tag\");\n\tthis.droppableClass = this.getAttribute(\"class\");\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nDroppableWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"class\"] || changedAttributes.tag) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.droppable = DroppableWidget;\n\n})();\n", "title": "$:/core/modules/widgets/droppable.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/dropzone.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/dropzone.js\ntype: application/javascript\nmodule-type: widget\n\nDropzone widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar DropZoneWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nDropZoneWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nDropZoneWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\tvar domNode = this.document.createElement(\"div\");\n\tdomNode.className = \"tc-dropzone\";\n\t// Add event handlers\n\t$tw.utils.addEventListeners(domNode,[\n\t\t{name: \"dragenter\", handlerObject: this, handlerMethod: \"handleDragEnterEvent\"},\n\t\t{name: \"dragover\", handlerObject: this, handlerMethod: \"handleDragOverEvent\"},\n\t\t{name: \"dragleave\", handlerObject: this, handlerMethod: \"handleDragLeaveEvent\"},\n\t\t{name: \"drop\", handlerObject: this, handlerMethod: \"handleDropEvent\"},\n\t\t{name: \"paste\", handlerObject: this, handlerMethod: \"handlePasteEvent\"}\n\t]);\n\tdomNode.addEventListener(\"click\",function (event) {\n\t},false);\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n\t// Stack of outstanding enter/leave events\n\tthis.currentlyEntered = [];\n};\n\nDropZoneWidget.prototype.enterDrag = function(event) {\n\tif(this.currentlyEntered.indexOf(event.target) === -1) {\n\t\tthis.currentlyEntered.push(event.target);\n\t}\n\t// If we're entering for the first time we need to apply highlighting\n\t$tw.utils.addClass(this.domNodes[0],\"tc-dragover\");\n};\n\nDropZoneWidget.prototype.leaveDrag = function(event) {\n\tvar pos = this.currentlyEntered.indexOf(event.target);\n\tif(pos !== -1) {\n\t\tthis.currentlyEntered.splice(pos,1);\n\t}\n\t// Remove highlighting if we're leaving externally\n\tif(this.currentlyEntered.length === 0) {\n\t\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t}\n};\n\nDropZoneWidget.prototype.handleDragEnterEvent = function(event) {\n\t// Check for this window being the source of the drag\n\tif($tw.dragInProgress) {\n\t\treturn false;\n\t}\n\tthis.enterDrag(event);\n\t// Tell the browser that we're ready to handle the drop\n\tevent.preventDefault();\n\t// Tell the browser not to ripple the drag up to any parent drop handlers\n\tevent.stopPropagation();\n};\n\nDropZoneWidget.prototype.handleDragOverEvent = function(event) {\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\t// Check for this window being the source of the drag\n\tif($tw.dragInProgress) {\n\t\treturn false;\n\t}\n\t// Tell the browser that we're still interested in the drop\n\tevent.preventDefault();\n\tevent.dataTransfer.dropEffect = \"copy\"; // Explicitly show this is a copy\n};\n\nDropZoneWidget.prototype.handleDragLeaveEvent = function(event) {\n\tthis.leaveDrag(event);\n};\n\nDropZoneWidget.prototype.handleDropEvent = function(event) {\n\tvar self = this;\n\tthis.leaveDrag(event);\n\t// Check for being over a TEXTAREA or INPUT\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) !== -1) {\n\t\treturn false;\n\t}\n\t// Check for this window being the source of the drag\n\tif($tw.dragInProgress) {\n\t\treturn false;\n\t}\n\tvar self = this,\n\t\tdataTransfer = event.dataTransfer;\n\t// Remove highlighting\n\t$tw.utils.removeClass(this.domNodes[0],\"tc-dragover\");\n\t// Import any files in the drop\n\tvar numFiles = 0;\n\tif(dataTransfer.files) {\n\t\tnumFiles = this.wiki.readFiles(dataTransfer.files,function(tiddlerFieldsArray) {\n\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify(tiddlerFieldsArray)});\n\t\t});\n\t}\n\t// Try to import the various data types we understand\n\tif(numFiles === 0) {\n\t\t$tw.utils.importDataTransfer(dataTransfer,this.wiki.generateNewTitle(\"Untitled\"),function(fieldsArray) {\n\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify(fieldsArray)});\n\t\t});\n\t}\n\t// Tell the browser that we handled the drop\n\tevent.preventDefault();\n\t// Stop the drop ripple up to any parent handlers\n\tevent.stopPropagation();\n};\n\nDropZoneWidget.prototype.handlePasteEvent = function(event) {\n\t// Let the browser handle it if we're in a textarea or input box\n\tif([\"TEXTAREA\",\"INPUT\"].indexOf(event.target.tagName) == -1) {\n\t\tvar self = this,\n\t\t\titems = event.clipboardData.items;\n\t\t// Enumerate the clipboard items\n\t\tfor(var t = 0; t<items.length; t++) {\n\t\t\tvar item = items[t];\n\t\t\tif(item.kind === \"file\") {\n\t\t\t\t// Import any files\n\t\t\t\tthis.wiki.readFile(item.getAsFile(),function(tiddlerFieldsArray) {\n\t\t\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify(tiddlerFieldsArray)});\n\t\t\t\t});\n\t\t\t} else if(item.kind === \"string\") {\n\t\t\t\t// Create tiddlers from string items\n\t\t\t\tvar type = item.type;\n\t\t\t\titem.getAsString(function(str) {\n\t\t\t\t\tvar tiddlerFields = {\n\t\t\t\t\t\ttitle: self.wiki.generateNewTitle(\"Untitled\"),\n\t\t\t\t\t\ttext: str,\n\t\t\t\t\t\ttype: type\n\t\t\t\t\t};\n\t\t\t\t\tif($tw.log.IMPORT) {\n\t\t\t\t\t\tconsole.log(\"Importing string '\" + str + \"', type: '\" + type + \"'\");\n\t\t\t\t\t}\n\t\t\t\t\tself.dispatchEvent({type: \"tm-import-tiddlers\", param: JSON.stringify([tiddlerFields])});\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t// Tell the browser that we've handled the paste\n\t\tevent.stopPropagation();\n\t\tevent.preventDefault();\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nDropZoneWidget.prototype.execute = function() {\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nDropZoneWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.dropzone = DropZoneWidget;\n\n})();\n", "title": "$:/core/modules/widgets/dropzone.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/edit-binary.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/edit-binary.js\ntype: application/javascript\nmodule-type: widget\n\nEdit-binary widget; placeholder for editing binary tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar BINARY_WARNING_MESSAGE = \"$:/core/ui/BinaryWarning\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditBinaryWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditBinaryWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditBinaryWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nEditBinaryWidget.prototype.execute = function() {\n\t// Construct the child widgets\n\tthis.makeChildWidgets([{\n\t\ttype: \"transclude\",\n\t\tattributes: {\n\t\t\ttiddler: {type: \"string\", value: BINARY_WARNING_MESSAGE}\n\t\t}\n\t}]);\n};\n\n/*\nRefresh by refreshing our child widget\n*/\nEditBinaryWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports[\"edit-binary\"] = EditBinaryWidget;\n\n})();\n", "title": "$:/core/modules/widgets/edit-binary.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/edit-bitmap.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/edit-bitmap.js\ntype: application/javascript\nmodule-type: widget\n\nEdit-bitmap widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Default image sizes\nvar DEFAULT_IMAGE_WIDTH = 600,\n\tDEFAULT_IMAGE_HEIGHT = 370;\n\n// Configuration tiddlers\nvar LINE_WIDTH_TITLE = \"$:/config/BitmapEditor/LineWidth\",\n\tLINE_COLOUR_TITLE = \"$:/config/BitmapEditor/Colour\",\n\tLINE_OPACITY_TITLE = \"$:/config/BitmapEditor/Opacity\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditBitmapWidget = function(parseTreeNode,options) {\n\t// Initialise the editor operations if they've not been done already\n\tif(!this.editorOperations) {\n\t\tEditBitmapWidget.prototype.editorOperations = {};\n\t\t$tw.modules.applyMethods(\"bitmapeditoroperation\",this.editorOperations);\n\t}\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditBitmapWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditBitmapWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Create the wrapper for the toolbar and render its content\n\tthis.toolbarNode = this.document.createElement(\"div\");\n\tthis.toolbarNode.className = \"tc-editor-toolbar\";\n\tparent.insertBefore(this.toolbarNode,nextSibling);\n\tthis.domNodes.push(this.toolbarNode);\n\t// Create the on-screen canvas\n\tthis.canvasDomNode = $tw.utils.domMaker(\"canvas\",{\n\t\tdocument: this.document,\n\t\t\"class\":\"tc-edit-bitmapeditor\",\n\t\teventListeners: [{\n\t\t\tname: \"touchstart\", handlerObject: this, handlerMethod: \"handleTouchStartEvent\"\n\t\t},{\n\t\t\tname: \"touchmove\", handlerObject: this, handlerMethod: \"handleTouchMoveEvent\"\n\t\t},{\n\t\t\tname: \"touchend\", handlerObject: this, handlerMethod: \"handleTouchEndEvent\"\n\t\t},{\n\t\t\tname: \"mousedown\", handlerObject: this, handlerMethod: \"handleMouseDownEvent\"\n\t\t},{\n\t\t\tname: \"mousemove\", handlerObject: this, handlerMethod: \"handleMouseMoveEvent\"\n\t\t},{\n\t\t\tname: \"mouseup\", handlerObject: this, handlerMethod: \"handleMouseUpEvent\"\n\t\t}]\n\t});\n\t// Set the width and height variables\n\tthis.setVariable(\"tv-bitmap-editor-width\",this.canvasDomNode.width + \"px\");\n\tthis.setVariable(\"tv-bitmap-editor-height\",this.canvasDomNode.height + \"px\");\n\t// Render toolbar child widgets\n\tthis.renderChildren(this.toolbarNode,null);\n\t// // Insert the elements into the DOM\n\tparent.insertBefore(this.canvasDomNode,nextSibling);\n\tthis.domNodes.push(this.canvasDomNode);\n\t// Load the image into the canvas\n\tif($tw.browser) {\n\t\tthis.loadCanvas();\n\t}\n\t// Add widget message listeners\n\tthis.addEventListeners([\n\t\t{type: \"tm-edit-bitmap-operation\", handler: \"handleEditBitmapOperationMessage\"}\n\t]);\n};\n\n/*\nHandle an edit bitmap operation message from the toolbar\n*/\nEditBitmapWidget.prototype.handleEditBitmapOperationMessage = function(event) {\n\t// Invoke the handler\n\tvar handler = this.editorOperations[event.param];\n\tif(handler) {\n\t\thandler.call(this,event);\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nEditBitmapWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.editTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nJust refresh the toolbar\n*/\nEditBitmapWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nSet the bitmap size variables and refresh the toolbar\n*/\nEditBitmapWidget.prototype.refreshToolbar = function() {\n\t// Set the width and height variables\n\tthis.setVariable(\"tv-bitmap-editor-width\",this.canvasDomNode.width + \"px\");\n\tthis.setVariable(\"tv-bitmap-editor-height\",this.canvasDomNode.height + \"px\");\n\t// Refresh each of our child widgets\n\t$tw.utils.each(this.children,function(childWidget) {\n\t\tchildWidget.refreshSelf();\n\t});\n};\n\nEditBitmapWidget.prototype.loadCanvas = function() {\n\tvar tiddler = this.wiki.getTiddler(this.editTitle),\n\t\tcurrImage = new Image();\n\t// Set up event handlers for loading the image\n\tvar self = this;\n\tcurrImage.onload = function() {\n\t\t// Copy the image to the on-screen canvas\n\t\tself.initCanvas(self.canvasDomNode,currImage.width,currImage.height,currImage);\n\t\t// And also copy the current bitmap to the off-screen canvas\n\t\tself.currCanvas = self.document.createElement(\"canvas\");\n\t\tself.initCanvas(self.currCanvas,currImage.width,currImage.height,currImage);\n\t\t// Set the width and height input boxes\n\t\tself.refreshToolbar();\n\t};\n\tcurrImage.onerror = function() {\n\t\t// Set the on-screen canvas size and clear it\n\t\tself.initCanvas(self.canvasDomNode,DEFAULT_IMAGE_WIDTH,DEFAULT_IMAGE_HEIGHT);\n\t\t// Set the off-screen canvas size and clear it\n\t\tself.currCanvas = self.document.createElement(\"canvas\");\n\t\tself.initCanvas(self.currCanvas,DEFAULT_IMAGE_WIDTH,DEFAULT_IMAGE_HEIGHT);\n\t\t// Set the width and height input boxes\n\t\tself.refreshToolbar();\n\t};\n\t// Get the current bitmap into an image object\n\tcurrImage.src = \"data:\" + tiddler.fields.type + \";base64,\" + tiddler.fields.text;\n};\n\nEditBitmapWidget.prototype.initCanvas = function(canvas,width,height,image) {\n\tcanvas.width = width;\n\tcanvas.height = height;\n\tvar ctx = canvas.getContext(\"2d\");\n\tif(image) {\n\t\tctx.drawImage(image,0,0);\n\t} else {\n\t\tctx.fillStyle = \"#fff\";\n\t\tctx.fillRect(0,0,canvas.width,canvas.height);\n\t}\n};\n\n/*\n** Change the size of the canvas, preserving the current image\n*/\nEditBitmapWidget.prototype.changeCanvasSize = function(newWidth,newHeight) {\n\t// Create and size a new canvas\n\tvar newCanvas = this.document.createElement(\"canvas\");\n\tthis.initCanvas(newCanvas,newWidth,newHeight);\n\t// Copy the old image\n\tvar ctx = newCanvas.getContext(\"2d\");\n\tctx.drawImage(this.currCanvas,0,0);\n\t// Set the new canvas as the current one\n\tthis.currCanvas = newCanvas;\n\t// Set the size of the onscreen canvas\n\tthis.canvasDomNode.width = newWidth;\n\tthis.canvasDomNode.height = newHeight;\n\t// Paint the onscreen canvas with the offscreen canvas\n\tctx = this.canvasDomNode.getContext(\"2d\");\n\tctx.drawImage(this.currCanvas,0,0);\n};\n\nEditBitmapWidget.prototype.handleTouchStartEvent = function(event) {\n\tthis.brushDown = true;\n\tthis.strokeStart(event.touches[0].clientX,event.touches[0].clientY);\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleTouchMoveEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.strokeMove(event.touches[0].clientX,event.touches[0].clientY);\n\t}\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleTouchEndEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.brushDown = false;\n\t\tthis.strokeEnd();\n\t}\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleMouseDownEvent = function(event) {\n\tthis.strokeStart(event.clientX,event.clientY);\n\tthis.brushDown = true;\n\tevent.preventDefault();\n\tevent.stopPropagation();\n\treturn false;\n};\n\nEditBitmapWidget.prototype.handleMouseMoveEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.strokeMove(event.clientX,event.clientY);\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\treturn false;\n\t}\n\treturn true;\n};\n\nEditBitmapWidget.prototype.handleMouseUpEvent = function(event) {\n\tif(this.brushDown) {\n\t\tthis.brushDown = false;\n\t\tthis.strokeEnd();\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\treturn false;\n\t}\n\treturn true;\n};\n\nEditBitmapWidget.prototype.adjustCoordinates = function(x,y) {\n\tvar canvasRect = this.canvasDomNode.getBoundingClientRect(),\n\t\tscale = this.canvasDomNode.width/canvasRect.width;\n\treturn {x: (x - canvasRect.left) * scale, y: (y - canvasRect.top) * scale};\n};\n\nEditBitmapWidget.prototype.strokeStart = function(x,y) {\n\t// Start off a new stroke\n\tthis.stroke = [this.adjustCoordinates(x,y)];\n};\n\nEditBitmapWidget.prototype.strokeMove = function(x,y) {\n\tvar ctx = this.canvasDomNode.getContext(\"2d\"),\n\t\tt;\n\t// Add the new position to the end of the stroke\n\tthis.stroke.push(this.adjustCoordinates(x,y));\n\t// Redraw the previous image\n\tctx.drawImage(this.currCanvas,0,0);\n\t// Render the stroke\n\tctx.globalAlpha = parseFloat(this.wiki.getTiddlerText(LINE_OPACITY_TITLE,\"1.0\"));\n\tctx.strokeStyle = this.wiki.getTiddlerText(LINE_COLOUR_TITLE,\"#ff0\");\n\tctx.lineWidth = parseFloat(this.wiki.getTiddlerText(LINE_WIDTH_TITLE,\"3\"));\n\tctx.lineCap = \"round\";\n\tctx.lineJoin = \"round\";\n\tctx.beginPath();\n\tctx.moveTo(this.stroke[0].x,this.stroke[0].y);\n\tfor(t=1; t<this.stroke.length-1; t++) {\n\t\tvar s1 = this.stroke[t],\n\t\t\ts2 = this.stroke[t-1],\n\t\t\ttx = (s1.x + s2.x)/2,\n\t\t\tty = (s1.y + s2.y)/2;\n\t\tctx.quadraticCurveTo(s2.x,s2.y,tx,ty);\n\t}\n\tctx.stroke();\n};\n\nEditBitmapWidget.prototype.strokeEnd = function() {\n\t// Copy the bitmap to the off-screen canvas\n\tvar ctx = this.currCanvas.getContext(\"2d\");\n\tctx.drawImage(this.canvasDomNode,0,0);\n\t// Save the image into the tiddler\n\tthis.saveChanges();\n};\n\nEditBitmapWidget.prototype.saveChanges = function() {\n\tvar tiddler = this.wiki.getTiddler(this.editTitle);\n\tif(tiddler) {\n\t\t// data URIs look like \"data:<type>;base64,<text>\"\n\t\tvar dataURL = this.canvasDomNode.toDataURL(tiddler.fields.type),\n\t\t\tposColon = dataURL.indexOf(\":\"),\n\t\t\tposSemiColon = dataURL.indexOf(\";\"),\n\t\t\tposComma = dataURL.indexOf(\",\"),\n\t\t\ttype = dataURL.substring(posColon+1,posSemiColon),\n\t\t\ttext = dataURL.substring(posComma+1);\n\t\tvar update = {type: type, text: text};\n\t\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getModificationFields(),tiddler,update,this.wiki.getCreationFields()));\n\t}\n};\n\nexports[\"edit-bitmap\"] = EditBitmapWidget;\n\n})();\n", "title": "$:/core/modules/widgets/edit-bitmap.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/edit-shortcut.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/edit-shortcut.js\ntype: application/javascript\nmodule-type: widget\n\nWidget to display an editable keyboard shortcut\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditShortcutWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditShortcutWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditShortcutWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.inputNode = this.document.createElement(\"input\");\n\t// Assign classes\n\tif(this.shortcutClass) {\n\t\tthis.inputNode.className = this.shortcutClass;\t\t\n\t}\n\t// Assign other attributes\n\tif(this.shortcutStyle) {\n\t\tthis.inputNode.setAttribute(\"style\",this.shortcutStyle);\n\t}\n\tif(this.shortcutTooltip) {\n\t\tthis.inputNode.setAttribute(\"title\",this.shortcutTooltip);\n\t}\n\tif(this.shortcutPlaceholder) {\n\t\tthis.inputNode.setAttribute(\"placeholder\",this.shortcutPlaceholder);\n\t}\n\tif(this.shortcutAriaLabel) {\n\t\tthis.inputNode.setAttribute(\"aria-label\",this.shortcutAriaLabel);\n\t}\n\t// Assign the current shortcut\n\tthis.updateInputNode();\n\t// Add event handlers\n\t$tw.utils.addEventListeners(this.inputNode,[\n\t\t{name: \"keydown\", handlerObject: this, handlerMethod: \"handleKeydownEvent\"}\n\t]);\n\t// Link into the DOM\n\tparent.insertBefore(this.inputNode,nextSibling);\n\tthis.domNodes.push(this.inputNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nEditShortcutWidget.prototype.execute = function() {\n\tthis.shortcutTiddler = this.getAttribute(\"tiddler\");\n\tthis.shortcutField = this.getAttribute(\"field\");\n\tthis.shortcutIndex = this.getAttribute(\"index\");\n\tthis.shortcutPlaceholder = this.getAttribute(\"placeholder\");\n\tthis.shortcutDefault = this.getAttribute(\"default\",\"\");\n\tthis.shortcutClass = this.getAttribute(\"class\");\n\tthis.shortcutStyle = this.getAttribute(\"style\");\n\tthis.shortcutTooltip = this.getAttribute(\"tooltip\");\n\tthis.shortcutAriaLabel = this.getAttribute(\"aria-label\");\n};\n\n/*\nUpdate the value of the input node\n*/\nEditShortcutWidget.prototype.updateInputNode = function() {\n\tif(this.shortcutField) {\n\t\tvar tiddler = this.wiki.getTiddler(this.shortcutTiddler);\n\t\tif(tiddler && $tw.utils.hop(tiddler.fields,this.shortcutField)) {\n\t\t\tthis.inputNode.value = tiddler.getFieldString(this.shortcutField);\n\t\t} else {\n\t\t\tthis.inputNode.value = this.shortcutDefault;\n\t\t}\n\t} else if(this.shortcutIndex) {\n\t\tthis.inputNode.value = this.wiki.extractTiddlerDataItem(this.shortcutTiddler,this.shortcutIndex,this.shortcutDefault);\n\t} else {\n\t\tthis.inputNode.value = this.wiki.getTiddlerText(this.shortcutTiddler,this.shortcutDefault);\n\t}\n};\n\n/*\nHandle a dom \"keydown\" event\n*/\nEditShortcutWidget.prototype.handleKeydownEvent = function(event) {\n\t// Ignore shift, ctrl, meta, alt\n\tif(event.keyCode && $tw.keyboardManager.getModifierKeys().indexOf(event.keyCode) === -1) {\n\t\t// Get the shortcut text representation\n\t\tvar value = $tw.keyboardManager.getPrintableShortcuts([{\n\t\t\tctrlKey: event.ctrlKey,\n\t\t\tshiftKey: event.shiftKey,\n\t\t\taltKey: event.altKey,\n\t\t\tmetaKey: event.metaKey,\n\t\t\tkeyCode: event.keyCode\n\t\t}]);\n\t\tif(value.length > 0) {\n\t\t\tthis.wiki.setText(this.shortcutTiddler,this.shortcutField,this.shortcutIndex,value[0]);\n\t\t}\n\t\t// Ignore the keydown if it was already handled\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\treturn true;\t\t\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget needed re-rendering\n*/\nEditShortcutWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.placeholder || changedAttributes[\"default\"] || changedAttributes[\"class\"] || changedAttributes.style || changedAttributes.tooltip || changedAttributes[\"aria-label\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else if(changedTiddlers[this.shortcutTiddler]) {\n\t\tthis.updateInputNode();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports[\"edit-shortcut\"] = EditShortcutWidget;\n\n})();\n", "title": "$:/core/modules/widgets/edit-shortcut.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/edit-text.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/edit-text.js\ntype: application/javascript\nmodule-type: widget\n\nEdit-text widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar editTextWidgetFactory = require(\"$:/core/modules/editor/factory.js\").editTextWidgetFactory,\n\tFramedEngine = require(\"$:/core/modules/editor/engines/framed.js\").FramedEngine,\n\tSimpleEngine = require(\"$:/core/modules/editor/engines/simple.js\").SimpleEngine;\n\nexports[\"edit-text\"] = editTextWidgetFactory(FramedEngine,SimpleEngine);\n\n})();\n", "title": "$:/core/modules/widgets/edit-text.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/edit.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/edit.js\ntype: application/javascript\nmodule-type: widget\n\nEdit widget is a meta-widget chooses the appropriate actual editting widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EditWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEditWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEditWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n// Mappings from content type to editor type are stored in tiddlers with this prefix\nvar EDITOR_MAPPING_PREFIX = \"$:/config/EditorTypeMappings/\";\n\n/*\nCompute the internal state of the widget\n*/\nEditWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.editTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.editField = this.getAttribute(\"field\",\"text\");\n\tthis.editIndex = this.getAttribute(\"index\");\n\tthis.editClass = this.getAttribute(\"class\");\n\tthis.editPlaceholder = this.getAttribute(\"placeholder\");\n\t// Choose the appropriate edit widget\n\tthis.editorType = this.getEditorType();\n\t// Make the child widgets\n\tthis.makeChildWidgets([{\n\t\ttype: \"edit-\" + this.editorType,\n\t\tattributes: {\n\t\t\ttiddler: {type: \"string\", value: this.editTitle},\n\t\t\tfield: {type: \"string\", value: this.editField},\n\t\t\tindex: {type: \"string\", value: this.editIndex},\n\t\t\t\"class\": {type: \"string\", value: this.editClass},\n\t\t\t\"placeholder\": {type: \"string\", value: this.editPlaceholder}\n\t\t},\n\t\tchildren: this.parseTreeNode.children\n\t}]);\n};\n\nEditWidget.prototype.getEditorType = function() {\n\t// Get the content type of the thing we're editing\n\tvar type;\n\tif(this.editField === \"text\") {\n\t\tvar tiddler = this.wiki.getTiddler(this.editTitle);\n\t\tif(tiddler) {\n\t\t\ttype = tiddler.fields.type;\n\t\t}\n\t}\n\ttype = type || \"text/vnd.tiddlywiki\";\n\tvar editorType = this.wiki.getTiddlerText(EDITOR_MAPPING_PREFIX + type);\n\tif(!editorType) {\n\t\tvar typeInfo = $tw.config.contentTypeInfo[type];\n\t\tif(typeInfo && typeInfo.encoding === \"base64\") {\n\t\t\teditorType = \"binary\";\n\t\t} else {\n\t\t\teditorType = \"text\";\n\t\t}\n\t}\n\treturn editorType;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nEditWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\t// Refresh if an attribute has changed, or the type associated with the target tiddler has changed\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nexports.edit = EditWidget;\n\n})();\n", "title": "$:/core/modules/widgets/edit.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/element.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/element.js\ntype: application/javascript\nmodule-type: widget\n\nElement widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ElementWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nElementWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nElementWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Neuter blacklisted elements\n\tvar tag = this.parseTreeNode.tag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"safe-\" + tag;\n\t}\n\tvar domNode = this.document.createElementNS(this.namespace,tag);\n\tthis.assignAttributes(domNode,{excludeEventAttributes: true});\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nElementWidget.prototype.execute = function() {\n\t// Select the namespace for the tag\n\tvar tagNamespaces = {\n\t\t\tsvg: \"http://www.w3.org/2000/svg\",\n\t\t\tmath: \"http://www.w3.org/1998/Math/MathML\",\n\t\t\tbody: \"http://www.w3.org/1999/xhtml\"\n\t\t};\n\tthis.namespace = tagNamespaces[this.parseTreeNode.tag];\n\tif(this.namespace) {\n\t\tthis.setVariable(\"namespace\",this.namespace);\n\t} else {\n\t\tthis.namespace = this.getVariable(\"namespace\",{defaultValue: \"http://www.w3.org/1999/xhtml\"});\n\t}\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nElementWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes(),\n\t\thasChangedAttributes = $tw.utils.count(changedAttributes) > 0;\n\tif(hasChangedAttributes) {\n\t\t// Update our attributes\n\t\tthis.assignAttributes(this.domNodes[0],{excludeEventAttributes: true});\n\t}\n\treturn this.refreshChildren(changedTiddlers) || hasChangedAttributes;\n};\n\nexports.element = ElementWidget;\n\n})();\n", "title": "$:/core/modules/widgets/element.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/encrypt.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/encrypt.js\ntype: application/javascript\nmodule-type: widget\n\nEncrypt widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EncryptWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEncryptWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEncryptWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar textNode = this.document.createTextNode(this.encryptedText);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nEncryptWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.filter = this.getAttribute(\"filter\",\"[!is[system]]\");\n\t// Encrypt the filtered tiddlers\n\tvar tiddlers = this.wiki.filterTiddlers(this.filter),\n\t\tjson = {},\n\t\tself = this;\n\t$tw.utils.each(tiddlers,function(title) {\n\t\tvar tiddler = self.wiki.getTiddler(title),\n\t\t\tjsonTiddler = {};\n\t\tfor(var f in tiddler.fields) {\n\t\t\tjsonTiddler[f] = tiddler.getFieldString(f);\n\t\t}\n\t\tjson[title] = jsonTiddler;\n\t});\n\tthis.encryptedText = $tw.utils.htmlEncode($tw.crypto.encrypt(JSON.stringify(json)));\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nEncryptWidget.prototype.refresh = function(changedTiddlers) {\n\t// We don't need to worry about refreshing because the encrypt widget isn't for interactive use\n\treturn false;\n};\n\nexports.encrypt = EncryptWidget;\n\n})();\n", "title": "$:/core/modules/widgets/encrypt.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/entity.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/entity.js\ntype: application/javascript\nmodule-type: widget\n\nHTML entity widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar EntityWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nEntityWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nEntityWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.execute();\n\tvar entityString = this.getAttribute(\"entity\",this.parseTreeNode.entity || \"\"),\n\t\ttextNode = this.document.createTextNode($tw.utils.entityDecode(entityString));\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nEntityWidget.prototype.execute = function() {\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nEntityWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.entity) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports.entity = EntityWidget;\n\n})();\n", "title": "$:/core/modules/widgets/entity.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/fieldmangler.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/fieldmangler.js\ntype: application/javascript\nmodule-type: widget\n\nField mangler widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar FieldManglerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.addEventListeners([\n\t\t{type: \"tm-remove-field\", handler: \"handleRemoveFieldEvent\"},\n\t\t{type: \"tm-add-field\", handler: \"handleAddFieldEvent\"},\n\t\t{type: \"tm-remove-tag\", handler: \"handleRemoveTagEvent\"},\n\t\t{type: \"tm-add-tag\", handler: \"handleAddTagEvent\"}\n\t]);\n};\n\n/*\nInherit from the base widget class\n*/\nFieldManglerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nFieldManglerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nFieldManglerWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.mangleTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nFieldManglerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nFieldManglerWidget.prototype.handleRemoveFieldEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle),\n\t\tdeletion = {};\n\tdeletion[event.param] = undefined;\n\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,deletion));\n\treturn true;\n};\n\nFieldManglerWidget.prototype.handleAddFieldEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle),\n\t\taddition = this.wiki.getModificationFields(),\n\t\thadInvalidFieldName = false,\n\t\taddField = function(name,value) {\n\t\t\tvar trimmedName = name.toLowerCase().trim();\n\t\t\tif(!$tw.utils.isValidFieldName(trimmedName)) {\n\t\t\t\tif(!hadInvalidFieldName) {\n\t\t\t\t\talert($tw.language.getString(\n\t\t\t\t\t\t\"InvalidFieldName\",\n\t\t\t\t\t\t{variables:\n\t\t\t\t\t\t\t{fieldName: trimmedName}\n\t\t\t\t\t\t}\n\t\t\t\t\t));\n\t\t\t\t\thadInvalidFieldName = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif(!value && tiddler) {\n\t\t\t\t\tvalue = tiddler.fields[trimmedName];\n\t\t\t\t}\n\t\t\t\taddition[trimmedName] = value || \"\";\n\t\t\t}\n\t\t\treturn;\n\t\t};\n\taddition.title = this.mangleTitle;\n\tif(typeof event.param === \"string\") {\n\t\taddField(event.param,\"\");\n\t}\n\tif(typeof event.paramObject === \"object\") {\n\t\tfor(var name in event.paramObject) {\n\t\t\taddField(name,event.paramObject[name]);\n\t\t}\n\t}\n\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,addition));\n\treturn true;\n};\n\nFieldManglerWidget.prototype.handleRemoveTagEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle);\n\tif(tiddler && tiddler.fields.tags) {\n\t\tvar p = tiddler.fields.tags.indexOf(event.param);\n\t\tif(p !== -1) {\n\t\t\tvar modification = this.wiki.getModificationFields();\n\t\t\tmodification.tags = (tiddler.fields.tags || []).slice(0);\n\t\t\tmodification.tags.splice(p,1);\n\t\t\tif(modification.tags.length === 0) {\n\t\t\t\tmodification.tags = undefined;\n\t\t\t}\n\t\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));\n\t\t}\n\t}\n\treturn true;\n};\n\nFieldManglerWidget.prototype.handleAddTagEvent = function(event) {\n\tvar tiddler = this.wiki.getTiddler(this.mangleTitle);\n\tif(tiddler && typeof event.param === \"string\") {\n\t\tvar tag = event.param.trim();\n\t\tif(tag !== \"\") {\n\t\t\tvar modification = this.wiki.getModificationFields();\n\t\t\tmodification.tags = (tiddler.fields.tags || []).slice(0);\n\t\t\t$tw.utils.pushTop(modification.tags,tag);\n\t\t\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));\t\t\t\n\t\t}\n\t} else if(typeof event.param === \"string\" && event.param.trim() !== \"\" && this.mangleTitle.trim() !== \"\") {\n\t\tvar tag = [];\n\t\ttag.push(event.param.trim());\n\t\tthis.wiki.addTiddler({title: this.mangleTitle, tags: tag});\t\t\n\t}\n\treturn true;\n};\n\nexports.fieldmangler = FieldManglerWidget;\n\n})();\n", "title": "$:/core/modules/widgets/fieldmangler.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/fields.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/fields.js\ntype: application/javascript\nmodule-type: widget\n\nFields widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar FieldsWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nFieldsWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nFieldsWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar textNode = this.document.createTextNode(this.text);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nFieldsWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.tiddlerTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.template = this.getAttribute(\"template\");\n\tthis.exclude = this.getAttribute(\"exclude\");\n\tthis.stripTitlePrefix = this.getAttribute(\"stripTitlePrefix\",\"no\") === \"yes\";\n\t// Get the value to display\n\tvar tiddler = this.wiki.getTiddler(this.tiddlerTitle);\n\t// Get the exclusion list\n\tvar exclude;\n\tif(this.exclude) {\n\t\texclude = this.exclude.split(\" \");\n\t} else {\n\t\texclude = [\"text\"]; \n\t}\n\t// Compose the template\n\tvar text = [];\n\tif(this.template && tiddler) {\n\t\tvar fields = [];\n\t\tfor(var fieldName in tiddler.fields) {\n\t\t\tif(exclude.indexOf(fieldName) === -1) {\n\t\t\t\tfields.push(fieldName);\n\t\t\t}\n\t\t}\n\t\tfields.sort();\n\t\tfor(var f=0; f<fields.length; f++) {\n\t\t\tfieldName = fields[f];\n\t\t\tif(exclude.indexOf(fieldName) === -1) {\n\t\t\t\tvar row = this.template,\n\t\t\t\t\tvalue = tiddler.getFieldString(fieldName);\n\t\t\t\tif(this.stripTitlePrefix && fieldName === \"title\") {\n\t\t\t\t\tvar reStrip = /^\\{[^\\}]+\\}(.+)/mg,\n\t\t\t\t\t\treMatch = reStrip.exec(value);\n\t\t\t\t\tif(reMatch) {\n\t\t\t\t\t\tvalue = reMatch[1];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\trow = $tw.utils.replaceString(row,\"$name$\",fieldName);\n\t\t\t\trow = $tw.utils.replaceString(row,\"$value$\",value);\n\t\t\t\trow = $tw.utils.replaceString(row,\"$encoded_value$\",$tw.utils.htmlEncode(value));\n\t\t\t\ttext.push(row);\n\t\t\t}\n\t\t}\n\t}\n\tthis.text = text.join(\"\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nFieldsWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.template || changedAttributes.exclude || changedAttributes.stripTitlePrefix || changedTiddlers[this.tiddlerTitle]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports.fields = FieldsWidget;\n\n})();\n", "title": "$:/core/modules/widgets/fields.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/image.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/image.js\ntype: application/javascript\nmodule-type: widget\n\nThe image widget displays an image referenced with an external URI or with a local tiddler title.\n\n```\n<$image src=\"TiddlerTitle\" width=\"320\" height=\"400\" class=\"classnames\">\n```\n\nThe image source can be the title of an existing tiddler or the URL of an external image.\n\nExternal images always generate an HTML `<img>` tag.\n\nTiddlers that have a _canonical_uri field generate an HTML `<img>` tag with the src attribute containing the URI.\n\nTiddlers that contain image data generate an HTML `<img>` tag with the src attribute containing a base64 representation of the image.\n\nTiddlers that contain wikitext could be rendered to a DIV of the usual size of a tiddler, and then transformed to the size requested.\n\nThe width and height attributes are interpreted as a number of pixels, and do not need to include the \"px\" suffix.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ImageWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nImageWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nImageWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create element\n\t// Determine what type of image it is\n\tvar tag = \"img\", src = \"\",\n\t\ttiddler = this.wiki.getTiddler(this.imageSource);\n\tif(!tiddler) {\n\t\t// The source isn't the title of a tiddler, so we'll assume it's a URL\n\t\tsrc = this.getVariable(\"tv-get-export-image-link\",{params: [{name: \"src\",value: this.imageSource}],defaultValue: this.imageSource});\n\t} else {\n\t\t// Check if it is an image tiddler\n\t\tif(this.wiki.isImageTiddler(this.imageSource)) {\n\t\t\tvar type = tiddler.fields.type,\n\t\t\t\ttext = tiddler.fields.text,\n\t\t\t\t_canonical_uri = tiddler.fields._canonical_uri;\n\t\t\t// If the tiddler has body text then it doesn't need to be lazily loaded\n\t\t\tif(text) {\n\t\t\t\t// Render the appropriate element for the image type\n\t\t\t\tswitch(type) {\n\t\t\t\t\tcase \"application/pdf\":\n\t\t\t\t\t\ttag = \"embed\";\n\t\t\t\t\t\tsrc = \"data:application/pdf;base64,\" + text;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"image/svg+xml\":\n\t\t\t\t\t\tsrc = \"data:image/svg+xml,\" + encodeURIComponent(text);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tsrc = \"data:\" + type + \";base64,\" + text;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else if(_canonical_uri) {\n\t\t\t\tswitch(type) {\n\t\t\t\t\tcase \"application/pdf\":\n\t\t\t\t\t\ttag = \"embed\";\n\t\t\t\t\t\tsrc = _canonical_uri;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"image/svg+xml\":\n\t\t\t\t\t\tsrc = _canonical_uri;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tsrc = _canonical_uri;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\t\n\t\t\t} else {\n\t\t\t\t// Just trigger loading of the tiddler\n\t\t\t\tthis.wiki.getTiddlerText(this.imageSource);\n\t\t\t}\n\t\t}\n\t}\n\t// Create the element and assign the attributes\n\tvar domNode = this.document.createElement(tag);\n\tdomNode.setAttribute(\"src\",src);\n\tif(this.imageClass) {\n\t\tdomNode.setAttribute(\"class\",this.imageClass);\t\t\n\t}\n\tif(this.imageWidth) {\n\t\tdomNode.setAttribute(\"width\",this.imageWidth);\n\t}\n\tif(this.imageHeight) {\n\t\tdomNode.setAttribute(\"height\",this.imageHeight);\n\t}\n\tif(this.imageTooltip) {\n\t\tdomNode.setAttribute(\"title\",this.imageTooltip);\t\t\n\t}\n\tif(this.imageAlt) {\n\t\tdomNode.setAttribute(\"alt\",this.imageAlt);\t\t\n\t}\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.domNodes.push(domNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nImageWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.imageSource = this.getAttribute(\"source\");\n\tthis.imageWidth = this.getAttribute(\"width\");\n\tthis.imageHeight = this.getAttribute(\"height\");\n\tthis.imageClass = this.getAttribute(\"class\");\n\tthis.imageTooltip = this.getAttribute(\"tooltip\");\n\tthis.imageAlt = this.getAttribute(\"alt\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nImageWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.source || changedAttributes.width || changedAttributes.height || changedAttributes[\"class\"] || changedAttributes.tooltip || changedTiddlers[this.imageSource]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\t\n\t}\n};\n\nexports.image = ImageWidget;\n\n})();\n", "title": "$:/core/modules/widgets/image.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/importvariables.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/importvariables.js\ntype: application/javascript\nmodule-type: widget\n\nImport variable definitions from other tiddlers\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ImportVariablesWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nImportVariablesWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nImportVariablesWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nImportVariablesWidget.prototype.execute = function(tiddlerList) {\n\tvar self = this;\n\t// Get our parameters\n\tthis.filter = this.getAttribute(\"filter\");\n\t// Compute the filter\n\tthis.tiddlerList = tiddlerList || this.wiki.filterTiddlers(this.filter,this);\n\t// Accumulate the <$set> widgets from each tiddler\n\tvar widgetStackStart,widgetStackEnd;\n\tfunction addWidgetNode(widgetNode) {\n\t\tif(widgetNode) {\n\t\t\tif(!widgetStackStart && !widgetStackEnd) {\n\t\t\t\twidgetStackStart = widgetNode;\n\t\t\t\twidgetStackEnd = widgetNode;\n\t\t\t} else {\n\t\t\t\twidgetStackEnd.children = [widgetNode];\n\t\t\t\twidgetStackEnd = widgetNode;\n\t\t\t}\n\t\t}\n\t}\n\t$tw.utils.each(this.tiddlerList,function(title) {\n\t\tvar parser = self.wiki.parseTiddler(title);\n\t\tif(parser) {\n\t\t\tvar parseTreeNode = parser.tree[0];\n\t\t\twhile(parseTreeNode && parseTreeNode.type === \"set\") {\n\t\t\t\taddWidgetNode({\n\t\t\t\t\ttype: \"set\",\n\t\t\t\t\tattributes: parseTreeNode.attributes,\n\t\t\t\t\tparams: parseTreeNode.params\n\t\t\t\t});\n\t\t\t\tparseTreeNode = parseTreeNode.children[0];\n\t\t\t}\n\t\t} \n\t});\n\t// Add our own children to the end of the pile\n\tvar parseTreeNodes;\n\tif(widgetStackStart && widgetStackEnd) {\n\t\tparseTreeNodes = [widgetStackStart];\n\t\twidgetStackEnd.children = this.parseTreeNode.children;\n\t} else {\n\t\tparseTreeNodes = this.parseTreeNode.children;\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets(parseTreeNodes);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nImportVariablesWidget.prototype.refresh = function(changedTiddlers) {\n\t// Recompute our attributes and the filter list\n\tvar changedAttributes = this.computeAttributes(),\n\t\ttiddlerList = this.wiki.filterTiddlers(this.getAttribute(\"filter\"),this);\n\t// Refresh if the filter has changed, or the list of tiddlers has changed, or any of the tiddlers in the list has changed\n\tfunction haveListedTiddlersChanged() {\n\t\tvar changed = false;\n\t\ttiddlerList.forEach(function(title) {\n\t\t\tif(changedTiddlers[title]) {\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t});\n\t\treturn changed;\n\t}\n\tif(changedAttributes.filter || !$tw.utils.isArrayEqual(this.tiddlerList,tiddlerList) || haveListedTiddlersChanged()) {\n\t\t// Compute the filter\n\t\tthis.removeChildDomNodes();\n\t\tthis.execute(tiddlerList);\n\t\tthis.renderChildren(this.parentDomNode,this.findNextSiblingDomNode());\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nexports.importvariables = ImportVariablesWidget;\n\n})();\n", "title": "$:/core/modules/widgets/importvariables.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/keyboard.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/keyboard.js\ntype: application/javascript\nmodule-type: widget\n\nKeyboard shortcut widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar KeyboardWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nKeyboardWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nKeyboardWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar tag = this.parseTreeNode.isBlock ? \"div\" : \"span\";\n\tif(this.tag && $tw.config.htmlUnsafeElements.indexOf(this.tag) === -1) {\n\t\ttag = this.tag;\n\t}\n\t// Create element\n\tvar domNode = this.document.createElement(tag);\n\t// Assign classes\n\tvar classes = (this[\"class\"] || \"\").split(\" \");\n\tclasses.push(\"tc-keyboard\");\n\tdomNode.className = classes.join(\" \");\n\t// Add a keyboard event handler\n\tdomNode.addEventListener(\"keydown\",function (event) {\n\t\tif($tw.keyboardManager.checkKeyDescriptors(event,self.keyInfoArray)) {\n\t\t\tself.invokeActions(self,event);\n\t\t\tif(self.actions) {\n\t\t\t\tself.invokeActionString(self.actions,self,event);\n\t\t\t}\n\t\t\tself.dispatchMessage(event);\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},false);\n\t// Insert element\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\nKeyboardWidget.prototype.dispatchMessage = function(event) {\n\tthis.dispatchEvent({type: this.message, param: this.param, tiddlerTitle: this.getVariable(\"currentTiddler\")});\n};\n\n/*\nCompute the internal state of the widget\n*/\nKeyboardWidget.prototype.execute = function() {\n\t// Get attributes\n\tthis.actions = this.getAttribute(\"actions\");\n\tthis.message = this.getAttribute(\"message\");\n\tthis.param = this.getAttribute(\"param\");\n\tthis.key = this.getAttribute(\"key\");\n\tthis.tag = this.getAttribute(\"tag\");\n\tthis.keyInfoArray = $tw.keyboardManager.parseKeyDescriptors(this.key);\n\tthis[\"class\"] = this.getAttribute(\"class\");\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nKeyboardWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.message || changedAttributes.param || changedAttributes.key || changedAttributes[\"class\"] || changedAttributes.tag) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.keyboard = KeyboardWidget;\n\n})();\n", "title": "$:/core/modules/widgets/keyboard.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/link.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/link.js\ntype: application/javascript\nmodule-type: widget\n\nLink widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\nvar MISSING_LINK_CONFIG_TITLE = \"$:/config/MissingLinks\";\n\nvar LinkWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nLinkWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nLinkWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Get the value of the tv-wikilinks configuration macro\n\tvar wikiLinksMacro = this.getVariable(\"tv-wikilinks\"),\n\t\tuseWikiLinks = wikiLinksMacro ? (wikiLinksMacro.trim() !== \"no\") : true,\n\t\tmissingLinksEnabled = !(this.hideMissingLinks && this.isMissing && !this.isShadow);\n\t// Render the link if required\n\tif(useWikiLinks && missingLinksEnabled) {\n\t\tthis.renderLink(parent,nextSibling);\n\t} else {\n\t\t// Just insert the link text\n\t\tvar domNode = this.document.createElement(\"span\");\n\t\tparent.insertBefore(domNode,nextSibling);\n\t\tthis.renderChildren(domNode,null);\n\t\tthis.domNodes.push(domNode);\n\t}\n};\n\n/*\nRender this widget into the DOM\n*/\nLinkWidget.prototype.renderLink = function(parent,nextSibling) {\n\tvar self = this;\n\t// Sanitise the specified tag\n\tvar tag = this.linkTag;\n\tif($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {\n\t\ttag = \"a\";\n\t}\n\t// Create our element\n\tvar domNode = this.document.createElement(tag);\n\t// Assign classes\n\tvar classes = [];\n\tif(this.linkClasses) {\n\t\tclasses.push(this.linkClasses);\n\t}\n\tclasses.push(\"tc-tiddlylink\");\n\tif(this.isShadow) {\n\t\tclasses.push(\"tc-tiddlylink-shadow\");\n\t}\n\tif(this.isMissing && !this.isShadow) {\n\t\tclasses.push(\"tc-tiddlylink-missing\");\n\t} else {\n\t\tif(!this.isMissing) {\n\t\t\tclasses.push(\"tc-tiddlylink-resolves\");\n\t\t}\n\t}\n\tdomNode.setAttribute(\"class\",classes.join(\" \"));\n\t// Set an href\n\tvar wikiLinkTemplateMacro = this.getVariable(\"tv-wikilink-template\"),\n\t\twikiLinkTemplate = wikiLinkTemplateMacro ? wikiLinkTemplateMacro.trim() : \"#$uri_encoded$\",\n\t\twikiLinkText = $tw.utils.replaceString(wikiLinkTemplate,\"$uri_encoded$\",encodeURIComponent(this.to));\n\twikiLinkText = $tw.utils.replaceString(wikiLinkText,\"$uri_doubleencoded$\",encodeURIComponent(encodeURIComponent(this.to)));\n\twikiLinkText = this.getVariable(\"tv-get-export-link\",{params: [{name: \"to\",value: this.to}],defaultValue: wikiLinkText});\n\tif(tag === \"a\") {\n\t\tdomNode.setAttribute(\"href\",wikiLinkText);\n\t}\n\tif(this.tabIndex) {\n\t\tdomNode.setAttribute(\"tabindex\",this.tabIndex);\n\t}\n\t// Set the tooltip\n\t// HACK: Performance issues with re-parsing the tooltip prevent us defaulting the tooltip to \"<$transclude field='tooltip'><$transclude field='title'/></$transclude>\"\n\tvar tooltipWikiText = this.tooltip || this.getVariable(\"tv-wikilink-tooltip\");\n\tif(tooltipWikiText) {\n\t\tvar tooltipText = this.wiki.renderText(\"text/plain\",\"text/vnd.tiddlywiki\",tooltipWikiText,{\n\t\t\t\tparseAsInline: true,\n\t\t\t\tvariables: {\n\t\t\t\t\tcurrentTiddler: this.to\n\t\t\t\t},\n\t\t\t\tparentWidget: this\n\t\t\t});\n\t\tdomNode.setAttribute(\"title\",tooltipText);\n\t}\n\tif(this[\"aria-label\"]) {\n\t\tdomNode.setAttribute(\"aria-label\",this[\"aria-label\"]);\n\t}\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(domNode,[\n\t\t{name: \"click\", handlerObject: this, handlerMethod: \"handleClickEvent\"},\n\t]);\n\t// Make the link draggable if required\n\tif(this.draggable === \"yes\") {\n\t\t$tw.utils.makeDraggable({\n\t\t\tdomNode: domNode,\n\t\t\tdragTiddlerFn: function() {return self.to;},\n\t\t\twidget: this\n\t\t});\n\t}\n\t// Insert the link into the DOM and render any children\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\nLinkWidget.prototype.handleClickEvent = function(event) {\n\t// Send the click on its way as a navigate event\n\tvar bounds = this.domNodes[0].getBoundingClientRect();\n\tthis.dispatchEvent({\n\t\ttype: \"tm-navigate\",\n\t\tnavigateTo: this.to,\n\t\tnavigateFromTitle: this.getVariable(\"storyTiddler\"),\n\t\tnavigateFromNode: this,\n\t\tnavigateFromClientRect: { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height\n\t\t},\n\t\tnavigateSuppressNavigation: event.metaKey || event.ctrlKey || (event.button === 1)\n\t});\n\tif(this.domNodes[0].hasAttribute(\"href\")) {\n\t\tevent.preventDefault();\n\t}\n\tevent.stopPropagation();\n\treturn false;\n};\n\n/*\nCompute the internal state of the widget\n*/\nLinkWidget.prototype.execute = function() {\n\t// Pick up our attributes\n\tthis.to = this.getAttribute(\"to\",this.getVariable(\"currentTiddler\"));\n\tthis.tooltip = this.getAttribute(\"tooltip\");\n\tthis[\"aria-label\"] = this.getAttribute(\"aria-label\");\n\tthis.linkClasses = this.getAttribute(\"class\");\n\tthis.tabIndex = this.getAttribute(\"tabindex\");\n\tthis.draggable = this.getAttribute(\"draggable\",\"yes\");\n\tthis.linkTag = this.getAttribute(\"tag\",\"a\");\n\t// Determine the link characteristics\n\tthis.isMissing = !this.wiki.tiddlerExists(this.to);\n\tthis.isShadow = this.wiki.isShadowTiddler(this.to);\n\tthis.hideMissingLinks = ($tw.wiki.getTiddlerText(MISSING_LINK_CONFIG_TITLE,\"yes\") === \"no\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nLinkWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.to || changedTiddlers[this.to] || changedAttributes[\"aria-label\"] || changedAttributes.tooltip || changedTiddlers[MISSING_LINK_CONFIG_TITLE]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.link = LinkWidget;\n\n})();\n", "title": "$:/core/modules/widgets/link.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/linkcatcher.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/linkcatcher.js\ntype: application/javascript\nmodule-type: widget\n\nLinkcatcher widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar LinkCatcherWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.addEventListeners([\n\t\t{type: \"tm-navigate\", handler: \"handleNavigateEvent\"}\n\t]);\n};\n\n/*\nInherit from the base widget class\n*/\nLinkCatcherWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nLinkCatcherWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nLinkCatcherWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.catchTo = this.getAttribute(\"to\");\n\tthis.catchMessage = this.getAttribute(\"message\");\n\tthis.catchSet = this.getAttribute(\"set\");\n\tthis.catchSetTo = this.getAttribute(\"setTo\");\n\tthis.catchActions = this.getAttribute(\"actions\");\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nLinkCatcherWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.to || changedAttributes.message || changedAttributes.set || changedAttributes.setTo) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\n/*\nHandle a tm-navigate event\n*/\nLinkCatcherWidget.prototype.handleNavigateEvent = function(event) {\n\tif(this.catchTo) {\n\t\tthis.wiki.setTextReference(this.catchTo,event.navigateTo,this.getVariable(\"currentTiddler\"));\n\t}\n\tif(this.catchMessage && this.parentWidget) {\n\t\tthis.parentWidget.dispatchEvent({\n\t\t\ttype: this.catchMessage,\n\t\t\tparam: event.navigateTo,\n\t\t\tnavigateTo: event.navigateTo\n\t\t});\n\t}\n\tif(this.catchSet) {\n\t\tvar tiddler = this.wiki.getTiddler(this.catchSet);\n\t\tthis.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: this.catchSet, text: this.catchSetTo}));\n\t}\n\tif(this.catchActions) {\n\t\tthis.invokeActionString(this.catchActions,this);\n\t}\n\treturn false;\n};\n\nexports.linkcatcher = LinkCatcherWidget;\n\n})();\n", "title": "$:/core/modules/widgets/linkcatcher.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/list.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/list.js\ntype: application/javascript\nmodule-type: widget\n\nList and list item widgets\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\n/*\nThe list widget creates list element sub-widgets that reach back into the list widget for their configuration\n*/\n\nvar ListWidget = function(parseTreeNode,options) {\n\t// Initialise the storyviews if they've not been done already\n\tif(!this.storyViews) {\n\t\tListWidget.prototype.storyViews = {};\n\t\t$tw.modules.applyMethods(\"storyview\",this.storyViews);\n\t}\n\t// Main initialisation inherited from widget.js\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nListWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nListWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n\t// Construct the storyview\n\tvar StoryView = this.storyViews[this.storyViewName];\n\tif(this.storyViewName && !StoryView) {\n\t\tStoryView = this.storyViews[\"classic\"];\n\t}\n\tif(StoryView && !this.document.isTiddlyWikiFakeDom) {\n\t\tthis.storyview = new StoryView(this);\n\t} else {\n\t\tthis.storyview = null;\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nListWidget.prototype.execute = function() {\n\t// Get our attributes\n\tthis.template = this.getAttribute(\"template\");\n\tthis.editTemplate = this.getAttribute(\"editTemplate\");\n\tthis.variableName = this.getAttribute(\"variable\",\"currentTiddler\");\n\tthis.storyViewName = this.getAttribute(\"storyview\");\n\tthis.historyTitle = this.getAttribute(\"history\");\n\t// Compose the list elements\n\tthis.list = this.getTiddlerList();\n\tvar members = [],\n\t\tself = this;\n\t// Check for an empty list\n\tif(this.list.length === 0) {\n\t\tmembers = this.getEmptyMessage();\n\t} else {\n\t\t$tw.utils.each(this.list,function(title,index) {\n\t\t\tmembers.push(self.makeItemTemplate(title));\n\t\t});\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets(members);\n\t// Clear the last history\n\tthis.history = [];\n};\n\nListWidget.prototype.getTiddlerList = function() {\n\tvar defaultFilter = \"[!is[system]sort[title]]\";\n\treturn this.wiki.filterTiddlers(this.getAttribute(\"filter\",defaultFilter),this);\n};\n\nListWidget.prototype.getEmptyMessage = function() {\n\tvar emptyMessage = this.getAttribute(\"emptyMessage\",\"\"),\n\t\tparser = this.wiki.parseText(\"text/vnd.tiddlywiki\",emptyMessage,{parseAsInline: true});\n\tif(parser) {\n\t\treturn parser.tree;\n\t} else {\n\t\treturn [];\n\t}\n};\n\n/*\nCompose the template for a list item\n*/\nListWidget.prototype.makeItemTemplate = function(title) {\n\t// Check if the tiddler is a draft\n\tvar tiddler = this.wiki.getTiddler(title),\n\t\tisDraft = tiddler && tiddler.hasField(\"draft.of\"),\n\t\ttemplate = this.template,\n\t\ttemplateTree;\n\tif(isDraft && this.editTemplate) {\n\t\ttemplate = this.editTemplate;\n\t}\n\t// Compose the transclusion of the template\n\tif(template) {\n\t\ttemplateTree = [{type: \"transclude\", attributes: {tiddler: {type: \"string\", value: template}}}];\n\t} else {\n\t\tif(this.parseTreeNode.children && this.parseTreeNode.children.length > 0) {\n\t\t\ttemplateTree = this.parseTreeNode.children;\n\t\t} else {\n\t\t\t// Default template is a link to the title\n\t\t\ttemplateTree = [{type: \"element\", tag: this.parseTreeNode.isBlock ? \"div\" : \"span\", children: [{type: \"link\", attributes: {to: {type: \"string\", value: title}}, children: [\n\t\t\t\t\t{type: \"text\", text: title}\n\t\t\t]}]}];\n\t\t}\n\t}\n\t// Return the list item\n\treturn {type: \"listitem\", itemTitle: title, variableName: this.variableName, children: templateTree};\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nListWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes(),\n\t\tresult;\n\t// Call the storyview\n\tif(this.storyview && this.storyview.refreshStart) {\n\t\tthis.storyview.refreshStart(changedTiddlers,changedAttributes);\n\t}\n\t// Completely refresh if any of our attributes have changed\n\tif(changedAttributes.filter || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.emptyMessage || changedAttributes.storyview || changedAttributes.history) {\n\t\tthis.refreshSelf();\n\t\tresult = true;\n\t} else {\n\t\t// Handle any changes to the list\n\t\tresult = this.handleListChanges(changedTiddlers);\n\t\t// Handle any changes to the history stack\n\t\tif(this.historyTitle && changedTiddlers[this.historyTitle]) {\n\t\t\tthis.handleHistoryChanges();\n\t\t}\n\t}\n\t// Call the storyview\n\tif(this.storyview && this.storyview.refreshEnd) {\n\t\tthis.storyview.refreshEnd(changedTiddlers,changedAttributes);\n\t}\n\treturn result;\n};\n\n/*\nHandle any changes to the history list\n*/\nListWidget.prototype.handleHistoryChanges = function() {\n\t// Get the history data\n\tvar newHistory = this.wiki.getTiddlerDataCached(this.historyTitle,[]);\n\t// Ignore any entries of the history that match the previous history\n\tvar entry = 0;\n\twhile(entry < newHistory.length && entry < this.history.length && newHistory[entry].title === this.history[entry].title) {\n\t\tentry++;\n\t}\n\t// Navigate forwards to each of the new tiddlers\n\twhile(entry < newHistory.length) {\n\t\tif(this.storyview && this.storyview.navigateTo) {\n\t\t\tthis.storyview.navigateTo(newHistory[entry]);\n\t\t}\n\t\tentry++;\n\t}\n\t// Update the history\n\tthis.history = newHistory;\n};\n\n/*\nProcess any changes to the list\n*/\nListWidget.prototype.handleListChanges = function(changedTiddlers) {\n\t// Get the new list\n\tvar prevList = this.list;\n\tthis.list = this.getTiddlerList();\n\t// Check for an empty list\n\tif(this.list.length === 0) {\n\t\t// Check if it was empty before\n\t\tif(prevList.length === 0) {\n\t\t\t// If so, just refresh the empty message\n\t\t\treturn this.refreshChildren(changedTiddlers);\n\t\t} else {\n\t\t\t// Replace the previous content with the empty message\n\t\t\tfor(t=this.children.length-1; t>=0; t--) {\n\t\t\t\tthis.removeListItem(t);\n\t\t\t}\n\t\t\tvar nextSibling = this.findNextSiblingDomNode();\n\t\t\tthis.makeChildWidgets(this.getEmptyMessage());\n\t\t\tthis.renderChildren(this.parentDomNode,nextSibling);\n\t\t\treturn true;\n\t\t}\n\t} else {\n\t\t// If the list was empty then we need to remove the empty message\n\t\tif(prevList.length === 0) {\n\t\t\tthis.removeChildDomNodes();\n\t\t\tthis.children = [];\n\t\t}\n\t\t// Cycle through the list, inserting and removing list items as needed\n\t\tvar hasRefreshed = false;\n\t\tfor(var t=0; t<this.list.length; t++) {\n\t\t\tvar index = this.findListItem(t,this.list[t]);\n\t\t\tif(index === undefined) {\n\t\t\t\t// The list item must be inserted\n\t\t\t\tthis.insertListItem(t,this.list[t]);\n\t\t\t\thasRefreshed = true;\n\t\t\t} else {\n\t\t\t\t// There are intervening list items that must be removed\n\t\t\t\tfor(var n=index-1; n>=t; n--) {\n\t\t\t\t\tthis.removeListItem(n);\n\t\t\t\t\thasRefreshed = true;\n\t\t\t\t}\n\t\t\t\t// Refresh the item we're reusing\n\t\t\t\tvar refreshed = this.children[t].refresh(changedTiddlers);\n\t\t\t\thasRefreshed = hasRefreshed || refreshed;\n\t\t\t}\n\t\t}\n\t\t// Remove any left over items\n\t\tfor(t=this.children.length-1; t>=this.list.length; t--) {\n\t\t\tthis.removeListItem(t);\n\t\t\thasRefreshed = true;\n\t\t}\n\t\treturn hasRefreshed;\n\t}\n};\n\n/*\nFind the list item with a given title, starting from a specified position\n*/\nListWidget.prototype.findListItem = function(startIndex,title) {\n\twhile(startIndex < this.children.length) {\n\t\tif(this.children[startIndex].parseTreeNode.itemTitle === title) {\n\t\t\treturn startIndex;\n\t\t}\n\t\tstartIndex++;\n\t}\n\treturn undefined;\n};\n\n/*\nInsert a new list item at the specified index\n*/\nListWidget.prototype.insertListItem = function(index,title) {\n\t// Create, insert and render the new child widgets\n\tvar widget = this.makeChildWidget(this.makeItemTemplate(title));\n\twidget.parentDomNode = this.parentDomNode; // Hack to enable findNextSiblingDomNode() to work\n\tthis.children.splice(index,0,widget);\n\tvar nextSibling = widget.findNextSiblingDomNode();\n\twidget.render(this.parentDomNode,nextSibling);\n\t// Animate the insertion if required\n\tif(this.storyview && this.storyview.insert) {\n\t\tthis.storyview.insert(widget);\n\t}\n\treturn true;\n};\n\n/*\nRemove the specified list item\n*/\nListWidget.prototype.removeListItem = function(index) {\n\tvar widget = this.children[index];\n\t// Animate the removal if required\n\tif(this.storyview && this.storyview.remove) {\n\t\tthis.storyview.remove(widget);\n\t} else {\n\t\twidget.removeChildDomNodes();\n\t}\n\t// Remove the child widget\n\tthis.children.splice(index,1);\n};\n\nexports.list = ListWidget;\n\nvar ListItemWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nListItemWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nListItemWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nListItemWidget.prototype.execute = function() {\n\t// Set the current list item title\n\tthis.setVariable(this.parseTreeNode.variableName,this.parseTreeNode.itemTitle);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nListItemWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.listitem = ListItemWidget;\n\n})();", "title": "$:/core/modules/widgets/list.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/macrocall.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/macrocall.js\ntype: application/javascript\nmodule-type: widget\n\nMacrocall widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar MacroCallWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nMacroCallWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nMacroCallWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nMacroCallWidget.prototype.execute = function() {\n\t// Get the parse type if specified\n\tthis.parseType = this.getAttribute(\"$type\",\"text/vnd.tiddlywiki\");\n\tthis.renderOutput = this.getAttribute(\"$output\",\"text/html\");\n\t// Merge together the parameters specified in the parse tree with the specified attributes\n\tvar params = this.parseTreeNode.params ? this.parseTreeNode.params.slice(0) : [];\n\t$tw.utils.each(this.attributes,function(attribute,name) {\n\t\tif(name.charAt(0) !== \"$\") {\n\t\t\tparams.push({name: name, value: attribute});\t\t\t\n\t\t}\n\t});\n\t// Get the macro value\n\tvar text = this.getVariable(this.parseTreeNode.name || this.getAttribute(\"$name\"),{params: params}),\n\t\tparseTreeNodes;\n\t// Are we rendering to HTML?\n\tif(this.renderOutput === \"text/html\") {\n\t\t// If so we'll return the parsed macro\n\t\tvar parser = this.wiki.parseText(this.parseType,text,\n\t\t\t\t\t\t\t{parseAsInline: !this.parseTreeNode.isBlock});\n\t\tparseTreeNodes = parser ? parser.tree : [];\n\t} else {\n\t\t// Otherwise, we'll render the text\n\t\tvar plainText = this.wiki.renderText(\"text/plain\",this.parseType,text,{parentWidget: this});\n\t\tparseTreeNodes = [{type: \"text\", text: plainText}];\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets(parseTreeNodes);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nMacroCallWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif($tw.utils.count(changedAttributes) > 0) {\n\t\t// Rerender ourselves\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.macrocall = MacroCallWidget;\n\n})();\n", "title": "$:/core/modules/widgets/macrocall.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/navigator.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/navigator.js\ntype: application/javascript\nmodule-type: widget\n\nNavigator widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar IMPORT_TITLE = \"$:/Import\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar NavigatorWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.addEventListeners([\n\t\t{type: \"tm-navigate\", handler: \"handleNavigateEvent\"},\n\t\t{type: \"tm-edit-tiddler\", handler: \"handleEditTiddlerEvent\"},\n\t\t{type: \"tm-delete-tiddler\", handler: \"handleDeleteTiddlerEvent\"},\n\t\t{type: \"tm-save-tiddler\", handler: \"handleSaveTiddlerEvent\"},\n\t\t{type: \"tm-cancel-tiddler\", handler: \"handleCancelTiddlerEvent\"},\n\t\t{type: \"tm-close-tiddler\", handler: \"handleCloseTiddlerEvent\"},\n\t\t{type: \"tm-close-all-tiddlers\", handler: \"handleCloseAllTiddlersEvent\"},\n\t\t{type: \"tm-close-other-tiddlers\", handler: \"handleCloseOtherTiddlersEvent\"},\n\t\t{type: \"tm-new-tiddler\", handler: \"handleNewTiddlerEvent\"},\n\t\t{type: \"tm-import-tiddlers\", handler: \"handleImportTiddlersEvent\"},\n\t\t{type: \"tm-perform-import\", handler: \"handlePerformImportEvent\"},\n\t\t{type: \"tm-fold-tiddler\", handler: \"handleFoldTiddlerEvent\"},\n\t\t{type: \"tm-fold-other-tiddlers\", handler: \"handleFoldOtherTiddlersEvent\"},\n\t\t{type: \"tm-fold-all-tiddlers\", handler: \"handleFoldAllTiddlersEvent\"},\n\t\t{type: \"tm-unfold-all-tiddlers\", handler: \"handleUnfoldAllTiddlersEvent\"},\n\t\t{type: \"tm-rename-tiddler\", handler: \"handleRenameTiddlerEvent\"}\n\t]);\n};\n\n/*\nInherit from the base widget class\n*/\nNavigatorWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nNavigatorWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nNavigatorWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.storyTitle = this.getAttribute(\"story\");\n\tthis.historyTitle = this.getAttribute(\"history\");\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nNavigatorWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.story || changedAttributes.history) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nNavigatorWidget.prototype.getStoryList = function() {\n\treturn this.storyTitle ? this.wiki.getTiddlerList(this.storyTitle) : null;\n};\n\nNavigatorWidget.prototype.saveStoryList = function(storyList) {\n\tvar storyTiddler = this.wiki.getTiddler(this.storyTitle);\n\tthis.wiki.addTiddler(new $tw.Tiddler(\n\t\t{title: this.storyTitle},\n\t\tstoryTiddler,\n\t\t{list: storyList}\n\t));\n};\n\nNavigatorWidget.prototype.removeTitleFromStory = function(storyList,title) {\n\tvar p = storyList.indexOf(title);\n\twhile(p !== -1) {\n\t\tstoryList.splice(p,1);\n\t\tp = storyList.indexOf(title);\n\t}\n};\n\nNavigatorWidget.prototype.replaceFirstTitleInStory = function(storyList,oldTitle,newTitle) {\n\tvar pos = storyList.indexOf(oldTitle);\n\tif(pos !== -1) {\n\t\tstoryList[pos] = newTitle;\n\t\tdo {\n\t\t\tpos = storyList.indexOf(oldTitle,pos + 1);\n\t\t\tif(pos !== -1) {\n\t\t\t\tstoryList.splice(pos,1);\n\t\t\t}\n\t\t} while(pos !== -1);\n\t} else {\n\t\tstoryList.splice(0,0,newTitle);\n\t}\n};\n\nNavigatorWidget.prototype.addToStory = function(title,fromTitle) {\n\tvar storyList = this.getStoryList();\n\t// Quit if we cannot get hold of the story list\n\tif(!storyList) {\n\t\treturn;\n\t}\n\t// See if the tiddler is already there\n\tvar slot = storyList.indexOf(title);\n\t// Quit if it already exists in the story river\n\tif(slot >= 0) {\n\t\treturn;\n\t}\n\t// First we try to find the position of the story element we navigated from\n\tvar fromIndex = storyList.indexOf(fromTitle);\n\tif(fromIndex >= 0) {\n\t\t// The tiddler is added from inside the river\n\t\t// Determine where to insert the tiddler; Fallback is \"below\"\n\t\tswitch(this.getAttribute(\"openLinkFromInsideRiver\",\"below\")) {\n\t\t\tcase \"top\":\n\t\t\t\tslot = 0;\n\t\t\t\tbreak;\n\t\t\tcase \"bottom\":\n\t\t\t\tslot = storyList.length;\n\t\t\t\tbreak;\n\t\t\tcase \"above\":\n\t\t\t\tslot = fromIndex;\n\t\t\t\tbreak;\n\t\t\tcase \"below\": // Intentional fall-through\n\t\t\tdefault:\n\t\t\t\tslot = fromIndex + 1;\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\t// The tiddler is opened from outside the river. Determine where to insert the tiddler; default is \"top\"\n\t\tif(this.getAttribute(\"openLinkFromOutsideRiver\",\"top\") === \"bottom\") {\n\t\t\t// Insert at bottom\n\t\t\tslot = storyList.length;\n\t\t} else {\n\t\t\t// Insert at top\n\t\t\tslot = 0;\n\t\t}\n\t}\n\t// Add the tiddler\n\tstoryList.splice(slot,0,title);\n\t// Save the story\n\tthis.saveStoryList(storyList);\n};\n\n/*\nAdd a new record to the top of the history stack\ntitle: a title string or an array of title strings\nfromPageRect: page coordinates of the origin of the navigation\n*/\nNavigatorWidget.prototype.addToHistory = function(title,fromPageRect) {\n\tthis.wiki.addToHistory(title,fromPageRect,this.historyTitle);\n};\n\n/*\nHandle a tm-navigate event\n*/\nNavigatorWidget.prototype.handleNavigateEvent = function(event) {\n\tevent = $tw.hooks.invokeHook(\"th-navigating\",event);\n\tif(event.navigateTo) {\n\t\tthis.addToStory(event.navigateTo,event.navigateFromTitle);\n\t\tif(!event.navigateSuppressNavigation) {\n\t\t\tthis.addToHistory(event.navigateTo,event.navigateFromClientRect);\n\t\t}\n\t}\n\treturn false;\n};\n\n// Close a specified tiddler\nNavigatorWidget.prototype.handleCloseTiddlerEvent = function(event) {\n\tvar title = event.param || event.tiddlerTitle,\n\t\tstoryList = this.getStoryList();\n\t// Look for tiddlers with this title to close\n\tthis.removeTitleFromStory(storyList,title);\n\tthis.saveStoryList(storyList);\n\treturn false;\n};\n\n// Close all tiddlers\nNavigatorWidget.prototype.handleCloseAllTiddlersEvent = function(event) {\n\tthis.saveStoryList([]);\n\treturn false;\n};\n\n// Close other tiddlers\nNavigatorWidget.prototype.handleCloseOtherTiddlersEvent = function(event) {\n\tvar title = event.param || event.tiddlerTitle;\n\tthis.saveStoryList([title]);\n\treturn false;\n};\n\n// Place a tiddler in edit mode\nNavigatorWidget.prototype.handleEditTiddlerEvent = function(event) {\n\tvar self = this;\n\tfunction isUnmodifiedShadow(title) {\n\t\treturn self.wiki.isShadowTiddler(title) && !self.wiki.tiddlerExists(title);\n\t}\n\tfunction confirmEditShadow(title) {\n\t\treturn confirm($tw.language.getString(\n\t\t\t\"ConfirmEditShadowTiddler\",\n\t\t\t{variables:\n\t\t\t\t{title: title}\n\t\t\t}\n\t\t));\n\t}\n\tvar title = event.param || event.tiddlerTitle;\n\tif(isUnmodifiedShadow(title) && !confirmEditShadow(title)) {\n\t\treturn false;\n\t}\n\t// Replace the specified tiddler with a draft in edit mode\n\tvar draftTiddler = this.makeDraftTiddler(title);\n\t// Update the story and history if required\n\tif(!event.paramObject || event.paramObject.suppressNavigation !== \"yes\") {\n\t\tvar draftTitle = draftTiddler.fields.title,\n\t\t\tstoryList = this.getStoryList();\n\t\tthis.removeTitleFromStory(storyList,draftTitle);\n\t\tthis.replaceFirstTitleInStory(storyList,title,draftTitle);\n\t\tthis.addToHistory(draftTitle,event.navigateFromClientRect);\n\t\tthis.saveStoryList(storyList);\n\t\treturn false;\n\t}\n};\n\n// Delete a tiddler\nNavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {\n\t// Get the tiddler we're deleting\n\tvar title = event.param || event.tiddlerTitle,\n\t\ttiddler = this.wiki.getTiddler(title),\n\t\tstoryList = this.getStoryList(),\n\t\toriginalTitle = tiddler ? tiddler.fields[\"draft.of\"] : \"\",\n\t\toriginalTiddler = originalTitle ? this.wiki.getTiddler(originalTitle) : undefined,\n\t\tconfirmationTitle;\n\tif(!tiddler) {\n\t\treturn false;\n\t}\n\t// Check if the tiddler we're deleting is in draft mode\n\tif(originalTitle) {\n\t\t// If so, we'll prompt for confirmation referencing the original tiddler\n\t\tconfirmationTitle = originalTitle;\n\t} else {\n\t\t// If not a draft, then prompt for confirmation referencing the specified tiddler\n\t\tconfirmationTitle = title;\n\t}\n\t// Seek confirmation\n\tif((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || \"\") !== \"\") && !confirm($tw.language.getString(\n\t\t\t\t\"ConfirmDeleteTiddler\",\n\t\t\t\t{variables:\n\t\t\t\t\t{title: confirmationTitle}\n\t\t\t\t}\n\t\t\t))) {\n\t\treturn false;\n\t}\n\t// Delete the original tiddler\n\tif(originalTitle) {\n\t\tif(originalTiddler) {\n\t\t\t$tw.hooks.invokeHook(\"th-deleting-tiddler\",originalTiddler);\n\t\t}\n\t\tthis.wiki.deleteTiddler(originalTitle);\n\t\tthis.removeTitleFromStory(storyList,originalTitle);\n\t}\n\t// Invoke the hook function and delete this tiddler\n\t$tw.hooks.invokeHook(\"th-deleting-tiddler\",tiddler);\n\tthis.wiki.deleteTiddler(title);\n\t// Remove the closed tiddler from the story\n\tthis.removeTitleFromStory(storyList,title);\n\tthis.saveStoryList(storyList);\n\t// Trigger an autosave\n\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n\treturn false;\n};\n\n/*\nCreate/reuse the draft tiddler for a given title\n*/\nNavigatorWidget.prototype.makeDraftTiddler = function(targetTitle) {\n\t// See if there is already a draft tiddler for this tiddler\n\tvar draftTitle = this.wiki.findDraft(targetTitle);\n\tif(draftTitle) {\n\t\treturn this.wiki.getTiddler(draftTitle);\n\t}\n\t// Get the current value of the tiddler we're editing\n\tvar tiddler = this.wiki.getTiddler(targetTitle);\n\t// Save the initial value of the draft tiddler\n\tdraftTitle = this.generateDraftTitle(targetTitle);\n\tvar draftTiddler = new $tw.Tiddler(\n\t\t\ttiddler,\n\t\t\t{\n\t\t\t\ttitle: draftTitle,\n\t\t\t\t\"draft.title\": targetTitle,\n\t\t\t\t\"draft.of\": targetTitle\n\t\t\t},\n\t\t\tthis.wiki.getModificationFields()\n\t\t);\n\tthis.wiki.addTiddler(draftTiddler);\n\treturn draftTiddler;\n};\n\n/*\nGenerate a title for the draft of a given tiddler\n*/\nNavigatorWidget.prototype.generateDraftTitle = function(title) {\n\tvar c = 0,\n\t\tdraftTitle;\n\tdo {\n\t\tdraftTitle = \"Draft \" + (c ? (c + 1) + \" \" : \"\") + \"of '\" + title + \"'\";\n\t\tc++;\n\t} while(this.wiki.tiddlerExists(draftTitle));\n\treturn draftTitle;\n};\n\n// Take a tiddler out of edit mode, saving the changes\nNavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {\n\tvar title = event.param || event.tiddlerTitle,\n\t\ttiddler = this.wiki.getTiddler(title),\n\t\tstoryList = this.getStoryList();\n\t// Replace the original tiddler with the draft\n\tif(tiddler) {\n\t\tvar draftTitle = (tiddler.fields[\"draft.title\"] || \"\").trim(),\n\t\t\tdraftOf = (tiddler.fields[\"draft.of\"] || \"\").trim();\n\t\tif(draftTitle) {\n\t\t\tvar isRename = draftOf !== draftTitle,\n\t\t\t\tisConfirmed = true;\n\t\t\tif(isRename && this.wiki.tiddlerExists(draftTitle)) {\n\t\t\t\tisConfirmed = confirm($tw.language.getString(\n\t\t\t\t\t\"ConfirmOverwriteTiddler\",\n\t\t\t\t\t{variables:\n\t\t\t\t\t\t{title: draftTitle}\n\t\t\t\t\t}\n\t\t\t\t));\n\t\t\t}\n\t\t\tif(isConfirmed) {\n\t\t\t\t// Create the new tiddler and pass it through the th-saving-tiddler hook\n\t\t\t\tvar newTiddler = new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,{\n\t\t\t\t\ttitle: draftTitle,\n\t\t\t\t\t\"draft.title\": undefined,\n\t\t\t\t\t\"draft.of\": undefined\n\t\t\t\t},this.wiki.getModificationFields());\n\t\t\t\tnewTiddler = $tw.hooks.invokeHook(\"th-saving-tiddler\",newTiddler);\n\t\t\t\tthis.wiki.addTiddler(newTiddler);\n\t\t\t\t// If enabled, relink references to renamed tiddler\n\t\t\t\tvar shouldRelink = this.getAttribute(\"relinkOnRename\",\"no\").toLowerCase().trim() === \"yes\";\n\t\t\t\tif(isRename && shouldRelink && this.wiki.tiddlerExists(draftOf)) {\nconsole.log(\"Relinking '\" + draftOf + \"' to '\" + draftTitle + \"'\");\n\t\t\t\t\tthis.wiki.relinkTiddler(draftOf,draftTitle);\n\t\t\t\t}\n\t\t\t\t// Remove the draft tiddler\n\t\t\t\tthis.wiki.deleteTiddler(title);\n\t\t\t\t// Remove the original tiddler if we're renaming it\n\t\t\t\tif(isRename) {\n\t\t\t\t\tthis.wiki.deleteTiddler(draftOf);\n\t\t\t\t}\n\t\t\t\t// #2381 always remove new title & old\n\t\t\t\tthis.removeTitleFromStory(storyList,draftTitle);\n\t\t\t\tthis.removeTitleFromStory(storyList,draftOf);\n\t\t\t\tif(!event.paramObject || event.paramObject.suppressNavigation !== \"yes\") {\n\t\t\t\t\t// Replace the draft in the story with the original\n\t\t\t\t\tthis.replaceFirstTitleInStory(storyList,title,draftTitle);\n\t\t\t\t\tthis.addToHistory(draftTitle,event.navigateFromClientRect);\n\t\t\t\t\tif(draftTitle !== this.storyTitle) {\n\t\t\t\t\t\tthis.saveStoryList(storyList);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Trigger an autosave\n\t\t\t\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n};\n\n// Take a tiddler out of edit mode without saving the changes\nNavigatorWidget.prototype.handleCancelTiddlerEvent = function(event) {\n\t// Flip the specified tiddler from draft back to the original\n\tvar draftTitle = event.param || event.tiddlerTitle,\n\t\tdraftTiddler = this.wiki.getTiddler(draftTitle),\n\t\toriginalTitle = draftTiddler && draftTiddler.fields[\"draft.of\"];\n\tif(draftTiddler && originalTitle) {\n\t\t// Ask for confirmation if the tiddler text has changed\n\t\tvar isConfirmed = true,\n\t\t\toriginalTiddler = this.wiki.getTiddler(originalTitle),\n\t\t\tstoryList = this.getStoryList();\n\t\tif(this.wiki.isDraftModified(draftTitle)) {\n\t\t\tisConfirmed = confirm($tw.language.getString(\n\t\t\t\t\"ConfirmCancelTiddler\",\n\t\t\t\t{variables:\n\t\t\t\t\t{title: draftTitle}\n\t\t\t\t}\n\t\t\t));\n\t\t}\n\t\t// Remove the draft tiddler\n\t\tif(isConfirmed) {\n\t\t\tthis.wiki.deleteTiddler(draftTitle);\n\t\t\tif(!event.paramObject || event.paramObject.suppressNavigation !== \"yes\") {\n\t\t\t\tif(originalTiddler) {\n\t\t\t\t\tthis.replaceFirstTitleInStory(storyList,draftTitle,originalTitle);\n\t\t\t\t\tthis.addToHistory(originalTitle,event.navigateFromClientRect);\n\t\t\t\t} else {\n\t\t\t\t\tthis.removeTitleFromStory(storyList,draftTitle);\n\t\t\t\t}\n\t\t\t\tthis.saveStoryList(storyList);\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n};\n\n// Create a new draft tiddler\n// event.param can either be the title of a template tiddler, or a hashmap of fields.\n//\n// The title of the newly created tiddler follows these rules:\n// * If a hashmap was used and a title field was specified, use that title\n// * If a hashmap was used without a title field, use a default title, if necessary making it unique with a numeric suffix\n// * If a template tiddler was used, use the title of the template, if necessary making it unique with a numeric suffix\n//\n// If a draft of the target tiddler already exists then it is reused\nNavigatorWidget.prototype.handleNewTiddlerEvent = function(event) {\n\t// Get the story details\n\tvar storyList = this.getStoryList(),\n\t\ttemplateTiddler, additionalFields, title, draftTitle, existingTiddler;\n\t// Get the template tiddler (if any)\n\tif(typeof event.param === \"string\") {\n\t\t// Get the template tiddler\n\t\ttemplateTiddler = this.wiki.getTiddler(event.param);\n\t\t// Generate a new title\n\t\ttitle = this.wiki.generateNewTitle(event.param || $tw.language.getString(\"DefaultNewTiddlerTitle\"));\n\t}\n\t// Get the specified additional fields\n\tif(typeof event.paramObject === \"object\") {\n\t\tadditionalFields = event.paramObject;\n\t}\n\tif(typeof event.param === \"object\") { // Backwards compatibility with 5.1.3\n\t\tadditionalFields = event.param;\n\t}\n\tif(additionalFields && additionalFields.title) {\n\t\ttitle = additionalFields.title;\n\t}\n\t// Generate a title if we don't have one\n\ttitle = title || this.wiki.generateNewTitle($tw.language.getString(\"DefaultNewTiddlerTitle\"));\n\t// Find any existing draft for this tiddler\n\tdraftTitle = this.wiki.findDraft(title);\n\t// Pull in any existing tiddler\n\tif(draftTitle) {\n\t\texistingTiddler = this.wiki.getTiddler(draftTitle);\n\t} else {\n\t\tdraftTitle = this.generateDraftTitle(title);\n\t\texistingTiddler = this.wiki.getTiddler(title);\n\t}\n\t// Merge the tags\n\tvar mergedTags = [];\n\tif(existingTiddler && existingTiddler.fields.tags) {\n\t\t$tw.utils.pushTop(mergedTags,existingTiddler.fields.tags);\n\t}\n\tif(additionalFields && additionalFields.tags) {\n\t\t// Merge tags\n\t\tmergedTags = $tw.utils.pushTop(mergedTags,$tw.utils.parseStringArray(additionalFields.tags));\n\t}\n\tif(templateTiddler && templateTiddler.fields.tags) {\n\t\t// Merge tags\n\t\tmergedTags = $tw.utils.pushTop(mergedTags,templateTiddler.fields.tags);\n\t}\n\t// Save the draft tiddler\n\tvar draftTiddler = new $tw.Tiddler({\n\t\t\ttext: \"\",\n\t\t\t\"draft.title\": title\n\t\t},\n\t\ttemplateTiddler,\n\t\texistingTiddler,\n\t\tadditionalFields,\n\t\tthis.wiki.getCreationFields(),\n\t\t{\n\t\t\ttitle: draftTitle,\n\t\t\t\"draft.of\": title,\n\t\t\ttags: mergedTags\n\t\t},this.wiki.getModificationFields());\n\tthis.wiki.addTiddler(draftTiddler);\n\t// Update the story to insert the new draft at the top and remove any existing tiddler\n\tif(storyList.indexOf(draftTitle) === -1) {\n\t\tvar slot = storyList.indexOf(event.navigateFromTitle);\n\t\tstoryList.splice(slot + 1,0,draftTitle);\n\t}\n\tif(storyList.indexOf(title) !== -1) {\n\t\tstoryList.splice(storyList.indexOf(title),1);\t\t\n\t}\n\tthis.saveStoryList(storyList);\n\t// Add a new record to the top of the history stack\n\tthis.addToHistory(draftTitle);\n\treturn false;\n};\n\n// Import JSON tiddlers into a pending import tiddler\nNavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {\n\t// Get the tiddlers\n\tvar tiddlers = [];\n\ttry {\n\t\ttiddlers = JSON.parse(event.param);\t\n\t} catch(e) {\n\t}\n\t// Get the current $:/Import tiddler\n\tvar importTiddler = this.wiki.getTiddler(IMPORT_TITLE),\n\t\timportData = this.wiki.getTiddlerData(IMPORT_TITLE,{}),\n\t\tnewFields = new Object({\n\t\t\ttitle: IMPORT_TITLE,\n\t\t\ttype: \"application/json\",\n\t\t\t\"plugin-type\": \"import\",\n\t\t\t\"status\": \"pending\"\n\t\t}),\n\t\tincomingTiddlers = [];\n\t// Process each tiddler\n\timportData.tiddlers = importData.tiddlers || {};\n\t$tw.utils.each(tiddlers,function(tiddlerFields) {\n\t\tvar title = tiddlerFields.title;\n\t\tif(title) {\n\t\t\tincomingTiddlers.push(title);\n\t\t\timportData.tiddlers[title] = tiddlerFields;\n\t\t}\n\t});\n\t// Give the active upgrader modules a chance to process the incoming tiddlers\n\tvar messages = this.wiki.invokeUpgraders(incomingTiddlers,importData.tiddlers);\n\t$tw.utils.each(messages,function(message,title) {\n\t\tnewFields[\"message-\" + title] = message;\n\t});\n\t// Deselect any suppressed tiddlers\n\t$tw.utils.each(importData.tiddlers,function(tiddler,title) {\n\t\tif($tw.utils.count(tiddler) === 0) {\n\t\t\tnewFields[\"selection-\" + title] = \"unchecked\";\n\t\t}\n\t});\n\t// Save the $:/Import tiddler\n\tnewFields.text = JSON.stringify(importData,null,$tw.config.preferences.jsonSpaces);\n\tthis.wiki.addTiddler(new $tw.Tiddler(importTiddler,newFields));\n\t// Update the story and history details\n\tif(this.getVariable(\"tv-auto-open-on-import\") !== \"no\") {\n\t\tvar storyList = this.getStoryList(),\n\t\t\thistory = [];\n\t\t// Add it to the story\n\t\tif(storyList.indexOf(IMPORT_TITLE) === -1) {\n\t\t\tstoryList.unshift(IMPORT_TITLE);\n\t\t}\n\t\t// And to history\n\t\thistory.push(IMPORT_TITLE);\n\t\t// Save the updated story and history\n\t\tthis.saveStoryList(storyList);\n\t\tthis.addToHistory(history);\n\t}\n\treturn false;\n};\n\n// \nNavigatorWidget.prototype.handlePerformImportEvent = function(event) {\n\tvar self = this,\n\t\timportTiddler = this.wiki.getTiddler(event.param),\n\t\timportData = this.wiki.getTiddlerDataCached(event.param,{tiddlers: {}}),\n\t\timportReport = [];\n\t// Add the tiddlers to the store\n\timportReport.push($tw.language.getString(\"Import/Imported/Hint\") + \"\\n\");\n\t$tw.utils.each(importData.tiddlers,function(tiddlerFields) {\n\t\tvar title = tiddlerFields.title;\n\t\tif(title && importTiddler && importTiddler.fields[\"selection-\" + title] !== \"unchecked\") {\n\t\t\tvar tiddler = new $tw.Tiddler(tiddlerFields);\n\t\t\ttiddler = $tw.hooks.invokeHook(\"th-importing-tiddler\",tiddler);\n\t\t\tself.wiki.addTiddler(tiddler);\n\t\t\timportReport.push(\"# [[\" + tiddlerFields.title + \"]]\");\n\t\t}\n\t});\n\t// Replace the $:/Import tiddler with an import report\n\tthis.wiki.addTiddler(new $tw.Tiddler({\n\t\ttitle: event.param,\n\t\ttext: importReport.join(\"\\n\"),\n\t\t\"status\": \"complete\"\n\t}));\n\t// Navigate to the $:/Import tiddler\n\tthis.addToHistory([event.param]);\n\t// Trigger an autosave\n\t$tw.rootWidget.dispatchEvent({type: \"tm-auto-save-wiki\"});\n};\n\nNavigatorWidget.prototype.handleFoldTiddlerEvent = function(event) {\n\tvar paramObject = event.paramObject || {};\n\tif(paramObject.foldedState) {\n\t\tvar foldedState = this.wiki.getTiddlerText(paramObject.foldedState,\"show\") === \"show\" ? \"hide\" : \"show\";\n\t\tthis.wiki.setText(paramObject.foldedState,\"text\",null,foldedState);\n\t}\n};\n\nNavigatorWidget.prototype.handleFoldOtherTiddlersEvent = function(event) {\n\tvar self = this,\n\t\tparamObject = event.paramObject || {},\n\t\tprefix = paramObject.foldedStatePrefix;\n\t$tw.utils.each(this.getStoryList(),function(title) {\n\t\tself.wiki.setText(prefix + title,\"text\",null,event.param === title ? \"show\" : \"hide\");\n\t});\n};\n\nNavigatorWidget.prototype.handleFoldAllTiddlersEvent = function(event) {\n\tvar self = this,\n\t\tparamObject = event.paramObject || {},\n\t\tprefix = paramObject.foldedStatePrefix;\n\t$tw.utils.each(this.getStoryList(),function(title) {\n\t\tself.wiki.setText(prefix + title,\"text\",null,\"hide\");\n\t});\n};\n\nNavigatorWidget.prototype.handleUnfoldAllTiddlersEvent = function(event) {\n\tvar self = this,\n\t\tparamObject = event.paramObject || {},\n\t\tprefix = paramObject.foldedStatePrefix;\n\t$tw.utils.each(this.getStoryList(),function(title) {\n\t\tself.wiki.setText(prefix + title,\"text\",null,\"show\");\n\t});\n};\n\nNavigatorWidget.prototype.handleRenameTiddlerEvent = function(event) {\n\tvar paramObject = event.paramObject || {},\n\t\tfrom = paramObject.from || event.tiddlerTitle,\n\t\tto = paramObject.to;\n\t$tw.wiki.renameTiddler(from,to);\n};\n\nexports.navigator = NavigatorWidget;\n\n})();\n", "title": "$:/core/modules/widgets/navigator.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/password.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/password.js\ntype: application/javascript\nmodule-type: widget\n\nPassword widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar PasswordWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nPasswordWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nPasswordWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Get the current password\n\tvar password = $tw.browser ? $tw.utils.getPassword(this.passwordName) || \"\" : \"\";\n\t// Create our element\n\tvar domNode = this.document.createElement(\"input\");\n\tdomNode.setAttribute(\"type\",\"password\");\n\tdomNode.setAttribute(\"value\",password);\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(domNode,[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n\t// Insert the label into the DOM and render any children\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tthis.domNodes.push(domNode);\n};\n\nPasswordWidget.prototype.handleChangeEvent = function(event) {\n\tvar password = this.domNodes[0].value;\n\treturn $tw.utils.savePassword(this.passwordName,password);\n};\n\n/*\nCompute the internal state of the widget\n*/\nPasswordWidget.prototype.execute = function() {\n\t// Get the parameters from the attributes\n\tthis.passwordName = this.getAttribute(\"name\",\"\");\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nPasswordWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.name) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.password = PasswordWidget;\n\n})();\n", "title": "$:/core/modules/widgets/password.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/radio.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/radio.js\ntype: application/javascript\nmodule-type: widget\n\nSet a field or index at a given tiddler via radio buttons\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar RadioWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nRadioWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nRadioWidget.prototype.render = function(parent,nextSibling) {\n\t// Save the parent dom node\n\tthis.parentDomNode = parent;\n\t// Compute our attributes\n\tthis.computeAttributes();\n\t// Execute our logic\n\tthis.execute();\n\t// Create our elements\n\tthis.labelDomNode = this.document.createElement(\"label\");\n\tthis.labelDomNode.setAttribute(\"class\",this.radioClass);\n\tthis.inputDomNode = this.document.createElement(\"input\");\n\tthis.inputDomNode.setAttribute(\"type\",\"radio\");\n\tif(this.getValue() == this.radioValue) {\n\t\tthis.inputDomNode.setAttribute(\"checked\",\"true\");\n\t}\n\tthis.labelDomNode.appendChild(this.inputDomNode);\n\tthis.spanDomNode = this.document.createElement(\"span\");\n\tthis.labelDomNode.appendChild(this.spanDomNode);\n\t// Add a click event handler\n\t$tw.utils.addEventListeners(this.inputDomNode,[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n\t// Insert the label into the DOM and render any children\n\tparent.insertBefore(this.labelDomNode,nextSibling);\n\tthis.renderChildren(this.spanDomNode,null);\n\tthis.domNodes.push(this.labelDomNode);\n};\n\nRadioWidget.prototype.getValue = function() {\n\tvar value,\n\t\ttiddler = this.wiki.getTiddler(this.radioTitle);\n\tif (this.radioIndex) {\n\t\tvalue = this.wiki.extractTiddlerDataItem(this.radioTitle,this.radioIndex);\n\t} else {\n\t\tvalue = tiddler && tiddler.getFieldString(this.radioField);\n\t}\n\treturn value;\n};\n\nRadioWidget.prototype.setValue = function() {\n\tif(this.radioIndex) {\n\t\tthis.wiki.setText(this.radioTitle,\"\",this.radioIndex,this.radioValue);\n\t} else {\n\t\tvar tiddler = this.wiki.getTiddler(this.radioTitle),\n\t\t\taddition = {};\n\t\taddition[this.radioField] = this.radioValue;\n\t\tthis.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),{title: this.radioTitle},tiddler,addition,this.wiki.getModificationFields()));\n\t}\n};\n\nRadioWidget.prototype.handleChangeEvent = function(event) {\n\tif(this.inputDomNode.checked) {\n\t\tthis.setValue();\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nRadioWidget.prototype.execute = function() {\n\t// Get the parameters from the attributes\n\tthis.radioTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.radioField = this.getAttribute(\"field\",\"text\");\n\tthis.radioIndex = this.getAttribute(\"index\");\n\tthis.radioValue = this.getAttribute(\"value\");\n\tthis.radioClass = this.getAttribute(\"class\",\"\");\n\tif(this.radioClass !== \"\") {\n\t\tthis.radioClass += \" \";\n\t}\n\tthis.radioClass += \"tc-radio\";\n\t// Make the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nRadioWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.value || changedAttributes[\"class\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\tvar refreshed = false;\n\t\tif(changedTiddlers[this.radioTitle]) {\n\t\t\tthis.inputDomNode.checked = this.getValue() === this.radioValue;\n\t\t\trefreshed = true;\n\t\t}\n\t\treturn this.refreshChildren(changedTiddlers) || refreshed;\n\t}\n};\n\nexports.radio = RadioWidget;\n\n})();\n", "title": "$:/core/modules/widgets/radio.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/raw.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/raw.js\ntype: application/javascript\nmodule-type: widget\n\nRaw widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar RawWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nRawWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nRawWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.execute();\n\tvar div = this.document.createElement(\"div\");\n\tdiv.innerHTML=this.parseTreeNode.html;\n\tparent.insertBefore(div,nextSibling);\n\tthis.domNodes.push(div);\t\n};\n\n/*\nCompute the internal state of the widget\n*/\nRawWidget.prototype.execute = function() {\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nRawWidget.prototype.refresh = function(changedTiddlers) {\n\treturn false;\n};\n\nexports.raw = RawWidget;\n\n})();\n", "title": "$:/core/modules/widgets/raw.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/reveal.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/reveal.js\ntype: application/javascript\nmodule-type: widget\n\nReveal widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar RevealWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nRevealWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nRevealWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar tag = this.parseTreeNode.isBlock ? \"div\" : \"span\";\n\tif(this.revealTag && $tw.config.htmlUnsafeElements.indexOf(this.revealTag) === -1) {\n\t\ttag = this.revealTag;\n\t}\n\tvar domNode = this.document.createElement(tag);\n\tvar classes = this[\"class\"].split(\" \") || [];\n\tclasses.push(\"tc-reveal\");\n\tdomNode.className = classes.join(\" \");\n\tif(this.style) {\n\t\tdomNode.setAttribute(\"style\",this.style);\n\t}\n\tparent.insertBefore(domNode,nextSibling);\n\tthis.renderChildren(domNode,null);\n\tif(!domNode.isTiddlyWikiFakeDom && this.type === \"popup\" && this.isOpen) {\n\t\tthis.positionPopup(domNode);\n\t\t$tw.utils.addClass(domNode,\"tc-popup\"); // Make sure that clicks don't dismiss popups within the revealed content\n\t}\n\tif(!this.isOpen) {\n\t\tdomNode.setAttribute(\"hidden\",\"true\");\n\t}\n\tthis.domNodes.push(domNode);\n};\n\nRevealWidget.prototype.positionPopup = function(domNode) {\n\tdomNode.style.position = \"absolute\";\n\tdomNode.style.zIndex = \"1000\";\n\tswitch(this.position) {\n\t\tcase \"left\":\n\t\t\tdomNode.style.left = (this.popup.left - domNode.offsetWidth) + \"px\";\n\t\t\tdomNode.style.top = this.popup.top + \"px\";\n\t\t\tbreak;\n\t\tcase \"above\":\n\t\t\tdomNode.style.left = this.popup.left + \"px\";\n\t\t\tdomNode.style.top = (this.popup.top - domNode.offsetHeight) + \"px\";\n\t\t\tbreak;\n\t\tcase \"aboveright\":\n\t\t\tdomNode.style.left = (this.popup.left + this.popup.width) + \"px\";\n\t\t\tdomNode.style.top = (this.popup.top + this.popup.height - domNode.offsetHeight) + \"px\";\n\t\t\tbreak;\n\t\tcase \"right\":\n\t\t\tdomNode.style.left = (this.popup.left + this.popup.width) + \"px\";\n\t\t\tdomNode.style.top = this.popup.top + \"px\";\n\t\t\tbreak;\n\t\tcase \"belowleft\":\n\t\t\tdomNode.style.left = (this.popup.left + this.popup.width - domNode.offsetWidth) + \"px\";\n\t\t\tdomNode.style.top = (this.popup.top + this.popup.height) + \"px\";\n\t\t\tbreak;\n\t\tdefault: // Below\n\t\t\tdomNode.style.left = this.popup.left + \"px\";\n\t\t\tdomNode.style.top = (this.popup.top + this.popup.height) + \"px\";\n\t\t\tbreak;\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nRevealWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.state = this.getAttribute(\"state\");\n\tthis.revealTag = this.getAttribute(\"tag\");\n\tthis.type = this.getAttribute(\"type\");\n\tthis.text = this.getAttribute(\"text\");\n\tthis.position = this.getAttribute(\"position\");\n\tthis[\"class\"] = this.getAttribute(\"class\",\"\");\n\tthis.style = this.getAttribute(\"style\",\"\");\n\tthis[\"default\"] = this.getAttribute(\"default\",\"\");\n\tthis.animate = this.getAttribute(\"animate\",\"no\");\n\tthis.retain = this.getAttribute(\"retain\",\"no\");\n\tthis.openAnimation = this.animate === \"no\" ? undefined : \"open\";\n\tthis.closeAnimation = this.animate === \"no\" ? undefined : \"close\";\n\t// Compute the title of the state tiddler and read it\n\tthis.stateTitle = this.state;\n\tthis.readState();\n\t// Construct the child widgets\n\tvar childNodes = this.isOpen ? this.parseTreeNode.children : [];\n\tthis.hasChildNodes = this.isOpen;\n\tthis.makeChildWidgets(childNodes);\n};\n\n/*\nRead the state tiddler\n*/\nRevealWidget.prototype.readState = function() {\n\t// Read the information from the state tiddler\n\tvar state = this.stateTitle ? this.wiki.getTextReference(this.stateTitle,this[\"default\"],this.getVariable(\"currentTiddler\")) : this[\"default\"];\n\tswitch(this.type) {\n\t\tcase \"popup\":\n\t\t\tthis.readPopupState(state);\n\t\t\tbreak;\n\t\tcase \"match\":\n\t\t\tthis.readMatchState(state);\n\t\t\tbreak;\n\t\tcase \"nomatch\":\n\t\t\tthis.readMatchState(state);\n\t\t\tthis.isOpen = !this.isOpen;\n\t\t\tbreak;\n\t}\n};\n\nRevealWidget.prototype.readMatchState = function(state) {\n\tthis.isOpen = state === this.text;\n};\n\nRevealWidget.prototype.readPopupState = function(state) {\n\tvar popupLocationRegExp = /^\\((-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+),(-?[0-9\\.E]+)\\)$/,\n\t\tmatch = popupLocationRegExp.exec(state);\n\t// Check if the state matches the location regexp\n\tif(match) {\n\t\t// If so, we're open\n\t\tthis.isOpen = true;\n\t\t// Get the location\n\t\tthis.popup = {\n\t\t\tleft: parseFloat(match[1]),\n\t\t\ttop: parseFloat(match[2]),\n\t\t\twidth: parseFloat(match[3]),\n\t\t\theight: parseFloat(match[4])\n\t\t};\n\t} else {\n\t\t// If not, we're closed\n\t\tthis.isOpen = false;\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nRevealWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.state || changedAttributes.type || changedAttributes.text || changedAttributes.position || changedAttributes[\"default\"] || changedAttributes.animate) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\tvar refreshed = false,\n\t\t\tcurrentlyOpen = this.isOpen;\n\t\tthis.readState();\n\t\tif(this.isOpen !== currentlyOpen) {\n\t\t\tif(this.retain === \"yes\") {\n\t\t\t\tthis.updateState();\n\t\t\t} else {\n\t\t\t\tthis.refreshSelf();\n\t\t\t\trefreshed = true;\n\t\t\t}\n\t\t}\n\t\treturn this.refreshChildren(changedTiddlers) || refreshed;\n\t}\n};\n\n/*\nCalled by refresh() to dynamically show or hide the content\n*/\nRevealWidget.prototype.updateState = function() {\n\t// Read the current state\n\tthis.readState();\n\t// Construct the child nodes if needed\n\tvar domNode = this.domNodes[0];\n\tif(this.isOpen && !this.hasChildNodes) {\n\t\tthis.hasChildNodes = true;\n\t\tthis.makeChildWidgets(this.parseTreeNode.children);\n\t\tthis.renderChildren(domNode,null);\n\t}\n\t// Animate our DOM node\n\tif(!domNode.isTiddlyWikiFakeDom && this.type === \"popup\" && this.isOpen) {\n\t\tthis.positionPopup(domNode);\n\t\t$tw.utils.addClass(domNode,\"tc-popup\"); // Make sure that clicks don't dismiss popups within the revealed content\n\n\t}\n\tif(this.isOpen) {\n\t\tdomNode.removeAttribute(\"hidden\");\n $tw.anim.perform(this.openAnimation,domNode);\n\t} else {\n\t\t$tw.anim.perform(this.closeAnimation,domNode,{callback: function() {\n\t\t\tdomNode.setAttribute(\"hidden\",\"true\");\n }});\n\t}\n};\n\nexports.reveal = RevealWidget;\n\n})();\n", "title": "$:/core/modules/widgets/reveal.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/scrollable.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/scrollable.js\ntype: application/javascript\nmodule-type: widget\n\nScrollable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ScrollableWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n\tthis.scaleFactor = 1;\n\tthis.addEventListeners([\n\t\t{type: \"tm-scroll\", handler: \"handleScrollEvent\"}\n\t]);\n\tif($tw.browser) {\n\t\tthis.requestAnimationFrame = window.requestAnimationFrame ||\n\t\t\twindow.webkitRequestAnimationFrame ||\n\t\t\twindow.mozRequestAnimationFrame ||\n\t\t\tfunction(callback) {\n\t\t\t\treturn window.setTimeout(callback, 1000/60);\n\t\t\t};\n\t\tthis.cancelAnimationFrame = window.cancelAnimationFrame ||\n\t\t\twindow.webkitCancelAnimationFrame ||\n\t\t\twindow.webkitCancelRequestAnimationFrame ||\n\t\t\twindow.mozCancelAnimationFrame ||\n\t\t\twindow.mozCancelRequestAnimationFrame ||\n\t\t\tfunction(id) {\n\t\t\t\twindow.clearTimeout(id);\n\t\t\t};\n\t}\n};\n\n/*\nInherit from the base widget class\n*/\nScrollableWidget.prototype = new Widget();\n\nScrollableWidget.prototype.cancelScroll = function() {\n\tif(this.idRequestFrame) {\n\t\tthis.cancelAnimationFrame.call(window,this.idRequestFrame);\n\t\tthis.idRequestFrame = null;\n\t}\n};\n\n/*\nHandle a scroll event\n*/\nScrollableWidget.prototype.handleScrollEvent = function(event) {\n\t// Pass the scroll event through if our offsetsize is larger than our scrollsize\n\tif(this.outerDomNode.scrollWidth <= this.outerDomNode.offsetWidth && this.outerDomNode.scrollHeight <= this.outerDomNode.offsetHeight && this.fallthrough === \"yes\") {\n\t\treturn true;\n\t}\n\tthis.scrollIntoView(event.target);\n\treturn false; // Handled event\n};\n\n/*\nScroll an element into view\n*/\nScrollableWidget.prototype.scrollIntoView = function(element) {\n\tvar duration = $tw.utils.getAnimationDuration();\n\tthis.cancelScroll();\n\tthis.startTime = Date.now();\n\tvar scrollPosition = {\n\t\tx: this.outerDomNode.scrollLeft,\n\t\ty: this.outerDomNode.scrollTop\n\t};\n\t// Get the client bounds of the element and adjust by the scroll position\n\tvar scrollableBounds = this.outerDomNode.getBoundingClientRect(),\n\t\tclientTargetBounds = element.getBoundingClientRect(),\n\t\tbounds = {\n\t\t\tleft: clientTargetBounds.left + scrollPosition.x - scrollableBounds.left,\n\t\t\ttop: clientTargetBounds.top + scrollPosition.y - scrollableBounds.top,\n\t\t\twidth: clientTargetBounds.width,\n\t\t\theight: clientTargetBounds.height\n\t\t};\n\t// We'll consider the horizontal and vertical scroll directions separately via this function\n\tvar getEndPos = function(targetPos,targetSize,currentPos,currentSize) {\n\t\t\t// If the target is already visible then stay where we are\n\t\t\tif(targetPos >= currentPos && (targetPos + targetSize) <= (currentPos + currentSize)) {\n\t\t\t\treturn currentPos;\n\t\t\t// If the target is above/left of the current view, then scroll to its top/left\n\t\t\t} else if(targetPos <= currentPos) {\n\t\t\t\treturn targetPos;\n\t\t\t// If the target is smaller than the window and the scroll position is too far up, then scroll till the target is at the bottom of the window\n\t\t\t} else if(targetSize < currentSize && currentPos < (targetPos + targetSize - currentSize)) {\n\t\t\t\treturn targetPos + targetSize - currentSize;\n\t\t\t// If the target is big, then just scroll to the top\n\t\t\t} else if(currentPos < targetPos) {\n\t\t\t\treturn targetPos;\n\t\t\t// Otherwise, stay where we are\n\t\t\t} else {\n\t\t\t\treturn currentPos;\n\t\t\t}\n\t\t},\n\t\tendX = getEndPos(bounds.left,bounds.width,scrollPosition.x,this.outerDomNode.offsetWidth),\n\t\tendY = getEndPos(bounds.top,bounds.height,scrollPosition.y,this.outerDomNode.offsetHeight);\n\t// Only scroll if necessary\n\tif(endX !== scrollPosition.x || endY !== scrollPosition.y) {\n\t\tvar self = this,\n\t\t\tdrawFrame;\n\t\tdrawFrame = function () {\n\t\t\tvar t;\n\t\t\tif(duration <= 0) {\n\t\t\t\tt = 1;\n\t\t\t} else {\n\t\t\t\tt = ((Date.now()) - self.startTime) / duration;\t\n\t\t\t}\n\t\t\tif(t >= 1) {\n\t\t\t\tself.cancelScroll();\n\t\t\t\tt = 1;\n\t\t\t}\n\t\t\tt = $tw.utils.slowInSlowOut(t);\n\t\t\tself.outerDomNode.scrollLeft = scrollPosition.x + (endX - scrollPosition.x) * t;\n\t\t\tself.outerDomNode.scrollTop = scrollPosition.y + (endY - scrollPosition.y) * t;\n\t\t\tif(t < 1) {\n\t\t\t\tself.idRequestFrame = self.requestAnimationFrame.call(window,drawFrame);\n\t\t\t}\n\t\t};\n\t\tdrawFrame();\n\t}\n};\n\n/*\nRender this widget into the DOM\n*/\nScrollableWidget.prototype.render = function(parent,nextSibling) {\n\tvar self = this;\n\t// Remember parent\n\tthis.parentDomNode = parent;\n\t// Compute attributes and execute state\n\tthis.computeAttributes();\n\tthis.execute();\n\t// Create elements\n\tthis.outerDomNode = this.document.createElement(\"div\");\n\t$tw.utils.setStyle(this.outerDomNode,[\n\t\t{overflowY: \"auto\"},\n\t\t{overflowX: \"auto\"},\n\t\t{webkitOverflowScrolling: \"touch\"}\n\t]);\n\tthis.innerDomNode = this.document.createElement(\"div\");\n\tthis.outerDomNode.appendChild(this.innerDomNode);\n\t// Assign classes\n\tthis.outerDomNode.className = this[\"class\"] || \"\";\n\t// Insert element\n\tparent.insertBefore(this.outerDomNode,nextSibling);\n\tthis.renderChildren(this.innerDomNode,null);\n\tthis.domNodes.push(this.outerDomNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nScrollableWidget.prototype.execute = function() {\n\t// Get attributes\n\tthis.fallthrough = this.getAttribute(\"fallthrough\",\"yes\");\n\tthis[\"class\"] = this.getAttribute(\"class\");\n\t// Make child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nScrollableWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes[\"class\"]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports.scrollable = ScrollableWidget;\n\n})();\n", "title": "$:/core/modules/widgets/scrollable.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/select.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/select.js\ntype: application/javascript\nmodule-type: widget\n\nSelect widget:\n\n```\n<$select tiddler=\"MyTiddler\" field=\"text\">\n<$list filter=\"[tag[chapter]]\">\n<option value=<<currentTiddler>>>\n<$view field=\"description\"/>\n</option>\n</$list>\n</$select>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SelectWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSelectWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSelectWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n\tthis.setSelectValue();\n\t$tw.utils.addEventListeners(this.getSelectDomNode(),[\n\t\t{name: \"change\", handlerObject: this, handlerMethod: \"handleChangeEvent\"}\n\t]);\n};\n\n/*\nHandle a change event\n*/\nSelectWidget.prototype.handleChangeEvent = function(event) {\n\t// Get the new value and assign it to the tiddler\n\tif(this.selectMultiple == false) {\n\t\tvar value = this.getSelectDomNode().value;\n\t} else {\n\t\tvar value = this.getSelectValues()\n\t\t\t\tvalue = $tw.utils.stringifyList(value);\n\t}\n\tthis.wiki.setText(this.selectTitle,this.selectField,this.selectIndex,value);\n\t// Trigger actions\n\tif(this.selectActions) {\n\t\tthis.invokeActionString(this.selectActions,this,event);\n\t}\n};\n\n/*\nIf necessary, set the value of the select element to the current value\n*/\nSelectWidget.prototype.setSelectValue = function() {\n\tvar value = this.selectDefault;\n\t// Get the value\n\tif(this.selectIndex) {\n\t\tvalue = this.wiki.extractTiddlerDataItem(this.selectTitle,this.selectIndex);\n\t} else {\n\t\tvar tiddler = this.wiki.getTiddler(this.selectTitle);\n\t\tif(tiddler) {\n\t\t\tif(this.selectField === \"text\") {\n\t\t\t\t// Calling getTiddlerText() triggers lazy loading of skinny tiddlers\n\t\t\t\tvalue = this.wiki.getTiddlerText(this.selectTitle);\n\t\t\t} else {\n\t\t\t\tif($tw.utils.hop(tiddler.fields,this.selectField)) {\n\t\t\t\t\tvalue = tiddler.getFieldString(this.selectField);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif(this.selectField === \"title\") {\n\t\t\t\tvalue = this.selectTitle;\n\t\t\t}\n\t\t}\n\t}\n\t// Assign it to the select element if it's different than the current value\n\tif (this.selectMultiple) {\n\t\tvalue = value === undefined ? \"\" : value;\n\t\tvar select = this.getSelectDomNode();\n\t\tvar values = Array.isArray(value) ? value : $tw.utils.parseStringArray(value);\n\t\tfor(var i=0; i < select.children.length; i++){\n\t\t\tif(values.indexOf(select.children[i].value) != -1) {\n\t\t\t\tselect.children[i].selected = true;\n\t\t\t}\n\t\t}\n\t\t\n\t} else {\n\t\tvar domNode = this.getSelectDomNode();\n\t\tif(domNode.value !== value) {\n\t\t\tdomNode.value = value;\n\t\t}\n\t}\n};\n\n/*\nGet the DOM node of the select element\n*/\nSelectWidget.prototype.getSelectDomNode = function() {\n\treturn this.children[0].domNodes[0];\n};\n\n// Return an array of the selected opion values\n// select is an HTML select element\nSelectWidget.prototype.getSelectValues = function() {\n\tvar select, result, options, opt;\n\tselect = this.getSelectDomNode();\n\tresult = [];\n\toptions = select && select.options;\n\tfor (var i=0; i<options.length; i++) {\n\t\topt = options[i];\n\t\tif (opt.selected) {\n\t\t\tresult.push(opt.value || opt.text);\n\t\t}\n\t}\n\treturn result;\n}\n\n/*\nCompute the internal state of the widget\n*/\nSelectWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.selectActions = this.getAttribute(\"actions\");\n\tthis.selectTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.selectField = this.getAttribute(\"field\",\"text\");\n\tthis.selectIndex = this.getAttribute(\"index\");\n\tthis.selectClass = this.getAttribute(\"class\");\n\tthis.selectDefault = this.getAttribute(\"default\");\n\tthis.selectMultiple = this.getAttribute(\"multiple\", false);\n\tthis.selectSize = this.getAttribute(\"size\");\n\t// Make the child widgets\n\tvar selectNode = {\n\t\ttype: \"element\",\n\t\ttag: \"select\",\n\t\tchildren: this.parseTreeNode.children\n\t};\n\tif(this.selectClass) {\n\t\t$tw.utils.addAttributeToParseTreeNode(selectNode,\"class\",this.selectClass);\n\t}\n\tif(this.selectMultiple) {\n\t\t$tw.utils.addAttributeToParseTreeNode(selectNode,\"multiple\",\"multiple\");\n\t}\n\tif(this.selectSize) {\n\t\t$tw.utils.addAttributeToParseTreeNode(selectNode,\"size\",this.selectSize);\n\t}\n\tthis.makeChildWidgets([selectNode]);\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nSelectWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\t// If we're using a different tiddler/field/index then completely refresh ourselves\n\tif(changedAttributes.selectTitle || changedAttributes.selectField || changedAttributes.selectIndex) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t// If the target tiddler value has changed, just update setting and refresh the children\n\t} else {\n\t\tvar childrenRefreshed = this.refreshChildren(changedTiddlers);\n\t\tif(changedTiddlers[this.selectTitle] || childrenRefreshed) {\n\t\t\tthis.setSelectValue();\n\t\t} \n\t\treturn childrenRefreshed;\n\t}\n};\n\nexports.select = SelectWidget;\n\n})();\n", "title": "$:/core/modules/widgets/select.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/set.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/set.js\ntype: application/javascript\nmodule-type: widget\n\nSet variable widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar SetWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nSetWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nSetWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nSetWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.setName = this.getAttribute(\"name\",\"currentTiddler\");\n\tthis.setFilter = this.getAttribute(\"filter\");\n\tthis.setSelect = this.getAttribute(\"select\");\n\tthis.setValue = this.getAttribute(\"value\");\n\tthis.setEmptyValue = this.getAttribute(\"emptyValue\");\n\t// Set context variable\n\tthis.setVariable(this.setName,this.getValue(),this.parseTreeNode.params);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nGet the value to be assigned\n*/\nSetWidget.prototype.getValue = function() {\n\tvar value = this.setValue;\n\tif(this.setFilter) {\n\t\tvar results = this.wiki.filterTiddlers(this.setFilter,this);\n\t\tif(!this.setValue) {\n\t\t\tvar select;\n\t\t\tif(this.setSelect) {\n\t\t\t\tselect = parseInt(this.setSelect,10);\n\t\t\t}\n\t\t\tif(select !== undefined) {\n\t\t\t\tvalue = results[select] || \"\";\n\t\t\t} else {\n\t\t\t\tvalue = $tw.utils.stringifyList(results);\t\t\t\n\t\t\t}\n\t\t}\n\t\tif(results.length === 0 && this.setEmptyValue !== undefined) {\n\t\t\tvalue = this.setEmptyValue;\n\t\t}\n\t} else if(!value && this.setEmptyValue) {\n\t\tvalue = this.setEmptyValue;\n\t}\n\treturn value;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nSetWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.name || changedAttributes.filter || changedAttributes.select ||changedAttributes.value || changedAttributes.emptyValue ||\n\t (this.setFilter && this.getValue() != this.variables[this.setName].value)) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.setvariable = SetWidget;\nexports.set = SetWidget;\n\n})();\n", "title": "$:/core/modules/widgets/set.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/text.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/text.js\ntype: application/javascript\nmodule-type: widget\n\nText node widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar TextNodeWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nTextNodeWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nTextNodeWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tvar text = this.getAttribute(\"text\",this.parseTreeNode.text || \"\");\n\ttext = text.replace(/\\r/mg,\"\");\n\tvar textNode = this.document.createTextNode(text);\n\tparent.insertBefore(textNode,nextSibling);\n\tthis.domNodes.push(textNode);\n};\n\n/*\nCompute the internal state of the widget\n*/\nTextNodeWidget.prototype.execute = function() {\n\t// Nothing to do for a text node\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nTextNodeWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.text) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports.text = TextNodeWidget;\n\n})();\n", "title": "$:/core/modules/widgets/text.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/tiddler.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/tiddler.js\ntype: application/javascript\nmodule-type: widget\n\nTiddler widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar TiddlerWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nTiddlerWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nTiddlerWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nTiddlerWidget.prototype.execute = function() {\n\tthis.tiddlerState = this.computeTiddlerState();\n\tthis.setVariable(\"currentTiddler\",this.tiddlerState.currentTiddler);\n\tthis.setVariable(\"missingTiddlerClass\",this.tiddlerState.missingTiddlerClass);\n\tthis.setVariable(\"shadowTiddlerClass\",this.tiddlerState.shadowTiddlerClass);\n\tthis.setVariable(\"systemTiddlerClass\",this.tiddlerState.systemTiddlerClass);\n\tthis.setVariable(\"tiddlerTagClasses\",this.tiddlerState.tiddlerTagClasses);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nCompute the tiddler state flags\n*/\nTiddlerWidget.prototype.computeTiddlerState = function() {\n\t// Get our parameters\n\tthis.tiddlerTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\t// Compute the state\n\tvar state = {\n\t\tcurrentTiddler: this.tiddlerTitle || \"\",\n\t\tmissingTiddlerClass: (this.wiki.tiddlerExists(this.tiddlerTitle) || this.wiki.isShadowTiddler(this.tiddlerTitle)) ? \"tc-tiddler-exists\" : \"tc-tiddler-missing\",\n\t\tshadowTiddlerClass: this.wiki.isShadowTiddler(this.tiddlerTitle) ? \"tc-tiddler-shadow\" : \"\",\n\t\tsystemTiddlerClass: this.wiki.isSystemTiddler(this.tiddlerTitle) ? \"tc-tiddler-system\" : \"\",\n\t\ttiddlerTagClasses: this.getTagClasses()\n\t};\n\t// Compute a simple hash to make it easier to detect changes\n\tstate.hash = state.currentTiddler + state.missingTiddlerClass + state.shadowTiddlerClass + state.systemTiddlerClass + state.tiddlerTagClasses;\n\treturn state;\n};\n\n/*\nCreate a string of CSS classes derived from the tags of the current tiddler\n*/\nTiddlerWidget.prototype.getTagClasses = function() {\n\tvar tiddler = this.wiki.getTiddler(this.tiddlerTitle);\n\tif(tiddler) {\n\t\tvar tags = [];\n\t\t$tw.utils.each(tiddler.fields.tags,function(tag) {\n\t\t\ttags.push(\"tc-tagged-\" + encodeURIComponent(tag));\n\t\t});\n\t\treturn tags.join(\" \");\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nTiddlerWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes(),\n\t\tnewTiddlerState = this.computeTiddlerState();\n\tif(changedAttributes.tiddler || newTiddlerState.hash !== this.tiddlerState.hash) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nexports.tiddler = TiddlerWidget;\n\n})();\n", "title": "$:/core/modules/widgets/tiddler.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/transclude.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/transclude.js\ntype: application/javascript\nmodule-type: widget\n\nTransclude widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar TranscludeWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nTranscludeWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nTranscludeWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nTranscludeWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.transcludeTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.transcludeSubTiddler = this.getAttribute(\"subtiddler\");\n\tthis.transcludeField = this.getAttribute(\"field\");\n\tthis.transcludeIndex = this.getAttribute(\"index\");\n\tthis.transcludeMode = this.getAttribute(\"mode\");\n\t// Parse the text reference\n\tvar parseAsInline = !this.parseTreeNode.isBlock;\n\tif(this.transcludeMode === \"inline\") {\n\t\tparseAsInline = true;\n\t} else if(this.transcludeMode === \"block\") {\n\t\tparseAsInline = false;\n\t}\n\tvar parser = this.wiki.parseTextReference(\n\t\t\t\t\t\tthis.transcludeTitle,\n\t\t\t\t\t\tthis.transcludeField,\n\t\t\t\t\t\tthis.transcludeIndex,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tparseAsInline: parseAsInline,\n\t\t\t\t\t\t\tsubTiddler: this.transcludeSubTiddler\n\t\t\t\t\t\t}),\n\t\tparseTreeNodes = parser ? parser.tree : this.parseTreeNode.children;\n\t// Set context variables for recursion detection\n\tvar recursionMarker = this.makeRecursionMarker();\n\tthis.setVariable(\"transclusion\",recursionMarker);\n\t// Check for recursion\n\tif(parser) {\n\t\tif(this.parentWidget && this.parentWidget.hasVariable(\"transclusion\",recursionMarker)) {\n\t\t\tparseTreeNodes = [{type: \"element\", tag: \"span\", attributes: {\n\t\t\t\t\"class\": {type: \"string\", value: \"tc-error\"}\n\t\t\t}, children: [\n\t\t\t\t{type: \"text\", text: $tw.language.getString(\"Error/RecursiveTransclusion\")}\n\t\t\t]}];\n\t\t}\n\t}\n\t// Construct the child widgets\n\tthis.makeChildWidgets(parseTreeNodes);\n};\n\n/*\nCompose a string comprising the title, field and/or index to identify this transclusion for recursion detection\n*/\nTranscludeWidget.prototype.makeRecursionMarker = function() {\n\tvar output = [];\n\toutput.push(\"{\");\n\toutput.push(this.getVariable(\"currentTiddler\",{defaultValue: \"\"}));\n\toutput.push(\"|\");\n\toutput.push(this.transcludeTitle || \"\");\n\toutput.push(\"|\");\n\toutput.push(this.transcludeField || \"\");\n\toutput.push(\"|\");\n\toutput.push(this.transcludeIndex || \"\");\n\toutput.push(\"|\");\n\toutput.push(this.transcludeSubTiddler || \"\");\n\toutput.push(\"}\");\n\treturn output.join(\"\");\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nTranscludeWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedTiddlers[this.transcludeTitle]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn this.refreshChildren(changedTiddlers);\t\t\n\t}\n};\n\nexports.transclude = TranscludeWidget;\n\n})();\n", "title": "$:/core/modules/widgets/transclude.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/vars.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/vars.js\ntype: application/javascript\nmodule-type: widget\n\nThis widget allows multiple variables to be set in one go:\n\n```\n\\define helloworld() Hello world!\n<$vars greeting=\"Hi\" me={{!!title}} sentence=<<helloworld>>>\n <<greeting>>! I am <<me>> and I say: <<sentence>>\n</$vars>\n```\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar VarsWidget = function(parseTreeNode,options) {\n\t// Call the constructor\n\tWidget.call(this);\n\t// Initialise\t\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nVarsWidget.prototype = Object.create(Widget.prototype);\n\n/*\nRender this widget into the DOM\n*/\nVarsWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nVarsWidget.prototype.execute = function() {\n\t// Parse variables\n\tvar self = this;\n\t$tw.utils.each(this.attributes,function(val,key) {\n\t\tif(key.charAt(0) !== \"$\") {\n\t\t\tself.setVariable(key,val);\n\t\t}\n\t});\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nRefresh the widget by ensuring our attributes are up to date\n*/\nVarsWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(Object.keys(changedAttributes).length) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t}\n\treturn this.refreshChildren(changedTiddlers);\n};\n\nexports[\"vars\"] = VarsWidget;\n\n})();\n", "title": "$:/core/modules/widgets/vars.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/view.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/view.js\ntype: application/javascript\nmodule-type: widget\n\nView widget\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar ViewWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nViewWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nViewWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tif(this.text) {\n\t\tvar textNode = this.document.createTextNode(this.text);\n\t\tparent.insertBefore(textNode,nextSibling);\n\t\tthis.domNodes.push(textNode);\n\t} else {\n\t\tthis.makeChildWidgets();\n\t\tthis.renderChildren(parent,nextSibling);\n\t}\n};\n\n/*\nCompute the internal state of the widget\n*/\nViewWidget.prototype.execute = function() {\n\t// Get parameters from our attributes\n\tthis.viewTitle = this.getAttribute(\"tiddler\",this.getVariable(\"currentTiddler\"));\n\tthis.viewSubtiddler = this.getAttribute(\"subtiddler\");\n\tthis.viewField = this.getAttribute(\"field\",\"text\");\n\tthis.viewIndex = this.getAttribute(\"index\");\n\tthis.viewFormat = this.getAttribute(\"format\",\"text\");\n\tthis.viewTemplate = this.getAttribute(\"template\",\"\");\n\tswitch(this.viewFormat) {\n\t\tcase \"htmlwikified\":\n\t\t\tthis.text = this.getValueAsHtmlWikified();\n\t\t\tbreak;\n\t\tcase \"plainwikified\":\n\t\t\tthis.text = this.getValueAsPlainWikified();\n\t\t\tbreak;\n\t\tcase \"htmlencodedplainwikified\":\n\t\t\tthis.text = this.getValueAsHtmlEncodedPlainWikified();\n\t\t\tbreak;\n\t\tcase \"htmlencoded\":\n\t\t\tthis.text = this.getValueAsHtmlEncoded();\n\t\t\tbreak;\n\t\tcase \"urlencoded\":\n\t\t\tthis.text = this.getValueAsUrlEncoded();\n\t\t\tbreak;\n\t\tcase \"doubleurlencoded\":\n\t\t\tthis.text = this.getValueAsDoubleUrlEncoded();\n\t\t\tbreak;\n\t\tcase \"date\":\n\t\t\tthis.text = this.getValueAsDate(this.viewTemplate);\n\t\t\tbreak;\n\t\tcase \"relativedate\":\n\t\t\tthis.text = this.getValueAsRelativeDate();\n\t\t\tbreak;\n\t\tcase \"stripcomments\":\n\t\t\tthis.text = this.getValueAsStrippedComments();\n\t\t\tbreak;\n\t\tcase \"jsencoded\":\n\t\t\tthis.text = this.getValueAsJsEncoded();\n\t\t\tbreak;\n\t\tdefault: // \"text\"\n\t\t\tthis.text = this.getValueAsText();\n\t\t\tbreak;\n\t}\n};\n\n/*\nThe various formatter functions are baked into this widget for the moment. Eventually they will be replaced by macro functions\n*/\n\n/*\nRetrieve the value of the widget. Options are:\nasString: Optionally return the value as a string\n*/\nViewWidget.prototype.getValue = function(options) {\n\toptions = options || {};\n\tvar value = options.asString ? \"\" : undefined;\n\tif(this.viewIndex) {\n\t\tvalue = this.wiki.extractTiddlerDataItem(this.viewTitle,this.viewIndex);\n\t} else {\n\t\tvar tiddler;\n\t\tif(this.viewSubtiddler) {\n\t\t\ttiddler = this.wiki.getSubTiddler(this.viewTitle,this.viewSubtiddler);\t\n\t\t} else {\n\t\t\ttiddler = this.wiki.getTiddler(this.viewTitle);\n\t\t}\n\t\tif(tiddler) {\n\t\t\tif(this.viewField === \"text\" && !this.viewSubtiddler) {\n\t\t\t\t// Calling getTiddlerText() triggers lazy loading of skinny tiddlers\n\t\t\t\tvalue = this.wiki.getTiddlerText(this.viewTitle);\n\t\t\t} else {\n\t\t\t\tif($tw.utils.hop(tiddler.fields,this.viewField)) {\n\t\t\t\t\tif(options.asString) {\n\t\t\t\t\t\tvalue = tiddler.getFieldString(this.viewField);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvalue = tiddler.fields[this.viewField];\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif(this.viewField === \"title\") {\n\t\t\t\tvalue = this.viewTitle;\n\t\t\t}\n\t\t}\n\t}\n\treturn value;\n};\n\nViewWidget.prototype.getValueAsText = function() {\n\treturn this.getValue({asString: true});\n};\n\nViewWidget.prototype.getValueAsHtmlWikified = function() {\n\treturn this.wiki.renderText(\"text/html\",\"text/vnd.tiddlywiki\",this.getValueAsText(),{parentWidget: this});\n};\n\nViewWidget.prototype.getValueAsPlainWikified = function() {\n\treturn this.wiki.renderText(\"text/plain\",\"text/vnd.tiddlywiki\",this.getValueAsText(),{parentWidget: this});\n};\n\nViewWidget.prototype.getValueAsHtmlEncodedPlainWikified = function() {\n\treturn $tw.utils.htmlEncode(this.wiki.renderText(\"text/plain\",\"text/vnd.tiddlywiki\",this.getValueAsText(),{parentWidget: this}));\n};\n\nViewWidget.prototype.getValueAsHtmlEncoded = function() {\n\treturn $tw.utils.htmlEncode(this.getValueAsText());\n};\n\nViewWidget.prototype.getValueAsUrlEncoded = function() {\n\treturn encodeURIComponent(this.getValueAsText());\n};\n\nViewWidget.prototype.getValueAsDoubleUrlEncoded = function() {\n\treturn encodeURIComponent(encodeURIComponent(this.getValueAsText()));\n};\n\nViewWidget.prototype.getValueAsDate = function(format) {\n\tformat = format || \"YYYY MM DD 0hh:0mm\";\n\tvar value = $tw.utils.parseDate(this.getValue());\n\tif(value && $tw.utils.isDate(value) && value.toString() !== \"Invalid Date\") {\n\t\treturn $tw.utils.formatDateString(value,format);\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\nViewWidget.prototype.getValueAsRelativeDate = function(format) {\n\tvar value = $tw.utils.parseDate(this.getValue());\n\tif(value && $tw.utils.isDate(value) && value.toString() !== \"Invalid Date\") {\n\t\treturn $tw.utils.getRelativeDate((new Date()) - (new Date(value))).description;\n\t} else {\n\t\treturn \"\";\n\t}\n};\n\nViewWidget.prototype.getValueAsStrippedComments = function() {\n\tvar lines = this.getValueAsText().split(\"\\n\"),\n\t\tout = [];\n\tfor(var line=0; line<lines.length; line++) {\n\t\tvar text = lines[line];\n\t\tif(!/^\\s*\\/\\/#/.test(text)) {\n\t\t\tout.push(text);\n\t\t}\n\t}\n\treturn out.join(\"\\n\");\n};\n\nViewWidget.prototype.getValueAsJsEncoded = function() {\n\treturn $tw.utils.stringify(this.getValueAsText());\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nViewWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\tif(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.template || changedAttributes.format || changedTiddlers[this.viewTitle]) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\treturn false;\t\n\t}\n};\n\nexports.view = ViewWidget;\n\n})();\n", "title": "$:/core/modules/widgets/view.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/widget.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/widget.js\ntype: application/javascript\nmodule-type: widget\n\nWidget base class\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nCreate a widget object for a parse tree node\n\tparseTreeNode: reference to the parse tree node to be rendered\n\toptions: see below\nOptions include:\n\twiki: mandatory reference to wiki associated with this render tree\n\tparentWidget: optional reference to a parent renderer node for the context chain\n\tdocument: optional document object to use instead of global document\n*/\nvar Widget = function(parseTreeNode,options) {\n\tif(arguments.length > 0) {\n\t\tthis.initialise(parseTreeNode,options);\n\t}\n};\n\n/*\nInitialise widget properties. These steps are pulled out of the constructor so that we can reuse them in subclasses\n*/\nWidget.prototype.initialise = function(parseTreeNode,options) {\n\toptions = options || {};\n\t// Save widget info\n\tthis.parseTreeNode = parseTreeNode;\n\tthis.wiki = options.wiki;\n\tthis.parentWidget = options.parentWidget;\n\tthis.variablesConstructor = function() {};\n\tthis.variablesConstructor.prototype = this.parentWidget ? this.parentWidget.variables : {};\n\tthis.variables = new this.variablesConstructor();\n\tthis.document = options.document;\n\tthis.attributes = {};\n\tthis.children = [];\n\tthis.domNodes = [];\n\tthis.eventListeners = {};\n\t// Hashmap of the widget classes\n\tif(!this.widgetClasses) {\n\t\tWidget.prototype.widgetClasses = $tw.modules.applyMethods(\"widget\");\n\t}\n};\n\n/*\nRender this widget into the DOM\n*/\nWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nWidget.prototype.execute = function() {\n\tthis.makeChildWidgets();\n};\n\n/*\nSet the value of a context variable\nname: name of the variable\nvalue: value of the variable\nparams: array of {name:, default:} for each parameter\n*/\nWidget.prototype.setVariable = function(name,value,params) {\n\tthis.variables[name] = {value: value, params: params};\n};\n\n/*\nGet the prevailing value of a context variable\nname: name of variable\noptions: see below\nOptions include\nparams: array of {name:, value:} for each parameter\ndefaultValue: default value if the variable is not defined\n*/\nWidget.prototype.getVariable = function(name,options) {\n\toptions = options || {};\n\tvar actualParams = options.params || [],\n\t\tparentWidget = this.parentWidget;\n\t// Check for the variable defined in the parent widget (or an ancestor in the prototype chain)\n\tif(parentWidget && name in parentWidget.variables) {\n\t\tvar variable = parentWidget.variables[name],\n\t\t\tvalue = variable.value;\n\t\t// Substitute any parameters specified in the definition\n\t\tvalue = this.substituteVariableParameters(value,variable.params,actualParams);\n\t\tvalue = this.substituteVariableReferences(value);\n\t\treturn value;\n\t}\n\t// If the variable doesn't exist in the parent widget then look for a macro module\n\treturn this.evaluateMacroModule(name,actualParams,options.defaultValue);\n};\n\nWidget.prototype.substituteVariableParameters = function(text,formalParams,actualParams) {\n\tif(formalParams) {\n\t\tvar nextAnonParameter = 0, // Next candidate anonymous parameter in macro call\n\t\t\tparamInfo, paramValue;\n\t\t// Step through each of the parameters in the macro definition\n\t\tfor(var p=0; p<formalParams.length; p++) {\n\t\t\t// Check if we've got a macro call parameter with the same name\n\t\t\tparamInfo = formalParams[p];\n\t\t\tparamValue = undefined;\n\t\t\tfor(var m=0; m<actualParams.length; m++) {\n\t\t\t\tif(actualParams[m].name === paramInfo.name) {\n\t\t\t\t\tparamValue = actualParams[m].value;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If not, use the next available anonymous macro call parameter\n\t\t\twhile(nextAnonParameter < actualParams.length && actualParams[nextAnonParameter].name) {\n\t\t\t\tnextAnonParameter++;\n\t\t\t}\n\t\t\tif(paramValue === undefined && nextAnonParameter < actualParams.length) {\n\t\t\t\tparamValue = actualParams[nextAnonParameter++].value;\n\t\t\t}\n\t\t\t// If we've still not got a value, use the default, if any\n\t\t\tparamValue = paramValue || paramInfo[\"default\"] || \"\";\n\t\t\t// Replace any instances of this parameter\n\t\t\ttext = $tw.utils.replaceString(text,new RegExp(\"\\\\$\" + $tw.utils.escapeRegExp(paramInfo.name) + \"\\\\$\",\"mg\"),paramValue);\n\t\t}\n\t}\n\treturn text;\n};\n\nWidget.prototype.substituteVariableReferences = function(text) {\n\tvar self = this;\n\treturn (text || \"\").replace(/\\$\\(([^\\)\\$]+)\\)\\$/g,function(match,p1,offset,string) {\n\t\treturn self.getVariable(p1,{defaultValue: \"\"});\n\t});\n};\n\nWidget.prototype.evaluateMacroModule = function(name,actualParams,defaultValue) {\n\tif($tw.utils.hop($tw.macros,name)) {\n\t\tvar macro = $tw.macros[name],\n\t\t\targs = [];\n\t\tif(macro.params.length > 0) {\n\t\t\tvar nextAnonParameter = 0, // Next candidate anonymous parameter in macro call\n\t\t\t\tparamInfo, paramValue;\n\t\t\t// Step through each of the parameters in the macro definition\n\t\t\tfor(var p=0; p<macro.params.length; p++) {\n\t\t\t\t// Check if we've got a macro call parameter with the same name\n\t\t\t\tparamInfo = macro.params[p];\n\t\t\t\tparamValue = undefined;\n\t\t\t\tfor(var m=0; m<actualParams.length; m++) {\n\t\t\t\t\tif(actualParams[m].name === paramInfo.name) {\n\t\t\t\t\t\tparamValue = actualParams[m].value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// If not, use the next available anonymous macro call parameter\n\t\t\t\twhile(nextAnonParameter < actualParams.length && actualParams[nextAnonParameter].name) {\n\t\t\t\t\tnextAnonParameter++;\n\t\t\t\t}\n\t\t\t\tif(paramValue === undefined && nextAnonParameter < actualParams.length) {\n\t\t\t\t\tparamValue = actualParams[nextAnonParameter++].value;\n\t\t\t\t}\n\t\t\t\t// If we've still not got a value, use the default, if any\n\t\t\t\tparamValue = paramValue || paramInfo[\"default\"] || \"\";\n\t\t\t\t// Save the parameter\n\t\t\t\targs.push(paramValue);\n\t\t\t}\n\t\t}\n\t\telse for(var i=0; i<actualParams.length; ++i) {\n\t\t\targs.push(actualParams[i].value);\n\t\t}\n\t\treturn (macro.run.apply(this,args) || \"\").toString();\n\t} else {\n\t\treturn defaultValue;\n\t}\n};\n\n/*\nCheck whether a given context variable value exists in the parent chain\n*/\nWidget.prototype.hasVariable = function(name,value) {\n\tvar node = this;\n\twhile(node) {\n\t\tif($tw.utils.hop(node.variables,name) && node.variables[name].value === value) {\n\t\t\treturn true;\n\t\t}\n\t\tnode = node.parentWidget;\n\t}\n\treturn false;\n};\n\n/*\nConstruct a qualifying string based on a hash of concatenating the values of a given variable in the parent chain\n*/\nWidget.prototype.getStateQualifier = function(name) {\n\tthis.qualifiers = this.qualifiers || Object.create(null);\n\tname = name || \"transclusion\";\n\tif(this.qualifiers[name]) {\n\t\treturn this.qualifiers[name];\n\t} else {\n\t\tvar output = [],\n\t\t\tnode = this;\n\t\twhile(node && node.parentWidget) {\n\t\t\tif($tw.utils.hop(node.parentWidget.variables,name)) {\n\t\t\t\toutput.push(node.getVariable(name));\n\t\t\t}\n\t\t\tnode = node.parentWidget;\n\t\t}\n\t\tvar value = $tw.utils.hashString(output.join(\"\"));\n\t\tthis.qualifiers[name] = value;\n\t\treturn value;\n\t}\n};\n\n/*\nCompute the current values of the attributes of the widget. Returns a hashmap of the names of the attributes that have changed\n*/\nWidget.prototype.computeAttributes = function() {\n\tvar changedAttributes = {},\n\t\tself = this,\n\t\tvalue;\n\t$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {\n\t\tif(attribute.type === \"filtered\") {\n\t\t\tvalue = self.wiki.filterTiddlers(attribute.filter,self)[0] || \"\";\n\t\t} else if(attribute.type === \"indirect\") {\n\t\t\tvalue = self.wiki.getTextReference(attribute.textReference,\"\",self.getVariable(\"currentTiddler\"));\n\t\t} else if(attribute.type === \"macro\") {\n\t\t\tvalue = self.getVariable(attribute.value.name,{params: attribute.value.params});\n\t\t} else { // String attribute\n\t\t\tvalue = attribute.value;\n\t\t}\n\t\t// Check whether the attribute has changed\n\t\tif(self.attributes[name] !== value) {\n\t\t\tself.attributes[name] = value;\n\t\t\tchangedAttributes[name] = true;\n\t\t}\n\t});\n\treturn changedAttributes;\n};\n\n/*\nCheck for the presence of an attribute\n*/\nWidget.prototype.hasAttribute = function(name) {\n\treturn $tw.utils.hop(this.attributes,name);\n};\n\n/*\nGet the value of an attribute\n*/\nWidget.prototype.getAttribute = function(name,defaultText) {\n\tif($tw.utils.hop(this.attributes,name)) {\n\t\treturn this.attributes[name];\n\t} else {\n\t\treturn defaultText;\n\t}\n};\n\n/*\nAssign the computed attributes of the widget to a domNode\noptions include:\nexcludeEventAttributes: ignores attributes whose name begins with \"on\"\n*/\nWidget.prototype.assignAttributes = function(domNode,options) {\n\toptions = options || {};\n\tvar self = this;\n\t$tw.utils.each(this.attributes,function(v,a) {\n\t\t// Check exclusions\n\t\tif(options.excludeEventAttributes && a.substr(0,2) === \"on\") {\n\t\t\tv = undefined;\n\t\t}\n\t\tif(v !== undefined) {\n\t\t\tvar b = a.split(\":\");\n\t\t\t// Setting certain attributes can cause a DOM error (eg xmlns on the svg element)\n\t\t\ttry {\n\t\t\t\tif (b.length == 2 && b[0] == \"xlink\"){\n\t\t\t\t\tdomNode.setAttributeNS(\"http://www.w3.org/1999/xlink\",b[1],v);\n\t\t\t\t} else {\n\t\t\t\t\tdomNode.setAttributeNS(null,a,v);\n\t\t\t\t}\n\t\t\t} catch(e) {\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\nMake child widgets correspondng to specified parseTreeNodes\n*/\nWidget.prototype.makeChildWidgets = function(parseTreeNodes) {\n\tthis.children = [];\n\tvar self = this;\n\t$tw.utils.each(parseTreeNodes || (this.parseTreeNode && this.parseTreeNode.children),function(childNode) {\n\t\tself.children.push(self.makeChildWidget(childNode));\n\t});\n};\n\n/*\nConstruct the widget object for a parse tree node\n*/\nWidget.prototype.makeChildWidget = function(parseTreeNode) {\n\tvar WidgetClass = this.widgetClasses[parseTreeNode.type];\n\tif(!WidgetClass) {\n\t\tWidgetClass = this.widgetClasses.text;\n\t\tparseTreeNode = {type: \"text\", text: \"Undefined widget '\" + parseTreeNode.type + \"'\"};\n\t}\n\treturn new WidgetClass(parseTreeNode,{\n\t\twiki: this.wiki,\n\t\tvariables: {},\n\t\tparentWidget: this,\n\t\tdocument: this.document\n\t});\n};\n\n/*\nGet the next sibling of this widget\n*/\nWidget.prototype.nextSibling = function() {\n\tif(this.parentWidget) {\n\t\tvar index = this.parentWidget.children.indexOf(this);\n\t\tif(index !== -1 && index < this.parentWidget.children.length-1) {\n\t\t\treturn this.parentWidget.children[index+1];\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nGet the previous sibling of this widget\n*/\nWidget.prototype.previousSibling = function() {\n\tif(this.parentWidget) {\n\t\tvar index = this.parentWidget.children.indexOf(this);\n\t\tif(index !== -1 && index > 0) {\n\t\t\treturn this.parentWidget.children[index-1];\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nRender the children of this widget into the DOM\n*/\nWidget.prototype.renderChildren = function(parent,nextSibling) {\n\t$tw.utils.each(this.children,function(childWidget) {\n\t\tchildWidget.render(parent,nextSibling);\n\t});\n};\n\n/*\nAdd a list of event listeners from an array [{type:,handler:},...]\n*/\nWidget.prototype.addEventListeners = function(listeners) {\n\tvar self = this;\n\t$tw.utils.each(listeners,function(listenerInfo) {\n\t\tself.addEventListener(listenerInfo.type,listenerInfo.handler);\n\t});\n};\n\n/*\nAdd an event listener\n*/\nWidget.prototype.addEventListener = function(type,handler) {\n\tvar self = this;\n\tif(typeof handler === \"string\") { // The handler is a method name on this widget\n\t\tthis.eventListeners[type] = function(event) {\n\t\t\treturn self[handler].call(self,event);\n\t\t};\n\t} else { // The handler is a function\n\t\tthis.eventListeners[type] = function(event) {\n\t\t\treturn handler.call(self,event);\n\t\t};\n\t}\n};\n\n/*\nDispatch an event to a widget. If the widget doesn't handle the event then it is also dispatched to the parent widget\n*/\nWidget.prototype.dispatchEvent = function(event) {\n\t// Dispatch the event if this widget handles it\n\tvar listener = this.eventListeners[event.type];\n\tif(listener) {\n\t\t// Don't propagate the event if the listener returned false\n\t\tif(!listener(event)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t// Dispatch the event to the parent widget\n\tif(this.parentWidget) {\n\t\treturn this.parentWidget.dispatchEvent(event);\n\t}\n\treturn true;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nWidget.prototype.refresh = function(changedTiddlers) {\n\treturn this.refreshChildren(changedTiddlers);\n};\n\n/*\nRebuild a previously rendered widget\n*/\nWidget.prototype.refreshSelf = function() {\n\tvar nextSibling = this.findNextSiblingDomNode();\n\tthis.removeChildDomNodes();\n\tthis.render(this.parentDomNode,nextSibling);\n};\n\n/*\nRefresh all the children of a widget\n*/\nWidget.prototype.refreshChildren = function(changedTiddlers) {\n\tvar self = this,\n\t\trefreshed = false;\n\t$tw.utils.each(this.children,function(childWidget) {\n\t\trefreshed = childWidget.refresh(changedTiddlers) || refreshed;\n\t});\n\treturn refreshed;\n};\n\n/*\nFind the next sibling in the DOM to this widget. This is done by scanning the widget tree through all next siblings and their descendents that share the same parent DOM node\n*/\nWidget.prototype.findNextSiblingDomNode = function(startIndex) {\n\t// Refer to this widget by its index within its parents children\n\tvar parent = this.parentWidget,\n\t\tindex = startIndex !== undefined ? startIndex : parent.children.indexOf(this);\nif(index === -1) {\n\tthrow \"node not found in parents children\";\n}\n\t// Look for a DOM node in the later siblings\n\twhile(++index < parent.children.length) {\n\t\tvar domNode = parent.children[index].findFirstDomNode();\n\t\tif(domNode) {\n\t\t\treturn domNode;\n\t\t}\n\t}\n\t// Go back and look for later siblings of our parent if it has the same parent dom node\n\tvar grandParent = parent.parentWidget;\n\tif(grandParent && parent.parentDomNode === this.parentDomNode) {\n\t\tindex = grandParent.children.indexOf(parent);\n\t\tif(index !== -1) {\n\t\t\treturn parent.findNextSiblingDomNode(index);\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nFind the first DOM node generated by a widget or its children\n*/\nWidget.prototype.findFirstDomNode = function() {\n\t// Return the first dom node of this widget, if we've got one\n\tif(this.domNodes.length > 0) {\n\t\treturn this.domNodes[0];\n\t}\n\t// Otherwise, recursively call our children\n\tfor(var t=0; t<this.children.length; t++) {\n\t\tvar domNode = this.children[t].findFirstDomNode();\n\t\tif(domNode) {\n\t\t\treturn domNode;\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nRemove any DOM nodes created by this widget or its children\n*/\nWidget.prototype.removeChildDomNodes = function() {\n\t// If this widget has directly created DOM nodes, delete them and exit. This assumes that any child widgets are contained within the created DOM nodes, which would normally be the case\n\tif(this.domNodes.length > 0) {\n\t\t$tw.utils.each(this.domNodes,function(domNode) {\n\t\t\tdomNode.parentNode.removeChild(domNode);\n\t\t});\n\t\tthis.domNodes = [];\n\t} else {\n\t\t// Otherwise, ask the child widgets to delete their DOM nodes\n\t\t$tw.utils.each(this.children,function(childWidget) {\n\t\t\tchildWidget.removeChildDomNodes();\n\t\t});\n\t}\n};\n\n/*\nInvoke the action widgets that are descendents of the current widget.\n*/\nWidget.prototype.invokeActions = function(triggeringWidget,event) {\n\tvar handled = false;\n\t// For each child widget\n\tfor(var t=0; t<this.children.length; t++) {\n\t\tvar child = this.children[t];\n\t\t// Invoke the child if it is an action widget\n\t\tif(child.invokeAction) {\n\t\t\tchild.refreshSelf();\n\t\t\tif(child.invokeAction(triggeringWidget,event)) {\n\t\t\t\thandled = true;\n\t\t\t}\n\t\t}\n\t\t// Propagate through through the child if it permits it\n\t\tif(child.allowActionPropagation() && child.invokeActions(triggeringWidget,event)) {\n\t\t\thandled = true;\n\t\t}\n\t}\n\treturn handled;\n};\n\n/*\nInvoke the action widgets defined in a string\n*/\nWidget.prototype.invokeActionString = function(actions,triggeringWidget,event,variables) {\n\tactions = actions || \"\";\n\tvar parser = this.wiki.parseText(\"text/vnd.tiddlywiki\",actions,{\n\t\t\tparentWidget: this,\n\t\t\tdocument: this.document\n\t\t}),\n\t\twidgetNode = this.wiki.makeWidget(parser,{\n\t\t\tparentWidget: this,\n\t\t\tdocument: this.document,\n\t\t\tvariables: variables\n\t\t});\n\tvar container = this.document.createElement(\"div\");\n\twidgetNode.render(container,null);\n\treturn widgetNode.invokeActions(this,event);\n};\n\nWidget.prototype.allowActionPropagation = function() {\n\treturn true;\n};\n\nexports.widget = Widget;\n\n})();\n", "title": "$:/core/modules/widgets/widget.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/widgets/wikify.js": { "text": "/*\\\ntitle: $:/core/modules/widgets/wikify.js\ntype: application/javascript\nmodule-type: widget\n\nWidget to wikify text into a variable\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar Widget = require(\"$:/core/modules/widgets/widget.js\").widget;\n\nvar WikifyWidget = function(parseTreeNode,options) {\n\tthis.initialise(parseTreeNode,options);\n};\n\n/*\nInherit from the base widget class\n*/\nWikifyWidget.prototype = new Widget();\n\n/*\nRender this widget into the DOM\n*/\nWikifyWidget.prototype.render = function(parent,nextSibling) {\n\tthis.parentDomNode = parent;\n\tthis.computeAttributes();\n\tthis.execute();\n\tthis.renderChildren(parent,nextSibling);\n};\n\n/*\nCompute the internal state of the widget\n*/\nWikifyWidget.prototype.execute = function() {\n\t// Get our parameters\n\tthis.wikifyName = this.getAttribute(\"name\");\n\tthis.wikifyText = this.getAttribute(\"text\");\n\tthis.wikifyType = this.getAttribute(\"type\");\n\tthis.wikifyMode = this.getAttribute(\"mode\",\"block\");\n\tthis.wikifyOutput = this.getAttribute(\"output\",\"text\");\n\t// Create the parse tree\n\tthis.wikifyParser = this.wiki.parseText(this.wikifyType,this.wikifyText,{\n\t\t\tparseAsInline: this.wikifyMode === \"inline\"\n\t\t});\n\t// Create the widget tree \n\tthis.wikifyWidgetNode = this.wiki.makeWidget(this.wikifyParser,{\n\t\t\tdocument: $tw.fakeDocument,\n\t\t\tparentWidget: this\n\t\t});\n\t// Render the widget tree to the container\n\tthis.wikifyContainer = $tw.fakeDocument.createElement(\"div\");\n\tthis.wikifyWidgetNode.render(this.wikifyContainer,null);\n\tthis.wikifyResult = this.getResult();\n\t// Set context variable\n\tthis.setVariable(this.wikifyName,this.wikifyResult);\n\t// Construct the child widgets\n\tthis.makeChildWidgets();\n};\n\n/*\nReturn the result string\n*/\nWikifyWidget.prototype.getResult = function() {\n\tvar result;\n\tswitch(this.wikifyOutput) {\n\t\tcase \"text\":\n\t\t\tresult = this.wikifyContainer.textContent;\n\t\t\tbreak;\n\t\tcase \"formattedtext\":\n\t\t\tresult = this.wikifyContainer.formattedTextContent;\n\t\t\tbreak;\n\t\tcase \"html\":\n\t\t\tresult = this.wikifyContainer.innerHTML;\n\t\t\tbreak;\n\t\tcase \"parsetree\":\n\t\t\tresult = JSON.stringify(this.wikifyParser.tree,0,$tw.config.preferences.jsonSpaces);\n\t\t\tbreak;\n\t\tcase \"widgettree\":\n\t\t\tresult = JSON.stringify(this.getWidgetTree(),0,$tw.config.preferences.jsonSpaces);\n\t\t\tbreak;\n\t}\n\treturn result;\n};\n\n/*\nReturn a string of the widget tree\n*/\nWikifyWidget.prototype.getWidgetTree = function() {\n\tvar copyNode = function(widgetNode,resultNode) {\n\t\t\tvar type = widgetNode.parseTreeNode.type;\n\t\t\tresultNode.type = type;\n\t\t\tswitch(type) {\n\t\t\t\tcase \"element\":\n\t\t\t\t\tresultNode.tag = widgetNode.parseTreeNode.tag;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"text\":\n\t\t\t\t\tresultNode.text = widgetNode.parseTreeNode.text;\n\t\t\t\t\tbreak;\t\n\t\t\t}\n\t\t\tif(Object.keys(widgetNode.attributes || {}).length > 0) {\n\t\t\t\tresultNode.attributes = {};\n\t\t\t\t$tw.utils.each(widgetNode.attributes,function(attr,attrName) {\n\t\t\t\t\tresultNode.attributes[attrName] = widgetNode.getAttribute(attrName);\n\t\t\t\t});\n\t\t\t}\n\t\t\tif(Object.keys(widgetNode.children || {}).length > 0) {\n\t\t\t\tresultNode.children = [];\n\t\t\t\t$tw.utils.each(widgetNode.children,function(widgetChildNode) {\n\t\t\t\t\tvar node = {};\n\t\t\t\t\tresultNode.children.push(node);\n\t\t\t\t\tcopyNode(widgetChildNode,node);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tresults = {};\n\tcopyNode(this.wikifyWidgetNode,results);\n\treturn results;\n};\n\n/*\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\n*/\nWikifyWidget.prototype.refresh = function(changedTiddlers) {\n\tvar changedAttributes = this.computeAttributes();\n\t// Refresh ourselves entirely if any of our attributes have changed\n\tif(changedAttributes.name || changedAttributes.text || changedAttributes.type || changedAttributes.mode || changedAttributes.output) {\n\t\tthis.refreshSelf();\n\t\treturn true;\n\t} else {\n\t\t// Refresh the widget tree\n\t\tif(this.wikifyWidgetNode.refresh(changedTiddlers)) {\n\t\t\t// Check if there was any change\n\t\t\tvar result = this.getResult();\n\t\t\tif(result !== this.wikifyResult) {\n\t\t\t\t// If so, save the change\n\t\t\t\tthis.wikifyResult = result;\n\t\t\t\tthis.setVariable(this.wikifyName,this.wikifyResult);\n\t\t\t\t// Refresh each of our child widgets\n\t\t\t\t$tw.utils.each(this.children,function(childWidget) {\n\t\t\t\t\tchildWidget.refreshSelf();\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t// Just refresh the children\n\t\treturn this.refreshChildren(changedTiddlers);\n\t}\n};\n\nexports.wikify = WikifyWidget;\n\n})();\n", "title": "$:/core/modules/widgets/wikify.js", "type": "application/javascript", "module-type": "widget" }, "$:/core/modules/wiki-bulkops.js": { "text": "/*\\\ntitle: $:/core/modules/wiki-bulkops.js\ntype: application/javascript\nmodule-type: wikimethod\n\nBulk tiddler operations such as rename.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n/*\nRename a tiddler, and relink any tags or lists that reference it.\n*/\nfunction renameTiddler(fromTitle,toTitle,options) {\n\tfromTitle = (fromTitle || \"\").trim();\n\ttoTitle = (toTitle || \"\").trim();\n\toptions = options || {};\n\tif(fromTitle && toTitle && fromTitle !== toTitle) {\n\t\t// Rename the tiddler itself\n\t\tvar oldTiddler = this.getTiddler(fromTitle),\n\t\t\tnewTiddler = new $tw.Tiddler(oldTiddler,{title: toTitle},this.getModificationFields());\n\t\tnewTiddler = $tw.hooks.invokeHook(\"th-renaming-tiddler\",newTiddler,oldTiddler);\n\t\tthis.addTiddler(newTiddler);\n\t\tthis.deleteTiddler(fromTitle);\n\t\t// Rename any tags or lists that reference it\n\t\tthis.relinkTiddler(fromTitle,toTitle,options)\n\t}\n}\n\n/*\nRelink any tags or lists that reference a given tiddler\n*/\nfunction relinkTiddler(fromTitle,toTitle,options) {\n\tvar self = this;\n\tfromTitle = (fromTitle || \"\").trim();\n\ttoTitle = (toTitle || \"\").trim();\n\toptions = options || {};\n\tif(fromTitle && toTitle && fromTitle !== toTitle) {\n\t\tthis.each(function(tiddler,title) {\n\t\t\tvar type = tiddler.fields.type || \"\";\n\t\t\t// Don't touch plugins or JavaScript modules\n\t\t\tif(!tiddler.fields[\"plugin-type\"] && type !== \"application/javascript\") {\n\t\t\t\tvar tags = (tiddler.fields.tags || []).slice(0),\n\t\t\t\t\tlist = (tiddler.fields.list || []).slice(0),\n\t\t\t\t\tisModified = false;\n\t\t\t\tif(!options.dontRenameInTags) {\n\t\t\t\t\t// Rename tags\n\t\t\t\t\t$tw.utils.each(tags,function (title,index) {\n\t\t\t\t\t\tif(title === fromTitle) {\nconsole.log(\"Renaming tag '\" + tags[index] + \"' to '\" + toTitle + \"' of tiddler '\" + tiddler.fields.title + \"'\");\n\t\t\t\t\t\t\ttags[index] = toTitle;\n\t\t\t\t\t\t\tisModified = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif(!options.dontRenameInLists) {\n\t\t\t\t\t// Rename lists\n\t\t\t\t\t$tw.utils.each(list,function (title,index) {\n\t\t\t\t\t\tif(title === fromTitle) {\nconsole.log(\"Renaming list item '\" + list[index] + \"' to '\" + toTitle + \"' of tiddler '\" + tiddler.fields.title + \"'\");\n\t\t\t\t\t\t\tlist[index] = toTitle;\n\t\t\t\t\t\t\tisModified = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif(isModified) {\n\t\t\t\t\tvar newTiddler = new $tw.Tiddler(tiddler,{tags: tags, list: list},self.getModificationFields())\n\t\t\t\t\tnewTiddler = $tw.hooks.invokeHook(\"th-relinking-tiddler\",newTiddler,tiddler);\n\t\t\t\t\tself.addTiddler(newTiddler);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n};\n\nexports.renameTiddler = renameTiddler;\nexports.relinkTiddler = relinkTiddler;\n\n})();\n", "title": "$:/core/modules/wiki-bulkops.js", "type": "application/javascript", "module-type": "wikimethod" }, "$:/core/modules/wiki.js": { "text": "/*\\\ntitle: $:/core/modules/wiki.js\ntype: application/javascript\nmodule-type: wikimethod\n\nExtension methods for the $tw.Wiki object\n\nAdds the following properties to the wiki object:\n\n* `eventListeners` is a hashmap by type of arrays of listener functions\n* `changedTiddlers` is a hashmap describing changes to named tiddlers since wiki change events were last dispatched. Each entry is a hashmap containing two fields:\n\tmodified: true/false\n\tdeleted: true/false\n* `changeCount` is a hashmap by tiddler title containing a numerical index that starts at zero and is incremented each time a tiddler is created changed or deleted\n* `caches` is a hashmap by tiddler title containing a further hashmap of named cache objects. Caches are automatically cleared when a tiddler is modified or deleted\n* `globalCache` is a hashmap by cache name of cache objects that are cleared whenever any tiddler change occurs\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar widget = require(\"$:/core/modules/widgets/widget.js\");\n\nvar USER_NAME_TITLE = \"$:/status/UserName\",\n\tTIMESTAMP_DISABLE_TITLE = \"$:/config/TimestampDisable\";\n\n/*\nGet the value of a text reference. Text references can have any of these forms:\n\t<tiddlertitle>\n\t<tiddlertitle>!!<fieldname>\n\t!!<fieldname> - specifies a field of the current tiddlers\n\t<tiddlertitle>##<index>\n*/\nexports.getTextReference = function(textRef,defaultText,currTiddlerTitle) {\n\tvar tr = $tw.utils.parseTextReference(textRef),\n\t\ttitle = tr.title || currTiddlerTitle;\n\tif(tr.field) {\n\t\tvar tiddler = this.getTiddler(title);\n\t\tif(tr.field === \"title\") { // Special case so we can return the title of a non-existent tiddler\n\t\t\treturn title;\n\t\t} else if(tiddler && $tw.utils.hop(tiddler.fields,tr.field)) {\n\t\t\treturn tiddler.getFieldString(tr.field);\n\t\t} else {\n\t\t\treturn defaultText;\n\t\t}\n\t} else if(tr.index) {\n\t\treturn this.extractTiddlerDataItem(title,tr.index,defaultText);\n\t} else {\n\t\treturn this.getTiddlerText(title,defaultText);\n\t}\n};\n\nexports.setTextReference = function(textRef,value,currTiddlerTitle) {\n\tvar tr = $tw.utils.parseTextReference(textRef),\n\t\ttitle = tr.title || currTiddlerTitle;\n\tthis.setText(title,tr.field,tr.index,value);\n};\n\nexports.setText = function(title,field,index,value,options) {\n\toptions = options || {};\n\tvar creationFields = options.suppressTimestamp ? {} : this.getCreationFields(),\n\t\tmodificationFields = options.suppressTimestamp ? {} : this.getModificationFields();\n\t// Check if it is a reference to a tiddler field\n\tif(index) {\n\t\tvar data = this.getTiddlerData(title,Object.create(null));\n\t\tif(value !== undefined) {\n\t\t\tdata[index] = value;\n\t\t} else {\n\t\t\tdelete data[index];\n\t\t}\n\t\tthis.setTiddlerData(title,data,modificationFields);\n\t} else {\n\t\tvar tiddler = this.getTiddler(title),\n\t\t\tfields = {title: title};\n\t\tfields[field || \"text\"] = value;\n\t\tthis.addTiddler(new $tw.Tiddler(creationFields,tiddler,fields,modificationFields));\n\t}\n};\n\nexports.deleteTextReference = function(textRef,currTiddlerTitle) {\n\tvar tr = $tw.utils.parseTextReference(textRef),\n\t\ttitle,tiddler,fields;\n\t// Check if it is a reference to a tiddler\n\tif(tr.title && !tr.field) {\n\t\tthis.deleteTiddler(tr.title);\n\t// Else check for a field reference\n\t} else if(tr.field) {\n\t\ttitle = tr.title || currTiddlerTitle;\n\t\ttiddler = this.getTiddler(title);\n\t\tif(tiddler && $tw.utils.hop(tiddler.fields,tr.field)) {\n\t\t\tfields = Object.create(null);\n\t\t\tfields[tr.field] = undefined;\n\t\t\tthis.addTiddler(new $tw.Tiddler(tiddler,fields,this.getModificationFields()));\n\t\t}\n\t}\n};\n\nexports.addEventListener = function(type,listener) {\n\tthis.eventListeners = this.eventListeners || {};\n\tthis.eventListeners[type] = this.eventListeners[type] || [];\n\tthis.eventListeners[type].push(listener);\t\n};\n\nexports.removeEventListener = function(type,listener) {\n\tvar listeners = this.eventListeners[type];\n\tif(listeners) {\n\t\tvar p = listeners.indexOf(listener);\n\t\tif(p !== -1) {\n\t\t\tlisteners.splice(p,1);\n\t\t}\n\t}\n};\n\nexports.dispatchEvent = function(type /*, args */) {\n\tvar args = Array.prototype.slice.call(arguments,1),\n\t\tlisteners = this.eventListeners[type];\n\tif(listeners) {\n\t\tfor(var p=0; p<listeners.length; p++) {\n\t\t\tvar listener = listeners[p];\n\t\t\tlistener.apply(listener,args);\n\t\t}\n\t}\n};\n\n/*\nCauses a tiddler to be marked as changed, incrementing the change count, and triggers event handlers.\nThis method should be called after the changes it describes have been made to the wiki.tiddlers[] array.\n\ttitle: Title of tiddler\n\tisDeleted: defaults to false (meaning the tiddler has been created or modified),\n\t\ttrue if the tiddler has been deleted\n*/\nexports.enqueueTiddlerEvent = function(title,isDeleted) {\n\t// Record the touch in the list of changed tiddlers\n\tthis.changedTiddlers = this.changedTiddlers || Object.create(null);\n\tthis.changedTiddlers[title] = this.changedTiddlers[title] || Object.create(null);\n\tthis.changedTiddlers[title][isDeleted ? \"deleted\" : \"modified\"] = true;\n\t// Increment the change count\n\tthis.changeCount = this.changeCount || Object.create(null);\n\tif($tw.utils.hop(this.changeCount,title)) {\n\t\tthis.changeCount[title]++;\n\t} else {\n\t\tthis.changeCount[title] = 1;\n\t}\n\t// Trigger events\n\tthis.eventListeners = this.eventListeners || {};\n\tif(!this.eventsTriggered) {\n\t\tvar self = this;\n\t\t$tw.utils.nextTick(function() {\n\t\t\tvar changes = self.changedTiddlers;\n\t\t\tself.changedTiddlers = Object.create(null);\n\t\t\tself.eventsTriggered = false;\n\t\t\tif($tw.utils.count(changes) > 0) {\n\t\t\t\tself.dispatchEvent(\"change\",changes);\n\t\t\t}\n\t\t});\n\t\tthis.eventsTriggered = true;\n\t}\n};\n\nexports.getSizeOfTiddlerEventQueue = function() {\n\treturn $tw.utils.count(this.changedTiddlers);\n};\n\nexports.clearTiddlerEventQueue = function() {\n\tthis.changedTiddlers = Object.create(null);\n\tthis.changeCount = Object.create(null);\n};\n\nexports.getChangeCount = function(title) {\n\tthis.changeCount = this.changeCount || Object.create(null);\n\tif($tw.utils.hop(this.changeCount,title)) {\n\t\treturn this.changeCount[title];\n\t} else {\n\t\treturn 0;\n\t}\n};\n\n/*\nGenerate an unused title from the specified base\n*/\nexports.generateNewTitle = function(baseTitle,options) {\n\toptions = options || {};\n\tvar c = 0,\n\t\ttitle = baseTitle;\n\twhile(this.tiddlerExists(title) || this.isShadowTiddler(title) || this.findDraft(title)) {\n\t\ttitle = baseTitle + \n\t\t\t(options.prefix || \" \") + \n\t\t\t(++c);\n\t}\n\treturn title;\n};\n\nexports.isSystemTiddler = function(title) {\n\treturn title && title.indexOf(\"$:/\") === 0;\n};\n\nexports.isTemporaryTiddler = function(title) {\n\treturn title && title.indexOf(\"$:/temp/\") === 0;\n};\n\nexports.isImageTiddler = function(title) {\n\tvar tiddler = this.getTiddler(title);\n\tif(tiddler) {\t\t\n\t\tvar contentTypeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || \"text/vnd.tiddlywiki\"];\n\t\treturn !!contentTypeInfo && contentTypeInfo.flags.indexOf(\"image\") !== -1;\n\t} else {\n\t\treturn null;\n\t}\n};\n\n/*\nLike addTiddler() except it will silently reject any plugin tiddlers that are older than the currently loaded version. Returns true if the tiddler was imported\n*/\nexports.importTiddler = function(tiddler) {\n\tvar existingTiddler = this.getTiddler(tiddler.fields.title);\n\t// Check if we're dealing with a plugin\n\tif(tiddler && tiddler.hasField(\"plugin-type\") && tiddler.hasField(\"version\") && existingTiddler && existingTiddler.hasField(\"plugin-type\") && existingTiddler.hasField(\"version\")) {\n\t\t// Reject the incoming plugin if it is older\n\t\tif(!$tw.utils.checkVersions(tiddler.fields.version,existingTiddler.fields.version)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\t// Fall through to adding the tiddler\n\tthis.addTiddler(tiddler);\n\treturn true;\n};\n\n/*\nReturn a hashmap of the fields that should be set when a tiddler is created\n*/\nexports.getCreationFields = function() {\n\tif(this.getTiddlerText(TIMESTAMP_DISABLE_TITLE,\"\").toLowerCase() !== \"yes\") {\n\t\tvar fields = {\n\t\t\t\tcreated: new Date()\n\t\t\t},\n\t\t\tcreator = this.getTiddlerText(USER_NAME_TITLE);\n\t\tif(creator) {\n\t\t\tfields.creator = creator;\n\t\t}\n\t\treturn fields;\n\t} else {\n\t\treturn {};\n\t}\n};\n\n/*\nReturn a hashmap of the fields that should be set when a tiddler is modified\n*/\nexports.getModificationFields = function() {\n\tif(this.getTiddlerText(TIMESTAMP_DISABLE_TITLE,\"\").toLowerCase() !== \"yes\") {\n\t\tvar fields = Object.create(null),\n\t\t\tmodifier = this.getTiddlerText(USER_NAME_TITLE);\n\t\tfields.modified = new Date();\n\t\tif(modifier) {\n\t\t\tfields.modifier = modifier;\n\t\t}\n\t\treturn fields;\n\t} else {\n\t\treturn {};\n\t}\n};\n\n/*\nReturn a sorted array of tiddler titles. Options include:\nsortField: field to sort by\nexcludeTag: tag to exclude\nincludeSystem: whether to include system tiddlers (defaults to false)\n*/\nexports.getTiddlers = function(options) {\n\toptions = options || Object.create(null);\n\tvar self = this,\n\t\tsortField = options.sortField || \"title\",\n\t\ttiddlers = [], t, titles = [];\n\tthis.each(function(tiddler,title) {\n\t\tif(options.includeSystem || !self.isSystemTiddler(title)) {\n\t\t\tif(!options.excludeTag || !tiddler.hasTag(options.excludeTag)) {\n\t\t\t\ttiddlers.push(tiddler);\n\t\t\t}\n\t\t}\n\t});\n\ttiddlers.sort(function(a,b) {\n\t\tvar aa = a.fields[sortField].toLowerCase() || \"\",\n\t\t\tbb = b.fields[sortField].toLowerCase() || \"\";\n\t\tif(aa < bb) {\n\t\t\treturn -1;\n\t\t} else {\n\t\t\tif(aa > bb) {\n\t\t\t\treturn 1;\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t});\n\tfor(t=0; t<tiddlers.length; t++) {\n\t\ttitles.push(tiddlers[t].fields.title);\n\t}\n\treturn titles;\n};\n\nexports.countTiddlers = function(excludeTag) {\n\tvar tiddlers = this.getTiddlers({excludeTag: excludeTag});\n\treturn $tw.utils.count(tiddlers);\n};\n\n/*\nReturns a function iterator(callback) that iterates through the specified titles, and invokes the callback with callback(tiddler,title)\n*/\nexports.makeTiddlerIterator = function(titles) {\n\tvar self = this;\n\tif(!$tw.utils.isArray(titles)) {\n\t\ttitles = Object.keys(titles);\n\t} else {\n\t\ttitles = titles.slice(0);\n\t}\n\treturn function(callback) {\n\t\ttitles.forEach(function(title) {\n\t\t\tcallback(self.getTiddler(title),title);\n\t\t});\n\t};\n};\n\n/*\nSort an array of tiddler titles by a specified field\n\ttitles: array of titles (sorted in place)\n\tsortField: name of field to sort by\n\tisDescending: true if the sort should be descending\n\tisCaseSensitive: true if the sort should consider upper and lower case letters to be different\n*/\nexports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric) {\n\tvar self = this;\n\ttitles.sort(function(a,b) {\n\t\tvar x,y,\n\t\t\tcompareNumbers = function(x,y) {\n\t\t\t\tvar result = \n\t\t\t\t\tisNaN(x) && !isNaN(y) ? (isDescending ? -1 : 1) :\n\t\t\t\t\t!isNaN(x) && isNaN(y) ? (isDescending ? 1 : -1) :\n\t\t\t\t\t\t\t\t\t\t\t(isDescending ? y - x : x - y);\n\t\t\t\treturn result;\n\t\t\t};\n\t\tif(sortField !== \"title\") {\n\t\t\tvar tiddlerA = self.getTiddler(a),\n\t\t\t\ttiddlerB = self.getTiddler(b);\n\t\t\tif(tiddlerA) {\n\t\t\t\ta = tiddlerA.fields[sortField] || \"\";\n\t\t\t} else {\n\t\t\t\ta = \"\";\n\t\t\t}\n\t\t\tif(tiddlerB) {\n\t\t\t\tb = tiddlerB.fields[sortField] || \"\";\n\t\t\t} else {\n\t\t\t\tb = \"\";\n\t\t\t}\n\t\t}\n\t\tx = Number(a);\n\t\ty = Number(b);\n\t\tif(isNumeric && (!isNaN(x) || !isNaN(y))) {\n\t\t\treturn compareNumbers(x,y);\n\t\t} else if($tw.utils.isDate(a) && $tw.utils.isDate(b)) {\n\t\t\treturn isDescending ? b - a : a - b;\n\t\t} else {\n\t\t\ta = String(a);\n\t\t\tb = String(b);\n\t\t\tif(!isCaseSensitive) {\n\t\t\t\ta = a.toLowerCase();\n\t\t\t\tb = b.toLowerCase();\n\t\t\t}\n\t\t\treturn isDescending ? b.localeCompare(a) : a.localeCompare(b);\n\t\t}\n\t});\n};\n\n/*\nFor every tiddler invoke a callback(title,tiddler) with `this` set to the wiki object. Options include:\nsortField: field to sort by\nexcludeTag: tag to exclude\nincludeSystem: whether to include system tiddlers (defaults to false)\n*/\nexports.forEachTiddler = function(/* [options,]callback */) {\n\tvar arg = 0,\n\t\toptions = arguments.length >= 2 ? arguments[arg++] : {},\n\t\tcallback = arguments[arg++],\n\t\ttitles = this.getTiddlers(options),\n\t\tt, tiddler;\n\tfor(t=0; t<titles.length; t++) {\n\t\ttiddler = this.getTiddler(titles[t]);\n\t\tif(tiddler) {\n\t\t\tcallback.call(this,tiddler.fields.title,tiddler);\n\t\t}\n\t}\n};\n\n/*\nReturn an array of tiddler titles that are directly linked from the specified tiddler\n*/\nexports.getTiddlerLinks = function(title) {\n\tvar self = this;\n\t// We'll cache the links so they only get computed if the tiddler changes\n\treturn this.getCacheForTiddler(title,\"links\",function() {\n\t\t// Parse the tiddler\n\t\tvar parser = self.parseTiddler(title);\n\t\t// Count up the links\n\t\tvar links = [],\n\t\t\tcheckParseTree = function(parseTree) {\n\t\t\t\tfor(var t=0; t<parseTree.length; t++) {\n\t\t\t\t\tvar parseTreeNode = parseTree[t];\n\t\t\t\t\tif(parseTreeNode.type === \"link\" && parseTreeNode.attributes.to && parseTreeNode.attributes.to.type === \"string\") {\n\t\t\t\t\t\tvar value = parseTreeNode.attributes.to.value;\n\t\t\t\t\t\tif(links.indexOf(value) === -1) {\n\t\t\t\t\t\t\tlinks.push(value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif(parseTreeNode.children) {\n\t\t\t\t\t\tcheckParseTree(parseTreeNode.children);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\tif(parser) {\n\t\t\tcheckParseTree(parser.tree);\n\t\t}\n\t\treturn links;\n\t});\n};\n\n/*\nReturn an array of tiddler titles that link to the specified tiddler\n*/\nexports.getTiddlerBacklinks = function(targetTitle) {\n\tvar self = this,\n\t\tbacklinks = [];\n\tthis.forEachTiddler(function(title,tiddler) {\n\t\tvar links = self.getTiddlerLinks(title);\n\t\tif(links.indexOf(targetTitle) !== -1) {\n\t\t\tbacklinks.push(title);\n\t\t}\n\t});\n\treturn backlinks;\n};\n\n/*\nReturn a hashmap of tiddler titles that are referenced but not defined. Each value is the number of times the missing tiddler is referenced\n*/\nexports.getMissingTitles = function() {\n\tvar self = this,\n\t\tmissing = [];\n// We should cache the missing tiddler list, even if we recreate it every time any tiddler is modified\n\tthis.forEachTiddler(function(title,tiddler) {\n\t\tvar links = self.getTiddlerLinks(title);\n\t\t$tw.utils.each(links,function(link) {\n\t\t\tif((!self.tiddlerExists(link) && !self.isShadowTiddler(link)) && missing.indexOf(link) === -1) {\n\t\t\t\tmissing.push(link);\n\t\t\t}\n\t\t});\n\t});\n\treturn missing;\n};\n\nexports.getOrphanTitles = function() {\n\tvar self = this,\n\t\torphans = this.getTiddlers();\n\tthis.forEachTiddler(function(title,tiddler) {\n\t\tvar links = self.getTiddlerLinks(title);\n\t\t$tw.utils.each(links,function(link) {\n\t\t\tvar p = orphans.indexOf(link);\n\t\t\tif(p !== -1) {\n\t\t\t\torphans.splice(p,1);\n\t\t\t}\n\t\t});\n\t});\n\treturn orphans; // Todo\n};\n\n/*\nRetrieves a list of the tiddler titles that are tagged with a given tag\n*/\nexports.getTiddlersWithTag = function(tag) {\n\tvar self = this;\n\treturn this.getGlobalCache(\"taglist-\" + tag,function() {\n\t\tvar tagmap = self.getTagMap();\n\t\treturn self.sortByList(tagmap[tag],tag);\n\t});\n};\n\n/*\nGet a hashmap by tag of arrays of tiddler titles\n*/\nexports.getTagMap = function() {\n\tvar self = this;\n\treturn this.getGlobalCache(\"tagmap\",function() {\n\t\tvar tags = Object.create(null),\n\t\t\tstoreTags = function(tagArray,title) {\n\t\t\t\tif(tagArray) {\n\t\t\t\t\tfor(var index=0; index<tagArray.length; index++) {\n\t\t\t\t\t\tvar tag = tagArray[index];\n\t\t\t\t\t\tif($tw.utils.hop(tags,tag)) {\n\t\t\t\t\t\t\ttags[tag].push(title);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttags[tag] = [title];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\ttitle, tiddler;\n\t\t// Collect up all the tags\n\t\tself.eachShadow(function(tiddler,title) {\n\t\t\tif(!self.tiddlerExists(title)) {\n\t\t\t\ttiddler = self.getTiddler(title);\n\t\t\t\tstoreTags(tiddler.fields.tags,title);\n\t\t\t}\n\t\t});\n\t\tself.each(function(tiddler,title) {\n\t\t\tstoreTags(tiddler.fields.tags,title);\n\t\t});\n\t\treturn tags;\n\t});\n};\n\n/*\nLookup a given tiddler and return a list of all the tiddlers that include it in the specified list field\n*/\nexports.findListingsOfTiddler = function(targetTitle,fieldName) {\n\tfieldName = fieldName || \"list\";\n\tvar titles = [];\n\tthis.each(function(tiddler,title) {\n\t\tvar list = $tw.utils.parseStringArray(tiddler.fields[fieldName]);\n\t\tif(list && list.indexOf(targetTitle) !== -1) {\n\t\t\ttitles.push(title);\n\t\t}\n\t});\n\treturn titles;\n};\n\n/*\nSorts an array of tiddler titles according to an ordered list\n*/\nexports.sortByList = function(array,listTitle) {\n\tvar list = this.getTiddlerList(listTitle);\n\tif(!array || array.length === 0) {\n\t\treturn [];\n\t} else {\n\t\tvar titles = [], t, title;\n\t\t// First place any entries that are present in the list\n\t\tfor(t=0; t<list.length; t++) {\n\t\t\ttitle = list[t];\n\t\t\tif(array.indexOf(title) !== -1) {\n\t\t\t\ttitles.push(title);\n\t\t\t}\n\t\t}\n\t\t// Then place any remaining entries\n\t\tfor(t=0; t<array.length; t++) {\n\t\t\ttitle = array[t];\n\t\t\tif(list.indexOf(title) === -1) {\n\t\t\t\ttitles.push(title);\n\t\t\t}\n\t\t}\n\t\t// Finally obey the list-before and list-after fields of each tiddler in turn\n\t\tvar sortedTitles = titles.slice(0);\n\t\tfor(t=0; t<sortedTitles.length; t++) {\n\t\t\ttitle = sortedTitles[t];\n\t\t\tvar currPos = titles.indexOf(title),\n\t\t\t\tnewPos = -1,\n\t\t\t\ttiddler = this.getTiddler(title);\n\t\t\tif(tiddler) {\n\t\t\t\tvar beforeTitle = tiddler.fields[\"list-before\"],\n\t\t\t\t\tafterTitle = tiddler.fields[\"list-after\"];\n\t\t\t\tif(beforeTitle === \"\") {\n\t\t\t\t\tnewPos = 0;\n\t\t\t\t} else if(beforeTitle) {\n\t\t\t\t\tnewPos = titles.indexOf(beforeTitle);\n\t\t\t\t} else if(afterTitle) {\n\t\t\t\t\tnewPos = titles.indexOf(afterTitle);\n\t\t\t\t\tif(newPos >= 0) {\n\t\t\t\t\t\t++newPos;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(newPos === -1) {\n\t\t\t\t\tnewPos = currPos;\n\t\t\t\t}\n\t\t\t\tif(newPos !== currPos) {\n\t\t\t\t\ttitles.splice(currPos,1);\n\t\t\t\t\tif(newPos >= currPos) {\n\t\t\t\t\t\tnewPos--;\n\t\t\t\t\t}\n\t\t\t\t\ttitles.splice(newPos,0,title);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t\treturn titles;\n\t}\n};\n\nexports.getSubTiddler = function(title,subTiddlerTitle) {\n\tvar bundleInfo = this.getPluginInfo(title) || this.getTiddlerDataCached(title);\n\tif(bundleInfo && bundleInfo.tiddlers) {\n\t\tvar subTiddler = bundleInfo.tiddlers[subTiddlerTitle];\n\t\tif(subTiddler) {\n\t\t\treturn new $tw.Tiddler(subTiddler);\n\t\t}\n\t}\n\treturn null;\n};\n\n/*\nRetrieve a tiddler as a JSON string of the fields\n*/\nexports.getTiddlerAsJson = function(title) {\n\tvar tiddler = this.getTiddler(title);\n\tif(tiddler) {\n\t\tvar fields = Object.create(null);\n\t\t$tw.utils.each(tiddler.fields,function(value,name) {\n\t\t\tfields[name] = tiddler.getFieldString(name);\n\t\t});\n\t\treturn JSON.stringify(fields);\n\t} else {\n\t\treturn JSON.stringify({title: title});\n\t}\n};\n\n/*\nGet the content of a tiddler as a JavaScript object. How this is done depends on the type of the tiddler:\n\napplication/json: the tiddler JSON is parsed into an object\napplication/x-tiddler-dictionary: the tiddler is parsed as sequence of name:value pairs\n\nOther types currently just return null.\n\ntitleOrTiddler: string tiddler title or a tiddler object\ndefaultData: default data to be returned if the tiddler is missing or doesn't contain data\n\nNote that the same value is returned for repeated calls for the same tiddler data. The value is frozen to prevent modification; otherwise modifications would be visible to all callers\n*/\nexports.getTiddlerDataCached = function(titleOrTiddler,defaultData) {\n\tvar self = this,\n\t\ttiddler = titleOrTiddler;\n\tif(!(tiddler instanceof $tw.Tiddler)) {\n\t\ttiddler = this.getTiddler(tiddler);\t\n\t}\n\tif(tiddler) {\n\t\treturn this.getCacheForTiddler(tiddler.fields.title,\"data\",function() {\n\t\t\t// Return the frozen value\n\t\t\tvar value = self.getTiddlerData(tiddler.fields.title,undefined);\n\t\t\t$tw.utils.deepFreeze(value);\n\t\t\treturn value;\n\t\t}) || defaultData;\n\t} else {\n\t\treturn defaultData;\n\t}\n};\n\n/*\nAlternative, uncached version of getTiddlerDataCached(). The return value can be mutated freely and reused\n*/\nexports.getTiddlerData = function(titleOrTiddler,defaultData) {\n\tvar tiddler = titleOrTiddler,\n\t\tdata;\n\tif(!(tiddler instanceof $tw.Tiddler)) {\n\t\ttiddler = this.getTiddler(tiddler);\t\n\t}\n\tif(tiddler && tiddler.fields.text) {\n\t\tswitch(tiddler.fields.type) {\n\t\t\tcase \"application/json\":\n\t\t\t\t// JSON tiddler\n\t\t\t\ttry {\n\t\t\t\t\tdata = JSON.parse(tiddler.fields.text);\n\t\t\t\t} catch(ex) {\n\t\t\t\t\treturn defaultData;\n\t\t\t\t}\n\t\t\t\treturn data;\n\t\t\tcase \"application/x-tiddler-dictionary\":\n\t\t\t\treturn $tw.utils.parseFields(tiddler.fields.text);\n\t\t}\n\t}\n\treturn defaultData;\n};\n\n/*\nExtract an indexed field from within a data tiddler\n*/\nexports.extractTiddlerDataItem = function(titleOrTiddler,index,defaultText) {\n\tvar data = this.getTiddlerDataCached(titleOrTiddler,Object.create(null)),\n\t\ttext;\n\tif(data && $tw.utils.hop(data,index)) {\n\t\ttext = data[index];\n\t}\n\tif(typeof text === \"string\" || typeof text === \"number\") {\n\t\treturn text.toString();\n\t} else {\n\t\treturn defaultText;\n\t}\n};\n\n/*\nSet a tiddlers content to a JavaScript object. Currently this is done by setting the tiddler's type to \"application/json\" and setting the text to the JSON text of the data.\ntitle: title of tiddler\ndata: object that can be serialised to JSON\nfields: optional hashmap of additional tiddler fields to be set\n*/\nexports.setTiddlerData = function(title,data,fields) {\n\tvar existingTiddler = this.getTiddler(title),\n\t\tnewFields = {\n\t\t\ttitle: title\n\t};\n\tif(existingTiddler && existingTiddler.fields.type === \"application/x-tiddler-dictionary\") {\n\t\tnewFields.text = $tw.utils.makeTiddlerDictionary(data);\n\t} else {\n\t\tnewFields.type = \"application/json\";\n\t\tnewFields.text = JSON.stringify(data,null,$tw.config.preferences.jsonSpaces);\n\t}\n\tthis.addTiddler(new $tw.Tiddler(this.getCreationFields(),existingTiddler,fields,newFields,this.getModificationFields()));\n};\n\n/*\nReturn the content of a tiddler as an array containing each line\n*/\nexports.getTiddlerList = function(title,field,index) {\n\tif(index) {\n\t\treturn $tw.utils.parseStringArray(this.extractTiddlerDataItem(title,index,\"\"));\n\t}\n\tfield = field || \"list\";\n\tvar tiddler = this.getTiddler(title);\n\tif(tiddler) {\n\t\treturn ($tw.utils.parseStringArray(tiddler.fields[field]) || []).slice(0);\n\t}\n\treturn [];\n};\n\n// Return a named global cache object. Global cache objects are cleared whenever a tiddler change occurs\nexports.getGlobalCache = function(cacheName,initializer) {\n\tthis.globalCache = this.globalCache || Object.create(null);\n\tif($tw.utils.hop(this.globalCache,cacheName)) {\n\t\treturn this.globalCache[cacheName];\n\t} else {\n\t\tthis.globalCache[cacheName] = initializer();\n\t\treturn this.globalCache[cacheName];\n\t}\n};\n\nexports.clearGlobalCache = function() {\n\tthis.globalCache = Object.create(null);\n};\n\n// Return the named cache object for a tiddler. If the cache doesn't exist then the initializer function is invoked to create it\nexports.getCacheForTiddler = function(title,cacheName,initializer) {\n\tthis.caches = this.caches || Object.create(null);\n\tvar caches = this.caches[title];\n\tif(caches && caches[cacheName]) {\n\t\treturn caches[cacheName];\n\t} else {\n\t\tif(!caches) {\n\t\t\tcaches = Object.create(null);\n\t\t\tthis.caches[title] = caches;\n\t\t}\n\t\tcaches[cacheName] = initializer();\n\t\treturn caches[cacheName];\n\t}\n};\n\n// Clear all caches associated with a particular tiddler, or, if the title is null, clear all the caches for all the tiddlers\nexports.clearCache = function(title) {\n\tif(title) {\n\t\tthis.caches = this.caches || Object.create(null);\n\t\tif($tw.utils.hop(this.caches,title)) {\n\t\t\tdelete this.caches[title];\n\t\t}\n\t} else {\n\t\tthis.caches = Object.create(null);\n\t}\n};\n\nexports.initParsers = function(moduleType) {\n\t// Install the parser modules\n\t$tw.Wiki.parsers = {};\n\tvar self = this;\n\t$tw.modules.forEachModuleOfType(\"parser\",function(title,module) {\n\t\tfor(var f in module) {\n\t\t\tif($tw.utils.hop(module,f)) {\n\t\t\t\t$tw.Wiki.parsers[f] = module[f]; // Store the parser class\n\t\t\t}\n\t\t}\n\t});\n};\n\n/*\nParse a block of text of a specified MIME type\n\ttype: content type of text to be parsed\n\ttext: text\n\toptions: see below\nOptions include:\n\tparseAsInline: if true, the text of the tiddler will be parsed as an inline run\n\t_canonical_uri: optional string of the canonical URI of this content\n*/\nexports.parseText = function(type,text,options) {\n\ttext = text || \"\";\n\toptions = options || {};\n\t// Select a parser\n\tvar Parser = $tw.Wiki.parsers[type];\n\tif(!Parser && $tw.utils.getFileExtensionInfo(type)) {\n\t\tParser = $tw.Wiki.parsers[$tw.utils.getFileExtensionInfo(type).type];\n\t}\n\tif(!Parser) {\n\t\tParser = $tw.Wiki.parsers[options.defaultType || \"text/vnd.tiddlywiki\"];\n\t}\n\tif(!Parser) {\n\t\treturn null;\n\t}\n\t// Return the parser instance\n\treturn new Parser(type,text,{\n\t\tparseAsInline: options.parseAsInline,\n\t\twiki: this,\n\t\t_canonical_uri: options._canonical_uri\n\t});\n};\n\n/*\nParse a tiddler according to its MIME type\n*/\nexports.parseTiddler = function(title,options) {\n\toptions = $tw.utils.extend({},options);\n\tvar cacheType = options.parseAsInline ? \"inlineParseTree\" : \"blockParseTree\",\n\t\ttiddler = this.getTiddler(title),\n\t\tself = this;\n\treturn tiddler ? this.getCacheForTiddler(title,cacheType,function() {\n\t\t\tif(tiddler.hasField(\"_canonical_uri\")) {\n\t\t\t\toptions._canonical_uri = tiddler.fields._canonical_uri;\n\t\t\t}\n\t\t\treturn self.parseText(tiddler.fields.type,tiddler.fields.text,options);\n\t\t}) : null;\n};\n\nexports.parseTextReference = function(title,field,index,options) {\n\tvar tiddler,text;\n\tif(options.subTiddler) {\n\t\ttiddler = this.getSubTiddler(title,options.subTiddler);\n\t} else {\n\t\ttiddler = this.getTiddler(title);\n\t\tif(field === \"text\" || (!field && !index)) {\n\t\t\tthis.getTiddlerText(title); // Force the tiddler to be lazily loaded\n\t\t\treturn this.parseTiddler(title,options);\n\t\t}\n\t}\n\tif(field === \"text\" || (!field && !index)) {\n\t\tif(tiddler && tiddler.fields) {\n\t\t\treturn this.parseText(tiddler.fields.type || \"text/vnd.tiddlywiki\",tiddler.fields.text,options);\t\t\t\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t} else if(field) {\n\t\tif(field === \"title\") {\n\t\t\ttext = title;\n\t\t} else {\n\t\t\tif(!tiddler || !tiddler.hasField(field)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\ttext = tiddler.fields[field];\n\t\t}\n\t\treturn this.parseText(\"text/vnd.tiddlywiki\",text.toString(),options);\n\t} else if(index) {\n\t\tthis.getTiddlerText(title); // Force the tiddler to be lazily loaded\n\t\ttext = this.extractTiddlerDataItem(tiddler,index,undefined);\n\t\tif(text === undefined) {\n\t\t\treturn null;\n\t\t}\n\t\treturn this.parseText(\"text/vnd.tiddlywiki\",text,options);\n\t}\n};\n\n/*\nMake a widget tree for a parse tree\nparser: parser object\noptions: see below\nOptions include:\ndocument: optional document to use\nvariables: hashmap of variables to set\nparentWidget: optional parent widget for the root node\n*/\nexports.makeWidget = function(parser,options) {\n\toptions = options || {};\n\tvar widgetNode = {\n\t\t\ttype: \"widget\",\n\t\t\tchildren: []\n\t\t},\n\t\tcurrWidgetNode = widgetNode;\n\t// Create set variable widgets for each variable\n\t$tw.utils.each(options.variables,function(value,name) {\n\t\tvar setVariableWidget = {\n\t\t\ttype: \"set\",\n\t\t\tattributes: {\n\t\t\t\tname: {type: \"string\", value: name},\n\t\t\t\tvalue: {type: \"string\", value: value}\n\t\t\t},\n\t\t\tchildren: []\n\t\t};\n\t\tcurrWidgetNode.children = [setVariableWidget];\n\t\tcurrWidgetNode = setVariableWidget;\n\t});\n\t// Add in the supplied parse tree nodes\n\tcurrWidgetNode.children = parser ? parser.tree : [];\n\t// Create the widget\n\treturn new widget.widget(widgetNode,{\n\t\twiki: this,\n\t\tdocument: options.document || $tw.fakeDocument,\n\t\tparentWidget: options.parentWidget\n\t});\n};\n\n/*\nMake a widget tree for transclusion\ntitle: target tiddler title\noptions: as for wiki.makeWidget() plus:\noptions.field: optional field to transclude (defaults to \"text\")\noptions.mode: transclusion mode \"inline\" or \"block\"\noptions.children: optional array of children for the transclude widget\noptions.importVariables: optional importvariables filter string for macros to be included\noptions.importPageMacros: optional boolean; if true, equivalent to passing \"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\" to options.importVariables\n*/\nexports.makeTranscludeWidget = function(title,options) {\n\toptions = options || {};\n\tvar parseTreeDiv = {tree: [{\n\t\t\ttype: \"element\",\n\t\t\ttag: \"div\",\n\t\t\tchildren: []}]},\n\t\tparseTreeImportVariables = {\n\t\t\ttype: \"importvariables\",\n\t\t\tattributes: {\n\t\t\t\tfilter: {\n\t\t\t\t\tname: \"filter\",\n\t\t\t\t\ttype: \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\tisBlock: false,\n\t\t\tchildren: []},\n\t\tparseTreeTransclude = {\n\t\t\ttype: \"transclude\",\n\t\t\tattributes: {\n\t\t\t\ttiddler: {\n\t\t\t\t\tname: \"tiddler\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tvalue: title}},\n\t\t\tisBlock: !options.parseAsInline};\n\tif(options.importVariables || options.importPageMacros) {\n\t\tif(options.importVariables) {\n\t\t\tparseTreeImportVariables.attributes.filter.value = options.importVariables;\n\t\t} else if(options.importPageMacros) {\n\t\t\tparseTreeImportVariables.attributes.filter.value = \"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\";\n\t\t}\n\t\tparseTreeDiv.tree[0].children.push(parseTreeImportVariables);\n\t\tparseTreeImportVariables.children.push(parseTreeTransclude);\n\t} else {\n\t\tparseTreeDiv.tree[0].children.push(parseTreeTransclude);\n\t}\n\tif(options.field) {\n\t\tparseTreeTransclude.attributes.field = {type: \"string\", value: options.field};\n\t}\n\tif(options.mode) {\n\t\tparseTreeTransclude.attributes.mode = {type: \"string\", value: options.mode};\n\t}\n\tif(options.children) {\n\t\tparseTreeTransclude.children = options.children;\n\t}\n\treturn $tw.wiki.makeWidget(parseTreeDiv,options);\n};\n\n/*\nParse text in a specified format and render it into another format\n\toutputType: content type for the output\n\ttextType: content type of the input text\n\ttext: input text\n\toptions: see below\nOptions include:\nvariables: hashmap of variables to set\nparentWidget: optional parent widget for the root node\n*/\nexports.renderText = function(outputType,textType,text,options) {\n\toptions = options || {};\n\tvar parser = this.parseText(textType,text,options),\n\t\twidgetNode = this.makeWidget(parser,options);\n\tvar container = $tw.fakeDocument.createElement(\"div\");\n\twidgetNode.render(container,null);\n\treturn outputType === \"text/html\" ? container.innerHTML : container.textContent;\n};\n\n/*\nParse text from a tiddler and render it into another format\n\toutputType: content type for the output\n\ttitle: title of the tiddler to be rendered\n\toptions: see below\nOptions include:\nvariables: hashmap of variables to set\nparentWidget: optional parent widget for the root node\n*/\nexports.renderTiddler = function(outputType,title,options) {\n\toptions = options || {};\n\tvar parser = this.parseTiddler(title,options),\n\t\twidgetNode = this.makeWidget(parser,options);\n\tvar container = $tw.fakeDocument.createElement(\"div\");\n\twidgetNode.render(container,null);\n\treturn outputType === \"text/html\" ? container.innerHTML : (outputType === \"text/plain-formatted\" ? container.formattedTextContent : container.textContent);\n};\n\n/*\nReturn an array of tiddler titles that match a search string\n\ttext: The text string to search for\n\toptions: see below\nOptions available:\n\tsource: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title)\n\texclude: An array of tiddler titles to exclude from the search\n\tinvert: If true returns tiddlers that do not contain the specified string\n\tcaseSensitive: If true forces a case sensitive search\n\tliteral: If true, searches for literal string, rather than separate search terms\n\tfield: If specified, restricts the search to the specified field\n*/\nexports.search = function(text,options) {\n\toptions = options || {};\n\tvar self = this,\n\t\tt,\n\t\tinvert = !!options.invert;\n\t// Convert the search string into a regexp for each term\n\tvar terms, searchTermsRegExps,\n\t\tflags = options.caseSensitive ? \"\" : \"i\";\n\tif(options.literal) {\n\t\tif(text.length === 0) {\n\t\t\tsearchTermsRegExps = null;\n\t\t} else {\n\t\t\tsearchTermsRegExps = [new RegExp(\"(\" + $tw.utils.escapeRegExp(text) + \")\",flags)];\n\t\t}\n\t} else {\n\t\tterms = text.split(/ +/);\n\t\tif(terms.length === 1 && terms[0] === \"\") {\n\t\t\tsearchTermsRegExps = null;\n\t\t} else {\n\t\t\tsearchTermsRegExps = [];\n\t\t\tfor(t=0; t<terms.length; t++) {\n\t\t\t\tsearchTermsRegExps.push(new RegExp(\"(\" + $tw.utils.escapeRegExp(terms[t]) + \")\",flags));\n\t\t\t}\n\t\t}\n\t}\n\t// Function to check a given tiddler for the search term\n\tvar searchTiddler = function(title) {\n\t\tif(!searchTermsRegExps) {\n\t\t\treturn true;\n\t\t}\n\t\tvar tiddler = self.getTiddler(title);\n\t\tif(!tiddler) {\n\t\t\ttiddler = new $tw.Tiddler({title: title, text: \"\", type: \"text/vnd.tiddlywiki\"});\n\t\t}\n\t\tvar contentTypeInfo = $tw.config.contentTypeInfo[tiddler.fields.type] || $tw.config.contentTypeInfo[\"text/vnd.tiddlywiki\"],\n\t\t\tmatch;\n\t\tfor(var t=0; t<searchTermsRegExps.length; t++) {\n\t\t\tmatch = false;\n\t\t\tif(options.field) {\n\t\t\t\tmatch = searchTermsRegExps[t].test(tiddler.getFieldString(options.field));\n\t\t\t} else {\n\t\t\t\t// Search title, tags and body\n\t\t\t\tif(contentTypeInfo.encoding === \"utf8\") {\n\t\t\t\t\tmatch = match || searchTermsRegExps[t].test(tiddler.fields.text);\n\t\t\t\t}\n\t\t\t\tvar tags = tiddler.fields.tags ? tiddler.fields.tags.join(\"\\0\") : \"\";\n\t\t\t\tmatch = match || searchTermsRegExps[t].test(tags) || searchTermsRegExps[t].test(tiddler.fields.title);\n\t\t\t}\n\t\t\tif(!match) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t};\n\t// Loop through all the tiddlers doing the search\n\tvar results = [],\n\t\tsource = options.source || this.each;\n\tsource(function(tiddler,title) {\n\t\tif(searchTiddler(title) !== options.invert) {\n\t\t\tresults.push(title);\n\t\t}\n\t});\n\t// Remove any of the results we have to exclude\n\tif(options.exclude) {\n\t\tfor(t=0; t<options.exclude.length; t++) {\n\t\t\tvar p = results.indexOf(options.exclude[t]);\n\t\t\tif(p !== -1) {\n\t\t\t\tresults.splice(p,1);\n\t\t\t}\n\t\t}\n\t}\n\treturn results;\n};\n\n/*\nTrigger a load for a tiddler if it is skinny. Returns the text, or undefined if the tiddler is missing, null if the tiddler is being lazily loaded.\n*/\nexports.getTiddlerText = function(title,defaultText) {\n\tvar tiddler = this.getTiddler(title);\n\t// Return undefined if the tiddler isn't found\n\tif(!tiddler) {\n\t\treturn defaultText;\n\t}\n\tif(tiddler.fields.text !== undefined) {\n\t\t// Just return the text if we've got it\n\t\treturn tiddler.fields.text;\n\t} else {\n\t\t// Tell any listeners about the need to lazily load this tiddler\n\t\tthis.dispatchEvent(\"lazyLoad\",title);\n\t\t// Indicate that the text is being loaded\n\t\treturn null;\n\t}\n};\n\n/*\nCheck whether the text of a tiddler matches a given value. By default, the comparison is case insensitive, and any spaces at either end of the tiddler text is trimmed\n*/\nexports.checkTiddlerText = function(title,targetText,options) {\n\toptions = options || {};\n\tvar text = this.getTiddlerText(title,\"\");\n\tif(!options.noTrim) {\n\t\ttext = text.trim();\n\t}\n\tif(!options.caseSensitive) {\n\t\ttext = text.toLowerCase();\n\t\ttargetText = targetText.toLowerCase();\n\t}\n\treturn text === targetText;\n}\n\n/*\nRead an array of browser File objects, invoking callback(tiddlerFieldsArray) once they're all read\n*/\nexports.readFiles = function(files,callback) {\n\tvar result = [],\n\t\toutstanding = files.length;\n\tfor(var f=0; f<files.length; f++) {\n\t\tthis.readFile(files[f],function(tiddlerFieldsArray) {\n\t\t\tresult.push.apply(result,tiddlerFieldsArray);\n\t\t\tif(--outstanding === 0) {\n\t\t\t\tcallback(result);\n\t\t\t}\n\t\t});\n\t}\n\treturn files.length;\n};\n\n/*\nRead a browser File object, invoking callback(tiddlerFieldsArray) with an array of tiddler fields objects\n*/\nexports.readFile = function(file,callback) {\n\t// Get the type, falling back to the filename extension\n\tvar self = this,\n\t\ttype = file.type;\n\tif(type === \"\" || !type) {\n\t\tvar dotPos = file.name.lastIndexOf(\".\");\n\t\tif(dotPos !== -1) {\n\t\t\tvar fileExtensionInfo = $tw.utils.getFileExtensionInfo(file.name.substr(dotPos));\n\t\t\tif(fileExtensionInfo) {\n\t\t\t\ttype = fileExtensionInfo.type;\n\t\t\t}\n\t\t}\n\t}\n\t// Figure out if we're reading a binary file\n\tvar contentTypeInfo = $tw.config.contentTypeInfo[type],\n\t\tisBinary = contentTypeInfo ? contentTypeInfo.encoding === \"base64\" : false;\n\t// Log some debugging information\n\tif($tw.log.IMPORT) {\n\t\tconsole.log(\"Importing file '\" + file.name + \"', type: '\" + type + \"', isBinary: \" + isBinary);\n\t}\n\t// Create the FileReader\n\tvar reader = new FileReader();\n\t// Onload\n\treader.onload = function(event) {\n\t\tvar text = event.target.result,\n\t\t\ttiddlerFields = {title: file.name || \"Untitled\", type: type};\n\t\tif(isBinary) {\n\t\t\tvar commaPos = text.indexOf(\",\");\n\t\t\tif(commaPos !== -1) {\n\t\t\t\ttext = text.substr(commaPos + 1);\n\t\t\t}\n\t\t}\n\t\t// Check whether this is an encrypted TiddlyWiki file\n\t\tvar encryptedJson = $tw.utils.extractEncryptedStoreArea(text);\n\t\tif(encryptedJson) {\n\t\t\t// If so, attempt to decrypt it with the current password\n\t\t\t$tw.utils.decryptStoreAreaInteractive(encryptedJson,function(tiddlers) {\n\t\t\t\tcallback(tiddlers);\n\t\t\t});\n\t\t} else {\n\t\t\t// Otherwise, just try to deserialise any tiddlers in the file\n\t\t\tcallback(self.deserializeTiddlers(type,text,tiddlerFields));\n\t\t}\n\t};\n\t// Kick off the read\n\tif(isBinary) {\n\t\treader.readAsDataURL(file);\n\t} else {\n\t\treader.readAsText(file);\n\t}\n};\n\n/*\nFind any existing draft of a specified tiddler\n*/\nexports.findDraft = function(targetTitle) {\n\tvar draftTitle = undefined;\n\tthis.forEachTiddler({includeSystem: true},function(title,tiddler) {\n\t\tif(tiddler.fields[\"draft.title\"] && tiddler.fields[\"draft.of\"] === targetTitle) {\n\t\t\tdraftTitle = title;\n\t\t}\n\t});\n\treturn draftTitle;\n}\n\n/*\nCheck whether the specified draft tiddler has been modified.\nIf the original tiddler doesn't exist, create a vanilla tiddler variable,\nto check if additional fields have been added.\n*/\nexports.isDraftModified = function(title) {\n\tvar tiddler = this.getTiddler(title);\n\tif(!tiddler.isDraft()) {\n\t\treturn false;\n\t}\n\tvar ignoredFields = [\"created\", \"modified\", \"title\", \"draft.title\", \"draft.of\"],\n\t\torigTiddler = this.getTiddler(tiddler.fields[\"draft.of\"]) || new $tw.Tiddler({text:\"\", tags:[]}),\n\t\ttitleModified = tiddler.fields[\"draft.title\"] !== tiddler.fields[\"draft.of\"];\n\treturn titleModified || !tiddler.isEqual(origTiddler,ignoredFields);\n};\n\n/*\nAdd a new record to the top of the history stack\ntitle: a title string or an array of title strings\nfromPageRect: page coordinates of the origin of the navigation\nhistoryTitle: title of history tiddler (defaults to $:/HistoryList)\n*/\nexports.addToHistory = function(title,fromPageRect,historyTitle) {\n\tvar story = new $tw.Story({wiki: this, historyTitle: historyTitle});\n\tstory.addToHistory(title,fromPageRect);\n};\n\n/*\nInvoke the available upgrader modules\ntitles: array of tiddler titles to be processed\ntiddlers: hashmap by title of tiddler fields of pending import tiddlers. These can be modified by the upgraders. An entry with no fields indicates a tiddler that was pending import has been suppressed. When entries are added to the pending import the tiddlers hashmap may have entries that are not present in the titles array\nReturns a hashmap of messages keyed by tiddler title.\n*/\nexports.invokeUpgraders = function(titles,tiddlers) {\n\t// Collect up the available upgrader modules\n\tvar self = this;\n\tif(!this.upgraderModules) {\n\t\tthis.upgraderModules = [];\n\t\t$tw.modules.forEachModuleOfType(\"upgrader\",function(title,module) {\n\t\t\tif(module.upgrade) {\n\t\t\t\tself.upgraderModules.push(module);\n\t\t\t}\n\t\t});\n\t}\n\t// Invoke each upgrader in turn\n\tvar messages = {};\n\tfor(var t=0; t<this.upgraderModules.length; t++) {\n\t\tvar upgrader = this.upgraderModules[t],\n\t\t\tupgraderMessages = upgrader.upgrade(this,titles,tiddlers);\n\t\t$tw.utils.extend(messages,upgraderMessages);\n\t}\n\treturn messages;\n};\n\n})();\n\n", "title": "$:/core/modules/wiki.js", "type": "application/javascript", "module-type": "wikimethod" }, "$:/palettes/Blanca": { "title": "$:/palettes/Blanca", "name": "Blanca", "description": "A clean white palette to let you focus", "tags": "$:/tags/Palette", "type": "application/x-tiddler-dictionary", "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #66cccc\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #999999\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #ffffff\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #7897f3\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #ccc\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #ffffff\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #7897f3\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #eeeeee\ntab-border-selected: #cccccc\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ffeedd\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: #eee\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #ff9900\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\n" }, "$:/palettes/Blue": { "title": "$:/palettes/Blue", "name": "Blue", "description": "A blue theme", "tags": "$:/tags/Palette", "type": "application/x-tiddler-dictionary", "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #fff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour foreground>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333353\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #999999\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #ddddff\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #5778d8\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #ffffff\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: <<colour page-background>>\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #5959c0\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: #ccccdd\ntab-border-selected: #ccccdd\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #eeeeff\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #666666\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #ffffff\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #ffffff\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #5959c0\ntoolbar-new-button: #5eb95e\ntoolbar-options-button: rgb(128, 88, 165)\ntoolbar-save-button: #0e90d2\ntoolbar-info-button: #0e90d2\ntoolbar-edit-button: rgb(243, 123, 29)\ntoolbar-close-button: #dd514c\ntoolbar-delete-button: #dd514c\ntoolbar-cancel-button: rgb(243, 123, 29)\ntoolbar-done-button: #5eb95e\nuntagged-background: #999999\nvery-muted-foreground: #888888\n" }, "$:/palettes/Muted": { "title": "$:/palettes/Muted", "name": "Muted", "description": "Bright tiddlers on a muted background", "tags": "$:/tags/Palette", "type": "application/x-tiddler-dictionary", "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #bbb\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #6f6f70\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #29a6ee\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #c2c1c2\nsidebar-foreground-shadow: rgba(255,255,255,0)\nsidebar-foreground: #d3d2d4\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #6f6f70\nsidebar-tab-background: #666667\nsidebar-tab-border-selected: #999\nsidebar-tab-border: #515151\nsidebar-tab-divider: #999\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: #999\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #d1d0d2\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #d5ad34\ntag-foreground: #ffffff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #182955\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #999999\nvery-muted-foreground: #888888\n" }, "$:/palettes/ContrastLight": { "title": "$:/palettes/ContrastLight", "name": "Contrast (Light)", "description": "High contrast and unambiguous (light version)", "tags": "$:/tags/Palette", "type": "application/x-tiddler-dictionary", "text": "alert-background: #f00\nalert-border: <<colour background>>\nalert-highlight: <<colour foreground>>\nalert-muted-foreground: #800\nbackground: #fff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: <<colour background>>\nbutton-foreground: <<colour foreground>>\nbutton-border: <<colour foreground>>\ncode-background: <<colour background>>\ncode-border: <<colour foreground>>\ncode-foreground: <<colour foreground>>\ndirty-indicator: #f00\ndownload-background: #080\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: <<colour foreground>>\ndropdown-tab-background: <<colour foreground>>\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #00a\nexternal-link-foreground: #00e\nforeground: #000\nmessage-background: <<colour foreground>>\nmessage-border: <<colour background>>\nmessage-foreground: <<colour background>>\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: <<colour foreground>>\nmodal-footer-background: <<colour background>>\nmodal-footer-border: <<colour foreground>>\nmodal-header-border: <<colour foreground>>\nmuted-foreground: <<colour foreground>>\nnotification-background: <<colour background>>\nnotification-border: <<colour foreground>>\npage-background: <<colour background>>\npre-background: <<colour background>>\npre-border: <<colour foreground>>\nprimary: #00f\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: <<colour background>>\nsidebar-controls-foreground: <<colour foreground>>\nsidebar-foreground-shadow: rgba(0,0,0, 0)\nsidebar-foreground: <<colour foreground>>\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: <<colour foreground>>\nsidebar-tab-background-selected: <<colour background>>\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: <<colour foreground>>\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: <<colour foreground>>\nsidebar-tiddler-link-foreground: <<colour primary>>\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: <<colour foreground>>\ntab-border-selected: <<colour foreground>>\ntab-border: <<colour foreground>>\ntab-divider: <<colour foreground>>\ntab-foreground-selected: <<colour foreground>>\ntab-foreground: <<colour background>>\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #000\ntag-foreground: #fff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour foreground>>\ntiddler-controls-foreground-hover: #ddd\ntiddler-controls-foreground-selected: #fdd\ntiddler-controls-foreground: <<colour foreground>>\ntiddler-editor-background: <<colour background>>\ntiddler-editor-border-image: <<colour foreground>>\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: <<colour background>>\ntiddler-editor-fields-odd: <<colour background>>\ntiddler-info-background: <<colour background>>\ntiddler-info-border: <<colour foreground>>\ntiddler-info-tab-background: <<colour background>>\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: <<colour foreground>>\ntiddler-title-foreground: <<colour foreground>>\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: <<colour foreground>>\nvery-muted-foreground: #888888\n" }, "$:/palettes/ContrastDark": { "title": "$:/palettes/ContrastDark", "name": "Contrast (Dark)", "description": "High contrast and unambiguous (dark version)", "tags": "$:/tags/Palette", "type": "application/x-tiddler-dictionary", "text": "alert-background: #f00\nalert-border: <<colour background>>\nalert-highlight: <<colour foreground>>\nalert-muted-foreground: #800\nbackground: #000\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: <<colour background>>\nbutton-foreground: <<colour foreground>>\nbutton-border: <<colour foreground>>\ncode-background: <<colour background>>\ncode-border: <<colour foreground>>\ncode-foreground: <<colour foreground>>\ndirty-indicator: #f00\ndownload-background: #080\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: <<colour foreground>>\ndropdown-tab-background: <<colour foreground>>\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #00a\nexternal-link-foreground: #00e\nforeground: #fff\nmessage-background: <<colour foreground>>\nmessage-border: <<colour background>>\nmessage-foreground: <<colour background>>\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: <<colour foreground>>\nmodal-footer-background: <<colour background>>\nmodal-footer-border: <<colour foreground>>\nmodal-header-border: <<colour foreground>>\nmuted-foreground: <<colour foreground>>\nnotification-background: <<colour background>>\nnotification-border: <<colour foreground>>\npage-background: <<colour background>>\npre-background: <<colour background>>\npre-border: <<colour foreground>>\nprimary: #00f\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: <<colour background>>\nsidebar-controls-foreground: <<colour foreground>>\nsidebar-foreground-shadow: rgba(0,0,0, 0)\nsidebar-foreground: <<colour foreground>>\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: <<colour foreground>>\nsidebar-tab-background-selected: <<colour background>>\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: <<colour foreground>>\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: <<colour foreground>>\nsidebar-tiddler-link-foreground: <<colour primary>>\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: <<colour background>>\ntab-background: <<colour foreground>>\ntab-border-selected: <<colour foreground>>\ntab-border: <<colour foreground>>\ntab-divider: <<colour foreground>>\ntab-foreground-selected: <<colour foreground>>\ntab-foreground: <<colour background>>\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #fff\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: <<colour foreground>>\ntiddler-controls-foreground-hover: #ddd\ntiddler-controls-foreground-selected: #fdd\ntiddler-controls-foreground: <<colour foreground>>\ntiddler-editor-background: <<colour background>>\ntiddler-editor-border-image: <<colour foreground>>\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: <<colour background>>\ntiddler-editor-fields-odd: <<colour background>>\ntiddler-info-background: <<colour background>>\ntiddler-info-border: <<colour foreground>>\ntiddler-info-tab-background: <<colour background>>\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: <<colour foreground>>\ntiddler-title-foreground: <<colour foreground>>\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: <<colour foreground>>\nvery-muted-foreground: #888888\n" }, "$:/palettes/DarkPhotos": { "created": "20150402111612188", "description": "Good with dark photo backgrounds", "modified": "20150402112344080", "name": "DarkPhotos", "tags": "$:/tags/Palette", "title": "$:/palettes/DarkPhotos", "type": "application/x-tiddler-dictionary", "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background: \nbutton-foreground: \nbutton-border: \ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #ddd\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #336438\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #5778d8\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #ccf\nsidebar-controls-foreground: #fff\nsidebar-foreground-shadow: rgba(0,0,0, 0.5)\nsidebar-foreground: #fff\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #eee\nsidebar-tab-background-selected: rgba(255,255,255, 0.8)\nsidebar-tab-background: rgba(255,255,255, 0.4)\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: rgba(255,255,255, 0.2)\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #aaf\nsidebar-tiddler-link-foreground: #ddf\nsite-title-foreground: #fff\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ec6\ntag-foreground: #ffffff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #182955\ntoolbar-new-button: \ntoolbar-options-button: \ntoolbar-save-button: \ntoolbar-info-button: \ntoolbar-edit-button: \ntoolbar-close-button: \ntoolbar-delete-button: \ntoolbar-cancel-button: \ntoolbar-done-button: \nuntagged-background: #999999\nvery-muted-foreground: #888888\n" }, "$:/palettes/Rocker": { "title": "$:/palettes/Rocker", "name": "Rocker", "description": "A dark theme", "tags": "$:/tags/Palette", "type": "application/x-tiddler-dictionary", "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #999999\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #000\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #cc0000\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #ffffff\nsidebar-foreground-shadow: rgba(255,255,255, 0.0)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #000\nsidebar-tab-background: <<colour tab-background>>\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: <<colour tab-divider>>\nsidebar-tab-foreground-selected: \nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #ffbb99\nsidebar-tiddler-link-foreground: #cc0000\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ffbb99\ntag-foreground: #000\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #cc0000\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\n" }, "$:/palettes/SolarFlare": { "title": "$:/palettes/SolarFlare", "name": "Solar Flare", "description": "Warm, relaxing earth colours", "tags": "$:/tags/Palette", "type": "application/x-tiddler-dictionary", "text": ": Background Tones\n\nbase03: #002b36\nbase02: #073642\n\n: Content Tones\n\nbase01: #586e75\nbase00: #657b83\nbase0: #839496\nbase1: #93a1a1\n\n: Background Tones\n\nbase2: #eee8d5\nbase3: #fdf6e3\n\n: Accent Colors\n\nyellow: #b58900\norange: #cb4b16\nred: #dc322f\nmagenta: #d33682\nviolet: #6c71c4\nblue: #268bd2\ncyan: #2aa198\ngreen: #859900\n\n: Additional Tones (RA)\n\nbase10: #c0c4bb\nviolet-muted: #7c81b0\nblue-muted: #4e7baa\n\nyellow-hot: #ffcc44\norange-hot: #eb6d20\nred-hot: #ff2222\nblue-hot: #2298ee\ngreen-hot: #98ee22\n\n: Palette\n\n: Do not use colour macro for background and foreground\nbackground: #fdf6e3\n download-foreground: <<colour background>>\n dragger-foreground: <<colour background>>\n dropdown-background: <<colour background>>\n modal-background: <<colour background>>\n sidebar-foreground-shadow: <<colour background>>\n tiddler-background: <<colour background>>\n tiddler-border: <<colour background>>\n tiddler-link-background: <<colour background>>\n tab-background-selected: <<colour background>>\n dropdown-tab-background-selected: <<colour tab-background-selected>>\nforeground: #657b83\n dragger-background: <<colour foreground>>\n tab-foreground: <<colour foreground>>\n tab-foreground-selected: <<colour tab-foreground>>\n sidebar-tab-foreground-selected: <<colour tab-foreground-selected>>\n sidebar-tab-foreground: <<colour tab-foreground>>\n sidebar-button-foreground: <<colour foreground>>\n sidebar-controls-foreground: <<colour foreground>>\n sidebar-foreground: <<colour foreground>>\n: base03\n: base02\n: base01\n alert-muted-foreground: <<colour base01>>\n: base00\n code-foreground: <<colour base00>>\n message-foreground: <<colour base00>>\n tag-foreground: <<colour base00>>\n: base0\n sidebar-tiddler-link-foreground: <<colour base0>>\n: base1\n muted-foreground: <<colour base1>>\n blockquote-bar: <<colour muted-foreground>>\n dropdown-border: <<colour muted-foreground>>\n sidebar-muted-foreground: <<colour muted-foreground>>\n tiddler-title-foreground: <<colour muted-foreground>>\n site-title-foreground: <<colour tiddler-title-foreground>>\n: base2\n modal-footer-background: <<colour base2>>\n page-background: <<colour base2>>\n modal-backdrop: <<colour page-background>>\n notification-background: <<colour page-background>>\n code-background: <<colour page-background>>\n code-border: <<colour code-background>>\n pre-background: <<colour page-background>>\n pre-border: <<colour pre-background>>\n sidebar-tab-background-selected: <<colour page-background>>\n table-header-background: <<colour base2>>\n tag-background: <<colour base2>>\n tiddler-editor-background: <<colour base2>>\n tiddler-info-background: <<colour base2>>\n tiddler-info-tab-background: <<colour base2>>\n tab-background: <<colour base2>>\n dropdown-tab-background: <<colour tab-background>>\n: base3\n alert-background: <<colour base3>>\n message-background: <<colour base3>>\n: yellow\n: orange\n: red\n: magenta\n alert-highlight: <<colour magenta>>\n: violet\n external-link-foreground: <<colour violet>>\n: blue\n: cyan\n: green\n: base10\n tiddler-controls-foreground: <<colour base10>>\n: violet-muted\n external-link-foreground-visited: <<colour violet-muted>>\n: blue-muted\n primary: <<colour blue-muted>>\n download-background: <<colour primary>>\n tiddler-link-foreground: <<colour primary>>\n\nalert-border: #b99e2f\ndirty-indicator: #ff0000\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nmessage-border: #cfd6e6\nmodal-border: #999999\nsidebar-controls-foreground-hover:\nsidebar-muted-foreground-hover:\nsidebar-tab-background: #ded8c5\nsidebar-tiddler-link-foreground-hover:\nstatic-alert-foreground: #aaaaaa\ntab-border: #cccccc\n modal-footer-border: <<colour tab-border>>\n modal-header-border: <<colour tab-border>>\n notification-border: <<colour tab-border>>\n sidebar-tab-border: <<colour tab-border>>\n tab-border-selected: <<colour tab-border>>\n sidebar-tab-border-selected: <<colour tab-border-selected>>\ntab-divider: #d8d8d8\n sidebar-tab-divider: <<colour tab-divider>>\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-border: #dddddd\ntiddler-subtitle-foreground: #c0c0c0\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\n" }, "$:/palettes/Vanilla": { "title": "$:/palettes/Vanilla", "name": "Vanilla", "description": "Pale and unobtrusive", "tags": "$:/tags/Palette", "type": "application/x-tiddler-dictionary", "text": "alert-background: #ffe476\nalert-border: #b99e2f\nalert-highlight: #881122\nalert-muted-foreground: #b99e2f\nbackground: #ffffff\nblockquote-bar: <<colour muted-foreground>>\nbutton-background:\nbutton-foreground:\nbutton-border:\ncode-background: #f7f7f9\ncode-border: #e1e1e8\ncode-foreground: #dd1144\ndirty-indicator: #ff0000\ndownload-background: #34c734\ndownload-foreground: <<colour background>>\ndragger-background: <<colour foreground>>\ndragger-foreground: <<colour background>>\ndropdown-background: <<colour background>>\ndropdown-border: <<colour muted-foreground>>\ndropdown-tab-background-selected: #fff\ndropdown-tab-background: #ececec\ndropzone-background: rgba(0,200,0,0.7)\nexternal-link-background-hover: inherit\nexternal-link-background-visited: inherit\nexternal-link-background: inherit\nexternal-link-foreground-hover: inherit\nexternal-link-foreground-visited: #0000aa\nexternal-link-foreground: #0000ee\nforeground: #333333\nmessage-background: #ecf2ff\nmessage-border: #cfd6e6\nmessage-foreground: #547599\nmodal-backdrop: <<colour foreground>>\nmodal-background: <<colour background>>\nmodal-border: #999999\nmodal-footer-background: #f5f5f5\nmodal-footer-border: #dddddd\nmodal-header-border: #eeeeee\nmuted-foreground: #bbb\nnotification-background: #ffffdd\nnotification-border: #999999\npage-background: #f4f4f4\npre-background: #f5f5f5\npre-border: #cccccc\nprimary: #5778d8\nsidebar-button-foreground: <<colour foreground>>\nsidebar-controls-foreground-hover: #000000\nsidebar-controls-foreground: #aaaaaa\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\nsidebar-foreground: #acacac\nsidebar-muted-foreground-hover: #444444\nsidebar-muted-foreground: #c0c0c0\nsidebar-tab-background-selected: #f4f4f4\nsidebar-tab-background: #e0e0e0\nsidebar-tab-border-selected: <<colour tab-border-selected>>\nsidebar-tab-border: <<colour tab-border>>\nsidebar-tab-divider: #e4e4e4\nsidebar-tab-foreground-selected:\nsidebar-tab-foreground: <<colour tab-foreground>>\nsidebar-tiddler-link-foreground-hover: #444444\nsidebar-tiddler-link-foreground: #999999\nsite-title-foreground: <<colour tiddler-title-foreground>>\nstatic-alert-foreground: #aaaaaa\ntab-background-selected: #ffffff\ntab-background: #d8d8d8\ntab-border-selected: #d8d8d8\ntab-border: #cccccc\ntab-divider: #d8d8d8\ntab-foreground-selected: <<colour tab-foreground>>\ntab-foreground: #666666\ntable-border: #dddddd\ntable-footer-background: #a8a8a8\ntable-header-background: #f0f0f0\ntag-background: #ec6\ntag-foreground: #ffffff\ntiddler-background: <<colour background>>\ntiddler-border: <<colour background>>\ntiddler-controls-foreground-hover: #888888\ntiddler-controls-foreground-selected: #444444\ntiddler-controls-foreground: #cccccc\ntiddler-editor-background: #f8f8f8\ntiddler-editor-border-image: #ffffff\ntiddler-editor-border: #cccccc\ntiddler-editor-fields-even: #e0e8e0\ntiddler-editor-fields-odd: #f0f4f0\ntiddler-info-background: #f8f8f8\ntiddler-info-border: #dddddd\ntiddler-info-tab-background: #f8f8f8\ntiddler-link-background: <<colour background>>\ntiddler-link-foreground: <<colour primary>>\ntiddler-subtitle-foreground: #c0c0c0\ntiddler-title-foreground: #182955\ntoolbar-new-button:\ntoolbar-options-button:\ntoolbar-save-button:\ntoolbar-info-button:\ntoolbar-edit-button:\ntoolbar-close-button:\ntoolbar-delete-button:\ntoolbar-cancel-button:\ntoolbar-done-button:\nuntagged-background: #999999\nvery-muted-foreground: #888888\n" }, "$:/core/readme": { "title": "$:/core/readme", "text": "This plugin contains TiddlyWiki's core components, comprising:\n\n* JavaScript code modules\n* Icons\n* Templates needed to create TiddlyWiki's user interface\n* British English (''en-GB'') translations of the localisable strings used by the core\n" }, "$:/library/sjcl.js/license": { "title": "$:/library/sjcl.js/license", "type": "text/plain", "text": "SJCL is open. You can use, modify and redistribute it under a BSD\nlicense or under the GNU GPL, version 2.0.\n\n---------------------------------------------------------------------\n\nhttp://opensource.org/licenses/BSD-2-Clause\n\nCopyright (c) 2009-2015, Emily Stark, Mike Hamburg and Dan Boneh at\nStanford University. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n1. Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright\nnotice, this list of conditions and the following disclaimer in the\ndocumentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\nIS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\nTO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nHOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---------------------------------------------------------------------\n\nhttp://opensource.org/licenses/GPL-2.0\n\nThe Stanford Javascript Crypto Library (hosted here on GitHub) is a\nproject by the Stanford Computer Security Lab to build a secure,\npowerful, fast, small, easy-to-use, cross-browser library for\ncryptography in Javascript.\n\nCopyright (c) 2009-2015, Emily Stark, Mike Hamburg and Dan Boneh at\nStanford University.\n\nThis program is free software; you can redistribute it and/or modify it\nunder the terms of the GNU General Public License as published by the\nFree Software Foundation; either version 2 of the License, or (at your\noption) any later version.\n\nThis program is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\nPublic License for more details.\n\nYou should have received a copy of the GNU General Public License along\nwith this program; if not, write to the Free Software Foundation, Inc.,\n59 Temple Place, Suite 330, Boston, MA 02111-1307 USA" }, "$:/core/templates/MOTW.html": { "title": "$:/core/templates/MOTW.html", "text": "\\rules only filteredtranscludeinline transcludeinline entity\n<!-- The following comment is called a MOTW comment and is necessary for the TiddlyIE Internet Explorer extension -->\n<!-- saved from url=(0021)http://tiddlywiki.com --> " }, "$:/core/templates/alltiddlers.template.html": { "title": "$:/core/templates/alltiddlers.template.html", "type": "text/vnd.tiddlywiki-html", "text": "<!-- This template is provided for backwards compatibility with older versions of TiddlyWiki -->\n\n<$set name=\"exportFilter\" value=\"[!is[system]sort[title]]\">\n\n{{$:/core/templates/exporters/StaticRiver}}\n\n</$set>\n" }, "$:/core/templates/canonical-uri-external-image": { "title": "$:/core/templates/canonical-uri-external-image", "text": "<!--\n\nThis template is used to assign the ''_canonical_uri'' field to external images.\n\nChange the `./images/` part to a different base URI. The URI can be relative or absolute.\n\n-->\n./images/<$view field=\"title\" format=\"doubleurlencoded\"/>" }, "$:/core/templates/canonical-uri-external-text": { "title": "$:/core/templates/canonical-uri-external-text", "text": "<!--\n\nThis template is used to assign the ''_canonical_uri'' field to external text files.\n\nChange the `./text/` part to a different base URI. The URI can be relative or absolute.\n\n-->\n./text/<$view field=\"title\" format=\"doubleurlencoded\"/>.tid" }, "$:/core/templates/css-tiddler": { "title": "$:/core/templates/css-tiddler", "text": "<!--\n\nThis template is used for saving CSS tiddlers as a style tag with data attributes representing the tiddler fields.\n\n-->`<style`<$fields template=' data-tiddler-$name$=\"$encoded_value$\"'></$fields>` type=\"text/css\">`<$view field=\"text\" format=\"text\" />`</style>`" }, "$:/core/templates/exporters/CsvFile": { "title": "$:/core/templates/exporters/CsvFile", "tags": "$:/tags/Exporter", "description": "{{$:/language/Exporters/CsvFile}}", "extension": ".csv", "text": "\\define renderContent()\n<$text text=<<csvtiddlers filter:\"\"\"$(exportFilter)$\"\"\" format:\"quoted-comma-sep\">>/>\n\\end\n<<renderContent>>\n" }, "$:/core/templates/exporters/JsonFile": { "title": "$:/core/templates/exporters/JsonFile", "tags": "$:/tags/Exporter", "description": "{{$:/language/Exporters/JsonFile}}", "extension": ".json", "text": "\\define renderContent()\n<$text text=<<jsontiddlers filter:\"\"\"$(exportFilter)$\"\"\">>/>\n\\end\n<<renderContent>>\n" }, "$:/core/templates/exporters/StaticRiver": { "title": "$:/core/templates/exporters/StaticRiver", "tags": "$:/tags/Exporter", "description": "{{$:/language/Exporters/StaticRiver}}", "extension": ".html", "text": "\\define tv-wikilink-template() #$uri_encoded$\n\\define tv-config-toolbar-icons() no\n\\define tv-config-toolbar-text() no\n\\define tv-config-toolbar-class() tc-btn-invisible\n\\rules only filteredtranscludeinline transcludeinline\n<!doctype html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"{{$:/core/templates/version}}\" />\n<meta name=\"format-detection\" content=\"telephone=no\">\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<title>{{$:/core/wiki/title}}</title>\n<div id=\"styleArea\">\n{{$:/boot/boot.css||$:/core/templates/css-tiddler}}\n</div>\n<style type=\"text/css\">\n{{$:/core/ui/PageStylesheet||$:/core/templates/wikified-tiddler}}\n</style>\n</head>\n<body class=\"tc-body\">\n{{$:/StaticBanner||$:/core/templates/html-tiddler}}\n<section class=\"tc-story-river\">\n{{$:/core/templates/exporters/StaticRiver/Content||$:/core/templates/html-tiddler}}\n</section>\n</body>\n</html>\n" }, "$:/core/templates/exporters/StaticRiver/Content": { "title": "$:/core/templates/exporters/StaticRiver/Content", "text": "\\define renderContent()\n{{{ $(exportFilter)$ ||$:/core/templates/static-tiddler}}}\n\\end\n<$importvariables filter=\"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\">\n<<renderContent>>\n</$importvariables>\n" }, "$:/core/templates/exporters/TidFile": { "title": "$:/core/templates/exporters/TidFile", "tags": "$:/tags/Exporter", "description": "{{$:/language/Exporters/TidFile}}", "extension": ".tid", "text": "\\define renderContent()\n{{{ $(exportFilter)$ +[limit[1]] ||$:/core/templates/tid-tiddler}}}\n\\end\n<$importvariables filter=\"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\"><<renderContent>></$importvariables>" }, "$:/core/templates/html-div-tiddler": { "title": "$:/core/templates/html-div-tiddler", "text": "<!--\n\nThis template is used for saving tiddlers as an HTML DIV tag with attributes representing the tiddler fields.\n\n-->`<div`<$fields template=' $name$=\"$encoded_value$\"'></$fields>`>\n<pre>`<$view field=\"text\" format=\"htmlencoded\" />`</pre>\n</div>`\n" }, "$:/core/templates/html-tiddler": { "title": "$:/core/templates/html-tiddler", "text": "<!--\n\nThis template is used for saving tiddlers as raw HTML\n\n--><$view field=\"text\" format=\"htmlwikified\" />" }, "$:/core/templates/javascript-tiddler": { "title": "$:/core/templates/javascript-tiddler", "text": "<!--\n\nThis template is used for saving JavaScript tiddlers as a script tag with data attributes representing the tiddler fields.\n\n-->`<script`<$fields template=' data-tiddler-$name$=\"$encoded_value$\"'></$fields>` type=\"text/javascript\">`<$view field=\"text\" format=\"text\" />`</script>`" }, "$:/core/templates/json-tiddler": { "title": "$:/core/templates/json-tiddler", "text": "<!--\n\nThis template is used for saving tiddlers as raw JSON\n\n--><$text text=<<jsontiddler>>/>" }, "$:/core/templates/module-tiddler": { "title": "$:/core/templates/module-tiddler", "text": "<!--\n\nThis template is used for saving JavaScript tiddlers as a script tag with data attributes representing the tiddler fields. The body of the tiddler is wrapped in a call to the `$tw.modules.define` function in order to define the body of the tiddler as a module\n\n-->`<script`<$fields template=' data-tiddler-$name$=\"$encoded_value$\"'></$fields>` type=\"text/javascript\" data-module=\"yes\">$tw.modules.define(\"`<$view field=\"title\" format=\"jsencoded\" />`\",\"`<$view field=\"module-type\" format=\"jsencoded\" />`\",function(module,exports,require) {`<$view field=\"text\" format=\"text\" />`});\n</script>`" }, "$:/core/templates/plain-text-tiddler": { "title": "$:/core/templates/plain-text-tiddler", "text": "<$view field=\"text\" format=\"text\" />" }, "$:/core/templates/raw-static-tiddler": { "title": "$:/core/templates/raw-static-tiddler", "text": "<!--\n\nThis template is used for saving tiddlers as static HTML\n\n--><$view field=\"text\" format=\"plainwikified\" />" }, "$:/core/save/all": { "title": "$:/core/save/all", "text": "\\define saveTiddlerFilter()\n[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$\n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n" }, "$:/core/save/empty": { "title": "$:/core/save/empty", "text": "\\define saveTiddlerFilter()\n[is[system]] -[prefix[$:/state/popup/]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]\n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n" }, "$:/core/save/lazy-all": { "title": "$:/core/save/lazy-all", "text": "\\define saveTiddlerFilter()\n[is[system]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] \n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n" }, "$:/core/save/lazy-images": { "title": "$:/core/save/lazy-images", "text": "\\define saveTiddlerFilter()\n[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[!is[system]is[image]] +[sort[title]] \n\\end\n{{$:/core/templates/tiddlywiki5.html}}\n" }, "$:/core/templates/single.tiddler.window": { "title": "$:/core/templates/single.tiddler.window", "text": "<$set name=\"themeTitle\" value={{$:/view}}>\n\n<$set name=\"tempCurrentTiddler\" value=<<currentTiddler>>>\n\n<$set name=\"currentTiddler\" value={{$:/language}}>\n\n<$set name=\"languageTitle\" value={{!!name}}>\n\n<$set name=\"currentTiddler\" value=<<tempCurrentTiddler>>>\n\n<$importvariables filter=\"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\">\n\n<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\">\n\n<$transclude mode=\"block\"/>\n\n</$navigator>\n\n</$importvariables>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n\n" }, "$:/core/templates/split-recipe": { "title": "$:/core/templates/split-recipe", "text": "<$list filter=\"[!is[system]]\">\ntiddler: <$view field=\"title\" format=\"urlencoded\"/>.tid\n</$list>\n" }, "$:/core/templates/static-tiddler": { "title": "$:/core/templates/static-tiddler", "text": "<a name=<<currentTiddler>>>\n<$transclude tiddler=\"$:/core/ui/ViewTemplate\"/>\n</a>" }, "$:/core/templates/static.area": { "title": "$:/core/templates/static.area", "text": "<$reveal type=\"nomatch\" state=\"$:/isEncrypted\" text=\"yes\">\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawStaticContent]!has[draft.of]] ||$:/core/templates/raw-static-tiddler}}}\n{{$:/core/templates/static.content||$:/core/templates/html-tiddler}}\n</$reveal>\n<$reveal type=\"match\" state=\"$:/isEncrypted\" text=\"yes\">\nThis file contains an encrypted ~TiddlyWiki. Enable ~JavaScript and enter the decryption password when prompted.\n</$reveal>\n" }, "$:/core/templates/static.content": { "title": "$:/core/templates/static.content", "type": "text/vnd.tiddlywiki", "text": "<!-- For Google, and people without JavaScript-->\nThis [[TiddlyWiki|http://tiddlywiki.com]] contains the following tiddlers:\n\n<ul>\n<$list filter=<<saveTiddlerFilter>>>\n<li><$view field=\"title\" format=\"text\"></$view></li>\n</$list>\n</ul>\n" }, "$:/core/templates/static.template.css": { "title": "$:/core/templates/static.template.css", "text": "{{$:/boot/boot.css||$:/core/templates/plain-text-tiddler}}\n\n{{$:/core/ui/PageStylesheet||$:/core/templates/wikified-tiddler}}\n" }, "$:/core/templates/static.template.html": { "title": "$:/core/templates/static.template.html", "type": "text/vnd.tiddlywiki-html", "text": "\\define tv-wikilink-template() static/$uri_doubleencoded$.html\n\\define tv-config-toolbar-icons() no\n\\define tv-config-toolbar-text() no\n\\define tv-config-toolbar-class() tc-btn-invisible\n\\rules only filteredtranscludeinline transcludeinline\n<!doctype html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"{{$:/core/templates/version}}\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\">\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<title>{{$:/core/wiki/title}}</title>\n<div id=\"styleArea\">\n{{$:/boot/boot.css||$:/core/templates/css-tiddler}}\n</div>\n<style type=\"text/css\">\n{{$:/core/ui/PageStylesheet||$:/core/templates/wikified-tiddler}}\n</style>\n</head>\n<body class=\"tc-body\">\n{{$:/StaticBanner||$:/core/templates/html-tiddler}}\n{{$:/core/ui/PageTemplate||$:/core/templates/html-tiddler}}\n</body>\n</html>\n" }, "$:/core/templates/static.tiddler.html": { "title": "$:/core/templates/static.tiddler.html", "text": "\\define tv-wikilink-template() $uri_doubleencoded$.html\n\\define tv-config-toolbar-icons() no\n\\define tv-config-toolbar-text() no\n\\define tv-config-toolbar-class() tc-btn-invisible\n`<!doctype html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"`{{$:/core/templates/version}}`\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\">\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<link rel=\"stylesheet\" href=\"static.css\">\n<title>`<$view field=\"caption\"><$view field=\"title\"/></$view>: {{$:/core/wiki/title}}`</title>\n</head>\n<body class=\"tc-body\">\n`{{$:/StaticBanner||$:/core/templates/html-tiddler}}`\n<section class=\"tc-story-river\">\n`<$importvariables filter=\"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\">\n<$view tiddler=\"$:/core/ui/ViewTemplate\" format=\"htmlwikified\"/>\n</$importvariables>`\n</section>\n</body>\n</html>\n`" }, "$:/core/templates/store.area.template.html": { "title": "$:/core/templates/store.area.template.html", "text": "<$reveal type=\"nomatch\" state=\"$:/isEncrypted\" text=\"yes\">\n`<div id=\"storeArea\" style=\"display:none;\">`\n<$list filter=<<saveTiddlerFilter>> template=\"$:/core/templates/html-div-tiddler\"/>\n`</div>`\n</$reveal>\n<$reveal type=\"match\" state=\"$:/isEncrypted\" text=\"yes\">\n`<!--~~ Encrypted tiddlers ~~-->`\n`<pre id=\"encryptedStoreArea\" type=\"text/plain\" style=\"display:none;\">`\n<$encrypt filter=<<saveTiddlerFilter>>/>\n`</pre>`\n</$reveal>" }, "$:/core/templates/tid-tiddler": { "title": "$:/core/templates/tid-tiddler", "text": "<!--\n\nThis template is used for saving tiddlers in TiddlyWeb *.tid format\n\n--><$fields exclude='text bag' template='$name$: $value$\n'></$fields>`\n`<$view field=\"text\" format=\"text\" />" }, "$:/core/templates/tiddler-metadata": { "title": "$:/core/templates/tiddler-metadata", "text": "<!--\n\nThis template is used for saving tiddler metadata *.meta files\n\n--><$fields exclude='text bag' template='$name$: $value$\n'></$fields>" }, "$:/core/templates/tiddlywiki5.html": { "title": "$:/core/templates/tiddlywiki5.html", "text": "\\rules only filteredtranscludeinline transcludeinline\n<!doctype html>\n{{$:/core/templates/MOTW.html}}<html>\n<head>\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge\">\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n<meta name=\"application-name\" content=\"TiddlyWiki\" />\n<meta name=\"generator\" content=\"TiddlyWiki\" />\n<meta name=\"tiddlywiki-version\" content=\"{{$:/core/templates/version}}\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n<meta name=\"mobile-web-app-capable\" content=\"yes\"/>\n<meta name=\"format-detection\" content=\"telephone=no\" />\n<meta name=\"copyright\" content=\"{{$:/core/copyright.txt}}\" />\n<link id=\"faviconLink\" rel=\"shortcut icon\" href=\"favicon.ico\">\n<title>{{$:/core/wiki/title}}</title>\n<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->\n\n<!--~~ Raw markup ~~-->\n{{{ [all[shadows+tiddlers]tag[$:/core/wiki/rawmarkup]] [all[shadows+tiddlers]tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}\n{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}\n</head>\n<body class=\"tc-body\">\n<!--~~ Static styles ~~-->\n<div id=\"styleArea\">\n{{$:/boot/boot.css||$:/core/templates/css-tiddler}}\n</div>\n<!--~~ Static content for Google and browsers without JavaScript ~~-->\n<noscript>\n<div id=\"splashArea\">\n{{$:/core/templates/static.area}}\n</div>\n</noscript>\n<!--~~ Ordinary tiddlers ~~-->\n{{$:/core/templates/store.area.template.html}}\n<!--~~ Library modules ~~-->\n<div id=\"libraryModules\" style=\"display:none;\">\n{{{ [is[system]type[application/javascript]library[yes]] ||$:/core/templates/javascript-tiddler}}}\n</div>\n<!--~~ Boot kernel prologue ~~-->\n<div id=\"bootKernelPrefix\" style=\"display:none;\">\n{{ $:/boot/bootprefix.js ||$:/core/templates/javascript-tiddler}}\n</div>\n<!--~~ Boot kernel ~~-->\n<div id=\"bootKernel\" style=\"display:none;\">\n{{ $:/boot/boot.js ||$:/core/templates/javascript-tiddler}}\n</div>\n</body>\n</html>\n" }, "$:/core/templates/version": { "title": "$:/core/templates/version", "text": "<<version>>" }, "$:/core/templates/wikified-tiddler": { "title": "$:/core/templates/wikified-tiddler", "text": "<$transclude />" }, "$:/core/ui/AboveStory/tw2-plugin-check": { "title": "$:/core/ui/AboveStory/tw2-plugin-check", "tags": "$:/tags/AboveStory", "text": "\\define lingo-base() $:/language/AboveStory/ClassicPlugin/\n<$list filter=\"[all[system+tiddlers]tag[systemConfig]limit[1]]\">\n\n<div class=\"tc-message-box\">\n\n<<lingo Warning>>\n\n<ul>\n\n<$list filter=\"[all[system+tiddlers]tag[systemConfig]]\">\n\n<li>\n\n<$link><$view field=\"title\"/></$link>\n\n</li>\n\n</$list>\n\n</ul>\n\n</div>\n\n</$list>\n" }, "$:/core/ui/AdvancedSearch/Filter": { "title": "$:/core/ui/AdvancedSearch/Filter", "tags": "$:/tags/AdvancedSearch", "caption": "{{$:/language/Search/Filter/Caption}}", "text": "\\define lingo-base() $:/language/Search/\n<<lingo Filter/Hint>>\n\n<div class=\"tc-search tc-advanced-search\">\n<$edit-text tiddler=\"$:/temp/advancedsearch\" type=\"search\" tag=\"input\"/>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/AdvancedSearch/FilterButton]!has[draft.of]]\"><$transclude/></$list>\n</div>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$set name=\"resultCount\" value=\"\"\"<$count filter={{$:/temp/advancedsearch}}/>\"\"\">\n<div class=\"tc-search-results\">\n<<lingo Filter/Matches>>\n<$list filter={{$:/temp/advancedsearch}} template=\"$:/core/ui/ListItemTemplate\"/>\n</div>\n</$set>\n</$reveal>\n" }, "$:/core/ui/AdvancedSearch/Filter/FilterButtons/clear": { "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/clear", "tags": "$:/tags/AdvancedSearch/FilterButton", "text": "<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" $field=\"text\" $value=\"\"/>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n" }, "$:/core/ui/AdvancedSearch/Filter/FilterButtons/delete": { "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/delete", "tags": "$:/tags/AdvancedSearch/FilterButton", "text": "<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button popup=<<qualify \"$:/state/filterDeleteDropdown\">> class=\"tc-btn-invisible\">\n{{$:/core/images/delete-button}}\n</$button>\n</$reveal>\n\n<$reveal state=<<qualify \"$:/state/filterDeleteDropdown\">> type=\"popup\" position=\"belowleft\" animate=\"yes\">\n<div class=\"tc-block-dropdown-wrapper\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<div class=\"tc-dropdown-item-plain\">\n<$set name=\"resultCount\" value=\"\"\"<$count filter={{$:/temp/advancedsearch}}/>\"\"\">\nAre you sure you wish to delete <<resultCount>> tiddler(s)?\n</$set>\n</div>\n<div class=\"tc-dropdown-item-plain\">\n<$button class=\"tc-btn\">\n<$action-deletetiddler $filter={{$:/temp/advancedsearch}}/>\nDelete these tiddlers\n</$button>\n</div>\n</div>\n</div>\n</$reveal>\n" }, "$:/core/ui/AdvancedSearch/Filter/FilterButtons/dropdown": { "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/dropdown", "tags": "$:/tags/AdvancedSearch/FilterButton", "text": "<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/filterDropdown\">> class=\"tc-btn-invisible\">\n{{$:/core/images/down-arrow}}\n</$button>\n</span>\n\n<$reveal state=<<qualify \"$:/state/filterDropdown\">> type=\"popup\" position=\"belowleft\" animate=\"yes\">\n<$linkcatcher to=\"$:/temp/advancedsearch\">\n<div class=\"tc-block-dropdown-wrapper\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Filter]]\"><$link to={{!!filter}}><$transclude field=\"description\"/></$link>\n</$list>\n</div>\n</div>\n</$linkcatcher>\n</$reveal>\n" }, "$:/core/ui/AdvancedSearch/Filter/FilterButtons/export": { "title": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/export", "tags": "$:/tags/AdvancedSearch/FilterButton", "text": "<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$macrocall $name=\"exportButton\" exportFilter={{$:/temp/advancedsearch}} lingoBase=\"$:/language/Buttons/ExportTiddlers/\"/>\n</$reveal>\n" }, "$:/core/ui/AdvancedSearch/Shadows": { "title": "$:/core/ui/AdvancedSearch/Shadows", "tags": "$:/tags/AdvancedSearch", "caption": "{{$:/language/Search/Shadows/Caption}}", "text": "\\define lingo-base() $:/language/Search/\n<$linkcatcher to=\"$:/temp/advancedsearch\">\n\n<<lingo Shadows/Hint>>\n\n<div class=\"tc-search\">\n<$edit-text tiddler=\"$:/temp/advancedsearch\" type=\"search\" tag=\"input\"/>\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" $field=\"text\" $value=\"\"/>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n\n</$linkcatcher>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n\n<$list filter=\"[{$:/temp/advancedsearch}minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n\n<$set name=\"resultCount\" value=\"\"\"<$count filter=\"[all[shadows]search{$:/temp/advancedsearch}] -[[$:/temp/advancedsearch]]\"/>\"\"\">\n\n<div class=\"tc-search-results\">\n\n<<lingo Shadows/Matches>>\n\n<$list filter=\"[all[shadows]search{$:/temp/advancedsearch}sort[title]limit[250]] -[[$:/temp/advancedsearch]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n\n</div>\n\n</$set>\n\n</$list>\n\n</$reveal>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"match\" text=\"\">\n\n</$reveal>\n" }, "$:/core/ui/AdvancedSearch/Standard": { "title": "$:/core/ui/AdvancedSearch/Standard", "tags": "$:/tags/AdvancedSearch", "caption": "{{$:/language/Search/Standard/Caption}}", "text": "\\define lingo-base() $:/language/Search/\n<$linkcatcher to=\"$:/temp/advancedsearch\">\n\n<<lingo Standard/Hint>>\n\n<div class=\"tc-search\">\n<$edit-text tiddler=\"$:/temp/advancedsearch\" type=\"search\" tag=\"input\"/>\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" $field=\"text\" $value=\"\"/>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n\n</$linkcatcher>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$list filter=\"[{$:/temp/advancedsearch}minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n<$set name=\"searchTiddler\" value=\"$:/temp/advancedsearch\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]butfirst[]limit[1]]\" emptyMessage=\"\"\"\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\">\n<$transclude/>\n</$list>\n\"\"\">\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\" default={{$:/config/SearchResults/Default}}/>\n</$list>\n</$set>\n</$list>\n</$reveal>\n" }, "$:/core/ui/AdvancedSearch/System": { "title": "$:/core/ui/AdvancedSearch/System", "tags": "$:/tags/AdvancedSearch", "caption": "{{$:/language/Search/System/Caption}}", "text": "\\define lingo-base() $:/language/Search/\n<$linkcatcher to=\"$:/temp/advancedsearch\">\n\n<<lingo System/Hint>>\n\n<div class=\"tc-search\">\n<$edit-text tiddler=\"$:/temp/advancedsearch\" type=\"search\" tag=\"input\"/>\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" $field=\"text\" $value=\"\"/>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n\n</$linkcatcher>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"nomatch\" text=\"\">\n\n<$list filter=\"[{$:/temp/advancedsearch}minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n\n<$set name=\"resultCount\" value=\"\"\"<$count filter=\"[is[system]search{$:/temp/advancedsearch}] -[[$:/temp/advancedsearch]]\"/>\"\"\">\n\n<div class=\"tc-search-results\">\n\n<<lingo System/Matches>>\n\n<$list filter=\"[is[system]search{$:/temp/advancedsearch}sort[title]limit[250]] -[[$:/temp/advancedsearch]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n\n</div>\n\n</$set>\n\n</$list>\n\n</$reveal>\n\n<$reveal state=\"$:/temp/advancedsearch\" type=\"match\" text=\"\">\n\n</$reveal>\n" }, "$:/AdvancedSearch": { "title": "$:/AdvancedSearch", "icon": "$:/core/images/advanced-search-button", "color": "#bbb", "text": "<div class=\"tc-advanced-search\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/AdvancedSearch]!has[draft.of]]\" \"$:/core/ui/AdvancedSearch/System\">>\n</div>\n" }, "$:/core/ui/AlertTemplate": { "title": "$:/core/ui/AlertTemplate", "text": "<div class=\"tc-alert\">\n<div class=\"tc-alert-toolbar\">\n<$button class=\"tc-btn-invisible\"><$action-deletetiddler $tiddler=<<currentTiddler>>/>{{$:/core/images/delete-button}}</$button>\n</div>\n<div class=\"tc-alert-subtitle\">\n<$view field=\"component\"/> - <$view field=\"modified\" format=\"date\" template=\"0hh:0mm:0ss DD MM YYYY\"/> <$reveal type=\"nomatch\" state=\"!!count\" text=\"\"><span class=\"tc-alert-highlight\">({{$:/language/Count}}: <$view field=\"count\"/>)</span></$reveal>\n</div>\n<div class=\"tc-alert-body\">\n\n<$transclude/>\n\n</div>\n</div>\n" }, "$:/core/ui/BinaryWarning": { "title": "$:/core/ui/BinaryWarning", "text": "\\define lingo-base() $:/language/BinaryWarning/\n<div class=\"tc-binary-warning\">\n\n<<lingo Prompt>>\n\n</div>\n" }, "$:/core/ui/Components/plugin-info": { "title": "$:/core/ui/Components/plugin-info", "text": "\\define lingo-base() $:/language/ControlPanel/Plugins/\n\n\\define popup-state-macro()\n$(qualified-state)$-$(currentTiddler)$\n\\end\n\n\\define tabs-state-macro()\n$(popup-state)$-$(pluginInfoType)$\n\\end\n\n\\define plugin-icon-title()\n$(currentTiddler)$/icon\n\\end\n\n\\define plugin-disable-title()\n$:/config/Plugins/Disabled/$(currentTiddler)$\n\\end\n\n\\define plugin-table-body(type,disabledMessage,default-popup-state)\n<div class=\"tc-plugin-info-chunk tc-small-icon\">\n<$reveal type=\"nomatch\" state=<<popup-state>> text=\"yes\" default=\"\"\"$default-popup-state$\"\"\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"yes\">\n{{$:/core/images/right-arrow}}\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<popup-state>> text=\"yes\" default=\"\"\"$default-popup-state$\"\"\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"no\">\n{{$:/core/images/down-arrow}}\n</$button>\n</$reveal>\n</div>\n<div class=\"tc-plugin-info-chunk\">\n<$transclude tiddler=<<currentTiddler>> subtiddler=<<plugin-icon-title>>>\n<$transclude tiddler=\"$:/core/images/plugin-generic-$type$\"/>\n</$transclude>\n</div>\n<div class=\"tc-plugin-info-chunk\">\n<h1>\n''<$view field=\"description\"><$view field=\"title\"/></$view>'' $disabledMessage$\n</h1>\n<h2>\n<$view field=\"title\"/>\n</h2>\n<h2>\n<div><em><$view field=\"version\"/></em></div>\n</h2>\n</div>\n\\end\n\n\\define plugin-info(type,default-popup-state)\n<$set name=\"popup-state\" value=<<popup-state-macro>>>\n<$reveal type=\"nomatch\" state=<<plugin-disable-title>> text=\"yes\">\n<$link to={{!!title}} class=\"tc-plugin-info\">\n<<plugin-table-body type:\"$type$\" default-popup-state:\"\"\"$default-popup-state$\"\"\">>\n</$link>\n</$reveal>\n<$reveal type=\"match\" state=<<plugin-disable-title>> text=\"yes\">\n<$link to={{!!title}} class=\"tc-plugin-info tc-plugin-info-disabled\">\n<<plugin-table-body type:\"$type$\" default-popup-state:\"\"\"$default-popup-state$\"\"\" disabledMessage:\"<$macrocall $name='lingo' title='Disabled/Status'/>\">>\n</$link>\n</$reveal>\n<$reveal type=\"match\" text=\"yes\" state=<<popup-state>> default=\"\"\"$default-popup-state$\"\"\">\n<div class=\"tc-plugin-info-dropdown\">\n<div class=\"tc-plugin-info-dropdown-body\">\n<$list filter=\"[all[current]] -[[$:/core]]\">\n<div style=\"float:right;\">\n<$reveal type=\"nomatch\" state=<<plugin-disable-title>> text=\"yes\">\n<$button set=<<plugin-disable-title>> setTo=\"yes\" tooltip={{$:/language/ControlPanel/Plugins/Disable/Hint}} aria-label={{$:/language/ControlPanel/Plugins/Disable/Caption}}>\n<<lingo Disable/Caption>>\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<plugin-disable-title>> text=\"yes\">\n<$button set=<<plugin-disable-title>> setTo=\"no\" tooltip={{$:/language/ControlPanel/Plugins/Enable/Hint}} aria-label={{$:/language/ControlPanel/Plugins/Enable/Caption}}>\n<<lingo Enable/Caption>>\n</$button>\n</$reveal>\n</div>\n</$list>\n<$reveal type=\"nomatch\" text=\"\" state=\"!!list\">\n<$set name=\"tabsList\" filter=\"[<currentTiddler>list[]] contents\">\n<$macrocall $name=\"tabs\" state=<<tabs-state-macro>> tabsList=<<tabsList>> default=\"readme\" template=\"$:/core/ui/PluginInfo\"/>\n</$set>\n</$reveal>\n<$reveal type=\"match\" text=\"\" state=\"!!list\">\n<<lingo NoInformation/Hint>>\n</$reveal>\n</div>\n</div>\n</$reveal>\n</$set>\n\\end\n\n<$macrocall $name=\"plugin-info\" type=<<plugin-type>> default-popup-state=<<default-popup-state>>/>\n" }, "$:/core/ui/Components/tag-link": { "title": "$:/core/ui/Components/tag-link", "text": "<$link>\n<$set name=\"backgroundColor\" value={{!!color}}>\n<span style=<<tag-styles>> class=\"tc-tag-label\">\n<$view field=\"title\" format=\"text\"/>\n</span>\n</$set>\n</$link>" }, "$:/core/ui/ControlPanel/Advanced": { "title": "$:/core/ui/ControlPanel/Advanced", "tags": "$:/tags/ControlPanel/Info", "caption": "{{$:/language/ControlPanel/Advanced/Caption}}", "text": "{{$:/language/ControlPanel/Advanced/Hint}}\n\n<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Advanced]!has[draft.of]]\" \"$:/core/ui/ControlPanel/TiddlerFields\">>\n</div>\n" }, "$:/core/ui/ControlPanel/Appearance": { "title": "$:/core/ui/ControlPanel/Appearance", "tags": "$:/tags/ControlPanel", "caption": "{{$:/language/ControlPanel/Appearance/Caption}}", "text": "{{$:/language/ControlPanel/Appearance/Hint}}\n\n<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Appearance]!has[draft.of]]\" \"$:/core/ui/ControlPanel/Theme\">>\n</div>\n" }, "$:/core/ui/ControlPanel/Basics": { "title": "$:/core/ui/ControlPanel/Basics", "tags": "$:/tags/ControlPanel/Info", "caption": "{{$:/language/ControlPanel/Basics/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Basics/\n\n\\define show-filter-count(filter)\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" $value=\"\"\"$filter$\"\"\"/>\n<$action-setfield $tiddler=\"$:/state/tab--1498284803\" $value=\"$:/core/ui/AdvancedSearch/Filter\"/>\n<$action-navigate $to=\"$:/AdvancedSearch\"/>\n''<$count filter=\"\"\"$filter$\"\"\"/>''\n{{$:/core/images/advanced-search-button}}\n</$button>\n\\end\n\n|<<lingo Version/Prompt>> |''<<version>>'' |\n|<$link to=\"$:/SiteTitle\"><<lingo Title/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteTitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/SiteSubtitle\"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteSubtitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/status/UserName\"><<lingo Username/Prompt>></$link> |<$edit-text tiddler=\"$:/status/UserName\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/config/AnimationDuration\"><<lingo AnimDuration/Prompt>></$link> |<$edit-text tiddler=\"$:/config/AnimationDuration\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/DefaultTiddlers\"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit tag=\"textarea\" tiddler=\"$:/DefaultTiddlers\" class=\"tc-edit-texteditor\"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |\n|<$link to=\"$:/config/NewJournal/Title\"><<lingo NewJournal/Title/Prompt>></$link> |<$edit-text tiddler=\"$:/config/NewJournal/Title\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/config/NewJournal/Text\"><<lingo NewJournal/Text/Prompt>></$link> |<$edit tiddler=\"$:/config/NewJournal/Text\" tag=\"textarea\" class=\"tc-edit-texteditor\" default=\"\"/> |\n|<$link to=\"$:/config/NewJournal/Tags\"><<lingo NewJournal/Tags/Prompt>></$link> |<$edit-text tiddler=\"$:/config/NewJournal/Tags\" default=\"\" tag=\"input\"/> |\n|<<lingo Language/Prompt>> |{{$:/snippets/minilanguageswitcher}} |\n|<<lingo Tiddlers/Prompt>> |<<show-filter-count \"[!is[system]sort[title]]\">> |\n|<<lingo Tags/Prompt>> |<<show-filter-count \"[tags[]sort[title]]\">> |\n|<<lingo SystemTiddlers/Prompt>> |<<show-filter-count \"[is[system]sort[title]]\">> |\n|<<lingo ShadowTiddlers/Prompt>> |<<show-filter-count \"[all[shadows]sort[title]]\">> |\n|<<lingo OverriddenShadowTiddlers/Prompt>> |<<show-filter-count \"[is[tiddler]is[shadow]sort[title]]\">> |\n" }, "$:/core/ui/ControlPanel/EditorTypes": { "title": "$:/core/ui/ControlPanel/EditorTypes", "tags": "$:/tags/ControlPanel/Advanced", "caption": "{{$:/language/ControlPanel/EditorTypes/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/EditorTypes/\n\n<<lingo Hint>>\n\n<table>\n<tbody>\n<tr>\n<th><<lingo Type/Caption>></th>\n<th><<lingo Editor/Caption>></th>\n</tr>\n<$list filter=\"[all[shadows+tiddlers]prefix[$:/config/EditorTypeMappings/]sort[title]]\">\n<tr>\n<td>\n<$link>\n<$list filter=\"[all[current]removeprefix[$:/config/EditorTypeMappings/]]\">\n<$text text={{!!title}}/>\n</$list>\n</$link>\n</td>\n<td>\n<$view field=\"text\"/>\n</td>\n</tr>\n</$list>\n</tbody>\n</table>\n" }, "$:/core/ui/ControlPanel/Info": { "title": "$:/core/ui/ControlPanel/Info", "tags": "$:/tags/ControlPanel", "caption": "{{$:/language/ControlPanel/Info/Caption}}", "text": "{{$:/language/ControlPanel/Info/Hint}}\n\n<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Info]!has[draft.of]]\" \"$:/core/ui/ControlPanel/Basics\">>\n</div>\n" }, "$:/core/ui/ControlPanel/KeyboardShortcuts": { "title": "$:/core/ui/ControlPanel/KeyboardShortcuts", "tags": "$:/tags/ControlPanel", "caption": "{{$:/language/ControlPanel/KeyboardShortcuts/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/KeyboardShortcuts/\n\n\\define new-shortcut(title)\n<div class=\"tc-dropdown-item-plain\">\n<$edit-shortcut tiddler=\"$title$\" placeholder={{$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt}} style=\"width:auto;\"/> <$button>\n<<lingo Add/Caption>>\n<$action-listops\n\t$tiddler=\"$(shortcutTitle)$\"\n\t$field=\"text\"\n\t$subfilter=\"[{$title$}]\"\n/>\n<$action-deletetiddler\n\t$tiddler=\"$title$\"\n/>\n</$button>\n</div>\n\\end\n\n\\define shortcut-list-item(caption)\n<td>\n</td>\n<td style=\"text-align:right;font-size:0.7em;\">\n<<lingo Platform/$caption$>>\n</td>\n<td>\n<div style=\"position:relative;\">\n<$button popup=<<qualify \"$:/state/dropdown/$(shortcutTitle)$\">> class=\"tc-btn-invisible\">\n{{$:/core/images/edit-button}}\n</$button>\n<$macrocall $name=\"displayshortcuts\" $output=\"text/html\" shortcuts={{$(shortcutTitle)$}} prefix=\"<kbd>\" separator=\"</kbd> <kbd>\" suffix=\"</kbd>\"/>\n\n<$reveal state=<<qualify \"$:/state/dropdown/$(shortcutTitle)$\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-block-dropdown-wrapper\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown tc-popup-keep\">\n<$list filter=\"[list[$(shortcutTitle)$!!text]sort[title]]\" variable=\"shortcut\" emptyMessage=\"\"\"\n<div class=\"tc-dropdown-item-plain\">\n//<<lingo NoShortcuts/Caption>>//\n</div>\n\"\"\">\n<div class=\"tc-dropdown-item-plain\">\n<$button class=\"tc-btn-invisible\" tooltip=<<lingo Remove/Hint>>>\n<$action-listops\n\t$tiddler=\"$(shortcutTitle)$\"\n\t$field=\"text\"\n\t$subfilter=\"+[remove<shortcut>]\"\n/>\n×\n</$button>\n<kbd>\n<$macrocall $name=\"displayshortcuts\" $output=\"text/html\" shortcuts=<<shortcut>>/>\n</kbd>\n</div>\n</$list>\n<hr/>\n<$macrocall $name=\"new-shortcut\" title=<<qualify \"$:/state/new-shortcut/$(shortcutTitle)$\">>/>\n</div>\n</div>\n</$reveal>\n</div>\n</td>\n\\end\n\n\\define shortcut-list(caption,prefix)\n<tr>\n<$list filter=\"[all[tiddlers+shadows][$prefix$$(shortcutName)$]]\" variable=\"shortcutTitle\">\n<<shortcut-list-item \"$caption$\">>\n</$list>\n</tr>\n\\end\n\n\\define shortcut-editor()\n<<shortcut-list \"All\" \"$:/config/shortcuts/\">>\n<<shortcut-list \"Mac\" \"$:/config/shortcuts-mac/\">>\n<<shortcut-list \"NonMac\" \"$:/config/shortcuts-not-mac/\">>\n<<shortcut-list \"Linux\" \"$:/config/shortcuts-linux/\">>\n<<shortcut-list \"NonLinux\" \"$:/config/shortcuts-not-linux/\">>\n<<shortcut-list \"Windows\" \"$:/config/shortcuts-windows/\">>\n<<shortcut-list \"NonWindows\" \"$:/config/shortcuts-not-windows/\">>\n\\end\n\n\\define shortcut-preview()\n<$macrocall $name=\"displayshortcuts\" $output=\"text/html\" shortcuts={{$(shortcutPrefix)$$(shortcutName)$}} prefix=\"<kbd>\" separator=\"</kbd> <kbd>\" suffix=\"</kbd>\"/>\n\\end\n\n\\define shortcut-item-inner()\n<tr>\n<td>\n<$reveal type=\"nomatch\" state=<<dropdownStateTitle>> text=\"open\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield\n\t$tiddler=<<dropdownStateTitle>>\n\t$value=\"open\"\n/>\n{{$:/core/images/right-arrow}}\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<dropdownStateTitle>> text=\"open\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield\n\t$tiddler=<<dropdownStateTitle>>\n\t$value=\"close\"\n/>\n{{$:/core/images/down-arrow}}\n</$button>\n</$reveal>\n''<$text text=<<shortcutName>>/>''\n</td>\n<td>\n<$transclude tiddler=\"$:/config/ShortcutInfo/$(shortcutName)$\"/>\n</td>\n<td>\n<$list filter=\"$:/config/shortcuts/ $:/config/shortcuts-mac/ $:/config/shortcuts-not-mac/ $:/config/shortcuts-linux/ $:/config/shortcuts-not-linux/ $:/config/shortcuts-windows/ $:/config/shortcuts-not-windows/\" variable=\"shortcutPrefix\">\n<<shortcut-preview>>\n</$list>\n</td>\n</tr>\n<$set name=\"dropdownState\" value={{$(dropdownStateTitle)$}}>\n<$list filter=\"[<dropdownState>prefix[open]]\" variable=\"listItem\">\n<<shortcut-editor>>\n</$list>\n</$set>\n\\end\n\n\\define shortcut-item()\n<$set name=\"dropdownStateTitle\" value=<<qualify \"$:/state/dropdown/keyboardshortcut/$(shortcutName)$\">>>\n<<shortcut-item-inner>>\n</$set>\n\\end\n\n<table>\n<tbody>\n<$list filter=\"[all[shadows+tiddlers]removeprefix[$:/config/ShortcutInfo/]]\" variable=\"shortcutName\">\n<<shortcut-item>>\n</$list>\n</tbody>\n</table>\n" }, "$:/core/ui/ControlPanel/LoadedModules": { "title": "$:/core/ui/ControlPanel/LoadedModules", "tags": "$:/tags/ControlPanel/Advanced", "caption": "{{$:/language/ControlPanel/LoadedModules/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/\n<<lingo LoadedModules/Hint>>\n\n{{$:/snippets/modules}}\n" }, "$:/core/ui/ControlPanel/Modals/AddPlugins": { "title": "$:/core/ui/ControlPanel/Modals/AddPlugins", "subtitle": "{{$:/core/images/download-button}} {{$:/language/ControlPanel/Plugins/Add/Caption}}", "text": "\\define install-plugin-button()\n<$button>\n<$action-sendmessage $message=\"tm-load-plugin-from-library\" url={{!!url}} title={{$(assetInfo)$!!original-title}}/>\n<$list filter=\"[<assetInfo>get[original-title]get[version]]\" variable=\"installedVersion\" emptyMessage=\"\"\"{{$:/language/ControlPanel/Plugins/Install/Caption}}\"\"\">\n{{$:/language/ControlPanel/Plugins/Reinstall/Caption}}\n</$list>\n</$button>\n\\end\n\n\\define popup-state-macro()\n$:/state/add-plugin-info/$(connectionTiddler)$/$(assetInfo)$\n\\end\n\n\\define display-plugin-info(type)\n<$set name=\"popup-state\" value=<<popup-state-macro>>>\n<div class=\"tc-plugin-info\">\n<div class=\"tc-plugin-info-chunk tc-small-icon\">\n<$reveal type=\"nomatch\" state=<<popup-state>> text=\"yes\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"yes\">\n{{$:/core/images/right-arrow}}\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<popup-state>> text=\"yes\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<popup-state>> setTo=\"no\">\n{{$:/core/images/down-arrow}}\n</$button>\n</$reveal>\n</div>\n<div class=\"tc-plugin-info-chunk\">\n<$list filter=\"[<assetInfo>has[icon]]\" emptyMessage=\"\"\"<$transclude tiddler=\"$:/core/images/plugin-generic-$type$\"/>\"\"\">\n<img src={{$(assetInfo)$!!icon}}/>\n</$list>\n</div>\n<div class=\"tc-plugin-info-chunk\">\n<h1><$view tiddler=<<assetInfo>> field=\"description\"/></h1>\n<h2><$view tiddler=<<assetInfo>> field=\"original-title\"/></h2>\n<div><em><$view tiddler=<<assetInfo>> field=\"version\"/></em></div>\n</div>\n<div class=\"tc-plugin-info-chunk\">\n<<install-plugin-button>>\n</div>\n</div>\n<$reveal type=\"match\" text=\"yes\" state=<<popup-state>>>\n<div class=\"tc-plugin-info-dropdown\">\n<div class=\"tc-plugin-info-dropdown-message\">\n<$list filter=\"[<assetInfo>get[original-title]get[version]]\" variable=\"installedVersion\" emptyMessage=\"\"\"{{$:/language/ControlPanel/Plugins/NotInstalled/Hint}}\"\"\">\n<em>\n{{$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint}}\n</em>\n</$list>\n</div>\n<div class=\"tc-plugin-info-dropdown-body\">\n<$transclude tiddler=<<assetInfo>> field=\"readme\" mode=\"block\"/>\n</div>\n</div>\n</$reveal>\n</$set>\n\\end\n\n\\define load-plugin-library-button()\n<$button class=\"tc-btn-big-green\">\n<$action-sendmessage $message=\"tm-load-plugin-library\" url={{!!url}} infoTitlePrefix=\"$:/temp/RemoteAssetInfo/\"/>\n{{$:/core/images/chevron-right}} {{$:/language/ControlPanel/Plugins/OpenPluginLibrary}}\n</$button>\n\\end\n\n\\define display-server-assets(type)\n{{$:/language/Search/Search}}: <$edit-text tiddler=\"\"\"$:/temp/RemoteAssetSearch/$(currentTiddler)$\"\"\" default=\"\" type=\"search\" tag=\"input\"/>\n<$reveal state=\"\"\"$:/temp/RemoteAssetSearch/$(currentTiddler)$\"\"\" type=\"nomatch\" text=\"\">\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"\"\"$:/temp/RemoteAssetSearch/$(currentTiddler)$\"\"\" $field=\"text\" $value=\"\"/>\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n<div class=\"tc-plugin-library-listing\">\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[$type$]search{$:/temp/RemoteAssetSearch/$(currentTiddler)$}sort[description]]\" variable=\"assetInfo\">\n<<display-plugin-info \"$type$\">>\n</$list>\n</div>\n\\end\n\n\\define display-server-connection()\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/ServerConnection]suffix{!!url}]\" variable=\"connectionTiddler\" emptyMessage=<<load-plugin-library-button>>>\n\n<<tabs \"[[$:/core/ui/ControlPanel/Plugins/Add/Plugins]] [[$:/core/ui/ControlPanel/Plugins/Add/Themes]] [[$:/core/ui/ControlPanel/Plugins/Add/Languages]]\" \"$:/core/ui/ControlPanel/Plugins/Add/Plugins\">>\n\n</$list>\n\\end\n\n\\define close-library-button()\n<$reveal type='nomatch' state='$:/temp/ServerConnection/$(PluginLibraryURL)$' text=''>\n<$button class='tc-btn-big-green'>\n<$action-sendmessage $message=\"tm-unload-plugin-library\" url={{!!url}}/>\n{{$:/core/images/chevron-left}} {{$:/language/ControlPanel/Plugins/ClosePluginLibrary}}\n<$action-deletetiddler $filter=\"[prefix[$:/temp/ServerConnection/$(PluginLibraryURL)$]][prefix[$:/temp/RemoteAssetInfo/$(PluginLibraryURL)$]]\"/>\n</$button>\n</$reveal>\n\\end\n\n\\define plugin-library-listing()\n<$list filter=\"[all[tiddlers+shadows]tag[$:/tags/PluginLibrary]]\">\n<div class=\"tc-plugin-library\">\n\n!! <$link><$transclude field=\"caption\"><$view field=\"title\"/></$transclude></$link>\n\n//<$view field=\"url\"/>//\n\n<$transclude/>\n\n<$set name=PluginLibraryURL value={{!!url}}>\n<<close-library-button>>\n</$set>\n\n<<display-server-connection>>\n</div>\n</$list>\n\\end\n\n<$importvariables filter=\"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\">\n\n<div>\n<<plugin-library-listing>>\n</div>\n\n</$importvariables>\n" }, "$:/core/ui/ControlPanel/Palette": { "title": "$:/core/ui/ControlPanel/Palette", "tags": "$:/tags/ControlPanel/Appearance", "caption": "{{$:/language/ControlPanel/Palette/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Palette/\n\n{{$:/snippets/paletteswitcher}}\n\n<$reveal type=\"nomatch\" state=\"$:/state/ShowPaletteEditor\" text=\"yes\">\n\n<$button set=\"$:/state/ShowPaletteEditor\" setTo=\"yes\"><<lingo ShowEditor/Caption>></$button>\n\n</$reveal>\n\n<$reveal type=\"match\" state=\"$:/state/ShowPaletteEditor\" text=\"yes\">\n\n<$button set=\"$:/state/ShowPaletteEditor\" setTo=\"no\"><<lingo HideEditor/Caption>></$button>\n{{$:/snippets/paletteeditor}}\n\n</$reveal>\n\n" }, "$:/core/ui/ControlPanel/Parsing": { "title": "$:/core/ui/ControlPanel/Parsing", "tags": "$:/tags/ControlPanel/Advanced", "caption": "{{$:/language/ControlPanel/Parsing/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Parsing/\n\n\\define toggle(Type)\n<$checkbox\ntiddler=\"\"\"$:/config/WikiParserRules/$Type$/$(rule)$\"\"\"\nfield=\"text\"\nchecked=\"enable\"\nunchecked=\"disable\"\ndefault=\"enable\">\n<<rule>>\n</$checkbox>\n\\end\n\n\\define rules(type,Type)\n<$list filter=\"[wikiparserrules[$type$]]\" variable=\"rule\">\n<dd><<toggle $Type$>></dd>\n</$list>\n\\end\n\n<<lingo Hint>>\n\n<dl>\n<dt><<lingo Pragma/Caption>></dt>\n<<rules pragma Pragma>>\n<dt><<lingo Inline/Caption>></dt>\n<<rules inline Inline>>\n<dt><<lingo Block/Caption>></dt>\n<<rules block Block>>\n</dl>" }, "$:/core/ui/ControlPanel/Plugins/Add/Languages": { "title": "$:/core/ui/ControlPanel/Plugins/Add/Languages", "caption": "{{$:/language/ControlPanel/Plugins/Languages/Caption}} (<$count filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[language]]\"/>)", "text": "<<display-server-assets language>>\n" }, "$:/core/ui/ControlPanel/Plugins/Add/Plugins": { "title": "$:/core/ui/ControlPanel/Plugins/Add/Plugins", "caption": "{{$:/language/ControlPanel/Plugins/Plugins/Caption}} (<$count filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[plugin]]\"/>)", "text": "<<display-server-assets plugin>>\n" }, "$:/core/ui/ControlPanel/Plugins/Add/Themes": { "title": "$:/core/ui/ControlPanel/Plugins/Add/Themes", "caption": "{{$:/language/ControlPanel/Plugins/Themes/Caption}} (<$count filter=\"[all[tiddlers+shadows]tag[$:/tags/RemoteAssetInfo]server-url{!!url}original-plugin-type[theme]]\"/>)", "text": "<<display-server-assets theme>>\n" }, "$:/core/ui/ControlPanel/Plugins/AddPlugins": { "title": "$:/core/ui/ControlPanel/Plugins/AddPlugins", "text": "\\define lingo-base() $:/language/ControlPanel/Plugins/\n\n<$button message=\"tm-modal\" param=\"$:/core/ui/ControlPanel/Modals/AddPlugins\" tooltip={{$:/language/ControlPanel/Plugins/Add/Hint}} class=\"tc-btn-big-green\" style=\"background:blue;\">\n{{$:/core/images/download-button}} <<lingo Add/Caption>>\n</$button>\n" }, "$:/core/ui/ControlPanel/Plugins/Installed/Languages": { "title": "$:/core/ui/ControlPanel/Plugins/Installed/Languages", "caption": "{{$:/language/ControlPanel/Plugins/Languages/Caption}} (<$count filter=\"[!has[draft.of]plugin-type[language]]\"/>)", "text": "<<plugin-table language>>\n" }, "$:/core/ui/ControlPanel/Plugins/Installed/Plugins": { "title": "$:/core/ui/ControlPanel/Plugins/Installed/Plugins", "caption": "{{$:/language/ControlPanel/Plugins/Plugins/Caption}} (<$count filter=\"[!has[draft.of]plugin-type[plugin]]\"/>)", "text": "<<plugin-table plugin>>\n" }, "$:/core/ui/ControlPanel/Plugins/Installed/Themes": { "title": "$:/core/ui/ControlPanel/Plugins/Installed/Themes", "caption": "{{$:/language/ControlPanel/Plugins/Themes/Caption}} (<$count filter=\"[!has[draft.of]plugin-type[theme]]\"/>)", "text": "<<plugin-table theme>>\n" }, "$:/core/ui/ControlPanel/Plugins": { "title": "$:/core/ui/ControlPanel/Plugins", "tags": "$:/tags/ControlPanel", "caption": "{{$:/language/ControlPanel/Plugins/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Plugins/\n\n\\define plugin-table(type)\n<$set name=\"plugin-type\" value=\"\"\"$type$\"\"\">\n<$set name=\"qualified-state\" value=<<qualify \"$:/state/plugin-info\">>>\n<$list filter=\"[!has[draft.of]plugin-type[$type$]sort[description]]\" emptyMessage=<<lingo \"Empty/Hint\">> template=\"$:/core/ui/Components/plugin-info\"/>\n</$set>\n</$set>\n\\end\n\n{{$:/core/ui/ControlPanel/Plugins/AddPlugins}}\n\n<<lingo Installed/Hint>>\n\n<<tabs \"[[$:/core/ui/ControlPanel/Plugins/Installed/Plugins]] [[$:/core/ui/ControlPanel/Plugins/Installed/Themes]] [[$:/core/ui/ControlPanel/Plugins/Installed/Languages]]\" \"$:/core/ui/ControlPanel/Plugins/Installed/Plugins\">>\n" }, "$:/core/ui/ControlPanel/Saving/DownloadSaver": { "title": "$:/core/ui/ControlPanel/Saving/DownloadSaver", "tags": "$:/tags/ControlPanel/Saving", "caption": "{{$:/language/ControlPanel/Saving/DownloadSaver/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Saving/DownloadSaver/\n\n<<lingo Hint>>\n\n!! <$link to=\"$:/config/DownloadSaver/AutoSave\"><<lingo AutoSave/Hint>></$link>\n\n<$checkbox tiddler=\"$:/config/DownloadSaver/AutoSave\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> <<lingo AutoSave/Description>> </$checkbox>\n" }, "$:/core/ui/ControlPanel/Saving/General": { "title": "$:/core/ui/ControlPanel/Saving/General", "tags": "$:/tags/ControlPanel/Saving", "caption": "{{$:/language/ControlPanel/Saving/General/Caption}}", "list-before": "", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/\n\n{{$:/language/ControlPanel/Saving/General/Hint}}\n\n!! <$link to=\"$:/config/AutoSave\"><<lingo AutoSave/Caption>></$link>\n\n<<lingo AutoSave/Hint>>\n\n<$radio tiddler=\"$:/config/AutoSave\" value=\"yes\"> <<lingo AutoSave/Enabled/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/AutoSave\" value=\"no\"> <<lingo AutoSave/Disabled/Description>> </$radio>\n" }, "$:/core/ui/ControlPanel/Saving/TiddlySpot": { "title": "$:/core/ui/ControlPanel/Saving/TiddlySpot", "tags": "$:/tags/ControlPanel/Saving", "caption": "{{$:/language/ControlPanel/Saving/TiddlySpot/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Saving/TiddlySpot/\n\n\\define backupURL()\nhttp://$(userName)$.tiddlyspot.com/backup/\n\\end\n\\define backupLink()\n<$reveal type=\"nomatch\" state=\"$:/UploadName\" text=\"\">\n<$set name=\"userName\" value={{$:/UploadName}}>\n<$reveal type=\"match\" state=\"$:/UploadURL\" text=\"\">\n<<backupURL>>\n</$reveal>\n<$reveal type=\"nomatch\" state=\"$:/UploadURL\" text=\"\">\n<$macrocall $name=resolvePath source={{$:/UploadBackupDir}} root={{$:/UploadURL}}>>\n</$reveal>\n</$set>\n</$reveal>\n\\end\n\n<<lingo Description>>\n\n|<<lingo UserName>> |<$edit-text tiddler=\"$:/UploadName\" default=\"\" tag=\"input\"/> |\n|<<lingo Password>> |<$password name=\"upload\"/> |\n|<<lingo Backups>> |<<backupLink>> |\n\n''<<lingo Advanced/Heading>>''\n\n|<<lingo ServerURL>> |<$edit-text tiddler=\"$:/UploadURL\" default=\"\" tag=\"input\"/> |\n|<<lingo Filename>> |<$edit-text tiddler=\"$:/UploadFilename\" default=\"index.html\" tag=\"input\"/> |\n|<<lingo UploadDir>> |<$edit-text tiddler=\"$:/UploadDir\" default=\".\" tag=\"input\"/> |\n|<<lingo BackupDir>> |<$edit-text tiddler=\"$:/UploadBackupDir\" default=\".\" tag=\"input\"/> |\n\n<<lingo TiddlySpot/Hint>>" }, "$:/core/ui/ControlPanel/Saving": { "title": "$:/core/ui/ControlPanel/Saving", "tags": "$:/tags/ControlPanel", "caption": "{{$:/language/ControlPanel/Saving/Caption}}", "text": "{{$:/language/ControlPanel/Saving/Hint}}\n\n<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Saving]!has[draft.of]]\" \"$:/core/ui/ControlPanel/Saving/General\">>\n</div>\n" }, "$:/core/buttonstyles/Borderless": { "title": "$:/core/buttonstyles/Borderless", "tags": "$:/tags/ToolbarButtonStyle", "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless}}", "text": "tc-btn-invisible" }, "$:/core/buttonstyles/Boxed": { "title": "$:/core/buttonstyles/Boxed", "tags": "$:/tags/ToolbarButtonStyle", "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed}}", "text": "tc-btn-boxed" }, "$:/core/buttonstyles/Rounded": { "title": "$:/core/buttonstyles/Rounded", "tags": "$:/tags/ToolbarButtonStyle", "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded}}", "text": "tc-btn-rounded" }, "$:/core/ui/ControlPanel/Settings/CamelCase": { "title": "$:/core/ui/ControlPanel/Settings/CamelCase", "tags": "$:/tags/ControlPanel/Settings", "caption": "{{$:/language/ControlPanel/Settings/CamelCase/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/CamelCase/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/WikiParserRules/Inline/wikilink\" field=\"text\" checked=\"enable\" unchecked=\"disable\" default=\"enable\"> <$link to=\"$:/config/WikiParserRules/Inline/wikilink\"><<lingo Description>></$link> </$checkbox>\n" }, "$:/core/ui/ControlPanel/Settings/DefaultSidebarTab": { "caption": "{{$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption}}", "tags": "$:/tags/ControlPanel/Settings", "title": "$:/core/ui/ControlPanel/Settings/DefaultSidebarTab", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/DefaultSidebarTab/\n\n<$link to=\"$:/config/DefaultSidebarTab\"><<lingo Hint>></$link>\n\n<$select tiddler=\"$:/config/DefaultSidebarTab\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SideBar]!has[draft.of]]\">\n<option value=<<currentTiddler>>><$transclude field=\"caption\"><$text text=<<currentTiddler>>/></$transclude></option>\n</$list>\n</$select>\n" }, "$:/core/ui/ControlPanel/Settings/EditorToolbar": { "title": "$:/core/ui/ControlPanel/Settings/EditorToolbar", "tags": "$:/tags/ControlPanel/Settings", "caption": "{{$:/language/ControlPanel/Settings/EditorToolbar/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/EditorToolbar/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/TextEditor/EnableToolbar\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/TextEditor/EnableToolbar\"><<lingo Description>></$link> </$checkbox>\n\n" }, "$:/core/ui/ControlPanel/Settings/InfoPanelMode": { "title": "$:/core/ui/ControlPanel/Settings/InfoPanelMode", "tags": "$:/tags/ControlPanel/Settings", "caption": "{{$:/language/ControlPanel/Settings/InfoPanelMode/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/InfoPanelMode/\n<$link to=\"$:/config/TiddlerInfo/Mode\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/TiddlerInfo/Mode\" value=\"popup\"> <<lingo Popup/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/TiddlerInfo/Mode\" value=\"sticky\"> <<lingo Sticky/Description>> </$radio>\n" }, "$:/core/ui/ControlPanel/Settings/LinkToBehaviour": { "title": "$:/core/ui/ControlPanel/Settings/LinkToBehaviour", "tags": "$:/tags/ControlPanel/Settings", "caption": "{{$:/language/ControlPanel/Settings/LinkToBehaviour/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/LinkToBehaviour/\n\n<$link to=\"$:/config/Navigation/openLinkFromInsideRiver\"><<lingo \"InsideRiver/Hint\">></$link>\n\n<$select tiddler=\"$:/config/Navigation/openLinkFromInsideRiver\">\n <option value=\"above\"><<lingo \"OpenAbove\">></option>\n <option value=\"below\"><<lingo \"OpenBelow\">></option>\n <option value=\"top\"><<lingo \"OpenAtTop\">></option>\n <option value=\"bottom\"><<lingo \"OpenAtBottom\">></option>\n</$select>\n\n<$link to=\"$:/config/Navigation/openLinkFromOutsideRiver\"><<lingo \"OutsideRiver/Hint\">></$link>\n\n<$select tiddler=\"$:/config/Navigation/openLinkFromOutsideRiver\">\n <option value=\"top\"><<lingo \"OpenAtTop\">></option>\n <option value=\"bottom\"><<lingo \"OpenAtBottom\">></option>\n</$select>\n" }, "$:/core/ui/ControlPanel/Settings/MissingLinks": { "title": "$:/core/ui/ControlPanel/Settings/MissingLinks", "tags": "$:/tags/ControlPanel/Settings", "caption": "{{$:/language/ControlPanel/Settings/MissingLinks/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/MissingLinks/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/MissingLinks\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/MissingLinks\"><<lingo Description>></$link> </$checkbox>\n\n" }, "$:/core/ui/ControlPanel/Settings/NavigationAddressBar": { "title": "$:/core/ui/ControlPanel/Settings/NavigationAddressBar", "tags": "$:/tags/ControlPanel/Settings", "caption": "{{$:/language/ControlPanel/Settings/NavigationAddressBar/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/NavigationAddressBar/\n\n<$link to=\"$:/config/Navigation/UpdateAddressBar\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateAddressBar\" value=\"permaview\"> <<lingo Permaview/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateAddressBar\" value=\"permalink\"> <<lingo Permalink/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateAddressBar\" value=\"no\"> <<lingo No/Description>> </$radio>\n" }, "$:/core/ui/ControlPanel/Settings/NavigationHistory": { "title": "$:/core/ui/ControlPanel/Settings/NavigationHistory", "tags": "$:/tags/ControlPanel/Settings", "caption": "{{$:/language/ControlPanel/Settings/NavigationHistory/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/NavigationHistory/\n<$link to=\"$:/config/Navigation/UpdateHistory\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateHistory\" value=\"yes\"> <<lingo Yes/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Navigation/UpdateHistory\" value=\"no\"> <<lingo No/Description>> </$radio>\n" }, "$:/core/ui/ControlPanel/Settings/PerformanceInstrumentation": { "title": "$:/core/ui/ControlPanel/Settings/PerformanceInstrumentation", "tags": "$:/tags/ControlPanel/Settings", "caption": "{{$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/PerformanceInstrumentation/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/Performance/Instrumentation\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> <$link to=\"$:/config/Performance/Instrumentation\"><<lingo Description>></$link> </$checkbox>\n" }, "$:/core/ui/ControlPanel/Settings/TitleLinks": { "title": "$:/core/ui/ControlPanel/Settings/TitleLinks", "tags": "$:/tags/ControlPanel/Settings", "caption": "{{$:/language/ControlPanel/Settings/TitleLinks/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/TitleLinks/\n<$link to=\"$:/config/Tiddlers/TitleLinks\"><<lingo Hint>></$link>\n\n<$radio tiddler=\"$:/config/Tiddlers/TitleLinks\" value=\"yes\"> <<lingo Yes/Description>> </$radio>\n\n<$radio tiddler=\"$:/config/Tiddlers/TitleLinks\" value=\"no\"> <<lingo No/Description>> </$radio>\n" }, "$:/core/ui/ControlPanel/Settings/ToolbarButtonStyle": { "title": "$:/core/ui/ControlPanel/Settings/ToolbarButtonStyle", "tags": "$:/tags/ControlPanel/Settings", "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/ToolbarButtonStyle/\n<$link to=\"$:/config/Toolbar/ButtonClass\"><<lingo \"Hint\">></$link>\n\n<$select tiddler=\"$:/config/Toolbar/ButtonClass\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ToolbarButtonStyle]]\">\n<option value={{!!text}}>{{!!caption}}</option>\n</$list>\n</$select>\n" }, "$:/core/ui/ControlPanel/Settings/ToolbarButtons": { "title": "$:/core/ui/ControlPanel/Settings/ToolbarButtons", "tags": "$:/tags/ControlPanel/Settings", "caption": "{{$:/language/ControlPanel/Settings/ToolbarButtons/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/ToolbarButtons/\n<<lingo Hint>>\n\n<$checkbox tiddler=\"$:/config/Toolbar/Icons\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"yes\"> <$link to=\"$:/config/Toolbar/Icons\"><<lingo Icons/Description>></$link> </$checkbox>\n\n<$checkbox tiddler=\"$:/config/Toolbar/Text\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> <$link to=\"$:/config/Toolbar/Text\"><<lingo Text/Description>></$link> </$checkbox>\n" }, "$:/core/ui/ControlPanel/Settings": { "title": "$:/core/ui/ControlPanel/Settings", "tags": "$:/tags/ControlPanel", "caption": "{{$:/language/ControlPanel/Settings/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/Settings/\n\n<<lingo Hint>>\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Settings]]\">\n\n<div style=\"border-top:1px solid #eee;\">\n\n!! <$link><$transclude field=\"caption\"/></$link>\n\n<$transclude/>\n\n</div>\n\n</$list>\n" }, "$:/core/ui/ControlPanel/StoryView": { "title": "$:/core/ui/ControlPanel/StoryView", "tags": "$:/tags/ControlPanel/Appearance", "caption": "{{$:/language/ControlPanel/StoryView/Caption}}", "text": "{{$:/snippets/viewswitcher}}\n" }, "$:/core/ui/ControlPanel/Theme": { "title": "$:/core/ui/ControlPanel/Theme", "tags": "$:/tags/ControlPanel/Appearance", "caption": "{{$:/language/ControlPanel/Theme/Caption}}", "text": "{{$:/snippets/themeswitcher}}\n" }, "$:/core/ui/ControlPanel/TiddlerFields": { "title": "$:/core/ui/ControlPanel/TiddlerFields", "tags": "$:/tags/ControlPanel/Advanced", "caption": "{{$:/language/ControlPanel/TiddlerFields/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/\n\n<<lingo TiddlerFields/Hint>>\n\n{{$:/snippets/allfields}}" }, "$:/core/ui/ControlPanel/Toolbars/EditToolbar": { "title": "$:/core/ui/ControlPanel/Toolbars/EditToolbar", "tags": "$:/tags/ControlPanel/Toolbars", "caption": "{{$:/language/ControlPanel/Toolbars/EditToolbar/Caption}}", "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/EditToolbarButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/EditToolbar/Hint}}\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/EditToolbar\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/ItemTemplate\"/>\n\n</$set>\n\n</$set>" }, "$:/core/ui/ControlPanel/Toolbars/EditorItemTemplate": { "title": "$:/core/ui/ControlPanel/Toolbars/EditorItemTemplate", "text": "\\define config-title()\n$(config-base)$$(currentTiddler)$\n\\end\n\n<$draggable tiddler=<<currentTiddler>>>\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <span class=\"tc-icon-wrapper\"><$transclude tiddler={{!!icon}}/></span> <$transclude field=\"caption\"/> -- <i class=\"tc-muted\"><$transclude field=\"description\"/></i>\n</$draggable>\n" }, "$:/core/ui/ControlPanel/Toolbars/EditorToolbar": { "title": "$:/core/ui/ControlPanel/Toolbars/EditorToolbar", "tags": "$:/tags/ControlPanel/Toolbars", "caption": "{{$:/language/ControlPanel/Toolbars/EditorToolbar/Caption}}", "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/EditorToolbarButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/EditorToolbar/Hint}}\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/EditorToolbar\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/EditorItemTemplate\"/>\n" }, "$:/core/ui/ControlPanel/Toolbars/ItemTemplate": { "title": "$:/core/ui/ControlPanel/Toolbars/ItemTemplate", "text": "\\define config-title()\n$(config-base)$$(currentTiddler)$\n\\end\n\n<$draggable tiddler=<<currentTiddler>>>\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <span class=\"tc-icon-wrapper\"> <$transclude field=\"caption\"/> <i class=\"tc-muted\">-- <$transclude field=\"description\"/></i></span>\n</$draggable>\n" }, "$:/core/ui/ControlPanel/Toolbars/PageControls": { "title": "$:/core/ui/ControlPanel/Toolbars/PageControls", "tags": "$:/tags/ControlPanel/Toolbars", "caption": "{{$:/language/ControlPanel/Toolbars/PageControls/Caption}}", "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/PageControlButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/PageControls/Hint}}\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/PageControls\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/ItemTemplate\"/>\n\n</$set>\n\n</$set>\n" }, "$:/core/ui/ControlPanel/Toolbars/ViewToolbar": { "title": "$:/core/ui/ControlPanel/Toolbars/ViewToolbar", "tags": "$:/tags/ControlPanel/Toolbars", "caption": "{{$:/language/ControlPanel/Toolbars/ViewToolbar/Caption}}", "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\n\\define config-base() $:/config/ViewToolbarButtons/Visibility/\n\n{{$:/language/ControlPanel/Toolbars/ViewToolbar/Hint}}\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$macrocall $name=\"list-tagged-draggable\" tag=\"$:/tags/ViewToolbar\" itemTemplate=\"$:/core/ui/ControlPanel/Toolbars/ItemTemplate\"/>\n\n</$set>\n\n</$set>\n" }, "$:/core/ui/ControlPanel/Toolbars": { "title": "$:/core/ui/ControlPanel/Toolbars", "tags": "$:/tags/ControlPanel/Appearance", "caption": "{{$:/language/ControlPanel/Toolbars/Caption}}", "text": "{{$:/language/ControlPanel/Toolbars/Hint}}\n\n<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Toolbars]!has[draft.of]]\" \"$:/core/ui/ControlPanel/Toolbars/ViewToolbar\" \"$:/state/tabs/controlpanel/toolbars\" \"tc-vertical\">>\n</div>\n" }, "$:/ControlPanel": { "title": "$:/ControlPanel", "icon": "$:/core/images/options-button", "color": "#bbb", "text": "<div class=\"tc-control-panel\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/ControlPanel]!has[draft.of]]\" \"$:/core/ui/ControlPanel/Info\">>\n</div>\n" }, "$:/core/ui/DefaultSearchResultList": { "title": "$:/core/ui/DefaultSearchResultList", "tags": "$:/tags/SearchResults", "caption": "{{$:/language/Search/DefaultResults/Caption}}", "text": "\\define searchResultList()\n//<small>{{$:/language/Search/Matches/Title}}</small>//\n\n<$list filter=\"[!is[system]search:title{$(searchTiddler)$}sort[title]limit[250]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n\n//<small>{{$:/language/Search/Matches/All}}</small>//\n\n<$list filter=\"[!is[system]search{$(searchTiddler)$}sort[title]limit[250]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n\n\\end\n<<searchResultList>>\n" }, "$:/core/ui/EditTemplate/body/preview/output": { "title": "$:/core/ui/EditTemplate/body/preview/output", "tags": "$:/tags/EditPreview", "caption": "{{$:/language/EditTemplate/Body/Preview/Type/Output}}", "text": "<$set name=\"tv-tiddler-preview\" value=\"yes\">\n\n<$transclude />\n\n</$set>\n" }, "$:/core/ui/EditTemplate/body/editor": { "title": "$:/core/ui/EditTemplate/body/editor", "text": "<$edit\n\n field=\"text\"\n class=\"tc-edit-texteditor\"\n placeholder={{$:/language/EditTemplate/Body/Placeholder}}\n\n><$set\n\n name=\"targetTiddler\"\n value=<<currentTiddler>>\n\n><$list\n\n filter=\"[all[shadows+tiddlers]tag[$:/tags/EditorToolbar]!has[draft.of]]\"\n\n><$reveal\n\n type=\"nomatch\"\n state=<<config-visibility-title>>\n text=\"hide\"\n class=\"tc-text-editor-toolbar-item-wrapper\"\n\n><$transclude\n\n tiddler=\"$:/core/ui/EditTemplate/body/toolbar/button\"\n mode=\"inline\"\n\n/></$reveal></$list></$set></$edit>\n" }, "$:/core/ui/EditTemplate/body/toolbar/button": { "title": "$:/core/ui/EditTemplate/body/toolbar/button", "text": "\\define toolbar-button-icon()\n<$list\n\n filter=\"[all[current]!has[custom-icon]]\"\n variable=\"no-custom-icon\"\n\n><$transclude\n\n tiddler={{!!icon}}\n\n/></$list>\n\\end\n\n\\define toolbar-button-tooltip()\n{{!!description}}<$macrocall $name=\"displayshortcuts\" $output=\"text/plain\" shortcuts={{!!shortcuts}} prefix=\"` - [\" separator=\"] [\" suffix=\"]`\"/>\n\\end\n\n\\define toolbar-button()\n<$list\n\n filter={{!!condition}}\n variable=\"list-condition\"\n\n><$wikify\n\n name=\"tooltip-text\"\n text=<<toolbar-button-tooltip>>\n mode=\"inline\"\n output=\"text\"\n\n><$list\n\n filter=\"[all[current]!has[dropdown]]\"\n variable=\"no-dropdown\"\n\n><$button\n\n class=\"tc-btn-invisible $(buttonClasses)$\"\n tooltip=<<tooltip-text>>\n\n><span\n\n data-tw-keyboard-shortcut={{!!shortcuts}}\n\n/><<toolbar-button-icon>><$transclude\n\n tiddler=<<currentTiddler>>\n field=\"text\"\n\n/></$button></$list><$list\n\n filter=\"[all[current]has[dropdown]]\"\n variable=\"dropdown\"\n\n><$set\n\n name=\"dropdown-state\"\n value=<<qualify \"$:/state/EditorToolbarDropdown\">>\n\n><$button\n\n popup=<<dropdown-state>>\n class=\"tc-popup-keep tc-btn-invisible $(buttonClasses)$\"\n selectedClass=\"tc-selected\"\n tooltip=<<tooltip-text>>\n\n><span\n\n data-tw-keyboard-shortcut={{!!shortcuts}}\n\n/><<toolbar-button-icon>><$transclude\n\n tiddler=<<currentTiddler>>\n field=\"text\"\n\n/></$button><$reveal\n\n state=<<dropdown-state>>\n type=\"popup\"\n position=\"below\"\n animate=\"yes\"\n tag=\"span\"\n\n><div\n\n class=\"tc-drop-down tc-popup-keep\"\n\n><$transclude\n\n tiddler={{!!dropdown}}\n mode=\"block\"\n\n/></div></$reveal></$set></$list></$wikify></$list>\n\\end\n\n\\define toolbar-button-outer()\n<$set\n\n name=\"buttonClasses\"\n value={{!!button-classes}}\n\n><<toolbar-button>></$set>\n\\end\n\n<<toolbar-button-outer>>" }, "$:/core/ui/EditTemplate/body": { "title": "$:/core/ui/EditTemplate/body", "tags": "$:/tags/EditTemplate", "text": "\\define lingo-base() $:/language/EditTemplate/Body/\n\\define config-visibility-title()\n$:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$\n\\end\n<$list filter=\"[is[current]has[_canonical_uri]]\">\n\n<div class=\"tc-message-box\">\n\n<<lingo External/Hint>>\n\n<a href={{!!_canonical_uri}}><$text text={{!!_canonical_uri}}/></a>\n\n<$edit-text field=\"_canonical_uri\" class=\"tc-edit-fields\"></$edit-text>\n\n</div>\n\n</$list>\n\n<$list filter=\"[is[current]!has[_canonical_uri]]\">\n\n<$reveal state=\"$:/state/showeditpreview\" type=\"match\" text=\"yes\">\n\n<div class=\"tc-tiddler-preview\">\n\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/editor\" mode=\"inline\"/>\n\n<div class=\"tc-tiddler-preview-preview\">\n\n<$transclude tiddler={{$:/state/editpreviewtype}} mode=\"inline\">\n\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/preview/output\" mode=\"inline\"/>\n\n</$transclude>\n\n</div>\n\n</div>\n\n</$reveal>\n\n<$reveal state=\"$:/state/showeditpreview\" type=\"nomatch\" text=\"yes\">\n\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/editor\" mode=\"inline\"/>\n\n</$reveal>\n\n</$list>\n" }, "$:/core/ui/EditTemplate/controls": { "title": "$:/core/ui/EditTemplate/controls", "tags": "$:/tags/EditTemplate", "text": "\\define config-title()\n$:/config/EditToolbarButtons/Visibility/$(listItem)$\n\\end\n<div class=\"tc-tiddler-title tc-tiddler-edit-title\">\n<$view field=\"title\"/>\n<span class=\"tc-tiddler-controls tc-titlebar\"><$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditToolbar]!has[draft.of]]\" variable=\"listItem\"><$reveal type=\"nomatch\" state=<<config-title>> text=\"hide\"><$transclude tiddler=<<listItem>>/></$reveal></$list></span>\n<div style=\"clear: both;\"></div>\n</div>\n" }, "$:/core/ui/EditTemplate/fields": { "title": "$:/core/ui/EditTemplate/fields", "tags": "$:/tags/EditTemplate", "text": "\\define lingo-base() $:/language/EditTemplate/\n\\define config-title()\n$:/config/EditTemplateFields/Visibility/$(currentField)$\n\\end\n\n\\define config-filter()\n[[hide]] -[title{$(config-title)$}]\n\\end\n\n\\define new-field-inner()\n<$reveal type=\"nomatch\" text=\"\" default=<<name>>>\n<$button>\n<$action-sendmessage $message=\"tm-add-field\" $name=<<name>> $value=<<value>>/>\n<$action-deletetiddler $tiddler=\"$:/temp/newfieldname\"/>\n<$action-deletetiddler $tiddler=\"$:/temp/newfieldvalue\"/>\n<<lingo Fields/Add/Button>>\n</$button>\n</$reveal>\n<$reveal type=\"match\" text=\"\" default=<<name>>>\n<$button>\n<<lingo Fields/Add/Button>>\n</$button>\n</$reveal>\n\\end\n\n\\define new-field()\n<$set name=\"name\" value={{$:/temp/newfieldname}}>\n<$set name=\"value\" value={{$:/temp/newfieldvalue}}>\n<<new-field-inner>>\n</$set>\n</$set>\n\\end\n\n<div class=\"tc-edit-fields\">\n<table class=\"tc-edit-fields\">\n<tbody>\n<$list filter=\"[all[current]fields[]] +[sort[title]]\" variable=\"currentField\">\n<$list filter=<<config-filter>> variable=\"temp\">\n<tr class=\"tc-edit-field\">\n<td class=\"tc-edit-field-name\">\n<$text text=<<currentField>>/>:</td>\n<td class=\"tc-edit-field-value\">\n<$edit-text tiddler=<<currentTiddler>> field=<<currentField>> placeholder={{$:/language/EditTemplate/Fields/Add/Value/Placeholder}}/>\n</td>\n<td class=\"tc-edit-field-remove\">\n<$button class=\"tc-btn-invisible\" tooltip={{$:/language/EditTemplate/Field/Remove/Hint}} aria-label={{$:/language/EditTemplate/Field/Remove/Caption}}>\n<$action-deletefield $field=<<currentField>>/>\n{{$:/core/images/delete-button}}\n</$button>\n</td>\n</tr>\n</$list>\n</$list>\n</tbody>\n</table>\n</div>\n\n<$fieldmangler>\n<div class=\"tc-edit-field-add\">\n<em class=\"tc-edit\">\n<<lingo Fields/Add/Prompt>>\n</em>\n<span class=\"tc-edit-field-add-name\">\n<$edit-text tiddler=\"$:/temp/newfieldname\" tag=\"input\" default=\"\" placeholder={{$:/language/EditTemplate/Fields/Add/Name/Placeholder}} focusPopup=<<qualify \"$:/state/popup/field-dropdown\">> class=\"tc-edit-texteditor tc-popup-handle\"/>\n</span>\n<$button popup=<<qualify \"$:/state/popup/field-dropdown\">> class=\"tc-btn-invisible tc-btn-dropdown\" tooltip={{$:/language/EditTemplate/Field/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Field/Dropdown/Caption}}>{{$:/core/images/down-arrow}}</$button>\n<$reveal state=<<qualify \"$:/state/popup/field-dropdown\">> type=\"nomatch\" text=\"\" default=\"\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<$linkcatcher to=\"$:/temp/newfieldname\">\n<div class=\"tc-dropdown-item\">\n<<lingo Fields/Add/Dropdown/User>>\n</div>\n<$list filter=\"[!is[shadow]!is[system]fields[]search:title{$:/temp/newfieldname}sort[]] -created -creator -draft.of -draft.title -modified -modifier -tags -text -title -type\" variable=\"currentField\">\n<$link to=<<currentField>>>\n<<currentField>>\n</$link>\n</$list>\n<div class=\"tc-dropdown-item\">\n<<lingo Fields/Add/Dropdown/System>>\n</div>\n<$list filter=\"[fields[]search:title{$:/temp/newfieldname}sort[]] -[!is[shadow]!is[system]fields[]]\" variable=\"currentField\">\n<$link to=<<currentField>>>\n<<currentField>>\n</$link>\n</$list>\n</$linkcatcher>\n</div>\n</$reveal>\n<span class=\"tc-edit-field-add-value\">\n<$edit-text tiddler=\"$:/temp/newfieldvalue\" tag=\"input\" default=\"\" placeholder={{$:/language/EditTemplate/Fields/Add/Value/Placeholder}} class=\"tc-edit-texteditor\"/>\n</span>\n<span class=\"tc-edit-field-add-button\">\n<$macrocall $name=\"new-field\"/>\n</span>\n</div>\n</$fieldmangler>\n" }, "$:/core/ui/EditTemplate/shadow": { "title": "$:/core/ui/EditTemplate/shadow", "tags": "$:/tags/EditTemplate", "text": "\\define lingo-base() $:/language/EditTemplate/Shadow/\n\\define pluginLinkBody()\n<$link to=\"\"\"$(pluginTitle)$\"\"\">\n<$text text=\"\"\"$(pluginTitle)$\"\"\"/>\n</$link>\n\\end\n<$list filter=\"[all[current]get[draft.of]is[shadow]!is[tiddler]]\">\n\n<$list filter=\"[all[current]shadowsource[]]\" variable=\"pluginTitle\">\n\n<$set name=\"pluginLink\" value=<<pluginLinkBody>>>\n<div class=\"tc-message-box\">\n\n<<lingo Warning>>\n\n</div>\n</$set>\n</$list>\n\n</$list>\n\n<$list filter=\"[all[current]get[draft.of]is[shadow]is[tiddler]]\">\n\n<$list filter=\"[all[current]shadowsource[]]\" variable=\"pluginTitle\">\n\n<$set name=\"pluginLink\" value=<<pluginLinkBody>>>\n<div class=\"tc-message-box\">\n\n<<lingo OverriddenWarning>>\n\n</div>\n</$set>\n</$list>\n\n</$list>" }, "$:/core/ui/EditTemplate/tags": { "title": "$:/core/ui/EditTemplate/tags", "tags": "$:/tags/EditTemplate", "text": "\\define lingo-base() $:/language/EditTemplate/\n\n\\define tag-styles()\nbackground-color:$(backgroundColor)$;\nfill:$(foregroundColor)$;\ncolor:$(foregroundColor)$;\n\\end\n\n\\define tag-body-inner(colour,fallbackTarget,colourA,colourB)\n<$vars foregroundColor=<<contrastcolour target:\"\"\"$colour$\"\"\" fallbackTarget:\"\"\"$fallbackTarget$\"\"\" colourA:\"\"\"$colourA$\"\"\" colourB:\"\"\"$colourB$\"\"\">> backgroundColor=\"\"\"$colour$\"\"\">\n<span style=<<tag-styles>> class=\"tc-tag-label\">\n<$view field=\"title\" format=\"text\" />\n<$button message=\"tm-remove-tag\" param={{!!title}} class=\"tc-btn-invisible tc-remove-tag-button\">×</$button>\n</span>\n</$vars>\n\\end\n\n\\define tag-body(colour,palette)\n<$macrocall $name=\"tag-body-inner\" colour=\"\"\"$colour$\"\"\" fallbackTarget={{$palette$##tag-background}} colourA={{$palette$##foreground}} colourB={{$palette$##background}}/>\n\\end\n\n\\define tag-picker-actions()\n<$action-listops\n\t$tiddler=<<currentTiddler>>\n\t$field=\"tags\"\n\t$subfilter=\"[<tag>] [all[current]tags[]]\"\n/>\n\\end\n\n<div class=\"tc-edit-tags\">\n<$fieldmangler>\n<$list filter=\"[all[current]tags[]sort[title]]\" storyview=\"pop\">\n<$macrocall $name=\"tag-body\" colour={{!!color}} palette={{$:/palette}}/>\n</$list>\n</$fieldmangler>\n<$macrocall $name=\"tag-picker\" actions=<<tag-picker-actions>>/>\n</div>\n" }, "$:/core/ui/EditTemplate/title": { "title": "$:/core/ui/EditTemplate/title", "tags": "$:/tags/EditTemplate", "text": "<$edit-text field=\"draft.title\" class=\"tc-titlebar tc-edit-texteditor\" focus=\"true\"/>\n\n<$vars pattern=\"\"\"[\\|\\[\\]{}]\"\"\" bad-chars=\"\"\"`| [ ] { }`\"\"\">\n\n<$list filter=\"[is[current]regexp:draft.title<pattern>]\" variable=\"listItem\">\n\n<div class=\"tc-message-box\">\n\n{{$:/core/images/warning}} {{$:/language/EditTemplate/Title/BadCharacterWarning}}\n\n</div>\n\n</$list>\n\n</$vars>\n\n<$reveal state=\"!!draft.title\" type=\"nomatch\" text={{!!draft.of}} tag=\"div\">\n\n<$list filter=\"[{!!draft.title}!is[missing]]\" variable=\"listItem\">\n\n<div class=\"tc-message-box\">\n\n{{$:/core/images/warning}} {{$:/language/EditTemplate/Title/Exists/Prompt}}\n\n</div>\n\n</$list>\n\n<$list filter=\"[{!!draft.of}!is[missing]]\" variable=\"listItem\">\n\n<$vars fromTitle={{!!draft.of}} toTitle={{!!draft.title}}>\n\n<$checkbox tiddler=\"$:/config/RelinkOnRename\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"no\"> {{$:/language/EditTemplate/Title/Relink/Prompt}}</$checkbox>\n\n</$vars>\n\n</$list>\n\n</$reveal>\n\n\n" }, "$:/core/ui/EditTemplate/type": { "title": "$:/core/ui/EditTemplate/type", "tags": "$:/tags/EditTemplate", "text": "\\define lingo-base() $:/language/EditTemplate/\n<div class=\"tc-type-selector\"><$fieldmangler>\n<em class=\"tc-edit\"><<lingo Type/Prompt>></em> <$edit-text field=\"type\" tag=\"input\" default=\"\" placeholder={{$:/language/EditTemplate/Type/Placeholder}} focusPopup=<<qualify \"$:/state/popup/type-dropdown\">> class=\"tc-edit-typeeditor tc-popup-handle\"/> <$button popup=<<qualify \"$:/state/popup/type-dropdown\">> class=\"tc-btn-invisible tc-btn-dropdown\" tooltip={{$:/language/EditTemplate/Type/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Type/Dropdown/Caption}}>{{$:/core/images/down-arrow}}</$button> <$button message=\"tm-remove-field\" param=\"type\" class=\"tc-btn-invisible tc-btn-icon\" tooltip={{$:/language/EditTemplate/Type/Delete/Hint}} aria-label={{$:/language/EditTemplate/Type/Delete/Caption}}>{{$:/core/images/delete-button}}</$button>\n</$fieldmangler></div>\n\n<div class=\"tc-block-dropdown-wrapper\">\n<$reveal state=<<qualify \"$:/state/popup/type-dropdown\">> type=\"nomatch\" text=\"\" default=\"\">\n<div class=\"tc-block-dropdown tc-edit-type-dropdown\">\n<$linkcatcher to=\"!!type\">\n<$list filter='[all[shadows+tiddlers]prefix[$:/language/Docs/Types/]each[group]sort[group-sort]]'>\n<div class=\"tc-dropdown-item\">\n<$text text={{!!group}}/>\n</div>\n<$list filter=\"[all[shadows+tiddlers]prefix[$:/language/Docs/Types/]group{!!group}] +[sort[description]]\"><$link to={{!!name}}><$view field=\"description\"/> (<$view field=\"name\"/>)</$link>\n</$list>\n</$list>\n</$linkcatcher>\n</div>\n</$reveal>\n</div>" }, "$:/core/ui/EditTemplate": { "title": "$:/core/ui/EditTemplate", "text": "\\define actions()\n<$action-sendmessage $message=\"tm-add-tag\" $param={{$:/temp/NewTagName}}/>\n<$action-deletetiddler $tiddler=\"$:/temp/NewTagName\"/>\n<$action-sendmessage $message=\"tm-add-field\" $name={{$:/temp/newfieldname}} $value={{$:/temp/newfieldvalue}}/>\n<$action-deletetiddler $tiddler=\"$:/temp/newfieldname\"/>\n<$action-deletetiddler $tiddler=\"$:/temp/newfieldvalue\"/>\n<$action-sendmessage $message=\"tm-save-tiddler\"/>\n\\end\n\\define frame-classes()\ntc-tiddler-frame tc-tiddler-edit-frame $(missingTiddlerClass)$ $(shadowTiddlerClass)$ $(systemTiddlerClass)$\n\\end\n<div class=<<frame-classes>>>\n<$fieldmangler>\n<$set name=\"storyTiddler\" value=<<currentTiddler>>>\n<$keyboard key=\"((cancel-edit-tiddler))\" message=\"tm-cancel-tiddler\">\n<$keyboard key=\"((save-tiddler))\" actions=<<actions>>>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditTemplate]!has[draft.of]]\" variable=\"listItem\">\n<$transclude tiddler=<<listItem>>/>\n</$list>\n</$keyboard>\n</$keyboard>\n</$set>\n</$fieldmangler>\n</div>\n" }, "$:/core/ui/Buttons/cancel": { "title": "$:/core/ui/Buttons/cancel", "tags": "$:/tags/EditToolbar", "caption": "{{$:/core/images/cancel-button}} {{$:/language/Buttons/Cancel/Caption}}", "description": "{{$:/language/Buttons/Cancel/Hint}}", "text": "<$button message=\"tm-cancel-tiddler\" tooltip={{$:/language/Buttons/Cancel/Hint}} aria-label={{$:/language/Buttons/Cancel/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/cancel-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Cancel/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/delete": { "title": "$:/core/ui/Buttons/delete", "tags": "$:/tags/EditToolbar $:/tags/ViewToolbar", "caption": "{{$:/core/images/delete-button}} {{$:/language/Buttons/Delete/Caption}}", "description": "{{$:/language/Buttons/Delete/Hint}}", "text": "<$button message=\"tm-delete-tiddler\" tooltip={{$:/language/Buttons/Delete/Hint}} aria-label={{$:/language/Buttons/Delete/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/delete-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Delete/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/save": { "title": "$:/core/ui/Buttons/save", "tags": "$:/tags/EditToolbar", "caption": "{{$:/core/images/done-button}} {{$:/language/Buttons/Save/Caption}}", "description": "{{$:/language/Buttons/Save/Hint}}", "text": "<$fieldmangler><$button tooltip={{$:/language/Buttons/Save/Hint}} aria-label={{$:/language/Buttons/Save/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-add-tag\" $param={{$:/temp/NewTagName}}/>\n<$action-deletetiddler $tiddler=\"$:/temp/NewTagName\"/>\n<$action-sendmessage $message=\"tm-add-field\" $name={{$:/temp/newfieldname}} $value={{$:/temp/newfieldvalue}}/>\n<$action-deletetiddler $tiddler=\"$:/temp/newfieldname\"/>\n<$action-deletetiddler $tiddler=\"$:/temp/newfieldvalue\"/>\n<$action-sendmessage $message=\"tm-save-tiddler\"/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/done-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Save/Caption}}/></span>\n</$list>\n</$button>\n</$fieldmangler>\n" }, "$:/core/ui/EditorToolbar/bold": { "title": "$:/core/ui/EditorToolbar/bold", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/bold", "caption": "{{$:/language/Buttons/Bold/Caption}}", "description": "{{$:/language/Buttons/Bold/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((bold))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"''\"\n\tsuffix=\"''\"\n/>\n" }, "$:/core/ui/EditorToolbar/clear-dropdown": { "title": "$:/core/ui/EditorToolbar/clear-dropdown", "text": "''{{$:/language/Buttons/Clear/Hint}}''\n\n<div class=\"tc-colour-chooser\">\n\n<$macrocall $name=\"colour-picker\" actions=\"\"\"\n\n<$action-sendmessage\n\t$message=\"tm-edit-bitmap-operation\"\n\t$param=\"clear\"\n\tcolour=<<colour-picker-value>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n\"\"\"/>\n\n</div>\n" }, "$:/core/ui/EditorToolbar/clear": { "title": "$:/core/ui/EditorToolbar/clear", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/erase", "caption": "{{$:/language/Buttons/Clear/Caption}}", "description": "{{$:/language/Buttons/Clear/Hint}}", "condition": "[<targetTiddler>is[image]]", "dropdown": "$:/core/ui/EditorToolbar/clear-dropdown", "text": "" }, "$:/core/ui/EditorToolbar/editor-height-dropdown": { "title": "$:/core/ui/EditorToolbar/editor-height-dropdown", "text": "\\define lingo-base() $:/language/Buttons/EditorHeight/\n''<<lingo Hint>>''\n\n<$radio tiddler=\"$:/config/TextEditor/EditorHeight/Mode\" value=\"auto\"> {{$:/core/images/auto-height}} <<lingo Caption/Auto>></$radio>\n\n<$radio tiddler=\"$:/config/TextEditor/EditorHeight/Mode\" value=\"fixed\"> {{$:/core/images/fixed-height}} <<lingo Caption/Fixed>> <$edit-text tag=\"input\" tiddler=\"$:/config/TextEditor/EditorHeight/Height\" default=\"100px\"/></$radio>\n" }, "$:/core/ui/EditorToolbar/editor-height": { "title": "$:/core/ui/EditorToolbar/editor-height", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/fixed-height", "custom-icon": "yes", "caption": "{{$:/language/Buttons/EditorHeight/Caption}}", "description": "{{$:/language/Buttons/EditorHeight/Hint}}", "condition": "[<targetTiddler>!is[image]]", "dropdown": "$:/core/ui/EditorToolbar/editor-height-dropdown", "text": "<$reveal tag=\"span\" state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"fixed\">\n{{$:/core/images/fixed-height}}\n</$reveal>\n<$reveal tag=\"span\" state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"auto\">\n{{$:/core/images/auto-height}}\n</$reveal>\n" }, "$:/core/ui/EditorToolbar/excise-dropdown": { "title": "$:/core/ui/EditorToolbar/excise-dropdown", "text": "\\define lingo-base() $:/language/Buttons/Excise/\n\n\\define body(config-title)\n''<<lingo Hint>>''\n\n<<lingo Caption/NewTitle>> <$edit-text tag=\"input\" tiddler=\"$config-title$/new-title\" default=\"\" focus=\"true\"/>\n\n<$set name=\"new-title\" value={{$config-title$/new-title}}>\n<$list filter=\"\"\"[<new-title>is[tiddler]]\"\"\">\n<div class=\"tc-error\">\n<<lingo Caption/TiddlerExists>>\n</div>\n</$list>\n</$set>\n\n<$checkbox tiddler=\"\"\"$config-title$/tagnew\"\"\" field=\"text\" checked=\"yes\" unchecked=\"no\" default=\"false\"> <<lingo Caption/Tag>></$checkbox>\n\n<<lingo Caption/Replace>> <$select tiddler=\"\"\"$config-title$/type\"\"\" default=\"transclude\">\n<option value=\"link\"><<lingo Caption/Replace/Link>></option>\n<option value=\"transclude\"><<lingo Caption/Replace/Transclusion>></option>\n<option value=\"macro\"><<lingo Caption/Replace/Macro>></option>\n</$select>\n\n<$reveal state=\"\"\"$config-title$/type\"\"\" type=\"match\" text=\"macro\">\n<<lingo Caption/MacroName>> <$edit-text tag=\"input\" tiddler=\"\"\"$config-title$/macro-title\"\"\" default=\"translink\"/>\n</$reveal>\n\n<$button>\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"excise\"\n\ttitle={{$config-title$/new-title}}\n\ttype={{$config-title$/type}}\n\tmacro={{$config-title$/macro-title}}\n\ttagnew={{$config-title$/tagnew}}\n/>\n<$action-deletetiddler\n\t$tiddler=\"$config-title$/new-title\"\n/>\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n<<lingo Caption/Excise>>\n</$button>\n\\end\n\n<$macrocall $name=\"body\" config-title=<<qualify \"$:/state/Excise/\">>/>\n" }, "$:/core/ui/EditorToolbar/excise": { "title": "$:/core/ui/EditorToolbar/excise", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/excise", "caption": "{{$:/language/Buttons/Excise/Caption}}", "description": "{{$:/language/Buttons/Excise/Hint}}", "condition": "[<targetTiddler>!is[image]]", "shortcuts": "((excise))", "dropdown": "$:/core/ui/EditorToolbar/excise-dropdown", "text": "" }, "$:/core/ui/EditorToolbar/heading-1": { "title": "$:/core/ui/EditorToolbar/heading-1", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/heading-1", "caption": "{{$:/language/Buttons/Heading1/Caption}}", "description": "{{$:/language/Buttons/Heading1/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "button-classes": "tc-text-editor-toolbar-item-start-group", "shortcuts": "((heading-1))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"1\"\n/>\n" }, "$:/core/ui/EditorToolbar/heading-2": { "title": "$:/core/ui/EditorToolbar/heading-2", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/heading-2", "caption": "{{$:/language/Buttons/Heading2/Caption}}", "description": "{{$:/language/Buttons/Heading2/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((heading-2))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"2\"\n/>\n" }, "$:/core/ui/EditorToolbar/heading-3": { "title": "$:/core/ui/EditorToolbar/heading-3", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/heading-3", "caption": "{{$:/language/Buttons/Heading3/Caption}}", "description": "{{$:/language/Buttons/Heading3/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((heading-3))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"3\"\n/>\n" }, "$:/core/ui/EditorToolbar/heading-4": { "title": "$:/core/ui/EditorToolbar/heading-4", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/heading-4", "caption": "{{$:/language/Buttons/Heading4/Caption}}", "description": "{{$:/language/Buttons/Heading4/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((heading-4))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"4\"\n/>\n" }, "$:/core/ui/EditorToolbar/heading-5": { "title": "$:/core/ui/EditorToolbar/heading-5", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/heading-5", "caption": "{{$:/language/Buttons/Heading5/Caption}}", "description": "{{$:/language/Buttons/Heading5/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((heading-5))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"5\"\n/>\n" }, "$:/core/ui/EditorToolbar/heading-6": { "title": "$:/core/ui/EditorToolbar/heading-6", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/heading-6", "caption": "{{$:/language/Buttons/Heading6/Caption}}", "description": "{{$:/language/Buttons/Heading6/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((heading-6))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"!\"\n\tcount=\"6\"\n/>\n" }, "$:/core/ui/EditorToolbar/italic": { "title": "$:/core/ui/EditorToolbar/italic", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/italic", "caption": "{{$:/language/Buttons/Italic/Caption}}", "description": "{{$:/language/Buttons/Italic/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((italic))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"//\"\n\tsuffix=\"//\"\n/>\n" }, "$:/core/ui/EditorToolbar/line-width-dropdown": { "title": "$:/core/ui/EditorToolbar/line-width-dropdown", "text": "\\define lingo-base() $:/language/Buttons/LineWidth/\n\n\\define toolbar-line-width-inner()\n<$button tag=\"a\" tooltip=\"\"\"$(line-width)$\"\"\">\n\n<$action-setfield\n\t$tiddler=\"$:/config/BitmapEditor/LineWidth\"\n\t$value=\"$(line-width)$\"\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<div style=\"display: inline-block; margin: 4px calc(80px - $(line-width)$); background-color: #000; width: calc(100px + $(line-width)$ * 2); height: $(line-width)$; border-radius: 120px; vertical-align: middle;\"/>\n\n<span style=\"margin-left: 8px;\">\n\n<$text text=\"\"\"$(line-width)$\"\"\"/>\n\n<$reveal state=\"$:/config/BitmapEditor/LineWidth\" type=\"match\" text=\"\"\"$(line-width)$\"\"\" tag=\"span\">\n\n<$entity entity=\" \"/>\n\n<$entity entity=\"✓\"/>\n\n</$reveal>\n\n</span>\n\n</$button>\n\\end\n\n''<<lingo Hint>>''\n\n<$list filter={{$:/config/BitmapEditor/LineWidths}} variable=\"line-width\">\n\n<<toolbar-line-width-inner>>\n\n</$list>\n" }, "$:/core/ui/EditorToolbar/line-width": { "title": "$:/core/ui/EditorToolbar/line-width", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/line-width", "caption": "{{$:/language/Buttons/LineWidth/Caption}}", "description": "{{$:/language/Buttons/LineWidth/Hint}}", "condition": "[<targetTiddler>is[image]]", "dropdown": "$:/core/ui/EditorToolbar/line-width-dropdown", "text": "<$text text={{$:/config/BitmapEditor/LineWidth}}/>" }, "$:/core/ui/EditorToolbar/link-dropdown": { "title": "$:/core/ui/EditorToolbar/link-dropdown", "text": "\\define lingo-base() $:/language/Buttons/Link/\n\n\\define link-actions()\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"make-link\"\n\ttext={{$(linkTiddler)$}}\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<searchTiddler>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<linkTiddler>>\n/>\n\\end\n\n\\define external-link()\n<$button class=\"tc-btn-invisible\" style=\"width: auto; display: inline-block; background-colour: inherit;\">\n<$action-sendmessage $message=\"tm-edit-text-operation\" $param=\"make-link\" text={{$(searchTiddler)$}}\n/>\n{{$:/core/images/chevron-right}}\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<searchTiddler>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<linkTiddler>>\n/>\n</$button>\n\\end\n\n\n\\define body(config-title)\n''<<lingo Hint>>''\n\n<$vars searchTiddler=\"\"\"$config-title$/search\"\"\" linkTiddler=\"\"\"$config-title$/link\"\"\" linktext=\"\" >\n\n<$edit-text tiddler=<<searchTiddler>> type=\"search\" tag=\"input\" focus=\"true\" placeholder={{$:/language/Search/Search}} default=\"\"/>\n<$reveal tag=\"span\" state=<<searchTiddler>> type=\"nomatch\" text=\"\">\n<<external-link>>\n<$button class=\"tc-btn-invisible\" style=\"width: auto; display: inline-block; background-colour: inherit;\">\n<$action-setfield $tiddler=<<searchTiddler>> text=\"\" />\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n\n<$reveal tag=\"div\" state=<<searchTiddler>> type=\"nomatch\" text=\"\">\n\n<$linkcatcher actions=<<link-actions>> to=<<linkTiddler>>>\n\n{{$:/core/ui/SearchResults}}\n\n</$linkcatcher>\n\n</$reveal>\n\n</$vars>\n\n\\end\n\n<$macrocall $name=\"body\" config-title=<<qualify \"$:/state/Link/\">>/>" }, "$:/core/ui/EditorToolbar/link": { "title": "$:/core/ui/EditorToolbar/link", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/link", "caption": "{{$:/language/Buttons/Link/Caption}}", "description": "{{$:/language/Buttons/Link/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "button-classes": "tc-text-editor-toolbar-item-start-group", "shortcuts": "((link))", "dropdown": "$:/core/ui/EditorToolbar/link-dropdown", "text": "" }, "$:/core/ui/EditorToolbar/list-bullet": { "title": "$:/core/ui/EditorToolbar/list-bullet", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/list-bullet", "caption": "{{$:/language/Buttons/ListBullet/Caption}}", "description": "{{$:/language/Buttons/ListBullet/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((list-bullet))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"*\"\n\tcount=\"1\"\n/>\n" }, "$:/core/ui/EditorToolbar/list-number": { "title": "$:/core/ui/EditorToolbar/list-number", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/list-number", "caption": "{{$:/language/Buttons/ListNumber/Caption}}", "description": "{{$:/language/Buttons/ListNumber/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((list-number))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"prefix-lines\"\n\tcharacter=\"#\"\n\tcount=\"1\"\n/>\n" }, "$:/core/ui/EditorToolbar/mono-block": { "title": "$:/core/ui/EditorToolbar/mono-block", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/mono-block", "caption": "{{$:/language/Buttons/MonoBlock/Caption}}", "description": "{{$:/language/Buttons/MonoBlock/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "button-classes": "tc-text-editor-toolbar-item-start-group", "shortcuts": "((mono-block))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-lines\"\n\tprefix=\"\n```\"\n\tsuffix=\"```\"\n/>\n" }, "$:/core/ui/EditorToolbar/mono-line": { "title": "$:/core/ui/EditorToolbar/mono-line", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/mono-line", "caption": "{{$:/language/Buttons/MonoLine/Caption}}", "description": "{{$:/language/Buttons/MonoLine/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((mono-line))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"`\"\n\tsuffix=\"`\"\n/>\n" }, "$:/core/ui/EditorToolbar/more-dropdown": { "title": "$:/core/ui/EditorToolbar/more-dropdown", "text": "\\define config-title()\n$:/config/EditorToolbarButtons/Visibility/$(toolbarItem)$\n\\end\n\n\\define conditional-button()\n<$list filter={{$(toolbarItem)$!!condition}} variable=\"condition\">\n<$transclude tiddler=\"$:/core/ui/EditTemplate/body/toolbar/button\" mode=\"inline\"/> <$transclude tiddler=<<toolbarItem>> field=\"description\"/>\n</$list>\n\\end\n\n<div class=\"tc-text-editor-toolbar-more\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditorToolbar]!has[draft.of]] -[[$:/core/ui/EditorToolbar/more]]\">\n<$reveal type=\"match\" state=<<config-visibility-title>> text=\"hide\" tag=\"div\">\n<<conditional-button>>\n</$reveal>\n</$list>\n</div>\n" }, "$:/core/ui/EditorToolbar/more": { "title": "$:/core/ui/EditorToolbar/more", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/down-arrow", "caption": "{{$:/language/Buttons/More/Caption}}", "description": "{{$:/language/Buttons/More/Hint}}", "condition": "[<targetTiddler>]", "dropdown": "$:/core/ui/EditorToolbar/more-dropdown", "text": "" }, "$:/core/ui/EditorToolbar/opacity-dropdown": { "title": "$:/core/ui/EditorToolbar/opacity-dropdown", "text": "\\define lingo-base() $:/language/Buttons/Opacity/\n\n\\define toolbar-opacity-inner()\n<$button tag=\"a\" tooltip=\"\"\"$(opacity)$\"\"\">\n\n<$action-setfield\n\t$tiddler=\"$:/config/BitmapEditor/Opacity\"\n\t$value=\"$(opacity)$\"\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<div style=\"display: inline-block; vertical-align: middle; background-color: $(current-paint-colour)$; opacity: $(opacity)$; width: 1em; height: 1em; border-radius: 50%;\"/>\n\n<span style=\"margin-left: 8px;\">\n\n<$text text=\"\"\"$(opacity)$\"\"\"/>\n\n<$reveal state=\"$:/config/BitmapEditor/Opacity\" type=\"match\" text=\"\"\"$(opacity)$\"\"\" tag=\"span\">\n\n<$entity entity=\" \"/>\n\n<$entity entity=\"✓\"/>\n\n</$reveal>\n\n</span>\n\n</$button>\n\\end\n\n\\define toolbar-opacity()\n''<<lingo Hint>>''\n\n<$list filter={{$:/config/BitmapEditor/Opacities}} variable=\"opacity\">\n\n<<toolbar-opacity-inner>>\n\n</$list>\n\\end\n\n<$set name=\"current-paint-colour\" value={{$:/config/BitmapEditor/Colour}}>\n\n<$set name=\"current-opacity\" value={{$:/config/BitmapEditor/Opacity}}>\n\n<<toolbar-opacity>>\n\n</$set>\n\n</$set>\n" }, "$:/core/ui/EditorToolbar/opacity": { "title": "$:/core/ui/EditorToolbar/opacity", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/opacity", "caption": "{{$:/language/Buttons/Opacity/Caption}}", "description": "{{$:/language/Buttons/Opacity/Hint}}", "condition": "[<targetTiddler>is[image]]", "dropdown": "$:/core/ui/EditorToolbar/opacity-dropdown", "text": "<$text text={{$:/config/BitmapEditor/Opacity}}/>\n" }, "$:/core/ui/EditorToolbar/paint-dropdown": { "title": "$:/core/ui/EditorToolbar/paint-dropdown", "text": "''{{$:/language/Buttons/Paint/Hint}}''\n\n<$macrocall $name=\"colour-picker\" actions=\"\"\"\n\n<$action-setfield\n\t$tiddler=\"$:/config/BitmapEditor/Colour\"\n\t$value=<<colour-picker-value>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n\"\"\"/>\n" }, "$:/core/ui/EditorToolbar/paint": { "title": "$:/core/ui/EditorToolbar/paint", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/paint", "caption": "{{$:/language/Buttons/Paint/Caption}}", "description": "{{$:/language/Buttons/Paint/Hint}}", "condition": "[<targetTiddler>is[image]]", "dropdown": "$:/core/ui/EditorToolbar/paint-dropdown", "text": "\\define toolbar-paint()\n<div style=\"display: inline-block; vertical-align: middle; background-color: $(colour-picker-value)$; width: 1em; height: 1em; border-radius: 50%;\"/>\n\\end\n<$set name=\"colour-picker-value\" value={{$:/config/BitmapEditor/Colour}}>\n<<toolbar-paint>>\n</$set>\n" }, "$:/core/ui/EditorToolbar/picture-dropdown": { "title": "$:/core/ui/EditorToolbar/picture-dropdown", "text": "\\define replacement-text()\n[img[$(imageTitle)$]]\n\\end\n\n''{{$:/language/Buttons/Picture/Hint}}''\n\n<$macrocall $name=\"image-picker\" actions=\"\"\"\n\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"replace-selection\"\n\ttext=<<replacement-text>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n\"\"\"/>\n" }, "$:/core/ui/EditorToolbar/picture": { "title": "$:/core/ui/EditorToolbar/picture", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/picture", "caption": "{{$:/language/Buttons/Picture/Caption}}", "description": "{{$:/language/Buttons/Picture/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((picture))", "dropdown": "$:/core/ui/EditorToolbar/picture-dropdown", "text": "" }, "$:/core/ui/EditorToolbar/preview-type-dropdown": { "title": "$:/core/ui/EditorToolbar/preview-type-dropdown", "text": "\\define preview-type-button()\n<$button tag=\"a\">\n\n<$action-setfield $tiddler=\"$:/state/editpreviewtype\" $value=\"$(previewType)$\"/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<$transclude tiddler=<<previewType>> field=\"caption\" mode=\"inline\">\n\n<$view tiddler=<<previewType>> field=\"title\" mode=\"inline\"/>\n\n</$transclude> \n\n<$reveal tag=\"span\" state=\"$:/state/editpreviewtype\" type=\"match\" text=<<previewType>> default=\"$:/core/ui/EditTemplate/body/preview/output\">\n\n<$entity entity=\" \"/>\n\n<$entity entity=\"✓\"/>\n\n</$reveal>\n\n</$button>\n\\end\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/EditPreview]!has[draft.of]]\" variable=\"previewType\">\n\n<<preview-type-button>>\n\n</$list>\n" }, "$:/core/ui/EditorToolbar/preview-type": { "title": "$:/core/ui/EditorToolbar/preview-type", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/chevron-down", "caption": "{{$:/language/Buttons/PreviewType/Caption}}", "description": "{{$:/language/Buttons/PreviewType/Hint}}", "condition": "[all[shadows+tiddlers]tag[$:/tags/EditPreview]!has[draft.of]butfirst[]limit[1]]", "button-classes": "tc-text-editor-toolbar-item-adjunct", "dropdown": "$:/core/ui/EditorToolbar/preview-type-dropdown" }, "$:/core/ui/EditorToolbar/preview": { "title": "$:/core/ui/EditorToolbar/preview", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/preview-open", "custom-icon": "yes", "caption": "{{$:/language/Buttons/Preview/Caption}}", "description": "{{$:/language/Buttons/Preview/Hint}}", "condition": "[<targetTiddler>]", "button-classes": "tc-text-editor-toolbar-item-start-group", "shortcuts": "((preview))", "text": "<$reveal state=\"$:/state/showeditpreview\" type=\"match\" text=\"yes\" tag=\"span\">\n{{$:/core/images/preview-open}}\n<$action-setfield $tiddler=\"$:/state/showeditpreview\" $value=\"no\"/>\n</$reveal>\n<$reveal state=\"$:/state/showeditpreview\" type=\"nomatch\" text=\"yes\" tag=\"span\">\n{{$:/core/images/preview-closed}}\n<$action-setfield $tiddler=\"$:/state/showeditpreview\" $value=\"yes\"/>\n</$reveal>\n" }, "$:/core/ui/EditorToolbar/quote": { "title": "$:/core/ui/EditorToolbar/quote", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/quote", "caption": "{{$:/language/Buttons/Quote/Caption}}", "description": "{{$:/language/Buttons/Quote/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((quote))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-lines\"\n\tprefix=\"\n<<<\"\n\tsuffix=\"<<<\"\n/>\n" }, "$:/core/ui/EditorToolbar/size-dropdown": { "title": "$:/core/ui/EditorToolbar/size-dropdown", "text": "\\define lingo-base() $:/language/Buttons/Size/\n\n\\define toolbar-button-size-preset(config-title)\n<$set name=\"width\" filter=\"$(sizePair)$ +[first[]]\">\n\n<$set name=\"height\" filter=\"$(sizePair)$ +[last[]]\">\n\n<$button tag=\"a\">\n\n<$action-setfield\n\t$tiddler=\"\"\"$config-title$/new-width\"\"\"\n\t$value=<<width>>\n/>\n\n<$action-setfield\n\t$tiddler=\"\"\"$config-title$/new-height\"\"\"\n\t$value=<<height>>\n/>\n\n<$action-deletetiddler\n\t$tiddler=\"\"\"$config-title$/presets-popup\"\"\"\n/>\n\n<$text text=<<width>>/> × <$text text=<<height>>/>\n\n</$button>\n\n</$set>\n\n</$set>\n\\end\n\n\\define toolbar-button-size(config-title)\n''{{$:/language/Buttons/Size/Hint}}''\n\n<<lingo Caption/Width>> <$edit-text tag=\"input\" tiddler=\"\"\"$config-title$/new-width\"\"\" default=<<tv-bitmap-editor-width>> focus=\"true\" size=\"8\"/> <<lingo Caption/Height>> <$edit-text tag=\"input\" tiddler=\"\"\"$config-title$/new-height\"\"\" default=<<tv-bitmap-editor-height>> size=\"8\"/> <$button popup=\"\"\"$config-title$/presets-popup\"\"\" class=\"tc-btn-invisible tc-popup-keep\" style=\"width: auto; display: inline-block; background-colour: inherit;\" selectedClass=\"tc-selected\">\n{{$:/core/images/down-arrow}}\n</$button>\n\n<$reveal tag=\"span\" state=\"\"\"$config-title$/presets-popup\"\"\" type=\"popup\" position=\"belowleft\" animate=\"yes\">\n\n<div class=\"tc-drop-down tc-popup-keep\">\n\n<$list filter={{$:/config/BitmapEditor/ImageSizes}} variable=\"sizePair\">\n\n<$macrocall $name=\"toolbar-button-size-preset\" config-title=\"$config-title$\"/>\n\n</$list>\n\n</div>\n\n</$reveal>\n\n<$button>\n<$action-sendmessage\n\t$message=\"tm-edit-bitmap-operation\"\n\t$param=\"resize\"\n\twidth={{$config-title$/new-width}}\n\theight={{$config-title$/new-height}}\n/>\n<$action-deletetiddler\n\t$tiddler=\"\"\"$config-title$/new-width\"\"\"\n/>\n<$action-deletetiddler\n\t$tiddler=\"\"\"$config-title$/new-height\"\"\"\n/>\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n<<lingo Caption/Resize>>\n</$button>\n\\end\n\n<$macrocall $name=\"toolbar-button-size\" config-title=<<qualify \"$:/state/Size/\">>/>\n" }, "$:/core/ui/EditorToolbar/size": { "title": "$:/core/ui/EditorToolbar/size", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/size", "caption": "{{$:/language/Buttons/Size/Caption}}", "description": "{{$:/language/Buttons/Size/Hint}}", "condition": "[<targetTiddler>is[image]]", "dropdown": "$:/core/ui/EditorToolbar/size-dropdown", "text": "" }, "$:/core/ui/EditorToolbar/stamp-dropdown": { "title": "$:/core/ui/EditorToolbar/stamp-dropdown", "text": "\\define toolbar-button-stamp-inner()\n<$button tag=\"a\">\n\n<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"replace-selection\"\n\ttext={{$(snippetTitle)$}}\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<$view tiddler=<<snippetTitle>> field=\"caption\" mode=\"inline\">\n\n<$view tiddler=<<snippetTitle>> field=\"title\" mode=\"inline\"/>\n\n</$view>\n\n</$button>\n\\end\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TextEditor/Snippet]!has[draft.of]sort[caption]]\" variable=\"snippetTitle\">\n\n<<toolbar-button-stamp-inner>>\n\n</$list>\n\n----\n\n<$button tag=\"a\">\n\n<$action-sendmessage\n\t$message=\"tm-new-tiddler\"\n\ttags=\"$:/tags/TextEditor/Snippet\"\n\tcaption={{$:/language/Buttons/Stamp/New/Title}}\n\ttext={{$:/language/Buttons/Stamp/New/Text}}\n/>\n\n<$action-deletetiddler\n\t$tiddler=<<dropdown-state>>\n/>\n\n<em>\n\n<$text text={{$:/language/Buttons/Stamp/Caption/New}}/>\n\n</em>\n\n</$button>\n" }, "$:/core/ui/EditorToolbar/stamp": { "title": "$:/core/ui/EditorToolbar/stamp", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/stamp", "caption": "{{$:/language/Buttons/Stamp/Caption}}", "description": "{{$:/language/Buttons/Stamp/Hint}}", "condition": "[<targetTiddler>!is[image]]", "shortcuts": "((stamp))", "dropdown": "$:/core/ui/EditorToolbar/stamp-dropdown", "text": "" }, "$:/core/ui/EditorToolbar/strikethrough": { "title": "$:/core/ui/EditorToolbar/strikethrough", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/strikethrough", "caption": "{{$:/language/Buttons/Strikethrough/Caption}}", "description": "{{$:/language/Buttons/Strikethrough/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((strikethrough))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"~~\"\n\tsuffix=\"~~\"\n/>\n" }, "$:/core/ui/EditorToolbar/subscript": { "title": "$:/core/ui/EditorToolbar/subscript", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/subscript", "caption": "{{$:/language/Buttons/Subscript/Caption}}", "description": "{{$:/language/Buttons/Subscript/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((subscript))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\",,\"\n\tsuffix=\",,\"\n/>\n" }, "$:/core/ui/EditorToolbar/superscript": { "title": "$:/core/ui/EditorToolbar/superscript", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/superscript", "caption": "{{$:/language/Buttons/Superscript/Caption}}", "description": "{{$:/language/Buttons/Superscript/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((superscript))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"^^\"\n\tsuffix=\"^^\"\n/>\n" }, "$:/core/ui/EditorToolbar/underline": { "title": "$:/core/ui/EditorToolbar/underline", "tags": "$:/tags/EditorToolbar", "icon": "$:/core/images/underline", "caption": "{{$:/language/Buttons/Underline/Caption}}", "description": "{{$:/language/Buttons/Underline/Hint}}", "condition": "[<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]", "shortcuts": "((underline))", "text": "<$action-sendmessage\n\t$message=\"tm-edit-text-operation\"\n\t$param=\"wrap-selection\"\n\tprefix=\"__\"\n\tsuffix=\"__\"\n/>\n" }, "$:/core/Filters/AllTags": { "title": "$:/core/Filters/AllTags", "tags": "$:/tags/Filter", "filter": "[tags[]!is[system]sort[title]]", "description": "{{$:/language/Filters/AllTags}}", "text": "" }, "$:/core/Filters/AllTiddlers": { "title": "$:/core/Filters/AllTiddlers", "tags": "$:/tags/Filter", "filter": "[!is[system]sort[title]]", "description": "{{$:/language/Filters/AllTiddlers}}", "text": "" }, "$:/core/Filters/Drafts": { "title": "$:/core/Filters/Drafts", "tags": "$:/tags/Filter", "filter": "[has[draft.of]sort[title]]", "description": "{{$:/language/Filters/Drafts}}", "text": "" }, "$:/core/Filters/Missing": { "title": "$:/core/Filters/Missing", "tags": "$:/tags/Filter", "filter": "[all[missing]sort[title]]", "description": "{{$:/language/Filters/Missing}}", "text": "" }, "$:/core/Filters/Orphans": { "title": "$:/core/Filters/Orphans", "tags": "$:/tags/Filter", "filter": "[all[orphans]sort[title]]", "description": "{{$:/language/Filters/Orphans}}", "text": "" }, "$:/core/Filters/OverriddenShadowTiddlers": { "title": "$:/core/Filters/OverriddenShadowTiddlers", "tags": "$:/tags/Filter", "filter": "[is[shadow]]", "description": "{{$:/language/Filters/OverriddenShadowTiddlers}}", "text": "" }, "$:/core/Filters/RecentSystemTiddlers": { "title": "$:/core/Filters/RecentSystemTiddlers", "tags": "$:/tags/Filter", "filter": "[has[modified]!sort[modified]limit[50]]", "description": "{{$:/language/Filters/RecentSystemTiddlers}}", "text": "" }, "$:/core/Filters/RecentTiddlers": { "title": "$:/core/Filters/RecentTiddlers", "tags": "$:/tags/Filter", "filter": "[!is[system]has[modified]!sort[modified]limit[50]]", "description": "{{$:/language/Filters/RecentTiddlers}}", "text": "" }, "$:/core/Filters/ShadowTiddlers": { "title": "$:/core/Filters/ShadowTiddlers", "tags": "$:/tags/Filter", "filter": "[all[shadows]sort[title]]", "description": "{{$:/language/Filters/ShadowTiddlers}}", "text": "" }, "$:/core/Filters/StoryList": { "title": "$:/core/Filters/StoryList", "tags": "$:/tags/Filter", "filter": "[list[$:/StoryList]] -$:/AdvancedSearch", "description": "{{$:/language/Filters/StoryList}}", "text": "" }, "$:/core/Filters/SystemTags": { "title": "$:/core/Filters/SystemTags", "tags": "$:/tags/Filter", "filter": "[all[shadows+tiddlers]tags[]is[system]sort[title]]", "description": "{{$:/language/Filters/SystemTags}}", "text": "" }, "$:/core/Filters/SystemTiddlers": { "title": "$:/core/Filters/SystemTiddlers", "tags": "$:/tags/Filter", "filter": "[is[system]sort[title]]", "description": "{{$:/language/Filters/SystemTiddlers}}", "text": "" }, "$:/core/Filters/TypedTiddlers": { "title": "$:/core/Filters/TypedTiddlers", "tags": "$:/tags/Filter", "filter": "[!is[system]has[type]each[type]sort[type]] -[type[text/vnd.tiddlywiki]]", "description": "{{$:/language/Filters/TypedTiddlers}}", "text": "" }, "$:/core/ui/ImportListing": { "title": "$:/core/ui/ImportListing", "text": "\\define lingo-base() $:/language/Import/\n\n\\define messageField()\nmessage-$(payloadTiddler)$\n\\end\n\n\\define selectionField()\nselection-$(payloadTiddler)$\n\\end\n\n\\define previewPopupState()\n$(currentTiddler)$!!popup-$(payloadTiddler)$\n\\end\n\n\\define select-all-actions()\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" variable=\"payloadTiddler\">\n<$action-setfield $field={{{ [<payloadTiddler>addprefix[selection-]] }}} $value={{$:/state/import/select-all}}/>\n</$list>\n\\end\n\n<table>\n<tbody>\n<tr>\n<th>\n<$checkbox tiddler=\"$:/state/import/select-all\" field=\"text\" checked=\"checked\" unchecked=\"unchecked\" default=\"checked\" actions=<<select-all-actions>>>\n<<lingo Listing/Select/Caption>>\n</$checkbox>\n</th>\n<th>\n<<lingo Listing/Title/Caption>>\n</th>\n<th>\n<<lingo Listing/Status/Caption>>\n</th>\n</tr>\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" variable=\"payloadTiddler\">\n<tr>\n<td>\n<$checkbox field=<<selectionField>> checked=\"checked\" unchecked=\"unchecked\" default=\"checked\"/>\n</td>\n<td>\n<$reveal type=\"nomatch\" state=<<previewPopupState>> text=\"yes\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<previewPopupState>> setTo=\"yes\">\n{{$:/core/images/right-arrow}} <$text text=<<payloadTiddler>>/>\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=<<previewPopupState>> text=\"yes\">\n<$button class=\"tc-btn-invisible tc-btn-dropdown\" set=<<previewPopupState>> setTo=\"no\">\n{{$:/core/images/down-arrow}} <$text text=<<payloadTiddler>>/>\n</$button>\n</$reveal>\n</td>\n<td>\n<$view field=<<messageField>>/>\n</td>\n</tr>\n<tr>\n<td colspan=\"3\">\n<$reveal type=\"match\" text=\"yes\" state=<<previewPopupState>>>\n<$transclude subtiddler=<<payloadTiddler>> mode=\"block\"/>\n</$reveal>\n</td>\n</tr>\n</$list>\n</tbody>\n</table>\n" }, "$:/core/ui/ListItemTemplate": { "title": "$:/core/ui/ListItemTemplate", "text": "<div class=\"tc-menu-list-item\">\n<$link to={{!!title}}>\n<$view field=\"title\"/>\n</$link>\n</div>" }, "$:/Manager/ItemMain/Fields": { "title": "$:/Manager/ItemMain/Fields", "tags": "$:/tags/Manager/ItemMain", "caption": "{{$:/language/Manager/Item/Fields}}", "text": "<table>\n<tbody>\n<$list filter=\"[all[current]fields[]sort[title]] -text\" template=\"$:/core/ui/TiddlerFieldTemplate\" variable=\"listItem\"/>\n</tbody>\n</table>\n" }, "$:/Manager/ItemMain/RawText": { "title": "$:/Manager/ItemMain/RawText", "tags": "$:/tags/Manager/ItemMain", "caption": "{{$:/language/Manager/Item/RawText}}", "text": "<pre><code><$view/></code></pre>\n" }, "$:/Manager/ItemMain/WikifiedText": { "title": "$:/Manager/ItemMain/WikifiedText", "tags": "$:/tags/Manager/ItemMain", "caption": "{{$:/language/Manager/Item/WikifiedText}}", "text": "<$transclude mode=\"block\"/>\n" }, "$:/Manager/ItemSidebar/Colour": { "title": "$:/Manager/ItemSidebar/Colour", "tags": "$:/tags/Manager/ItemSidebar", "caption": "{{$:/language/Manager/Item/Colour}}", "text": "\\define swatch-styles()\nheight: 1em;\nbackground-color: $(colour)$\n\\end\n\n<$vars colour={{!!color}}>\n<p style=<<swatch-styles>>/>\n</$vars>\n<p>\n<$edit-text field=\"color\" tag=\"input\" type=\"color\"/> / <$edit-text field=\"color\" tag=\"input\" type=\"text\" size=\"9\"/>\n</p>\n" }, "$:/Manager/ItemSidebar/Icon": { "title": "$:/Manager/ItemSidebar/Icon", "tags": "$:/tags/Manager/ItemSidebar", "caption": "{{$:/language/Manager/Item/Icon}}", "text": "<p>\n<div class=\"tc-manager-icon-editor\">\n<$button popup=<<qualify \"$:/state/popup/image-picker\">> class=\"tc-btn-invisible\">\n<$transclude tiddler={{!!icon}}>\n{{$:/language/Manager/Item/Icon/None}}\n</$transclude>\n</$button>\n<div class=\"tc-block-dropdown-wrapper\" style=\"position: static;\">\n<$reveal state=<<qualify \"$:/state/popup/image-picker\">> type=\"nomatch\" text=\"\" default=\"\" tag=\"div\" class=\"tc-popup\">\n<div class=\"tc-block-dropdown tc-popup-keep\" style=\"width: 80%; left: 10%; right: 10%; padding: 0.5em;\">\n<$macrocall $name=\"image-picker-include-tagged-images\" actions=\"\"\"\n<$action-setfield $field=\"icon\" $value=<<imageTitle>>/>\n<$action-deletetiddler $tiddler=<<qualify \"$:/state/popup/image-picker\">>/>\n\"\"\"/>\n</div>\n</$reveal>\n</div>\n</div>\n</p>\n" }, "$:/Manager/ItemSidebar/Tags": { "title": "$:/Manager/ItemSidebar/Tags", "tags": "$:/tags/Manager/ItemSidebar", "caption": "{{$:/language/Manager/Item/Tags}}", "text": "\\define tag-checkbox-actions()\n<$action-listops\n\t$tiddler=\"$:/config/Manager/RecentTags\"\n\t$subfilter=\"[<tag>] [list[$:/config/Manager/RecentTags]] +[limit[12]]\"\n/>\n\\end\n\n\\define tag-picker-actions()\n<<tag-checkbox-actions>>\n<$action-listops\n\t$tiddler=<<currentTiddler>>\n\t$field=\"tags\"\n\t$subfilter=\"[<tag>] [all[current]tags[]]\"\n/>\n\\end\n\n<p>\n<$list filter=\"[is[current]tags[]] [list[$:/config/Manager/RecentTags]] +[sort[title]] \" variable=\"tag\">\n<div>\n<$checkbox tiddler=<<currentTiddler>> tag=<<tag>> actions=<<tag-checkbox-actions>>>\n<$macrocall $name=\"tag-pill\" tag=<<tag>>/>\n</$checkbox>\n</div>\n</$list>\n</p>\n<p>\n<$macrocall $name=\"tag-picker\" actions=<<tag-picker-actions>>/>\n</p>\n" }, "$:/Manager/ItemSidebar/Tools": { "title": "$:/Manager/ItemSidebar/Tools", "tags": "$:/tags/Manager/ItemSidebar", "caption": "{{$:/language/Manager/Item/Tools}}", "text": "<p>\n<$button to=<<currentTiddler>>>{{$:/core/images/link}} open</$button>\n</p>\n<p>\n<$button message=\"tm-edit-tiddler\" param=<<currentTiddler>>>{{$:/core/images/edit-button}} edit</$button>\n</p>\n" }, "$:/Manager": { "title": "$:/Manager", "icon": "$:/core/images/list", "color": "#bbb", "text": "\\define lingo-base() $:/language/Manager/\n\n\\define list-item-content-item()\n<div class=\"tc-manager-list-item-content-item\">\n\t<$vars state-title=\"\"\"$:/state/popup/manager/item/$(listItem)$\"\"\">\n\t\t<$reveal state=<<state-title>> type=\"match\" text=\"show\" default=\"show\" tag=\"div\">\n\t\t\t<$button set=<<state-title>> setTo=\"hide\" class=\"tc-btn-invisible tc-manager-list-item-content-item-heading\">\n\t\t\t\t{{$:/core/images/down-arrow}} <$transclude tiddler=<<listItem>> field=\"caption\"/>\n\t\t\t</$button>\n\t\t</$reveal>\n\t\t<$reveal state=<<state-title>> type=\"nomatch\" text=\"show\" default=\"show\" tag=\"div\">\n\t\t\t<$button set=<<state-title>> setTo=\"show\" class=\"tc-btn-invisible tc-manager-list-item-content-item-heading\">\n\t\t\t\t{{$:/core/images/right-arrow}} <$transclude tiddler=<<listItem>> field=\"caption\"/>\n\t\t\t</$button>\n\t\t</$reveal>\n\t\t<$reveal state=<<state-title>> type=\"match\" text=\"show\" default=\"show\" tag=\"div\" class=\"tc-manager-list-item-content-item-body\">\n\t\t\t<$transclude tiddler=<<listItem>>/>\n\t\t</$reveal>\n\t</$vars>\n</div>\n\\end\n\n<div class=\"tc-manager-wrapper\">\n\t<div class=\"tc-manager-controls\">\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/Show/Prompt>> <$select tiddler=\"$:/config/Manager/Show\" default=\"tiddlers\">\n\t\t\t\t<option value=\"tiddlers\"><<lingo Controls/Show/Option/Tiddlers>></option>\n\t\t\t\t<option value=\"tags\"><<lingo Controls/Show/Option/Tags>></option>\n\t\t\t</$select>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/Search/Prompt>> <$edit-text tiddler=\"$:/config/Manager/Filter\" tag=\"input\" default=\"\" placeholder={{$:/language/Manager/Controls/Search/Placeholder}}/>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/FilterByTag/Prompt>> <$select tiddler=\"$:/config/Manager/Tag\" default=\"\">\n\t\t\t\t<option value=\"\"><<lingo Controls/FilterByTag/None>></option>\n\t\t\t\t<$list filter=\"[!is{$:/config/Manager/System}tags[]!is[system]sort[title]]\" variable=\"tag\">\n\t\t\t\t\t<option value=<<tag>>><$text text=<<tag>>/></option>\n\t\t\t\t</$list>\n\t\t\t</$select>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<<lingo Controls/Sort/Prompt>> <$select tiddler=\"$:/config/Manager/Sort\" default=\"title\">\n\t\t\t\t<optgroup label=\"Common\">\n\t\t\t\t\t<$list filter=\"title modified modifier created creator created\" variable=\"field\">\n\t\t\t\t\t\t<option value=<<field>>><$text text=<<field>>/></option>\n\t\t\t\t\t</$list>\n\t\t\t\t</optgroup>\n\t\t\t\t<optgroup label=\"All\">\n\t\t\t\t\t<$list filter=\"[all{$:/config/Manager/Show}!is{$:/config/Manager/System}fields[]sort[title]] -title -modified -modifier -created -creator -created\" variable=\"field\">\n\t\t\t\t\t\t<option value=<<field>>><$text text=<<field>>/></option>\n\t\t\t\t\t</$list>\n\t\t\t\t</optgroup>\n\t\t\t</$select>\n\t\t\t<$checkbox tiddler=\"$:/config/Manager/Order\" field=\"text\" checked=\"reverse\" unchecked=\"forward\" default=\"forward\">\n\t\t\t\t<<lingo Controls/Order/Prompt>>\n\t\t\t</$checkbox>\n\t\t</div>\n\t\t<div class=\"tc-manager-control\">\n\t\t\t<$checkbox tiddler=\"$:/config/Manager/System\" field=\"text\" checked=\"\" unchecked=\"system\" default=\"system\">\n\t\t\t\t{{$:/language/SystemTiddlers/Include/Prompt}}\n\t\t\t</$checkbox>\n\t\t</div>\n\t</div>\n\t<div class=\"tc-manager-list\">\n\t\t<$list filter=\"[all{$:/config/Manager/Show}!is{$:/config/Manager/System}search{$:/config/Manager/Filter}tag:strict{$:/config/Manager/Tag}sort{$:/config/Manager/Sort}order{$:/config/Manager/Order}]\">\n\t\t\t<$vars transclusion=<<currentTiddler>>>\n\t\t\t\t<div style=\"tc-manager-list-item\">\n\t\t\t\t\t<$button popup=<<qualify \"$:/state/manager/popup\">> class=\"tc-btn-invisible tc-manager-list-item-heading\" selectedClass=\"tc-manager-list-item-heading-selected\">\n\t\t\t\t\t\t<$text text=<<currentTiddler>>/>\n\t\t\t\t\t</$button>\n\t\t\t\t\t<$reveal state=<<qualify \"$:/state/manager/popup\">> type=\"nomatch\" text=\"\" default=\"\" tag=\"div\" class=\"tc-manager-list-item-content tc-popup-handle\">\n\t\t\t\t\t\t<div class=\"tc-manager-list-item-content-tiddler\">\n\t\t\t\t\t\t\t<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Manager/ItemMain]!has[draft.of]]\" variable=\"listItem\">\n\t\t\t\t\t\t\t\t<<list-item-content-item>>\n\t\t\t\t\t\t\t</$list>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"tc-manager-list-item-content-sidebar\">\n\t\t\t\t\t\t\t<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Manager/ItemSidebar]!has[draft.of]]\" variable=\"listItem\">\n\t\t\t\t\t\t\t\t<<list-item-content-item>>\n\t\t\t\t\t\t\t</$list>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</$reveal>\n\t\t\t\t</div>\n\t\t\t</$vars>\n\t\t</$list>\n\t</div>\n</div>\n" }, "$:/core/ui/MissingTemplate": { "title": "$:/core/ui/MissingTemplate", "text": "<div class=\"tc-tiddler-missing\">\n<$button popup=<<qualify \"$:/state/popup/missing\">> class=\"tc-btn-invisible tc-missing-tiddler-label\">\n<$view field=\"title\" format=\"text\" />\n</$button>\n<$reveal state=<<qualify \"$:/state/popup/missing\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n<$transclude tiddler=\"$:/core/ui/ListItemTemplate\"/>\n<hr>\n<$list filter=\"[all[current]backlinks[]sort[title]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n</div>\n</$reveal>\n</div>\n" }, "$:/core/ui/MoreSideBar/All": { "title": "$:/core/ui/MoreSideBar/All", "tags": "$:/tags/MoreSideBar", "caption": "{{$:/language/SideBar/All/Caption}}", "text": "<$list filter={{$:/core/Filters/AllTiddlers!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n" }, "$:/core/ui/MoreSideBar/Drafts": { "title": "$:/core/ui/MoreSideBar/Drafts", "tags": "$:/tags/MoreSideBar", "caption": "{{$:/language/SideBar/Drafts/Caption}}", "text": "<$list filter={{$:/core/Filters/Drafts!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n" }, "$:/core/ui/MoreSideBar/Missing": { "title": "$:/core/ui/MoreSideBar/Missing", "tags": "$:/tags/MoreSideBar", "caption": "{{$:/language/SideBar/Missing/Caption}}", "text": "<$list filter={{$:/core/Filters/Missing!!filter}} template=\"$:/core/ui/MissingTemplate\"/>\n" }, "$:/core/ui/MoreSideBar/Orphans": { "title": "$:/core/ui/MoreSideBar/Orphans", "tags": "$:/tags/MoreSideBar", "caption": "{{$:/language/SideBar/Orphans/Caption}}", "text": "<$list filter={{$:/core/Filters/Orphans!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n" }, "$:/core/ui/MoreSideBar/Plugins": { "title": "$:/core/ui/MoreSideBar/Plugins", "tags": "$:/tags/MoreSideBar", "caption": "{{$:/language/ControlPanel/Plugins/Caption}}", "text": "\n{{$:/language/ControlPanel/Plugins/Installed/Hint}}\n\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/MoreSideBar/Plugins]!has[draft.of]]\" \"$:/core/ui/MoreSideBar/Plugins/Plugins\">>\n" }, "$:/core/ui/MoreSideBar/Recent": { "title": "$:/core/ui/MoreSideBar/Recent", "tags": "$:/tags/MoreSideBar", "caption": "{{$:/language/SideBar/Recent/Caption}}", "text": "<$macrocall $name=\"timeline\" format={{$:/language/RecentChanges/DateFormat}}/>\n" }, "$:/core/ui/MoreSideBar/Shadows": { "title": "$:/core/ui/MoreSideBar/Shadows", "tags": "$:/tags/MoreSideBar", "caption": "{{$:/language/SideBar/Shadows/Caption}}", "text": "<$list filter={{$:/core/Filters/ShadowTiddlers!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n" }, "$:/core/ui/MoreSideBar/System": { "title": "$:/core/ui/MoreSideBar/System", "tags": "$:/tags/MoreSideBar", "caption": "{{$:/language/SideBar/System/Caption}}", "text": "<$list filter={{$:/core/Filters/SystemTiddlers!!filter}} template=\"$:/core/ui/ListItemTemplate\"/>\n" }, "$:/core/ui/MoreSideBar/Tags": { "title": "$:/core/ui/MoreSideBar/Tags", "tags": "$:/tags/MoreSideBar", "caption": "{{$:/language/SideBar/Tags/Caption}}", "text": "<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n{{$:/core/ui/Buttons/tag-manager}}\n\n</$set>\n\n</$set>\n\n</$set>\n\n<$list filter={{$:/core/Filters/AllTags!!filter}}>\n\n<$transclude tiddler=\"$:/core/ui/TagTemplate\"/>\n\n</$list>\n\n<hr class=\"tc-untagged-separator\">\n\n{{$:/core/ui/UntaggedTemplate}}\n" }, "$:/core/ui/MoreSideBar/Types": { "title": "$:/core/ui/MoreSideBar/Types", "tags": "$:/tags/MoreSideBar", "caption": "{{$:/language/SideBar/Types/Caption}}", "text": "<$list filter={{$:/core/Filters/TypedTiddlers!!filter}}>\n<div class=\"tc-menu-list-item\">\n<$view field=\"type\"/>\n<$list filter=\"[type{!!type}!is[system]sort[title]]\">\n<div class=\"tc-menu-list-subitem\">\n<$link to={{!!title}}><$view field=\"title\"/></$link>\n</div>\n</$list>\n</div>\n</$list>\n" }, "$:/core/ui/MoreSideBar/Plugins/Languages": { "title": "$:/core/ui/MoreSideBar/Plugins/Languages", "tags": "$:/tags/MoreSideBar/Plugins", "caption": "{{$:/language/ControlPanel/Plugins/Languages/Caption}}", "text": "<$list filter=\"[!has[draft.of]plugin-type[language]sort[description]]\" template=\"$:/core/ui/PluginListItemTemplate\" emptyMessage={{$:/language/ControlPanel/Plugins/Empty/Hint}}/>\n" }, "$:/core/ui/MoreSideBar/Plugins/Plugins": { "title": "$:/core/ui/MoreSideBar/Plugins/Plugins", "tags": "$:/tags/MoreSideBar/Plugins", "caption": "{{$:/language/ControlPanel/Plugins/Plugins/Caption}}", "text": "<$list filter=\"[!has[draft.of]plugin-type[plugin]sort[description]]\" template=\"$:/core/ui/PluginListItemTemplate\" emptyMessage={{$:/language/ControlPanel/Plugins/Empty/Hint}}>>/>\n" }, "$:/core/ui/MoreSideBar/Plugins/Theme": { "title": "$:/core/ui/MoreSideBar/Plugins/Theme", "tags": "$:/tags/MoreSideBar/Plugins", "caption": "{{$:/language/ControlPanel/Plugins/Themes/Caption}}", "text": "<$list filter=\"[!has[draft.of]plugin-type[theme]sort[description]]\" template=\"$:/core/ui/PluginListItemTemplate\" emptyMessage={{$:/language/ControlPanel/Plugins/Empty/Hint}}/>\n" }, "$:/core/ui/Buttons/advanced-search": { "title": "$:/core/ui/Buttons/advanced-search", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/advanced-search-button}} {{$:/language/Buttons/AdvancedSearch/Caption}}", "description": "{{$:/language/Buttons/AdvancedSearch/Hint}}", "text": "\\define control-panel-button(class)\n<$button to=\"$:/AdvancedSearch\" tooltip={{$:/language/Buttons/AdvancedSearch/Hint}} aria-label={{$:/language/Buttons/AdvancedSearch/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/advanced-search-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/AdvancedSearch/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/AdvancedSearch]]\" emptyMessage=<<control-panel-button>>>\n<<control-panel-button \"tc-selected\">>\n</$list>\n" }, "$:/core/ui/Buttons/close-all": { "title": "$:/core/ui/Buttons/close-all", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/close-all-button}} {{$:/language/Buttons/CloseAll/Caption}}", "description": "{{$:/language/Buttons/CloseAll/Hint}}", "text": "<$button message=\"tm-close-all-tiddlers\" tooltip={{$:/language/Buttons/CloseAll/Hint}} aria-label={{$:/language/Buttons/CloseAll/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/close-all-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/CloseAll/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/control-panel": { "title": "$:/core/ui/Buttons/control-panel", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/options-button}} {{$:/language/Buttons/ControlPanel/Caption}}", "description": "{{$:/language/Buttons/ControlPanel/Hint}}", "text": "\\define control-panel-button(class)\n<$button to=\"$:/ControlPanel\" tooltip={{$:/language/Buttons/ControlPanel/Hint}} aria-label={{$:/language/Buttons/ControlPanel/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/options-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/ControlPanel/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/ControlPanel]]\" emptyMessage=<<control-panel-button>>>\n<<control-panel-button \"tc-selected\">>\n</$list>\n" }, "$:/core/ui/Buttons/encryption": { "title": "$:/core/ui/Buttons/encryption", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/locked-padlock}} {{$:/language/Buttons/Encryption/Caption}}", "description": "{{$:/language/Buttons/Encryption/Hint}}", "text": "<$reveal type=\"match\" state=\"$:/isEncrypted\" text=\"yes\">\n<$button message=\"tm-clear-password\" tooltip={{$:/language/Buttons/Encryption/ClearPassword/Hint}} aria-label={{$:/language/Buttons/Encryption/ClearPassword/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/locked-padlock}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Encryption/ClearPassword/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>\n<$reveal type=\"nomatch\" state=\"$:/isEncrypted\" text=\"yes\">\n<$button message=\"tm-set-password\" tooltip={{$:/language/Buttons/Encryption/SetPassword/Hint}} aria-label={{$:/language/Buttons/Encryption/SetPassword/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/unlocked-padlock}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Encryption/SetPassword/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>" }, "$:/core/ui/Buttons/export-page": { "title": "$:/core/ui/Buttons/export-page", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/export-button}} {{$:/language/Buttons/ExportPage/Caption}}", "description": "{{$:/language/Buttons/ExportPage/Hint}}", "text": "<$macrocall $name=\"exportButton\" exportFilter=\"[!is[system]sort[title]]\" lingoBase=\"$:/language/Buttons/ExportPage/\"/>" }, "$:/core/ui/Buttons/fold-all": { "title": "$:/core/ui/Buttons/fold-all", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/fold-all-button}} {{$:/language/Buttons/FoldAll/Caption}}", "description": "{{$:/language/Buttons/FoldAll/Hint}}", "text": "<$button tooltip={{$:/language/Buttons/FoldAll/Hint}} aria-label={{$:/language/Buttons/FoldAll/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-all-tiddlers\" $param=<<currentTiddler>> foldedStatePrefix=\"$:/state/folded/\"/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\" variable=\"listItem\">\n{{$:/core/images/fold-all-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/FoldAll/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/full-screen": { "title": "$:/core/ui/Buttons/full-screen", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/full-screen-button}} {{$:/language/Buttons/FullScreen/Caption}}", "description": "{{$:/language/Buttons/FullScreen/Hint}}", "text": "<$button message=\"tm-full-screen\" tooltip={{$:/language/Buttons/FullScreen/Hint}} aria-label={{$:/language/Buttons/FullScreen/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/full-screen-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/FullScreen/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/home": { "title": "$:/core/ui/Buttons/home", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/home-button}} {{$:/language/Buttons/Home/Caption}}", "description": "{{$:/language/Buttons/Home/Hint}}", "text": "<$button message=\"tm-home\" tooltip={{$:/language/Buttons/Home/Hint}} aria-label={{$:/language/Buttons/Home/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/home-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Home/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/import": { "title": "$:/core/ui/Buttons/import", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/import-button}} {{$:/language/Buttons/Import/Caption}}", "description": "{{$:/language/Buttons/Import/Hint}}", "text": "<div class=\"tc-file-input-wrapper\">\n<$button tooltip={{$:/language/Buttons/Import/Hint}} aria-label={{$:/language/Buttons/Import/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/import-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Import/Caption}}/></span>\n</$list>\n</$button>\n<$browse tooltip={{$:/language/Buttons/Import/Hint}}/>\n</div>" }, "$:/core/ui/Buttons/language": { "title": "$:/core/ui/Buttons/language", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/globe}} {{$:/language/Buttons/Language/Caption}}", "description": "{{$:/language/Buttons/Language/Hint}}", "text": "\\define flag-title()\n$(languagePluginTitle)$/icon\n\\end\n<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/language\">> tooltip={{$:/language/Buttons/Language/Hint}} aria-label={{$:/language/Buttons/Language/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n<span class=\"tc-image-button\">\n<$set name=\"languagePluginTitle\" value={{$:/language}}>\n<$image source=<<flag-title>>/>\n</$set>\n</span>\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Language/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/language\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down tc-drop-down-language-chooser\">\n<$linkcatcher to=\"$:/language\">\n<$list filter=\"[[$:/languages/en-GB]] [plugin-type[language]sort[description]]\">\n<$link>\n<span class=\"tc-drop-down-bullet\">\n<$reveal type=\"match\" state=\"$:/language\" text=<<currentTiddler>>>\n•\n</$reveal>\n<$reveal type=\"nomatch\" state=\"$:/language\" text=<<currentTiddler>>>\n \n</$reveal>\n</span>\n<span class=\"tc-image-button\">\n<$set name=\"languagePluginTitle\" value=<<currentTiddler>>>\n<$transclude subtiddler=<<flag-title>>>\n<$list filter=\"[all[current]field:title[$:/languages/en-GB]]\">\n<$transclude tiddler=\"$:/languages/en-GB/icon\"/>\n</$list>\n</$transclude>\n</$set>\n</span>\n<$view field=\"description\">\n<$view field=\"name\">\n<$view field=\"title\"/>\n</$view>\n</$view>\n</$link>\n</$list>\n</$linkcatcher>\n</div>\n</$reveal>" }, "$:/core/ui/Buttons/manager": { "title": "$:/core/ui/Buttons/manager", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/list}} {{$:/language/Buttons/Manager/Caption}}", "description": "{{$:/language/Buttons/Manager/Hint}}", "text": "\\define manager-button(class)\n<$button to=\"$:/Manager\" tooltip={{$:/language/Buttons/Manager/Hint}} aria-label={{$:/language/Buttons/Manager/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/list}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Manager/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/Manager]]\" emptyMessage=<<manager-button>>>\n<<manager-button \"tc-selected\">>\n</$list>\n" }, "$:/core/ui/Buttons/more-page-actions": { "title": "$:/core/ui/Buttons/more-page-actions", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/down-arrow}} {{$:/language/Buttons/More/Caption}}", "description": "{{$:/language/Buttons/More/Hint}}", "text": "\\define config-title()\n$:/config/PageControlButtons/Visibility/$(listItem)$\n\\end\n<$button popup=<<qualify \"$:/state/popup/more\">> tooltip={{$:/language/Buttons/More/Hint}} aria-label={{$:/language/Buttons/More/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/down-arrow}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/More/Caption}}/></span>\n</$list>\n</$button><$reveal state=<<qualify \"$:/state/popup/more\">> type=\"popup\" position=\"below\" animate=\"yes\">\n\n<div class=\"tc-drop-down\">\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"tc-btn-invisible\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]] -[[$:/core/ui/Buttons/more-page-actions]]\" variable=\"listItem\">\n\n<$reveal type=\"match\" state=<<config-title>> text=\"hide\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$reveal>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</div>\n\n</$reveal>" }, "$:/core/ui/Buttons/new-image": { "title": "$:/core/ui/Buttons/new-image", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/new-image-button}} {{$:/language/Buttons/NewImage/Caption}}", "description": "{{$:/language/Buttons/NewImage/Hint}}", "text": "<$button tooltip={{$:/language/Buttons/NewImage/Hint}} aria-label={{$:/language/Buttons/NewImage/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-new-tiddler\" type=\"image/jpeg\"/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/new-image-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewImage/Caption}}/></span>\n</$list>\n</$button>\n" }, "$:/core/ui/Buttons/new-journal": { "title": "$:/core/ui/Buttons/new-journal", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/new-journal-button}} {{$:/language/Buttons/NewJournal/Caption}}", "description": "{{$:/language/Buttons/NewJournal/Hint}}", "text": "\\define journalButton()\n<$button tooltip={{$:/language/Buttons/NewJournal/Hint}} aria-label={{$:/language/Buttons/NewJournal/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-new-tiddler\" title=<<now \"$(journalTitleTemplate)$\">> tags=\"$(journalTags)$\" text=\"$(journalText)$\"/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/new-journal-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewJournal/Caption}}/></span>\n</$list>\n</$button>\n\\end\n<$set name=\"journalTitleTemplate\" value={{$:/config/NewJournal/Title}}>\n<$set name=\"journalTags\" value={{$:/config/NewJournal/Tags}}>\n<$set name=\"journalText\" value={{$:/config/NewJournal/Text}}>\n<<journalButton>>\n</$set></$set></$set>" }, "$:/core/ui/Buttons/new-tiddler": { "title": "$:/core/ui/Buttons/new-tiddler", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/new-button}} {{$:/language/Buttons/NewTiddler/Caption}}", "description": "{{$:/language/Buttons/NewTiddler/Hint}}", "text": "<$button message=\"tm-new-tiddler\" tooltip={{$:/language/Buttons/NewTiddler/Hint}} aria-label={{$:/language/Buttons/NewTiddler/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/new-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewTiddler/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/palette": { "title": "$:/core/ui/Buttons/palette", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/palette}} {{$:/language/Buttons/Palette/Caption}}", "description": "{{$:/language/Buttons/Palette/Hint}}", "text": "<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/palette\">> tooltip={{$:/language/Buttons/Palette/Hint}} aria-label={{$:/language/Buttons/Palette/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/palette}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Palette/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/palette\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\" style=\"font-size:0.7em;\">\n{{$:/snippets/paletteswitcher}}\n</div>\n</$reveal>" }, "$:/core/ui/Buttons/print": { "title": "$:/core/ui/Buttons/print", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/print-button}} {{$:/language/Buttons/Print/Caption}}", "description": "{{$:/language/Buttons/Print/Hint}}", "text": "<$button message=\"tm-print\" tooltip={{$:/language/Buttons/Print/Hint}} aria-label={{$:/language/Buttons/Print/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/print-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Print/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/refresh": { "title": "$:/core/ui/Buttons/refresh", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/refresh-button}} {{$:/language/Buttons/Refresh/Caption}}", "description": "{{$:/language/Buttons/Refresh/Hint}}", "text": "<$button message=\"tm-browser-refresh\" tooltip={{$:/language/Buttons/Refresh/Hint}} aria-label={{$:/language/Buttons/Refresh/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/refresh-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Refresh/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/save-wiki": { "title": "$:/core/ui/Buttons/save-wiki", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/save-button}} {{$:/language/Buttons/SaveWiki/Caption}}", "description": "{{$:/language/Buttons/SaveWiki/Hint}}", "text": "<$button message=\"tm-save-wiki\" param={{$:/config/SaveWikiButton/Template}} tooltip={{$:/language/Buttons/SaveWiki/Hint}} aria-label={{$:/language/Buttons/SaveWiki/Caption}} class=<<tv-config-toolbar-class>>>\n<span class=\"tc-dirty-indicator\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/save-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/SaveWiki/Caption}}/></span>\n</$list>\n</span>\n</$button>" }, "$:/core/ui/Buttons/storyview": { "title": "$:/core/ui/Buttons/storyview", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/storyview-classic}} {{$:/language/Buttons/StoryView/Caption}}", "description": "{{$:/language/Buttons/StoryView/Hint}}", "text": "\\define icon()\n$:/core/images/storyview-$(storyview)$\n\\end\n<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/storyview\">> tooltip={{$:/language/Buttons/StoryView/Hint}} aria-label={{$:/language/Buttons/StoryView/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n<$set name=\"storyview\" value={{$:/view}}>\n<$transclude tiddler=<<icon>>/>\n</$set>\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/StoryView/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/storyview\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n<$linkcatcher to=\"$:/view\">\n<$list filter=\"[storyviews[]]\" variable=\"storyview\">\n<$link to=<<storyview>>>\n<span class=\"tc-drop-down-bullet\">\n<$reveal type=\"match\" state=\"$:/view\" text=<<storyview>>>\n•\n</$reveal>\n<$reveal type=\"nomatch\" state=\"$:/view\" text=<<storyview>>>\n \n</$reveal>\n</span>\n<$transclude tiddler=<<icon>>/>\n<$text text=<<storyview>>/></$link>\n</$list>\n</$linkcatcher>\n</div>\n</$reveal>" }, "$:/core/ui/Buttons/tag-manager": { "title": "$:/core/ui/Buttons/tag-manager", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/tag-button}} {{$:/language/Buttons/TagManager/Caption}}", "description": "{{$:/language/Buttons/TagManager/Hint}}", "text": "\\define control-panel-button(class)\n<$button to=\"$:/TagManager\" tooltip={{$:/language/Buttons/TagManager/Hint}} aria-label={{$:/language/Buttons/TagManager/Caption}} class=\"\"\"$(tv-config-toolbar-class)$ $class$\"\"\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/tag-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/TagManager/Caption}}/></span>\n</$list>\n</$button>\n\\end\n\n<$list filter=\"[list[$:/StoryList]] +[field:title[$:/TagManager]]\" emptyMessage=<<control-panel-button>>>\n<<control-panel-button \"tc-selected\">>\n</$list>\n" }, "$:/core/ui/Buttons/theme": { "title": "$:/core/ui/Buttons/theme", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/theme-button}} {{$:/language/Buttons/Theme/Caption}}", "description": "{{$:/language/Buttons/Theme/Hint}}", "text": "<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/theme\">> tooltip={{$:/language/Buttons/Theme/Hint}} aria-label={{$:/language/Buttons/Theme/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/theme-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Theme/Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/theme\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n<$linkcatcher to=\"$:/theme\">\n<$list filter=\"[plugin-type[theme]sort[title]]\" variable=\"themeTitle\">\n<$link to=<<themeTitle>>>\n<span class=\"tc-drop-down-bullet\">\n<$reveal type=\"match\" state=\"$:/theme\" text=<<themeTitle>>>\n•\n</$reveal>\n<$reveal type=\"nomatch\" state=\"$:/theme\" text=<<themeTitle>>>\n \n</$reveal>\n</span>\n<$view tiddler=<<themeTitle>> field=\"name\"/>\n</$link>\n</$list>\n</$linkcatcher>\n</div>\n</$reveal>" }, "$:/core/ui/Buttons/timestamp": { "title": "$:/core/ui/Buttons/timestamp", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/timestamp-on}} {{$:/language/Buttons/Timestamp/Caption}}", "description": "{{$:/language/Buttons/Timestamp/Hint}}", "text": "<$reveal type=\"nomatch\" state=\"$:/config/TimestampDisable\" text=\"yes\">\n<$button tooltip={{$:/language/Buttons/Timestamp/On/Hint}} aria-label={{$:/language/Buttons/Timestamp/On/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-setfield $tiddler=\"$:/config/TimestampDisable\" $value=\"yes\"/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/timestamp-on}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Timestamp/On/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>\n<$reveal type=\"match\" state=\"$:/config/TimestampDisable\" text=\"yes\">\n<$button tooltip={{$:/language/Buttons/Timestamp/Off/Hint}} aria-label={{$:/language/Buttons/Timestamp/Off/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-setfield $tiddler=\"$:/config/TimestampDisable\" $value=\"no\"/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/timestamp-off}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Timestamp/Off/Caption}}/></span>\n</$list>\n</$button>\n</$reveal>" }, "$:/core/ui/Buttons/unfold-all": { "title": "$:/core/ui/Buttons/unfold-all", "tags": "$:/tags/PageControls", "caption": "{{$:/core/images/unfold-all-button}} {{$:/language/Buttons/UnfoldAll/Caption}}", "description": "{{$:/language/Buttons/UnfoldAll/Hint}}", "text": "<$button tooltip={{$:/language/Buttons/UnfoldAll/Hint}} aria-label={{$:/language/Buttons/UnfoldAll/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-unfold-all-tiddlers\" $param=<<currentTiddler>> foldedStatePrefix=\"$:/state/folded/\"/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\" variable=\"listItem\">\n{{$:/core/images/unfold-all-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/UnfoldAll/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/PageTemplate/pagecontrols": { "title": "$:/core/ui/PageTemplate/pagecontrols", "text": "\\define config-title()\n$:/config/PageControlButtons/Visibility/$(listItem)$\n\\end\n<div class=\"tc-page-controls\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]\" variable=\"listItem\">\n<$reveal type=\"nomatch\" state=<<config-title>> text=\"hide\">\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n</$reveal>\n</$list>\n</div>\n\n" }, "$:/core/ui/PageStylesheet": { "title": "$:/core/ui/PageStylesheet", "text": "<$importvariables filter=\"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\">\n\n<$set name=\"currentTiddler\" value={{$:/language}}>\n\n<$set name=\"languageTitle\" value={{!!name}}>\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Stylesheet]!has[draft.of]]\">\n<$transclude mode=\"block\"/>\n</$list>\n\n</$set>\n\n</$set>\n\n</$importvariables>\n" }, "$:/core/ui/PageTemplate/alerts": { "title": "$:/core/ui/PageTemplate/alerts", "tags": "$:/tags/PageTemplate", "text": "<div class=\"tc-alerts\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Alert]!has[draft.of]]\" template=\"$:/core/ui/AlertTemplate\" storyview=\"pop\"/>\n\n</div>\n" }, "$:/core/ui/PageTemplate/pluginreloadwarning": { "title": "$:/core/ui/PageTemplate/pluginreloadwarning", "tags": "$:/tags/PageTemplate", "text": "\\define lingo-base() $:/language/\n\n<$list filter=\"[has[plugin-type]haschanged[]!plugin-type[import]limit[1]]\">\n\n<$reveal type=\"nomatch\" state=\"$:/temp/HidePluginWarning\" text=\"yes\">\n\n<div class=\"tc-plugin-reload-warning\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n<<lingo PluginReloadWarning>> <$button set=\"$:/temp/HidePluginWarning\" setTo=\"yes\" class=\"tc-btn-invisible\">{{$:/core/images/close-button}}</$button>\n\n</$set>\n\n</div>\n\n</$reveal>\n\n</$list>\n" }, "$:/core/ui/PageTemplate/sidebar": { "title": "$:/core/ui/PageTemplate/sidebar", "tags": "$:/tags/PageTemplate", "text": "<$scrollable fallthrough=\"no\" class=\"tc-sidebar-scrollable\">\n\n<div class=\"tc-sidebar-header\">\n\n<$reveal state=\"$:/state/sidebar\" type=\"match\" text=\"yes\" default=\"yes\" retain=\"yes\" animate=\"yes\">\n\n<h1 class=\"tc-site-title\">\n\n<$transclude tiddler=\"$:/SiteTitle\" mode=\"inline\"/>\n\n</h1>\n\n<div class=\"tc-site-subtitle\">\n\n<$transclude tiddler=\"$:/SiteSubtitle\" mode=\"inline\"/>\n\n</div>\n\n{{||$:/core/ui/PageTemplate/pagecontrols}}\n\n<$transclude tiddler=\"$:/core/ui/SideBarLists\" mode=\"inline\"/>\n\n</$reveal>\n\n</div>\n\n</$scrollable>" }, "$:/core/ui/PageTemplate/story": { "title": "$:/core/ui/PageTemplate/story", "tags": "$:/tags/PageTemplate", "text": "<section class=\"tc-story-river\">\n\n<section class=\"story-backdrop\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/AboveStory]!has[draft.of]]\">\n\n<$transclude/>\n\n</$list>\n\n</section>\n\n<$list filter=\"[list[$:/StoryList]]\" history=\"$:/HistoryList\" template=\"$:/core/ui/ViewTemplate\" editTemplate=\"$:/core/ui/EditTemplate\" storyview={{$:/view}} emptyMessage={{$:/config/EmptyStoryMessage}}/>\n\n<section class=\"story-frontdrop\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/BelowStory]!has[draft.of]]\">\n\n<$transclude/>\n\n</$list>\n\n</section>\n\n</section>\n" }, "$:/core/ui/PageTemplate/topleftbar": { "title": "$:/core/ui/PageTemplate/topleftbar", "tags": "$:/tags/PageTemplate", "text": "<span class=\"tc-topbar tc-topbar-left\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TopLeftBar]!has[draft.of]]\" variable=\"listItem\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$list>\n\n</span>\n" }, "$:/core/ui/PageTemplate/toprightbar": { "title": "$:/core/ui/PageTemplate/toprightbar", "tags": "$:/tags/PageTemplate", "text": "<span class=\"tc-topbar tc-topbar-right\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TopRightBar]!has[draft.of]]\" variable=\"listItem\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$list>\n\n</span>\n" }, "$:/core/ui/PageTemplate": { "title": "$:/core/ui/PageTemplate", "text": "\\define containerClasses()\ntc-page-container tc-page-view-$(themeTitle)$ tc-language-$(languageTitle)$\n\\end\n\n<$importvariables filter=\"[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\">\n\n<$set name=\"tv-config-toolbar-icons\" value={{$:/config/Toolbar/Icons}}>\n\n<$set name=\"tv-config-toolbar-text\" value={{$:/config/Toolbar/Text}}>\n\n<$set name=\"tv-config-toolbar-class\" value={{$:/config/Toolbar/ButtonClass}}>\n\n<$set name=\"themeTitle\" value={{$:/view}}>\n\n<$set name=\"currentTiddler\" value={{$:/language}}>\n\n<$set name=\"languageTitle\" value={{!!name}}>\n\n<$set name=\"currentTiddler\" value=\"\">\n\n<div class=<<containerClasses>>>\n\n<$navigator story=\"$:/StoryList\" history=\"$:/HistoryList\" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>\n\n<$dropzone>\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageTemplate]!has[draft.of]]\" variable=\"listItem\">\n\n<$transclude tiddler=<<listItem>>/>\n\n</$list>\n\n</$dropzone>\n\n</$navigator>\n\n</div>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</$importvariables>\n" }, "$:/core/ui/PluginInfo": { "title": "$:/core/ui/PluginInfo", "text": "\\define localised-info-tiddler-title()\n$(currentTiddler)$/$(languageTitle)$/$(currentTab)$\n\\end\n\\define info-tiddler-title()\n$(currentTiddler)$/$(currentTab)$\n\\end\n\\define default-tiddler-title()\n$:/core/ui/PluginInfo/Default/$(currentTab)$\n\\end\n<$transclude tiddler=<<localised-info-tiddler-title>> mode=\"block\">\n<$transclude tiddler=<<currentTiddler>> subtiddler=<<localised-info-tiddler-title>> mode=\"block\">\n<$transclude tiddler=<<currentTiddler>> subtiddler=<<info-tiddler-title>> mode=\"block\">\n<$transclude tiddler=<<default-tiddler-title>> mode=\"block\">\n{{$:/language/ControlPanel/Plugin/NoInfoFound/Hint}}\n</$transclude>\n</$transclude>\n</$transclude>\n</$transclude>\n" }, "$:/core/ui/PluginInfo/Default/contents": { "title": "$:/core/ui/PluginInfo/Default/contents", "text": "\\define lingo-base() $:/language/TiddlerInfo/Advanced/PluginInfo/\n<<lingo Hint>>\n<ul>\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" emptyMessage=<<lingo Empty/Hint>>>\n<li>\n<$link to={{!!title}}>\n<$view field=\"title\"/>\n</$link>\n</li>\n</$list>\n</ul>\n" }, "$:/core/ui/PluginListItemTemplate": { "title": "$:/core/ui/PluginListItemTemplate", "text": "<div class=\"tc-menu-list-item\">\n<$link to={{!!title}}>\n<$view field=\"description\">\n<$view field=\"title\"/>\n</$view>\n</$link>\n</div>" }, "$:/core/ui/SearchResults": { "title": "$:/core/ui/SearchResults", "text": "<div class=\"tc-search-results\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]butfirst[]limit[1]]\" emptyMessage=\"\"\"\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\">\n<$transclude mode=\"block\"/>\n</$list>\n\"\"\">\n\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]\" default={{$:/config/SearchResults/Default}}/>\n\n</$list>\n\n</div>\n" }, "$:/core/ui/SideBar/More": { "title": "$:/core/ui/SideBar/More", "tags": "$:/tags/SideBar", "caption": "{{$:/language/SideBar/More/Caption}}", "text": "<div class=\"tc-more-sidebar\">\n<<tabs \"[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]\" \"$:/core/ui/MoreSideBar/Tags\" \"$:/state/tab/moresidebar\" \"tc-vertical\">>\n</div>\n" }, "$:/core/ui/SideBar/Open": { "title": "$:/core/ui/SideBar/Open", "tags": "$:/tags/SideBar", "caption": "{{$:/language/SideBar/Open/Caption}}", "text": "\\define lingo-base() $:/language/CloseAll/\n\n\\define drop-actions()\n<$action-listops $tiddler=\"$:/StoryList\" $subfilter=\"+[insertbefore:currentTiddler<actionTiddler>]\"/>\n\\end\n\n<$list filter=\"[list[$:/StoryList]]\" history=\"$:/HistoryList\" storyview=\"pop\">\n<div style=\"position: relative;\">\n<$droppable actions=<<drop-actions>>>\n<div class=\"tc-droppable-placeholder\">\n \n</div>\n<div>\n<$button message=\"tm-close-tiddler\" tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class=\"tc-btn-invisible tc-btn-mini\">×</$button> <$link to={{!!title}}><$view field=\"title\"/></$link>\n</div>\n</$droppable>\n</div>\n</$list>\n<$tiddler tiddler=\"\">\n<$droppable actions=<<drop-actions>>>\n<div class=\"tc-droppable-placeholder\">\n \n</div>\n<$button message=\"tm-close-all-tiddlers\" class=\"tc-btn-invisible tc-btn-mini\"><<lingo Button>></$button>\n</$droppable>\n</$tiddler>\n" }, "$:/core/ui/SideBar/Recent": { "title": "$:/core/ui/SideBar/Recent", "tags": "$:/tags/SideBar", "caption": "{{$:/language/SideBar/Recent/Caption}}", "text": "<$macrocall $name=\"timeline\" format={{$:/language/RecentChanges/DateFormat}}/>\n" }, "$:/core/ui/SideBar/Tools": { "title": "$:/core/ui/SideBar/Tools", "tags": "$:/tags/SideBar", "caption": "{{$:/language/SideBar/Tools/Caption}}", "text": "\\define lingo-base() $:/language/ControlPanel/\n\\define config-title()\n$:/config/PageControlButtons/Visibility/$(listItem)$\n\\end\n\n<<lingo Basics/Version/Prompt>> <<version>>\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]\" variable=\"listItem\">\n\n<div style=\"position:relative;\">\n\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <$transclude tiddler=<<listItem>>/> <i class=\"tc-muted\"><$transclude tiddler=<<listItem>> field=\"description\"/></i>\n\n</div>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n" }, "$:/core/ui/SideBarLists": { "title": "$:/core/ui/SideBarLists", "text": "<div class=\"tc-sidebar-lists\">\n\n<$set name=\"searchTiddler\" value=\"$:/temp/search\">\n<div class=\"tc-search\">\n<$edit-text tiddler=\"$:/temp/search\" type=\"search\" tag=\"input\" focus={{$:/config/Search/AutoFocus}} focusPopup=<<qualify \"$:/state/popup/search-dropdown\">> class=\"tc-popup-handle\"/>\n<$reveal state=\"$:/temp/search\" type=\"nomatch\" text=\"\">\n<$button tooltip={{$:/language/Buttons/AdvancedSearch/Hint}} aria-label={{$:/language/Buttons/AdvancedSearch/Caption}} class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/advancedsearch\" text={{$:/temp/search}}/>\n<$action-setfield $tiddler=\"$:/temp/search\" text=\"\"/>\n<$action-navigate $to=\"$:/AdvancedSearch\"/>\n{{$:/core/images/advanced-search-button}}\n</$button>\n<$button class=\"tc-btn-invisible\">\n<$action-setfield $tiddler=\"$:/temp/search\" text=\"\" />\n{{$:/core/images/close-button}}\n</$button>\n<$button popup=<<qualify \"$:/state/popup/search-dropdown\">> class=\"tc-btn-invisible\">\n{{$:/core/images/down-arrow}}\n<$list filter=\"[{$:/temp/search}minlength{$:/config/Search/MinLength}limit[1]]\" variable=\"listItem\">\n<$set name=\"resultCount\" value=\"\"\"<$count filter=\"[!is[system]search{$(searchTiddler)$}]\"/>\"\"\">\n{{$:/language/Search/Matches}}\n</$set>\n</$list>\n</$button>\n</$reveal>\n<$reveal state=\"$:/temp/search\" type=\"match\" text=\"\">\n<$button to=\"$:/AdvancedSearch\" tooltip={{$:/language/Buttons/AdvancedSearch/Hint}} aria-label={{$:/language/Buttons/AdvancedSearch/Caption}} class=\"tc-btn-invisible\">\n{{$:/core/images/advanced-search-button}}\n</$button>\n</$reveal>\n</div>\n\n<$reveal tag=\"div\" class=\"tc-block-dropdown-wrapper\" state=\"$:/temp/search\" type=\"nomatch\" text=\"\">\n\n<$reveal tag=\"div\" class=\"tc-block-dropdown tc-search-drop-down tc-popup-handle\" state=<<qualify \"$:/state/popup/search-dropdown\">> type=\"nomatch\" text=\"\" default=\"\">\n\n<$list filter=\"[{$:/temp/search}minlength{$:/config/Search/MinLength}limit[1]]\" emptyMessage=\"\"\"<div class=\"tc-search-results\">{{$:/language/Search/Search/TooShort}}</div>\"\"\" variable=\"listItem\">\n\n{{$:/core/ui/SearchResults}}\n\n</$list>\n\n</$reveal>\n\n</$reveal>\n\n</$set>\n\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/SideBar]!has[draft.of]]\" default={{$:/config/DefaultSidebarTab}} state=\"$:/state/tab/sidebar\" />\n\n</div>\n" }, "$:/TagManager": { "title": "$:/TagManager", "icon": "$:/core/images/tag-button", "color": "#bbb", "caption": "{{$:/language/TagManager/Caption}}", "text": "\\define lingo-base() $:/language/TagManager/\n\\define iconEditorTab(type)\n<$list filter=\"[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[sort[title]] +[$type$is[system]]\">\n<$link to={{!!title}}>\n<$transclude/> <$view field=\"title\"/>\n</$link>\n</$list>\n\\end\n\\define iconEditor(title)\n<div class=\"tc-drop-down-wrapper\">\n<$button popup=<<qualify \"$:/state/popup/icon/$title$\">> class=\"tc-btn-invisible tc-btn-dropdown\">{{$:/core/images/down-arrow}}</$button>\n<$reveal state=<<qualify \"$:/state/popup/icon/$title$\">> type=\"popup\" position=\"belowleft\" text=\"\" default=\"\">\n<div class=\"tc-drop-down\">\n<$linkcatcher to=\"$title$!!icon\">\n<<iconEditorTab type:\"!\">>\n<hr/>\n<<iconEditorTab type:\"\">>\n</$linkcatcher>\n</div>\n</$reveal>\n</div>\n\\end\n\\define qualifyTitle(title)\n$title$$(currentTiddler)$\n\\end\n\\define toggleButton(state)\n<$reveal state=\"$state$\" type=\"match\" text=\"closed\" default=\"closed\">\n<$button set=\"$state$\" setTo=\"open\" class=\"tc-btn-invisible tc-btn-dropdown\" selectedClass=\"tc-selected\">\n{{$:/core/images/info-button}}\n</$button>\n</$reveal>\n<$reveal state=\"$state$\" type=\"match\" text=\"open\" default=\"closed\">\n<$button set=\"$state$\" setTo=\"closed\" class=\"tc-btn-invisible tc-btn-dropdown\" selectedClass=\"tc-selected\">\n{{$:/core/images/info-button}}\n</$button>\n</$reveal>\n\\end\n<table class=\"tc-tag-manager-table\">\n<tbody>\n<tr>\n<th><<lingo Colour/Heading>></th>\n<th class=\"tc-tag-manager-tag\"><<lingo Tag/Heading>></th>\n<th><<lingo Count/Heading>></th>\n<th><<lingo Icon/Heading>></th>\n<th><<lingo Info/Heading>></th>\n</tr>\n<$list filter=\"[tags[]!is[system]sort[title]]\">\n<tr>\n<td><$edit-text field=\"color\" tag=\"input\" type=\"color\"/></td>\n<td><$macrocall $name=\"tag\" tag=<<currentTiddler>>/></td>\n<td><$count filter=\"[all[current]tagging[]]\"/></td>\n<td>\n<$macrocall $name=\"iconEditor\" title={{!!title}}/>\n</td>\n<td>\n<$macrocall $name=\"toggleButton\" state=<<qualifyTitle \"$:/state/tag-manager/\">> /> \n</td>\n</tr>\n<tr>\n<td></td>\n<td colspan=\"4\">\n<$reveal state=<<qualifyTitle \"$:/state/tag-manager/\">> type=\"match\" text=\"open\" default=\"\">\n<table>\n<tbody>\n<tr><td><<lingo Colour/Heading>></td><td><$edit-text field=\"color\" tag=\"input\" type=\"text\" size=\"9\"/></td></tr>\n<tr><td><<lingo Icon/Heading>></td><td><$edit-text field=\"icon\" tag=\"input\" size=\"45\"/></td></tr>\n</tbody>\n</table>\n</$reveal>\n</td>\n</tr>\n</$list>\n<tr>\n<td></td>\n<td>\n{{$:/core/ui/UntaggedTemplate}}\n</td>\n<td>\n<small class=\"tc-menu-list-count\"><$count filter=\"[untagged[]!is[system]] -[tags[]]\"/></small>\n</td>\n<td></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n" }, "$:/core/ui/TagTemplate": { "title": "$:/core/ui/TagTemplate", "text": "<span class=\"tc-tag-list-item\">\n<$set name=\"transclusion\" value=<<currentTiddler>>>\n<$macrocall $name=\"tag-pill-body\" tag=<<currentTiddler>> icon={{!!icon}} colour={{!!color}} palette={{$:/palette}} element-tag=\"\"\"$button\"\"\" element-attributes=\"\"\"popup=<<qualify \"$:/state/popup/tag\">> dragFilter='[all[current]tagging[]]' tag='span'\"\"\"/>\n<$reveal state=<<qualify \"$:/state/popup/tag\">> type=\"popup\" position=\"below\" animate=\"yes\" class=\"tc-drop-down\">\n<$transclude tiddler=\"$:/core/ui/ListItemTemplate\"/>\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TagDropdown]!has[draft.of]]\" variable=\"listItem\"> \n<$transclude tiddler=<<listItem>>/> \n</$list>\n<hr>\n<$macrocall $name=\"list-tagged-draggable\" tag=<<currentTiddler>>/>\n</$reveal>\n</$set>\n</span>\n" }, "$:/core/ui/TiddlerFieldTemplate": { "title": "$:/core/ui/TiddlerFieldTemplate", "text": "<tr class=\"tc-view-field\">\n<td class=\"tc-view-field-name\">\n<$text text=<<listItem>>/>\n</td>\n<td class=\"tc-view-field-value\">\n<$view field=<<listItem>>/>\n</td>\n</tr>" }, "$:/core/ui/TiddlerFields": { "title": "$:/core/ui/TiddlerFields", "text": "<table class=\"tc-view-field-table\">\n<tbody>\n<$list filter=\"[all[current]fields[]sort[title]] -text\" template=\"$:/core/ui/TiddlerFieldTemplate\" variable=\"listItem\"/>\n</tbody>\n</table>\n" }, "$:/core/ui/TiddlerInfo/Advanced/PluginInfo": { "title": "$:/core/ui/TiddlerInfo/Advanced/PluginInfo", "tags": "$:/tags/TiddlerInfo/Advanced", "text": "\\define lingo-base() $:/language/TiddlerInfo/Advanced/PluginInfo/\n<$list filter=\"[all[current]has[plugin-type]]\">\n\n! <<lingo Heading>>\n\n<<lingo Hint>>\n<ul>\n<$list filter=\"[all[current]plugintiddlers[]sort[title]]\" emptyMessage=<<lingo Empty/Hint>>>\n<li>\n<$link to={{!!title}}>\n<$view field=\"title\"/>\n</$link>\n</li>\n</$list>\n</ul>\n\n</$list>\n" }, "$:/core/ui/TiddlerInfo/Advanced/ShadowInfo": { "title": "$:/core/ui/TiddlerInfo/Advanced/ShadowInfo", "tags": "$:/tags/TiddlerInfo/Advanced", "text": "\\define lingo-base() $:/language/TiddlerInfo/Advanced/ShadowInfo/\n<$set name=\"infoTiddler\" value=<<currentTiddler>>>\n\n''<<lingo Heading>>''\n\n<$list filter=\"[all[current]!is[shadow]]\">\n\n<<lingo NotShadow/Hint>>\n\n</$list>\n\n<$list filter=\"[all[current]is[shadow]]\">\n\n<<lingo Shadow/Hint>>\n\n<$list filter=\"[all[current]shadowsource[]]\">\n\n<$set name=\"pluginTiddler\" value=<<currentTiddler>>>\n<<lingo Shadow/Source>>\n</$set>\n\n</$list>\n\n<$list filter=\"[all[current]is[shadow]is[tiddler]]\">\n\n<<lingo OverriddenShadow/Hint>>\n\n</$list>\n\n\n</$list>\n</$set>\n" }, "$:/core/ui/TiddlerInfo/Advanced": { "title": "$:/core/ui/TiddlerInfo/Advanced", "tags": "$:/tags/TiddlerInfo", "caption": "{{$:/language/TiddlerInfo/Advanced/Caption}}", "text": "<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/TiddlerInfo/Advanced]!has[draft.of]]\" variable=\"listItem\">\n<$transclude tiddler=<<listItem>>/>\n\n</$list>\n" }, "$:/core/ui/TiddlerInfo/Fields": { "title": "$:/core/ui/TiddlerInfo/Fields", "tags": "$:/tags/TiddlerInfo", "caption": "{{$:/language/TiddlerInfo/Fields/Caption}}", "text": "<$transclude tiddler=\"$:/core/ui/TiddlerFields\"/>\n" }, "$:/core/ui/TiddlerInfo/List": { "title": "$:/core/ui/TiddlerInfo/List", "tags": "$:/tags/TiddlerInfo", "caption": "{{$:/language/TiddlerInfo/List/Caption}}", "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[list{!!title}]\" emptyMessage=<<lingo List/Empty>> template=\"$:/core/ui/ListItemTemplate\"/>\n" }, "$:/core/ui/TiddlerInfo/Listed": { "title": "$:/core/ui/TiddlerInfo/Listed", "tags": "$:/tags/TiddlerInfo", "caption": "{{$:/language/TiddlerInfo/Listed/Caption}}", "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[all[current]listed[]!is[system]]\" emptyMessage=<<lingo Listed/Empty>> template=\"$:/core/ui/ListItemTemplate\"/>\n" }, "$:/core/ui/TiddlerInfo/References": { "title": "$:/core/ui/TiddlerInfo/References", "tags": "$:/tags/TiddlerInfo", "caption": "{{$:/language/TiddlerInfo/References/Caption}}", "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[all[current]backlinks[]sort[title]]\" emptyMessage=<<lingo References/Empty>> template=\"$:/core/ui/ListItemTemplate\">\n</$list>\n" }, "$:/core/ui/TiddlerInfo/Tagging": { "title": "$:/core/ui/TiddlerInfo/Tagging", "tags": "$:/tags/TiddlerInfo", "caption": "{{$:/language/TiddlerInfo/Tagging/Caption}}", "text": "\\define lingo-base() $:/language/TiddlerInfo/\n<$list filter=\"[all[current]tagging[]]\" emptyMessage=<<lingo Tagging/Empty>> template=\"$:/core/ui/ListItemTemplate\"/>\n" }, "$:/core/ui/TiddlerInfo/Tools": { "title": "$:/core/ui/TiddlerInfo/Tools", "tags": "$:/tags/TiddlerInfo", "caption": "{{$:/language/TiddlerInfo/Tools/Caption}}", "text": "\\define lingo-base() $:/language/TiddlerInfo/\n\\define config-title()\n$:/config/ViewToolbarButtons/Visibility/$(listItem)$\n\\end\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]]\" variable=\"listItem\">\n\n<$checkbox tiddler=<<config-title>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"show\"/> <$transclude tiddler=<<listItem>>/> <i class=\"tc-muted\"><$transclude tiddler=<<listItem>> field=\"description\"/></i>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n" }, "$:/core/ui/TiddlerInfo": { "title": "$:/core/ui/TiddlerInfo", "text": "<div style=\"position:relative;\">\n<div class=\"tc-tiddler-controls\" style=\"position:absolute;right:0;\">\n<$reveal state=\"$:/config/TiddlerInfo/Mode\" type=\"match\" text=\"sticky\">\n<$button set=<<tiddlerInfoState>> setTo=\"\" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=\"tc-btn-invisible\">\n{{$:/core/images/close-button}}\n</$button>\n</$reveal>\n</div>\n</div>\n\n<$macrocall $name=\"tabs\" tabsList=\"[all[shadows+tiddlers]tag[$:/tags/TiddlerInfo]!has[draft.of]]\" default={{$:/config/TiddlerInfo/Default}}/>" }, "$:/core/ui/TopBar/menu": { "title": "$:/core/ui/TopBar/menu", "tags": "$:/tags/TopRightBar", "text": "<$reveal state=\"$:/state/sidebar\" type=\"nomatch\" text=\"no\">\n<$button set=\"$:/state/sidebar\" setTo=\"no\" tooltip={{$:/language/Buttons/HideSideBar/Hint}} aria-label={{$:/language/Buttons/HideSideBar/Caption}} class=\"tc-btn-invisible\">{{$:/core/images/chevron-right}}</$button>\n</$reveal>\n<$reveal state=\"$:/state/sidebar\" type=\"match\" text=\"no\">\n<$button set=\"$:/state/sidebar\" setTo=\"yes\" tooltip={{$:/language/Buttons/ShowSideBar/Hint}} aria-label={{$:/language/Buttons/ShowSideBar/Caption}} class=\"tc-btn-invisible\">{{$:/core/images/chevron-left}}</$button>\n</$reveal>\n" }, "$:/core/ui/UntaggedTemplate": { "title": "$:/core/ui/UntaggedTemplate", "text": "\\define lingo-base() $:/language/SideBar/\n<$button popup=<<qualify \"$:/state/popup/tag\">> class=\"tc-btn-invisible tc-untagged-label tc-tag-label\">\n<<lingo Tags/Untagged/Caption>>\n</$button>\n<$reveal state=<<qualify \"$:/state/popup/tag\">> type=\"popup\" position=\"below\">\n<div class=\"tc-drop-down\">\n<$list filter=\"[untagged[]!is[system]] -[tags[]] +[sort[title]]\" template=\"$:/core/ui/ListItemTemplate\"/>\n</div>\n</$reveal>\n" }, "$:/core/ui/ViewTemplate/body": { "title": "$:/core/ui/ViewTemplate/body", "tags": "$:/tags/ViewTemplate", "text": "<$reveal tag=\"div\" class=\"tc-tiddler-body\" type=\"nomatch\" state=<<folded-state>> text=\"hide\" retain=\"yes\" animate=\"yes\">\n\n<$list filter=\"[all[current]!has[plugin-type]!field:hide-body[yes]]\">\n\n<$transclude>\n\n<$transclude tiddler=\"$:/language/MissingTiddler/Hint\"/>\n\n</$transclude>\n\n</$list>\n\n</$reveal>" }, "$:/core/ui/ViewTemplate/classic": { "title": "$:/core/ui/ViewTemplate/classic", "tags": "$:/tags/ViewTemplate $:/tags/EditTemplate", "text": "\\define lingo-base() $:/language/ClassicWarning/\n<$list filter=\"[all[current]type[text/x-tiddlywiki]]\">\n<div class=\"tc-message-box\">\n\n<<lingo Hint>>\n\n<$button set=\"!!type\" setTo=\"text/vnd.tiddlywiki\"><<lingo Upgrade/Caption>></$button>\n\n</div>\n</$list>\n" }, "$:/core/ui/ViewTemplate/import": { "title": "$:/core/ui/ViewTemplate/import", "tags": "$:/tags/ViewTemplate", "text": "\\define lingo-base() $:/language/Import/\n\n<$list filter=\"[all[current]field:plugin-type[import]]\">\n\n<div class=\"tc-import\">\n\n<<lingo Listing/Hint>>\n\n<$button message=\"tm-delete-tiddler\" param=<<currentTiddler>>><<lingo Listing/Cancel/Caption>></$button>\n<$button message=\"tm-perform-import\" param=<<currentTiddler>>><<lingo Listing/Import/Caption>></$button>\n\n{{||$:/core/ui/ImportListing}}\n\n<$button message=\"tm-delete-tiddler\" param=<<currentTiddler>>><<lingo Listing/Cancel/Caption>></$button>\n<$button message=\"tm-perform-import\" param=<<currentTiddler>>><<lingo Listing/Import/Caption>></$button>\n\n</div>\n\n</$list>\n" }, "$:/core/ui/ViewTemplate/plugin": { "title": "$:/core/ui/ViewTemplate/plugin", "tags": "$:/tags/ViewTemplate", "text": "<$list filter=\"[all[current]has[plugin-type]] -[all[current]field:plugin-type[import]]\">\n<$set name=\"plugin-type\" value={{!!plugin-type}}>\n<$set name=\"default-popup-state\" value=\"yes\">\n<$set name=\"qualified-state\" value=<<qualify \"$:/state/plugin-info\">>>\n{{||$:/core/ui/Components/plugin-info}}\n</$set>\n</$set>\n</$set>\n</$list>\n" }, "$:/core/ui/ViewTemplate/subtitle": { "title": "$:/core/ui/ViewTemplate/subtitle", "tags": "$:/tags/ViewTemplate", "text": "<$reveal type=\"nomatch\" state=<<folded-state>> text=\"hide\" tag=\"div\" retain=\"yes\" animate=\"yes\">\n<div class=\"tc-subtitle\">\n<$link to={{!!modifier}}>\n<$view field=\"modifier\"/>\n</$link> <$view field=\"modified\" format=\"date\" template={{$:/language/Tiddler/DateFormat}}/>\n</div>\n</$reveal>\n" }, "$:/core/ui/ViewTemplate/tags": { "title": "$:/core/ui/ViewTemplate/tags", "tags": "$:/tags/ViewTemplate", "text": "<$reveal type=\"nomatch\" state=<<folded-state>> text=\"hide\" tag=\"div\" retain=\"yes\" animate=\"yes\">\n<div class=\"tc-tags-wrapper\"><$list filter=\"[all[current]tags[]sort[title]]\" template=\"$:/core/ui/TagTemplate\" storyview=\"pop\"/></div>\n</$reveal>" }, "$:/core/ui/ViewTemplate/title": { "title": "$:/core/ui/ViewTemplate/title", "tags": "$:/tags/ViewTemplate", "text": "\\define title-styles()\nfill:$(foregroundColor)$;\n\\end\n\\define config-title()\n$:/config/ViewToolbarButtons/Visibility/$(listItem)$\n\\end\n<div class=\"tc-tiddler-title\">\n<div class=\"tc-titlebar\">\n<span class=\"tc-tiddler-controls\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]]\" variable=\"listItem\"><$reveal type=\"nomatch\" state=<<config-title>> text=\"hide\"><$transclude tiddler=<<listItem>>/></$reveal></$list>\n</span>\n<$set name=\"tv-wikilinks\" value={{$:/config/Tiddlers/TitleLinks}}>\n<$link>\n<$set name=\"foregroundColor\" value={{!!color}}>\n<span class=\"tc-tiddler-title-icon\" style=<<title-styles>>>\n<$transclude tiddler={{!!icon}}/>\n</span>\n</$set>\n<$list filter=\"[all[current]removeprefix[$:/]]\">\n<h2 class=\"tc-title\" title={{$:/language/SystemTiddler/Tooltip}}>\n<span class=\"tc-system-title-prefix\">$:/</span><$text text=<<currentTiddler>>/>\n</h2>\n</$list>\n<$list filter=\"[all[current]!prefix[$:/]]\">\n<h2 class=\"tc-title\">\n<$view field=\"title\"/>\n</h2>\n</$list>\n</$link>\n</$set>\n</div>\n\n<$reveal type=\"nomatch\" text=\"\" default=\"\" state=<<tiddlerInfoState>> class=\"tc-tiddler-info tc-popup-handle\" animate=\"yes\" retain=\"yes\">\n\n<$transclude tiddler=\"$:/core/ui/TiddlerInfo\"/>\n\n</$reveal>\n</div>" }, "$:/core/ui/ViewTemplate/unfold": { "title": "$:/core/ui/ViewTemplate/unfold", "tags": "$:/tags/ViewTemplate", "text": "<$reveal tag=\"div\" type=\"nomatch\" state=\"$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar\" text=\"hide\">\n<$reveal tag=\"div\" type=\"nomatch\" state=<<folded-state>> text=\"hide\" default=\"show\" retain=\"yes\" animate=\"yes\">\n<$button tooltip={{$:/language/Buttons/Fold/Hint}} aria-label={{$:/language/Buttons/Fold/Caption}} class=\"tc-fold-banner\">\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n{{$:/core/images/chevron-up}}\n</$button>\n</$reveal>\n<$reveal tag=\"div\" type=\"nomatch\" state=<<folded-state>> text=\"show\" default=\"show\" retain=\"yes\" animate=\"yes\">\n<$button tooltip={{$:/language/Buttons/Unfold/Hint}} aria-label={{$:/language/Buttons/Unfold/Caption}} class=\"tc-unfold-banner\">\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n{{$:/core/images/chevron-down}}\n</$button>\n</$reveal>\n</$reveal>\n" }, "$:/core/ui/ViewTemplate": { "title": "$:/core/ui/ViewTemplate", "text": "\\define frame-classes()\ntc-tiddler-frame tc-tiddler-view-frame $(missingTiddlerClass)$ $(shadowTiddlerClass)$ $(systemTiddlerClass)$ $(tiddlerTagClasses)$\n\\end\n\\define folded-state()\n$:/state/folded/$(currentTiddler)$\n\\end\n<$set name=\"storyTiddler\" value=<<currentTiddler>>><$set name=\"tiddlerInfoState\" value=<<qualify \"$:/state/popup/tiddler-info\">>><$tiddler tiddler=<<currentTiddler>>><div class=<<frame-classes>>><$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]\" variable=\"listItem\"><$transclude tiddler=<<listItem>>/></$list>\n</div>\n</$tiddler></$set></$set>\n" }, "$:/core/ui/Buttons/clone": { "title": "$:/core/ui/Buttons/clone", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/clone-button}} {{$:/language/Buttons/Clone/Caption}}", "description": "{{$:/language/Buttons/Clone/Hint}}", "text": "<$button message=\"tm-new-tiddler\" param=<<currentTiddler>> tooltip={{$:/language/Buttons/Clone/Hint}} aria-label={{$:/language/Buttons/Clone/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/clone-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Clone/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/close-others": { "title": "$:/core/ui/Buttons/close-others", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/close-others-button}} {{$:/language/Buttons/CloseOthers/Caption}}", "description": "{{$:/language/Buttons/CloseOthers/Hint}}", "text": "<$button message=\"tm-close-other-tiddlers\" param=<<currentTiddler>> tooltip={{$:/language/Buttons/CloseOthers/Hint}} aria-label={{$:/language/Buttons/CloseOthers/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/close-others-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/CloseOthers/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/close": { "title": "$:/core/ui/Buttons/close", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/close-button}} {{$:/language/Buttons/Close/Caption}}", "description": "{{$:/language/Buttons/Close/Hint}}", "text": "<$button message=\"tm-close-tiddler\" tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/close-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Close/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/edit": { "title": "$:/core/ui/Buttons/edit", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/edit-button}} {{$:/language/Buttons/Edit/Caption}}", "description": "{{$:/language/Buttons/Edit/Hint}}", "text": "<$button message=\"tm-edit-tiddler\" tooltip={{$:/language/Buttons/Edit/Hint}} aria-label={{$:/language/Buttons/Edit/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/edit-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Edit/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/export-tiddler": { "title": "$:/core/ui/Buttons/export-tiddler", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/export-button}} {{$:/language/Buttons/ExportTiddler/Caption}}", "description": "{{$:/language/Buttons/ExportTiddler/Hint}}", "text": "\\define makeExportFilter()\n[[$(currentTiddler)$]]\n\\end\n<$macrocall $name=\"exportButton\" exportFilter=<<makeExportFilter>> lingoBase=\"$:/language/Buttons/ExportTiddler/\" baseFilename=<<currentTiddler>>/>" }, "$:/core/ui/Buttons/fold-bar": { "title": "$:/core/ui/Buttons/fold-bar", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/chevron-up}} {{$:/language/Buttons/Fold/FoldBar/Caption}}", "description": "{{$:/language/Buttons/Fold/FoldBar/Hint}}", "text": "<!-- This dummy toolbar button is here to allow visibility of the fold-bar to be controlled as if it were a toolbar button -->" }, "$:/core/ui/Buttons/fold-others": { "title": "$:/core/ui/Buttons/fold-others", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/fold-others-button}} {{$:/language/Buttons/FoldOthers/Caption}}", "description": "{{$:/language/Buttons/FoldOthers/Hint}}", "text": "<$button tooltip={{$:/language/Buttons/FoldOthers/Hint}} aria-label={{$:/language/Buttons/FoldOthers/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-other-tiddlers\" $param=<<currentTiddler>> foldedStatePrefix=\"$:/state/folded/\"/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\" variable=\"listItem\">\n{{$:/core/images/fold-others-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/FoldOthers/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/fold": { "title": "$:/core/ui/Buttons/fold", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/fold-button}} {{$:/language/Buttons/Fold/Caption}}", "description": "{{$:/language/Buttons/Fold/Hint}}", "text": "<$reveal type=\"nomatch\" state=<<folded-state>> text=\"hide\" default=\"show\"><$button tooltip={{$:/language/Buttons/Fold/Hint}} aria-label={{$:/language/Buttons/Fold/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\" variable=\"listItem\">\n{{$:/core/images/fold-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text={{$:/language/Buttons/Fold/Caption}}/>\n</span>\n</$list>\n</$button></$reveal><$reveal type=\"match\" state=<<folded-state>> text=\"hide\" default=\"show\"><$button tooltip={{$:/language/Buttons/Unfold/Hint}} aria-label={{$:/language/Buttons/Unfold/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-fold-tiddler\" $param=<<currentTiddler>> foldedState=<<folded-state>>/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\" variable=\"listItem\">\n{{$:/core/images/unfold-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\">\n<$text text={{$:/language/Buttons/Unfold/Caption}}/>\n</span>\n</$list>\n</$button></$reveal>" }, "$:/core/ui/Buttons/info": { "title": "$:/core/ui/Buttons/info", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/info-button}} {{$:/language/Buttons/Info/Caption}}", "description": "{{$:/language/Buttons/Info/Hint}}", "text": "\\define button-content()\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/info-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Info/Caption}}/></span>\n</$list>\n\\end\n<$reveal state=\"$:/config/TiddlerInfo/Mode\" type=\"match\" text=\"popup\">\n<$button popup=<<tiddlerInfoState>> tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$macrocall $name=\"button-content\" mode=\"inline\"/>\n</$button>\n</$reveal>\n<$reveal state=\"$:/config/TiddlerInfo/Mode\" type=\"match\" text=\"sticky\">\n<$reveal state=<<tiddlerInfoState>> type=\"match\" text=\"\" default=\"\">\n<$button set=<<tiddlerInfoState>> setTo=\"yes\" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$macrocall $name=\"button-content\" mode=\"inline\"/>\n</$button>\n</$reveal>\n<$reveal state=<<tiddlerInfoState>> type=\"nomatch\" text=\"\" default=\"\">\n<$button set=<<tiddlerInfoState>> setTo=\"\" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$macrocall $name=\"button-content\" mode=\"inline\"/>\n</$button>\n</$reveal>\n</$reveal>" }, "$:/core/ui/Buttons/more-tiddler-actions": { "title": "$:/core/ui/Buttons/more-tiddler-actions", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/down-arrow}} {{$:/language/Buttons/More/Caption}}", "description": "{{$:/language/Buttons/More/Hint}}", "text": "\\define config-title()\n$:/config/ViewToolbarButtons/Visibility/$(listItem)$\n\\end\n<$button popup=<<qualify \"$:/state/popup/more\">> tooltip={{$:/language/Buttons/More/Hint}} aria-label={{$:/language/Buttons/More/Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/down-arrow}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/More/Caption}}/></span>\n</$list>\n</$button><$reveal state=<<qualify \"$:/state/popup/more\">> type=\"popup\" position=\"below\" animate=\"yes\">\n\n<div class=\"tc-drop-down\">\n\n<$set name=\"tv-config-toolbar-icons\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-text\" value=\"yes\">\n\n<$set name=\"tv-config-toolbar-class\" value=\"tc-btn-invisible\">\n\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]] -[[$:/core/ui/Buttons/more-tiddler-actions]]\" variable=\"listItem\">\n\n<$reveal type=\"match\" state=<<config-title>> text=\"hide\">\n\n<$transclude tiddler=<<listItem>> mode=\"inline\"/>\n\n</$reveal>\n\n</$list>\n\n</$set>\n\n</$set>\n\n</$set>\n\n</div>\n\n</$reveal>" }, "$:/core/ui/Buttons/new-here": { "title": "$:/core/ui/Buttons/new-here", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/new-here-button}} {{$:/language/Buttons/NewHere/Caption}}", "description": "{{$:/language/Buttons/NewHere/Hint}}", "text": "\\define newHereButtonTags()\n[[$(currentTiddler)$]]\n\\end\n\\define newHereButton()\n<$button tooltip={{$:/language/Buttons/NewHere/Hint}} aria-label={{$:/language/Buttons/NewHere/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-new-tiddler\" tags=<<newHereButtonTags>>/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/new-here-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewHere/Caption}}/></span>\n</$list>\n</$button>\n\\end\n<<newHereButton>>" }, "$:/core/ui/Buttons/new-journal-here": { "title": "$:/core/ui/Buttons/new-journal-here", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/new-journal-button}} {{$:/language/Buttons/NewJournalHere/Caption}}", "description": "{{$:/language/Buttons/NewJournalHere/Hint}}", "text": "\\define journalButtonTags()\n[[$(currentTiddlerTag)$]] $(journalTags)$\n\\end\n\\define journalButton()\n<$button tooltip={{$:/language/Buttons/NewJournalHere/Hint}} aria-label={{$:/language/Buttons/NewJournalHere/Caption}} class=<<tv-config-toolbar-class>>>\n<$action-sendmessage $message=\"tm-new-tiddler\" title=<<now \"$(journalTitleTemplate)$\">> tags=<<journalButtonTags>>/>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/new-journal-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/NewJournalHere/Caption}}/></span>\n</$list>\n</$button>\n\\end\n<$set name=\"journalTitleTemplate\" value={{$:/config/NewJournal/Title}}>\n<$set name=\"journalTags\" value={{$:/config/NewJournal/Tags}}>\n<$set name=\"currentTiddlerTag\" value=<<currentTiddler>>>\n<<journalButton>>\n</$set></$set></$set>" }, "$:/core/ui/Buttons/open-window": { "title": "$:/core/ui/Buttons/open-window", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/open-window}} {{$:/language/Buttons/OpenWindow/Caption}}", "description": "{{$:/language/Buttons/OpenWindow/Hint}}", "text": "<$button message=\"tm-open-window\" tooltip={{$:/language/Buttons/OpenWindow/Hint}} aria-label={{$:/language/Buttons/OpenWindow/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/open-window}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/OpenWindow/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/permalink": { "title": "$:/core/ui/Buttons/permalink", "tags": "$:/tags/ViewToolbar", "caption": "{{$:/core/images/permalink-button}} {{$:/language/Buttons/Permalink/Caption}}", "description": "{{$:/language/Buttons/Permalink/Hint}}", "text": "<$button message=\"tm-permalink\" tooltip={{$:/language/Buttons/Permalink/Hint}} aria-label={{$:/language/Buttons/Permalink/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/permalink-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Permalink/Caption}}/></span>\n</$list>\n</$button>" }, "$:/core/ui/Buttons/permaview": { "title": "$:/core/ui/Buttons/permaview", "tags": "$:/tags/ViewToolbar $:/tags/PageControls", "caption": "{{$:/core/images/permaview-button}} {{$:/language/Buttons/Permaview/Caption}}", "description": "{{$:/language/Buttons/Permaview/Hint}}", "text": "<$button message=\"tm-permaview\" tooltip={{$:/language/Buttons/Permaview/Hint}} aria-label={{$:/language/Buttons/Permaview/Caption}} class=<<tv-config-toolbar-class>>>\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/permaview-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$:/language/Buttons/Permaview/Caption}}/></span>\n</$list>\n</$button>" }, "$:/DefaultTiddlers": { "title": "$:/DefaultTiddlers", "text": "GettingStarted\n" }, "$:/temp/advancedsearch": { "title": "$:/temp/advancedsearch", "text": "" }, "$:/snippets/allfields": { "title": "$:/snippets/allfields", "text": "\\define renderfield(title)\n<tr class=\"tc-view-field\"><td class=\"tc-view-field-name\">''$title$'':</td><td class=\"tc-view-field-value\">//{{$:/language/Docs/Fields/$title$}}//</td></tr>\n\\end\n<table class=\"tc-view-field-table\"><tbody><$list filter=\"[fields[]sort[title]]\" variable=\"listItem\"><$macrocall $name=\"renderfield\" title=<<listItem>>/></$list>\n</tbody></table>\n" }, "$:/config/AnimationDuration": { "title": "$:/config/AnimationDuration", "text": "400" }, "$:/config/AutoSave": { "title": "$:/config/AutoSave", "text": "yes" }, "$:/config/BitmapEditor/Colour": { "title": "$:/config/BitmapEditor/Colour", "text": "#444" }, "$:/config/BitmapEditor/ImageSizes": { "title": "$:/config/BitmapEditor/ImageSizes", "text": "[[62px 100px]] [[100px 62px]] [[124px 200px]] [[200px 124px]] [[248px 400px]] [[371px 600px]] [[400px 248px]] [[556px 900px]] [[600px 371px]] [[742px 1200px]] [[900px 556px]] [[1200px 742px]]" }, "$:/config/BitmapEditor/LineWidth": { "title": "$:/config/BitmapEditor/LineWidth", "text": "3px" }, "$:/config/BitmapEditor/LineWidths": { "title": "$:/config/BitmapEditor/LineWidths", "text": "0.25px 0.5px 1px 2px 3px 4px 6px 8px 10px 16px 20px 28px 40px 56px 80px" }, "$:/config/BitmapEditor/Opacities": { "title": "$:/config/BitmapEditor/Opacities", "text": "0.01 0.025 0.05 0.075 0.1 0.15 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0" }, "$:/config/BitmapEditor/Opacity": { "title": "$:/config/BitmapEditor/Opacity", "text": "1.0" }, "$:/config/DefaultSidebarTab": { "title": "$:/config/DefaultSidebarTab", "text": "$:/core/ui/SideBar/Open" }, "$:/config/DownloadSaver/AutoSave": { "title": "$:/config/DownloadSaver/AutoSave", "text": "no" }, "$:/config/Drafts/TypingTimeout": { "title": "$:/config/Drafts/TypingTimeout", "text": "400" }, "$:/config/EditTemplateFields/Visibility/title": { "title": "$:/config/EditTemplateFields/Visibility/title", "text": "hide" }, "$:/config/EditTemplateFields/Visibility/tags": { "title": "$:/config/EditTemplateFields/Visibility/tags", "text": "hide" }, "$:/config/EditTemplateFields/Visibility/text": { "title": "$:/config/EditTemplateFields/Visibility/text", "text": "hide" }, "$:/config/EditTemplateFields/Visibility/creator": { "title": "$:/config/EditTemplateFields/Visibility/creator", "text": "hide" }, "$:/config/EditTemplateFields/Visibility/created": { "title": "$:/config/EditTemplateFields/Visibility/created", "text": "hide" }, "$:/config/EditTemplateFields/Visibility/modified": { "title": "$:/config/EditTemplateFields/Visibility/modified", "text": "hide" }, "$:/config/EditTemplateFields/Visibility/modifier": { "title": "$:/config/EditTemplateFields/Visibility/modifier", "text": "hide" }, "$:/config/EditTemplateFields/Visibility/type": { "title": "$:/config/EditTemplateFields/Visibility/type", "text": "hide" }, "$:/config/EditTemplateFields/Visibility/draft.title": { "title": "$:/config/EditTemplateFields/Visibility/draft.title", "text": "hide" }, "$:/config/EditTemplateFields/Visibility/draft.of": { "title": "$:/config/EditTemplateFields/Visibility/draft.of", "text": "hide" }, "$:/config/EditTemplateFields/Visibility/revision": { "title": "$:/config/EditTemplateFields/Visibility/revision", "text": "hide" }, "$:/config/EditTemplateFields/Visibility/bag": { "title": "$:/config/EditTemplateFields/Visibility/bag", "text": "hide" }, "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-4": { "title": "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-4", "text": "hide" }, "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-5": { "title": "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-5", "text": "hide" }, "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-6": { "title": "$:/config/EditorToolbarButtons/Visibility/$:/core/ui/EditorToolbar/heading-6", "text": "hide" }, "$:/config/EditorTypeMappings/image/gif": { "title": "$:/config/EditorTypeMappings/image/gif", "text": "bitmap" }, "$:/config/EditorTypeMappings/image/jpeg": { "title": "$:/config/EditorTypeMappings/image/jpeg", "text": "bitmap" }, "$:/config/EditorTypeMappings/image/jpg": { "title": "$:/config/EditorTypeMappings/image/jpg", "text": "bitmap" }, "$:/config/EditorTypeMappings/image/png": { "title": "$:/config/EditorTypeMappings/image/png", "text": "bitmap" }, "$:/config/EditorTypeMappings/image/x-icon": { "title": "$:/config/EditorTypeMappings/image/x-icon", "text": "bitmap" }, "$:/config/EditorTypeMappings/text/vnd.tiddlywiki": { "title": "$:/config/EditorTypeMappings/text/vnd.tiddlywiki", "text": "text" }, "$:/config/Manager/Show": { "title": "$:/config/Manager/Show", "text": "tiddlers" }, "$:/config/Manager/Filter": { "title": "$:/config/Manager/Filter", "text": "" }, "$:/config/Manager/Order": { "title": "$:/config/Manager/Order", "text": "forward" }, "$:/config/Manager/Sort": { "title": "$:/config/Manager/Sort", "text": "title" }, "$:/config/Manager/System": { "title": "$:/config/Manager/System", "text": "system" }, "$:/config/Manager/Tag": { "title": "$:/config/Manager/Tag", "text": "" }, "$:/state/popup/manager/item/$:/Manager/ItemMain/RawText": { "title": "$:/state/popup/manager/item/$:/Manager/ItemMain/RawText", "text": "hide" }, "$:/config/MissingLinks": { "title": "$:/config/MissingLinks", "text": "yes" }, "$:/config/Navigation/UpdateAddressBar": { "title": "$:/config/Navigation/UpdateAddressBar", "text": "no" }, "$:/config/Navigation/UpdateHistory": { "title": "$:/config/Navigation/UpdateHistory", "text": "no" }, "$:/config/OfficialPluginLibrary": { "title": "$:/config/OfficialPluginLibrary", "tags": "$:/tags/PluginLibrary", "url": "http://tiddlywiki.com/library/v5.1.14/index.html", "caption": "{{$:/language/OfficialPluginLibrary}}", "text": "{{$:/language/OfficialPluginLibrary/Hint}}\n" }, "$:/config/Navigation/openLinkFromInsideRiver": { "title": "$:/config/Navigation/openLinkFromInsideRiver", "text": "below" }, "$:/config/Navigation/openLinkFromOutsideRiver": { "title": "$:/config/Navigation/openLinkFromOutsideRiver", "text": "top" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/advanced-search": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/advanced-search", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/close-all": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/close-all", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/encryption": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/encryption", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/export-page": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/export-page", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/fold-all": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/fold-all", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/full-screen": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/full-screen", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/refresh": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/refresh", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/import": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/import", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/language": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/language", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/tag-manager": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/tag-manager", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/manager": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/manager", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/more-page-actions": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/more-page-actions", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-journal": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-journal", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-image": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/new-image", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/palette": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/palette", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/permaview": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/permaview", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/print": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/print", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/storyview": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/storyview", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/timestamp": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/timestamp", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/theme": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/theme", "text": "hide" }, "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/unfold-all": { "title": "$:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/unfold-all", "text": "hide" }, "$:/config/Performance/Instrumentation": { "title": "$:/config/Performance/Instrumentation", "text": "no" }, "$:/config/SaveWikiButton/Template": { "title": "$:/config/SaveWikiButton/Template", "text": "$:/core/save/all" }, "$:/config/SaverFilter": { "title": "$:/config/SaverFilter", "text": "[all[]] -[[$:/HistoryList]] -[[$:/StoryList]] -[[$:/Import]] -[[$:/isEncrypted]] -[[$:/UploadName]] -[prefix[$:/state/]] -[prefix[$:/temp/]]" }, "$:/config/Search/AutoFocus": { "title": "$:/config/Search/AutoFocus", "text": "true" }, "$:/config/Search/MinLength": { "title": "$:/config/Search/MinLength", "text": "3" }, "$:/config/SearchResults/Default": { "title": "$:/config/SearchResults/Default", "text": "$:/core/ui/DefaultSearchResultList" }, "$:/config/ShortcutInfo/bold": { "title": "$:/config/ShortcutInfo/bold", "text": "{{$:/language/Buttons/Bold/Hint}}" }, "$:/config/ShortcutInfo/cancel-edit-tiddler": { "title": "$:/config/ShortcutInfo/cancel-edit-tiddler", "text": "{{$:/language/Buttons/Cancel/Hint}}" }, "$:/config/ShortcutInfo/excise": { "title": "$:/config/ShortcutInfo/excise", "text": "{{$:/language/Buttons/Excise/Hint}}" }, "$:/config/ShortcutInfo/heading-1": { "title": "$:/config/ShortcutInfo/heading-1", "text": "{{$:/language/Buttons/Heading1/Hint}}" }, "$:/config/ShortcutInfo/heading-2": { "title": "$:/config/ShortcutInfo/heading-2", "text": "{{$:/language/Buttons/Heading2/Hint}}" }, "$:/config/ShortcutInfo/heading-3": { "title": "$:/config/ShortcutInfo/heading-3", "text": "{{$:/language/Buttons/Heading3/Hint}}" }, "$:/config/ShortcutInfo/heading-4": { "title": "$:/config/ShortcutInfo/heading-4", "text": "{{$:/language/Buttons/Heading4/Hint}}" }, "$:/config/ShortcutInfo/heading-5": { "title": "$:/config/ShortcutInfo/heading-5", "text": "{{$:/language/Buttons/Heading5/Hint}}" }, "$:/config/ShortcutInfo/heading-6": { "title": "$:/config/ShortcutInfo/heading-6", "text": "{{$:/language/Buttons/Heading6/Hint}}" }, "$:/config/ShortcutInfo/italic": { "title": "$:/config/ShortcutInfo/italic", "text": "{{$:/language/Buttons/Italic/Hint}}" }, "$:/config/ShortcutInfo/link": { "title": "$:/config/ShortcutInfo/link", "text": "{{$:/language/Buttons/Link/Hint}}" }, "$:/config/ShortcutInfo/list-bullet": { "title": "$:/config/ShortcutInfo/list-bullet", "text": "{{$:/language/Buttons/ListBullet/Hint}}" }, "$:/config/ShortcutInfo/list-number": { "title": "$:/config/ShortcutInfo/list-number", "text": "{{$:/language/Buttons/ListNumber/Hint}}" }, "$:/config/ShortcutInfo/mono-block": { "title": "$:/config/ShortcutInfo/mono-block", "text": "{{$:/language/Buttons/MonoBlock/Hint}}" }, "$:/config/ShortcutInfo/mono-line": { "title": "$:/config/ShortcutInfo/mono-line", "text": "{{$:/language/Buttons/MonoLine/Hint}}" }, "$:/config/ShortcutInfo/picture": { "title": "$:/config/ShortcutInfo/picture", "text": "{{$:/language/Buttons/Picture/Hint}}" }, "$:/config/ShortcutInfo/preview": { "title": "$:/config/ShortcutInfo/preview", "text": "{{$:/language/Buttons/Preview/Hint}}" }, "$:/config/ShortcutInfo/quote": { "title": "$:/config/ShortcutInfo/quote", "text": "{{$:/language/Buttons/Quote/Hint}}" }, "$:/config/ShortcutInfo/save-tiddler": { "title": "$:/config/ShortcutInfo/save-tiddler", "text": "{{$:/language/Buttons/Save/Hint}}" }, "$:/config/ShortcutInfo/stamp": { "title": "$:/config/ShortcutInfo/stamp", "text": "{{$:/language/Buttons/Stamp/Hint}}" }, "$:/config/ShortcutInfo/strikethrough": { "title": "$:/config/ShortcutInfo/strikethrough", "text": "{{$:/language/Buttons/Strikethrough/Hint}}" }, "$:/config/ShortcutInfo/subscript": { "title": "$:/config/ShortcutInfo/subscript", "text": "{{$:/language/Buttons/Subscript/Hint}}" }, "$:/config/ShortcutInfo/superscript": { "title": "$:/config/ShortcutInfo/superscript", "text": "{{$:/language/Buttons/Superscript/Hint}}" }, "$:/config/ShortcutInfo/underline": { "title": "$:/config/ShortcutInfo/underline", "text": "{{$:/language/Buttons/Underline/Hint}}" }, "$:/config/SyncFilter": { "title": "$:/config/SyncFilter", "text": "[is[tiddler]] -[[$:/HistoryList]] -[[$:/Import]] -[[$:/isEncrypted]] -[prefix[$:/status/]] -[prefix[$:/state/]] -[prefix[$:/temp/]]" }, "$:/config/TextEditor/EditorHeight/Height": { "title": "$:/config/TextEditor/EditorHeight/Height", "text": "400px" }, "$:/config/TextEditor/EditorHeight/Mode": { "title": "$:/config/TextEditor/EditorHeight/Mode", "text": "auto" }, "$:/config/TiddlerInfo/Default": { "title": "$:/config/TiddlerInfo/Default", "text": "$:/core/ui/TiddlerInfo/Fields" }, "$:/config/TiddlerInfo/Mode": { "title": "$:/config/TiddlerInfo/Mode", "text": "popup" }, "$:/config/Tiddlers/TitleLinks": { "title": "$:/config/Tiddlers/TitleLinks", "text": "no" }, "$:/config/Toolbar/ButtonClass": { "title": "$:/config/Toolbar/ButtonClass", "text": "tc-btn-invisible" }, "$:/config/Toolbar/Icons": { "title": "$:/config/Toolbar/Icons", "text": "yes" }, "$:/config/Toolbar/Text": { "title": "$:/config/Toolbar/Text", "text": "no" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/clone": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/clone", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/close-others": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/close-others", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/export-tiddler": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/export-tiddler", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/info": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/info", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/more-tiddler-actions": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/more-tiddler-actions", "text": "show" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-here": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-here", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-journal-here": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/new-journal-here", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/open-window": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/open-window", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permalink": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permalink", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permaview": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/permaview", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/delete": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/delete", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar", "text": "hide" }, "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-others": { "title": "$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-others", "text": "hide" }, "$:/config/shortcuts-mac/bold": { "title": "$:/config/shortcuts-mac/bold", "text": "meta-B" }, "$:/config/shortcuts-mac/italic": { "title": "$:/config/shortcuts-mac/italic", "text": "meta-I" }, "$:/config/shortcuts-mac/underline": { "title": "$:/config/shortcuts-mac/underline", "text": "meta-U" }, "$:/config/shortcuts-not-mac/bold": { "title": "$:/config/shortcuts-not-mac/bold", "text": "ctrl-B" }, "$:/config/shortcuts-not-mac/italic": { "title": "$:/config/shortcuts-not-mac/italic", "text": "ctrl-I" }, "$:/config/shortcuts-not-mac/underline": { "title": "$:/config/shortcuts-not-mac/underline", "text": "ctrl-U" }, "$:/config/shortcuts/cancel-edit-tiddler": { "title": "$:/config/shortcuts/cancel-edit-tiddler", "text": "escape" }, "$:/config/shortcuts/excise": { "title": "$:/config/shortcuts/excise", "text": "ctrl-E" }, "$:/config/shortcuts/heading-1": { "title": "$:/config/shortcuts/heading-1", "text": "ctrl-1" }, "$:/config/shortcuts/heading-2": { "title": "$:/config/shortcuts/heading-2", "text": "ctrl-2" }, "$:/config/shortcuts/heading-3": { "title": "$:/config/shortcuts/heading-3", "text": "ctrl-3" }, "$:/config/shortcuts/heading-4": { "title": "$:/config/shortcuts/heading-4", "text": "ctrl-4" }, "$:/config/shortcuts/heading-5": { "title": "$:/config/shortcuts/heading-5", "text": "ctrl-5" }, "$:/config/shortcuts/heading-6": { "title": "$:/config/shortcuts/heading-6", "text": "ctrl-6" }, "$:/config/shortcuts/link": { "title": "$:/config/shortcuts/link", "text": "ctrl-L" }, "$:/config/shortcuts/list-bullet": { "title": "$:/config/shortcuts/list-bullet", "text": "ctrl-shift-L" }, "$:/config/shortcuts/list-number": { "title": "$:/config/shortcuts/list-number", "text": "ctrl-shift-N" }, "$:/config/shortcuts/mono-block": { "title": "$:/config/shortcuts/mono-block", "text": "ctrl-shift-M" }, "$:/config/shortcuts/mono-line": { "title": "$:/config/shortcuts/mono-line", "text": "ctrl-M" }, "$:/config/shortcuts/picture": { "title": "$:/config/shortcuts/picture", "text": "ctrl-shift-I" }, "$:/config/shortcuts/preview": { "title": "$:/config/shortcuts/preview", "text": "alt-P" }, "$:/config/shortcuts/quote": { "title": "$:/config/shortcuts/quote", "text": "ctrl-Q" }, "$:/config/shortcuts/save-tiddler": { "title": "$:/config/shortcuts/save-tiddler", "text": "ctrl+enter" }, "$:/config/shortcuts/stamp": { "title": "$:/config/shortcuts/stamp", "text": "ctrl-S" }, "$:/config/shortcuts/strikethrough": { "title": "$:/config/shortcuts/strikethrough", "text": "ctrl-T" }, "$:/config/shortcuts/subscript": { "title": "$:/config/shortcuts/subscript", "text": "ctrl-shift-B" }, "$:/config/shortcuts/superscript": { "title": "$:/config/shortcuts/superscript", "text": "ctrl-shift-P" }, "$:/config/WikiParserRules/Inline/wikilink": { "title": "$:/config/WikiParserRules/Inline/wikilink", "text": "enable" }, "$:/snippets/currpalettepreview": { "title": "$:/snippets/currpalettepreview", "text": "\\define swatchStyle()\nbackground-color: $(swatchColour)$;\n\\end\n\\define swatch(colour)\n<$set name=\"swatchColour\" value={{##$colour$}}>\n<div class=\"tc-swatch\" style=<<swatchStyle>>/>\n</$set>\n\\end\n<div class=\"tc-swatches-horiz\">\n<<swatch foreground>>\n<<swatch background>>\n<<swatch muted-foreground>>\n<<swatch primary>>\n<<swatch page-background>>\n<<swatch tab-background>>\n<<swatch tiddler-info-background>>\n</div>\n" }, "$:/snippets/download-wiki-button": { "title": "$:/snippets/download-wiki-button", "text": "\\define lingo-base() $:/language/ControlPanel/Tools/Download/\n<$button class=\"tc-btn-big-green\">\n<$action-sendmessage $message=\"tm-download-file\" $param=\"$:/core/save/all\" filename=\"index.html\"/>\n<<lingo Full/Caption>> {{$:/core/images/save-button}}\n</$button>" }, "$:/language": { "title": "$:/language", "text": "$:/languages/en-GB" }, "$:/snippets/languageswitcher": { "title": "$:/snippets/languageswitcher", "text": "{{$:/language/ControlPanel/Basics/Language/Prompt}} <$select tiddler=\"$:/language\">\n<$list filter=\"[[$:/languages/en-GB]] [plugin-type[language]sort[description]]\">\n<option value=<<currentTiddler>>><$view field=\"description\"><$view field=\"name\"><$view field=\"title\"/></$view></$view></option>\n</$list>\n</$select>" }, "$:/core/macros/CSS": { "title": "$:/core/macros/CSS", "tags": "$:/tags/Macro", "text": "\\define colour(name)\n<$transclude tiddler={{$:/palette}} index=\"$name$\"><$transclude tiddler=\"$:/palettes/Vanilla\" index=\"$name$\"/></$transclude>\n\\end\n\n\\define color(name)\n<<colour $name$>>\n\\end\n\n\\define box-shadow(shadow)\n``\n -webkit-box-shadow: $shadow$;\n -moz-box-shadow: $shadow$;\n box-shadow: $shadow$;\n``\n\\end\n\n\\define filter(filter)\n``\n -webkit-filter: $filter$;\n -moz-filter: $filter$;\n filter: $filter$;\n``\n\\end\n\n\\define transition(transition)\n``\n -webkit-transition: $transition$;\n -moz-transition: $transition$;\n transition: $transition$;\n``\n\\end\n\n\\define transform-origin(origin)\n``\n -webkit-transform-origin: $origin$;\n -moz-transform-origin: $origin$;\n transform-origin: $origin$;\n``\n\\end\n\n\\define background-linear-gradient(gradient)\n``\nbackground-image: linear-gradient($gradient$);\nbackground-image: -o-linear-gradient($gradient$);\nbackground-image: -moz-linear-gradient($gradient$);\nbackground-image: -webkit-linear-gradient($gradient$);\nbackground-image: -ms-linear-gradient($gradient$);\n``\n\\end\n\n\\define column-count(columns)\n``\n-moz-column-count: $columns$;\n-webkit-column-count: $columns$;\ncolumn-count: $columns$;\n``\n\\end\n\n\\define datauri(title)\n<$macrocall $name=\"makedatauri\" type={{$title$!!type}} text={{$title$}}/>\n\\end\n\n\\define if-sidebar(text)\n<$reveal state=\"$:/state/sidebar\" type=\"match\" text=\"yes\" default=\"yes\">$text$</$reveal>\n\\end\n\n\\define if-no-sidebar(text)\n<$reveal state=\"$:/state/sidebar\" type=\"nomatch\" text=\"yes\" default=\"yes\">$text$</$reveal>\n\\end\n" }, "$:/core/macros/colour-picker": { "title": "$:/core/macros/colour-picker", "tags": "$:/tags/Macro", "text": "\\define colour-picker-update-recent()\n<$action-listops\n\t$tiddler=\"$:/config/ColourPicker/Recent\"\n\t$subfilter=\"$(colour-picker-value)$ [list[$:/config/ColourPicker/Recent]remove[$(colour-picker-value)$]] +[limit[8]]\"\n/>\n\\end\n\n\\define colour-picker-inner(actions)\n<$button tag=\"a\" tooltip=\"\"\"$(colour-picker-value)$\"\"\">\n\n$(colour-picker-update-recent)$\n\n$actions$\n\n<div style=\"background-color: $(colour-picker-value)$; width: 100%; height: 100%; border-radius: 50%;\"/>\n\n</$button>\n\\end\n\n\\define colour-picker-recent-inner(actions)\n<$set name=\"colour-picker-value\" value=\"$(recentColour)$\">\n<$macrocall $name=\"colour-picker-inner\" actions=\"\"\"$actions$\"\"\"/>\n</$set>\n\\end\n\n\\define colour-picker-recent(actions)\n{{$:/language/ColourPicker/Recent}} <$list filter=\"[list[$:/config/ColourPicker/Recent]]\" variable=\"recentColour\">\n<$macrocall $name=\"colour-picker-recent-inner\" actions=\"\"\"$actions$\"\"\"/></$list>\n\\end\n\n\\define colour-picker(actions)\n<div class=\"tc-colour-chooser\">\n\n<$macrocall $name=\"colour-picker-recent\" actions=\"\"\"$actions$\"\"\"/>\n\n---\n\n<$list filter=\"LightPink Pink Crimson LavenderBlush PaleVioletRed HotPink DeepPink MediumVioletRed Orchid Thistle Plum Violet Magenta Fuchsia DarkMagenta Purple MediumOrchid DarkViolet DarkOrchid Indigo BlueViolet MediumPurple MediumSlateBlue SlateBlue DarkSlateBlue Lavender GhostWhite Blue MediumBlue MidnightBlue DarkBlue Navy RoyalBlue CornflowerBlue LightSteelBlue LightSlateGrey SlateGrey DodgerBlue AliceBlue SteelBlue LightSkyBlue SkyBlue DeepSkyBlue LightBlue PowderBlue CadetBlue Azure LightCyan PaleTurquoise Cyan Aqua DarkTurquoise DarkSlateGrey DarkCyan Teal MediumTurquoise LightSeaGreen Turquoise Aquamarine MediumAquamarine MediumSpringGreen MintCream SpringGreen MediumSeaGreen SeaGreen Honeydew LightGreen PaleGreen DarkSeaGreen LimeGreen Lime ForestGreen Green DarkGreen Chartreuse LawnGreen GreenYellow DarkOliveGreen YellowGreen OliveDrab Beige LightGoldenrodYellow Ivory LightYellow Yellow Olive DarkKhaki LemonChiffon PaleGoldenrod Khaki Gold Cornsilk Goldenrod DarkGoldenrod FloralWhite OldLace Wheat Moccasin Orange PapayaWhip BlanchedAlmond NavajoWhite AntiqueWhite Tan BurlyWood Bisque DarkOrange Linen Peru PeachPuff SandyBrown Chocolate SaddleBrown Seashell Sienna LightSalmon Coral OrangeRed DarkSalmon Tomato MistyRose Salmon Snow LightCoral RosyBrown IndianRed Red Brown FireBrick DarkRed Maroon White WhiteSmoke Gainsboro LightGrey Silver DarkGrey Grey DimGrey Black\" variable=\"colour-picker-value\">\n<$macrocall $name=\"colour-picker-inner\" actions=\"\"\"$actions$\"\"\"/>\n</$list>\n\n---\n\n<$edit-text tiddler=\"$:/config/ColourPicker/New\" tag=\"input\" default=\"\" placeholder=\"\"/> \n<$edit-text tiddler=\"$:/config/ColourPicker/New\" type=\"color\" tag=\"input\"/>\n<$set name=\"colour-picker-value\" value={{$:/config/ColourPicker/New}}>\n<$macrocall $name=\"colour-picker-inner\" actions=\"\"\"$actions$\"\"\"/>\n</$set>\n\n</div>\n\n\\end\n" }, "$:/core/macros/export": { "title": "$:/core/macros/export", "tags": "$:/tags/Macro", "text": "\\define exportButtonFilename(baseFilename)\n$baseFilename$$(extension)$\n\\end\n\n\\define exportButton(exportFilter:\"[!is[system]sort[title]]\",lingoBase,baseFilename:\"tiddlers\")\n<span class=\"tc-popup-keep\">\n<$button popup=<<qualify \"$:/state/popup/export\">> tooltip={{$lingoBase$Hint}} aria-label={{$lingoBase$Caption}} class=<<tv-config-toolbar-class>> selectedClass=\"tc-selected\">\n<$list filter=\"[<tv-config-toolbar-icons>prefix[yes]]\">\n{{$:/core/images/export-button}}\n</$list>\n<$list filter=\"[<tv-config-toolbar-text>prefix[yes]]\">\n<span class=\"tc-btn-text\"><$text text={{$lingoBase$Caption}}/></span>\n</$list>\n</$button>\n</span>\n<$reveal state=<<qualify \"$:/state/popup/export\">> type=\"popup\" position=\"below\" animate=\"yes\">\n<div class=\"tc-drop-down\">\n<$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Exporter]]\">\n<$set name=\"extension\" value={{!!extension}}>\n<$button class=\"tc-btn-invisible\">\n<$action-sendmessage $message=\"tm-download-file\" $param=<<currentTiddler>> exportFilter=\"\"\"$exportFilter$\"\"\" filename=<<exportButtonFilename \"\"\"$baseFilename$\"\"\">>/>\n<$action-deletetiddler $tiddler=<<qualify \"$:/state/popup/export\">>/>\n<$transclude field=\"description\"/>\n</$button>\n</$set>\n</$list>\n</div>\n</$reveal>\n\\end\n" }, "$:/core/macros/image-picker": { "title": "$:/core/macros/image-picker", "tags": "$:/tags/Macro", "text": "\\define image-picker-thumbnail(actions)\n<$button tag=\"a\" tooltip=\"\"\"$(imageTitle)$\"\"\">\n$actions$\n<$transclude tiddler=<<imageTitle>>/>\n</$button>\n\\end\n\n\\define image-picker-list(filter,actions)\n<$list filter=\"\"\"$filter$\"\"\" variable=\"imageTitle\">\n<$macrocall $name=\"image-picker-thumbnail\" actions=\"\"\"$actions$\"\"\"/>\n</$list>\n\\end\n\n\\define image-picker(actions,filter:\"[all[shadows+tiddlers]is[image]] -[type[application/pdf]] +[!has[draft.of]sort[title]]\")\n<div class=\"tc-image-chooser\">\n<$vars state-system=<<qualify \"$:/state/image-picker/system\">>>\n<$checkbox tiddler=<<state-system>> field=\"text\" checked=\"show\" unchecked=\"hide\" default=\"hide\">\n{{$:/language/SystemTiddlers/Include/Prompt}}\n</$checkbox>\n<$reveal state=<<state-system>> type=\"match\" text=\"hide\" default=\"hide\" tag=\"div\">\n<$macrocall $name=\"image-picker-list\" filter=\"\"\"$filter$ +[!is[system]]\"\"\" actions=\"\"\"$actions$\"\"\"/>\n</$reveal>\n<$reveal state=<<state-system>> type=\"nomatch\" text=\"hide\" default=\"hide\" tag=\"div\">\n<$macrocall $name=\"image-picker-list\" filter=\"\"\"$filter$\"\"\" actions=\"\"\"$actions$\"\"\"/>\n</$reveal>\n</$vars>\n</div>\n\\end\n\n\\define image-picker-include-tagged-images(actions)\n<$macrocall $name=\"image-picker\" filter=\"[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[!has[draft.of]sort[title]]\" actions=\"\"\"$actions$\"\"\"/>\n\\end\n" }, "$:/core/macros/lingo": { "title": "$:/core/macros/lingo", "tags": "$:/tags/Macro", "text": "\\define lingo-base()\n$:/language/\n\\end\n\n\\define lingo(title)\n{{$(lingo-base)$$title$}}\n\\end\n" }, "$:/core/macros/list": { "title": "$:/core/macros/list", "tags": "$:/tags/Macro", "text": "\\define list-links(filter,type:\"ul\",subtype:\"li\",class:\"\")\n<$type$ class=\"$class$\">\n<$list filter=\"$filter$\">\n<$subtype$>\n<$link to={{!!title}}>\n<$transclude field=\"caption\">\n<$view field=\"title\"/>\n</$transclude>\n</$link>\n</$subtype$>\n</$list>\n</$type$>\n\\end\n\n\\define list-links-draggable-drop-actions()\n<$action-listops $tiddler=<<targetTiddler>> $field=<<targetField>> $subfilter=\"+[insertbefore:currentTiddler<actionTiddler>]\"/>\n\\end\n\n\\define list-links-draggable(tiddler,field:\"list\",type:\"ul\",subtype:\"li\",class:\"\",itemTemplate)\n<$vars targetTiddler=\"\"\"$tiddler$\"\"\" targetField=\"\"\"$field$\"\"\">\n<$type$ class=\"$class$\">\n<$list filter=\"[list[$tiddler$!!$field$]]\">\n<$droppable actions=<<list-links-draggable-drop-actions>> tag=\"\"\"$subtype$\"\"\">\n<div class=\"tc-droppable-placeholder\">\n \n</div>\n<div>\n<$link to={{!!title}}>\n<$transclude tiddler=\"\"\"$itemTemplate$\"\"\">\n<$transclude field=\"caption\">\n<$view field=\"title\"/>\n</$transclude>\n</$transclude>\n</$link>\n</div>\n</$droppable>\n</$list>\n<$tiddler tiddler=\"\">\n<$droppable actions=<<list-links-draggable-drop-actions>> tag=\"\"\"$subtype$\"\"\">\n<div class=\"tc-droppable-placeholder\">\n \n</div>\n<div>\n \n</div>\n</$droppable>\n</$tiddler>\n</$type$>\n</$vars>\n\\end\n\n\\define list-tagged-draggable-drop-actions()\n<!-- Save the current ordering of the tiddlers with this tag -->\n<$set name=\"order\" filter=\"[<tag>tagging[]]\">\n<!-- Remove any list-after or list-before fields from the tiddlers with this tag -->\n<$list filter=\"[<tag>tagging[]]\">\n<$action-deletefield $field=\"list-before\"/>\n<$action-deletefield $field=\"list-after\"/>\n</$list>\n<!-- Assign the list field of the tag with the current ordering -->\n<$action-setfield $tiddler=<<tag>> $field=\"list\" $value=<<order>>/>\n<!-- Add the newly inserted item to the list -->\n<$action-listops $tiddler=<<tag>> $field=\"list\" $subfilter=\"+[insertbefore:currentTiddler<actionTiddler>]\"/>\n<!-- Make sure the newly added item has the right tag -->\n<$action-listops $tiddler=<<actionTiddler>> $tags=\"[<tag>]\"/>\n</$set>\n\\end\n\n\\define list-tagged-draggable(tag,itemTemplate,elementTag:\"div\")\n<$set name=\"tag\" value=\"\"\"$tag$\"\"\">\n<$list filter=\"[<tag>tagging[]]\">\n<$elementTag$ class=\"tc-menu-list-item\">\n<$droppable actions=<<list-tagged-draggable-drop-actions>>>\n<$elementTag$ class=\"tc-droppable-placeholder\">\n \n</$elementTag$>\n<$elementTag$>\n<$transclude tiddler=\"\"\"$itemTemplate$\"\"\">\n<$link to={{!!title}}>\n<$view field=\"title\"/>\n</$link>\n</$transclude>\n</$elementTag$>\n</$droppable>\n</$elementTag$>\n</$list>\n<$tiddler tiddler=\"\">\n<$droppable actions=<<list-tagged-draggable-drop-actions>>>\n<$elementTag$ class=\"tc-droppable-placeholder\">\n \n</$elementTag$>\n<$elementTag$ style=\"height:0.5em;\">\n</$elementTag$>\n</$droppable>\n</$tiddler>\n</$set>\n\\end\n" }, "$:/core/macros/tabs": { "title": "$:/core/macros/tabs", "tags": "$:/tags/Macro", "text": "\\define tabs(tabsList,default,state:\"$:/state/tab\",class,template)\n<div class=\"tc-tab-set $class$\">\n<div class=\"tc-tab-buttons $class$\">\n<$list filter=\"$tabsList$\" variable=\"currentTab\"><$set name=\"save-currentTiddler\" value=<<currentTiddler>>><$tiddler tiddler=<<currentTab>>><$button set=<<qualify \"$state$\">> setTo=<<currentTab>> default=\"$default$\" selectedClass=\"tc-tab-selected\" tooltip={{!!tooltip}}>\n<$tiddler tiddler=<<save-currentTiddler>>>\n<$set name=\"tv-wikilinks\" value=\"no\">\n<$transclude tiddler=<<currentTab>> field=\"caption\">\n<$macrocall $name=\"currentTab\" $type=\"text/plain\" $output=\"text/plain\"/>\n</$transclude>\n</$set></$tiddler></$button></$tiddler></$set></$list>\n</div>\n<div class=\"tc-tab-divider $class$\"/>\n<div class=\"tc-tab-content $class$\">\n<$list filter=\"$tabsList$\" variable=\"currentTab\">\n\n<$reveal type=\"match\" state=<<qualify \"$state$\">> text=<<currentTab>> default=\"$default$\">\n\n<$transclude tiddler=\"$template$\" mode=\"block\">\n\n<$transclude tiddler=<<currentTab>> mode=\"block\"/>\n\n</$transclude>\n\n</$reveal>\n\n</$list>\n</div>\n</div>\n\\end\n" }, "$:/core/macros/tag-picker": { "title": "$:/core/macros/tag-picker", "tags": "$:/tags/Macro", "text": "\\define add-tag-actions()\n<$action-sendmessage $message=\"tm-add-tag\" $param={{$:/temp/NewTagName}}/>\n<$action-deletetiddler $tiddler=\"$:/temp/NewTagName\"/>\n\\end\n\n\\define tag-button()\n<$button class=\"tc-btn-invisible\" tag=\"a\">\n$(actions)$\n<$action-deletetiddler $tiddler=\"$:/temp/NewTagName\"/>\n<$macrocall $name=\"tag-pill\" tag=<<tag>>/>\n</$button>\n\\end\n\n\\define tag-picker(actions)\n<$set name=\"actions\" value=\"\"\"$actions$\"\"\">\n<div class=\"tc-edit-add-tag\">\n<span class=\"tc-add-tag-name\">\n<$keyboard key=\"ENTER\" actions=<<add-tag-actions>>>\n<$edit-text tiddler=\"$:/temp/NewTagName\" tag=\"input\" default=\"\" placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}} focusPopup=<<qualify \"$:/state/popup/tags-auto-complete\">> class=\"tc-edit-texteditor tc-popup-handle\"/>\n</$keyboard>\n</span> <$button popup=<<qualify \"$:/state/popup/tags-auto-complete\">> class=\"tc-btn-invisible\" tooltip={{$:/language/EditTemplate/Tags/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Tags/Dropdown/Caption}}>{{$:/core/images/down-arrow}}</$button> <span class=\"tc-add-tag-button\">\n<$set name=\"tag\" value={{$:/temp/NewTagName}}>\n<$button set=\"$:/temp/NewTagName\" setTo=\"\" class=\"\">\n$actions$\n<$action-deletetiddler $tiddler=\"$:/temp/NewTagName\"/>\n{{$:/language/EditTemplate/Tags/Add/Button}}\n</$button>\n</$set>\n</span>\n</div>\n<div class=\"tc-block-dropdown-wrapper\">\n<$reveal state=<<qualify \"$:/state/popup/tags-auto-complete\">> type=\"nomatch\" text=\"\" default=\"\">\n<div class=\"tc-block-dropdown\">\n<$list filter=\"[tags[]!is[system]search:title{$:/temp/NewTagName}sort[]]\" variable=\"tag\">\n<<tag-button>>\n</$list>\n<hr>\n<$list filter=\"[tags[]is[system]search:title{$:/temp/NewTagName}sort[]]\" variable=\"tag\">\n<<tag-button>>\n</$list>\n</div>\n</$reveal>\n</div>\n</$set>\n\\end\n" }, "$:/core/macros/tag": { "title": "$:/core/macros/tag", "tags": "$:/tags/Macro", "text": "\\define tag-pill-styles()\nbackground-color:$(backgroundColor)$;\nfill:$(foregroundColor)$;\ncolor:$(foregroundColor)$;\n\\end\n\n\\define tag-pill-inner(tag,icon,colour,fallbackTarget,colourA,colourB,element-tag,element-attributes,actions)\n<$vars foregroundColor=<<contrastcolour target:\"\"\"$colour$\"\"\" fallbackTarget:\"\"\"$fallbackTarget$\"\"\" colourA:\"\"\"$colourA$\"\"\" colourB:\"\"\"$colourB$\"\"\">> backgroundColor=\"\"\"$colour$\"\"\">\n<$element-tag$ $element-attributes$ class=\"tc-tag-label tc-btn-invisible\" style=<<tag-pill-styles>>>\n$actions$<$transclude tiddler=\"\"\"$icon$\"\"\"/> <$view tiddler=\"\"\"$tag$\"\"\" field=\"title\" format=\"text\" />\n</$element-tag$>\n</$vars>\n\\end\n\n\\define tag-pill-body(tag,icon,colour,palette,element-tag,element-attributes,actions)\n<$macrocall $name=\"tag-pill-inner\" tag=\"\"\"$tag$\"\"\" icon=\"\"\"$icon$\"\"\" colour=\"\"\"$colour$\"\"\" fallbackTarget={{$palette$##tag-background}} colourA={{$palette$##foreground}} colourB={{$palette$##background}} element-tag=\"\"\"$element-tag$\"\"\" element-attributes=\"\"\"$element-attributes$\"\"\" actions=\"\"\"$actions$\"\"\"/>\n\\end\n\n\\define tag-pill(tag,element-tag:\"span\",element-attributes:\"\",actions:\"\")\n<span class=\"tc-tag-list-item\">\n<$macrocall $name=\"tag-pill-body\" tag=\"\"\"$tag$\"\"\" icon={{$tag$!!icon}} colour={{$tag$!!color}} palette={{$:/palette}} element-tag=\"\"\"$element-tag$\"\"\" element-attributes=\"\"\"$element-attributes$\"\"\" actions=\"\"\"$actions$\"\"\"/>\n</span>\n\\end\n\n\\define tag(tag)\n{{$tag$||$:/core/ui/TagTemplate}}\n\\end\n" }, "$:/core/macros/thumbnails": { "title": "$:/core/macros/thumbnails", "tags": "$:/tags/Macro", "text": "\\define thumbnail(link,icon,color,background-color,image,caption,width:\"280\",height:\"157\")\n<$link to=\"\"\"$link$\"\"\"><div class=\"tc-thumbnail-wrapper\">\n<div class=\"tc-thumbnail-image\" style=\"width:$width$px;height:$height$px;\"><$reveal type=\"nomatch\" text=\"\" default=\"\"\"$image$\"\"\" tag=\"div\" style=\"width:$width$px;height:$height$px;\">\n[img[$image$]]\n</$reveal><$reveal type=\"match\" text=\"\" default=\"\"\"$image$\"\"\" tag=\"div\" class=\"tc-thumbnail-background\" style=\"width:$width$px;height:$height$px;background-color:$background-color$;\"></$reveal></div><div class=\"tc-thumbnail-icon\" style=\"fill:$color$;color:$color$;\">\n$icon$\n</div><div class=\"tc-thumbnail-caption\">\n$caption$\n</div>\n</div></$link>\n\\end\n\n\\define thumbnail-right(link,icon,color,background-color,image,caption,width:\"280\",height:\"157\")\n<div class=\"tc-thumbnail-right-wrapper\"><<thumbnail \"\"\"$link$\"\"\" \"\"\"$icon$\"\"\" \"\"\"$color$\"\"\" \"\"\"$background-color$\"\"\" \"\"\"$image$\"\"\" \"\"\"$caption$\"\"\" \"\"\"$width$\"\"\" \"\"\"$height$\"\"\">></div>\n\\end\n\n\\define list-thumbnails(filter,width:\"280\",height:\"157\")\n<$list filter=\"\"\"$filter$\"\"\"><$macrocall $name=\"thumbnail\" link={{!!link}} icon={{!!icon}} color={{!!color}} background-color={{!!background-color}} image={{!!image}} caption={{!!caption}} width=\"\"\"$width$\"\"\" height=\"\"\"$height$\"\"\"/></$list>\n\\end\n" }, "$:/core/macros/timeline": { "created": "20141212105914482", "modified": "20141212110330815", "tags": "$:/tags/Macro", "title": "$:/core/macros/timeline", "type": "text/vnd.tiddlywiki", "text": "\\define timeline-title()\n<!-- Override this macro with a global macro \n of the same name if you need to change \n how titles are displayed on the timeline \n -->\n<$view field=\"title\"/>\n\\end\n\\define timeline(limit:\"100\",format:\"DDth MMM YYYY\",subfilter:\"\",dateField:\"modified\")\n<div class=\"tc-timeline\">\n<$list filter=\"[!is[system]$subfilter$has[$dateField$]!sort[$dateField$]limit[$limit$]eachday[$dateField$]]\">\n<div class=\"tc-menu-list-item\">\n<$view field=\"$dateField$\" format=\"date\" template=\"$format$\"/>\n<$list filter=\"[sameday:$dateField${!!$dateField$}!is[system]$subfilter$!sort[$dateField$]]\">\n<div class=\"tc-menu-list-subitem\">\n<$link to={{!!title}}>\n<<timeline-title>>\n</$link>\n</div>\n</$list>\n</div>\n</$list>\n</div>\n\\end\n" }, "$:/core/macros/toc": { "title": "$:/core/macros/toc", "tags": "$:/tags/Macro", "text": "\\define toc-caption()\n<$set name=\"tv-wikilinks\" value=\"no\">\n <$transclude field=\"caption\">\n <$view field=\"title\"/>\n </$transclude>\n</$set>\n\\end\n\n\\define toc-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<ol class=\"tc-toc\">\n <$list filter=\"\"\"[all[shadows+tiddlers]tag[$tag$]!has[draft.of]$sort$] $exclude$\"\"\">\n <$vars item=<<currentTiddler>> path=\"\"\"$path$/$tag$\"\"\" excluded=\"\"\"$exclude$ -[[$tag$]]\"\"\">\n <$set name=\"toc-item-class\" filter=\"\"\"$itemClassFilter$\"\"\" emptyValue=\"toc-item\" value=\"toc-item-selected\">\n <li class=<<toc-item-class>>>\n <$list filter=\"[all[current]toc-link[no]]\" emptyMessage=\"<$link><$view field='caption'><$view field='title'/></$view></$link>\">\n <<toc-caption>>\n </$list>\n <$macrocall $name=\"toc-body\" tag=<<item>> sort=\"\"\"$sort$\"\"\" itemClassFilter=\"\"\"$itemClassFilter$\"\"\" exclude=<<excluded>> path=<<path>>/>\n </li>\n </$set>\n </$vars>\n </$list>\n</ol>\n\\end\n\n\\define toc(tag,sort:\"\",itemClassFilter:\" \")\n<<toc-body tag:\"\"\"$tag$\"\"\" sort:\"\"\"$sort$\"\"\" itemClassFilter:\"\"\"$itemClassFilter$\"\"\">>\n\\end\n\n\\define toc-linked-expandable-body(tag,sort:\"\",itemClassFilter,exclude,path)\n<!-- helper function -->\n<$set name=\"toc-state\" value=<<qualify \"\"\"$:/state/toc$path$-$(currentTiddler)$\"\"\">>>\n <$set name=\"toc-item-class\" filter=\"\"\"$itemClassFilter$\"\"\" emptyValue=\"toc-item\" value=\"toc-item-selected\">\n <li class=<<toc-item-class>>>\n <$link>\n <$reveal type=\"nomatch\" state=<<toc-state>> text=\"open\">\n <$button set=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible\">\n {{$:/core/images/right-arrow}}\n </$button>\n </$reveal>\n <$reveal type=\"match\" state=<<toc-state>> text=\"open\">\n <$button set=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible\">\n {{$:/core/images/down-arrow}}\n </$button>\n </$reveal>\n <<toc-caption>>\n </$link>\n <$reveal type=\"match\" state=<<toc-state>> text=\"open\">\n <$macrocall $name=\"toc-expandable\" tag=<<currentTiddler>> sort=\"\"\"$sort$\"\"\" itemClassFilter=\"\"\"$itemClassFilter$\"\"\" exclude=\"\"\"$exclude$\"\"\" path=\"\"\"$path$\"\"\"/>\n </$reveal>\n </li>\n </$set>\n</$set>\n\\end\n\n\\define toc-unlinked-expandable-body(tag,sort:\"\",itemClassFilter:\" \",exclude,path)\n<!-- helper function -->\n<$set name=\"toc-state\" value=<<qualify \"\"\"$:/state/toc$path$-$(currentTiddler)$\"\"\">>>\n <$set name=\"toc-item-class\" filter=\"\"\"$itemClassFilter$\"\"\" emptyValue=\"toc-item\" value=\"toc-item-selected\">\n <li class=<<toc-item-class>>>\n <$reveal type=\"nomatch\" state=<<toc-state>> text=\"open\">\n <$button set=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible\">\n {{$:/core/images/right-arrow}}\n <<toc-caption>>\n </$button>\n </$reveal>\n <$reveal type=\"match\" state=<<toc-state>> text=\"open\">\n <$button set=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible\">\n {{$:/core/images/down-arrow}}\n <<toc-caption>>\n </$button>\n </$reveal>\n <$reveal type=\"match\" state=<<toc-state>> text=\"open\">\n <$macrocall $name=\"toc-expandable\" tag=<<currentTiddler>> sort=\"\"\"$sort$\"\"\" itemClassFilter=\"\"\"$itemClassFilter$\"\"\" exclude=\"\"\"$exclude$\"\"\" path=\"\"\"$path$\"\"\"/>\n </$reveal>\n </li>\n </$set>\n</$set>\n\\end\n\n\\define toc-expandable-empty-message()\n<<toc-linked-expandable-body tag:\"\"\"$(tag)$\"\"\" sort:\"\"\"$(sort)$\"\"\" itemClassFilter:\"\"\"$(itemClassFilter)$\"\"\" exclude:\"\"\"$(excluded)$\"\"\" path:\"\"\"$(path)$\"\"\">>\n\\end\n\n\\define toc-expandable(tag,sort:\"\",itemClassFilter:\" \",exclude,path)\n<$vars tag=\"\"\"$tag$\"\"\" sort=\"\"\"$sort$\"\"\" itemClassFilter=\"\"\"$itemClassFilter$\"\"\" excluded=\"\"\"$exclude$ -[[$tag$]]\"\"\" path=\"\"\"$path$/$tag$\"\"\">\n <ol class=\"tc-toc toc-expandable\">\n <$list filter=\"\"\"[all[shadows+tiddlers]tag[$tag$]!has[draft.of]$sort$] $exclude$\"\"\">\n <$list filter=\"[all[current]toc-link[no]]\" emptyMessage=<<toc-expandable-empty-message>> >\n <$macrocall $name=\"toc-unlinked-expandable-body\" tag=\"\"\"$tag$\"\"\" sort=\"\"\"$sort$\"\"\" itemClassFilter=\"\"\"itemClassFilter\"\"\" exclude=<<excluded>> path=<<path>> />\n </$list>\n </$list>\n </ol>\n</$vars>\n\\end\n\n\\define toc-linked-selective-expandable-body(tag,sort:\"\",itemClassFilter:\" \",exclude,path)\n<$set name=\"toc-state\" value=<<qualify \"\"\"$:/state/toc$path$-$(currentTiddler)$\"\"\">>>\n <$set name=\"toc-item-class\" filter=\"\"\"$itemClassFilter$\"\"\" emptyValue=\"toc-item\" value=\"toc-item-selected\" >\n <li class=<<toc-item-class>>>\n <$link>\n <$list filter=\"[all[current]tagging[]limit[1]]\" variable=\"ignore\" emptyMessage=\"<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button>\">\n <$reveal type=\"nomatch\" state=<<toc-state>> text=\"open\">\n <$button set=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible\">\n {{$:/core/images/right-arrow}}\n </$button>\n </$reveal>\n <$reveal type=\"match\" state=<<toc-state>> text=\"open\">\n <$button set=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible\">\n {{$:/core/images/down-arrow}}\n </$button>\n </$reveal>\n </$list>\n <<toc-caption>>\n </$link>\n <$reveal type=\"match\" state=<<toc-state>> text=\"open\">\n <$macrocall $name=\"toc-selective-expandable\" tag=<<currentTiddler>> sort=\"\"\"$sort$\"\"\" itemClassFilter=\"\"\"$itemClassFilter$\"\"\" exclude=\"\"\"$exclude$\"\"\" path=\"\"\"$path$\"\"\"/>\n </$reveal>\n </li>\n </$set>\n</$set>\n\\end\n\n\\define toc-unlinked-selective-expandable-body(tag,sort:\"\",itemClassFilter:\" \",exclude,path)\n<$set name=\"toc-state\" value=<<qualify \"\"\"$:/state/toc$path$-$(currentTiddler)$\"\"\">>>\n <$set name=\"toc-item-class\" filter=\"\"\"$itemClassFilter$\"\"\" emptyValue=\"toc-item\" value=\"toc-item-selected\">\n <li class=<<toc-item-class>>>\n <$list filter=\"[all[current]tagging[]limit[1]]\" variable=\"ignore\" emptyMessage=\"<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button> <$view field='caption'><$view field='title'/></$view>\">\n <$reveal type=\"nomatch\" state=<<toc-state>> text=\"open\">\n <$button set=<<toc-state>> setTo=\"open\" class=\"tc-btn-invisible\">\n {{$:/core/images/right-arrow}}\n <<toc-caption>>\n </$button>\n </$reveal>\n <$reveal type=\"match\" state=<<toc-state>> text=\"open\">\n <$button set=<<toc-state>> setTo=\"close\" class=\"tc-btn-invisible\">\n {{$:/core/images/down-arrow}}\n <<toc-caption>>\n </$button>\n </$reveal>\n </$list>\n <$reveal type=\"match\" state=<<toc-state>> text=\"open\">\n <$macrocall $name=\"\"\"toc-selective-expandable\"\"\" tag=<<currentTiddler>> sort=\"\"\"$sort$\"\"\" itemClassFilter=\"\"\"$itemClassFilter$\"\"\" exclude=\"\"\"$exclude$\"\"\" path=\"\"\"$path$\"\"\"/>\n </$reveal>\n </li>\n </$set>\n</$set>\n\\end\n\n\\define toc-selective-expandable-empty-message()\n<<toc-linked-selective-expandable-body tag:\"\"\"$(tag)$\"\"\" sort:\"\"\"$(sort)$\"\"\" itemClassFilter:\"\"\"$(itemClassFilter)$\"\"\" exclude:\"\"\"$(excluded)$\"\"\" path:\"\"\"$(path)$\"\"\">>\n\\end\n\n\\define toc-selective-expandable(tag,sort:\"\",itemClassFilter,exclude,path)\n<$vars tag=\"\"\"$tag$\"\"\" sort=\"\"\"$sort$\"\"\" itemClassFilter=\"\"\"$itemClassFilter$\"\"\" excluded=\"\"\"$exclude$ -[[$tag$]]\"\"\" path=\"\"\"$path$/$tag$\"\"\">\n <ol class=\"tc-toc toc-selective-expandable\">\n <$list filter=\"\"\"[all[shadows+tiddlers]tag[$tag$]!has[draft.of]$sort$] $exclude$\"\"\">\n <$list filter=\"[all[current]toc-link[no]]\" variable=\"ignore\" emptyMessage=<<toc-selective-expandable-empty-message>> >\n <$macrocall $name=toc-unlinked-selective-expandable-body tag=\"\"\"$tag$\"\"\" sort=\"\"\"$sort$\"\"\" itemClassFilter=\"\"\"$itemClassFilter$\"\"\" exclude=<<excluded>> path=<<path>> >\n </$list>\n </$list>\n </ol>\n</$vars>\n\\end\n\n\\define toc-tabbed-selected-item-filter(selectedTiddler)\n[all[current]field:title{$selectedTiddler$}]\n\\end\n\n\\define toc-tabbed-external-nav(tag,sort:\"\",selectedTiddler:\"$:/temp/toc/selectedTiddler\",unselectedText,missingText,template:\"\")\n<$tiddler tiddler={{$selectedTiddler$}}>\n <div class=\"tc-tabbed-table-of-contents\">\n <$linkcatcher to=\"$selectedTiddler$\">\n <div class=\"tc-table-of-contents\">\n <$macrocall $name=\"toc-selective-expandable\" tag=\"\"\"$tag$\"\"\" sort=\"\"\"$sort$\"\"\" itemClassFilter=<<toc-tabbed-selected-item-filter selectedTiddler:\"\"\"$selectedTiddler$\"\"\">>/>\n </div>\n </$linkcatcher>\n <div class=\"tc-tabbed-table-of-contents-content\">\n <$reveal state=\"\"\"$selectedTiddler$\"\"\" type=\"nomatch\" text=\"\">\n <$transclude mode=\"block\" tiddler=\"$template$\">\n <h1><<toc-caption>></h1>\n <$transclude mode=\"block\">$missingText$</$transclude>\n </$transclude>\n </$reveal>\n <$reveal state=\"\"\"$selectedTiddler$\"\"\" type=\"match\" text=\"\">\n $unselectedText$\n </$reveal>\n </div>\n </div>\n</$tiddler>\n\\end\n\n\\define toc-tabbed-internal-nav(tag,sort:\"\",selectedTiddler:\"$:/temp/toc/selectedTiddler\",unselectedText,missingText,template:\"\")\n<$linkcatcher to=\"\"\"$selectedTiddler$\"\"\">\n <$macrocall $name=\"toc-tabbed-external-nav\" tag=\"\"\"$tag$\"\"\" sort=\"\"\"$sort$\"\"\" selectedTiddler=\"\"\"$selectedTiddler$\"\"\" unselectedText=\"\"\"$unselectedText$\"\"\" missingText=\"\"\"$missingText$\"\"\" template=\"\"\"$template$\"\"\"/>\n</$linkcatcher>\n\\end\n\n" }, "$:/core/macros/translink": { "title": "$:/core/macros/translink", "tags": "$:/tags/Macro", "text": "\\define translink(title,mode:\"block\")\n<div style=\"border:1px solid #ccc; padding: 0.5em; background: black; foreground; white;\">\n<$link to=\"\"\"$title$\"\"\">\n<$text text=\"\"\"$title$\"\"\"/>\n</$link>\n<div style=\"border:1px solid #ccc; padding: 0.5em; background: white; foreground; black;\">\n<$transclude tiddler=\"\"\"$title$\"\"\" mode=\"$mode$\">\n\"<$text text=\"\"\"$title$\"\"\"/>\" is missing\n</$transclude>\n</div>\n</div>\n\\end\n" }, "$:/snippets/minilanguageswitcher": { "title": "$:/snippets/minilanguageswitcher", "text": "<$select tiddler=\"$:/language\">\n<$list filter=\"[[$:/languages/en-GB]] [plugin-type[language]sort[title]]\">\n<option value=<<currentTiddler>>><$view field=\"description\"><$view field=\"name\"><$view field=\"title\"/></$view></$view></option>\n</$list>\n</$select>" }, "$:/snippets/minithemeswitcher": { "title": "$:/snippets/minithemeswitcher", "text": "\\define lingo-base() $:/language/ControlPanel/Theme/\n<<lingo Prompt>> <$select tiddler=\"$:/theme\">\n<$list filter=\"[plugin-type[theme]sort[title]]\">\n<option value=<<currentTiddler>>><$view field=\"name\"><$view field=\"title\"/></$view></option>\n</$list>\n</$select>" }, "$:/snippets/modules": { "title": "$:/snippets/modules", "text": "\\define describeModuleType(type)\n{{$:/language/Docs/ModuleTypes/$type$}}\n\\end\n<$list filter=\"[moduletypes[]]\">\n\n!! <$macrocall $name=\"currentTiddler\" $type=\"text/plain\" $output=\"text/plain\"/>\n\n<$macrocall $name=\"describeModuleType\" type=<<currentTiddler>>/>\n\n<ul><$list filter=\"[all[current]modules[]]\"><li><$link><<currentTiddler>></$link>\n</li>\n</$list>\n</ul>\n</$list>\n" }, "$:/palette": { "title": "$:/palette", "text": "$:/palettes/Vanilla" }, "$:/snippets/paletteeditor": { "title": "$:/snippets/paletteeditor", "text": "\\define lingo-base() $:/language/ControlPanel/Palette/Editor/\n\\define describePaletteColour(colour)\n<$transclude tiddler=\"$:/language/Docs/PaletteColours/$colour$\"><$text text=\"$colour$\"/></$transclude>\n\\end\n<$set name=\"currentTiddler\" value={{$:/palette}}>\n\n<<lingo Prompt>> <$link to={{$:/palette}}><$macrocall $name=\"currentTiddler\" $output=\"text/plain\"/></$link>\n\n<$list filter=\"[all[current]is[shadow]is[tiddler]]\" variable=\"listItem\">\n<<lingo Prompt/Modified>>\n<$button message=\"tm-delete-tiddler\" param={{$:/palette}}><<lingo Reset/Caption>></$button>\n</$list>\n\n<$list filter=\"[all[current]is[shadow]!is[tiddler]]\" variable=\"listItem\">\n<<lingo Clone/Prompt>>\n</$list>\n\n<$button message=\"tm-new-tiddler\" param={{$:/palette}}><<lingo Clone/Caption>></$button>\n\n<table>\n<tbody>\n<$list filter=\"[all[current]indexes[]]\" variable=\"colourName\">\n<tr>\n<td>\n''<$macrocall $name=\"describePaletteColour\" colour=<<colourName>>/>''<br/>\n<$macrocall $name=\"colourName\" $output=\"text/plain\"/>\n</td>\n<td>\n<$edit-text index=<<colourName>> tag=\"input\"/>\n<br>\n<$edit-text index=<<colourName>> type=\"color\" tag=\"input\"/>\n</td>\n</tr>\n</$list>\n</tbody>\n</table>\n</$set>\n" }, "$:/snippets/palettepreview": { "title": "$:/snippets/palettepreview", "text": "<$set name=\"currentTiddler\" value={{$:/palette}}>\n<$transclude tiddler=\"$:/snippets/currpalettepreview\"/>\n</$set>\n" }, "$:/snippets/paletteswitcher": { "title": "$:/snippets/paletteswitcher", "text": "\\define lingo-base() $:/language/ControlPanel/Palette/\n<div class=\"tc-prompt\">\n<<lingo Prompt>> <$view tiddler={{$:/palette}} field=\"name\"/>\n</div>\n\n<$linkcatcher to=\"$:/palette\">\n<div class=\"tc-chooser\"><$list filter=\"[all[shadows+tiddlers]tag[$:/tags/Palette]sort[description]]\"><div class=\"tc-chooser-item\"><$link to={{!!title}}><div><$reveal state=\"$:/palette\" type=\"match\" text={{!!title}}>•</$reveal><$reveal state=\"$:/palette\" type=\"nomatch\" text={{!!title}}> </$reveal> ''<$view field=\"name\" format=\"text\"/>'' - <$view field=\"description\" format=\"text\"/></div><$transclude tiddler=\"$:/snippets/currpalettepreview\"/></$link></div>\n</$list>\n</div>\n</$linkcatcher>" }, "$:/temp/search": { "title": "$:/temp/search", "text": "" }, "$:/tags/AdvancedSearch": { "title": "$:/tags/AdvancedSearch", "list": "[[$:/core/ui/AdvancedSearch/Standard]] [[$:/core/ui/AdvancedSearch/System]] [[$:/core/ui/AdvancedSearch/Shadows]] [[$:/core/ui/AdvancedSearch/Filter]]" }, "$:/tags/AdvancedSearch/FilterButton": { "title": "$:/tags/AdvancedSearch/FilterButton", "list": "$:/core/ui/AdvancedSearch/Filter/FilterButtons/dropdown $:/core/ui/AdvancedSearch/Filter/FilterButtons/clear $:/core/ui/AdvancedSearch/Filter/FilterButtons/export $:/core/ui/AdvancedSearch/Filter/FilterButtons/delete" }, "$:/tags/ControlPanel": { "title": "$:/tags/ControlPanel", "list": "$:/core/ui/ControlPanel/Info $:/core/ui/ControlPanel/Appearance $:/core/ui/ControlPanel/Settings $:/core/ui/ControlPanel/Saving $:/core/ui/ControlPanel/Plugins $:/core/ui/ControlPanel/Tools $:/core/ui/ControlPanel/Internals" }, "$:/tags/ControlPanel/Info": { "title": "$:/tags/ControlPanel/Info", "list": "$:/core/ui/ControlPanel/Basics $:/core/ui/ControlPanel/Advanced" }, "$:/tags/ControlPanel/Plugins": { "title": "$:/tags/ControlPanel/Plugins", "list": "[[$:/core/ui/ControlPanel/Plugins/Installed]] [[$:/core/ui/ControlPanel/Plugins/Add]]" }, "$:/tags/EditTemplate": { "title": "$:/tags/EditTemplate", "list": "[[$:/core/ui/EditTemplate/controls]] [[$:/core/ui/EditTemplate/title]] [[$:/core/ui/EditTemplate/tags]] [[$:/core/ui/EditTemplate/shadow]] [[$:/core/ui/ViewTemplate/classic]] [[$:/core/ui/EditTemplate/body]] [[$:/core/ui/EditTemplate/type]] [[$:/core/ui/EditTemplate/fields]]" }, "$:/tags/EditToolbar": { "title": "$:/tags/EditToolbar", "list": "[[$:/core/ui/Buttons/delete]] [[$:/core/ui/Buttons/cancel]] [[$:/core/ui/Buttons/save]]" }, "$:/tags/EditorToolbar": { "title": "$:/tags/EditorToolbar", "list": "$:/core/ui/EditorToolbar/paint $:/core/ui/EditorToolbar/opacity $:/core/ui/EditorToolbar/line-width $:/core/ui/EditorToolbar/clear $:/core/ui/EditorToolbar/bold $:/core/ui/EditorToolbar/italic $:/core/ui/EditorToolbar/strikethrough $:/core/ui/EditorToolbar/underline $:/core/ui/EditorToolbar/superscript $:/core/ui/EditorToolbar/subscript $:/core/ui/EditorToolbar/mono-line $:/core/ui/EditorToolbar/mono-block $:/core/ui/EditorToolbar/quote $:/core/ui/EditorToolbar/list-bullet $:/core/ui/EditorToolbar/list-number $:/core/ui/EditorToolbar/heading-1 $:/core/ui/EditorToolbar/heading-2 $:/core/ui/EditorToolbar/heading-3 $:/core/ui/EditorToolbar/heading-4 $:/core/ui/EditorToolbar/heading-5 $:/core/ui/EditorToolbar/heading-6 $:/core/ui/EditorToolbar/link $:/core/ui/EditorToolbar/excise $:/core/ui/EditorToolbar/picture $:/core/ui/EditorToolbar/stamp $:/core/ui/EditorToolbar/size $:/core/ui/EditorToolbar/editor-height $:/core/ui/EditorToolbar/more $:/core/ui/EditorToolbar/preview $:/core/ui/EditorToolbar/preview-type" }, "$:/tags/Manager/ItemMain": { "title": "$:/tags/Manager/ItemMain", "list": "$:/Manager/ItemMain/WikifiedText $:/Manager/ItemMain/RawText $:/Manager/ItemMain/Fields" }, "$:/tags/Manager/ItemSidebar": { "title": "$:/tags/Manager/ItemSidebar", "list": "$:/Manager/ItemSidebar/Tags $:/Manager/ItemSidebar/Colour $:/Manager/ItemSidebar/Icon $:/Manager/ItemSidebar/Tools" }, "$:/tags/MoreSideBar": { "title": "$:/tags/MoreSideBar", "list": "[[$:/core/ui/MoreSideBar/All]] [[$:/core/ui/MoreSideBar/Recent]] [[$:/core/ui/MoreSideBar/Tags]] [[$:/core/ui/MoreSideBar/Missing]] [[$:/core/ui/MoreSideBar/Drafts]] [[$:/core/ui/MoreSideBar/Orphans]] [[$:/core/ui/MoreSideBar/Types]] [[$:/core/ui/MoreSideBar/System]] [[$:/core/ui/MoreSideBar/Shadows]] [[$:/core/ui/MoreSideBar/Plugins]]", "text": "" }, "$:/tags/PageControls": { "title": "$:/tags/PageControls", "list": "[[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/more-page-actions]]" }, "$:/tags/PageTemplate": { "title": "$:/tags/PageTemplate", "list": "[[$:/core/ui/PageTemplate/topleftbar]] [[$:/core/ui/PageTemplate/toprightbar]] [[$:/core/ui/PageTemplate/sidebar]] [[$:/core/ui/PageTemplate/story]] [[$:/core/ui/PageTemplate/alerts]]", "text": "" }, "$:/tags/SideBar": { "title": "$:/tags/SideBar", "list": "[[$:/core/ui/SideBar/Open]] [[$:/core/ui/SideBar/Recent]] [[$:/core/ui/SideBar/Tools]] [[$:/core/ui/SideBar/More]]", "text": "" }, "$:/tags/TiddlerInfo": { "title": "$:/tags/TiddlerInfo", "list": "[[$:/core/ui/TiddlerInfo/Tools]] [[$:/core/ui/TiddlerInfo/References]] [[$:/core/ui/TiddlerInfo/Tagging]] [[$:/core/ui/TiddlerInfo/List]] [[$:/core/ui/TiddlerInfo/Listed]] [[$:/core/ui/TiddlerInfo/Fields]]", "text": "" }, "$:/tags/TiddlerInfo/Advanced": { "title": "$:/tags/TiddlerInfo/Advanced", "list": "[[$:/core/ui/TiddlerInfo/Advanced/ShadowInfo]] [[$:/core/ui/TiddlerInfo/Advanced/PluginInfo]]" }, "$:/tags/ViewTemplate": { "title": "$:/tags/ViewTemplate", "list": "[[$:/core/ui/ViewTemplate/title]] [[$:/core/ui/ViewTemplate/unfold]] [[$:/core/ui/ViewTemplate/subtitle]] [[$:/core/ui/ViewTemplate/tags]] [[$:/core/ui/ViewTemplate/classic]] [[$:/core/ui/ViewTemplate/body]]" }, "$:/tags/ViewToolbar": { "title": "$:/tags/ViewToolbar", "list": "[[$:/core/ui/Buttons/more-tiddler-actions]] [[$:/core/ui/Buttons/info]] [[$:/core/ui/Buttons/new-here]] [[$:/core/ui/Buttons/new-journal-here]] [[$:/core/ui/Buttons/clone]] [[$:/core/ui/Buttons/export-tiddler]] [[$:/core/ui/Buttons/edit]] [[$:/core/ui/Buttons/delete]] [[$:/core/ui/Buttons/permalink]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/open-window]] [[$:/core/ui/Buttons/close-others]] [[$:/core/ui/Buttons/close]] [[$:/core/ui/Buttons/fold-others]] [[$:/core/ui/Buttons/fold]]" }, "$:/snippets/themeswitcher": { "title": "$:/snippets/themeswitcher", "text": "\\define lingo-base() $:/language/ControlPanel/Theme/\n<<lingo Prompt>> <$view tiddler={{$:/theme}} field=\"name\"/>\n\n<$linkcatcher to=\"$:/theme\">\n<$list filter=\"[plugin-type[theme]sort[title]]\"><div><$reveal state=\"$:/theme\" type=\"match\" text={{!!title}}>•</$reveal><$reveal state=\"$:/theme\" type=\"nomatch\" text={{!!title}}> </$reveal> <$link to={{!!title}}>''<$view field=\"name\" format=\"text\"/>'' <$view field=\"description\" format=\"text\"/></$link></div>\n</$list>\n</$linkcatcher>" }, "$:/core/wiki/title": { "title": "$:/core/wiki/title", "type": "text/vnd.tiddlywiki", "text": "{{$:/SiteTitle}} --- {{$:/SiteSubtitle}}" }, "$:/view": { "title": "$:/view", "text": "classic" }, "$:/snippets/viewswitcher": { "title": "$:/snippets/viewswitcher", "text": "\\define lingo-base() $:/language/ControlPanel/StoryView/\n<<lingo Prompt>> <$select tiddler=\"$:/view\">\n<$list filter=\"[storyviews[]]\">\n<option><$view field=\"title\"/></option>\n</$list>\n</$select>" } } }
\define tv-wikilink-template() http://tiddlywiki.com/dev/static/$uri_doubleencoded$.html <!-- For Google, and people without JavaScript--> <$reveal state="!!hack-to-give-us-something-to-compare-against" type="nomatch" text=<<savingEmpty>>> It looks like this browser doesn't run JavaScript. You can use one of these static HTML versions to browse the same content: * http://tiddlywiki.com/dev/static.html - browse individual tiddlers as separate pages * http://tiddlywiki.com/dev/alltiddlers.html#HelloThere - single file containing all tiddlers --- {{HelloThere}} </$reveal>
[list[$:/StoryList]]
<div class="github-fork-ribbon-wrapper right" style><div class="github-fork-ribbon" style="background-color:#DF4848;"><a href="https://github.com/Jermolene/TiddlyWiki5" target="_blank" rel="noopener noreferrer">Find me on ~GitHub</a></div></div>
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tV7o7VRVhUwmU/WYoijO0KFDX33yySefGzVqFH5ZCFogCHKsMnfu3MLQoUM//OCDD9Y1NTW1KopSk8vlTvCKg7DV6+yQKp4FwmvsKMsyJJPJqtnnhmF0n3nmmf/yne98Zxt+O0gQMI0XQT5n8vk8rFy50li9evWEjo6O6z/++OMrU6lUi2VZEZ6FwVogpAiQp3TobVkF0t7eDoVCgVSgO+edd95v77///p82NTVh5hUSCHRhIcjnjGEYkMlk8sViccOQIUM+/uijjxZs2bLlvFWrVt2dy+UavKrTedaIV0CdPGeaZlXVeX19/U4AeACVB4IKBEG+YESj0YpBAgBrFy1atL2zszPd1dX1je7u7mmmaTZwXQiMYvCrBSE/tm1XFIiqqk5LS8vvL7300s6nnnoKvwwkMBgDQZBjkLlz5+bGjx//QTKZXF5bW7tVUZSobduaaZo19KRAWjl49caiFY0sy5DP5yGXy4Esy9DQ0PDWpEmTfvuzn/1sP37yCFogCPJFvzFLvbUsAGhdtmzZk++///5LK1eu/F/ZbPZO13WbRUOs2HbtPMuEnkCoqmpaUZSXb7rppu3/8z//gx88MigwiI4gXxCKxSL88pe/PPOtt976tizLF6fT6XFAFQN7tT2hH3McB3p6eiCfz0NTU9OrS5YsuaqxsTGPnzCCFgiCHKdomgYAsPa5557bsGrVqvPXr19/dyqVmiFJkhG09TttoWialh0/fvyfUHkgBwu2MkGQLxhXX321deWVV75dW1t7y1lnnfV9RVF2KopiidJ3efNAbNuGKVOmPPf1r399MX6iCFogCPIl4pxzzrEAoHXu3LmPhUKhhV1dXf/w2Wef/Z1lWaNt29ZpJcIWGVqWBdFotD0Wiz0wZcoUtD6QgwZjIAhyHJDNZuV/+Id/OLujo+OaQqFwZTabHeY4ToRt5R4OhyGZTDoNDQ2/vu222+791re+hR13EVQgCIIALFu2LDZ37tyz29vbb+/o6LgMAAxJkiqu6lAo5DiOs2n8+PHf/+Mf/7iiHFdBkIMCYyAIchwxc+bM9K233ro0Ho/fcfHFF1+vadpaSZL6iAsrFAp11dTULPjqV7+6GpUHghYIgiBcnnjiCXjrrbdifX19/29ra+tVrutOmDVr1j3nn3/+ExdccMEe/IQQBEEQTzKZjDxr1qwzv/71r99zzz33nI+fCIIgCDIoNm3aZLS3t2PmJYIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgyBeB/x+kYj1YVqBWTAAAAABJRU5ErkJggg==
UA-32839735-1
tiddlywiki.com
The following tiddlers were imported: # [[rebol.png]]
no
$:/languages/en-GB
{ "tiddlers": { "$:/language/Buttons/AdvancedSearch/Caption": { "title": "$:/language/Buttons/AdvancedSearch/Caption", "text": "Erweiterte Suche" }, "$:/language/Buttons/AdvancedSearch/Hint": { "title": "$:/language/Buttons/AdvancedSearch/Hint", "text": "Erweiterte Suche" }, "$:/language/Buttons/Cancel/Caption": { "title": "$:/language/Buttons/Cancel/Caption", "text": "Abbrechen" }, "$:/language/Buttons/Cancel/Hint": { "title": "$:/language/Buttons/Cancel/Hint", "text": "Änderungen verwerfen" }, "$:/language/Buttons/Clone/Caption": { "title": "$:/language/Buttons/Clone/Caption", "text": "Klone" }, "$:/language/Buttons/Clone/Hint": { "title": "$:/language/Buttons/Clone/Hint", "text": "Klone diesen Tiddler" }, "$:/language/Buttons/Close/Caption": { "title": "$:/language/Buttons/Close/Caption", "text": "Schließen" }, "$:/language/Buttons/Close/Hint": { "title": "$:/language/Buttons/Close/Hint", "text": "Schließe diesen Tiddler" }, "$:/language/Buttons/CloseAll/Caption": { "title": "$:/language/Buttons/CloseAll/Caption", "text": "Alle schließen" }, "$:/language/Buttons/CloseAll/Hint": { "title": "$:/language/Buttons/CloseAll/Hint", "text": "Alle Tiddler schließen" }, "$:/language/Buttons/CloseOthers/Caption": { "title": "$:/language/Buttons/CloseOthers/Caption", "text": "Andere schließen" }, "$:/language/Buttons/CloseOthers/Hint": { "title": "$:/language/Buttons/CloseOthers/Hint", "text": "Alle anderen Tiddler schließen" }, "$:/language/Buttons/ControlPanel/Caption": { "title": "$:/language/Buttons/ControlPanel/Caption", "text": "Control-Panel" }, "$:/language/Buttons/ControlPanel/Hint": { "title": "$:/language/Buttons/ControlPanel/Hint", "text": "Öffne das Control-Panel" }, "$:/language/Buttons/Delete/Caption": { "title": "$:/language/Buttons/Delete/Caption", "text": "Löschen" }, "$:/language/Buttons/Delete/Hint": { "title": "$:/language/Buttons/Delete/Hint", "text": "Lösche diesen Tiddler" }, "$:/language/Buttons/Edit/Caption": { "title": "$:/language/Buttons/Edit/Caption", "text": "Bearbeiten" }, "$:/language/Buttons/Edit/Hint": { "title": "$:/language/Buttons/Edit/Hint", "text": "Bearbeite diesen Tiddler" }, "$:/language/Buttons/Encryption/Caption": { "title": "$:/language/Buttons/Encryption/Caption", "text": "Verschlüsselung" }, "$:/language/Buttons/Encryption/Hint": { "title": "$:/language/Buttons/Encryption/Hint", "text": "Aktivieren oder löschen des Passworts für dieses Wiki" }, "$:/language/Buttons/Encryption/ClearPassword/Caption": { "title": "$:/language/Buttons/Encryption/ClearPassword/Caption", "text": "Verschlüsselung deaktivieren" }, "$:/language/Buttons/Encryption/ClearPassword/Hint": { "title": "$:/language/Buttons/Encryption/ClearPassword/Hint", "text": "Lösche das Passwort und speichere ohne Verschlüsselung" }, "$:/language/Buttons/Encryption/SetPassword/Caption": { "title": "$:/language/Buttons/Encryption/SetPassword/Caption", "text": "Verschlüsselung" }, "$:/language/Buttons/Encryption/SetPassword/Hint": { "title": "$:/language/Buttons/Encryption/SetPassword/Hint", "text": "Definiert ein Passwort, um dieses Wiki zu verschlüsseln" }, "$:/language/Buttons/ExportPage/Caption": { "title": "$:/language/Buttons/ExportPage/Caption", "text": "Alle exportieren" }, "$:/language/Buttons/ExportPage/Hint": { "title": "$:/language/Buttons/ExportPage/Hint", "text": "Alle Tiddler exportieren" }, "$:/language/Buttons/ExportTiddler/Caption": { "title": "$:/language/Buttons/ExportTiddler/Caption", "text": "Exportieren" }, "$:/language/Buttons/ExportTiddler/Hint": { "title": "$:/language/Buttons/ExportTiddler/Hint", "text": "Diesen Tiddler exportieren" }, "$:/language/Buttons/ExportTiddlers/Caption": { "title": "$:/language/Buttons/ExportTiddlers/Caption", "text": "Mehrere exportieren" }, "$:/language/Buttons/ExportTiddlers/Hint": { "title": "$:/language/Buttons/ExportTiddlers/Hint", "text": "Mehrere Tiddler exportieren" }, "$:/language/Buttons/Fold/Caption": { "title": "$:/language/Buttons/Fold/Caption", "text": "Ausblenden Textbereich" }, "$:/language/Buttons/Fold/Hint": { "title": "$:/language/Buttons/Fold/Hint", "text": "Der Tiddler Textbereich wird ausgeblendet" }, "$:/language/Buttons/Fold/FoldBar/Caption": { "title": "$:/language/Buttons/Fold/FoldBar/Caption", "text": "Textbereich ein/aus" }, "$:/language/Buttons/Fold/FoldBar/Hint": { "title": "$:/language/Buttons/Fold/FoldBar/Hint", "text": "Optionelle Buttons im Tiddler, um den Textbereich ein- bzw. auszublenden" }, "$:/language/Buttons/Unfold/Caption": { "title": "$:/language/Buttons/Unfold/Caption", "text": "Einblenden Textbereich" }, "$:/language/Buttons/Unfold/Hint": { "title": "$:/language/Buttons/Unfold/Hint", "text": "Der Tiddler Textbereich wird eingeblendet" }, "$:/language/Buttons/FoldOthers/Caption": { "title": "$:/language/Buttons/FoldOthers/Caption", "text": "Ausblenden andere Textbereiche" }, "$:/language/Buttons/FoldOthers/Hint": { "title": "$:/language/Buttons/FoldOthers/Hint", "text": "Die Textbereiche aller anderen Tiddler werden ausgeblendet" }, "$:/language/Buttons/FoldAll/Caption": { "title": "$:/language/Buttons/FoldAll/Caption", "text": "Ausblenden aller Textbereiche" }, "$:/language/Buttons/FoldAll/Hint": { "title": "$:/language/Buttons/FoldAll/Hint", "text": "Ausblenden der Textbereiche aller Tiddler" }, "$:/language/Buttons/UnfoldAll/Caption": { "title": "$:/language/Buttons/UnfoldAll/Caption", "text": "Einblenden aller Textbereiche" }, "$:/language/Buttons/UnfoldAll/Hint": { "title": "$:/language/Buttons/UnfoldAll/Hint", "text": "Einblenden der Textbereiche aller Tiddler" }, "$:/language/Buttons/FullScreen/Caption": { "title": "$:/language/Buttons/FullScreen/Caption", "text": "Vollbild" }, "$:/language/Buttons/FullScreen/Hint": { "title": "$:/language/Buttons/FullScreen/Hint", "text": "Aktivieren oder Deaktivieren des Vollbild-Modus" }, "$:/language/Buttons/Help/Caption": { "title": "$:/language/Buttons/Help/Caption", "text": "Hilfe" }, "$:/language/Buttons/Help/Hint": { "title": "$:/language/Buttons/Help/Hint", "text": "Hilfe anzeigen" }, "$:/language/Buttons/Import/Caption": { "title": "$:/language/Buttons/Import/Caption", "text": "Import" }, "$:/language/Buttons/Import/Hint": { "title": "$:/language/Buttons/Import/Hint", "text": "Importiere unterschiedliche Dateitypen. zB: Text, Bilder, TiddlyWiki oder JSON" }, "$:/language/Buttons/Info/Caption": { "title": "$:/language/Buttons/Info/Caption", "text": "Info" }, "$:/language/Buttons/Info/Hint": { "title": "$:/language/Buttons/Info/Hint", "text": "Informationen zu diesem Tiddler anzeigen" }, "$:/language/Buttons/Home/Caption": { "title": "$:/language/Buttons/Home/Caption", "text": "Home" }, "$:/language/Buttons/Home/Hint": { "title": "$:/language/Buttons/Home/Hint", "text": "Öffnen der Standard-Tiddler" }, "$:/language/Buttons/Language/Caption": { "title": "$:/language/Buttons/Language/Caption", "text": "Sprache" }, "$:/language/Buttons/Language/Hint": { "title": "$:/language/Buttons/Language/Hint", "text": "Auswahldialog für die Systemsprache" }, "$:/language/Buttons/Manager/Caption": { "title": "$:/language/Buttons/Manager/Caption", "text": "Tiddler Manager" }, "$:/language/Buttons/Manager/Hint": { "title": "$:/language/Buttons/Manager/Hint", "text": "Öffne den Tiddler Manager" }, "$:/language/Buttons/More/Caption": { "title": "$:/language/Buttons/More/Caption", "text": "mehr" }, "$:/language/Buttons/More/Hint": { "title": "$:/language/Buttons/More/Hint", "text": "Weitere Aktionen" }, "$:/language/Buttons/NewHere/Caption": { "title": "$:/language/Buttons/NewHere/Caption", "text": "Neu hier" }, "$:/language/Buttons/NewHere/Hint": { "title": "$:/language/Buttons/NewHere/Hint", "text": "Erstelle einen neuen Tiddler, der mit dem Namen dieses Tiddlers getaggt ist" }, "$:/language/Buttons/NewJournal/Caption": { "title": "$:/language/Buttons/NewJournal/Caption", "text": "Neues Journal" }, "$:/language/Buttons/NewJournal/Hint": { "title": "$:/language/Buttons/NewJournal/Hint", "text": "Erstelle einen neuen Journal-Tiddler" }, "$:/language/Buttons/NewJournalHere/Caption": { "title": "$:/language/Buttons/NewJournalHere/Caption", "text": "Neues Journal hier" }, "$:/language/Buttons/NewJournalHere/Hint": { "title": "$:/language/Buttons/NewJournalHere/Hint", "text": "Erstelle ein neues Journal der mit diesem getaggt ist" }, "$:/language/Buttons/NewImage/Caption": { "title": "$:/language/Buttons/NewImage/Caption", "text": "Neues Bild" }, "$:/language/Buttons/NewImage/Hint": { "title": "$:/language/Buttons/NewImage/Hint", "text": "Erstelle ein neues Bild" }, "$:/language/Buttons/NewMarkdown/Caption": { "title": "$:/language/Buttons/NewMarkdown/Caption", "text": "Neuer Markdown Tiddler" }, "$:/language/Buttons/NewMarkdown/Hint": { "title": "$:/language/Buttons/NewMarkdown/Hint", "text": "Erstelle einen neuen \"Markdown\" Tiddler" }, "$:/language/Buttons/NewTiddler/Caption": { "title": "$:/language/Buttons/NewTiddler/Caption", "text": "Neuer Tiddler" }, "$:/language/Buttons/NewTiddler/Hint": { "title": "$:/language/Buttons/NewTiddler/Hint", "text": "Erstelle einen neuen Tiddler" }, "$:/language/Buttons/OpenWindow/Caption": { "title": "$:/language/Buttons/OpenWindow/Caption", "text": "Öffne in neuem Fenster" }, "$:/language/Buttons/OpenWindow/Hint": { "title": "$:/language/Buttons/OpenWindow/Hint", "text": "Öffne diesen Tiddler in einem neuen Fenster" }, "$:/language/Buttons/Palette/Caption": { "title": "$:/language/Buttons/Palette/Caption", "text": "Palette" }, "$:/language/Buttons/Palette/Hint": { "title": "$:/language/Buttons/Palette/Hint", "text": "Wähle eine Farbpalette" }, "$:/language/Buttons/Permalink/Caption": { "title": "$:/language/Buttons/Permalink/Caption", "text": "Permalink" }, "$:/language/Buttons/Permalink/Hint": { "title": "$:/language/Buttons/Permalink/Hint", "text": "Die Adressleiste des Browsers enthält einen Link zu diesem Tiddler" }, "$:/language/Buttons/Permaview/Caption": { "title": "$:/language/Buttons/Permaview/Caption", "text": "Permaview" }, "$:/language/Buttons/Permaview/Hint": { "title": "$:/language/Buttons/Permaview/Hint", "text": "Die Adressleiste des Browsers enthält einen Link zu allen offenen Tiddlern in dieser Story" }, "$:/language/Buttons/Print/Caption": { "title": "$:/language/Buttons/Print/Caption", "text": "Seite drucken" }, "$:/language/Buttons/Print/Hint": { "title": "$:/language/Buttons/Print/Hint", "text": "Aktuelle Seite drucken" }, "$:/language/Buttons/Refresh/Caption": { "title": "$:/language/Buttons/Refresh/Caption", "text": "Aktualisieren" }, "$:/language/Buttons/Refresh/Hint": { "title": "$:/language/Buttons/Refresh/Hint", "text": "Die Seite wird neu in den Browser geladen" }, "$:/language/Buttons/Save/Caption": { "title": "$:/language/Buttons/Save/Caption", "text": "Fertig" }, "$:/language/Buttons/Save/Hint": { "title": "$:/language/Buttons/Save/Hint", "text": "Änderungen für diesen Tiddler bestätigen" }, "$:/language/Buttons/SaveWiki/Caption": { "title": "$:/language/Buttons/SaveWiki/Caption", "text": "Speichern" }, "$:/language/Buttons/SaveWiki/Hint": { "title": "$:/language/Buttons/SaveWiki/Hint", "text": "Das Wiki speichern" }, "$:/language/Buttons/StoryView/Caption": { "title": "$:/language/Buttons/StoryView/Caption", "text": "Story-Modus" }, "$:/language/Buttons/StoryView/Hint": { "title": "$:/language/Buttons/StoryView/Hint", "text": "Auswahl des Anzeigemodus für die Story" }, "$:/language/Buttons/HideSideBar/Caption": { "title": "$:/language/Buttons/HideSideBar/Caption", "text": "Sidebar ausblenden" }, "$:/language/Buttons/HideSideBar/Hint": { "title": "$:/language/Buttons/HideSideBar/Hint", "text": "Sidebar ausblenden" }, "$:/language/Buttons/ShowSideBar/Caption": { "title": "$:/language/Buttons/ShowSideBar/Caption", "text": "Sidebar einblenden" }, "$:/language/Buttons/ShowSideBar/Hint": { "title": "$:/language/Buttons/ShowSideBar/Hint", "text": "Sidebar einblenden" }, "$:/language/Buttons/TagManager/Caption": { "title": "$:/language/Buttons/TagManager/Caption", "text": "Tag-Manager" }, "$:/language/Buttons/TagManager/Hint": { "title": "$:/language/Buttons/TagManager/Hint", "text": "Öffne den Tag-Manager" }, "$:/language/Buttons/Timestamp/Caption": { "title": "$:/language/Buttons/Timestamp/Caption", "text": "Zeitstempel" }, "$:/language/Buttons/Timestamp/Hint": { "title": "$:/language/Buttons/Timestamp/Hint", "text": "Einstellung, ob Änderungen den Zeitstempel beeinflussen" }, "$:/language/Buttons/Timestamp/On/Caption": { "title": "$:/language/Buttons/Timestamp/On/Caption", "text": "Zeitstempel EIN" }, "$:/language/Buttons/Timestamp/On/Hint": { "title": "$:/language/Buttons/Timestamp/On/Hint", "text": "Zeitstempel aktualisieren, wenn ein Tiddler verändert wird" }, "$:/language/Buttons/Timestamp/Off/Caption": { "title": "$:/language/Buttons/Timestamp/Off/Caption", "text": "Zeitstempel AUS" }, "$:/language/Buttons/Timestamp/Off/Hint": { "title": "$:/language/Buttons/Timestamp/Off/Hint", "text": "Zeitstempel bleibt unverändert, wenn ein Tiddler geändert wird" }, "$:/language/Buttons/Theme/Caption": { "title": "$:/language/Buttons/Theme/Caption", "text": "Theme" }, "$:/language/Buttons/Theme/Hint": { "title": "$:/language/Buttons/Theme/Hint", "text": "Theme auswählen" }, "$:/language/Buttons/Bold/Caption": { "title": "$:/language/Buttons/Bold/Caption", "text": "Fett" }, "$:/language/Buttons/Bold/Hint": { "title": "$:/language/Buttons/Bold/Hint", "text": "Ausgewählten Text fett darstellen" }, "$:/language/Buttons/Clear/Caption": { "title": "$:/language/Buttons/Clear/Caption", "text": "Löschen" }, "$:/language/Buttons/Clear/Hint": { "title": "$:/language/Buttons/Clear/Hint", "text": "Bild mit Hintergrund Farbe löschen" }, "$:/language/Buttons/EditorHeight/Caption": { "title": "$:/language/Buttons/EditorHeight/Caption", "text": "Editor Höhe" }, "$:/language/Buttons/EditorHeight/Caption/Auto": { "title": "$:/language/Buttons/EditorHeight/Caption/Auto", "text": "Editor Höhe an Inhalt anpassen" }, "$:/language/Buttons/EditorHeight/Caption/Fixed": { "title": "$:/language/Buttons/EditorHeight/Caption/Fixed", "text": "Fixe Höhe:" }, "$:/language/Buttons/EditorHeight/Hint": { "title": "$:/language/Buttons/EditorHeight/Hint", "text": "Wählen Sie die Höhe des Editors" }, "$:/language/Buttons/Excise/Caption": { "title": "$:/language/Buttons/Excise/Caption", "text": "Verschieben" }, "$:/language/Buttons/Excise/Caption/Excise": { "title": "$:/language/Buttons/Excise/Caption/Excise", "text": "Text verschieben" }, "$:/language/Buttons/Excise/Caption/MacroName": { "title": "$:/language/Buttons/Excise/Caption/MacroName", "text": "Makro Name:" }, "$:/language/Buttons/Excise/Caption/NewTitle": { "title": "$:/language/Buttons/Excise/Caption/NewTitle", "text": "Titel des neuen Tiddlers:" }, "$:/language/Buttons/Excise/Caption/Replace": { "title": "$:/language/Buttons/Excise/Caption/Replace", "text": "Ersetze den verschobenen Text mit:" }, "$:/language/Buttons/Excise/Caption/Replace/Macro": { "title": "$:/language/Buttons/Excise/Caption/Replace/Macro", "text": "Makro" }, "$:/language/Buttons/Excise/Caption/Replace/Link": { "title": "$:/language/Buttons/Excise/Caption/Replace/Link", "text": "Link" }, "$:/language/Buttons/Excise/Caption/Replace/Transclusion": { "title": "$:/language/Buttons/Excise/Caption/Replace/Transclusion", "text": "Transklusion" }, "$:/language/Buttons/Excise/Caption/Tag": { "title": "$:/language/Buttons/Excise/Caption/Tag", "text": "Tagge den neuen Tiddler mit dem Titel des aktuellen Tiddlers" }, "$:/language/Buttons/Excise/Caption/TiddlerExists": { "title": "$:/language/Buttons/Excise/Caption/TiddlerExists", "text": "Warnung: Tiddler existiert bereits!" }, "$:/language/Buttons/Excise/Hint": { "title": "$:/language/Buttons/Excise/Hint", "text": "Verschiebe den ausgewählten Text in einen neuen Tiddler" }, "$:/language/Buttons/Heading1/Caption": { "title": "$:/language/Buttons/Heading1/Caption", "text": "Überschrift 1" }, "$:/language/Buttons/Heading1/Hint": { "title": "$:/language/Buttons/Heading1/Hint", "text": "Überschrift 1 auf die Zeilen anwenden, die eine Auswahl enthalten" }, "$:/language/Buttons/Heading2/Caption": { "title": "$:/language/Buttons/Heading2/Caption", "text": "Überschrift 2" }, "$:/language/Buttons/Heading2/Hint": { "title": "$:/language/Buttons/Heading2/Hint", "text": "Überschrift 2 auf die Zeilen anwenden, die eine Auswahl enthalten" }, "$:/language/Buttons/Heading3/Caption": { "title": "$:/language/Buttons/Heading3/Caption", "text": "Überschrift 3" }, "$:/language/Buttons/Heading3/Hint": { "title": "$:/language/Buttons/Heading3/Hint", "text": "Überschrift 3 auf die Zeilen anwenden, die eine Auswahl enthalten" }, "$:/language/Buttons/Heading4/Caption": { "title": "$:/language/Buttons/Heading4/Caption", "text": "Überschrift 4" }, "$:/language/Buttons/Heading4/Hint": { "title": "$:/language/Buttons/Heading4/Hint", "text": "Überschrift 4 auf die Zeilen anwenden, die eine Auswahl enthalten" }, "$:/language/Buttons/Heading5/Caption": { "title": "$:/language/Buttons/Heading5/Caption", "text": "Überschrift 5" }, "$:/language/Buttons/Heading5/Hint": { "title": "$:/language/Buttons/Heading5/Hint", "text": "Überschrift 5 auf die Zeilen anwenden, die eine Auswahl enthalten" }, "$:/language/Buttons/Heading6/Caption": { "title": "$:/language/Buttons/Heading6/Caption", "text": "Überschrift 6" }, "$:/language/Buttons/Heading6/Hint": { "title": "$:/language/Buttons/Heading6/Hint", "text": "Überschrift 6 auf die Zeilen anwenden, die eine Auswahl enthalten" }, "$:/language/Buttons/Italic/Caption": { "title": "$:/language/Buttons/Italic/Caption", "text": "Kursiv" }, "$:/language/Buttons/Italic/Hint": { "title": "$:/language/Buttons/Italic/Hint", "text": "Kursiv auf den selektierten Text anwenden" }, "$:/language/Buttons/LineWidth/Caption": { "title": "$:/language/Buttons/LineWidth/Caption", "text": "Zeilen Länge" }, "$:/language/Buttons/LineWidth/Hint": { "title": "$:/language/Buttons/LineWidth/Hint", "text": "Wählen Sie die Zeilenlänge" }, "$:/language/Buttons/Link/Caption": { "title": "$:/language/Buttons/Link/Caption", "text": "Link" }, "$:/language/Buttons/Link/Hint": { "title": "$:/language/Buttons/Link/Hint", "text": "Erstellt einen Wiki-Link" }, "$:/language/Buttons/ListBullet/Caption": { "title": "$:/language/Buttons/ListBullet/Caption", "text": "Punkteliste" }, "$:/language/Buttons/ListBullet/Hint": { "title": "$:/language/Buttons/ListBullet/Hint", "text": "Zeilen, die eine Markierung enthalten, werden als Punkteliste formatiert" }, "$:/language/Buttons/ListNumber/Caption": { "title": "$:/language/Buttons/ListNumber/Caption", "text": "Aufzählungsliste" }, "$:/language/Buttons/ListNumber/Hint": { "title": "$:/language/Buttons/ListNumber/Hint", "text": "Zeilen, die eine Markierung enthalten, werden als Auzählungsliste formatiert" }, "$:/language/Buttons/MonoBlock/Caption": { "title": "$:/language/Buttons/MonoBlock/Caption", "text": "Dicktengleicher Textblock" }, "$:/language/Buttons/MonoBlock/Hint": { "title": "$:/language/Buttons/MonoBlock/Hint", "text": "Alle Zeilen die eine Markierung enthalten, werden als Textblock mit einer dicktengleichen Schrift formatiert" }, "$:/language/Buttons/MonoLine/Caption": { "title": "$:/language/Buttons/MonoLine/Caption", "text": "Dicktengleich" }, "$:/language/Buttons/MonoLine/Hint": { "title": "$:/language/Buttons/MonoLine/Hint", "text": "Alle markierten Zeichen werden mit einer dicktengleichen Schrift formatiert" }, "$:/language/Buttons/Opacity/Caption": { "title": "$:/language/Buttons/Opacity/Caption", "text": "Transparenz" }, "$:/language/Buttons/Opacity/Hint": { "title": "$:/language/Buttons/Opacity/Hint", "text": "Wählen sie die Transparenz" }, "$:/language/Buttons/Paint/Caption": { "title": "$:/language/Buttons/Paint/Caption", "text": "Malfarbe" }, "$:/language/Buttons/Paint/Hint": { "title": "$:/language/Buttons/Paint/Hint", "text": "Wählen Sie die Malfarbe" }, "$:/language/Buttons/Picture/Caption": { "title": "$:/language/Buttons/Picture/Caption", "text": "Bild" }, "$:/language/Buttons/Picture/Hint": { "title": "$:/language/Buttons/Picture/Hint", "text": "Bild einfügen" }, "$:/language/Buttons/Preview/Caption": { "title": "$:/language/Buttons/Preview/Caption", "text": "Vorschau" }, "$:/language/Buttons/Preview/Hint": { "title": "$:/language/Buttons/Preview/Hint", "text": "Vorschau einblenden" }, "$:/language/Buttons/PreviewType/Caption": { "title": "$:/language/Buttons/PreviewType/Caption", "text": "Vorschau Typ" }, "$:/language/Buttons/PreviewType/Hint": { "title": "$:/language/Buttons/PreviewType/Hint", "text": "Wählen Sie den Vorschau Typ" }, "$:/language/Buttons/Quote/Caption": { "title": "$:/language/Buttons/Quote/Caption", "text": "Zitat" }, "$:/language/Buttons/Quote/Hint": { "title": "$:/language/Buttons/Quote/Hint", "text": "Alle Zeilen, die eine Markierung enthalten werden als Referenz/Zitat formatiert" }, "$:/language/Buttons/Size/Caption": { "title": "$:/language/Buttons/Size/Caption", "text": "Bildgröße" }, "$:/language/Buttons/Size/Caption/Height": { "title": "$:/language/Buttons/Size/Caption/Height", "text": "Höhe:" }, "$:/language/Buttons/Size/Caption/Resize": { "title": "$:/language/Buttons/Size/Caption/Resize", "text": "Bildgröße ändern" }, "$:/language/Buttons/Size/Caption/Width": { "title": "$:/language/Buttons/Size/Caption/Width", "text": "Weite:" }, "$:/language/Buttons/Size/Hint": { "title": "$:/language/Buttons/Size/Hint", "text": "Bildweite ändern" }, "$:/language/Buttons/Stamp/Caption": { "title": "$:/language/Buttons/Stamp/Caption", "text": "Stempel" }, "$:/language/Buttons/Stamp/Caption/New": { "title": "$:/language/Buttons/Stamp/Caption/New", "text": "Eigenen Stempel erstellen" }, "$:/language/Buttons/Stamp/Hint": { "title": "$:/language/Buttons/Stamp/Hint", "text": "Textschnipsel hier einfügen" }, "$:/language/Buttons/Stamp/New/Title": { "title": "$:/language/Buttons/Stamp/New/Title", "text": "Name, der im Menü angezeigt werden soll" }, "$:/language/Buttons/Stamp/New/Text": { "title": "$:/language/Buttons/Stamp/New/Text", "text": "Text des Schnipsels. (Nicher vergessen eine aussagekräftigen Titel zu verwenden)" }, "$:/language/Buttons/Strikethrough/Caption": { "title": "$:/language/Buttons/Strikethrough/Caption", "text": "Durchgestrichen" }, "$:/language/Buttons/Strikethrough/Hint": { "title": "$:/language/Buttons/Strikethrough/Hint", "text": "Ausgewählten Text durchgestrichen darstgellen" }, "$:/language/Buttons/Subscript/Caption": { "title": "$:/language/Buttons/Subscript/Caption", "text": "Tiefsgestellt" }, "$:/language/Buttons/Subscript/Hint": { "title": "$:/language/Buttons/Subscript/Hint", "text": "Ausgewählten Text tiefgestellt darstellen" }, "$:/language/Buttons/Superscript/Caption": { "title": "$:/language/Buttons/Superscript/Caption", "text": "Hochgestellt" }, "$:/language/Buttons/Superscript/Hint": { "title": "$:/language/Buttons/Superscript/Hint", "text": "Ausgewählten Text hochgestellt darstellen" }, "$:/language/Buttons/Underline/Caption": { "title": "$:/language/Buttons/Underline/Caption", "text": "Unterstreichen" }, "$:/language/Buttons/Underline/Hint": { "title": "$:/language/Buttons/Underline/Hint", "text": "Ausgewählten Text unterstrichen darstellen" }, "$:/language/ControlPanel/Advanced/Caption": { "title": "$:/language/ControlPanel/Advanced/Caption", "text": "Erweitert" }, "$:/language/ControlPanel/Advanced/Hint": { "title": "$:/language/ControlPanel/Advanced/Hint", "text": "Interne Informationen über dieses ~TiddlyWiki." }, "$:/language/ControlPanel/Appearance/Caption": { "title": "$:/language/ControlPanel/Appearance/Caption", "text": "Design" }, "$:/language/ControlPanel/Appearance/Hint": { "title": "$:/language/ControlPanel/Appearance/Hint", "text": "Möglichkeiten um das Aussehen Ihres ~TiddlyWikis anzupassen." }, "$:/language/ControlPanel/Basics/AnimDuration/Prompt": { "title": "$:/language/ControlPanel/Basics/AnimDuration/Prompt", "text": "Dauer der Animation:" }, "$:/language/ControlPanel/Basics/Caption": { "title": "$:/language/ControlPanel/Basics/Caption", "text": "Basis" }, "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint": { "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint", "text": "Verwenden Sie [[doppelte eckige Klammern]] für Titel mit Leerzeichen oder wählen Sie <$button set=\"$:/DefaultTiddlers\" setTo=\"[list[$:/StoryList]]\">Offene Tiddler beim Laden wiederherstellen.</$button>" }, "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt", "text": "Standard-Tiddler:" }, "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint": { "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint", "text": "Tiddler, die beim Start geladen werden:" }, "$:/language/ControlPanel/Basics/Language/Prompt": { "title": "$:/language/ControlPanel/Basics/Language/Prompt", "text": "Hallo! Aktuelle Sprache:" }, "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt": { "title": "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt", "text": "Titel des neuen Journal-Tiddlers:" }, "$:/language/ControlPanel/Basics/NewJournal/Text/Prompt": { "title": "$:/language/ControlPanel/Basics/NewJournal/Text/Prompt", "text": "Text des neuen Journal-Tiddlers:" }, "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt": { "title": "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt", "text": "Tags des neuen Journal-Tiddlers:" }, "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt", "text": "Anzahl überschriebener Schatten-Tiddler:" }, "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt", "text": "Anzahl Schatten-Tiddler:" }, "$:/language/ControlPanel/Basics/Subtitle/Prompt": { "title": "$:/language/ControlPanel/Basics/Subtitle/Prompt", "text": "Untertitel:" }, "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt", "text": "Anzahl System-Tiddler:" }, "$:/language/ControlPanel/Basics/Tags/Prompt": { "title": "$:/language/ControlPanel/Basics/Tags/Prompt", "text": "Anzahl Tags:" }, "$:/language/ControlPanel/Basics/Tiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/Tiddlers/Prompt", "text": "Anzahl Tiddler:" }, "$:/language/ControlPanel/Basics/Title/Prompt": { "title": "$:/language/ControlPanel/Basics/Title/Prompt", "text": "Titel dieses ~TiddlyWikis:" }, "$:/language/ControlPanel/Basics/Username/Prompt": { "title": "$:/language/ControlPanel/Basics/Username/Prompt", "text": "Benutzersignatur zum Editieren:" }, "$:/language/ControlPanel/Basics/Version/Prompt": { "title": "$:/language/ControlPanel/Basics/Version/Prompt", "text": "~TiddlyWiki Version:" }, "$:/language/ControlPanel/EditorTypes/Caption": { "title": "$:/language/ControlPanel/EditorTypes/Caption", "text": "Editor Typen" }, "$:/language/ControlPanel/EditorTypes/Editor/Caption": { "title": "$:/language/ControlPanel/EditorTypes/Editor/Caption", "text": "Editor" }, "$:/language/ControlPanel/EditorTypes/Hint": { "title": "$:/language/ControlPanel/EditorTypes/Hint", "text": "Diese Tiddler definieren, welcher Editor für bestimmte Tiddler Typen (MIME-Type) verwendet werden soll." }, "$:/language/ControlPanel/EditorTypes/Type/Caption": { "title": "$:/language/ControlPanel/EditorTypes/Type/Caption", "text": "MIME-Type" }, "$:/language/ControlPanel/Info/Caption": { "title": "$:/language/ControlPanel/Info/Caption", "text": "Info" }, "$:/language/ControlPanel/Info/Hint": { "title": "$:/language/ControlPanel/Info/Hint", "text": "Informationen über dieses TiddlyWiki" }, "$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Add/Prompt", "text": "Tastenkürzel hier eingeben" }, "$:/language/ControlPanel/KeyboardShortcuts/Add/Caption": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Add/Caption", "text": "Tastenkürzel erstellen" }, "$:/language/ControlPanel/KeyboardShortcuts/Caption": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Caption", "text": "Tastenkürzel" }, "$:/language/ControlPanel/KeyboardShortcuts/Hint": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Hint", "text": "Tastenkürzel Zuweisungen bearbeiten" }, "$:/language/ControlPanel/KeyboardShortcuts/NoShortcuts/Caption": { "title": "$:/language/ControlPanel/KeyboardShortcuts/NoShortcuts/Caption", "text": "Keine Tastenkürzel Zusweisungen vorhanden" }, "$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Remove/Hint", "text": "Löschen eines Tastenkürzels" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/All": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/All", "text": "Alle Plattformen" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/Mac": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Mac", "text": "Nur Macintosh" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonMac": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonMac", "text": "Alle Plattformen, außer Macintosh" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/Linux": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Linux", "text": "Nur Linux" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonLinux": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonLinux", "text": "Alle Plattformen, außer Linux" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/Windows": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/Windows", "text": "Nur Windows" }, "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonWindows": { "title": "$:/language/ControlPanel/KeyboardShortcuts/Platform/NonWindows", "text": "Alle Plattformen, außer Windows" }, "$:/language/ControlPanel/LoadedModules/Caption": { "title": "$:/language/ControlPanel/LoadedModules/Caption", "text": "Geladene Module" }, "$:/language/ControlPanel/LoadedModules/Hint": { "title": "$:/language/ControlPanel/LoadedModules/Hint", "text": "Hier werden die geladenen Module und ihre Quelltext-Komponenten angezeigt. Kursiv hervorgehobene Tiddler haben keinen Quelltext. Sie werden während des Boot-Prozesses (Aufrufen des Tiddlywikis) erstellt." }, "$:/language/ControlPanel/Palette/Caption": { "title": "$:/language/ControlPanel/Palette/Caption", "text": "Palette" }, "$:/language/ControlPanel/Palette/Editor/Clone/Caption": { "title": "$:/language/ControlPanel/Palette/Editor/Clone/Caption", "text": "Palette klonen" }, "$:/language/ControlPanel/Palette/Editor/Clone/Prompt": { "title": "$:/language/ControlPanel/Palette/Editor/Clone/Prompt", "text": "Es wird empfohlen, dass Sie diese Schatten-Palette klonen, bevor Sie sie bearbeiten. Der Name der Palette wird im Tiddler-Feld \"description\" eingestellt." }, "$:/language/ControlPanel/Palette/Editor/Prompt/Modified": { "title": "$:/language/ControlPanel/Palette/Editor/Prompt/Modified", "text": "Diese Schatten-Palette wurde bearbeitet." }, "$:/language/ControlPanel/Palette/Editor/Prompt": { "title": "$:/language/ControlPanel/Palette/Editor/Prompt", "text": "Bearbeiten" }, "$:/language/ControlPanel/Palette/Editor/Reset/Caption": { "title": "$:/language/ControlPanel/Palette/Editor/Reset/Caption", "text": "Palette zurücksetzen" }, "$:/language/ControlPanel/Palette/HideEditor/Caption": { "title": "$:/language/ControlPanel/Palette/HideEditor/Caption", "text": "Editor ausblenden" }, "$:/language/ControlPanel/Palette/Prompt": { "title": "$:/language/ControlPanel/Palette/Prompt", "text": "Ausgewählte Farbpalette:" }, "$:/language/ControlPanel/Palette/ShowEditor/Caption": { "title": "$:/language/ControlPanel/Palette/ShowEditor/Caption", "text": "Editor zeigen" }, "$:/language/ControlPanel/Parsing/Caption": { "title": "$:/language/ControlPanel/Parsing/Caption", "text": "Parser" }, "$:/language/ControlPanel/Parsing/Hint": { "title": "$:/language/ControlPanel/Parsing/Hint", "text": "Hier können Sie die globalen Parser-Einstellungen ändern. ACHTUNG: Manche Einstellungen können dazu führen, dass ~TiddlyWiki nicht mehr richtig funktioniert. Sollte das der Fall sein, dann können Sie die Änderungen im [[\"safe mode\"|http://tiddlywiki.com/#SafeMode]] rückgängig machen." }, "$:/language/ControlPanel/Parsing/Block/Caption": { "title": "$:/language/ControlPanel/Parsing/Block/Caption", "text": "Block Regeln" }, "$:/language/ControlPanel/Parsing/Inline/Caption": { "title": "$:/language/ControlPanel/Parsing/Inline/Caption", "text": "Inline Regeln" }, "$:/language/ControlPanel/Parsing/Pragma/Caption": { "title": "$:/language/ControlPanel/Parsing/Pragma/Caption", "text": "Pragma Regeln" }, "$:/language/ControlPanel/Plugins/Add/Caption": { "title": "$:/language/ControlPanel/Plugins/Add/Caption", "text": "Suche" }, "$:/language/ControlPanel/Plugins/Add/Hint": { "title": "$:/language/ControlPanel/Plugins/Add/Hint", "text": "Suche und installiere neue Plugins" }, "$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint": { "title": "$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint", "text": "Dieses Plugin ist bereits installiert. Version: <$text text=<<installedVersion>>/>" }, "$:/language/ControlPanel/Plugins/Caption": { "title": "$:/language/ControlPanel/Plugins/Caption", "text": "Plugins" }, "$:/language/ControlPanel/Plugins/Disable/Caption": { "title": "$:/language/ControlPanel/Plugins/Disable/Caption", "text": "deaktivieren" }, "$:/language/ControlPanel/Plugins/Disable/Hint": { "title": "$:/language/ControlPanel/Plugins/Disable/Hint", "text": "Deaktivieren Sie dieses Plugin beim nächsten Laden der Seite." }, "$:/language/ControlPanel/Plugins/Disabled/Status": { "title": "$:/language/ControlPanel/Plugins/Disabled/Status", "text": "(deaktiviert)" }, "$:/language/ControlPanel/Plugins/Empty/Hint": { "title": "$:/language/ControlPanel/Plugins/Empty/Hint", "text": "keine" }, "$:/language/ControlPanel/Plugins/Enable/Caption": { "title": "$:/language/ControlPanel/Plugins/Enable/Caption", "text": "aktivieren" }, "$:/language/ControlPanel/Plugins/Enable/Hint": { "title": "$:/language/ControlPanel/Plugins/Enable/Hint", "text": "Aktivieren Sie dieses Plugin beim nächsten Laden der Seite." }, "$:/language/ControlPanel/Plugins/Install/Caption": { "title": "$:/language/ControlPanel/Plugins/Install/Caption", "text": "installieren" }, "$:/language/ControlPanel/Plugins/Installed/Hint": { "title": "$:/language/ControlPanel/Plugins/Installed/Hint", "text": "Momentan installierte Plugins" }, "$:/language/ControlPanel/Plugins/Languages/Caption": { "title": "$:/language/ControlPanel/Plugins/Languages/Caption", "text": "Sprachen" }, "$:/language/ControlPanel/Plugins/Languages/Hint": { "title": "$:/language/ControlPanel/Plugins/Languages/Hint", "text": "Spracherweiterungen" }, "$:/language/ControlPanel/Plugins/NoInfoFound/Hint": { "title": "$:/language/ControlPanel/Plugins/NoInfoFound/Hint", "text": "Kein ''\"<$text text=<<currentTab>>/>\"'' gefunden" }, "$:/language/ControlPanel/Plugins/NoInformation/Hint": { "title": "$:/language/ControlPanel/Plugins/NoInformation/Hint", "text": "Keine Information vorhanden" }, "$:/language/ControlPanel/Plugins/NotInstalled/Hint": { "title": "$:/language/ControlPanel/Plugins/NotInstalled/Hint", "text": "Dieses Plugin ist momentan nicht installiert" }, "$:/language/ControlPanel/Plugins/OpenPluginLibrary": { "title": "$:/language/ControlPanel/Plugins/OpenPluginLibrary", "text": "Öffne das Plugin-Verzeichnis" }, "$:/language/ControlPanel/Plugins/ClosePluginLibrary": { "title": "$:/language/ControlPanel/Plugins/ClosePluginLibrary", "text": "Schließe das Plugin-Verzeichnis" }, "$:/language/ControlPanel/Plugins/Plugins/Caption": { "title": "$:/language/ControlPanel/Plugins/Plugins/Caption", "text": "Plugins" }, "$:/language/ControlPanel/Plugins/Plugins/Hint": { "title": "$:/language/ControlPanel/Plugins/Plugins/Hint", "text": "Erweiterungen" }, "$:/language/ControlPanel/Plugins/Reinstall/Caption": { "title": "$:/language/ControlPanel/Plugins/Reinstall/Caption", "text": "erneut installieren" }, "$:/language/ControlPanel/Plugins/Themes/Caption": { "title": "$:/language/ControlPanel/Plugins/Themes/Caption", "text": "Themes" }, "$:/language/ControlPanel/Plugins/Themes/Hint": { "title": "$:/language/ControlPanel/Plugins/Themes/Hint", "text": "Theme Erweiterungen" }, "$:/language/ControlPanel/Saving/Caption": { "title": "$:/language/ControlPanel/Saving/Caption", "text": "Speichern" }, "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Description": { "title": "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Description", "text": "Erlaube automatisches Speichern für den \"Download Saver\"" }, "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Hint": { "title": "$:/language/ControlPanel/Saving/DownloadSaver/AutoSave/Hint", "text": "Erlaube automatisches Speichern für den \"Download Saver\"" }, "$:/language/ControlPanel/Saving/DownloadSaver/Caption": { "title": "$:/language/ControlPanel/Saving/DownloadSaver/Caption", "text": "Download Saver" }, "$:/language/ControlPanel/Saving/DownloadSaver/Hint": { "title": "$:/language/ControlPanel/Saving/DownloadSaver/Hint", "text": "Diese Einstellungen gelten für den HTML5-compatiblen \"Download Saver\"" }, "$:/language/ControlPanel/Saving/General/Caption": { "title": "$:/language/ControlPanel/Saving/General/Caption", "text": "Allgemein" }, "$:/language/ControlPanel/Saving/General/Hint": { "title": "$:/language/ControlPanel/Saving/General/Hint", "text": "Diese Einstellungen gelten für alle Speichermechanismen" }, "$:/language/ControlPanel/Saving/Hint": { "title": "$:/language/ControlPanel/Saving/Hint", "text": "Einstellungen zu den TiddlyWiki Speichermechanismen" }, "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading", "text": "Erweiterte Einstellungen" }, "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir", "text": "Verzeichnis für das \"Backup\"" }, "$:/language/ControlPanel/Saving/TiddlySpot/Backups": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Backups", "text": "\"Backups\"" }, "$:/language/ControlPanel/Saving/TiddlySpot/Caption": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Caption", "text": "Speichern auf ~TiddlySpot" }, "$:/language/ControlPanel/Saving/TiddlySpot/Description": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Description", "text": "Diese Einstellungen sind nur für http://tiddlyspot.com und kompatible Server aktiv!" }, "$:/language/ControlPanel/Saving/TiddlySpot/Filename": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Filename", "text": "Dateiname für den \"Upload\"" }, "$:/language/ControlPanel/Saving/TiddlySpot/Heading": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Heading", "text": "~TiddlySpot" }, "$:/language/ControlPanel/Saving/TiddlySpot/Hint": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Hint", "text": "//Die Standard-Server-URL ist `http://<wikiname>.tiddlyspot.com/store.cgi` und kann im Feld 'Server-URL' verändert werden. zB: http://example.com/store.php//" }, "$:/language/ControlPanel/Saving/TiddlySpot/Password": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Password", "text": "Passwort" }, "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL", "text": "Server-URL" }, "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir", "text": "Verzeichnis für den \"Upload\"" }, "$:/language/ControlPanel/Saving/TiddlySpot/UserName": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/UserName", "text": "Name des Wikis" }, "$:/language/ControlPanel/Settings/AutoSave/Caption": { "title": "$:/language/ControlPanel/Settings/AutoSave/Caption", "text": "Automatisch speichern" }, "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description": { "title": "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description", "text": "Änderungen NICHT automatisch speichern" }, "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description": { "title": "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description", "text": "Änderungen automatisch speichern" }, "$:/language/ControlPanel/Settings/AutoSave/Hint": { "title": "$:/language/ControlPanel/Settings/AutoSave/Hint", "text": "Änderungen des Wikis automatisch speichern" }, "$:/language/ControlPanel/Settings/CamelCase/Caption": { "title": "$:/language/ControlPanel/Settings/CamelCase/Caption", "text": "Camel Case Wiki Links" }, "$:/language/ControlPanel/Settings/CamelCase/Hint": { "title": "$:/language/ControlPanel/Settings/CamelCase/Hint", "text": "Hier können Sie die automatische Umwandlung von \"~CamelCase Links\" einstellen. ''Wichtig:'' Die Seite muss neu geladen werden, damit die Einstellungen wirksam werden." }, "$:/language/ControlPanel/Settings/CamelCase/Description": { "title": "$:/language/ControlPanel/Settings/CamelCase/Description", "text": "Automatische ~CamelCase Umwandlung aktivieren" }, "$:/language/ControlPanel/Settings/Caption": { "title": "$:/language/ControlPanel/Settings/Caption", "text": "Einstellungen" }, "$:/language/ControlPanel/Settings/EditorToolbar/Caption": { "title": "$:/language/ControlPanel/Settings/EditorToolbar/Caption", "text": "Editor Toolbar" }, "$:/language/ControlPanel/Settings/EditorToolbar/Hint": { "title": "$:/language/ControlPanel/Settings/EditorToolbar/Hint", "text": "Aktivieren oder deaktivieren der Editor Toolbar" }, "$:/language/ControlPanel/Settings/EditorToolbar/Description": { "title": "$:/language/ControlPanel/Settings/EditorToolbar/Description", "text": "Editor Toolbar anzeigen" }, "$:/language/ControlPanel/Settings/InfoPanelMode/Caption": { "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Caption", "text": "Tiddler Info Panel Modus" }, "$:/language/ControlPanel/Settings/InfoPanelMode/Hint": { "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Hint", "text": "Einstellung, wann das Info Panel geschlossen wird:" }, "$:/language/ControlPanel/Settings/InfoPanelMode/Popup/Description": { "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Popup/Description", "text": "Tiddler Info-Panel schließt automatisch" }, "$:/language/ControlPanel/Settings/InfoPanelMode/Sticky/Description": { "title": "$:/language/ControlPanel/Settings/InfoPanelMode/Sticky/Description", "text": "TiddlerTiddler Info-Panel bleibt offen, bis es geschlossen wird" }, "$:/language/ControlPanel/Settings/Hint": { "title": "$:/language/ControlPanel/Settings/Hint", "text": "Diese erweiterten Einstellungen ermöglichen Ihnen, das Verhalten von TiddlyWiki zu ändern." }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption", "text": "Navigation Adresszeile" }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint", "text": "Verhalten der Adresszeile des Browsers, wenn ein Tiddler geöffnet wird:" }, "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description", "text": "Die Adresszeile des Browsers wird nicht verändert." }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description", "text": "Den aktuellen Tiddler einbinden." }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description", "text": "Alle geöffneten Tiddler einbinden." }, "$:/language/ControlPanel/Settings/NavigationHistory/Caption": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/Caption", "text": "Browser Chronik" }, "$:/language/ControlPanel/Settings/NavigationHistory/Hint": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/Hint", "text": "Die Browser Chronik ändern, wenn ein Tiddler angezeigt wird:" }, "$:/language/ControlPanel/Settings/NavigationHistory/No/Description": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/No/Description", "text": "Browser Chronik nicht ändern." }, "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description", "text": "Browser Chronik ändern." }, "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption": { "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption", "text": "Performance Messung" }, "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Hint": { "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Hint", "text": "Anzeige der Performance Statistik in der Browser Entwickler Konsole. ''Wichtig:'' Seite neu laden um die Einstellung zu aktivieren!" }, "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Description": { "title": "$:/language/ControlPanel/Settings/PerformanceInstrumentation/Description", "text": "Aktiviere Performance Messung" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption", "text": "Toolbar Button Stil" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint", "text": "Wählen Sie einen Stil:" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless", "text": "Ohne Rand" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed", "text": "Box" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded", "text": "Abgerundet" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Caption": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Caption", "text": "Toolbar Buttons" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Hint": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Hint", "text": "Standard Toolbar Button Erscheinungsbild:" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description", "text": "Icon anzeigen" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description", "text": "Text anzeigen" }, "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption": { "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption", "text": "Standard Sidebar Tab" }, "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint": { "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint", "text": "Definition, welcher Sidebar Tab standardmäßig aktiv ist." }, "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption", "text": "Tiddler Öffnen" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint", "text": "Navigation bei Klicks //innerhalb// der Story" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint", "text": "Navigation bei Klicks //außerhalb// der Story" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove", "text": "Öffne vor dem aktuellen Tiddler" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow", "text": "Öffne unter dem aktuellen Tiddler" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop", "text": "Öffne als ersten Tiddler in der Story" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom", "text": "Öffne alse letzten Tiddler in der Story" }, "$:/language/ControlPanel/Settings/TitleLinks/Caption": { "title": "$:/language/ControlPanel/Settings/TitleLinks/Caption", "text": "Tiddler Titel" }, "$:/language/ControlPanel/Settings/TitleLinks/Hint": { "title": "$:/language/ControlPanel/Settings/TitleLinks/Hint", "text": "Tiddler Titel als Links anzeigen:" }, "$:/language/ControlPanel/Settings/TitleLinks/No/Description": { "title": "$:/language/ControlPanel/Settings/TitleLinks/No/Description", "text": "Tiddler Titel normal anzeigen." }, "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description": { "title": "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description", "text": "Tiddler Titel als Link anzeigen." }, "$:/language/ControlPanel/Settings/MissingLinks/Caption": { "title": "$:/language/ControlPanel/Settings/MissingLinks/Caption", "text": "Wiki-Links" }, "$:/language/ControlPanel/Settings/MissingLinks/Hint": { "title": "$:/language/ControlPanel/Settings/MissingLinks/Hint", "text": "Aktiviere Links zu fehlenden Tiddlern. zB: FehlenderTiddler [[Einführung]]" }, "$:/language/ControlPanel/Settings/MissingLinks/Description": { "title": "$:/language/ControlPanel/Settings/MissingLinks/Description", "text": "Aktiviere Links zu fehlenden Tiddlern." }, "$:/language/ControlPanel/StoryView/Caption": { "title": "$:/language/ControlPanel/StoryView/Caption", "text": "Anzeige" }, "$:/language/ControlPanel/StoryView/Prompt": { "title": "$:/language/ControlPanel/StoryView/Prompt", "text": "Ausgewählte Anzeige:" }, "$:/language/ControlPanel/Theme/Caption": { "title": "$:/language/ControlPanel/Theme/Caption", "text": "Theme" }, "$:/language/ControlPanel/Theme/Prompt": { "title": "$:/language/ControlPanel/Theme/Prompt", "text": "Ausgewähltes Theme:" }, "$:/language/ControlPanel/TiddlerFields/Caption": { "title": "$:/language/ControlPanel/TiddlerFields/Caption", "text": "Tiddler Felder" }, "$:/language/ControlPanel/TiddlerFields/Hint": { "title": "$:/language/ControlPanel/TiddlerFields/Hint", "text": "Hier finden Sie alle [[Felder|TiddlerFields]], die in diesem Wiki verwendet werden. Inklusive der Felder aus System-, exklusive Schatten-Tiddler." }, "$:/language/ControlPanel/Toolbars/Caption": { "title": "$:/language/ControlPanel/Toolbars/Caption", "text": "Toolbar" }, "$:/language/ControlPanel/Toolbars/EditToolbar/Caption": { "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Caption", "text": "Edit Toolbar" }, "$:/language/ControlPanel/Toolbars/EditToolbar/Hint": { "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Hint", "text": "Auswählen, welche Buttons im \"Edit Modus\" angezeigt werden. Verwenden Sie \"Drag and Drop\", um die Reihenfolge zu ändern" }, "$:/language/ControlPanel/Toolbars/Hint": { "title": "$:/language/ControlPanel/Toolbars/Hint", "text": "Auswählen, welche \"Toolbar Button\" angezeigt werden" }, "$:/language/ControlPanel/Toolbars/PageControls/Caption": { "title": "$:/language/ControlPanel/Toolbars/PageControls/Caption", "text": "Page Toolbar" }, "$:/language/ControlPanel/Toolbars/PageControls/Hint": { "title": "$:/language/ControlPanel/Toolbars/PageControls/Hint", "text": "Auswählen, welche Buttons im Hauptmenü angezeigt werden. Verwenden Sie \"Drag and Drop\", um die Reihenfolge zu ändern" }, "$:/language/ControlPanel/Toolbars/EditorToolbar/Caption": { "title": "$:/language/ControlPanel/Toolbars/EditorToolbar/Caption", "text": "Editor Toolbar" }, "$:/language/ControlPanel/Toolbars/EditorToolbar/Hint": { "title": "$:/language/ControlPanel/Toolbars/EditorToolbar/Hint", "text": "Auswählen, welche Editorbuttons angezeigt werden sollen. Manche Buttons sind vom Tiddler-Typ abhängig und werden eventuell ausgeblendet." }, "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption": { "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption", "text": "View Toolbar" }, "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint": { "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint", "text": "Auswählen, welche Buttons im \"View Modus\" angezeigt werden. Verwenden Sie \"Drag and Drop\", um die Reihenfolge zu ändern" }, "$:/language/ControlPanel/Tools/Download/Full/Caption": { "title": "$:/language/ControlPanel/Tools/Download/Full/Caption", "text": "Herunterladen des ''gesamten Wikis''" }, "$:/core/de-DE/readme": { "title": "$:/core/de-DE/readme", "text": "Dieses Plugin enthält die TiddlyWiki Basis Komponenten, bestehend aus:\n\n* JavaScript Code Module.\n* Piktogramme (icons).\n* Vorlagen, die benötigt werden um die TiddlyWiki Oberfläche zu erstellen.\n* British English (''en-GB'') übersetzbare Texte, die von der TW Basis Software verwendet werden.\n" }, "$:/language/Date/DaySuffix/1": { "title": "$:/language/Date/DaySuffix/1", "text": "." }, "$:/language/Date/DaySuffix/2": { "title": "$:/language/Date/DaySuffix/2", "text": "." }, "$:/language/Date/DaySuffix/3": { "title": "$:/language/Date/DaySuffix/3", "text": "." }, "$:/language/Date/DaySuffix/4": { "title": "$:/language/Date/DaySuffix/4", "text": "." }, "$:/language/Date/DaySuffix/5": { "title": "$:/language/Date/DaySuffix/5", "text": "." }, "$:/language/Date/DaySuffix/6": { "title": "$:/language/Date/DaySuffix/6", "text": "." }, "$:/language/Date/DaySuffix/7": { "title": "$:/language/Date/DaySuffix/7", "text": "." }, "$:/language/Date/DaySuffix/8": { "title": "$:/language/Date/DaySuffix/8", "text": "." }, "$:/language/Date/DaySuffix/9": { "title": "$:/language/Date/DaySuffix/9", "text": "." }, "$:/language/Date/DaySuffix/10": { "title": "$:/language/Date/DaySuffix/10", "text": "." }, "$:/language/Date/DaySuffix/11": { "title": "$:/language/Date/DaySuffix/11", "text": "." }, "$:/language/Date/DaySuffix/12": { "title": "$:/language/Date/DaySuffix/12", "text": "." }, "$:/language/Date/DaySuffix/13": { "title": "$:/language/Date/DaySuffix/13", "text": "." }, "$:/language/Date/DaySuffix/14": { "title": "$:/language/Date/DaySuffix/14", "text": "." }, "$:/language/Date/DaySuffix/15": { "title": "$:/language/Date/DaySuffix/15", "text": "." }, "$:/language/Date/DaySuffix/16": { "title": "$:/language/Date/DaySuffix/16", "text": "." }, "$:/language/Date/DaySuffix/17": { "title": "$:/language/Date/DaySuffix/17", "text": "." }, "$:/language/Date/DaySuffix/18": { "title": "$:/language/Date/DaySuffix/18", "text": "." }, "$:/language/Date/DaySuffix/19": { "title": "$:/language/Date/DaySuffix/19", "text": "." }, "$:/language/Date/DaySuffix/20": { "title": "$:/language/Date/DaySuffix/20", "text": "." }, "$:/language/Date/DaySuffix/21": { "title": "$:/language/Date/DaySuffix/21", "text": "." }, "$:/language/Date/DaySuffix/22": { "title": "$:/language/Date/DaySuffix/22", "text": "." }, "$:/language/Date/DaySuffix/23": { "title": "$:/language/Date/DaySuffix/23", "text": "." }, "$:/language/Date/DaySuffix/24": { "title": "$:/language/Date/DaySuffix/24", "text": "." }, "$:/language/Date/DaySuffix/25": { "title": "$:/language/Date/DaySuffix/25", "text": "." }, "$:/language/Date/DaySuffix/26": { "title": "$:/language/Date/DaySuffix/26", "text": "." }, "$:/language/Date/DaySuffix/27": { "title": "$:/language/Date/DaySuffix/27", "text": "." }, "$:/language/Date/DaySuffix/28": { "title": "$:/language/Date/DaySuffix/28", "text": "." }, "$:/language/Date/DaySuffix/29": { "title": "$:/language/Date/DaySuffix/29", "text": "." }, "$:/language/Date/DaySuffix/30": { "title": "$:/language/Date/DaySuffix/30", "text": "." }, "$:/language/Date/DaySuffix/31": { "title": "$:/language/Date/DaySuffix/31", "text": "." }, "$:/language/Date/Long/Day/0": { "title": "$:/language/Date/Long/Day/0", "text": "Sonntag" }, "$:/language/Date/Long/Day/1": { "title": "$:/language/Date/Long/Day/1", "text": "Montag" }, "$:/language/Date/Long/Day/2": { "title": "$:/language/Date/Long/Day/2", "text": "Dienstag" }, "$:/language/Date/Long/Day/3": { "title": "$:/language/Date/Long/Day/3", "text": "Mittwoch" }, "$:/language/Date/Long/Day/4": { "title": "$:/language/Date/Long/Day/4", "text": "Donnerstag" }, "$:/language/Date/Long/Day/5": { "title": "$:/language/Date/Long/Day/5", "text": "Freitag" }, "$:/language/Date/Long/Day/6": { "title": "$:/language/Date/Long/Day/6", "text": "Samstag" }, "$:/language/Date/Long/Month/1": { "title": "$:/language/Date/Long/Month/1", "text": "Januar" }, "$:/language/Date/Long/Month/2": { "title": "$:/language/Date/Long/Month/2", "text": "Februar" }, "$:/language/Date/Long/Month/3": { "title": "$:/language/Date/Long/Month/3", "text": "März" }, "$:/language/Date/Long/Month/4": { "title": "$:/language/Date/Long/Month/4", "text": "April" }, "$:/language/Date/Long/Month/5": { "title": "$:/language/Date/Long/Month/5", "text": "Mai" }, "$:/language/Date/Long/Month/6": { "title": "$:/language/Date/Long/Month/6", "text": "Juni" }, "$:/language/Date/Long/Month/7": { "title": "$:/language/Date/Long/Month/7", "text": "Juli" }, "$:/language/Date/Long/Month/8": { "title": "$:/language/Date/Long/Month/8", "text": "August" }, "$:/language/Date/Long/Month/9": { "title": "$:/language/Date/Long/Month/9", "text": "September" }, "$:/language/Date/Long/Month/10": { "title": "$:/language/Date/Long/Month/10", "text": "Oktober" }, "$:/language/Date/Long/Month/11": { "title": "$:/language/Date/Long/Month/11", "text": "November" }, "$:/language/Date/Long/Month/12": { "title": "$:/language/Date/Long/Month/12", "text": "Dezember" }, "$:/language/Date/Period/am": { "title": "$:/language/Date/Period/am", "text": "am" }, "$:/language/Date/Period/pm": { "title": "$:/language/Date/Period/pm", "text": "pm" }, "$:/language/Date/Short/Day/0": { "title": "$:/language/Date/Short/Day/0", "text": "So" }, "$:/language/Date/Short/Day/1": { "title": "$:/language/Date/Short/Day/1", "text": "Mo" }, "$:/language/Date/Short/Day/2": { "title": "$:/language/Date/Short/Day/2", "text": "Di" }, "$:/language/Date/Short/Day/3": { "title": "$:/language/Date/Short/Day/3", "text": "Mi" }, "$:/language/Date/Short/Day/4": { "title": "$:/language/Date/Short/Day/4", "text": "Do" }, "$:/language/Date/Short/Day/5": { "title": "$:/language/Date/Short/Day/5", "text": "Fr" }, "$:/language/Date/Short/Day/6": { "title": "$:/language/Date/Short/Day/6", "text": "Sa" }, "$:/language/Date/Short/Month/1": { "title": "$:/language/Date/Short/Month/1", "text": "Jan" }, "$:/language/Date/Short/Month/2": { "title": "$:/language/Date/Short/Month/2", "text": "Feb" }, "$:/language/Date/Short/Month/3": { "title": "$:/language/Date/Short/Month/3", "text": "Mär" }, "$:/language/Date/Short/Month/4": { "title": "$:/language/Date/Short/Month/4", "text": "Apr" }, "$:/language/Date/Short/Month/5": { "title": "$:/language/Date/Short/Month/5", "text": "Mai" }, "$:/language/Date/Short/Month/6": { "title": "$:/language/Date/Short/Month/6", "text": "Jun" }, "$:/language/Date/Short/Month/7": { "title": "$:/language/Date/Short/Month/7", "text": "Jul" }, "$:/language/Date/Short/Month/8": { "title": "$:/language/Date/Short/Month/8", "text": "Aug" }, "$:/language/Date/Short/Month/9": { "title": "$:/language/Date/Short/Month/9", "text": "Sep" }, "$:/language/Date/Short/Month/10": { "title": "$:/language/Date/Short/Month/10", "text": "Okt" }, "$:/language/Date/Short/Month/11": { "title": "$:/language/Date/Short/Month/11", "text": "Nov" }, "$:/language/Date/Short/Month/12": { "title": "$:/language/Date/Short/Month/12", "text": "Dez" }, "$:/language/RelativeDate/Future/Days": { "title": "$:/language/RelativeDate/Future/Days", "text": "in <<period>> Tagen" }, "$:/language/RelativeDate/Future/Hours": { "title": "$:/language/RelativeDate/Future/Hours", "text": "in <<period>> Stunden" }, "$:/language/RelativeDate/Future/Minutes": { "title": "$:/language/RelativeDate/Future/Minutes", "text": "in <<period>> Minuten" }, "$:/language/RelativeDate/Future/Months": { "title": "$:/language/RelativeDate/Future/Months", "text": "in <<period>> Monaten" }, "$:/language/RelativeDate/Future/Second": { "title": "$:/language/RelativeDate/Future/Second", "text": "in einer Sekunde" }, "$:/language/RelativeDate/Future/Seconds": { "title": "$:/language/RelativeDate/Future/Seconds", "text": "in <<period>> Sekunden" }, "$:/language/RelativeDate/Future/Years": { "title": "$:/language/RelativeDate/Future/Years", "text": "in <<period>> Jahren" }, "$:/language/RelativeDate/Past/Days": { "title": "$:/language/RelativeDate/Past/Days", "text": "vor <<period>> Tagen" }, "$:/language/RelativeDate/Past/Hours": { "title": "$:/language/RelativeDate/Past/Hours", "text": "vor <<period>> Stunden" }, "$:/language/RelativeDate/Past/Minutes": { "title": "$:/language/RelativeDate/Past/Minutes", "text": "vor <<period>> Minuten" }, "$:/language/RelativeDate/Past/Months": { "title": "$:/language/RelativeDate/Past/Months", "text": "vor <<period>> Monaten" }, "$:/language/RelativeDate/Past/Second": { "title": "$:/language/RelativeDate/Past/Second", "text": "vor einer Sekunde" }, "$:/language/RelativeDate/Past/Seconds": { "title": "$:/language/RelativeDate/Past/Seconds", "text": "vor <<period>> Sekunden" }, "$:/language/RelativeDate/Past/Years": { "title": "$:/language/RelativeDate/Past/Years", "text": "vor <<period>> Jahren" }, "$:/language/Docs/ModuleTypes/allfilteroperator": { "title": "$:/language/Docs/ModuleTypes/allfilteroperator", "text": "Ein Sub-Operator für den ''all'' Filter Operator." }, "$:/language/Docs/ModuleTypes/animation": { "title": "$:/language/Docs/ModuleTypes/animation", "text": "Animationen, die vom RevealWidget verwendet werden." }, "$:/language/Docs/ModuleTypes/bitmapeditoroperation": { "title": "$:/language/Docs/ModuleTypes/bitmapeditoroperation", "text": "Eine \"Bitmap-Editor\" Toolbar Operation." }, "$:/language/Docs/ModuleTypes/command": { "title": "$:/language/Docs/ModuleTypes/command", "text": "Kommandozeilen-Parameter, die mit node.js ausgeführt werden können." }, "$:/language/Docs/ModuleTypes/config": { "title": "$:/language/Docs/ModuleTypes/config", "text": "Daten, die in `$tw.config` eingefügt werden." }, "$:/language/Docs/ModuleTypes/filteroperator": { "title": "$:/language/Docs/ModuleTypes/filteroperator", "text": "Individuelle Funktionen für den Filter-Operator." }, "$:/language/Docs/ModuleTypes/global": { "title": "$:/language/Docs/ModuleTypes/global", "text": "Globale Daten, die in `$tw` eingefügt werden." }, "$:/language/Docs/ModuleTypes/info": { "title": "$:/language/Docs/ModuleTypes/info", "text": "Veröffentlicht System-Informationen mit dem Pseudo-plugin: [[$:/temp/info-plugin]]" }, "$:/language/Docs/ModuleTypes/isfilteroperator": { "title": "$:/language/Docs/ModuleTypes/isfilteroperator", "text": "Operanden für den Filter-Operator: ''is''" }, "$:/language/Docs/ModuleTypes/library": { "title": "$:/language/Docs/ModuleTypes/library", "text": "Allgemeiner Modultyp, für JavaScript Module." }, "$:/language/Docs/ModuleTypes/macro": { "title": "$:/language/Docs/ModuleTypes/macro", "text": "Globale Makro-Definitionen in JavaScript." }, "$:/language/Docs/ModuleTypes/parser": { "title": "$:/language/Docs/ModuleTypes/parser", "text": "Parser für verschiedene Tiddler Typen." }, "$:/language/Docs/ModuleTypes/saver": { "title": "$:/language/Docs/ModuleTypes/saver", "text": "\"Savers\" stellen verschiedene Methoden zum Speichern mit dem Browser zur Verfügung." }, "$:/language/Docs/ModuleTypes/startup": { "title": "$:/language/Docs/ModuleTypes/startup", "text": "Funktionen zur Initialisierung." }, "$:/language/Docs/ModuleTypes/storyview": { "title": "$:/language/Docs/ModuleTypes/storyview", "text": "[[Story-View|Story]] ist für das Verhalten des \"ListWidgets\" zuständig, das die Tiddler \"Hauptanzeige\" verwaltet. Mit dem Toolbutton Story-Modus wird einer dieser Modi ausgewählt." }, "$:/language/Docs/ModuleTypes/texteditoroperation": { "title": "$:/language/Docs/ModuleTypes/texteditoroperation", "text": "Eine Text-Editor Toolbar Operation." }, "$:/language/Docs/ModuleTypes/tiddlerdeserializer": { "title": "$:/language/Docs/ModuleTypes/tiddlerdeserializer", "text": "Konvertiert verschiedene textbasierte Inhaltstypen in das Tiddler-Format." }, "$:/language/Docs/ModuleTypes/tiddlerfield": { "title": "$:/language/Docs/ModuleTypes/tiddlerfield", "text": "Definiert das Verhalten, der unterschiedlichen Tiddler-Felder." }, "$:/language/Docs/ModuleTypes/tiddlermethod": { "title": "$:/language/Docs/ModuleTypes/tiddlermethod", "text": "Methoden werden dem `$tw.Tiddler` Prototypen hinzugefügt." }, "$:/language/Docs/ModuleTypes/upgrader": { "title": "$:/language/Docs/ModuleTypes/upgrader", "text": "Führt spezifische Änderungen während des Upgrade- oder Import-prozesses durch." }, "$:/language/Docs/ModuleTypes/utils": { "title": "$:/language/Docs/ModuleTypes/utils", "text": "Methoden werden `$tw.utils` hinzugefügt." }, "$:/language/Docs/ModuleTypes/utils-node": { "title": "$:/language/Docs/ModuleTypes/utils-node", "text": "Erweitert `$tw.utils` mit Methoden aus node.js." }, "$:/language/Docs/ModuleTypes/widget": { "title": "$:/language/Docs/ModuleTypes/widget", "text": "Widgets verarbeiten das Rendern und Aktualisieren der Anzeige in der DOM." }, "$:/language/Docs/ModuleTypes/wikimethod": { "title": "$:/language/Docs/ModuleTypes/wikimethod", "text": "Methoden werden zu `$tw.Wiki` hinzugefügt." }, "$:/language/Docs/ModuleTypes/wikirule": { "title": "$:/language/Docs/ModuleTypes/wikirule", "text": "Enthält die individuellen Parser Regeln für den WikiText-Parser." }, "$:/language/Docs/PaletteColours/alert-background": { "title": "$:/language/Docs/PaletteColours/alert-background", "text": "Warnung Hintergrund" }, "$:/language/Docs/PaletteColours/alert-border": { "title": "$:/language/Docs/PaletteColours/alert-border", "text": "Warnung Rahmen" }, "$:/language/Docs/PaletteColours/alert-highlight": { "title": "$:/language/Docs/PaletteColours/alert-highlight", "text": "Warnung Hervorhebung" }, "$:/language/Docs/PaletteColours/alert-muted-foreground": { "title": "$:/language/Docs/PaletteColours/alert-muted-foreground", "text": "Warnung gedeckt Vordergrund" }, "$:/language/Docs/PaletteColours/background": { "title": "$:/language/Docs/PaletteColours/background", "text": "Hintergrund Global" }, "$:/language/Docs/PaletteColours/blockquote-bar": { "title": "$:/language/Docs/PaletteColours/blockquote-bar", "text": "Zitat Markierung" }, "$:/language/Docs/PaletteColours/button-background": { "title": "$:/language/Docs/PaletteColours/button-background", "text": "Standard-Button Hintergrund" }, "$:/language/Docs/PaletteColours/button-border": { "title": "$:/language/Docs/PaletteColours/button-border", "text": "Standard-Button Rahmen" }, "$:/language/Docs/PaletteColours/button-foreground": { "title": "$:/language/Docs/PaletteColours/button-foreground", "text": "Standard-Button Vordergrund" }, "$:/language/Docs/PaletteColours/dirty-indicator": { "title": "$:/language/Docs/PaletteColours/dirty-indicator", "text": "Speichern nötig - Indikator" }, "$:/language/Docs/PaletteColours/code-background": { "title": "$:/language/Docs/PaletteColours/code-background", "text": "Code Hintergrund" }, "$:/language/Docs/PaletteColours/code-border": { "title": "$:/language/Docs/PaletteColours/code-border", "text": "Code Rahmen" }, "$:/language/Docs/PaletteColours/code-foreground": { "title": "$:/language/Docs/PaletteColours/code-foreground", "text": "Code Vordergrund" }, "$:/language/Docs/PaletteColours/download-background": { "title": "$:/language/Docs/PaletteColours/download-background", "text": "Herunterladen-Button Hintergrund" }, "$:/language/Docs/PaletteColours/download-foreground": { "title": "$:/language/Docs/PaletteColours/download-foreground", "text": "Herunterladen-Button Vordergrund" }, "$:/language/Docs/PaletteColours/dragger-background": { "title": "$:/language/Docs/PaletteColours/dragger-background", "text": "Ziehen Hintergrund" }, "$:/language/Docs/PaletteColours/dragger-foreground": { "title": "$:/language/Docs/PaletteColours/dragger-foreground", "text": "Ziehen Vordergrund" }, "$:/language/Docs/PaletteColours/dropdown-background": { "title": "$:/language/Docs/PaletteColours/dropdown-background", "text": "Auswahldialog Hintergrund" }, "$:/language/Docs/PaletteColours/dropdown-border": { "title": "$:/language/Docs/PaletteColours/dropdown-border", "text": "Auswahldialog Rahmen" }, "$:/language/Docs/PaletteColours/dropdown-tab-background-selected": { "title": "$:/language/Docs/PaletteColours/dropdown-tab-background-selected", "text": "Auswahldialog ausgewählter Reiter Hintergrund" }, "$:/language/Docs/PaletteColours/dropdown-tab-background": { "title": "$:/language/Docs/PaletteColours/dropdown-tab-background", "text": "Auswahldialog Reiter Hintergrund" }, "$:/language/Docs/PaletteColours/dropzone-background": { "title": "$:/language/Docs/PaletteColours/dropzone-background", "text": "Import Zone Hintergrund" }, "$:/language/Docs/PaletteColours/external-link-background-hover": { "title": "$:/language/Docs/PaletteColours/external-link-background-hover", "text": "Externer Link Hintergrund (hover)" }, "$:/language/Docs/PaletteColours/external-link-background-visited": { "title": "$:/language/Docs/PaletteColours/external-link-background-visited", "text": "Externer Link besucht Hintergrund" }, "$:/language/Docs/PaletteColours/external-link-background": { "title": "$:/language/Docs/PaletteColours/external-link-background", "text": "Externer Link Hintergrund" }, "$:/language/Docs/PaletteColours/external-link-foreground-hover": { "title": "$:/language/Docs/PaletteColours/external-link-foreground-hover", "text": "Externer Link Vordergrund (hover)" }, "$:/language/Docs/PaletteColours/external-link-foreground-visited": { "title": "$:/language/Docs/PaletteColours/external-link-foreground-visited", "text": "Externer Link besucht Vordergrund" }, "$:/language/Docs/PaletteColours/external-link-foreground": { "title": "$:/language/Docs/PaletteColours/external-link-foreground", "text": "Externer Link Vordergrund" }, "$:/language/Docs/PaletteColours/foreground": { "title": "$:/language/Docs/PaletteColours/foreground", "text": "Vordergrund Global" }, "$:/language/Docs/PaletteColours/message-background": { "title": "$:/language/Docs/PaletteColours/message-background", "text": "Meldungs-Box Hintergrund" }, "$:/language/Docs/PaletteColours/message-border": { "title": "$:/language/Docs/PaletteColours/message-border", "text": "Meldungs-Box Rahmen" }, "$:/language/Docs/PaletteColours/message-foreground": { "title": "$:/language/Docs/PaletteColours/message-foreground", "text": "Meldungs-Box Vordergrund" }, "$:/language/Docs/PaletteColours/modal-backdrop": { "title": "$:/language/Docs/PaletteColours/modal-backdrop", "text": "Modaler Dialog abgedunkelt" }, "$:/language/Docs/PaletteColours/modal-background": { "title": "$:/language/Docs/PaletteColours/modal-background", "text": "Modaler Dialog Hintergrund" }, "$:/language/Docs/PaletteColours/modal-border": { "title": "$:/language/Docs/PaletteColours/modal-border", "text": "Modaler Dialog Rahmen" }, "$:/language/Docs/PaletteColours/modal-footer-background": { "title": "$:/language/Docs/PaletteColours/modal-footer-background", "text": "Modaler Dialog Fußzeile Hintergrund" }, "$:/language/Docs/PaletteColours/modal-footer-border": { "title": "$:/language/Docs/PaletteColours/modal-footer-border", "text": "Modaler Dialog Fußzeile Rahmen" }, "$:/language/Docs/PaletteColours/modal-header-border": { "title": "$:/language/Docs/PaletteColours/modal-header-border", "text": "Modaler Dialog Kopfzeile Rahmen" }, "$:/language/Docs/PaletteColours/muted-foreground": { "title": "$:/language/Docs/PaletteColours/muted-foreground", "text": "Global gedeckt Vordergrund" }, "$:/language/Docs/PaletteColours/notification-background": { "title": "$:/language/Docs/PaletteColours/notification-background", "text": "Mitteilung Hintergrund" }, "$:/language/Docs/PaletteColours/notification-border": { "title": "$:/language/Docs/PaletteColours/notification-border", "text": "Mitteilung Rahmen" }, "$:/language/Docs/PaletteColours/page-background": { "title": "$:/language/Docs/PaletteColours/page-background", "text": "Seite Hintergrund" }, "$:/language/Docs/PaletteColours/pre-background": { "title": "$:/language/Docs/PaletteColours/pre-background", "text": "Formatierter Code Hintergrund" }, "$:/language/Docs/PaletteColours/pre-border": { "title": "$:/language/Docs/PaletteColours/pre-border", "text": "Formatierter Code Rahmen" }, "$:/language/Docs/PaletteColours/primary": { "title": "$:/language/Docs/PaletteColours/primary", "text": "Global Primary" }, "$:/language/Docs/PaletteColours/sidebar-button-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-button-foreground", "text": "Seitenleiste Button Vordergrund" }, "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover": { "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover", "text": "Seitenleiste Bedienelement Vordergrund (hover)" }, "$:/language/Docs/PaletteColours/sidebar-controls-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground", "text": "Seitenleiste Bedienelement Vordergrund" }, "$:/language/Docs/PaletteColours/sidebar-foreground-shadow": { "title": "$:/language/Docs/PaletteColours/sidebar-foreground-shadow", "text": "Seitenleiste Vordergrund Schatten" }, "$:/language/Docs/PaletteColours/sidebar-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-foreground", "text": "Seitenleiste Vordergrund" }, "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover": { "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover", "text": "Seitenleiste gedeckt Vordergrund (hover)" }, "$:/language/Docs/PaletteColours/sidebar-muted-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground", "text": "Seitenleiste gedeckt Vordergrund" }, "$:/language/Docs/PaletteColours/sidebar-tab-background-selected": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-background-selected", "text": "Seitenleiste Reiter" }, "$:/language/Docs/PaletteColours/sidebar-tab-background": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-background", "text": "Seitenleiste Reiter Hintergrund" }, "$:/language/Docs/PaletteColours/sidebar-tab-border-selected": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-border-selected", "text": "Seitenleiste Reiter Rahmen für selektierte Reiter" }, "$:/language/Docs/PaletteColours/sidebar-tab-border": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-border", "text": "Seitenleiste Reiter Rahmen" }, "$:/language/Docs/PaletteColours/sidebar-tab-divider": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-divider", "text": "Seitenleiste Reiter Trennzeichen" }, "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected", "text": "Seitenleiste Reiter Vordergrund für selectierte Reiter" }, "$:/language/Docs/PaletteColours/sidebar-tab-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground", "text": "Seitenleiste Reiter Vordergrund" }, "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover": { "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover", "text": "Seitenleiste Tiddler Link Vordergrund (hover)" }, "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground", "text": "Seitenleiste Tiddler Link Vordergrund" }, "$:/language/Docs/PaletteColours/site-title-foreground": { "title": "$:/language/Docs/PaletteColours/site-title-foreground", "text": "Wiki Titel Vordergrund" }, "$:/language/Docs/PaletteColours/static-alert-foreground": { "title": "$:/language/Docs/PaletteColours/static-alert-foreground", "text": "Statische Warnung Vordergrund" }, "$:/language/Docs/PaletteColours/tab-background-selected": { "title": "$:/language/Docs/PaletteColours/tab-background-selected", "text": "Reiter Hintergrund für selektierte Reiter" }, "$:/language/Docs/PaletteColours/tab-background": { "title": "$:/language/Docs/PaletteColours/tab-background", "text": "Reiter Hintergrund" }, "$:/language/Docs/PaletteColours/tab-border-selected": { "title": "$:/language/Docs/PaletteColours/tab-border-selected", "text": "Reiter Rahmen für selektierte Reiter" }, "$:/language/Docs/PaletteColours/tab-border": { "title": "$:/language/Docs/PaletteColours/tab-border", "text": "Reiter Rahmen" }, "$:/language/Docs/PaletteColours/tab-divider": { "title": "$:/language/Docs/PaletteColours/tab-divider", "text": "Reiter Trennzeichen" }, "$:/language/Docs/PaletteColours/tab-foreground-selected": { "title": "$:/language/Docs/PaletteColours/tab-foreground-selected", "text": "Reiter Vordergrund für selektierte Reiter" }, "$:/language/Docs/PaletteColours/tab-foreground": { "title": "$:/language/Docs/PaletteColours/tab-foreground", "text": "Reiter Vordergrund" }, "$:/language/Docs/PaletteColours/table-border": { "title": "$:/language/Docs/PaletteColours/table-border", "text": "Tabelle Rahmen" }, "$:/language/Docs/PaletteColours/table-footer-background": { "title": "$:/language/Docs/PaletteColours/table-footer-background", "text": "Tabelle Fußzeile Hintergrund" }, "$:/language/Docs/PaletteColours/table-header-background": { "title": "$:/language/Docs/PaletteColours/table-header-background", "text": "Tabelle Kopfzeile Hintergrund" }, "$:/language/Docs/PaletteColours/tag-background": { "title": "$:/language/Docs/PaletteColours/tag-background", "text": "Tag Hintergrund" }, "$:/language/Docs/PaletteColours/tag-foreground": { "title": "$:/language/Docs/PaletteColours/tag-foreground", "text": "Tag Vordergrund" }, "$:/language/Docs/PaletteColours/tiddler-background": { "title": "$:/language/Docs/PaletteColours/tiddler-background", "text": "Tiddler Hintergrund" }, "$:/language/Docs/PaletteColours/tiddler-border": { "title": "$:/language/Docs/PaletteColours/tiddler-border", "text": "Tiddler Rahmen" }, "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover": { "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover", "text": "Tiddler Bedienelement Vordergrund (hover)" }, "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected": { "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected", "text": "Tiddler Bedienelement Vordergrund für selektierte Elemente" }, "$:/language/Docs/PaletteColours/tiddler-controls-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground", "text": "Tiddler Bedienelement Vordergrund" }, "$:/language/Docs/PaletteColours/tiddler-editor-background": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-background", "text": "Tiddler Editor Hintergrund" }, "$:/language/Docs/PaletteColours/tiddler-editor-border-image": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-border-image", "text": "Tiddler Editor Rahmen Bild" }, "$:/language/Docs/PaletteColours/tiddler-editor-border": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-border", "text": "Tiddler Editor Rahmen" }, "$:/language/Docs/PaletteColours/tiddler-editor-fields-even": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-even", "text": "Tiddler Editor Hintergrund geradzahlige Felder in Tabelle" }, "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd", "text": "Tiddler Editor Hintergrund un-geradzahlige Felder in Tabelle" }, "$:/language/Docs/PaletteColours/tiddler-info-background": { "title": "$:/language/Docs/PaletteColours/tiddler-info-background", "text": "Tiddler Info Bereich Hintergrund" }, "$:/language/Docs/PaletteColours/tiddler-info-border": { "title": "$:/language/Docs/PaletteColours/tiddler-info-border", "text": "Tiddler Info Bereich Rahmen" }, "$:/language/Docs/PaletteColours/tiddler-info-tab-background": { "title": "$:/language/Docs/PaletteColours/tiddler-info-tab-background", "text": "Tiddler Info Bereich Reiter Hintergrund" }, "$:/language/Docs/PaletteColours/tiddler-link-background": { "title": "$:/language/Docs/PaletteColours/tiddler-link-background", "text": "Tiddler Link Hintergrund" }, "$:/language/Docs/PaletteColours/tiddler-link-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-link-foreground", "text": "Tiddler Link Vordergrund" }, "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground", "text": "Tiddler Untertitel Vordergrund" }, "$:/language/Docs/PaletteColours/tiddler-title-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-title-foreground", "text": "Tiddler Titel Vordergrund" }, "$:/language/Docs/PaletteColours/toolbar-new-button": { "title": "$:/language/Docs/PaletteColours/toolbar-new-button", "text": "Werkzeugleiste 'Neuer Tiddler' Button Vordergrund" }, "$:/language/Docs/PaletteColours/toolbar-options-button": { "title": "$:/language/Docs/PaletteColours/toolbar-options-button", "text": "Werkzeugleiste 'Optionen' Button Vordergrund" }, "$:/language/Docs/PaletteColours/toolbar-save-button": { "title": "$:/language/Docs/PaletteColours/toolbar-save-button", "text": "Werkzeugleiste 'Speichern' Button Vordergrund" }, "$:/language/Docs/PaletteColours/toolbar-info-button": { "title": "$:/language/Docs/PaletteColours/toolbar-info-button", "text": "Werkzeugleiste 'Info' Button Vordergrund" }, "$:/language/Docs/PaletteColours/toolbar-edit-button": { "title": "$:/language/Docs/PaletteColours/toolbar-edit-button", "text": "Werkzeugleiste 'Bearbeiten' Button Vordergrund" }, "$:/language/Docs/PaletteColours/toolbar-close-button": { "title": "$:/language/Docs/PaletteColours/toolbar-close-button", "text": "Werkzeugleiste 'Schließen' Button Vordergrund" }, "$:/language/Docs/PaletteColours/toolbar-delete-button": { "title": "$:/language/Docs/PaletteColours/toolbar-delete-button", "text": "Werkzeugleiste 'Löschen' Button Vordergrund" }, "$:/language/Docs/PaletteColours/toolbar-cancel-button": { "title": "$:/language/Docs/PaletteColours/toolbar-cancel-button", "text": "Werkzeugleiste 'Abbruch' Button Vordergrund" }, "$:/language/Docs/PaletteColours/toolbar-done-button": { "title": "$:/language/Docs/PaletteColours/toolbar-done-button", "text": "Werkzeugleiste 'Fertig' Button Vordergrund" }, "$:/language/Docs/PaletteColours/untagged-background": { "title": "$:/language/Docs/PaletteColours/untagged-background", "text": "(untagged) Pille Hintergrund" }, "$:/language/Docs/PaletteColours/very-muted-foreground": { "title": "$:/language/Docs/PaletteColours/very-muted-foreground", "text": "Stark abgedunkelter Vordergrund" }, "$:/language/EditTemplate/Body/External/Hint": { "title": "$:/language/EditTemplate/Body/External/Hint", "text": "Dies ist ein externer Tiddler, der nicht im TW file gespeichert ist. Sie können die \"Tags\" und \"Feld\" Texte ändern, jedoch nicht den Inhalt des Tiddlers!" }, "$:/language/EditTemplate/Body/Placeholder": { "title": "$:/language/EditTemplate/Body/Placeholder", "text": "Geben Sie den Text für diesen Tiddler ein." }, "$:/language/EditTemplate/Body/Preview/Type/Output": { "title": "$:/language/EditTemplate/Body/Preview/Type/Output", "text": "Anzeige" }, "$:/language/EditTemplate/Field/Remove/Caption": { "title": "$:/language/EditTemplate/Field/Remove/Caption", "text": "Lösche Feld" }, "$:/language/EditTemplate/Field/Remove/Hint": { "title": "$:/language/EditTemplate/Field/Remove/Hint", "text": "Lösche Feld" }, "$:/language/EditTemplate/Fields/Add/Button": { "title": "$:/language/EditTemplate/Fields/Add/Button", "text": "ok" }, "$:/language/EditTemplate/Fields/Add/Name/Placeholder": { "title": "$:/language/EditTemplate/Fields/Add/Name/Placeholder", "text": "Feld Name" }, "$:/language/EditTemplate/Fields/Add/Prompt": { "title": "$:/language/EditTemplate/Fields/Add/Prompt", "text": "Feld einfügen:" }, "$:/language/EditTemplate/Fields/Add/Value/Placeholder": { "title": "$:/language/EditTemplate/Fields/Add/Value/Placeholder", "text": "Feld Text / Wert" }, "$:/language/EditTemplate/Fields/Add/Dropdown/System": { "title": "$:/language/EditTemplate/Fields/Add/Dropdown/System", "text": "System Felder" }, "$:/language/EditTemplate/Fields/Add/Dropdown/User": { "title": "$:/language/EditTemplate/Fields/Add/Dropdown/User", "text": "Anwender Felder" }, "$:/language/EditTemplate/Shadow/Warning": { "title": "$:/language/EditTemplate/Shadow/Warning", "text": "Dies ist ein Schatten-Tiddler. Jede Änderung, die Sie machen, überschreibt die Standardversion des Plugins: <<pluginLink>>" }, "$:/language/EditTemplate/Shadow/OverriddenWarning": { "title": "$:/language/EditTemplate/Shadow/OverriddenWarning", "text": "Dies ist ein veränderter Tiddler. Um zur Standardversion zurückzukehren, löschen Sie diesen Tiddler. Plugin: <<pluginLink>>" }, "$:/language/EditTemplate/Tags/Add/Button": { "title": "$:/language/EditTemplate/Tags/Add/Button", "text": "ok" }, "$:/language/EditTemplate/Tags/Add/Placeholder": { "title": "$:/language/EditTemplate/Tags/Add/Placeholder", "text": "neuer Tag" }, "$:/language/EditTemplate/Tags/Dropdown/Caption": { "title": "$:/language/EditTemplate/Tags/Dropdown/Caption", "text": "Tag Liste" }, "$:/language/EditTemplate/Tags/Dropdown/Hint": { "title": "$:/language/EditTemplate/Tags/Dropdown/Hint", "text": "Tag Liste anzeigen" }, "$:/language/EditTemplate/Title/BadCharacterWarning": { "title": "$:/language/EditTemplate/Title/BadCharacterWarning", "text": "Warnung: Folgende Zeichen im Titel können zu Problemen führen: <<bad-chars>>" }, "$:/language/EditTemplate/Title/Exists/Prompt": { "title": "$:/language/EditTemplate/Title/Exists/Prompt", "text": "Tiddler Name existiert bereits" }, "$:/language/EditTemplate/Title/Relink/Prompt": { "title": "$:/language/EditTemplate/Title/Relink/Prompt", "text": "Ändere ''<$text text=<<fromTitle>>/>'' -> ''<$text text=<<toTitle>>/>'' in //tags// und //list// Feld aller anderen Tiddler" }, "$:/language/EditTemplate/Type/Dropdown/Caption": { "title": "$:/language/EditTemplate/Type/Dropdown/Caption", "text": "Tiddler Typ Liste" }, "$:/language/EditTemplate/Type/Dropdown/Hint": { "title": "$:/language/EditTemplate/Type/Dropdown/Hint", "text": "Anzeigen der Tiddler Typ Liste" }, "$:/language/EditTemplate/Type/Delete/Caption": { "title": "$:/language/EditTemplate/Type/Delete/Caption", "text": "Lösche Inhalts Typ" }, "$:/language/EditTemplate/Type/Delete/Hint": { "title": "$:/language/EditTemplate/Type/Delete/Hint", "text": "Lösche Inhalts Typ" }, "$:/language/EditTemplate/Type/Placeholder": { "title": "$:/language/EditTemplate/Type/Placeholder", "text": "Tiddler Format" }, "$:/language/EditTemplate/Type/Prompt": { "title": "$:/language/EditTemplate/Type/Prompt", "text": "Typ:" }, "$:/language/Exporters/StaticRiver": { "title": "$:/language/Exporters/StaticRiver", "text": "HTML - Statisch" }, "$:/language/Exporters/JsonFile": { "title": "$:/language/Exporters/JsonFile", "text": "JSON - Format" }, "$:/language/Exporters/CsvFile": { "title": "$:/language/Exporters/CsvFile", "text": "CSV - Format" }, "$:/language/Exporters/TidFile": { "title": "$:/language/Exporters/TidFile", "text": ".tid - Format" }, "$:/language/Docs/Fields/_canonical_uri": { "title": "$:/language/Docs/Fields/_canonical_uri", "text": "Die komplette URI eines externen Foto Tiddlers. URI = Uniform Resource Identifier, Identifikator für Ressourcen im Internet." }, "$:/language/Docs/Fields/bag": { "title": "$:/language/Docs/Fields/bag", "text": "Der Name eines ~TiddlyWeb \"bags\" von dem der Tiddler kam." }, "$:/language/Docs/Fields/caption": { "title": "$:/language/Docs/Fields/caption", "text": "Der Text, der auf \"Tab-Buttons\" angezeigt wird." }, "$:/language/Docs/Fields/color": { "title": "$:/language/Docs/Fields/color", "text": "Der CSS Farbwert, der mit einem Tiddler assoziiert wird." }, "$:/language/Docs/Fields/component": { "title": "$:/language/Docs/Fields/component", "text": "Der Name einer Komponente, die für eine [[Alarm Anzeige|AlertMechanism]] verantwortlich ist." }, "$:/language/Docs/Fields/current-tiddler": { "title": "$:/language/Docs/Fields/current-tiddler", "text": "Wird verwendet um den \"obersten\" Tiddler in der [[Tiddler Historie|HistoryMechanism]] zwischen zu speichern." }, "$:/language/Docs/Fields/created": { "title": "$:/language/Docs/Fields/created", "text": "Datum an dem der Tiddler erstellt wurde." }, "$:/language/Docs/Fields/creator": { "title": "$:/language/Docs/Fields/creator", "text": "Name des Erstellers dieses Tiddlers." }, "$:/language/Docs/Fields/dependents": { "title": "$:/language/Docs/Fields/dependents", "text": "Listet die Abhängigkeiten bei \"plugins\" auf." }, "$:/language/Docs/Fields/description": { "title": "$:/language/Docs/Fields/description", "text": "Die Beschreibung für ein \"plugin\" oder einen \"modalen\" Dialog." }, "$:/language/Docs/Fields/draft.of": { "title": "$:/language/Docs/Fields/draft.of", "text": "Entwurf von - enthält den Titel des Tiddlers, zu dem dieser Entwurf-Tiddler gehört." }, "$:/language/Docs/Fields/draft.title": { "title": "$:/language/Docs/Fields/draft.title", "text": "Entwurf Titel - enthält den neuen Titel, wenn der Entwurf-Tiddler gespeichert wird." }, "$:/language/Docs/Fields/footer": { "title": "$:/language/Docs/Fields/footer", "text": "Der Fußnoten Text bei einem \"~Wizard-Dialog\"" }, "$:/language/Docs/Fields/hack-to-give-us-something-to-compare-against": { "title": "$:/language/Docs/Fields/hack-to-give-us-something-to-compare-against", "text": "Ein temporäres Feld, verwendet in [[$:/core/templates/static.content]]" }, "$:/language/Docs/Fields/icon": { "title": "$:/language/Docs/Fields/icon", "text": "Der Titel eines ~Icon-Tiddlers, der mit diesem Tiddler verbunden ist." }, "$:/language/Docs/Fields/library": { "title": "$:/language/Docs/Fields/library", "text": "Wenn dieses Feld=\"yes\" ist, dann soll der Tiddler als JavaScript Bibliothek gespeichert werden." }, "$:/language/Docs/Fields/list": { "title": "$:/language/Docs/Fields/list", "text": "Eine geordnete Tiddler Liste, die mit diesem Tiddler verbunden ist." }, "$:/language/Docs/Fields/list-before": { "title": "$:/language/Docs/Fields/list-before", "text": "Dient zum Einfügen von Tiddler Titeln in das \"list\" Feld. Wenn gesetzt, wird der neue Tiddler ''vor'' dem hier definierten Tiddler in die Liste eingefügt. Wenn vorhanden, aber leer, dann wird der neue Tiddler an den Anfang der Liste gesetzt." }, "$:/language/Docs/Fields/list-after": { "title": "$:/language/Docs/Fields/list-after", "text": "Dient zum Einfügen von Tiddler Titeln in das \"list\" Feld. Wenn gesetzt, wird der neue Tiddler ''nach'' dem hier definierten Tiddler in die Liste eingefügt." }, "$:/language/Docs/Fields/modified": { "title": "$:/language/Docs/Fields/modified", "text": "Datum, an dem der Tiddler zuletzt verändert wurde." }, "$:/language/Docs/Fields/modifier": { "title": "$:/language/Docs/Fields/modifier", "text": "Name der Person, die den Tiddler zuletzt verändert hat." }, "$:/language/Docs/Fields/name": { "title": "$:/language/Docs/Fields/name", "text": "Ein Menschen lesbarer Name für einen \"plugin\" Tiddler." }, "$:/language/Docs/Fields/plugin-priority": { "title": "$:/language/Docs/Fields/plugin-priority", "text": "Ein numerischer Wert, der die Priorität eines \"plugins\" festlegt." }, "$:/language/Docs/Fields/plugin-type": { "title": "$:/language/Docs/Fields/plugin-type", "text": "Der Typ eines \"plugins\"." }, "$:/language/Docs/Fields/revision": { "title": "$:/language/Docs/Fields/revision", "text": "Die Revisionsnummer eines Tiddlers. Wird von einem Server vergeben." }, "$:/language/Docs/Fields/released": { "title": "$:/language/Docs/Fields/released", "text": "Datum der ~TiddlyWiki Ausgabe." }, "$:/language/Docs/Fields/source": { "title": "$:/language/Docs/Fields/source", "text": "Eine Quelltext URL, verbunden mit diesem Tiddler." }, "$:/language/Docs/Fields/subtitle": { "title": "$:/language/Docs/Fields/subtitle", "text": "Der Untertitel für einen \"~Wizard-Dialog\"." }, "$:/language/Docs/Fields/tags": { "title": "$:/language/Docs/Fields/tags", "text": "Eine Liste von \"Tags\" für diesen Tiddler." }, "$:/language/Docs/Fields/text": { "title": "$:/language/Docs/Fields/text", "text": "Der Haupttext eines Tiddlers." }, "$:/language/Docs/Fields/title": { "title": "$:/language/Docs/Fields/title", "text": "Ein individueller einmaliger Name eines Tiddlers." }, "$:/language/Docs/Fields/type": { "title": "$:/language/Docs/Fields/type", "text": "Legt den Typ eines Tiddlers fest (aka MIME-type)." }, "$:/language/Docs/Fields/version": { "title": "$:/language/Docs/Fields/version", "text": "Versions-Information eines \"plugins\"." }, "$:/language/Filters/AllTiddlers": { "title": "$:/language/Filters/AllTiddlers", "text": "Alle Tiddler außer System-Tiddler" }, "$:/language/Filters/RecentSystemTiddlers": { "title": "$:/language/Filters/RecentSystemTiddlers", "text": "Kürzlich veränderte Tiddler, inklusive System-Tiddler" }, "$:/language/Filters/RecentTiddlers": { "title": "$:/language/Filters/RecentTiddlers", "text": "Kürzlich veränderte Tiddler" }, "$:/language/Filters/AllTags": { "title": "$:/language/Filters/AllTags", "text": "Alle Tags außer System-Tags" }, "$:/language/Filters/Missing": { "title": "$:/language/Filters/Missing", "text": "Fehlende Tiddler" }, "$:/language/Filters/Drafts": { "title": "$:/language/Filters/Drafts", "text": "Entwurf Tiddler" }, "$:/language/Filters/Orphans": { "title": "$:/language/Filters/Orphans", "text": "Waisen Tiddler" }, "$:/language/Filters/SystemTiddlers": { "title": "$:/language/Filters/SystemTiddlers", "text": "System-Tiddler" }, "$:/language/Filters/ShadowTiddlers": { "title": "$:/language/Filters/ShadowTiddlers", "text": "Schatten-Tiddler" }, "$:/language/Filters/OverriddenShadowTiddlers": { "title": "$:/language/Filters/OverriddenShadowTiddlers", "text": "Überschriebene Schatten-Tiddler" }, "$:/language/Filters/SystemTags": { "title": "$:/language/Filters/SystemTags", "text": "System-Tags" }, "$:/language/Filters/StoryList": { "title": "$:/language/Filters/StoryList", "text": "Tiddler im \"story river\", außer <$text text=\"$:/AdvancedSearch\"/>" }, "$:/language/Filters/TypedTiddlers": { "title": "$:/language/Filters/TypedTiddlers", "text": "Nicht \"wiki-text\" Tiddler" }, "GettingStarted": { "title": "GettingStarted", "text": "\\define lingo-base() $:/language/ControlPanel/Basics/\nWillkommen bei ~TiddlyWiki, einem persönlichen nicht-linearen Web-Notizbuch.\n\nVor dem Start, vergewissern Sie sich, dass Sie dieses Wiki auch wirklich speichern können. Weitere Informationen finden Sie für:\n\n* Österreich: http://tiddlywiki.com/languages/de-AT\n* Deutschland: http://tiddlywiki.com/languages/de-DE\n* Allgemein (englisch): http://tiddlywiki.com \n\nErste Schritte:\n\n* Erstellen Sie einen neuen Tiddler mit dem \"Plus-Button\" in der rechten Navigationsleiste.\n* Einstellungen können im [[Kontrollpanel|$:/ControlPanel]] vorgenommen werden. Siehe: \"Zahnrad-Button\" \n** Das Anzeigen dieses Tiddlers können Sie verhindern, indem Sie die \"~DefaultTiddlers\" im ''Basis-Tab'' verändern.\n* Speichern wird mit dem \"Speichern-Button\" in der Navigationsleiste ausgelöst. \n* Österreich: [[Weitere Informationen zu WikiText|http://tiddlywiki.com/languages/de-AT/index.html#WikiText]]\n* Deutschland: [[Weitere Informationen zu WikiText|http://tiddlywiki.com/languages/de-DE/index.html#WikiText]]\n\nHinweis: Die österreichische und deutsche Version unterscheiden sich momentan nur in der Flagge, die bei der Standard Sprachauswahl angezeigt wird. In Zukunft können Beschriftungen der Benutzeroberfläche geringfügig von einander abweichen. zB: Jänner - Januar.\n\n!! Einrichten dieser ~TiddlyWiki\n\n<div class=\"tc-control-panel\">\n\n|<$link to=\"$:/SiteTitle\"><<lingo Title/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteTitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/SiteSubtitle\"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteSubtitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/DefaultTiddlers\"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit-text tag=\"textarea\" tiddler=\"$:/DefaultTiddlers\"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |\n</div>\n\nSee the [[control panel|$:/ControlPanel]] for more options.\n" }, "$:/language/Help/build": { "title": "$:/language/Help/build", "description": "Ausführen, von vorkonfigurierten Befehlen.", "text": "Dieser Befehl erstellt die vorkonfigurierten Ziele, der aktuellen Wiki Edition. Sind keine Ziele spezifiziert, dann werden all konfigurierten Ziele erstellt.\n\n```\n--build <target> [<target> ...]\n```\n\nZiele werden in der `tiddlywiki.info` Datei, im Wiki Verzeichnis konfiguriert.\n" }, "$:/language/Help/clearpassword": { "title": "$:/language/Help/clearpassword", "description": "Lösche das Passwort, das für die vorhergehenen Verschlüsselungen verwendet wurde.", "text": "Lösche das Passwort, das für die vorhergehenen Verschlüsselungen verwendet wurde.\n\n```\n--clearpassword\n```\n" }, "$:/language/Help/default": { "title": "$:/language/Help/default", "text": "\\define commandTitle()\n$:/language/Help/$(command)$\n\\end\n```\nVerwendung: tiddlywiki [<wikifolder>] [--<command> [<args>...]...]\n```\n\nVerfügbare Befehle:\n\n<ul>\n<$list filter=\"[commands[]sort[title]]\" variable=\"command\">\n<li><$link to=<<commandTitle>>><$macrocall $name=\"command\" $type=\"text/plain\" $output=\"text/plain\"/></$link>: <$transclude tiddler=<<commandTitle>> field=\"description\"/></li>\n</$list>\n</ul>\n\nDetailierte Informationen zu den Befehlen:\n\n```\ntiddlywiki --help <command>\n```\n" }, "$:/language/Help/editions": { "title": "$:/language/Help/editions", "description": "Listet alle verfügbaren TiddlyWiki Editionen auf", "text": "Listet alle verfügbaren TiddlyWiki Editionen auf.\n\n```\n--editions\n```\n\nSie können ein neues Wiki mit dem `--init` Kommando erstellen. Dabei wird eine der angezeigten Editionen \"geklont\".\n" }, "$:/language/Help/fetch": { "title": "$:/language/Help/fetch", "description": "Fetch tiddlers from wiki by URL", "text": "Abrufen eines oder mehrerer Dateien über HTTP/HTTPS. Importieren der tiddler, die dem Filter entsprechen. Umwandeln der ankommenden Titel, wenn nötig.\n\n```\n--fetch file <url> <import-filter> <transform-filter>\n--fetch files <url-filter> <import-filter> <transform-filter>\n```\n\nWird der `file` parameter verwendet, wird nur eine einzelne Datei geholt. Der erste Parameter ist die URL von der die Datei geladen werden soll.\n\nWird der `files` parameter verwendet, werden mehrere Dateien geholt. In diesem Fall ist der erste Parameter ein Filter, der eine Liste von URLs ergibt, von denen die Dateien gelesen werden sollen. Zum Beispiel: Mehrere Tiddler sind getagged mit: `remote-server` und enthalten ein Feld: `url`. ... Der Filter `[tag[remote-server]get[url]]` wird alle verfügbaren URLs ansprechen.\n\n\nDer `<import-filter>` Parameter, spezifiziert jene Tiddler, die importiert werden sollen. Standard ist: `[all[tiddlers]]`, wenn nichts angegeben wird.\n\nDer `<transform-filter>` Parameter, spezifiziert einen Filter, mit dem der Tiddler Name verändert werden kann. zB: `[addprefix[$:/meinImport/]]` würde `$:/meinImport/` allen Tiddler Namen voran stellen.\n\nWird `--verbose` vor dem `--fetch` Befehl benutzt, dann werden erweiterte Diagnose Infos ausgegeben.\n\nHinweis: ~TiddlyWiki wird ''keine'' veralteten plugins importieren.\n\nDas folgende Beispiel wird alle \"nicht-system\" Tiddler von http://tiddlywiki.com holen und in ein `JSON` file speichern.\n\n```\ntiddlywiki --verbose --fetch file \"http://tiddlywiki.com/\" \"[!is[system]]\" \"\" --rendertiddler \"$:/core/templates/exporters/JsonFile\" output.json text/plain \"\" exportFilter \"[!is[system]]\"\n```\n" }, "$:/language/Help/help": { "title": "$:/language/Help/help", "description": "Anzeige der Hilfe für die TiddlyWiki Befehle.", "text": "Anzeige der Hilfe für die TiddlyWiki Befehle.\n\nBeispiel:\n\n```\n--help [<command>]\n```\n\nWird der Parameter <command> nicht angegeben, werden alle Befehle aufgelistet.\n" }, "$:/language/Help/init": { "title": "$:/language/Help/init", "description": "Initialisiere eine neues Wiki Verzeichnis.", "text": "Initialisiere eine neues [[Wiki Verzeichnis|WikiFolders]] mit der Kopie einer Edition.\n\n```\n--init <edition> [<edition> ...]\n```\n\nBeispiel:\n\n```\ntiddlywiki ./MyWikiFolder --init empty\n```\n\nAnmerkung:\n\n* Das Wiki Verzeichnis wird angelegt, wenn es nicht existiert.\n* Der <edition> Parameter ist standardmäßig: ''empty''.\n* Der --init Befehl bricht ab, wenn das angegebene Verzeichnis nicht leer ist.\n* Der --init Befehl löscht alle `includeWikis` Definitionen aus der neuen `tiddlywiki.info` Datei\n* Wenn mehrere Editionen importiert werden, wird die zuletzt importierte `tidlywiki.info` Datei aktiv sein. Alle anderen weden überschrieben.\n\n* `--editions` listet alle verfügbaren Editionen auf.\n" }, "$:/language/Help/load": { "title": "$:/language/Help/load", "description": "Lade Tiddler von einer Datei.", "text": "Lade Tiddler aus einer TiddlyWiki 2.x.x `.html`, `.tiddler`, .`tid`, `.json` oder anderen Datei.\n\n```\n--load <filepath>\n```\n\nUm Daten aus einer verschlüsselten TiddlyWiki Datei zu laden, muss zuerst mit dem \"password\" Parameter ein Passwort definiert werden. \n\nBeispiel:\n\n```\ntiddlywiki ./MyWiki --password pa55w0rd --load my_encrypted_wiki.html\n```\n\nHinweis: TiddlyWiki wird nur neuere Versionen eines bestehenden Plugins laden!\n" }, "$:/language/Help/makelibrary": { "title": "$:/language/Help/makelibrary", "description": "Erstellt die \"Upgrade Bibliothek\", die vom upgrade Prozess benötigt wird", "text": "Erstellt den tiddler: `$:/UpgradeLibrary`, der vom upgrade Prozess benötigt wird.\n\nDie \"Upgrade Bibliothek\" ist ein \"normales\" Plugin, vom Typ: `library`. Es enthält eine Kopie jedes Plugins, Themas und Sprachpacketes, das im TiddlyWiki Archiv enthalten ist.\n\nDieser Befehl ist ein \"interner\" Befehl! Er ist nur relevant für Benutzer, die einen spezifischen \"Upgrade Prezess\" erstellen müssen. zB: Umwandeln von einem Tiddler in mehrere Tiddler, um Inkompatibilitäten zu vermeiden.\n\n```\n--makelibrary <title>\n```\n\nDas \"title\" Argument ist standardmäßig: `$:/UpgradeLibrary`.\n" }, "$:/language/Help/notfound": { "title": "$:/language/Help/notfound", "text": "Keine Hilfe zu diesem Thema gefunden!" }, "$:/language/Help/output": { "title": "$:/language/Help/output", "description": "Setzt das Basis Ausgabeverzeichnis für die folgenden Befehle.", "text": "Setzt das Basis Ausgabeverzeichnis für die folgenden Befehle. Das Standard Verzeichnis heißt: `output` und ist ein Unterverzeichnis des `edition` Verzeichnisses.\n\n```\n--output <pathname>\n```\n\nIst das spezifizierte Verzeichnis \"relativ\", dann wird es relativ zum bestehenden Arbeitsverzeichnis angelegt.\nZum Beispiel: `--output .` setzt das Ausgabeverzeichnis auf das aktuelle Verzeichnis.\n" }, "$:/language/Help/password": { "title": "$:/language/Help/password", "description": "Setzen eines Passwortes für Verschlüsselungsoperationen.", "text": "Setzen eines Passwortes für Verschlüsselungsoperationen\n\n```\n--password <password>\n```\n\nHinweis: Diese Option kann nicht verwendet werden, um ein \"Server Passwort\" festzulegen! Informationen zum Server Passwort siehe \"--server\" Kommando.\n" }, "$:/language/Help/rendertiddler": { "title": "$:/language/Help/rendertiddler", "description": "Ausgabe eines individuellen Tiddlers, in einem spezifizierten Format.", "text": "Ausgabe eines individuellen Tiddlers, in einem spezifizierten Format (standard: `text/html`) und Dateinamen.\n\nOptional kann ein Template tiddler angegeben werden. Die \"currentTiddler\" Variable wird auf den Tiddler gesetzt, der zu rendern ist.\n\n```\n--rendertiddler <title> <filename> [<type>] [<template>] [<name>] [<value>]\n```\n\nStandardmäßig ist das `output` Verzeichnis ein Unterverzeichnis im `edition` Verzeichnis. Der `--output` Befehl kann verwendet werden, um ein anderes Verzeichnis auszuwählen.\n\nNicht vorhandene Verzeichnisse werden automatisch erstellt.\n\n''Beispiel:''\n\nDer folgende Befehl speichert alle tiddler mit dem `tag: done` in eine `JSON` Datei mit dem Namen: `output.json`. Das Template `$:/core/templates/exporters/JsonFile` wird auf die zu speichernden Daten angewandt.\n\n```\n--rendertiddler \"$:/core/templates/exporters/JsonFile\" output.json text/plain \"\" exportFilter \"[tag[done]]\"\n```\n" }, "$:/language/Help/rendertiddlers": { "title": "$:/language/Help/rendertiddlers", "description": "Gefilterte Ausgabe von Tiddlern, in einem spezifizierten Format.", "text": "Gefilterte Ausgabe mehrerer Tiddler, in ein angegebenes Dateiformat (standard: `text/html`) mit spezifischer Erweiterung (Standard: `.html`).\n\n```\n--rendertiddlers <filter> <template> <pathname> [<type>] [<extension>] [\"noclean\"]\n```\n\nBeispiel:\n\n```\n--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html ./static text/plain\n```\n\nStandardmäßig ist das `output` Verzeichnis ein Unterverzeichnis im `edition` Verzeichnis. Der `--output` Befehl kann verwendet werden, um ein anderes Verzeichnis auszuwählen.\n\nNicht vorhandene Verzeichnisse werden automatisch erstellt und enthaltene Dateien werden gelöscht. Mit dem \"noclean\" Parameter, kann das löschen vorhandener Dateien unterdrückt werden.\n" }, "$:/language/Help/savetiddler": { "title": "$:/language/Help/savetiddler", "description": "Speichert einen Tiddler als File.", "text": "Speichert einen individuellen Tiddler im Text- oder Binärformat mit dem angegebenen Dateinamen.\n\n```\n--savetiddler <title> <filename>\n```\n\nStandardmäßig ist das `output` Verzeichnis ein Unterverzeichnis im `edition` Verzeichnis. Der `--output` Befehl kann verwendet werden, um ein anderes Verzeichnis auszuwählen.\n\nNicht vorhandene Verzeichnisse werden automatisch erstellt.\n" }, "$:/language/Help/savetiddlers": { "title": "$:/language/Help/savetiddlers", "description": "Speichert eine Gruppe von Tiddler in ein Verzeichnis", "text": "Speichert eine Gruppe von Tiddler im Text- oder Binärformat in ein angegebenes Verzeichnis.\n\n```\n--savetiddlers <filter> <pathname> [\"noclean\"]\n```\n\nStandardmäßig ist das `output` Verzeichnis ein Unterverzeichnis im `edition` Verzeichnis. Der `--output` Befehl kann verwendet werden, um ein anderes Verzeichnis auszuwählen.\n\nWichtig: Alle Dateien im Ausgabeverzeichnis werden automatisch gelöscht, wenn dieser Befehl verwendet wird. Um dies zu verhindern kann der ''noclean'' Parameter verwendet werden.\n\nNicht vorhandene Verzeichnisse im Pfadnamen werden automatisch erstellt.\n" }, "$:/language/Help/server": { "title": "$:/language/Help/server", "description": "Stellt einen HTTP server für TiddlyWiki zur Verfügung.", "text": "TiddlyWiki bringt einen sehr einfachen Web-Server mit. Dieser ist zwar kompatibel mit dem TiddlyWeb Protokoll, ist jedoch nicht ausgereift genug, um im produktiven Einsatz im Netz eingesetzt zu werden. \n\nDer Server kann spezifische Tiddler im angegebenen Format anzeigen (rendern). Zudem können einzelne, oder mehrere Tiddler im JSON Format übertragen werden. Die unterstützten HTTP Funktionen sind: `GET`, `PUT` und `DELETE`\n\n```\n--server <port> <roottiddler> <rendertype> <servetype> <username> <password> <host>\n```\n\nDie Parameter sind: \n\n* ''port'' - Port Nummer mit der kommuniziert werden soll (Standard: \"8080\").\n* ''roottiddler'' - Der Tiddler, der als ~Basis-Tiddler verwendet werden soll ( Standard: \"$:/core/save/all\").\n* ''rendertype'' - MIME-Type, zu dem der ~Basis-Tiddler \"gerendert\" werden soll ( Standard: \"text/plain\").\n* ''servetype'' - MIME-Type, mit dem der Basis-Tiddler ausgeliefert werden soll ( Standard: \"text/html\").\n* ''username'' - Benutzer Name, mit dem veränderte Tiddler signiert werden.\n* ''password'' - Passwort mit dem eine sehr \"simple\" Zugangsbeschränkung aufgebaut werden kann.\n* ''host'' - ~Host-Name von dem ausgeliefert werden soll. Host ist optional ( Standard: \"127.0.0.1\" oder auch \"localhost\").\n* ''pathprefix'' - Optionales prefix für Pfade.\n\nWenn beim Serverstart ein Passwort angegeben wird, dann wird der Benutzer aufgefordert den Benutzernamen und das Passwort einzugeben, bevor ein Wiki angezeigt wird. ACHTUNG: Das Passwort wird im Klartext übertragen. Diese Vorgehensweise ist nicht für den Einsatz im Netz geeignet.\n\nBeispiel:\n\n```\n--server 8080 $:/core/save/all text/plain text/html MeinBenutzerName passw0rt\n```\n\nDer Name und das Passwort können als \"leere\" Zeichenketten definiert werden, wenn ein \"hostname\" oder \"pathprefix\" nötig ist, jedoch kein Passwort verwendet werden soll.\n\n```\n--server 8080 $:/core/save/all text/plain text/html \"\" \"\" 192.168.0.245\n```\n\nEs ist möglich mehrere TiddlyWiki Server gleichzeitig zu starten. Jeder Server muss jedoch mit einem eigenen Port gestartet werden.\n" }, "$:/language/Help/setfield": { "title": "$:/language/Help/setfield", "description": "Experimentell - Setzt ein Tiddler \"field\" auf einen bestimmten Wert", "text": "//Wichtig! Dieser Befehl is experimentell und kann während der Betaphase geändert oder ersetzt werden!//\n\nSetzt ein spezifiziertes Feld, für eine Gruppe von Tiddlern. Ein Template wird \"wikifiziert\" und das Ergebnis in das Feld geschrieben. Die `currentTiddler` Variable wird auf den jeweiligen Tiddler gesetzt. \n\n```\n--setfield <filter> <fieldname> <templatetitle> <rendertype>\n```\n\nThe parameters are:\n\n* ''filter'' - Filter, der die zu modifizierenden Tiddler auswählt.\n* ''fieldname'' - Das zu verändernde Feld (Standardwert: \"text\").\n* ''templatetitle'' - Der zu wikifizierende Vorlagen Tiddler, dessen Ergebnis in das Feld geschrieben wird. Wenn Leer, dann wird das Feld gelöscht.\n* ''rendertype'' - Der Text Typ für den \"rendering\" Vorgang (Standardwert: \"text/plain\"; \"text/html\" kann verwendet werden, um \"HTML tags\" zu erzeugen).\n" }, "$:/language/Help/unpackplugin": { "title": "$:/language/Help/unpackplugin", "description": "Extrahiere Tiddler aus einem Plugin", "text": "Extrahiert alle Tiddler aus einem plugin und schreibt diese als einzelne Tiddler Dateien:\n\n```\n--unpackplugin <title>\n```\n" }, "$:/language/Help/verbose": { "title": "$:/language/Help/verbose", "description": "Aktiviert die erweiterte Fehlerausgabe.", "text": "Aktiviert die erweiterte Fehlerausgabe. Nützlich um Fehler zu finden.\n\n```\n--verbose\n```\n" }, "$:/language/Help/version": { "title": "$:/language/Help/version", "description": "Gibt die Versionsnummer von TiddlyWiki aus.", "text": "Gibt die Versionsnummer von TiddlyWiki aus.\n\n```\n--version\n```\n" }, "$:/language/Import/Imported/Hint": { "title": "$:/language/Import/Imported/Hint", "text": "Folgende Tiddler wurden importiert:" }, "$:/language/Import/Listing/Cancel/Caption": { "title": "$:/language/Import/Listing/Cancel/Caption", "text": "Abbrechen" }, "$:/language/Import/Listing/Hint": { "title": "$:/language/Import/Listing/Hint", "text": "Diese Tiddler können importiert werden:" }, "$:/language/Import/Listing/Import/Caption": { "title": "$:/language/Import/Listing/Import/Caption", "text": "Importieren" }, "$:/language/Import/Listing/Select/Caption": { "title": "$:/language/Import/Listing/Select/Caption", "text": "Auswahl" }, "$:/language/Import/Listing/Status/Caption": { "title": "$:/language/Import/Listing/Status/Caption", "text": "Status" }, "$:/language/Import/Listing/Title/Caption": { "title": "$:/language/Import/Listing/Title/Caption", "text": "Titel" }, "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible": { "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible", "text": "Unterdrückte, inkompatible oder veraltete \"plugins\"" }, "$:/language/Import/Upgrader/Plugins/Suppressed/Version": { "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Version", "text": "Einige \"plugins\" weden unterdrückt! Importierte plugins: <<incoming>> sind älter als existierende: <<existing>>." }, "$:/language/Import/Upgrader/Plugins/Upgraded": { "title": "$:/language/Import/Upgrader/Plugins/Upgraded", "text": "Aktualisieren der plugins von: <<incoming>> nach: <<upgraded>>" }, "$:/language/Import/Upgrader/State/Suppressed": { "title": "$:/language/Import/Upgrader/State/Suppressed", "text": "Unterdrückte temporäre Status Tiddler" }, "$:/language/Import/Upgrader/System/Suppressed": { "title": "$:/language/Import/Upgrader/System/Suppressed", "text": "Unterdrückte \"System Tiddler\"" }, "$:/language/Import/Upgrader/ThemeTweaks/Created": { "title": "$:/language/Import/Upgrader/ThemeTweaks/Created", "text": "Migrieren der \"theme tweaks\" von: <$text text=<<from>>/>" }, "$:/language/AboveStory/ClassicPlugin/Warning": { "title": "$:/language/AboveStory/ClassicPlugin/Warning", "text": "Es scheint, Sie möchten ein Plugin verwenden, dass für [[TiddlyWiki Classic|http://tiddlywiki.com/#TiddlyWikiClassic]] entwickelt wurde. Diese Plugins können jedoch mit ~TiddlyWiki Version 5 nicht verwendet werden. ~TiddlyWiki Classic plugin erkannt:" }, "$:/language/BinaryWarning/Prompt": { "title": "$:/language/BinaryWarning/Prompt", "text": "Dieser Tiddler enthält binäre Daten." }, "$:/language/ClassicWarning/Hint": { "title": "$:/language/ClassicWarning/Hint", "text": "Dieser Tiddler wurde im TiddlyWiki Classic Format erstellt. Dieses Format ist nur teilweise kompatibel mit TiddlyWiki Version 5. Mehr Info finden Sie unter: http://tiddlywiki.com/static/Upgrading.html" }, "$:/language/ClassicWarning/Upgrade/Caption": { "title": "$:/language/ClassicWarning/Upgrade/Caption", "text": "upgrade" }, "$:/language/CloseAll/Button": { "title": "$:/language/CloseAll/Button", "text": "alle schließen" }, "$:/language/ColourPicker/Recent": { "title": "$:/language/ColourPicker/Recent", "text": "Kürzlich:" }, "$:/language/ConfirmCancelTiddler": { "title": "$:/language/ConfirmCancelTiddler", "text": "Wollen Sie die Änderungen im Tiddler: \"<$text text=<<title>>/>\" verwerfen?" }, "$:/language/ConfirmDeleteTiddler": { "title": "$:/language/ConfirmDeleteTiddler", "text": "Wollen Sie den Tiddler: \"<$text text=<<title>>/>\" löschen?" }, "$:/language/ConfirmOverwriteTiddler": { "title": "$:/language/ConfirmOverwriteTiddler", "text": "Tiddler: \"<$text text=<<title>>/>\" existiert! OK überschreibt den tiddler!" }, "$:/language/ConfirmEditShadowTiddler": { "title": "$:/language/ConfirmEditShadowTiddler", "text": "Sie sind dabei, einen Schatten-Tiddler zu verändern. Zukünftige, automatische Anpassungen werden dadurch unterdrückt. Sie können Ihre Änderungen rückgängig machen, indem Sie diesen Tiddler wieder löschen. Wollen Sie den Tiddler: \"<$text text=<<title>>/>\" ändern?" }, "$:/language/Count": { "title": "$:/language/Count", "text": "Anzahl" }, "$:/language/DefaultNewTiddlerTitle": { "title": "$:/language/DefaultNewTiddlerTitle", "text": "Neuer Tiddler" }, "$:/language/DropMessage": { "title": "$:/language/DropMessage", "text": "Hierher ziehen (oder Escape um abzubrechen)" }, "$:/language/Encryption/Cancel": { "title": "$:/language/Encryption/Cancel", "text": "Abbrechen" }, "$:/language/Encryption/ConfirmClearPassword": { "title": "$:/language/Encryption/ConfirmClearPassword", "text": "Wollen Sie das Passwort löschen? Damit wird die Verschlüsselung beim nächsten Speichervorgang abgeschalten!" }, "$:/language/Encryption/PromptSetPassword": { "title": "$:/language/Encryption/PromptSetPassword", "text": "Der TiddlyWiki Inhalt wird mit dem nächsten Speichern verschlüsselt!" }, "$:/language/Encryption/Username": { "title": "$:/language/Encryption/Username", "text": "Benutzername" }, "$:/language/Encryption/Password": { "title": "$:/language/Encryption/Password", "text": "Passwort" }, "$:/language/Encryption/RepeatPassword": { "title": "$:/language/Encryption/RepeatPassword", "text": "Passwort wiederholen" }, "$:/language/Encryption/PasswordNoMatch": { "title": "$:/language/Encryption/PasswordNoMatch", "text": "Passwörter stimmen nicht überein" }, "$:/language/Encryption/SetPassword": { "title": "$:/language/Encryption/SetPassword", "text": "Passwort setzen" }, "$:/language/Error/Caption": { "title": "$:/language/Error/Caption", "text": "Fehler" }, "$:/language/Error/EditConflict": { "title": "$:/language/Error/EditConflict", "text": "Datei auf Server verändert" }, "$:/language/Error/Filter": { "title": "$:/language/Error/Filter", "text": "Filter Fehler" }, "$:/language/Error/FilterSyntax": { "title": "$:/language/Error/FilterSyntax", "text": "Syntax Fehler im Filter-Ausdruck" }, "$:/language/Error/IsFilterOperator": { "title": "$:/language/Error/IsFilterOperator", "text": "Filter Fehler: Unbekannter Operand für den 'is' Filter Operator" }, "$:/language/Error/LoadingPluginLibrary": { "title": "$:/language/Error/LoadingPluginLibrary", "text": "Fehler beim Laden der \"plugin library\"" }, "$:/language/Error/RecursiveTransclusion": { "title": "$:/language/Error/RecursiveTransclusion", "text": "Recursive Transclusion: Fehler im \"transclude widget\"" }, "$:/language/Error/RetrievingSkinny": { "title": "$:/language/Error/RetrievingSkinny", "text": "Fehler beim Empfangen einer \"skinny\" Tiddler Liste" }, "$:/language/Error/SavingToTWEdit": { "title": "$:/language/Error/SavingToTWEdit", "text": "Fehler beim Speichern mit \"TWEdit\"" }, "$:/language/Error/WhileSaving": { "title": "$:/language/Error/WhileSaving", "text": "Fehler beim Speichern" }, "$:/language/Error/XMLHttpRequest": { "title": "$:/language/Error/XMLHttpRequest", "text": "XMLHttpRequest Fehler-Code" }, "$:/language/InternalJavaScriptError/Title": { "title": "$:/language/InternalJavaScriptError/Title", "text": "Interner JavaScript Fehler" }, "$:/language/InternalJavaScriptError/Hint": { "title": "$:/language/InternalJavaScriptError/Hint", "text": "Es tut uns leid, aber bitte starten Sie Ihr TiddlyWiki neu, indem sie die Seite im Browser neu laden." }, "$:/language/InvalidFieldName": { "title": "$:/language/InvalidFieldName", "text": "Das Feld: \"<$text text=<<fieldName>>/>\" enthält illegale Zeichen. Felder müssen klein geschrieben werden. Erlaubte Sonderzeichen sind: Zahlen, Unterstrich (`_`), Minus (`-`) und Punkt (`.`)." }, "$:/language/LazyLoadingWarning": { "title": "$:/language/LazyLoadingWarning", "text": "<p>Lade externe Datei von ''<$text text={{!!_canonical_uri}}/>''</p><p>Wenn diese Meldung nicht automatisch gelöscht wird, dann verwenden Sie wahrscheinlich einen Browser der diese Funktion nicht unterstützt. Siehe http://tiddlywiki.com/#ExternalText</p>" }, "$:/language/LoginToTiddlySpace": { "title": "$:/language/LoginToTiddlySpace", "text": "Login bei TiddlySpace" }, "$:/language/Manager/Controls/FilterByTag/None": { "title": "$:/language/Manager/Controls/FilterByTag/None", "text": "(kein)" }, "$:/language/Manager/Controls/FilterByTag/Prompt": { "title": "$:/language/Manager/Controls/FilterByTag/Prompt", "text": "Filtern nach tag:" }, "$:/language/Manager/Controls/Order/Prompt": { "title": "$:/language/Manager/Controls/Order/Prompt", "text": "Invertiert" }, "$:/language/Manager/Controls/Search/Placeholder": { "title": "$:/language/Manager/Controls/Search/Placeholder", "text": "Suche" }, "$:/language/Manager/Controls/Search/Prompt": { "title": "$:/language/Manager/Controls/Search/Prompt", "text": "Suche:" }, "$:/language/Manager/Controls/Show/Option/Tags": { "title": "$:/language/Manager/Controls/Show/Option/Tags", "text": "Tags" }, "$:/language/Manager/Controls/Show/Option/Tiddlers": { "title": "$:/language/Manager/Controls/Show/Option/Tiddlers", "text": "Tiddler" }, "$:/language/Manager/Controls/Show/Prompt": { "title": "$:/language/Manager/Controls/Show/Prompt", "text": "Anzeigen:" }, "$:/language/Manager/Controls/Sort/Prompt": { "title": "$:/language/Manager/Controls/Sort/Prompt", "text": "Sortieren nach:" }, "$:/language/Manager/Item/Colour": { "title": "$:/language/Manager/Item/Colour", "text": "Farbe" }, "$:/language/Manager/Item/Fields": { "title": "$:/language/Manager/Item/Fields", "text": "Feld" }, "$:/language/Manager/Item/Icon/None": { "title": "$:/language/Manager/Item/Icon/None", "text": "(kein)" }, "$:/language/Manager/Item/Icon": { "title": "$:/language/Manager/Item/Icon", "text": "Icon" }, "$:/language/Manager/Item/RawText": { "title": "$:/language/Manager/Item/RawText", "text": "Text" }, "$:/language/Manager/Item/Tags": { "title": "$:/language/Manager/Item/Tags", "text": "Tags" }, "$:/language/Manager/Item/Tools": { "title": "$:/language/Manager/Item/Tools", "text": "Tools" }, "$:/language/Manager/Item/WikifiedText": { "title": "$:/language/Manager/Item/WikifiedText", "text": "Wikified Text" }, "$:/language/MissingTiddler/Hint": { "title": "$:/language/MissingTiddler/Hint", "text": "Fehlender Tiddler \"<$text text=<<currentTiddler>>/>\" - klicken Sie {{$:/core/images/edit-button}} um ihn zu erzeugen." }, "$:/language/No": { "title": "$:/language/No", "text": "Nein" }, "$:/language/OfficialPluginLibrary": { "title": "$:/language/OfficialPluginLibrary", "text": "Offizielles ~TiddlyWiki Plugin-Verzeichnis" }, "$:/language/OfficialPluginLibrary/Hint": { "title": "$:/language/OfficialPluginLibrary/Hint", "text": "Offizielles ~TiddlyWiki Plugin-Verzeichnis auf tiddlywiki.com. Plugin, Themes und Sprach Dateien werden vom \"core team\" gewartet." }, "$:/language/PluginReloadWarning": { "title": "$:/language/PluginReloadWarning", "text": "Das Wiki muss gespeichert {{$:/core/ui/Buttons/save-wiki}} und neu gladen {{$:/core/ui/Buttons/refresh}} werden, damit die Plugins ausgeführt werden." }, "$:/language/RecentChanges/DateFormat": { "title": "$:/language/RecentChanges/DateFormat", "text": "YYYY MMM DD" }, "$:/language/SystemTiddler/Tooltip": { "title": "$:/language/SystemTiddler/Tooltip", "text": "Das ist ein System-Tiddler" }, "$:/language/SystemTiddlers/Include/Prompt": { "title": "$:/language/SystemTiddlers/Include/Prompt", "text": "System-Tiddler einschließen" }, "$:/language/TagManager/Colour/Heading": { "title": "$:/language/TagManager/Colour/Heading", "text": "Farbe" }, "$:/language/TagManager/Count/Heading": { "title": "$:/language/TagManager/Count/Heading", "text": "Anzahl" }, "$:/language/TagManager/Icon/Heading": { "title": "$:/language/TagManager/Icon/Heading", "text": "Symbol" }, "$:/language/TagManager/Info/Heading": { "title": "$:/language/TagManager/Info/Heading", "text": "Info" }, "$:/language/TagManager/Tag/Heading": { "title": "$:/language/TagManager/Tag/Heading", "text": "Tag" }, "$:/language/Tiddler/DateFormat": { "title": "$:/language/Tiddler/DateFormat", "text": "DDth MMM YYYY um 0hh:0mm" }, "$:/language/UnsavedChangesWarning": { "title": "$:/language/UnsavedChangesWarning", "text": "TiddlyWiki wurde geändert, aber noch nicht gespeichert!" }, "$:/language/Yes": { "title": "$:/language/Yes", "text": "Ja" }, "$:/language/Modals/Download": { "title": "$:/language/Modals/Download", "type": "text/vnd.tiddlywiki", "subtitle": "Änderungen Speichern", "footer": "<$button message=\"tm-close-tiddler\">Schließen</$button>", "help": "http://tiddlywiki.com/static/DownloadingChanges.html", "text": "Ihr Browser unterstützt nur manuelles Speichern. \n\nUm das geänderte Wiki zu speichern, machen Sie einen \"rechts klick\" auf den folgenden Link. Wählen Sie \"Datei herunterladen\" oder \"Datei speichern\" und wählen Sie Name und Verzeichnis.\n\n//Sie können den Vorgang etwas beschleunigen, indem Sie die \"Control-Taste\" (Windows) oder die \"Options/Alt-Taste\" (Max OS X) drücken. Es wird kein \"Speichern Dialog\" erscheinen. Jedoch wird bei einigen Browsern die Datei einen zufälligen Namen bekommen. Sie müssen die Datei eventuell umbenennen, um sie öffnen zu können.//\n\nBei \"Smartphones\", die das Speichern von Dateien nicht erlauben, können Sie ein Lesezeichen erstellen, dass mit Ihrem PC synchronisiert wird. Dort können Sie die Dateien dann wie gewohnt speichern.\n" }, "$:/language/Modals/SaveInstructions": { "title": "$:/language/Modals/SaveInstructions", "type": "text/vnd.tiddlywiki", "subtitle": "Aktuellen Stand speichern", "footer": "<$button message=\"tm-close-tiddler\">Schließen</$button>", "help": "http://tiddlywiki.com/static/SavingChanges.html", "text": "Ihre Änderungen sollen als ~TiddlyWiki HTML Datei gespeichert werden. \n\n!!! Desktop Browser\n\n# Verwenden Sie ''Speichern unter'' aus dem ''Datei'' Menü.\n# Wählen Sie den Dateinamen und das Verzeichnis. \n\n#* Bei einigen Browsern müssen Sie das Format explizit angeben. Zb: ''Webseite, nur HTML'' oder ähnliches.\n# Den Browser-Tab schließen.\n\n!!! Smartphone Browser\n\n# Erstellen Sie ein \"Lesezeichen\"\n#* Wenn Sie \"iCloud\" oder \"Google Sync\" verwenden, dann werden Ihre Daten automatisch mit dem Desktop PC synchronisiert. Dort können Sie wie oben beschrieben fortfahren. \n# Den Browser-Tab schließen.\n\n//Wenn Sie das Lesezeichen mit \"Mobile Safari\" öffnen, dann wird diese Meldung erneut angezeigt. Klicken Sie ''Schließen'' um fort zu fahren.//\n" }, "$:/config/NewJournal/Title": { "title": "$:/config/NewJournal/Title", "text": "YYYY MMM 0DD" }, "$:/config/NewJournal/Text": { "title": "$:/config/NewJournal/Text", "text": "" }, "$:/config/NewJournal/Tags": { "title": "$:/config/NewJournal/Tags", "text": "Journal" }, "$:/language/Notifications/Save/Done": { "title": "$:/language/Notifications/Save/Done", "text": "Wiki gespeichert!" }, "$:/language/Notifications/Save/Starting": { "title": "$:/language/Notifications/Save/Starting", "text": "Wiki zum Speichern vorbereiten!" }, "$:/language/Search/DefaultResults/Caption": { "title": "$:/language/Search/DefaultResults/Caption", "text": "Liste" }, "$:/language/Search/Filter/Caption": { "title": "$:/language/Search/Filter/Caption", "text": "Filter" }, "$:/language/Search/Filter/Hint": { "title": "$:/language/Search/Filter/Hint", "text": "Suche mit [[\"filter expression\"|http://tiddlywiki.com/static/Filters.html]]." }, "$:/language/Search/Filter/Matches": { "title": "$:/language/Search/Filter/Matches", "text": "//<small><<resultCount>> Treffer</small>//" }, "$:/language/Search/Matches": { "title": "$:/language/Search/Matches", "text": "//<small><<resultCount>> Treffer</small>//" }, "$:/language/Search/Matches/All": { "title": "$:/language/Search/Matches/All", "text": "Alle Treffer:" }, "$:/language/Search/Matches/Title": { "title": "$:/language/Search/Matches/Title", "text": "Titel Treffer:" }, "$:/language/Search/Search": { "title": "$:/language/Search/Search", "text": "Suchen" }, "$:/language/Search/Search/TooShort": { "title": "$:/language/Search/Search/TooShort", "text": "Suchtext ist zu kurz" }, "$:/language/Search/Shadows/Caption": { "title": "$:/language/Search/Shadows/Caption", "text": "Schatten" }, "$:/language/Search/Shadows/Hint": { "title": "$:/language/Search/Shadows/Hint", "text": "Suche in Schatten-Tiddlern." }, "$:/language/Search/Shadows/Matches": { "title": "$:/language/Search/Shadows/Matches", "text": "//<small><<resultCount>> Treffer</small>//" }, "$:/language/Search/Standard/Caption": { "title": "$:/language/Search/Standard/Caption", "text": "Standard" }, "$:/language/Search/Standard/Hint": { "title": "$:/language/Search/Standard/Hint", "text": "Suche in Standard-Tiddlern." }, "$:/language/Search/Standard/Matches": { "title": "$:/language/Search/Standard/Matches", "text": "//<small><<resultCount>> matches</small>//" }, "$:/language/Search/System/Caption": { "title": "$:/language/Search/System/Caption", "text": "System" }, "$:/language/Search/System/Hint": { "title": "$:/language/Search/System/Hint", "text": "Suche in System-Tiddlern." }, "$:/language/Search/System/Matches": { "title": "$:/language/Search/System/Matches", "text": "//<small><<resultCount>> Treffer</small>//" }, "$:/language/SideBar/All/Caption": { "title": "$:/language/SideBar/All/Caption", "text": "Alle" }, "$:/language/SideBar/Contents/Caption": { "title": "$:/language/SideBar/Contents/Caption", "text": "Inhalt" }, "$:/language/SideBar/Drafts/Caption": { "title": "$:/language/SideBar/Drafts/Caption", "text": "Entwurf" }, "$:/language/SideBar/Missing/Caption": { "title": "$:/language/SideBar/Missing/Caption", "text": "Fehlend" }, "$:/language/SideBar/More/Caption": { "title": "$:/language/SideBar/More/Caption", "text": "Mehr" }, "$:/language/SideBar/Open/Caption": { "title": "$:/language/SideBar/Open/Caption", "text": "Offen" }, "$:/language/SideBar/Orphans/Caption": { "title": "$:/language/SideBar/Orphans/Caption", "text": "Waisen" }, "$:/language/SideBar/Recent/Caption": { "title": "$:/language/SideBar/Recent/Caption", "text": "Zuletzt" }, "$:/language/SideBar/Shadows/Caption": { "title": "$:/language/SideBar/Shadows/Caption", "text": "Schatten" }, "$:/language/SideBar/System/Caption": { "title": "$:/language/SideBar/System/Caption", "text": "System" }, "$:/language/SideBar/Tags/Caption": { "title": "$:/language/SideBar/Tags/Caption", "text": "Tags" }, "$:/language/SideBar/Tags/Untagged/Caption": { "title": "$:/language/SideBar/Tags/Untagged/Caption", "text": "untagged" }, "$:/language/SideBar/Tools/Caption": { "title": "$:/language/SideBar/Tools/Caption", "text": "Tools" }, "$:/language/SideBar/Types/Caption": { "title": "$:/language/SideBar/Types/Caption", "text": "Typen" }, "$:/SiteSubtitle": { "title": "$:/SiteSubtitle", "text": "ein persönliches nicht-lineares Web-Notizbuch\n" }, "$:/SiteTitle": { "title": "$:/SiteTitle", "text": "Mein ~TiddlyWiki" }, "$:/language/Snippets/ListByTag": { "title": "$:/language/Snippets/ListByTag", "tags": "$:/tags/TextEditor/Snippet", "caption": "Tiddler-Liste mit tag: \"task\", sortiert nach \"titel\"", "text": "<<list-links \"[tag[task]sort[title]]\">>\n" }, "$:/language/Snippets/MacroDefinition": { "title": "$:/language/Snippets/MacroDefinition", "tags": "$:/tags/TextEditor/Snippet", "caption": "Makro Definition", "text": "\\define makroName(param1:\"standard parameter\", param2)\nText des Makros. Zugriff auf den $param1$.\n$param2$\n\\end\n" }, "$:/language/Snippets/Table4x3": { "title": "$:/language/Snippets/Table4x3", "tags": "$:/tags/TextEditor/Snippet", "caption": "Tabelle mit 5 Spalten, 4 Zeilen, Kopf- und Fußzeile", "text": "| |Alpha |Beta |Gamma |Delta |h\n|!Beta | | | | |\n|!Gamma | | | | |\n|!Delta | | | | |\n| |a|b|c|d|f\n| Beschriftung |c\n" }, "$:/language/Snippets/TableOfContents": { "title": "$:/language/Snippets/TableOfContents", "tags": "$:/tags/TextEditor/Snippet", "caption": "Inhaltsverzeichnis", "text": "<div class=\"tc-table-of-contents\">\n\n<<toc-selective-expandable 'InhaltsVerzeichnis'>>\n\n</div>" }, "$:/language/ThemeTweaks/ThemeTweaks": { "title": "$:/language/ThemeTweaks/ThemeTweaks", "text": "Theme Tweaks" }, "$:/language/ThemeTweaks/ThemeTweaks/Hint": { "title": "$:/language/ThemeTweaks/ThemeTweaks/Hint", "text": "Hier können sie verschiedene Elemente des ''Vanilla'' (Standard) Themas einstellen." }, "$:/language/ThemeTweaks/Options": { "title": "$:/language/ThemeTweaks/Options", "text": "Optionen" }, "$:/language/ThemeTweaks/Options/SidebarLayout": { "title": "$:/language/ThemeTweaks/Options/SidebarLayout", "text": "Seitenleiste Darstellung" }, "$:/language/ThemeTweaks/Options/SidebarLayout/Fixed-Fluid": { "title": "$:/language/ThemeTweaks/Options/SidebarLayout/Fixed-Fluid", "text": "Fixe Story, variable Seitenleiste" }, "$:/language/ThemeTweaks/Options/SidebarLayout/Fluid-Fixed": { "title": "$:/language/ThemeTweaks/Options/SidebarLayout/Fluid-Fixed", "text": "Variable Story, fixe Seitenleiste" }, "$:/language/ThemeTweaks/Options/StickyTitles": { "title": "$:/language/ThemeTweaks/Options/StickyTitles", "text": "\"Klebender Titel\"" }, "$:/language/ThemeTweaks/Options/StickyTitles/Hint": { "title": "$:/language/ThemeTweaks/Options/StickyTitles/Hint", "text": "Tiddler-Titel bleiben beim \"Scrollen\" am oberen Bildschirmrand \"kleben\". Funktioniert möglicherweise nicht mit jedem Browser." }, "$:/language/ThemeTweaks/Options/CodeWrapping": { "title": "$:/language/ThemeTweaks/Options/CodeWrapping", "text": "Lange Zeilen in \"Code-Blöcken\" umbrechen" }, "$:/language/ThemeTweaks/Settings": { "title": "$:/language/ThemeTweaks/Settings", "text": "Einstellungen" }, "$:/language/ThemeTweaks/Settings/FontFamily": { "title": "$:/language/ThemeTweaks/Settings/FontFamily", "text": "Schriftfamilie" }, "$:/language/ThemeTweaks/Settings/CodeFontFamily": { "title": "$:/language/ThemeTweaks/Settings/CodeFontFamily", "text": "\"Code\" Schriftfamilie" }, "$:/language/ThemeTweaks/Settings/BackgroundImage": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImage", "text": "Hintergrundbild für die Seite" }, "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment", "text": "Hintergrundbild Anhang" }, "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Scroll": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Scroll", "text": "Mit Inhalt \"scrollen\"" }, "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Fixed": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageAttachment/Fixed", "text": "Fixe position im Fenster" }, "$:/language/ThemeTweaks/Settings/BackgroundImageSize": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize", "text": "Hintergrundbild Größe" }, "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Auto": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Auto", "text": "Auto" }, "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Cover": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Cover", "text": "Abdecken" }, "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Contain": { "title": "$:/language/ThemeTweaks/Settings/BackgroundImageSize/Contain", "text": "Anpassen" }, "$:/language/ThemeTweaks/Metrics": { "title": "$:/language/ThemeTweaks/Metrics", "text": "Größen" }, "$:/language/ThemeTweaks/Metrics/FontSize": { "title": "$:/language/ThemeTweaks/Metrics/FontSize", "text": "Schriftgröße" }, "$:/language/ThemeTweaks/Metrics/LineHeight": { "title": "$:/language/ThemeTweaks/Metrics/LineHeight", "text": "Zeilenhöhe" }, "$:/language/ThemeTweaks/Metrics/BodyFontSize": { "title": "$:/language/ThemeTweaks/Metrics/BodyFontSize", "text": "Schriftgröße für Tiddler Inhalt" }, "$:/language/ThemeTweaks/Metrics/BodyLineHeight": { "title": "$:/language/ThemeTweaks/Metrics/BodyLineHeight", "text": "Zeilenhöhe für Tiddler Inhalt" }, "$:/language/ThemeTweaks/Metrics/StoryLeft": { "title": "$:/language/ThemeTweaks/Metrics/StoryLeft", "text": "\"Story\" - linke Position" }, "$:/language/ThemeTweaks/Metrics/StoryLeft/Hint": { "title": "$:/language/ThemeTweaks/Metrics/StoryLeft/Hint", "text": "Abstand des \"story rivers\" vom linken Fensterrand" }, "$:/language/ThemeTweaks/Metrics/StoryTop": { "title": "$:/language/ThemeTweaks/Metrics/StoryTop", "text": "\"Story\" - obere Position" }, "$:/language/ThemeTweaks/Metrics/StoryTop/Hint": { "title": "$:/language/ThemeTweaks/Metrics/StoryTop/Hint", "text": "Abstand des \"story rivers\" vom oberen Fensterrand" }, "$:/language/ThemeTweaks/Metrics/StoryRight": { "title": "$:/language/ThemeTweaks/Metrics/StoryRight", "text": "\"Story\" - rechte Position" }, "$:/language/ThemeTweaks/Metrics/StoryRight/Hint": { "title": "$:/language/ThemeTweaks/Metrics/StoryRight/Hint", "text": "Abstand der Seitenleiste from linken Fensterrand" }, "$:/language/ThemeTweaks/Metrics/StoryWidth": { "title": "$:/language/ThemeTweaks/Metrics/StoryWidth", "text": "\"Story\" - Breite" }, "$:/language/ThemeTweaks/Metrics/StoryWidth/Hint": { "title": "$:/language/ThemeTweaks/Metrics/StoryWidth/Hint", "text": "Breite des \"story rivers\"" }, "$:/language/ThemeTweaks/Metrics/TiddlerWidth": { "title": "$:/language/ThemeTweaks/Metrics/TiddlerWidth", "text": "Tiddlerbreite" }, "$:/language/ThemeTweaks/Metrics/TiddlerWidth/Hint": { "title": "$:/language/ThemeTweaks/Metrics/TiddlerWidth/Hint", "text": "im \"story river\"" }, "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint": { "title": "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint", "text": "Seitenleiste \"breakpoint\"" }, "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint/Hint": { "title": "$:/language/ThemeTweaks/Metrics/SidebarBreakpoint/Hint", "text": "Minimum Fensterbreite, bei der die Seitenleiste an den Anfang der Seite verschoben wird." }, "$:/language/ThemeTweaks/Metrics/SidebarWidth": { "title": "$:/language/ThemeTweaks/Metrics/SidebarWidth", "text": "Seitenleiste Breite" }, "$:/language/ThemeTweaks/Metrics/SidebarWidth/Hint": { "title": "$:/language/ThemeTweaks/Metrics/SidebarWidth/Hint", "text": "Die Breite der Leiste bei variabler/fixer Darstellung" }, "$:/language/TiddlerInfo/Advanced/Caption": { "title": "$:/language/TiddlerInfo/Advanced/Caption", "text": "Erweitert" }, "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint": { "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint", "text": "keine" }, "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading": { "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading", "text": "Plugin Details" }, "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint": { "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint", "text": "Dieses Plugin enthält folgende Schatten-Tiddler:" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading", "text": "Shatten Status" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint", "text": "Der Tiddler: <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> ist kein Schatten-Tiddler." }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint", "text": "Der Tiddler: <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> ist ein Schatten-Tiddler." }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source", "text": "Er ist definiert im Plugin: <$link to=<<pluginTiddler>>><$text text=<<pluginTiddler>>/></$link>." }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint", "text": "Der originale Schatten-Tiddler wurde durch diesen Tiddler überschrieben. Wenn Sie diesen Tiddler löschen, wird der originale Schatten-Tiddler wieder aktiv. Vorher eventuell eine Sicherungskopie erstellen!" }, "$:/language/TiddlerInfo/Fields/Caption": { "title": "$:/language/TiddlerInfo/Fields/Caption", "text": "Felder" }, "$:/language/TiddlerInfo/List/Caption": { "title": "$:/language/TiddlerInfo/List/Caption", "text": "Liste" }, "$:/language/TiddlerInfo/List/Empty": { "title": "$:/language/TiddlerInfo/List/Empty", "text": "Dieser Tiddler hat kein \"list\" Feld." }, "$:/language/TiddlerInfo/Listed/Caption": { "title": "$:/language/TiddlerInfo/Listed/Caption", "text": "Gelistet" }, "$:/language/TiddlerInfo/Listed/Empty": { "title": "$:/language/TiddlerInfo/Listed/Empty", "text": "Dieser Tiddler wird nicht von anderen Tiddlern gelistet." }, "$:/language/TiddlerInfo/References/Caption": { "title": "$:/language/TiddlerInfo/References/Caption", "text": "Referenzen" }, "$:/language/TiddlerInfo/References/Empty": { "title": "$:/language/TiddlerInfo/References/Empty", "text": "Kein Tiddler linkt zu Diesem." }, "$:/language/TiddlerInfo/Tagging/Caption": { "title": "$:/language/TiddlerInfo/Tagging/Caption", "text": "Tagging" }, "$:/language/TiddlerInfo/Tagging/Empty": { "title": "$:/language/TiddlerInfo/Tagging/Empty", "text": "Kein Tiddler ist mit diesem \"getaggt\"." }, "$:/language/TiddlerInfo/Tools/Caption": { "title": "$:/language/TiddlerInfo/Tools/Caption", "text": "Tools" }, "$:/language/Docs/Types/application/javascript": { "title": "$:/language/Docs/Types/application/javascript", "description": "JS - JavaScript Code", "name": "application/javascript", "group": "Entwickler" }, "$:/language/Docs/Types/application/json": { "title": "$:/language/Docs/Types/application/json", "description": "JSON - Daten", "name": "application/json", "group": "Entwickler" }, "$:/language/Docs/Types/application/x-tiddler-dictionary": { "title": "$:/language/Docs/Types/application/x-tiddler-dictionary", "description": "TiddlyWiki Datenkatalog", "name": "application/x-tiddler-dictionary", "group": "Entwickler" }, "$:/language/Docs/Types/image/gif": { "title": "$:/language/Docs/Types/image/gif", "description": "GIF - Bild", "name": "image/gif", "group": "Bilder" }, "$:/language/Docs/Types/image/jpeg": { "title": "$:/language/Docs/Types/image/jpeg", "description": "JPEG - Bild", "name": "image/jpeg", "group": "Bilder" }, "$:/language/Docs/Types/image/png": { "title": "$:/language/Docs/Types/image/png", "description": "PNG - Portable Netzwerkgrafik", "name": "image/png", "group": "Bilder" }, "$:/language/Docs/Types/image/svg+xml": { "title": "$:/language/Docs/Types/image/svg+xml", "description": "SVG - Strukturierte Vektor Graphik", "name": "image/svg+xml", "group": "Bilder" }, "$:/language/Docs/Types/image/x-icon": { "title": "$:/language/Docs/Types/image/x-icon", "description": "ICO - Piktogramm Format", "name": "image/x-icon", "group": "Bilder" }, "$:/language/Docs/Types/text/css": { "title": "$:/language/Docs/Types/text/css", "description": "CSS - Cascading Style Sheets", "name": "text/css", "group": "Entwickler" }, "$:/language/Docs/Types/text/html": { "title": "$:/language/Docs/Types/text/html", "description": "HTML - Auszeichnungssprache", "name": "text/html", "group": "Text" }, "$:/language/Docs/Types/text/plain": { "title": "$:/language/Docs/Types/text/plain", "description": "TXT - Unformatierter Text", "name": "text/plain", "group": "Text" }, "$:/language/Docs/Types/text/vnd.tiddlywiki": { "title": "$:/language/Docs/Types/text/vnd.tiddlywiki", "description": "TW5 - TiddlyWiki Version 5 Wikitext", "name": "text/vnd.tiddlywiki", "group": "Text" }, "$:/language/Docs/Types/text/x-tiddlywiki": { "title": "$:/language/Docs/Types/text/x-tiddlywiki", "description": "TWc - TiddlyWiki Classic Wikitext", "name": "text/x-tiddlywiki", "group": "Text" }, "$:/languages/de-DE/icon": { "title": "$:/languages/de-DE/icon", "type": "image/svg+xml", "text": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n\t\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1000\" height=\"600\" viewBox=\"0 0 5 3\">\n\t<desc>Flag of Germany</desc>\n\t<rect id=\"black_stripe\" width=\"5\" height=\"3\" y=\"0\" x=\"0\" fill=\"#000\"/>\n\t<rect id=\"red_stripe\" width=\"5\" height=\"2\" y=\"1\" x=\"0\" fill=\"#D00\"/>\n\t<rect id=\"gold_stripe\" width=\"5\" height=\"1\" y=\"2\" x=\"0\" fill=\"#FFCE00\"/>\n</svg>\n" } } }
{ "tiddlers": { "$:/language/Buttons/+ExportPage/Hint": { "title": "$:/language/Buttons/+ExportPage/Hint", "text": "Экспортировать все заметки" }, "$:/language/Buttons/+ExportTiddler/Caption": { "title": "$:/language/Buttons/+ExportTiddler/Caption", "text": "экспортировать заметку" }, "$:/language/Buttons/+ExportTiddler/Hint": { "title": "$:/language/Buttons/+ExportTiddler/Hint", "text": "Экспортировать заметку" }, "$:/language/Buttons/+ExportTiddlers/Caption": { "title": "$:/language/Buttons/+ExportTiddlers/Caption", "text": "экспортировать заметки" }, "$:/language/Buttons/+ExportTiddlers/Hint": { "title": "$:/language/Buttons/+ExportTiddlers/Hint", "text": "Экспортировать заметки" }, "$:/language/Buttons/AdvancedSearch/Caption": { "title": "$:/language/Buttons/AdvancedSearch/Caption", "text": "расширенный поиск" }, "$:/language/Buttons/AdvancedSearch/Hint": { "title": "$:/language/Buttons/AdvancedSearch/Hint", "text": "Расширенный поиск" }, "$:/language/Buttons/Cancel/Caption": { "title": "$:/language/Buttons/Cancel/Caption", "text": "отмена" }, "$:/language/Buttons/Cancel/Hint": { "title": "$:/language/Buttons/Cancel/Hint", "text": "Отменить редактирование заметки" }, "$:/language/Buttons/Clone/Caption": { "title": "$:/language/Buttons/Clone/Caption", "text": "клонировать" }, "$:/language/Buttons/Clone/Hint": { "title": "$:/language/Buttons/Clone/Hint", "text": "Создать копию заметки" }, "$:/language/Buttons/Close/Caption": { "title": "$:/language/Buttons/Close/Caption", "text": "закрыть" }, "$:/language/Buttons/Close/Hint": { "title": "$:/language/Buttons/Close/Hint", "text": "Закрыть заметку" }, "$:/language/Buttons/CloseAll/Caption": { "title": "$:/language/Buttons/CloseAll/Caption", "text": "закрыть все" }, "$:/language/Buttons/CloseAll/Hint": { "title": "$:/language/Buttons/CloseAll/Hint", "text": "Закрыть все заметки" }, "$:/language/Buttons/CloseOthers/Caption": { "title": "$:/language/Buttons/CloseOthers/Caption", "text": "закрыть остальные" }, "$:/language/Buttons/CloseOthers/Hint": { "title": "$:/language/Buttons/CloseOthers/Hint", "text": "Закрыть остальные заметки" }, "$:/language/Buttons/ControlPanel/Caption": { "title": "$:/language/Buttons/ControlPanel/Caption", "text": "панель управления" }, "$:/language/Buttons/ControlPanel/Hint": { "title": "$:/language/Buttons/ControlPanel/Hint", "text": "Открыть панель управления" }, "$:/language/Buttons/Delete/Caption": { "title": "$:/language/Buttons/Delete/Caption", "text": "удалить" }, "$:/language/Buttons/Delete/Hint": { "title": "$:/language/Buttons/Delete/Hint", "text": "Удалить заметку" }, "$:/language/Buttons/Edit/Caption": { "title": "$:/language/Buttons/Edit/Caption", "text": "редактировать" }, "$:/language/Buttons/Edit/Hint": { "title": "$:/language/Buttons/Edit/Hint", "text": "Редактировать заметку" }, "$:/language/Buttons/Encryption/Caption": { "title": "$:/language/Buttons/Encryption/Caption", "text": "шифрование" }, "$:/language/Buttons/Encryption/ClearPassword/Caption": { "title": "$:/language/Buttons/Encryption/ClearPassword/Caption", "text": "сбросить пароль" }, "$:/language/Buttons/Encryption/ClearPassword/Hint": { "title": "$:/language/Buttons/Encryption/ClearPassword/Hint", "text": "Сбросить пароль и сохранить без использования шифрования" }, "$:/language/Buttons/Encryption/Hint": { "title": "$:/language/Buttons/Encryption/Hint", "text": "Установить или сбросить пароль" }, "$:/language/Buttons/Encryption/SetPassword/Caption": { "title": "$:/language/Buttons/Encryption/SetPassword/Caption", "text": "установить пароль" }, "$:/language/Buttons/Encryption/SetPassword/Hint": { "title": "$:/language/Buttons/Encryption/SetPassword/Hint", "text": "Установить пароль и включить шифрование" }, "$:/language/Buttons/ExportPage/Caption": { "title": "$:/language/Buttons/ExportPage/Caption", "text": "экспортировать всё" }, "$:/language/Buttons/ExportPage/Hint": { "title": "$:/language/Buttons/ExportPage/Hint", "text": "Экспортировать все тиддлеры" }, "$:/language/Buttons/ExportTiddler/Caption": { "title": "$:/language/Buttons/ExportTiddler/Caption", "text": "экспорт тиддлера" }, "$:/language/Buttons/ExportTiddler/Hint": { "title": "$:/language/Buttons/ExportTiddler/Hint", "text": "Экспорт тиддлера" }, "$:/language/Buttons/ExportTiddlers/Caption": { "title": "$:/language/Buttons/ExportTiddlers/Caption", "text": "экспорт тиддлеров" }, "$:/language/Buttons/ExportTiddlers/Hint": { "title": "$:/language/Buttons/ExportTiddlers/Hint", "text": "Экспорт тиддлеров" }, "$:/language/Buttons/FullScreen/Caption": { "title": "$:/language/Buttons/FullScreen/Caption", "text": "полный экран" }, "$:/language/Buttons/FullScreen/Hint": { "title": "$:/language/Buttons/FullScreen/Hint", "text": "Включить или выключить полноэкранный режим" }, "$:/language/Buttons/Help/Caption": { "title": "$:/language/Buttons/Help/Caption", "text": "помощь" }, "$:/language/Buttons/Help/Hint": { "title": "$:/language/Buttons/Help/Hint", "text": "Показать панель помощи" }, "$:/language/Buttons/HideSideBar/Caption": { "title": "$:/language/Buttons/HideSideBar/Caption", "text": "скрыть боковую панель" }, "$:/language/Buttons/HideSideBar/Hint": { "title": "$:/language/Buttons/HideSideBar/Hint", "text": "Скрыть боковую панель" }, "$:/language/Buttons/Home/Caption": { "title": "$:/language/Buttons/Home/Caption", "text": "главная" }, "$:/language/Buttons/Home/Hint": { "title": "$:/language/Buttons/Home/Hint", "text": "Открыть заметки по умолчанию" }, "$:/language/Buttons/Import/Caption": { "title": "$:/language/Buttons/Import/Caption", "text": "импортировать" }, "$:/language/Buttons/Import/Hint": { "title": "$:/language/Buttons/Import/Hint", "text": "Импорт файлов" }, "$:/language/Buttons/Info/Caption": { "title": "$:/language/Buttons/Info/Caption", "text": "информация" }, "$:/language/Buttons/Info/Hint": { "title": "$:/language/Buttons/Info/Hint", "text": "Показать информацию об этой заметке" }, "$:/language/Buttons/Language/Caption": { "title": "$:/language/Buttons/Language/Caption", "text": "язык" }, "$:/language/Buttons/Language/Hint": { "title": "$:/language/Buttons/Language/Hint", "text": "Выбрать язык пользовательского интерфейса" }, "$:/language/Buttons/More/Caption": { "title": "$:/language/Buttons/More/Caption", "text": "ещё" }, "$:/language/Buttons/More/Hint": { "title": "$:/language/Buttons/More/Hint", "text": "Другие действия" }, "$:/language/Buttons/NewHere/Caption": { "title": "$:/language/Buttons/NewHere/Caption", "text": "новая заметка здесь" }, "$:/language/Buttons/NewHere/Hint": { "title": "$:/language/Buttons/NewHere/Hint", "text": "Создать новую заметку, помеченную этой заметкой" }, "$:/language/Buttons/NewJournal/Caption": { "title": "$:/language/Buttons/NewJournal/Caption", "text": "дневник" }, "$:/language/Buttons/NewJournal/Hint": { "title": "$:/language/Buttons/NewJournal/Hint", "text": "Создать новую заметку в дневник" }, "$:/language/Buttons/NewJournalHere/Caption": { "title": "$:/language/Buttons/NewJournalHere/Caption", "text": "дневник здесь" }, "$:/language/Buttons/NewJournalHere/Hint": { "title": "$:/language/Buttons/NewJournalHere/Hint", "text": "Создать новую заметку в дневник, помеченную этой заметкой" }, "$:/language/Buttons/NewTiddler/Caption": { "title": "$:/language/Buttons/NewTiddler/Caption", "text": "новая заметка" }, "$:/language/Buttons/NewTiddler/Hint": { "title": "$:/language/Buttons/NewTiddler/Hint", "text": "Создать новую заметку" }, "$:/language/Buttons/OpenWindow/Caption": { "title": "$:/language/Buttons/OpenWindow/Caption", "text": "открыть в новом окне" }, "$:/language/Buttons/OpenWindow/Hint": { "title": "$:/language/Buttons/OpenWindow/Hint", "text": "Открыть тиддлер в новом окне" }, "$:/language/Buttons/Palette/Caption": { "title": "$:/language/Buttons/Palette/Caption", "text": "цветовая схема" }, "$:/language/Buttons/Palette/Hint": { "title": "$:/language/Buttons/Palette/Hint", "text": "Выбрать цветовую схему" }, "$:/language/Buttons/Permalink/Caption": { "title": "$:/language/Buttons/Permalink/Caption", "text": "прямая ссылка" }, "$:/language/Buttons/Permalink/Hint": { "title": "$:/language/Buttons/Permalink/Hint", "text": "Показать прямую ссылку на заметку в адресной строке браузера" }, "$:/language/Buttons/Permaview/Caption": { "title": "$:/language/Buttons/Permaview/Caption", "text": "прямая ссылка" }, "$:/language/Buttons/Permaview/Hint": { "title": "$:/language/Buttons/Permaview/Hint", "text": "Показать прямую ссылку на открытые заметки в адресной строке браузера" }, "$:/language/Buttons/Refresh/Caption": { "title": "$:/language/Buttons/Refresh/Caption", "text": "oбновить" }, "$:/language/Buttons/Refresh/Hint": { "title": "$:/language/Buttons/Refresh/Hint", "text": "Выполнить обновление страницы" }, "$:/language/Buttons/Save/Caption": { "title": "$:/language/Buttons/Save/Caption", "text": "сохранить" }, "$:/language/Buttons/Save/Hint": { "title": "$:/language/Buttons/Save/Hint", "text": "Сохранить заметку" }, "$:/language/Buttons/SaveWiki/Caption": { "title": "$:/language/Buttons/SaveWiki/Caption", "text": "сохранить изменения" }, "$:/language/Buttons/SaveWiki/Hint": { "title": "$:/language/Buttons/SaveWiki/Hint", "text": "Сохранить изменения" }, "$:/language/Buttons/ShowSideBar/Caption": { "title": "$:/language/Buttons/ShowSideBar/Caption", "text": "показать боковую панель" }, "$:/language/Buttons/ShowSideBar/Hint": { "title": "$:/language/Buttons/ShowSideBar/Hint", "text": "Показать боковую панель" }, "$:/language/Buttons/StoryView/Caption": { "title": "$:/language/Buttons/StoryView/Caption", "text": "отображение заметок" }, "$:/language/Buttons/StoryView/Hint": { "title": "$:/language/Buttons/StoryView/Hint", "text": "Выбрать способ отображения заметок" }, "$:/language/Buttons/TagManager/Caption": { "title": "$:/language/Buttons/TagManager/Caption", "text": "управление метками" }, "$:/language/Buttons/TagManager/Hint": { "title": "$:/language/Buttons/TagManager/Hint", "text": "Открыть панель управления метками" }, "$:/language/Buttons/Theme/Caption": { "title": "$:/language/Buttons/Theme/Caption", "text": "тема" }, "$:/language/Buttons/Theme/Hint": { "title": "$:/language/Buttons/Theme/Hint", "text": "Выбрать тему" }, "$:/language/ControlPanel/Advanced/Caption": { "title": "$:/language/ControlPanel/Advanced/Caption", "text": "Расширенные" }, "$:/language/ControlPanel/Advanced/Hint": { "title": "$:/language/ControlPanel/Advanced/Hint", "text": "Системные сведения об этой TiddlyWiki" }, "$:/language/ControlPanel/Appearance/Caption": { "title": "$:/language/ControlPanel/Appearance/Caption", "text": "Внешний вид" }, "$:/language/ControlPanel/Appearance/Hint": { "title": "$:/language/ControlPanel/Appearance/Hint", "text": "Способы настройки внешнего вида TiddlyWiki." }, "$:/language/ControlPanel/Basics/AnimDuration/Prompt": { "title": "$:/language/ControlPanel/Basics/AnimDuration/Prompt", "text": "Продолжительность анимации:" }, "$:/language/ControlPanel/Basics/Caption": { "title": "$:/language/ControlPanel/Basics/Caption", "text": "Основные" }, "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint": { "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/BottomHint", "text": "Заметки, содержащие пробелы нужно взять в [[двойные квадратные скобки]]. А также можно возвращать <$button set=\"$:/DefaultTiddlers\" setTo=\"[list[$:/StoryList]]\">открытые ранее заметки</$button>" }, "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/Prompt", "text": "Открывать при старте:" }, "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint": { "title": "$:/language/ControlPanel/Basics/DefaultTiddlers/TopHint", "text": "Выберите заметки открытые при запуске:" }, "$:/language/ControlPanel/Basics/Language/Prompt": { "title": "$:/language/ControlPanel/Basics/Language/Prompt", "text": "Привет! Текущий язык:" }, "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt": { "title": "$:/language/ControlPanel/Basics/NewJournal/Tags/Prompt", "text": "Метки новых заметок дневника" }, "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt": { "title": "$:/language/ControlPanel/Basics/NewJournal/Title/Prompt", "text": "Заголовок новых заметок дневника" }, "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/OverriddenShadowTiddlers/Prompt", "text": "Количество переопределённых встроенных заметок:" }, "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/ShadowTiddlers/Prompt", "text": "Количество встроенных заметок:" }, "$:/language/ControlPanel/Basics/Subtitle/Prompt": { "title": "$:/language/ControlPanel/Basics/Subtitle/Prompt", "text": "Подзаголовок:" }, "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/SystemTiddlers/Prompt", "text": "Количество системных заметок:" }, "$:/language/ControlPanel/Basics/Tags/Prompt": { "title": "$:/language/ControlPanel/Basics/Tags/Prompt", "text": "Количество меток:" }, "$:/language/ControlPanel/Basics/Tiddlers/Prompt": { "title": "$:/language/ControlPanel/Basics/Tiddlers/Prompt", "text": "Количество заметок:" }, "$:/language/ControlPanel/Basics/Title/Prompt": { "title": "$:/language/ControlPanel/Basics/Title/Prompt", "text": "Заголовок этой ~TiddlyWiki:" }, "$:/language/ControlPanel/Basics/Username/Prompt": { "title": "$:/language/ControlPanel/Basics/Username/Prompt", "text": "Имя пользователя для подписи под изменениями:" }, "$:/language/ControlPanel/Basics/Version/Prompt": { "title": "$:/language/ControlPanel/Basics/Version/Prompt", "text": "Версия ~TiddlyWiki:" }, "$:/language/ControlPanel/EditorTypes/Caption": { "title": "$:/language/ControlPanel/EditorTypes/Caption", "text": "Редакторы" }, "$:/language/ControlPanel/EditorTypes/Editor/Caption": { "title": "$:/language/ControlPanel/EditorTypes/Editor/Caption", "text": "Редактор" }, "$:/language/ControlPanel/EditorTypes/Hint": { "title": "$:/language/ControlPanel/EditorTypes/Hint", "text": "Эти заметки определяют, какой редактор используется для конкретного типа заметки." }, "$:/language/ControlPanel/EditorTypes/Type/Caption": { "title": "$:/language/ControlPanel/EditorTypes/Type/Caption", "text": "Тип содержимого" }, "$:/language/ControlPanel/Info/Caption": { "title": "$:/language/ControlPanel/Info/Caption", "text": "Сведения" }, "$:/language/ControlPanel/Info/Hint": { "title": "$:/language/ControlPanel/Info/Hint", "text": "Сведения об этой TiddlyWiki" }, "$:/language/ControlPanel/LoadedModules/Caption": { "title": "$:/language/ControlPanel/LoadedModules/Caption", "text": "Загруженные модули" }, "$:/language/ControlPanel/LoadedModules/Hint": { "title": "$:/language/ControlPanel/LoadedModules/Hint", "text": "Это загруженные в настоящий момент модули, ссылающиеся на их исходные заметки. Модули, обозначенные курсивом, не имеют исходных заметок (обычно, потому что они были установлены во время процесса загрузки)." }, "$:/language/ControlPanel/Palette/Caption": { "title": "$:/language/ControlPanel/Palette/Caption", "text": "Цветовая схема" }, "$:/language/ControlPanel/Palette/Editor/Clone/Caption": { "title": "$:/language/ControlPanel/Palette/Editor/Clone/Caption", "text": "скопировать" }, "$:/language/ControlPanel/Palette/Editor/Clone/Prompt": { "title": "$:/language/ControlPanel/Palette/Editor/Clone/Prompt", "text": "Перед редактированием рекомендуется скопировать встроенную цветовую схему" }, "$:/language/ControlPanel/Palette/Editor/Prompt": { "title": "$:/language/ControlPanel/Palette/Editor/Prompt", "text": "Редактирование" }, "$:/language/ControlPanel/Palette/Editor/Prompt/Modified": { "title": "$:/language/ControlPanel/Palette/Editor/Prompt/Modified", "text": "Эта встроенная цветовая схема изменена" }, "$:/language/ControlPanel/Palette/Editor/Reset/Caption": { "title": "$:/language/ControlPanel/Palette/Editor/Reset/Caption", "text": "сброс" }, "$:/language/ControlPanel/Palette/HideEditor/Caption": { "title": "$:/language/ControlPanel/Palette/HideEditor/Caption", "text": "скрыть редактор" }, "$:/language/ControlPanel/Palette/Prompt": { "title": "$:/language/ControlPanel/Palette/Prompt", "text": "Текущая цветовая схема:" }, "$:/language/ControlPanel/Palette/ShowEditor/Caption": { "title": "$:/language/ControlPanel/Palette/ShowEditor/Caption", "text": "показать редактор" }, "$:/language/ControlPanel/Plugins/Add/Caption": { "title": "$:/language/ControlPanel/Plugins/Add/Caption", "text": "Другие плагины" }, "$:/language/ControlPanel/Plugins/Add/Hint": { "title": "$:/language/ControlPanel/Plugins/Add/Hint", "text": "Установить официальные плагины" }, "$:/language/ControlPanel/Plugins/Caption": { "title": "$:/language/ControlPanel/Plugins/Caption", "text": "Плагины" }, "$:/language/ControlPanel/Plugins/Disable/Caption": { "title": "$:/language/ControlPanel/Plugins/Disable/Caption", "text": "выключить" }, "$:/language/ControlPanel/Plugins/Disable/Hint": { "title": "$:/language/ControlPanel/Plugins/Disable/Hint", "text": "Выключить этот плагин" }, "$:/language/ControlPanel/Plugins/Disabled/Status": { "title": "$:/language/ControlPanel/Plugins/Disabled/Status", "text": "(выключен)" }, "$:/language/ControlPanel/Plugins/Empty/Hint": { "title": "$:/language/ControlPanel/Plugins/Empty/Hint", "text": "Нет" }, "$:/language/ControlPanel/Plugins/Enable/Caption": { "title": "$:/language/ControlPanel/Plugins/Enable/Caption", "text": "включить" }, "$:/language/ControlPanel/Plugins/Enable/Hint": { "title": "$:/language/ControlPanel/Plugins/Enable/Hint", "text": "Выключить этот плагин" }, "$:/language/ControlPanel/Plugins/Installed/Hint": { "title": "$:/language/ControlPanel/Plugins/Installed/Hint", "text": "Список установленных плагинов:" }, "$:/language/ControlPanel/Plugins/Language/Prompt": { "title": "$:/language/ControlPanel/Plugins/Language/Prompt", "text": "Языки" }, "$:/language/ControlPanel/Plugins/Languages/Caption": { "title": "$:/language/ControlPanel/Plugins/Languages/Caption", "text": "Языки" }, "$:/language/ControlPanel/Plugins/Languages/Hint": { "title": "$:/language/ControlPanel/Plugins/Languages/Hint", "text": "Плагины языковых пакетов" }, "$:/language/ControlPanel/Plugins/Plugin/Prompt": { "title": "$:/language/ControlPanel/Plugins/Plugin/Prompt", "text": "Плагины" }, "$:/language/ControlPanel/Plugins/Plugins/Caption": { "title": "$:/language/ControlPanel/Plugins/Plugins/Caption", "text": "Плагины" }, "$:/language/ControlPanel/Plugins/Plugins/Hint": { "title": "$:/language/ControlPanel/Plugins/Plugins/Hint", "text": "Плагины" }, "$:/language/ControlPanel/Plugins/Theme/Prompt": { "title": "$:/language/ControlPanel/Plugins/Theme/Prompt", "text": "Темы" }, "$:/language/ControlPanel/Plugins/Themes/Caption": { "title": "$:/language/ControlPanel/Plugins/Themes/Caption", "text": "Темы" }, "$:/language/ControlPanel/Plugins/Themes/Hint": { "title": "$:/language/ControlPanel/Plugins/Themes/Hint", "text": "Плагины тем" }, "$:/language/ControlPanel/Saving/Caption": { "title": "$:/language/ControlPanel/Saving/Caption", "text": "Сохранение" }, "$:/language/ControlPanel/Saving/Heading": { "title": "$:/language/ControlPanel/Saving/Heading", "text": "Сохранение" }, "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Advanced/Heading", "text": "Расширенные настройки" }, "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/BackupDir", "text": "Каталог для резервной копии" }, "$:/language/ControlPanel/Saving/TiddlySpot/Backups": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Backups", "text": "Резервная копия" }, "$:/language/ControlPanel/Saving/TiddlySpot/Description": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Description", "text": "Эти настройки нужны для сохранения на http://tiddlyspot.com или совместимый с ним удаленный сервер" }, "$:/language/ControlPanel/Saving/TiddlySpot/Filename": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Filename", "text": "Имя файла для загрузки" }, "$:/language/ControlPanel/Saving/TiddlySpot/Heading": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Heading", "text": "~TiddlySpot" }, "$:/language/ControlPanel/Saving/TiddlySpot/Hint": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Hint", "text": "//URL сервера по умолчанию - `http://<wikiname>.tiddlyspot.com/store.cgi`. Его можно указать если используется другой сервер//" }, "$:/language/ControlPanel/Saving/TiddlySpot/Password": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/Password", "text": "Пароль" }, "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/ServerURL", "text": "URL сервера" }, "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/UploadDir", "text": "Каталог загрузки" }, "$:/language/ControlPanel/Saving/TiddlySpot/UserName": { "title": "$:/language/ControlPanel/Saving/TiddlySpot/UserName", "text": "Название Wiki" }, "$:/language/ControlPanel/Settings/AutoSave/Caption": { "title": "$:/language/ControlPanel/Settings/AutoSave/Caption", "text": "Автосохранение" }, "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description": { "title": "$:/language/ControlPanel/Settings/AutoSave/Disabled/Description", "text": "Не сохранять изменения автоматически" }, "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description": { "title": "$:/language/ControlPanel/Settings/AutoSave/Enabled/Description", "text": "Сохранять изменения автоматически" }, "$:/language/ControlPanel/Settings/AutoSave/Hint": { "title": "$:/language/ControlPanel/Settings/AutoSave/Hint", "text": "Сохранять изменения автоматически в процессе редактирования" }, "$:/language/ControlPanel/Settings/Caption": { "title": "$:/language/ControlPanel/Settings/Caption", "text": "Настройки" }, "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption": { "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Caption", "text": "Стандартная боковая панель" }, "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint": { "title": "$:/language/ControlPanel/Settings/DefaultSidebarTab/Hint", "text": "Определяет какую боковую панель показывать по умолчанию" }, "$:/language/ControlPanel/Settings/Hint": { "title": "$:/language/ControlPanel/Settings/Hint", "text": "Эти настройки позволяют изменить поведение TiddlyWiki." }, "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/Caption", "text": "Открытие Тиддлера" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/InsideRiver/Hint", "text": "По ссылке //из// открытых тиддлеров" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAbove", "text": "Открывать выше открытого тиддлера" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtBottom", "text": "Открывать ниже всех открытых тиддлеров" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenAtTop", "text": "Открывать выше всех открытых тиддлеров" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OpenBelow", "text": "Открывать ниже открытого тиддлера" }, "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint": { "title": "$:/language/ControlPanel/Settings/LinkToBehaviour/OutsideRiver/Hint", "text": "По ссылке //вне// открытых тиддлеров" }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Caption", "text": "Адресная строка браузера" }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Hint", "text": "Поведение адресной строки браузера при открытии заметки:" }, "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/No/Description", "text": "Не изменять адресную строку" }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permalink/Description", "text": "Включить целевую заметку" }, "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description": { "title": "$:/language/ControlPanel/Settings/NavigationAddressBar/Permaview/Description", "text": "Включить целевую заметку и все открытые заметки" }, "$:/language/ControlPanel/Settings/NavigationHistory/Caption": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/Caption", "text": "История браузера" }, "$:/language/ControlPanel/Settings/NavigationHistory/Hint": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/Hint", "text": "Обновлять историю браузера при открытии заметки:" }, "$:/language/ControlPanel/Settings/NavigationHistory/No/Description": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/No/Description", "text": "Не обновлять историю" }, "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description": { "title": "$:/language/ControlPanel/Settings/NavigationHistory/Yes/Description", "text": "Обновлять историю" }, "$:/language/ControlPanel/Settings/TitleLinks/Caption": { "title": "$:/language/ControlPanel/Settings/TitleLinks/Caption", "text": "Заголовки Тиддлеров" }, "$:/language/ControlPanel/Settings/TitleLinks/Hint": { "title": "$:/language/ControlPanel/Settings/TitleLinks/Hint", "text": "Выборочно показывает заголовки тиддеров как ссылки" }, "$:/language/ControlPanel/Settings/TitleLinks/No/Description": { "title": "$:/language/ControlPanel/Settings/TitleLinks/No/Description", "text": "Не показывать заголовки тиддлеров как ссылки" }, "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description": { "title": "$:/language/ControlPanel/Settings/TitleLinks/Yes/Description", "text": "Показывать заголовки тиддлеров как ссылки" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Caption": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Caption", "text": "Кнопки" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Hint": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Hint", "text": "Внешний вид кнопок:" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Icons/Description", "text": "Показывать значок" }, "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description": { "title": "$:/language/ControlPanel/Settings/ToolbarButtons/Text/Description", "text": "Показывать текст" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption", "text": "Стиль кнопок панелей" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Hint", "text": "Выберите стиль кнопок панелей:" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Borderless", "text": "Без границ" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Boxed", "text": "Внутри квадрата" }, "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded": { "title": "$:/language/ControlPanel/Settings/ToolbarButtonStyle/Styles/Rounded", "text": "Внутри круга" }, "$:/language/ControlPanel/StoryView/Caption": { "title": "$:/language/ControlPanel/StoryView/Caption", "text": "Поведение открытых заметок" }, "$:/language/ControlPanel/StoryView/Prompt": { "title": "$:/language/ControlPanel/StoryView/Prompt", "text": "Текущий вид:" }, "$:/language/ControlPanel/Theme/Caption": { "title": "$:/language/ControlPanel/Theme/Caption", "text": "Тема" }, "$:/language/ControlPanel/Theme/Prompt": { "title": "$:/language/ControlPanel/Theme/Prompt", "text": "Текущая тема:" }, "$:/language/ControlPanel/TiddlerFields/Caption": { "title": "$:/language/ControlPanel/TiddlerFields/Caption", "text": "Поля заметок" }, "$:/language/ControlPanel/TiddlerFields/Hint": { "title": "$:/language/ControlPanel/TiddlerFields/Hint", "text": "Это полный набор полей заметок (включая системные заметки, но без встроенных)." }, "$:/language/ControlPanel/Toolbars/Caption": { "title": "$:/language/ControlPanel/Toolbars/Caption", "text": "Панели инструментов" }, "$:/language/ControlPanel/Toolbars/EditToolbar/Caption": { "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Caption", "text": "При редактировании" }, "$:/language/ControlPanel/Toolbars/EditToolbar/Hint": { "title": "$:/language/ControlPanel/Toolbars/EditToolbar/Hint", "text": "Выберите кнопки, отображаемые во время редактирования заметок" }, "$:/language/ControlPanel/Toolbars/Hint": { "title": "$:/language/ControlPanel/Toolbars/Hint", "text": "Выберите отображаемые кнопки" }, "$:/language/ControlPanel/Toolbars/PageControls/Caption": { "title": "$:/language/ControlPanel/Toolbars/PageControls/Caption", "text": "Боковой панели" }, "$:/language/ControlPanel/Toolbars/PageControls/Hint": { "title": "$:/language/ControlPanel/Toolbars/PageControls/Hint", "text": "Выберите кнопки, отображаемые на боковой панели" }, "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption": { "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Caption", "text": "При просмотре" }, "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint": { "title": "$:/language/ControlPanel/Toolbars/ViewToolbar/Hint", "text": "Выберите кнопки, отображаемые во время просмотра заметок" }, "$:/language/ControlPanel/Tools/Download/Full/Caption": { "title": "$:/language/ControlPanel/Tools/Download/Full/Caption", "text": "Скачать wiki целиком" }, "$:/core/readme": { "title": "$:/core/readme", "text": "Этот плагин содержит компоненты ядра TiddlyWiki, содержащие:\n\n* коды модуля JavaScript\n* Изображения\n* Шаблоны, необходимые для создания пользовательского интерфейса TiddlyWiki\n* British English (en-GB) переводы локализуемых строк используемых в ядре" }, "$:/language/Date/Long/Day/0": { "title": "$:/language/Date/Long/Day/0", "text": "Воскресенье" }, "$:/language/Date/Long/Day/1": { "title": "$:/language/Date/Long/Day/1", "text": "Понедельник" }, "$:/language/Date/Long/Day/2": { "title": "$:/language/Date/Long/Day/2", "text": "Вторник" }, "$:/language/Date/Long/Day/3": { "title": "$:/language/Date/Long/Day/3", "text": "Среда" }, "$:/language/Date/Long/Day/4": { "title": "$:/language/Date/Long/Day/4", "text": "Четверг" }, "$:/language/Date/Long/Day/5": { "title": "$:/language/Date/Long/Day/5", "text": "Пятница" }, "$:/language/Date/Long/Day/6": { "title": "$:/language/Date/Long/Day/6", "text": "Суббота" }, "$:/language/Date/Long/Month/1": { "title": "$:/language/Date/Long/Month/1", "text": "января" }, "$:/language/Date/Long/Month/2": { "title": "$:/language/Date/Long/Month/2", "text": "февраля" }, "$:/language/Date/Long/Month/3": { "title": "$:/language/Date/Long/Month/3", "text": "марта" }, "$:/language/Date/Long/Month/4": { "title": "$:/language/Date/Long/Month/4", "text": "апреля" }, "$:/language/Date/Long/Month/5": { "title": "$:/language/Date/Long/Month/5", "text": "мая" }, "$:/language/Date/Long/Month/6": { "title": "$:/language/Date/Long/Month/6", "text": "июня" }, "$:/language/Date/Long/Month/7": { "title": "$:/language/Date/Long/Month/7", "text": "июля" }, "$:/language/Date/Long/Month/8": { "title": "$:/language/Date/Long/Month/8", "text": "августа" }, "$:/language/Date/Long/Month/9": { "title": "$:/language/Date/Long/Month/9", "text": "сентября" }, "$:/language/Date/Long/Month/10": { "title": "$:/language/Date/Long/Month/10", "text": "октября" }, "$:/language/Date/Long/Month/11": { "title": "$:/language/Date/Long/Month/11", "text": "ноября" }, "$:/language/Date/Long/Month/12": { "title": "$:/language/Date/Long/Month/12", "text": "декабря" }, "$:/language/Date/Period/am": { "title": "$:/language/Date/Period/am", "text": "до полудня" }, "$:/language/Date/Period/pm": { "title": "$:/language/Date/Period/pm", "text": "после полудня" }, "$:/language/Date/Short/Day/0": { "title": "$:/language/Date/Short/Day/0", "text": "Вс" }, "$:/language/Date/Short/Day/1": { "title": "$:/language/Date/Short/Day/1", "text": "Пн" }, "$:/language/Date/Short/Day/2": { "title": "$:/language/Date/Short/Day/2", "text": "Вт" }, "$:/language/Date/Short/Day/3": { "title": "$:/language/Date/Short/Day/3", "text": "Ср" }, "$:/language/Date/Short/Day/4": { "title": "$:/language/Date/Short/Day/4", "text": "Чт" }, "$:/language/Date/Short/Day/5": { "title": "$:/language/Date/Short/Day/5", "text": "Пт" }, "$:/language/Date/Short/Day/6": { "title": "$:/language/Date/Short/Day/6", "text": "Сб" }, "$:/language/Date/Short/Month/1": { "title": "$:/language/Date/Short/Month/1", "text": "янв" }, "$:/language/Date/Short/Month/2": { "title": "$:/language/Date/Short/Month/2", "text": "фев" }, "$:/language/Date/Short/Month/3": { "title": "$:/language/Date/Short/Month/3", "text": "мрт" }, "$:/language/Date/Short/Month/4": { "title": "$:/language/Date/Short/Month/4", "text": "апр" }, "$:/language/Date/Short/Month/5": { "title": "$:/language/Date/Short/Month/5", "text": "май" }, "$:/language/Date/Short/Month/6": { "title": "$:/language/Date/Short/Month/6", "text": "июн" }, "$:/language/Date/Short/Month/7": { "title": "$:/language/Date/Short/Month/7", "text": "июл" }, "$:/language/Date/Short/Month/8": { "title": "$:/language/Date/Short/Month/8", "text": "авг" }, "$:/language/Date/Short/Month/9": { "title": "$:/language/Date/Short/Month/9", "text": "сен" }, "$:/language/Date/Short/Month/10": { "title": "$:/language/Date/Short/Month/10", "text": "окт" }, "$:/language/Date/Short/Month/11": { "title": "$:/language/Date/Short/Month/11", "text": "нбр" }, "$:/language/Date/Short/Month/12": { "title": "$:/language/Date/Short/Month/12", "text": "дек" }, "$:/language/Date/DaySuffix/1": { "title": "$:/language/Date/DaySuffix/1", "text": "-й" }, "$:/language/Date/DaySuffix/10": { "title": "$:/language/Date/DaySuffix/10", "text": "-й" }, "$:/language/Date/DaySuffix/11": { "title": "$:/language/Date/DaySuffix/11", "text": "-й" }, "$:/language/Date/DaySuffix/12": { "title": "$:/language/Date/DaySuffix/12", "text": "-й" }, "$:/language/Date/DaySuffix/13": { "title": "$:/language/Date/DaySuffix/13", "text": "-й" }, "$:/language/Date/DaySuffix/14": { "title": "$:/language/Date/DaySuffix/14", "text": "-й" }, "$:/language/Date/DaySuffix/15": { "title": "$:/language/Date/DaySuffix/15", "text": "-й" }, "$:/language/Date/DaySuffix/16": { "title": "$:/language/Date/DaySuffix/16", "text": "-й" }, "$:/language/Date/DaySuffix/17": { "title": "$:/language/Date/DaySuffix/17", "text": "-й" }, "$:/language/Date/DaySuffix/18": { "title": "$:/language/Date/DaySuffix/18", "text": "-й" }, "$:/language/Date/DaySuffix/19": { "title": "$:/language/Date/DaySuffix/19", "text": "-й" }, "$:/language/Date/DaySuffix/2": { "title": "$:/language/Date/DaySuffix/2", "text": "-й" }, "$:/language/Date/DaySuffix/20": { "title": "$:/language/Date/DaySuffix/20", "text": "-й" }, "$:/language/Date/DaySuffix/21": { "title": "$:/language/Date/DaySuffix/21", "text": "-й" }, "$:/language/Date/DaySuffix/22": { "title": "$:/language/Date/DaySuffix/22", "text": "-й" }, "$:/language/Date/DaySuffix/23": { "title": "$:/language/Date/DaySuffix/23", "text": "-й" }, "$:/language/Date/DaySuffix/24": { "title": "$:/language/Date/DaySuffix/24", "text": "-й" }, "$:/language/Date/DaySuffix/25": { "title": "$:/language/Date/DaySuffix/25", "text": "-й" }, "$:/language/Date/DaySuffix/26": { "title": "$:/language/Date/DaySuffix/26", "text": "-й" }, "$:/language/Date/DaySuffix/27": { "title": "$:/language/Date/DaySuffix/27", "text": "-й" }, "$:/language/Date/DaySuffix/28": { "title": "$:/language/Date/DaySuffix/28", "text": "-й" }, "$:/language/Date/DaySuffix/29": { "title": "$:/language/Date/DaySuffix/29", "text": "-й" }, "$:/language/Date/DaySuffix/3": { "title": "$:/language/Date/DaySuffix/3", "text": "-й" }, "$:/language/Date/DaySuffix/30": { "title": "$:/language/Date/DaySuffix/30", "text": "-й" }, "$:/language/Date/DaySuffix/31": { "title": "$:/language/Date/DaySuffix/31", "text": "-й" }, "$:/language/Date/DaySuffix/4": { "title": "$:/language/Date/DaySuffix/4", "text": "-й" }, "$:/language/Date/DaySuffix/5": { "title": "$:/language/Date/DaySuffix/5", "text": "-й" }, "$:/language/Date/DaySuffix/6": { "title": "$:/language/Date/DaySuffix/6", "text": "-й" }, "$:/language/Date/DaySuffix/7": { "title": "$:/language/Date/DaySuffix/7", "text": "-й" }, "$:/language/Date/DaySuffix/8": { "title": "$:/language/Date/DaySuffix/8", "text": "-й" }, "$:/language/Date/DaySuffix/9": { "title": "$:/language/Date/DaySuffix/9", "text": "-й" }, "$:/language/RelativeDate/Future/Days": { "title": "$:/language/RelativeDate/Future/Days", "text": "через <<period>> дней" }, "$:/language/RelativeDate/Future/Hours": { "title": "$:/language/RelativeDate/Future/Hours", "text": "через <<period>> часов" }, "$:/language/RelativeDate/Future/Minutes": { "title": "$:/language/RelativeDate/Future/Minutes", "text": "через <<period>> минут" }, "$:/language/RelativeDate/Future/Months": { "title": "$:/language/RelativeDate/Future/Months", "text": "через <<period>> месяцев" }, "$:/language/RelativeDate/Future/Second": { "title": "$:/language/RelativeDate/Future/Second", "text": "через 1 секунду" }, "$:/language/RelativeDate/Future/Seconds": { "title": "$:/language/RelativeDate/Future/Seconds", "text": "через <<period>> секунд" }, "$:/language/RelativeDate/Future/Years": { "title": "$:/language/RelativeDate/Future/Years", "text": "через <<period>> лет" }, "$:/language/RelativeDate/Past/Days": { "title": "$:/language/RelativeDate/Past/Days", "text": "<<period>> дней назад" }, "$:/language/RelativeDate/Past/Hours": { "title": "$:/language/RelativeDate/Past/Hours", "text": "<<period>> часов назад" }, "$:/language/RelativeDate/Past/Minutes": { "title": "$:/language/RelativeDate/Past/Minutes", "text": "<<period>> минут назад" }, "$:/language/RelativeDate/Past/Months": { "title": "$:/language/RelativeDate/Past/Months", "text": "<<period>> месяцев назад" }, "$:/language/RelativeDate/Past/Second": { "title": "$:/language/RelativeDate/Past/Second", "text": "1 секунду назад" }, "$:/language/RelativeDate/Past/Seconds": { "title": "$:/language/RelativeDate/Past/Seconds", "text": "<<period>> секунд назад" }, "$:/language/RelativeDate/Past/Years": { "title": "$:/language/RelativeDate/Past/Years", "text": "<<period>> лет назад" }, "$:/language/Docs/Fields/_canonical_uri": { "title": "$:/language/Docs/Fields/_canonical_uri", "text": "Полный URI заметки, содержащей внешнюю картинку" }, "$:/language/Docs/Fields/bag": { "title": "$:/language/Docs/Fields/bag", "text": "Название \"мешка\" заметки из TiddlyWeb" }, "$:/language/Docs/Fields/caption": { "title": "$:/language/Docs/Fields/caption", "text": "Текст на вкладке или кнопке" }, "$:/language/Docs/Fields/color": { "title": "$:/language/Docs/Fields/color", "text": "CSS значение цвета заметки" }, "$:/language/Docs/Fields/component": { "title": "$:/language/Docs/Fields/component", "text": "Название компонента, ответственного за [[заметку-тревогу|AlertMechanism]]" }, "$:/language/Docs/Fields/created": { "title": "$:/language/Docs/Fields/created", "text": "Дата создания заметки" }, "$:/language/Docs/Fields/creator": { "title": "$:/language/Docs/Fields/creator", "text": "Имя создателя заметки" }, "$:/language/Docs/Fields/current-tiddler": { "title": "$:/language/Docs/Fields/current-tiddler", "text": "Использовалось для хранения верхней заметки в [[списке истории|HistoryMechanism]]" }, "$:/language/Docs/Fields/dependents": { "title": "$:/language/Docs/Fields/dependents", "text": "Для плагина, перечисляет названия зависимых плагинов" }, "$:/language/Docs/Fields/description": { "title": "$:/language/Docs/Fields/description", "text": "Описание плагина или модального окна" }, "$:/language/Docs/Fields/draft.of": { "title": "$:/language/Docs/Fields/draft.of", "text": "Для черновиков, содержит название редактируемой заметки" }, "$:/language/Docs/Fields/draft.title": { "title": "$:/language/Docs/Fields/draft.title", "text": "Для черновиков, содержит новое название заметки" }, "$:/language/Docs/Fields/footer": { "title": "$:/language/Docs/Fields/footer", "text": "Текст \"подвала\" мастера" }, "$:/language/Docs/Fields/hack-to-give-us-something-to-compare-against": { "title": "$:/language/Docs/Fields/hack-to-give-us-something-to-compare-against", "text": "Временное поле используемое в [[$:/core/templates/static.content]]" }, "$:/language/Docs/Fields/icon": { "title": "$:/language/Docs/Fields/icon", "text": "Название заметки, содержащей значок заметки" }, "$:/language/Docs/Fields/library": { "title": "$:/language/Docs/Fields/library", "text": "Если \"yes\", то заметка сохраняется как библиотека JavaScript" }, "$:/language/Docs/Fields/list": { "title": "$:/language/Docs/Fields/list", "text": "Упорядоченный список названий связанных заметок" }, "$:/language/Docs/Fields/list-after": { "title": "$:/language/Docs/Fields/list-after", "text": "Название заметки, после которой эта заметка добавляется в упорядоченный список" }, "$:/language/Docs/Fields/list-before": { "title": "$:/language/Docs/Fields/list-before", "text": "Название заметки, перед которой эта заметка добавляется в упорядоченный список; если это поле создано и имеет пустое значение, то заметка добавляется в начало списка" }, "$:/language/Docs/Fields/modified": { "title": "$:/language/Docs/Fields/modified", "text": "Дата последнего изменения заметки" }, "$:/language/Docs/Fields/modifier": { "title": "$:/language/Docs/Fields/modifier", "text": "Имя редактора заметки" }, "$:/language/Docs/Fields/name": { "title": "$:/language/Docs/Fields/name", "text": "Название плагина" }, "$:/language/Docs/Fields/plugin-priority": { "title": "$:/language/Docs/Fields/plugin-priority", "text": "Число - приоритет плагина" }, "$:/language/Docs/Fields/plugin-type": { "title": "$:/language/Docs/Fields/plugin-type", "text": "Тип плагина" }, "$:/language/Docs/Fields/released": { "title": "$:/language/Docs/Fields/released", "text": "Дата выпуска TiddlyWiki" }, "$:/language/Docs/Fields/revision": { "title": "$:/language/Docs/Fields/revision", "text": "Версия заметки на сервере" }, "$:/language/Docs/Fields/source": { "title": "$:/language/Docs/Fields/source", "text": "Исходный URL связанный с заметкой" }, "$:/language/Docs/Fields/subtitle": { "title": "$:/language/Docs/Fields/subtitle", "text": "Подзаголовок мастера" }, "$:/language/Docs/Fields/tags": { "title": "$:/language/Docs/Fields/tags", "text": "Список меток связанный с заметкой" }, "$:/language/Docs/Fields/text": { "title": "$:/language/Docs/Fields/text", "text": "Содержимое заметки" }, "$:/language/Docs/Fields/title": { "title": "$:/language/Docs/Fields/title", "text": "Уникальное название заметки" }, "$:/language/Docs/Fields/type": { "title": "$:/language/Docs/Fields/type", "text": "Тип содержимого заметки" }, "$:/language/Docs/Fields/version": { "title": "$:/language/Docs/Fields/version", "text": "Версия плагина" }, "$:/language/Docs/ModuleTypes/animation": { "title": "$:/language/Docs/ModuleTypes/animation", "text": "Анимации для виджета Reveal." }, "$:/language/Docs/ModuleTypes/command": { "title": "$:/language/Docs/ModuleTypes/command", "text": "Команды, исполняемые Node.js." }, "$:/language/Docs/ModuleTypes/config": { "title": "$:/language/Docs/ModuleTypes/config", "text": "Данные для вставки в `$tw.config`." }, "$:/language/Docs/ModuleTypes/filteroperator": { "title": "$:/language/Docs/ModuleTypes/filteroperator", "text": "Отдельные методы операторов фильтра." }, "$:/language/Docs/ModuleTypes/global": { "title": "$:/language/Docs/ModuleTypes/global", "text": "Глобальные данные для вставки в `$tw`." }, "$:/language/Docs/ModuleTypes/isfilteroperator": { "title": "$:/language/Docs/ModuleTypes/isfilteroperator", "text": "Операнды для оператора фильтра ''is''." }, "$:/language/Docs/ModuleTypes/macro": { "title": "$:/language/Docs/ModuleTypes/macro", "text": "Макросы JavaScript." }, "$:/language/Docs/ModuleTypes/parser": { "title": "$:/language/Docs/ModuleTypes/parser", "text": "Парсеры для разных типов содержимого." }, "$:/language/Docs/ModuleTypes/saver": { "title": "$:/language/Docs/ModuleTypes/saver", "text": "Методы сохранения." }, "$:/language/Docs/ModuleTypes/startup": { "title": "$:/language/Docs/ModuleTypes/startup", "text": "Функции, выполняемые при загрузке." }, "$:/language/Docs/ModuleTypes/storyview": { "title": "$:/language/Docs/ModuleTypes/storyview", "text": "Настройка анимации и поведения виджета List." }, "$:/language/Docs/ModuleTypes/tiddlerdeserializer": { "title": "$:/language/Docs/ModuleTypes/tiddlerdeserializer", "text": "Превращают разные типы содержимого в заметки." }, "$:/language/Docs/ModuleTypes/tiddlerfield": { "title": "$:/language/Docs/ModuleTypes/tiddlerfield", "text": "Определяет поведение отдельных полей заметок." }, "$:/language/Docs/ModuleTypes/tiddlermethod": { "title": "$:/language/Docs/ModuleTypes/tiddlermethod", "text": "Добавляет методы к прототипу заметки `$tw.Tiddler`." }, "$:/language/Docs/ModuleTypes/upgrader": { "title": "$:/language/Docs/ModuleTypes/upgrader", "text": "Обработка заметок во время обновления/импорта." }, "$:/language/Docs/ModuleTypes/utils": { "title": "$:/language/Docs/ModuleTypes/utils", "text": "Добавляет методы в `$tw.utils`." }, "$:/language/Docs/ModuleTypes/utils-node": { "title": "$:/language/Docs/ModuleTypes/utils-node", "text": "Добавляет специфичные для Node.js методы в `$tw.utils`." }, "$:/language/Docs/ModuleTypes/widget": { "title": "$:/language/Docs/ModuleTypes/widget", "text": "Виджеты отвечают за отображение и обновление DOM." }, "$:/language/Docs/ModuleTypes/wikimethod": { "title": "$:/language/Docs/ModuleTypes/wikimethod", "text": "Добавляет методы в `$tw.Wiki`." }, "$:/language/Docs/ModuleTypes/wikirule": { "title": "$:/language/Docs/ModuleTypes/wikirule", "text": "Отдельные правила для главного парсера WikiText." }, "$:/language/Docs/PaletteColours/alert-background": { "title": "$:/language/Docs/PaletteColours/alert-background", "text": "Фон сообщения об ошибке" }, "$:/language/Docs/PaletteColours/alert-border": { "title": "$:/language/Docs/PaletteColours/alert-border", "text": "Граница сообщения об ошибке" }, "$:/language/Docs/PaletteColours/alert-highlight": { "title": "$:/language/Docs/PaletteColours/alert-highlight", "text": "Подсветка сообщения об ошибке" }, "$:/language/Docs/PaletteColours/alert-muted-foreground": { "title": "$:/language/Docs/PaletteColours/alert-muted-foreground", "text": "Приглушенный цвет текста сообщения об ошибке" }, "$:/language/Docs/PaletteColours/background": { "title": "$:/language/Docs/PaletteColours/background", "text": "Общий фон" }, "$:/language/Docs/PaletteColours/blockquote-bar": { "title": "$:/language/Docs/PaletteColours/blockquote-bar", "text": "Оформление цитаты" }, "$:/language/Docs/PaletteColours/button-background": { "title": "$:/language/Docs/PaletteColours/button-background", "text": "Фон кнопки по умолчанию" }, "$:/language/Docs/PaletteColours/button-border": { "title": "$:/language/Docs/PaletteColours/button-border", "text": "Граница кнопки по умолчанию" }, "$:/language/Docs/PaletteColours/button-foreground": { "title": "$:/language/Docs/PaletteColours/button-foreground", "text": "Цвет кнопки по умолчанию" }, "$:/language/Docs/PaletteColours/code-background": { "title": "$:/language/Docs/PaletteColours/code-background", "text": "Фон блоков кода" }, "$:/language/Docs/PaletteColours/code-border": { "title": "$:/language/Docs/PaletteColours/code-border", "text": "Граница блоков кода" }, "$:/language/Docs/PaletteColours/code-foreground": { "title": "$:/language/Docs/PaletteColours/code-foreground", "text": "Цвет текста блоков кода" }, "$:/language/Docs/PaletteColours/dirty-indicator": { "title": "$:/language/Docs/PaletteColours/dirty-indicator", "text": "Индикатор несохранённых изменений" }, "$:/language/Docs/PaletteColours/download-background": { "title": "$:/language/Docs/PaletteColours/download-background", "text": "Фон кнопки Скачать" }, "$:/language/Docs/PaletteColours/download-foreground": { "title": "$:/language/Docs/PaletteColours/download-foreground", "text": "Цвет текста кнопки Скачать" }, "$:/language/Docs/PaletteColours/dragger-background": { "title": "$:/language/Docs/PaletteColours/dragger-background", "text": "Фон перетаскиваемой ссылки" }, "$:/language/Docs/PaletteColours/dragger-foreground": { "title": "$:/language/Docs/PaletteColours/dragger-foreground", "text": "Цвет текста перетаскиваемой ссылки" }, "$:/language/Docs/PaletteColours/dropdown-background": { "title": "$:/language/Docs/PaletteColours/dropdown-background", "text": "Фон выпадающего меню" }, "$:/language/Docs/PaletteColours/dropdown-border": { "title": "$:/language/Docs/PaletteColours/dropdown-border", "text": "Граница выпадающего меню" }, "$:/language/Docs/PaletteColours/dropdown-tab-background": { "title": "$:/language/Docs/PaletteColours/dropdown-tab-background", "text": "Фон вкладок выпадающего меню" }, "$:/language/Docs/PaletteColours/dropdown-tab-background-selected": { "title": "$:/language/Docs/PaletteColours/dropdown-tab-background-selected", "text": "Фон выбранных вкладок выпадающего меню" }, "$:/language/Docs/PaletteColours/dropzone-background": { "title": "$:/language/Docs/PaletteColours/dropzone-background", "text": "Фон области перетаскивания" }, "$:/language/Docs/PaletteColours/external-link-background": { "title": "$:/language/Docs/PaletteColours/external-link-background", "text": "фон внешней ссылки" }, "$:/language/Docs/PaletteColours/external-link-background-hover": { "title": "$:/language/Docs/PaletteColours/external-link-background-hover", "text": "Фон внешней ссылки при наведении" }, "$:/language/Docs/PaletteColours/external-link-background-visited": { "title": "$:/language/Docs/PaletteColours/external-link-background-visited", "text": "Фон посещённой внешней ссылки" }, "$:/language/Docs/PaletteColours/external-link-foreground": { "title": "$:/language/Docs/PaletteColours/external-link-foreground", "text": "Цвет текста внешней ссылки" }, "$:/language/Docs/PaletteColours/external-link-foreground-hover": { "title": "$:/language/Docs/PaletteColours/external-link-foreground-hover", "text": "Цвет текста внешней ссылки при наведении" }, "$:/language/Docs/PaletteColours/external-link-foreground-visited": { "title": "$:/language/Docs/PaletteColours/external-link-foreground-visited", "text": "Цвет текста посещённой внешней ссылки" }, "$:/language/Docs/PaletteColours/foreground": { "title": "$:/language/Docs/PaletteColours/foreground", "text": "Общий цвет текста" }, "$:/language/Docs/PaletteColours/message-background": { "title": "$:/language/Docs/PaletteColours/message-background", "text": "Фон сообщений" }, "$:/language/Docs/PaletteColours/message-border": { "title": "$:/language/Docs/PaletteColours/message-border", "text": "Граница сообщений" }, "$:/language/Docs/PaletteColours/message-foreground": { "title": "$:/language/Docs/PaletteColours/message-foreground", "text": "Цвет текста сообщений" }, "$:/language/Docs/PaletteColours/modal-backdrop": { "title": "$:/language/Docs/PaletteColours/modal-backdrop", "text": "Цвет фона за модальным окном" }, "$:/language/Docs/PaletteColours/modal-background": { "title": "$:/language/Docs/PaletteColours/modal-background", "text": "Фон модального окна" }, "$:/language/Docs/PaletteColours/modal-border": { "title": "$:/language/Docs/PaletteColours/modal-border", "text": "Граница модального окна" }, "$:/language/Docs/PaletteColours/modal-footer-background": { "title": "$:/language/Docs/PaletteColours/modal-footer-background", "text": "Фон подвала модального окна" }, "$:/language/Docs/PaletteColours/modal-footer-border": { "title": "$:/language/Docs/PaletteColours/modal-footer-border", "text": "Граница подвала модального окна" }, "$:/language/Docs/PaletteColours/modal-header-border": { "title": "$:/language/Docs/PaletteColours/modal-header-border", "text": "Граница шапки модального окна" }, "$:/language/Docs/PaletteColours/muted-foreground": { "title": "$:/language/Docs/PaletteColours/muted-foreground", "text": "Приглушенный цвет текста" }, "$:/language/Docs/PaletteColours/notification-background": { "title": "$:/language/Docs/PaletteColours/notification-background", "text": "Фон уведомлений" }, "$:/language/Docs/PaletteColours/notification-border": { "title": "$:/language/Docs/PaletteColours/notification-border", "text": "Граница уведомлений" }, "$:/language/Docs/PaletteColours/page-background": { "title": "$:/language/Docs/PaletteColours/page-background", "text": "Фон страницы" }, "$:/language/Docs/PaletteColours/pre-background": { "title": "$:/language/Docs/PaletteColours/pre-background", "text": "Фон неформатированного текста" }, "$:/language/Docs/PaletteColours/pre-border": { "title": "$:/language/Docs/PaletteColours/pre-border", "text": "Граница неформатированного текста" }, "$:/language/Docs/PaletteColours/primary": { "title": "$:/language/Docs/PaletteColours/primary", "text": "Первичный цвет" }, "$:/language/Docs/PaletteColours/sidebar-button-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-button-foreground", "text": "Цвет текста кнопок боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-controls-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground", "text": "Цвет элементов управления боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover": { "title": "$:/language/Docs/PaletteColours/sidebar-controls-foreground-hover", "text": "Цвет элементов управления боковой панели при наведении" }, "$:/language/Docs/PaletteColours/sidebar-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-foreground", "text": "Цвет текста на боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-foreground-shadow": { "title": "$:/language/Docs/PaletteColours/sidebar-foreground-shadow", "text": "Цвет тени текста на боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-muted-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground", "text": "Приглушенный цвет текста на боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover": { "title": "$:/language/Docs/PaletteColours/sidebar-muted-foreground-hover", "text": "Приглушенный цвет текста на боковой панели при наведении" }, "$:/language/Docs/PaletteColours/sidebar-tab-background": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-background", "text": "Фон вкладок на боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-tab-background-selected": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-background-selected", "text": "Фон выбранных вкладок на боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-tab-border": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-border", "text": "Граница вкладок на боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-tab-border-selected": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-border-selected", "text": "Граница выбранных вкладок на боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-tab-divider": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-divider", "text": "Разделитель вкладок на боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-tab-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground", "text": "Цвет текста вкладок на боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected": { "title": "$:/language/Docs/PaletteColours/sidebar-tab-foreground-selected", "text": "Цвет текста выбранных вкладок на боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground": { "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground", "text": "Цвет ссылок на заметки на боковой панели" }, "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover": { "title": "$:/language/Docs/PaletteColours/sidebar-tiddler-link-foreground-hover", "text": "Цвет ссылок на заметки на боковой панели при наведении" }, "$:/language/Docs/PaletteColours/site-title-foreground": { "title": "$:/language/Docs/PaletteColours/site-title-foreground", "text": "Цвет заголовка сайта" }, "$:/language/Docs/PaletteColours/static-alert-foreground": { "title": "$:/language/Docs/PaletteColours/static-alert-foreground", "text": "Цвет текста статической версии сообщения об ошибке" }, "$:/language/Docs/PaletteColours/tab-background": { "title": "$:/language/Docs/PaletteColours/tab-background", "text": "Фон вкладок" }, "$:/language/Docs/PaletteColours/tab-background-selected": { "title": "$:/language/Docs/PaletteColours/tab-background-selected", "text": "Фон выбранных вкладок" }, "$:/language/Docs/PaletteColours/tab-border": { "title": "$:/language/Docs/PaletteColours/tab-border", "text": "Граница вкладок" }, "$:/language/Docs/PaletteColours/tab-border-selected": { "title": "$:/language/Docs/PaletteColours/tab-border-selected", "text": "Граница выбранных вкладок" }, "$:/language/Docs/PaletteColours/tab-divider": { "title": "$:/language/Docs/PaletteColours/tab-divider", "text": "Разделитель вкладок" }, "$:/language/Docs/PaletteColours/tab-foreground": { "title": "$:/language/Docs/PaletteColours/tab-foreground", "text": "Цвет текста вкладок" }, "$:/language/Docs/PaletteColours/tab-foreground-selected": { "title": "$:/language/Docs/PaletteColours/tab-foreground-selected", "text": "Цвет текста выбранных вкладок" }, "$:/language/Docs/PaletteColours/table-border": { "title": "$:/language/Docs/PaletteColours/table-border", "text": "Граница таблиц" }, "$:/language/Docs/PaletteColours/table-footer-background": { "title": "$:/language/Docs/PaletteColours/table-footer-background", "text": "Фон подвала таблиц" }, "$:/language/Docs/PaletteColours/table-header-background": { "title": "$:/language/Docs/PaletteColours/table-header-background", "text": "Фон шапки таблиц" }, "$:/language/Docs/PaletteColours/tag-background": { "title": "$:/language/Docs/PaletteColours/tag-background", "text": "Фон меток" }, "$:/language/Docs/PaletteColours/tag-foreground": { "title": "$:/language/Docs/PaletteColours/tag-foreground", "text": "Цвет текста меток" }, "$:/language/Docs/PaletteColours/tiddler-background": { "title": "$:/language/Docs/PaletteColours/tiddler-background", "text": "Фон заметок" }, "$:/language/Docs/PaletteColours/tiddler-border": { "title": "$:/language/Docs/PaletteColours/tiddler-border", "text": "Граница заметок" }, "$:/language/Docs/PaletteColours/tiddler-controls-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground", "text": "Цвет элементов управления заметки" }, "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover": { "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-hover", "text": "Цвет элементов управления заметки при наведении" }, "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected": { "title": "$:/language/Docs/PaletteColours/tiddler-controls-foreground-selected", "text": "Цвет выбранных элементов управления заметки" }, "$:/language/Docs/PaletteColours/tiddler-editor-background": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-background", "text": "Фон редактора заметок" }, "$:/language/Docs/PaletteColours/tiddler-editor-border": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-border", "text": "Граница редактора заметок" }, "$:/language/Docs/PaletteColours/tiddler-editor-border-image": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-border-image", "text": "Граница редактора изображений" }, "$:/language/Docs/PaletteColours/tiddler-editor-fields-even": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-even", "text": "Фон четных полей" }, "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd": { "title": "$:/language/Docs/PaletteColours/tiddler-editor-fields-odd", "text": "Фон нечётных полей" }, "$:/language/Docs/PaletteColours/tiddler-info-background": { "title": "$:/language/Docs/PaletteColours/tiddler-info-background", "text": "Фон информационной панели заметки" }, "$:/language/Docs/PaletteColours/tiddler-info-border": { "title": "$:/language/Docs/PaletteColours/tiddler-info-border", "text": "Граница информационной панели заметки" }, "$:/language/Docs/PaletteColours/tiddler-info-tab-background": { "title": "$:/language/Docs/PaletteColours/tiddler-info-tab-background", "text": "Фон вкладок информационной панели заметки" }, "$:/language/Docs/PaletteColours/tiddler-link-background": { "title": "$:/language/Docs/PaletteColours/tiddler-link-background", "text": "Фон ссылок на заметку" }, "$:/language/Docs/PaletteColours/tiddler-link-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-link-foreground", "text": "Цвет текста ссылок на заметку" }, "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-subtitle-foreground", "text": "Цвет текста подзаголовка заметки" }, "$:/language/Docs/PaletteColours/tiddler-title-foreground": { "title": "$:/language/Docs/PaletteColours/tiddler-title-foreground", "text": "Цвет текста заголовка заметки" }, "$:/language/Docs/PaletteColours/toolbar-cancel-button": { "title": "$:/language/Docs/PaletteColours/toolbar-cancel-button", "text": "Цвет кнопки 'отменить'" }, "$:/language/Docs/PaletteColours/toolbar-close-button": { "title": "$:/language/Docs/PaletteColours/toolbar-close-button", "text": "Цвет кнопки 'закрыть'" }, "$:/language/Docs/PaletteColours/toolbar-delete-button": { "title": "$:/language/Docs/PaletteColours/toolbar-delete-button", "text": "Цвет кнопки 'удалить'" }, "$:/language/Docs/PaletteColours/toolbar-done-button": { "title": "$:/language/Docs/PaletteColours/toolbar-done-button", "text": "Цвет кнопки 'готово'" }, "$:/language/Docs/PaletteColours/toolbar-edit-button": { "title": "$:/language/Docs/PaletteColours/toolbar-edit-button", "text": "Цвет кнопки 'редактировать'" }, "$:/language/Docs/PaletteColours/toolbar-info-button": { "title": "$:/language/Docs/PaletteColours/toolbar-info-button", "text": "Цвет кнопки 'информация'" }, "$:/language/Docs/PaletteColours/toolbar-new-button": { "title": "$:/language/Docs/PaletteColours/toolbar-new-button", "text": "Цвет кнопки 'создать'" }, "$:/language/Docs/PaletteColours/toolbar-options-button": { "title": "$:/language/Docs/PaletteColours/toolbar-options-button", "text": "Цвет кнопки 'настройки'" }, "$:/language/Docs/PaletteColours/toolbar-save-button": { "title": "$:/language/Docs/PaletteColours/toolbar-save-button", "text": "Цвет кнопки 'сохранить'" }, "$:/language/Docs/PaletteColours/untagged-background": { "title": "$:/language/Docs/PaletteColours/untagged-background", "text": "Фон метки 'без метки'" }, "$:/language/Docs/PaletteColours/very-muted-foreground": { "title": "$:/language/Docs/PaletteColours/very-muted-foreground", "text": "Очень приглушенный цвет текста" }, "$:/language/EditTemplate/Body/External/Hint": { "title": "$:/language/EditTemplate/Body/External/Hint", "text": "Содержимое этой заметки находится вне TiddlyWiki. Но вы можете редактировать метки и поля" }, "$:/language/EditTemplate/Body/Placeholder": { "title": "$:/language/EditTemplate/Body/Placeholder", "text": "Введите текст заметки" }, "$:/language/EditTemplate/Field/Remove/Caption": { "title": "$:/language/EditTemplate/Field/Remove/Caption", "text": "удалить поле" }, "$:/language/EditTemplate/Field/Remove/Hint": { "title": "$:/language/EditTemplate/Field/Remove/Hint", "text": "Удалить поле" }, "$:/language/EditTemplate/Fields/Add/Button": { "title": "$:/language/EditTemplate/Fields/Add/Button", "text": "добавить" }, "$:/language/EditTemplate/Fields/Add/Dropdown/System": { "title": "$:/language/EditTemplate/Fields/Add/Dropdown/System", "text": "Системные поля" }, "$:/language/EditTemplate/Fields/Add/Dropdown/User": { "title": "$:/language/EditTemplate/Fields/Add/Dropdown/User", "text": "Пользовательские поля" }, "$:/language/EditTemplate/Fields/Add/Name/Placeholder": { "title": "$:/language/EditTemplate/Fields/Add/Name/Placeholder", "text": "название поля" }, "$:/language/EditTemplate/Fields/Add/Prompt": { "title": "$:/language/EditTemplate/Fields/Add/Prompt", "text": "Добавить новое поле:" }, "$:/language/EditTemplate/Fields/Add/Value/Placeholder": { "title": "$:/language/EditTemplate/Fields/Add/Value/Placeholder", "text": "значение" }, "$:/language/EditTemplate/Shadow/OverriddenWarning": { "title": "$:/language/EditTemplate/Shadow/OverriddenWarning", "text": "Это переопределённая встроенная заметка. Для восстановления стандартного значения просто удалите её" }, "$:/language/EditTemplate/Shadow/Warning": { "title": "$:/language/EditTemplate/Shadow/Warning", "text": "Это встроенная заметка. Любое изменение переопределит стандартное значение" }, "$:/language/EditTemplate/Tags/Add/Button": { "title": "$:/language/EditTemplate/Tags/Add/Button", "text": "добавить" }, "$:/language/EditTemplate/Tags/Add/Placeholder": { "title": "$:/language/EditTemplate/Tags/Add/Placeholder", "text": "название метки" }, "$:/language/EditTemplate/Tags/Dropdown/Caption": { "title": "$:/language/EditTemplate/Tags/Dropdown/Caption", "text": "список меток" }, "$:/language/EditTemplate/Tags/Dropdown/Hint": { "title": "$:/language/EditTemplate/Tags/Dropdown/Hint", "text": "Показать список меток" }, "$:/language/EditTemplate/Type/Delete/Caption": { "title": "$:/language/EditTemplate/Type/Delete/Caption", "text": "удалить тип содержимого" }, "$:/language/EditTemplate/Type/Delete/Hint": { "title": "$:/language/EditTemplate/Type/Delete/Hint", "text": "Удалить тип содержимого" }, "$:/language/EditTemplate/Type/Dropdown/Caption": { "title": "$:/language/EditTemplate/Type/Dropdown/Caption", "text": "список типов содержимого" }, "$:/language/EditTemplate/Type/Dropdown/Hint": { "title": "$:/language/EditTemplate/Type/Dropdown/Hint", "text": "Показать список типов содержимого" }, "$:/language/EditTemplate/Type/Placeholder": { "title": "$:/language/EditTemplate/Type/Placeholder", "text": "тип содержимого" }, "$:/language/EditTemplate/Type/Prompt": { "title": "$:/language/EditTemplate/Type/Prompt", "text": "Тип:" }, "$:/language/Exporters/StaticRiver": { "title": "$:/language/Exporters/StaticRiver", "text": "Показываемые заметки в виде статического HTML файла" }, "$:/language/Exporters/JsonFile": { "title": "$:/language/Exporters/JsonFile", "text": "Заметки в формате JSON" }, "$:/language/Exporters/CsvFile": { "title": "$:/language/Exporters/CsvFile", "text": "Заметки в формате CSV" }, "$:/language/Exporters/TidFile": { "title": "$:/language/Exporters/TidFile", "text": "Одна заметка в формате \".tid\"" }, "$:/language/Filters/AllTags": { "title": "$:/language/Filters/AllTags", "text": "Все метки, кроме системных" }, "$:/language/Filters/AllTiddlers": { "title": "$:/language/Filters/AllTiddlers", "text": "Все заметки, кроме системных" }, "$:/language/Filters/Drafts": { "title": "$:/language/Filters/Drafts", "text": "Черновики" }, "$:/language/Filters/Missing": { "title": "$:/language/Filters/Missing", "text": "Отсутствующие заметки" }, "$:/language/Filters/Orphans": { "title": "$:/language/Filters/Orphans", "text": "Потерянные заметки" }, "$:/language/Filters/OverriddenShadowTiddlers": { "title": "$:/language/Filters/OverriddenShadowTiddlers", "text": "Переопределённые встроенные заметки" }, "$:/language/Filters/RecentSystemTiddlers": { "title": "$:/language/Filters/RecentSystemTiddlers", "text": "Недавно измененные заметки, включая системные" }, "$:/language/Filters/RecentTiddlers": { "title": "$:/language/Filters/RecentTiddlers", "text": "Недавно измененные заметки" }, "$:/language/Filters/ShadowTiddlers": { "title": "$:/language/Filters/ShadowTiddlers", "text": "Встроенные заметки" }, "$:/language/Filters/SystemTags": { "title": "$:/language/Filters/SystemTags", "text": "Системные метки" }, "$:/language/Filters/SystemTiddlers": { "title": "$:/language/Filters/SystemTiddlers", "text": "Системные заметки" }, "$:/language/Filters/TypedTiddlers": { "title": "$:/language/Filters/TypedTiddlers", "text": "Не вики-текстовые тиддлеры" }, "GettingStarted": { "title": "GettingStarted", "text": "\\define lingo-base() $:/language/ControlPanel/Basics/\nДобро пожаловать в ~TiddlyWiki, нелинейную личную сетевую записную книжку.\n\nДля начала убедитесь, что у вас работает сохранение - подробные инструкции на http://tiddlywiki.com/.\n\nЗатем вы можете:\n\n* Создать новые заметки, используя кнопку 'плюс' на боковой панели\n* Зайти в панель управления, используя кнопку с изображением 'шестерёнки' на боковой панели и настроить TiddlyWiki на свой вкус\n** Убрать это сообщение, изменив настройку 'заметки по умолчанию' на вкладке Основные\n* Сохранить изменения при помощи кнопки 'скачать' на боковой панели\n* Изучить подробнее WikiText\n\n!! Set up this ~TiddlyWiki\n\n<div class=\"tc-control-panel\">\n\n|<$link to=\"$:/SiteTitle\"><<lingo Title/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteTitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/SiteSubtitle\"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler=\"$:/SiteSubtitle\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/DefaultTiddlers\"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit-text tag=\"textarea\" tiddler=\"$:/DefaultTiddlers\"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |\n</div>\n\nSee the [[control panel|$:/ControlPanel]] for more options.\n" }, "$:/language/Import/Listing/Cancel/Caption": { "title": "$:/language/Import/Listing/Cancel/Caption", "text": "Отмена" }, "$:/language/Import/Listing/Hint": { "title": "$:/language/Import/Listing/Hint", "text": "Импортируемые заметки:" }, "$:/language/Import/Listing/Import/Caption": { "title": "$:/language/Import/Listing/Import/Caption", "text": "Импортировать" }, "$:/language/Import/Listing/Select/Caption": { "title": "$:/language/Import/Listing/Select/Caption", "text": "Выбор" }, "$:/language/Import/Listing/Status/Caption": { "title": "$:/language/Import/Listing/Status/Caption", "text": "Примечание" }, "$:/language/Import/Listing/Title/Caption": { "title": "$:/language/Import/Listing/Title/Caption", "text": "Название" }, "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible": { "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Incompatible", "text": "Заблокированный несовместимый или устаревший плагин" }, "$:/language/Import/Upgrader/Plugins/Suppressed/Version": { "title": "$:/language/Import/Upgrader/Plugins/Suppressed/Version", "text": "Заблокированный плагин (импотируемый <<incoming>> старее существующего <<existing>>)" }, "$:/language/Import/Upgrader/Plugins/Upgraded": { "title": "$:/language/Import/Upgrader/Plugins/Upgraded", "text": "Обновляемый плагин с версии <<incoming>> до <<upgraded>>" }, "$:/language/Import/Upgrader/State/Suppressed": { "title": "$:/language/Import/Upgrader/State/Suppressed", "text": "Заблокированная временная внутренняя заметка" }, "$:/language/Import/Upgrader/System/Suppressed": { "title": "$:/language/Import/Upgrader/System/Suppressed", "text": "Заблокированная системная заметка" }, "$:/language/Import/Upgrader/ThemeTweaks/Created": { "title": "$:/language/Import/Upgrader/ThemeTweaks/Created", "text": "Импортированная настройка темы из <$text text=<<from>>/>" }, "$:/language/BinaryWarning/Prompt": { "title": "$:/language/BinaryWarning/Prompt", "text": "Эта заметка содержит двоичные данные" }, "$:/language/ClassicWarning/Hint": { "title": "$:/language/ClassicWarning/Hint", "text": "Эта заметка написана в формате TiddlyWiki Classic WikiText, который не совместим с TiddlyWiki 5. Подробнее: http://tiddlywiki.com/static/Upgrading.html" }, "$:/language/ClassicWarning/Upgrade/Caption": { "title": "$:/language/ClassicWarning/Upgrade/Caption", "text": "обновление" }, "$:/language/CloseAll/Button": { "title": "$:/language/CloseAll/Button", "text": "закрыть все" }, "$:/language/ConfirmCancelTiddler": { "title": "$:/language/ConfirmCancelTiddler", "text": "Отменить изменения заметки \"<$text text=<<title>>/>\"?" }, "$:/language/ConfirmDeleteTiddler": { "title": "$:/language/ConfirmDeleteTiddler", "text": "Удалить заметку \"<$text text=<<title>>/>\"?" }, "$:/language/ConfirmEditShadowTiddler": { "title": "$:/language/ConfirmEditShadowTiddler", "text": "Вы собираетесь редактировать встроенную заметку. Любое изменение переопределит стандартное значение и может привести к проблемам при обновлении TiddlyWiki. Вы действительно хотите редактировать \"<$text text=<<title>>/>\"?" }, "$:/language/ConfirmOverwriteTiddler": { "title": "$:/language/ConfirmOverwriteTiddler", "text": "Заменить заметку \"<$text text=<<title>>/>\"?" }, "$:/language/Count": { "title": "$:/language/Count", "text": "номер" }, "$:/language/DefaultNewTiddlerTitle": { "title": "$:/language/DefaultNewTiddlerTitle", "text": "Новая заметка" }, "$:/language/DropMessage": { "title": "$:/language/DropMessage", "text": "Перетащите сюда (или нажмите escape для отмены)" }, "$:/language/Encryption/Cancel": { "title": "$:/language/Encryption/Cancel", "text": "Отмена" }, "$:/language/Encryption/ConfirmClearPassword": { "title": "$:/language/Encryption/ConfirmClearPassword", "text": "Вы действительно хотите сбросить пароль? Это действие отменит шифрование при следующем сохранении" }, "$:/language/Encryption/Password": { "title": "$:/language/Encryption/Password", "text": "Пароль" }, "$:/language/Encryption/PasswordNoMatch": { "title": "$:/language/Encryption/PasswordNoMatch", "text": "Пароли не совпадают" }, "$:/language/Encryption/PromptSetPassword": { "title": "$:/language/Encryption/PromptSetPassword", "text": "Установить новый пароль для TiddlyWiki" }, "$:/language/Encryption/RepeatPassword": { "title": "$:/language/Encryption/RepeatPassword", "text": "Повторите пароль" }, "$:/language/Encryption/SetPassword": { "title": "$:/language/Encryption/SetPassword", "text": "Введите пароль" }, "$:/language/Encryption/Username": { "title": "$:/language/Encryption/Username", "text": "Имя пользователя" }, "$:/language/InvalidFieldName": { "title": "$:/language/InvalidFieldName", "text": "Недопустимые символы в названии поля \"<$text text=<<fieldName>>/>\". Поля могут содержать только латинские буквы нижнего регистра, цифры и символы: подчеркивание (`_`), дефис (`-`) и точку (`.`)" }, "$:/language/MissingTiddler/Hint": { "title": "$:/language/MissingTiddler/Hint", "text": "Заметка \"<$text text=<<currentTiddler>>/>\" отсутствует - нажмите {{$:/core/images/edit-button}} чтобы её создать" }, "$:/language/OfficialPluginLibrary": { "title": "$:/language/OfficialPluginLibrary", "text": "Официальная Библиотека Плагинов ~TiddlyWiki" }, "$:/language/PluginReloadWarning": { "title": "$:/language/PluginReloadWarning", "text": "Пожалуйста, сохраните {{$:/core/ui/Buttons/save-wiki}} и перезапустите {{$:/core/ui/Buttons/refresh}} вики, чтобы изменения в плагинах возымели эффект." }, "$:/language/RecentChanges/DateFormat": { "title": "$:/language/RecentChanges/DateFormat", "text": "DD MMM YYYY" }, "$:/language/SystemTiddler/Tooltip": { "title": "$:/language/SystemTiddler/Tooltip", "text": "Это системная заметка" }, "$:/language/TagManager/Colour/Heading": { "title": "$:/language/TagManager/Colour/Heading", "text": "Цвет" }, "$:/language/TagManager/Count/Heading": { "title": "$:/language/TagManager/Count/Heading", "text": "Номер" }, "$:/language/TagManager/Icon/Heading": { "title": "$:/language/TagManager/Icon/Heading", "text": "Значок" }, "$:/language/TagManager/Info/Heading": { "title": "$:/language/TagManager/Info/Heading", "text": "Детали" }, "$:/language/TagManager/Tag/Heading": { "title": "$:/language/TagManager/Tag/Heading", "text": "Метка" }, "$:/language/UnsavedChangesWarning": { "title": "$:/language/UnsavedChangesWarning", "text": "Изменения TiddlyWiki не сохранены" }, "$:/language/Modals/Download": { "title": "$:/language/Modals/Download", "type": "text/vnd.tiddlywiki", "subtitle": "Скачать изменения", "footer": "<$button message=\"tm-close-tiddler\">Закрыть</$button>", "help": "http://tiddlywiki.com/static/DownloadingChanges.html", "text": "Ваш браузер поддерживает только ручное сохранение.\n\nЧтобы сохранить измененную ~TiddlyWiki, щёлкните правой кнопкой мыши по ссылке ниже и выберите \"Скачать файл\" или \"Сохранить файл\", затем выберите расположение и имя файла.\n\n//Вы можете заметно ускорить этот процесс, щёлкнув по ссылке с нажатой клавишей Control (Windows) или Options/Alt (Mac OS X). У вас не спросят расположение и имя файла, возможно, имя будет неузнаваемым -- также может понадобиться добавить расширение `.html` к имени файла.//\n\nНа смартфонах, которые на позволяют скачивать файлы, можно поместить ссылку в закладки, затем синхронизировать закладки с компьютером, где ~TiddlyWiki можно сохранить обычным методом.\n" }, "$:/language/Modals/SaveInstructions": { "title": "$:/language/Modals/SaveInstructions", "type": "text/vnd.tiddlywiki", "subtitle": "Сохраните свою работу", "footer": "<$button message=\"tm-close-tiddler\">Закрыть</$button>", "help": "http://tiddlywiki.com/static/SavingChanges.html", "text": "Изменения должны быть сохранены в виде HTML файла ~TiddlyWiki.\n\n!!! На компьютере\n\n# Нажмите ''Сохранить как'' в меню ''Файл''\n# Выберите название и расположение файла\n#* Иногда требуется также явно указать формат сохраняемого файла: ''Веб-страница, только HTML'' или подобный\n# Закройте эту вкладку\n\n!!! На смартфоне\n\n# Поместите эту страницу в закладки\n#* Если у вас настроен iCloud или Google Sync, тогда закладка автоматически синхронизируется с компьютером, и вы сможете открыть её и сохранить по инструкции для компьютеров\n# Закройте эту вкладку\n\n//При открытии закладки в Mobile Safari вы снова увидите это сообщение. Если вы хотите продолжить работу с файлом, нажмите на кнопку ''Закрыть'' ниже//\n" }, "$:/config/NewJournal/Tags": { "title": "$:/config/NewJournal/Tags", "text": "Дневник" }, "$:/config/NewJournal/Title": { "title": "$:/config/NewJournal/Title", "text": "DD MMM YYYY" }, "$:/language/Notifications/Save/Done": { "title": "$:/language/Notifications/Save/Done", "text": "Успешно сохранено" }, "$:/language/Notifications/Save/Starting": { "title": "$:/language/Notifications/Save/Starting", "text": "Идёт сохранение" }, "$:/language/Search/DefaultResults/Caption": { "title": "$:/language/Search/DefaultResults/Caption", "text": "Список" }, "$:/language/Search/Filter/Caption": { "title": "$:/language/Search/Filter/Caption", "text": "Фильтр" }, "$:/language/Search/Filter/Hint": { "title": "$:/language/Search/Filter/Hint", "text": "Поиск с помощью [[фильтров|http://tiddlywiki.com/static/Filters.html]]" }, "$:/language/Search/Filter/Matches": { "title": "$:/language/Search/Filter/Matches", "text": "//<small><<resultCount>> совпадений</small>//" }, "$:/language/Search/Matches": { "title": "$:/language/Search/Matches", "text": "//<small><<resultCount>> совпадений</small>//" }, "$:/language/Search/Shadows/Caption": { "title": "$:/language/Search/Shadows/Caption", "text": "Встроенные" }, "$:/language/Search/Shadows/Hint": { "title": "$:/language/Search/Shadows/Hint", "text": "Поиск встроенных заметок" }, "$:/language/Search/Shadows/Matches": { "title": "$:/language/Search/Shadows/Matches", "text": "//<small><<resultCount>> совпадений</small>//" }, "$:/language/Search/Standard/Caption": { "title": "$:/language/Search/Standard/Caption", "text": "Обычные" }, "$:/language/Search/Standard/Hint": { "title": "$:/language/Search/Standard/Hint", "text": "Поиск обычных заметок" }, "$:/language/Search/Standard/Matches": { "title": "$:/language/Search/Standard/Matches", "text": "//<small><<resultCount>> совпадений</small>//" }, "$:/language/Search/System/Caption": { "title": "$:/language/Search/System/Caption", "text": "Системные" }, "$:/language/Search/System/Hint": { "title": "$:/language/Search/System/Hint", "text": "Поиск системных заметок" }, "$:/language/Search/System/Matches": { "title": "$:/language/Search/System/Matches", "text": "//<small><<resultCount>> совпадений</small>//" }, "$:/language/SideBar/All/Caption": { "title": "$:/language/SideBar/All/Caption", "text": "Все" }, "$:/language/SideBar/Contents/Caption": { "title": "$:/language/SideBar/Contents/Caption", "text": "Оглавление" }, "$:/language/SideBar/Drafts/Caption": { "title": "$:/language/SideBar/Drafts/Caption", "text": "Черновики" }, "$:/language/SideBar/Missing/Caption": { "title": "$:/language/SideBar/Missing/Caption", "text": "Отсутствующие" }, "$:/language/SideBar/More/Caption": { "title": "$:/language/SideBar/More/Caption", "text": "Ещё" }, "$:/language/SideBar/Open/Caption": { "title": "$:/language/SideBar/Open/Caption", "text": "Открытые" }, "$:/language/SideBar/Orphans/Caption": { "title": "$:/language/SideBar/Orphans/Caption", "text": "Потерянные" }, "$:/language/SideBar/Recent/Caption": { "title": "$:/language/SideBar/Recent/Caption", "text": "Последние" }, "$:/language/SideBar/Shadows/Caption": { "title": "$:/language/SideBar/Shadows/Caption", "text": "Встроенные" }, "$:/language/SideBar/System/Caption": { "title": "$:/language/SideBar/System/Caption", "text": "Системные" }, "$:/language/SideBar/Tags/Caption": { "title": "$:/language/SideBar/Tags/Caption", "text": "Метки" }, "$:/language/SideBar/Tags/Untagged/Caption": { "title": "$:/language/SideBar/Tags/Untagged/Caption", "text": "без метки" }, "$:/language/SideBar/Tools/Caption": { "title": "$:/language/SideBar/Tools/Caption", "text": "Инструменты" }, "$:/language/SideBar/Types/Caption": { "title": "$:/language/SideBar/Types/Caption", "text": "Типы" }, "$:/SiteSubtitle": { "title": "$:/SiteSubtitle", "text": "нелинейная личная сетевая записная книжка" }, "$:/SiteTitle": { "title": "$:/SiteTitle", "text": "Моя ~TiddlyWiki" }, "$:/language/TiddlerInfo/Advanced/Caption": { "title": "$:/language/TiddlerInfo/Advanced/Caption", "text": "Расширенные" }, "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint": { "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Empty/Hint", "text": "нет" }, "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading": { "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Heading", "text": "Сведения о плагине" }, "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint": { "title": "$:/language/TiddlerInfo/Advanced/PluginInfo/Hint", "text": "Плагин содержит следующие встроенные заметки:" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Heading", "text": "Встроенность" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/NotShadow/Hint", "text": "Заметка <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> не является встроенной" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/OverriddenShadow/Hint", "text": "Она переопределена обычной заметкой" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Hint", "text": "Заметка <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> является встроенной" }, "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source": { "title": "$:/language/TiddlerInfo/Advanced/ShadowInfo/Shadow/Source", "text": "Она принадлежит плагину <$link to=<<pluginTiddler>>><$text text=<<pluginTiddler>>/></$link>" }, "$:/language/TiddlerInfo/Fields/Caption": { "title": "$:/language/TiddlerInfo/Fields/Caption", "text": "Поля" }, "$:/language/TiddlerInfo/List/Caption": { "title": "$:/language/TiddlerInfo/List/Caption", "text": "Список" }, "$:/language/TiddlerInfo/List/Empty": { "title": "$:/language/TiddlerInfo/List/Empty", "text": "У этой заметки нет списка" }, "$:/language/TiddlerInfo/Listed/Caption": { "title": "$:/language/TiddlerInfo/Listed/Caption", "text": "В списках" }, "$:/language/TiddlerInfo/Listed/Empty": { "title": "$:/language/TiddlerInfo/Listed/Empty", "text": "Этой заметки нет в списках" }, "$:/language/TiddlerInfo/References/Caption": { "title": "$:/language/TiddlerInfo/References/Caption", "text": "Ссылки" }, "$:/language/TiddlerInfo/References/Empty": { "title": "$:/language/TiddlerInfo/References/Empty", "text": "Другие заметки не ссылаются на эту" }, "$:/language/TiddlerInfo/Tagging/Caption": { "title": "$:/language/TiddlerInfo/Tagging/Caption", "text": "Отмеченные" }, "$:/language/TiddlerInfo/Tagging/Empty": { "title": "$:/language/TiddlerInfo/Tagging/Empty", "text": "Нет заметок, отмеченных этой" }, "$:/language/TiddlerInfo/Tools/Caption": { "title": "$:/language/TiddlerInfo/Tools/Caption", "text": "Инструменты" }, "$:/language/Docs/Types/application/javascript": { "title": "$:/language/Docs/Types/application/javascript", "description": "JavaScript code", "name": "application/javascript", "group": "Разработка" }, "$:/language/Docs/Types/application/json": { "title": "$:/language/Docs/Types/application/json", "description": "JSON data", "name": "application/json", "group": "Разработка" }, "$:/language/Docs/Types/application/x-tiddler-dictionary": { "title": "$:/language/Docs/Types/application/x-tiddler-dictionary", "description": "Data dictionary", "name": "application/x-tiddler-dictionary", "group": "Разработка" }, "$:/language/Docs/Types/image/gif": { "title": "$:/language/Docs/Types/image/gif", "description": "GIF изображение", "name": "image/gif", "group": "Изображение" }, "$:/language/Docs/Types/image/jpeg": { "title": "$:/language/Docs/Types/image/jpeg", "description": "JPEG изображение", "name": "image/jpeg", "group": "Изображение" }, "$:/language/Docs/Types/image/png": { "title": "$:/language/Docs/Types/image/png", "description": "PNG изображение", "name": "image/png", "group": "Изображение" }, "$:/language/Docs/Types/image/svg+xml": { "title": "$:/language/Docs/Types/image/svg+xml", "description": "SVG изображение", "name": "image/svg+xml", "group": "Изображение" }, "$:/language/Docs/Types/image/x-icon": { "title": "$:/language/Docs/Types/image/x-icon", "description": "ICO значок", "name": "image/x-icon", "group": "Изображение" }, "$:/language/Docs/Types/text/css": { "title": "$:/language/Docs/Types/text/css", "description": "Static stylesheet", "name": "text/css", "group": "Разработка" }, "$:/language/Docs/Types/text/html": { "title": "$:/language/Docs/Types/text/html", "description": "HTML разметка", "name": "text/html", "group": "Текст" }, "$:/language/Docs/Types/text/plain": { "title": "$:/language/Docs/Types/text/plain", "description": "Обычный текст", "name": "text/plain", "group": "Текст" }, "$:/language/Docs/Types/text/vnd.tiddlywiki": { "title": "$:/language/Docs/Types/text/vnd.tiddlywiki", "description": "TiddlyWiki 5", "name": "text/vnd.tiddlywiki", "group": "Текст" }, "$:/language/Docs/Types/text/x-tiddlywiki": { "title": "$:/language/Docs/Types/text/x-tiddlywiki", "description": "TiddlyWiki Classic", "name": "text/x-tiddlywiki", "group": "Текст" }, "$:/languages/ru-RU/icon": { "title": "$:/languages/ru-RU/icon", "type": "image/svg+xml", "text": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 9 6\" width=\"900\" height=\"600\">\n<rect width=\"9\" height=\"6\" fill=\"#D52B1E\"/>\n<rect width=\"9\" height=\"4\" fill=\"#0039A6\"/>\n<rect width=\"9\" height=\"2\" fill=\"#FFF\"/>\n<path d=\"m0,0h9v6H0z\" stroke=\"#a0a0a0\" stroke-width=\".1\" fill=\"none\"/>\n</svg>" } } }
$:/palettes/Dev
alert-background: #ffe476 alert-border: #b99e2f alert-highlight: #881122 alert-muted-foreground: #b99e2f background: #e5f8fd blockquote-bar: <<colour muted-foreground>> code-background: #f7f7f9 code-border: #e1e1e8 code-foreground: #dd1144 dirty-indicator: #ff0000 download-background: #34c734 download-foreground: <<colour background>> dragger-background: <<colour foreground>> dragger-foreground: <<colour background>> dropdown-background: <<colour background>> dropdown-border: <<colour muted-foreground>> dropdown-tab-background-selected: #fff dropdown-tab-background: #ececec dropzone-background: rgba(0,200,0,0.7) external-link-background-hover: inherit external-link-background-visited: inherit external-link-background: inherit external-link-foreground-hover: inherit external-link-foreground-visited: #0000aa external-link-foreground: #0000ee foreground: #4e432f message-background: #ecf2ff message-border: #cfd6e6 message-foreground: #547599 modal-backdrop: <<colour foreground>> modal-background: <<colour background>> modal-border: #999999 modal-footer-background: #f5f5f5 modal-footer-border: #dddddd modal-header-border: #eeeeee muted-foreground: #bbb notification-background: #ffffdd notification-border: #999999 page-background: #f4d7a3 pre-background: #f5f5f5 pre-border: #cccccc primary: #5778d8 sidebar-button-foreground: #877452 sidebar-controls-foreground-hover: #000000 sidebar-controls-foreground: #658deb sidebar-foreground-shadow: rgba(255,255,255, 0.4) sidebar-foreground: #9f8860 sidebar-muted-foreground-hover: #444444 sidebar-muted-foreground: #c9ac7a sidebar-tab-background-selected: #f4d7a3 sidebar-tab-background: #e6c58b sidebar-tab-border-selected: #d9ba83 sidebar-tab-border: #dbb678 sidebar-tab-divider: #dfbe87 sidebar-tab-foreground-selected: #8d764e sidebar-tab-foreground: #66573e sidebar-tiddler-link-foreground-hover: #8e7a56 sidebar-tiddler-link-foreground: #937e59 static-alert-foreground: #aaaaaa tab-background-selected: #dff6fc tab-background: #d8d8d8 tab-border-selected: #d8d8d8 tab-border: #cccccc tab-divider: #d8d8d8 tab-foreground-selected: <<colour tab-foreground>> tab-foreground: #666666 table-border: #dddddd table-footer-background: #a8a8a8 table-header-background: #f0f0f0 tag-background: #d5ad34 tag-foreground: #ffffff tiddler-background: <<colour background>> tiddler-border: <<colour background>> tiddler-controls-foreground-hover: #888888 tiddler-controls-foreground-selected: #444444 tiddler-controls-foreground: #9eaeb4 tiddler-editor-background: #f8f8f8 tiddler-editor-border-image: #ffffff tiddler-editor-border: #cccccc tiddler-editor-fields-even: #e0e8e0 tiddler-editor-fields-odd: #f0f4f0 tiddler-info-background: #f8f8f8 tiddler-info-border: #dddddd tiddler-info-tab-background: #f8f8f8 tiddler-link-background: <<colour background>> tiddler-link-foreground: <<colour primary>> tiddler-subtitle-foreground: #c0c0c0 tiddler-title-foreground: #715e3e toolbar-new-button: toolbar-options-button: toolbar-save-button: toolbar-info-button: toolbar-edit-button: toolbar-close-button: toolbar-delete-button: toolbar-cancel-button: toolbar-done-button: untagged-background: #999999 very-muted-foreground: #888888
<script> window.$tw = window.$tw || Object.create(null); $tw.boot = $tw.boot || Object.create(null); $tw.boot.encryptionPrompts = { decrypt: "Decrypt this TiddlyWiki by entering the password" }; </script> <style> body .tc-password-wrapper { background-color: rgb(183, 197, 235); border: 8px solid rgb(152, 164, 197); } body .tc-password-wrapper form { text-align: center; } body .tc-password-wrapper h1 { padding-bottom: 8px; } body .tc-password-wrapper input { width: auto; } </style>
{ "tiddlers": { "$:/plugins/tiddlywiki/github-fork-ribbon/readme": { "title": "$:/plugins/tiddlywiki/github-fork-ribbon/readme", "text": "This plugin provides a diagonal ribbon across the corner of the window. It resembles the design used by ~GitHub for their \"Fork me on ~GitHub\" ribbons.\n\nThe ribbon can be positioned over any corner, and can incorporate user defined text, colours and a link.\n\nThe CSS stylesheet is adapted from work by Simon Whitaker:\n\nhttps://github.com/simonwhitaker/github-fork-ribbon-css/\n\n[[Source code|https://github.com/Jermolene/TiddlyWiki5/blob/master/plugins/tiddlywiki/github-fork-ribbon]]\n" }, "$:/plugins/tiddlywiki/github-fork-ribbon/styles": { "title": "$:/plugins/tiddlywiki/github-fork-ribbon/styles", "tags": "[[$:/tags/Stylesheet]]", "text": "/* Left will inherit from right (so we don't need to duplicate code */\n.github-fork-ribbon {\n /* The right and left lasses determine the side we attach our banner to */\n position: absolute;\n\n /* Add a bit of padding to give some substance outside the \"stitching\" */\n padding: 2px 0;\n\n /* Set the base colour */\n background-color: #a00;\n\n /* Set a gradient: transparent black at the top to almost-transparent black at the bottom */\n background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.00)), to(rgba(0, 0, 0, 0.15)));\n background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.00), rgba(0, 0, 0, 0.15));\n background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.00), rgba(0, 0, 0, 0.15));\n background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0.00), rgba(0, 0, 0, 0.15));\n background-image: -ms-linear-gradient(top, rgba(0, 0, 0, 0.00), rgba(0, 0, 0, 0.15));\n background-image: linear-gradient(top, rgba(0, 0, 0, 0.00), rgba(0, 0, 0, 0.15));\n filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#000000', EndColorStr='#000000');\n\n /* Add a drop shadow */\n -webkit-box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.5);\n box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.5);\n\n z-index: 999;\n pointer-events: auto;\n}\n\n.github-fork-ribbon a, .github-fork-ribbon a.tc-tiddlylink,\n.github-fork-ribbon a:hover, .github-fork-ribbon a.tc-tiddlylink:hover {\n /* Set the font */\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 13px;\n font-weight: 700;\n color: white;\n\n /* Set the text properties */\n text-decoration: none;\n text-shadow: 0 -1px rgba(0,0,0,0.5);\n text-align: center;\n\n /* Set the geometry. If you fiddle with these you'll also need to tweak the top and right values in #github-fork-ribbon. */\n width: 200px;\n line-height: 20px;\n\n /* Set the layout properties */\n display: inline-block;\n padding: 2px 0;\n\n /* Add \"stitching\" effect */\n border-width: 1px 0;\n border-style: dotted;\n border-color: rgba(255,255,255,0.7);\n}\n\n.github-fork-ribbon-wrapper {\n width: 150px;\n height: 150px;\n position: absolute;\n overflow: hidden;\n top: 0;\n z-index: 999;\n pointer-events: none;\n}\n\n.github-fork-ribbon-wrapper.fixed {\n position: fixed;\n}\n\n.github-fork-ribbon-wrapper.left {\n left: 0;\n}\n\n.github-fork-ribbon-wrapper.right {\n right: 0;\n}\n\n.github-fork-ribbon-wrapper.left-bottom {\n position: fixed;\n top: inherit;\n bottom: 0;\n left: 0;\n}\n\n.github-fork-ribbon-wrapper.right-bottom {\n position: fixed;\n top: inherit;\n bottom: 0;\n right: 0;\n}\n\n.github-fork-ribbon-wrapper.right .github-fork-ribbon {\n top: 42px;\n right: -43px;\n\n /* Rotate the banner 45 degrees */\n -webkit-transform: rotate(45deg);\n -moz-transform: rotate(45deg);\n -o-transform: rotate(45deg);\n transform: rotate(45deg);\n}\n\n.github-fork-ribbon-wrapper.left .github-fork-ribbon {\n top: 42px;\n left: -43px;\n\n /* Rotate the banner -45 degrees */\n -webkit-transform: rotate(-45deg);\n -moz-transform: rotate(-45deg);\n -o-transform: rotate(-45deg);\n transform: rotate(-45deg);\n}\n\n\n.github-fork-ribbon-wrapper.left-bottom .github-fork-ribbon {\n top: 80px;\n left: -43px;\n\n /* Rotate the banner -45 degrees */\n -webkit-transform: rotate(45deg);\n -moz-transform: rotate(45deg);\n -o-transform: rotate(45deg);\n transform: rotate(45deg);\n}\n\n.github-fork-ribbon-wrapper.right-bottom .github-fork-ribbon {\n top: 80px;\n right: -43px;\n\n /* Rotate the banner -45 degrees */\n -webkit-transform: rotate(-45deg);\n -moz-transform: rotate(-45deg);\n -o-transform: rotate(-45deg);\n transform: rotate(-45deg);\n}\n" }, "$:/plugins/tiddlywiki/github-fork-ribbon/usage": { "title": "$:/plugins/tiddlywiki/github-fork-ribbon/usage", "text": "```\n<!-- TOP RIGHT RIBBON: START COPYING HERE -->\n<div class=\"github-fork-ribbon-wrapper right\"><div class=\"github-fork-ribbon\"><a href=\"https://github.com/simonwhitaker/github-fork-ribbon-css\">Fork me on ~GitHub</a></div>\n</div>\n<!-- TOP RIGHT RIBBON: END COPYING HERE -->\n\n<!-- TOP LEFT RIBBON: START COPYING HERE -->\n<div class=\"github-fork-ribbon-wrapper left\"><div class=\"github-fork-ribbon\"><a href=\"https://github.com/simonwhitaker/github-fork-ribbon-css\">Fork me on ~GitHub</a></div>\n</div>\n<!-- TOP LEFT RIBBON: END COPYING HERE -->\n\n\n<!-- BOTTOM RIGHT RIBBON: START COPYING HERE -->\n<div class=\"github-fork-ribbon-wrapper right-bottom\"><div class=\"github-fork-ribbon\"><a href=\"https://github.com/simonwhitaker/github-fork-ribbon-css\">Fork me on ~GitHub</a></div>\n</div>\n<!-- BOTTOM RIGHT RIBBON: END COPYING HERE -->\n\n<!-- BOTTOM LEFT RIBBON: START COPYING HERE -->\n<div class=\"github-fork-ribbon-wrapper left-bottom\"><div class=\"github-fork-ribbon\"><a href=\"https://github.com/simonwhitaker/github-fork-ribbon-css\">Fork me on ~GitHub</a></div>\n</div>\n<!-- BOTTOM LEFT RIBBON: END COPYING HERE -->\n```\n" } } }
{ "tiddlers": { "$:/plugins/tiddlywiki/googleanalytics/googleanalytics.js": { "text": "/*\\\ntitle: $:/plugins/tiddlywiki/googleanalytics/googleanalytics.js\ntype: application/javascript\nmodule-type: startup\n\nRuns Google Analytics with the account number in the tiddler `$:/GoogleAnalyticsAccount` and the domain name in `$:/GoogleAnalyticsDomain`\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\n// Export name and synchronous status\nexports.name = \"google-analytics\";\nexports.platforms = [\"browser\"];\nexports.synchronous = true;\n\nexports.startup = function() {\n\t// getting parameters\n\tvar GA_ACCOUNT = $tw.wiki.getTiddlerText(\"$:/GoogleAnalyticsAccount\",\"\").replace(/\\n/g,\"\"),\n\t\tGA_DOMAIN = $tw.wiki.getTiddlerText(\"$:/GoogleAnalyticsDomain\",\"\").replace(/\\n/g,\"\");\n\tif (GA_DOMAIN == \"\" || GA_DOMAIN == undefined) GA_DOMAIN = \"auto\";\n\n\t// using ga \"isogram\" function\n (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');\n\n ga('create', GA_ACCOUNT, GA_DOMAIN);\n ga('send', 'pageview');\n};\n\n})();\n", "title": "$:/plugins/tiddlywiki/googleanalytics/googleanalytics.js", "type": "application/javascript", "module-type": "startup" }, "$:/plugins/tiddlywiki/googleanalytics/readme": { "title": "$:/plugins/tiddlywiki/googleanalytics/readme", "text": "This plugin enables you to use Google Analytics to track access to your online TiddlyWiki document. Based upon the [[official Google code|https://developers.google.com/analytics/devguides/collection/analyticsjs]].\n\n[[Source code|https://github.com/Jermolene/TiddlyWiki5/blob/master/plugins/tiddlywiki/googleanalytics]]\n" }, "$:/plugins/tiddlywiki/googleanalytics/settings": { "title": "$:/plugins/tiddlywiki/googleanalytics/settings", "text": "You have only two value to set, only first is mandatory:\n\n# ''[[Google Analytics Account|$:/GoogleAnalyticsAccount]]'': (mandatory) a code of the form `UA-XXXXXX-XX` where X are digits<br/><$edit-text tiddler=\"$:/GoogleAnalyticsAccount\" default=\"\" tag=\"input\"/>\n\n# ''[[Google Analytics Domain|$:/GoogleAnalyticsDomain]]'': (optional) the website URL where the TiddlyWiki file is published. Defaults to `auto` if not set.<br/><$edit-text tiddler=\"$:/GoogleAnalyticsDomain\" default=\"\" tag=\"input\"/>\n" }, "$:/plugins/tiddlywiki/googleanalytics/usage": { "title": "$:/plugins/tiddlywiki/googleanalytics/usage", "text": "!! Create a Google Analytics account\n\nIf you don't already have an account:\n\n# Go to the Google Analytics website: http://www.google.com/analytics/\n# Click the ''Access Google Analytics'' button and follow instructions to set up your account\n# Enter the URL where the wiki is hosted\n# Note the Tracking ID for this domain of the form `UA-XXXXXX-XX`\n\n!! Install the plugin on your local copy of the TiddlyWiki\n\n# ''Backup your TiddlyWiki''. Just in case\n# Install the plugin via the plugin manager in control panel\n# Save the TiddlyWiki andrefresh the page to load the plugin\n# Go to [[$:/ControlPanel]] > Plugins tab and unfold the Google Analytics Plugin\n# Go to the //settings// tab and edit the parameters\n# Save the TiddlyWiki\n\n!! Upload the new version of your TiddlyWiki\n\n# Upload the saved TiddlyWiki to TiddlySpot, GitHub, GitLab or other web host\n# Return to your Google Analytics page to check that your site is being tracked\n" } } }
{ "tiddlers": { "$:/config/HighlightPlugin/TypeMappings/application/javascript": { "title": "$:/config/HighlightPlugin/TypeMappings/application/javascript", "text": "javascript" }, "$:/config/HighlightPlugin/TypeMappings/application/json": { "title": "$:/config/HighlightPlugin/TypeMappings/application/json", "text": "json" }, "$:/config/HighlightPlugin/TypeMappings/text/css": { "title": "$:/config/HighlightPlugin/TypeMappings/text/css", "text": "css" }, "$:/config/HighlightPlugin/TypeMappings/text/html": { "title": "$:/config/HighlightPlugin/TypeMappings/text/html", "text": "html" }, "$:/config/HighlightPlugin/TypeMappings/image/svg+xml": { "title": "$:/config/HighlightPlugin/TypeMappings/image/svg+xml", "text": "xml" }, "$:/config/HighlightPlugin/TypeMappings/text/x-markdown": { "title": "$:/config/HighlightPlugin/TypeMappings/text/x-markdown", "text": "markdown" }, "$:/plugins/tiddlywiki/highlight/highlight.js": { "text": "var hljs = require(\"$:/plugins/tiddlywiki/highlight/highlight.js\");\n!function(e){\"undefined\"!=typeof exports?e(exports):(window.hljs=e({}),\"function\"==typeof define&&define.amd&&define(\"hljs\",[],function(){return window.hljs}))}(function(e){function n(e){return e.replace(/&/gm,\"&\").replace(/</gm,\"<\").replace(/>/gm,\">\")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}function a(e){return/^(no-?highlight|plain|text)$/i.test(e)}function i(e){var n,t,r,i=e.className+\" \";if(i+=e.parentNode?e.parentNode.className:\"\",t=/\\blang(?:uage)?-([\\w-]+)\\b/i.exec(i))return w(t[1])?t[1]:\"no-highlight\";for(i=i.split(/\\s+/),n=0,r=i.length;r>n;n++)if(w(i[n])||a(i[n]))return i[n]}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3==i.nodeType?a+=i.nodeValue.length:1==i.nodeType&&(n.push({event:\"start\",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:\"stop\",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!=r[0].offset?e[0].offset<r[0].offset?e:r:\"start\"==r[0].event?e:r:e.length?e:r}function o(e){function r(e){return\" \"+e.nodeName+'=\"'+n(e.value)+'\"'}f+=\"<\"+t(e)+Array.prototype.map.call(e.attributes,r).join(\"\")+\">\"}function u(e){f+=\"</\"+t(e)+\">\"}function c(e){(\"start\"==e.event?o:u)(e.node)}for(var s=0,f=\"\",l=[];e.length||r.length;){var g=i();if(f+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g==e){l.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g==e&&g.length&&g[0].offset==s);l.reverse().forEach(o)}else\"start\"==g[0].event?l.push(g[0].node):l.pop(),c(g.splice(0,1)[0])}return f+n(a.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),\"m\"+(e.cI?\"i\":\"\")+(r?\"g\":\"\"))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(\" \").forEach(function(e){var t=e.split(\"|\");u[t[0]]=[n,t[1]?Number(t[1]):1]})};\"string\"==typeof a.k?c(\"keyword\",a.k):Object.keys(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\\b\\w+\\b/,!0),i&&(a.bK&&(a.b=\"\\\\b(\"+a.bK.split(\" \").join(\"|\")+\")\\\\b\"),a.b||(a.b=/\\B|\\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\\B|\\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||\"\",a.eW&&i.tE&&(a.tE+=(a.e?\"|\":\"\")+i.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push(\"self\"==e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var f=a.c.map(function(e){return e.bK?\"\\\\.?(\"+e.b+\")\\\\.?\":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=f.length?t(f.join(\"|\"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){for(var t=0;t<n.c.length;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function g(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function h(e,n,t,r){var a=r?\"\":E.classPrefix,i='<span class=\"'+a,o=t?\"\":\"</span>\";return i+=e+'\">',i+n+o}function p(){if(!L.k)return n(y);var e=\"\",t=0;L.lR.lastIndex=0;for(var r=L.lR.exec(y);r;){e+=n(y.substr(t,r.index-t));var a=g(L,r);a?(B+=a[1],e+=h(a[0],n(r[0]))):e+=n(r[0]),t=L.lR.lastIndex,r=L.lR.exec(y)}return e+n(y.substr(t))}function d(){var e=\"string\"==typeof L.sL;if(e&&!x[L.sL])return n(y);var t=e?f(L.sL,y,!0,M[L.sL]):l(y,L.sL.length?L.sL:void 0);return L.r>0&&(B+=t.r),e&&(M[L.sL]=t.top),h(t.language,t.value,!1,!0)}function b(){return void 0!==L.sL?d():p()}function v(e,t){var r=e.cN?h(e.cN,\"\",!0):\"\";e.rB?(k+=r,y=\"\"):e.eB?(k+=n(t)+r,y=\"\"):(k+=r,y=t),L=Object.create(e,{parent:{value:L}})}function m(e,t){if(y+=e,void 0===t)return k+=b(),0;var r=o(t,L);if(r)return k+=b(),v(r,t),r.rB?0:t.length;var a=u(L,t);if(a){var i=L;i.rE||i.eE||(y+=t),k+=b();do L.cN&&(k+=\"</span>\"),B+=L.r,L=L.parent;while(L!=a.parent);return i.eE&&(k+=n(t)),y=\"\",a.starts&&v(a.starts,\"\"),i.rE?0:t.length}if(c(t,L))throw new Error('Illegal lexeme \"'+t+'\" for mode \"'+(L.cN||\"<unnamed>\")+'\"');return y+=t,t.length||1}var N=w(e);if(!N)throw new Error('Unknown language: \"'+e+'\"');s(N);var R,L=i||N,M={},k=\"\";for(R=L;R!=N;R=R.parent)R.cN&&(k=h(R.cN,\"\",!0)+k);var y=\"\",B=0;try{for(var C,j,I=0;;){if(L.t.lastIndex=I,C=L.t.exec(t),!C)break;j=m(t.substr(I,C.index-I),C[0]),I=C.index+j}for(m(t.substr(I)),R=L;R.parent;R=R.parent)R.cN&&(k+=\"</span>\");return{r:B,value:k,language:e,top:L}}catch(O){if(-1!=O.message.indexOf(\"Illegal\"))return{r:0,value:n(t)};throw O}}function l(e,t){t=t||E.languages||Object.keys(x);var r={r:0,value:n(e)},a=r;return t.forEach(function(n){if(w(n)){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}}),a.language&&(r.second_best=a),r}function g(e){return E.tabReplace&&(e=e.replace(/^((<[^>]+>|\\t)+)/gm,function(e,n){return n.replace(/\\t/g,E.tabReplace)})),E.useBR&&(e=e.replace(/\\n/g,\"<br>\")),e}function h(e,n,t){var r=n?R[n]:t,a=[e.trim()];return e.match(/\\bhljs\\b/)||a.push(\"hljs\"),-1===e.indexOf(r)&&a.push(r),a.join(\" \").trim()}function p(e){var n=i(e);if(!a(n)){var t;E.useBR?(t=document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"div\"),t.innerHTML=e.innerHTML.replace(/\\n/g,\"\").replace(/<br[ \\/]*>/g,\"\\n\")):t=e;var r=t.textContent,o=n?f(n,r,!0):l(r),s=u(t);if(s.length){var p=document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"div\");p.innerHTML=o.value,o.value=c(s,u(p),r)}o.value=g(o.value),e.innerHTML=o.value,e.className=h(e.className,n,o.language),e.result={language:o.language,re:o.r},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.r})}}function d(e){E=o(E,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll(\"pre code\");Array.prototype.forEach.call(e,p)}}function v(){addEventListener(\"DOMContentLoaded\",b,!1),addEventListener(\"load\",b,!1)}function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e){R[e]=n})}function N(){return Object.keys(x)}function w(e){return e=e.toLowerCase(),x[e]||x[R[e]]}var E={classPrefix:\"hljs-\",tabReplace:null,useBR:!1,languages:void 0},x={},R={};return e.highlight=f,e.highlightAuto=l,e.fixMarkup=g,e.highlightBlock=p,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=w,e.inherit=o,e.IR=\"[a-zA-Z]\\\\w*\",e.UIR=\"[a-zA-Z_]\\\\w*\",e.NR=\"\\\\b\\\\d+(\\\\.\\\\d+)?\",e.CNR=\"(\\\\b0[xX][a-fA-F0-9]+|(\\\\b\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)([eE][-+]?\\\\d+)?)\",e.BNR=\"\\\\b(0b[01]+)\",e.RSR=\"!|!=|!==|%|%=|&|&&|&=|\\\\*|\\\\*=|\\\\+|\\\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\\\?|\\\\[|\\\\{|\\\\(|\\\\^|\\\\^=|\\\\||\\\\|=|\\\\|\\\\||~\",e.BE={b:\"\\\\\\\\[\\\\s\\\\S]\",r:0},e.ASM={cN:\"string\",b:\"'\",e:\"'\",i:\"\\\\n\",c:[e.BE]},e.QSM={cN:\"string\",b:'\"',e:'\"',i:\"\\\\n\",c:[e.BE]},e.PWM={b:/\\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\\b/},e.C=function(n,t,r){var a=e.inherit({cN:\"comment\",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:\"doctag\",b:\"(?:TODO|FIXME|NOTE|BUG|XXX):\",r:0}),a},e.CLCM=e.C(\"//\",\"$\"),e.CBCM=e.C(\"/\\\\*\",\"\\\\*/\"),e.HCM=e.C(\"#\",\"$\"),e.NM={cN:\"number\",b:e.NR,r:0},e.CNM={cN:\"number\",b:e.CNR,r:0},e.BNM={cN:\"number\",b:e.BNR,r:0},e.CSSNM={cN:\"number\",b:e.NR+\"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?\",r:0},e.RM={cN:\"regexp\",b:/\\//,e:/\\/[gimuy]*/,i:/\\n/,c:[e.BE,{b:/\\[/,e:/\\]/,r:0,c:[e.BE]}]},e.TM={cN:\"title\",b:e.IR,r:0},e.UTM={cN:\"title\",b:e.UIR,r:0},e});hljs.registerLanguage(\"markdown\",function(e){return{aliases:[\"md\",\"mkdown\",\"mkd\"],c:[{cN:\"header\",v:[{b:\"^#{1,6}\",e:\"$\"},{b:\"^.+?\\\\n[=-]{2,}$\"}]},{b:\"<\",e:\">\",sL:\"xml\",r:0},{cN:\"bullet\",b:\"^([*+-]|(\\\\d+\\\\.))\\\\s+\"},{cN:\"strong\",b:\"[*_]{2}.+?[*_]{2}\"},{cN:\"emphasis\",v:[{b:\"\\\\*.+?\\\\*\"},{b:\"_.+?_\",r:0}]},{cN:\"blockquote\",b:\"^>\\\\s+\",e:\"$\"},{cN:\"code\",v:[{b:\"`.+?`\"},{b:\"^( {4}|\t)\",e:\"$\",r:0}]},{cN:\"horizontal_rule\",b:\"^[-\\\\*]{3,}\",e:\"$\"},{b:\"\\\\[.+?\\\\][\\\\(\\\\[].*?[\\\\)\\\\]]\",rB:!0,c:[{cN:\"link_label\",b:\"\\\\[\",e:\"\\\\]\",eB:!0,rE:!0,r:0},{cN:\"link_url\",b:\"\\\\]\\\\(\",e:\"\\\\)\",eB:!0,eE:!0},{cN:\"link_reference\",b:\"\\\\]\\\\[\",e:\"\\\\]\",eB:!0,eE:!0}],r:10},{b:\"^\\\\[.+\\\\]:\",rB:!0,c:[{cN:\"link_reference\",b:\"\\\\[\",e:\"\\\\]:\",eB:!0,eE:!0,starts:{cN:\"link_url\",e:\"$\"}}]}]}});hljs.registerLanguage(\"ruby\",function(e){var c=\"[a-zA-Z_]\\\\w*[!?=]?|[-+~]\\\\@|<<|>>|=~|===?|<=>|[<>]=?|\\\\*\\\\*|[-/+%^&*~`|]|\\\\[\\\\]=?\",r=\"and false then defined module in return redo if BEGIN retry end for true self when next until do begin unless END rescue nil else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor\",b={cN:\"doctag\",b:\"@[A-Za-z]+\"},a={cN:\"value\",b:\"#<\",e:\">\"},n=[e.C(\"#\",\"$\",{c:[b]}),e.C(\"^\\\\=begin\",\"^\\\\=end\",{c:[b],r:10}),e.C(\"^__END__\",\"\\\\n$\")],s={cN:\"subst\",b:\"#\\\\{\",e:\"}\",k:r},t={cN:\"string\",c:[e.BE,s],v:[{b:/'/,e:/'/},{b:/\"/,e:/\"/},{b:/`/,e:/`/},{b:\"%[qQwWx]?\\\\(\",e:\"\\\\)\"},{b:\"%[qQwWx]?\\\\[\",e:\"\\\\]\"},{b:\"%[qQwWx]?{\",e:\"}\"},{b:\"%[qQwWx]?<\",e:\">\"},{b:\"%[qQwWx]?/\",e:\"/\"},{b:\"%[qQwWx]?%\",e:\"%\"},{b:\"%[qQwWx]?-\",e:\"-\"},{b:\"%[qQwWx]?\\\\|\",e:\"\\\\|\"},{b:/\\B\\?(\\\\\\d{1,3}|\\\\x[A-Fa-f0-9]{1,2}|\\\\u[A-Fa-f0-9]{4}|\\\\?\\S)\\b/}]},i={cN:\"params\",b:\"\\\\(\",e:\"\\\\)\",k:r},d=[t,a,{cN:\"class\",bK:\"class module\",e:\"$|;\",i:/=/,c:[e.inherit(e.TM,{b:\"[A-Za-z_]\\\\w*(::\\\\w+)*(\\\\?|\\\\!)?\"}),{cN:\"inheritance\",b:\"<\\\\s*\",c:[{cN:\"parent\",b:\"(\"+e.IR+\"::)?\"+e.IR}]}].concat(n)},{cN:\"function\",bK:\"def\",e:\"$|;\",c:[e.inherit(e.TM,{b:c}),i].concat(n)},{cN:\"constant\",b:\"(::)?(\\\\b[A-Z]\\\\w*(::)?)+\",r:0},{cN:\"symbol\",b:e.UIR+\"(\\\\!|\\\\?)?:\",r:0},{cN:\"symbol\",b:\":\",c:[t,{b:c}],r:0},{cN:\"number\",b:\"(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b\",r:0},{cN:\"variable\",b:\"(\\\\$\\\\W)|((\\\\$|\\\\@\\\\@?)(\\\\w+))\"},{b:\"(\"+e.RSR+\")\\\\s*\",c:[a,{cN:\"regexp\",c:[e.BE,s],i:/\\n/,v:[{b:\"/\",e:\"/[a-z]*\"},{b:\"%r{\",e:\"}[a-z]*\"},{b:\"%r\\\\(\",e:\"\\\\)[a-z]*\"},{b:\"%r!\",e:\"![a-z]*\"},{b:\"%r\\\\[\",e:\"\\\\][a-z]*\"}]}].concat(n),r:0}].concat(n);s.c=d,i.c=d;var o=\"[>?]>\",l=\"[\\\\w#]+\\\\(\\\\w+\\\\):\\\\d+:\\\\d+>\",u=\"(\\\\w+-)?\\\\d+\\\\.\\\\d+\\\\.\\\\d(p\\\\d+)?[^>]+>\",N=[{b:/^\\s*=>/,cN:\"status\",starts:{e:\"$\",c:d}},{cN:\"prompt\",b:\"^(\"+o+\"|\"+l+\"|\"+u+\")\",starts:{e:\"$\",c:d}}];return{aliases:[\"rb\",\"gemspec\",\"podspec\",\"thor\",\"irb\"],k:r,c:n.concat(N).concat(d)}});hljs.registerLanguage(\"makefile\",function(e){var a={cN:\"variable\",b:/\\$\\(/,e:/\\)/,c:[e.BE]};return{aliases:[\"mk\",\"mak\"],c:[e.HCM,{b:/^\\w+\\s*\\W*=/,rB:!0,r:0,starts:{cN:\"constant\",e:/\\s*\\W*=/,eE:!0,starts:{e:/$/,r:0,c:[a]}}},{cN:\"title\",b:/^[\\w]+:\\s*$/},{cN:\"phony\",b:/^\\.PHONY:/,e:/$/,k:\".PHONY\",l:/[\\.\\w]+/},{b:/^\\t+/,e:/$/,r:0,c:[e.QSM,a]}]}});hljs.registerLanguage(\"json\",function(e){var t={literal:\"true false null\"},i=[e.QSM,e.CNM],l={cN:\"value\",e:\",\",eW:!0,eE:!0,c:i,k:t},c={b:\"{\",e:\"}\",c:[{cN:\"attribute\",b:'\\\\s*\"',e:'\"\\\\s*:\\\\s*',eB:!0,eE:!0,c:[e.BE],i:\"\\\\n\",starts:l}],i:\"\\\\S\"},n={b:\"\\\\[\",e:\"\\\\]\",c:[e.inherit(l,{cN:null})],i:\"\\\\S\"};return i.splice(i.length,0,c,n),{c:i,k:t,i:\"\\\\S\"}});hljs.registerLanguage(\"xml\",function(t){var s=\"[A-Za-z0-9\\\\._:-]+\",c={b:/<\\?(php)?(?!\\w)/,e:/\\?>/,sL:\"php\"},e={eW:!0,i:/</,r:0,c:[c,{cN:\"attribute\",b:s,r:0},{b:\"=\",r:0,c:[{cN:\"value\",c:[c],v:[{b:/\"/,e:/\"/},{b:/'/,e:/'/},{b:/[^\\s\\/>]+/}]}]}]};return{aliases:[\"html\",\"xhtml\",\"rss\",\"atom\",\"xsl\",\"plist\"],cI:!0,c:[{cN:\"doctype\",b:\"<!DOCTYPE\",e:\">\",r:10,c:[{b:\"\\\\[\",e:\"\\\\]\"}]},t.C(\"<!--\",\"-->\",{r:10}),{cN:\"cdata\",b:\"<\\\\!\\\\[CDATA\\\\[\",e:\"\\\\]\\\\]>\",r:10},{cN:\"tag\",b:\"<style(?=\\\\s|>|$)\",e:\">\",k:{title:\"style\"},c:[e],starts:{e:\"</style>\",rE:!0,sL:\"css\"}},{cN:\"tag\",b:\"<script(?=\\\\s|>|$)\",e:\">\",k:{title:\"script\"},c:[e],starts:{e:\"</script>\",rE:!0,sL:[\"actionscript\",\"javascript\",\"handlebars\"]}},c,{cN:\"pi\",b:/<\\?\\w+/,e:/\\?>/,r:10},{cN:\"tag\",b:\"</?\",e:\"/?>\",c:[{cN:\"title\",b:/[^ \\/><\\n\\t]+/,r:0},e]}]}});hljs.registerLanguage(\"css\",function(e){var c=\"[a-zA-Z-][a-zA-Z0-9_-]*\",a={cN:\"function\",b:c+\"\\\\(\",rB:!0,eE:!0,e:\"\\\\(\"},r={cN:\"rule\",b:/[A-Z\\_\\.\\-]+\\s*:/,rB:!0,e:\";\",eW:!0,c:[{cN:\"attribute\",b:/\\S/,e:\":\",eE:!0,starts:{cN:\"value\",eW:!0,eE:!0,c:[a,e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:\"hexcolor\",b:\"#[0-9A-Fa-f]+\"},{cN:\"important\",b:\"!important\"}]}}]};return{cI:!0,i:/[=\\/|'\\$]/,c:[e.CBCM,r,{cN:\"id\",b:/\\#[A-Za-z0-9_-]+/},{cN:\"class\",b:/\\.[A-Za-z0-9_-]+/},{cN:\"attr_selector\",b:/\\[/,e:/\\]/,i:\"$\"},{cN:\"pseudo\",b:/:(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\"']+/},{cN:\"at_rule\",b:\"@(font-face|page)\",l:\"[a-z-]+\",k:\"font-face page\"},{cN:\"at_rule\",b:\"@\",e:\"[{;]\",c:[{cN:\"keyword\",b:/\\S+/},{b:/\\s/,eW:!0,eE:!0,r:0,c:[a,e.ASM,e.QSM,e.CSSNM]}]},{cN:\"tag\",b:c,r:0},{cN:\"rules\",b:\"{\",e:\"}\",i:/\\S/,c:[e.CBCM,r]}]}});hljs.registerLanguage(\"perl\",function(e){var t=\"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when\",r={cN:\"subst\",b:\"[$@]\\\\{\",e:\"\\\\}\",k:t},s={b:\"->{\",e:\"}\"},n={cN:\"variable\",v:[{b:/\\$\\d/},{b:/[\\$%@](\\^\\w\\b|#\\w+(::\\w+)*|{\\w+}|\\w+(::\\w*)*)/},{b:/[\\$%@][^\\s\\w{]/,r:0}]},o=[e.BE,r,n],i=[n,e.HCM,e.C(\"^\\\\=\\\\w\",\"\\\\=cut\",{eW:!0}),s,{cN:\"string\",c:o,v:[{b:\"q[qwxr]?\\\\s*\\\\(\",e:\"\\\\)\",r:5},{b:\"q[qwxr]?\\\\s*\\\\[\",e:\"\\\\]\",r:5},{b:\"q[qwxr]?\\\\s*\\\\{\",e:\"\\\\}\",r:5},{b:\"q[qwxr]?\\\\s*\\\\|\",e:\"\\\\|\",r:5},{b:\"q[qwxr]?\\\\s*\\\\<\",e:\"\\\\>\",r:5},{b:\"qw\\\\s+q\",e:\"q\",r:5},{b:\"'\",e:\"'\",c:[e.BE]},{b:'\"',e:'\"'},{b:\"`\",e:\"`\",c:[e.BE]},{b:\"{\\\\w+}\",c:[],r:0},{b:\"-?\\\\w+\\\\s*\\\\=\\\\>\",c:[],r:0}]},{cN:\"number\",b:\"(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b\",r:0},{b:\"(\\\\/\\\\/|\"+e.RSR+\"|\\\\b(split|return|print|reverse|grep)\\\\b)\\\\s*\",k:\"split return print reverse grep\",r:0,c:[e.HCM,{cN:\"regexp\",b:\"(s|tr|y)/(\\\\\\\\.|[^/])*/(\\\\\\\\.|[^/])*/[a-z]*\",r:10},{cN:\"regexp\",b:\"(m|qr)?/\",e:\"/[a-z]*\",c:[e.BE],r:0}]},{cN:\"sub\",bK:\"sub\",e:\"(\\\\s*\\\\(.*?\\\\))?[;{]\",r:5},{cN:\"operator\",b:\"-\\\\w\\\\b\",r:0},{b:\"^__DATA__$\",e:\"^__END__$\",sL:\"mojolicious\",c:[{b:\"^@@.*\",e:\"$\",cN:\"comment\"}]}];return r.c=i,s.c=i,{aliases:[\"pl\"],k:t,c:i}});hljs.registerLanguage(\"cs\",function(e){var r=\"abstract as base bool break byte case catch char checked const continue decimal dynamic default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long null when object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this true try typeof uint ulong unchecked unsafe ushort using virtual volatile void while async protected public private internal ascending descending from get group into join let orderby partial select set value var where yield\",t=e.IR+\"(<\"+e.IR+\">)?\";return{aliases:[\"csharp\"],k:r,i:/::/,c:[e.C(\"///\",\"$\",{rB:!0,c:[{cN:\"xmlDocTag\",v:[{b:\"///\",r:0},{b:\"<!--|-->\"},{b:\"</?\",e:\">\"}]}]}),e.CLCM,e.CBCM,{cN:\"preprocessor\",b:\"#\",e:\"$\",k:\"if else elif endif define undef warning error line region endregion pragma checksum\"},{cN:\"string\",b:'@\"',e:'\"',c:[{b:'\"\"'}]},e.ASM,e.QSM,e.CNM,{bK:\"class interface\",e:/[{;=]/,i:/[^\\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:\"namespace\",e:/[{;=]/,i:/[^\\s:]/,c:[{cN:\"title\",b:\"[a-zA-Z](\\\\.?\\\\w)*\",r:0},e.CLCM,e.CBCM]},{bK:\"new return throw await\",r:0},{cN:\"function\",b:\"(\"+t+\"\\\\s+)+\"+e.IR+\"\\\\s*\\\\(\",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:e.IR+\"\\\\s*\\\\(\",rB:!0,c:[e.TM],r:0},{cN:\"params\",b:/\\(/,e:/\\)/,eB:!0,eE:!0,k:r,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage(\"apache\",function(e){var r={cN:\"number\",b:\"[\\\\$%]\\\\d+\"};return{aliases:[\"apacheconf\"],cI:!0,c:[e.HCM,{cN:\"tag\",b:\"</?\",e:\">\"},{cN:\"keyword\",b:/\\w+/,r:0,k:{common:\"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername\"},starts:{e:/$/,r:0,k:{literal:\"on off all\"},c:[{cN:\"sqbracket\",b:\"\\\\s\\\\[\",e:\"\\\\]$\"},{cN:\"cbracket\",b:\"[\\\\$%]\\\\{\",e:\"\\\\}\",c:[\"self\",r]},r,e.QSM]}}],i:/\\S/}});hljs.registerLanguage(\"http\",function(t){return{aliases:[\"https\"],i:\"\\\\S\",c:[{cN:\"status\",b:\"^HTTP/[0-9\\\\.]+\",e:\"$\",c:[{cN:\"number\",b:\"\\\\b\\\\d{3}\\\\b\"}]},{cN:\"request\",b:\"^[A-Z]+ (.*?) HTTP/[0-9\\\\.]+$\",rB:!0,e:\"$\",c:[{cN:\"string\",b:\" \",e:\" \",eB:!0,eE:!0}]},{cN:\"attribute\",b:\"^\\\\w\",e:\": \",eE:!0,i:\"\\\\n|\\\\s|=\",starts:{cN:\"string\",e:\"$\"}},{b:\"\\\\n\\\\n\",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage(\"objectivec\",function(e){var t={cN:\"built_in\",b:\"(AV|CA|CF|CG|CI|MK|MP|NS|UI)\\\\w+\"},i={keyword:\"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required\",literal:\"false true FALSE TRUE nil YES NO NULL\",built_in:\"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once\"},o=/[a-zA-Z@][a-zA-Z0-9_]*/,n=\"@interface @class @protocol @implementation\";return{aliases:[\"mm\",\"objc\",\"obj-c\"],k:i,l:o,i:\"</\",c:[t,e.CLCM,e.CBCM,e.CNM,e.QSM,{cN:\"string\",v:[{b:'@\"',e:'\"',i:\"\\\\n\",c:[e.BE]},{b:\"'\",e:\"[^\\\\\\\\]'\",i:\"[^\\\\\\\\][^']\"}]},{cN:\"preprocessor\",b:\"#\",e:\"$\",c:[{cN:\"title\",v:[{b:'\"',e:'\"'},{b:\"<\",e:\">\"}]}]},{cN:\"class\",b:\"(\"+n.split(\" \").join(\"|\")+\")\\\\b\",e:\"({|$)\",eE:!0,k:n,l:o,c:[e.UTM]},{cN:\"variable\",b:\"\\\\.\"+e.UIR,r:0}]}});hljs.registerLanguage(\"python\",function(e){var r={cN:\"prompt\",b:/^(>>>|\\.\\.\\.) /},b={cN:\"string\",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[r],r:10},{b:/(u|b)?r?\"\"\"/,e:/\"\"\"/,c:[r],r:10},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)\"/,e:/\"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)\"/,e:/\"/},e.ASM,e.QSM]},a={cN:\"number\",r:0,v:[{b:e.BNR+\"[lLjJ]?\"},{b:\"\\\\b(0o[0-7]+)[lLjJ]?\"},{b:e.CNR+\"[lLjJ]?\"}]},l={cN:\"params\",b:/\\(/,e:/\\)/,c:[\"self\",r,a,b]};return{aliases:[\"py\",\"gyp\"],k:{keyword:\"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False\",built_in:\"Ellipsis NotImplemented\"},i:/(<\\/|->|\\?)/,c:[r,a,b,e.HCM,{v:[{cN:\"function\",bK:\"def\",r:10},{cN:\"class\",bK:\"class\"}],e:/:/,i:/[${=;\\n,]/,c:[e.UTM,l]},{cN:\"decorator\",b:/^[\\t ]*@/,e:/$/},{b:/\\b(print|exec)\\(/}]}});hljs.registerLanguage(\"java\",function(e){var a=e.UIR+\"(<\"+e.UIR+\">)?\",t=\"false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private\",c=\"\\\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+)(\\\\.([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+))?|\\\\.([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+))([eE][-+]?\\\\d+)?)[lLfF]?\",r={cN:\"number\",b:c,r:0};return{aliases:[\"jsp\"],k:t,i:/<\\/|#/,c:[e.C(\"/\\\\*\\\\*\",\"\\\\*/\",{r:0,c:[{cN:\"doctag\",b:\"@[A-Za-z]+\"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:\"class\",bK:\"class interface\",e:/[{;=]/,eE:!0,k:\"class interface\",i:/[:\"\\[\\]]/,c:[{bK:\"extends implements\"},e.UTM]},{bK:\"new throw return else\",r:0},{cN:\"function\",b:\"(\"+a+\"\\\\s+)+\"+e.UIR+\"\\\\s*\\\\(\",rB:!0,e:/[{;=]/,eE:!0,k:t,c:[{b:e.UIR+\"\\\\s*\\\\(\",rB:!0,r:0,c:[e.UTM]},{cN:\"params\",b:/\\(/,e:/\\)/,k:t,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},r,{cN:\"annotation\",b:\"@[A-Za-z]+\"}]}});hljs.registerLanguage(\"bash\",function(e){var t={cN:\"variable\",v:[{b:/\\$[\\w\\d#@][\\w\\d_]*/},{b:/\\$\\{(.*?)}/}]},s={cN:\"string\",b:/\"/,e:/\"/,c:[e.BE,t,{cN:\"variable\",b:/\\$\\(/,e:/\\)/,c:[e.BE]}]},a={cN:\"string\",b:/'/,e:/'/};return{aliases:[\"sh\",\"zsh\"],l:/-?[a-z\\.]+/,k:{keyword:\"if then else elif fi for while in do done case esac function\",literal:\"true false\",built_in:\"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp\",operator:\"-ne -eq -lt -gt -f -d -e -s -l -a\"},c:[{cN:\"shebang\",b:/^#![^\\n]+sh\\s*$/,r:10},{cN:\"function\",b:/\\w[\\w\\d_]*\\s*\\(\\s*\\)\\s*\\{/,rB:!0,c:[e.inherit(e.TM,{b:/\\w[\\w\\d_]*/})],r:0},e.HCM,e.NM,s,a,t]}});hljs.registerLanguage(\"sql\",function(e){var t=e.C(\"--\",\"$\");return{cI:!0,i:/[<>{}*]/,c:[{cN:\"operator\",bK:\"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke\",e:/;/,eW:!0,k:{keyword:\"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes c cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle d data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration e each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract f failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function g general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http i id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists k keep keep_duplicates key keys kill l language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim m main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex n name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding p package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime t table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek\",literal:\"true false null\",built_in:\"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void\"},c:[{cN:\"string\",b:\"'\",e:\"'\",c:[e.BE,{b:\"''\"}]},{cN:\"string\",b:'\"',e:'\"',c:[e.BE,{b:'\"\"'}]},{cN:\"string\",b:\"`\",e:\"`\",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}});hljs.registerLanguage(\"nginx\",function(e){var r={cN:\"variable\",v:[{b:/\\$\\d+/},{b:/\\$\\{/,e:/}/},{b:\"[\\\\$\\\\@]\"+e.UIR}]},b={eW:!0,l:\"[a-z/_]+\",k:{built_in:\"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll\"},r:0,i:\"=>\",c:[e.HCM,{cN:\"string\",c:[e.BE,r],v:[{b:/\"/,e:/\"/},{b:/'/,e:/'/}]},{cN:\"url\",b:\"([a-z]+):/\",e:\"\\\\s\",eW:!0,eE:!0,c:[r]},{cN:\"regexp\",c:[e.BE,r],v:[{b:\"\\\\s\\\\^\",e:\"\\\\s|{|;\",rE:!0},{b:\"~\\\\*?\\\\s+\",e:\"\\\\s|{|;\",rE:!0},{b:\"\\\\*(\\\\.[a-z\\\\-]+)+\"},{b:\"([a-z\\\\-]+\\\\.)+\\\\*\"}]},{cN:\"number\",b:\"\\\\b\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}(:\\\\d{1,5})?\\\\b\"},{cN:\"number\",b:\"\\\\b\\\\d+[kKmMgGdshdwy]*\\\\b\",r:0},r]};return{aliases:[\"nginxconf\"],c:[e.HCM,{b:e.UIR+\"\\\\s\",e:\";|{\",rB:!0,c:[{cN:\"title\",b:e.UIR,starts:b}],r:0}],i:\"[^\\\\s\\\\}]\"}});hljs.registerLanguage(\"cpp\",function(t){var e={cN:\"keyword\",b:\"\\\\b[a-z\\\\d_]*_t\\\\b\"},r={cN:\"string\",v:[t.inherit(t.QSM,{b:'((u8?|U)|L)?\"'}),{b:'(u8?|U)?R\"',e:'\"',c:[t.BE]},{b:\"'\\\\\\\\?.\",e:\"'\",i:\".\"}]},s={cN:\"number\",v:[{b:\"\\\\b(\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)(u|U|l|L|ul|UL|f|F)\"},{b:t.CNR}]},i={cN:\"preprocessor\",b:\"#\",e:\"$\",k:\"if else elif endif define undef warning error line pragma ifdef ifndef\",c:[{b:/\\\\\\n/,r:0},{bK:\"include\",e:\"$\",c:[r,{cN:\"string\",b:\"<\",e:\">\",i:\"\\\\n\"}]},r,s,t.CLCM,t.CBCM]},a=t.IR+\"\\\\s*\\\\(\",c={keyword:\"int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong\",built_in:\"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf\",literal:\"true false nullptr NULL\"};return{aliases:[\"c\",\"cc\",\"h\",\"c++\",\"h++\",\"hpp\"],k:c,i:\"</\",c:[e,t.CLCM,t.CBCM,s,r,i,{b:\"\\\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\\\s*<\",e:\">\",k:c,c:[\"self\",e]},{b:t.IR+\"::\",k:c},{bK:\"new throw return else\",r:0},{cN:\"function\",b:\"(\"+t.IR+\"[\\\\*&\\\\s]+)+\"+a,rB:!0,e:/[{;=]/,eE:!0,k:c,i:/[^\\w\\s\\*&]/,c:[{b:a,rB:!0,c:[t.TM],r:0},{cN:\"params\",b:/\\(/,e:/\\)/,k:c,r:0,c:[t.CLCM,t.CBCM,r,s]},t.CLCM,t.CBCM,i]}]}});hljs.registerLanguage(\"php\",function(e){var c={cN:\"variable\",b:\"\\\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*\"},a={cN:\"preprocessor\",b:/<\\?(php)?|\\?>/},i={cN:\"string\",c:[e.BE,a],v:[{b:'b\"',e:'\"'},{b:\"b'\",e:\"'\"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},t={v:[e.BNM,e.CNM]};return{aliases:[\"php3\",\"php4\",\"php5\",\"php6\"],cI:!0,k:\"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally\",c:[e.CLCM,e.HCM,e.C(\"/\\\\*\",\"\\\\*/\",{c:[{cN:\"doctag\",b:\"@[A-Za-z]+\"},a]}),e.C(\"__halt_compiler.+?;\",!1,{eW:!0,k:\"__halt_compiler\",l:e.UIR}),{cN:\"string\",b:/<<<['\"]?\\w+['\"]?$/,e:/^\\w+;?$/,c:[e.BE,{cN:\"subst\",v:[{b:/\\$\\w+/},{b:/\\{\\$/,e:/\\}/}]}]},a,c,{b:/(::|->)+[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*/},{cN:\"function\",bK:\"function\",e:/[;{]/,eE:!0,i:\"\\\\$|\\\\[|%\",c:[e.UTM,{cN:\"params\",b:\"\\\\(\",e:\"\\\\)\",c:[\"self\",c,e.CBCM,i,t]}]},{cN:\"class\",bK:\"class interface\",e:\"{\",eE:!0,i:/[:\\(\\$\"]/,c:[{bK:\"extends implements\"},e.UTM]},{bK:\"namespace\",e:\";\",i:/[\\.']/,c:[e.UTM]},{bK:\"use\",e:\";\",c:[e.UTM]},{b:\"=>\"},i,t]}});hljs.registerLanguage(\"coffeescript\",function(e){var c={keyword:\"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super then unless until loop of by when and or is isnt not\",literal:\"true false null undefined yes no on off\",built_in:\"npm require console print module global window document\"},n=\"[A-Za-z$_][0-9A-Za-z$_]*\",r={cN:\"subst\",b:/#\\{/,e:/}/,k:c},t=[e.BNM,e.inherit(e.CNM,{starts:{e:\"(\\\\s*/)?\",r:0}}),{cN:\"string\",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/\"\"\"/,e:/\"\"\"/,c:[e.BE,r]},{b:/\"/,e:/\"/,c:[e.BE,r]}]},{cN:\"regexp\",v:[{b:\"///\",e:\"///\",c:[r,e.HCM]},{b:\"//[gim]*\",r:0},{b:/\\/(?![ *])(\\\\\\/|.)*?\\/[gim]*(?=\\W|$)/}]},{cN:\"property\",b:\"@\"+n},{b:\"`\",e:\"`\",eB:!0,eE:!0,sL:\"javascript\"}];r.c=t;var s=e.inherit(e.TM,{b:n}),i=\"(\\\\(.*\\\\))?\\\\s*\\\\B[-=]>\",o={cN:\"params\",b:\"\\\\([^\\\\(]\",rB:!0,c:[{b:/\\(/,e:/\\)/,k:c,c:[\"self\"].concat(t)}]};return{aliases:[\"coffee\",\"cson\",\"iced\"],k:c,i:/\\/\\*/,c:t.concat([e.C(\"###\",\"###\"),e.HCM,{cN:\"function\",b:\"^\\\\s*\"+n+\"\\\\s*=\\\\s*\"+i,e:\"[-=]>\",rB:!0,c:[s,o]},{b:/[:\\(,=]\\s*/,r:0,c:[{cN:\"function\",b:i,e:\"[-=]>\",rB:!0,c:[o]}]},{cN:\"class\",bK:\"class\",e:\"$\",i:/[:=\"\\[\\]]/,c:[{bK:\"extends\",eW:!0,i:/[:=\"\\[\\]]/,c:[s]},s]},{cN:\"attribute\",b:n+\":\",e:\":\",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage(\"javascript\",function(e){return{aliases:[\"js\"],k:{keyword:\"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await\",literal:\"true false null undefined NaN Infinity\",built_in:\"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise\"},c:[{cN:\"pi\",r:10,b:/^\\s*['\"]use (strict|asm)['\"]/},e.ASM,e.QSM,{cN:\"string\",b:\"`\",e:\"`\",c:[e.BE,{cN:\"subst\",b:\"\\\\$\\\\{\",e:\"\\\\}\"}]},e.CLCM,e.CBCM,{cN:\"number\",v:[{b:\"\\\\b(0[bB][01]+)\"},{b:\"\\\\b(0[oO][0-7]+)\"},{b:e.CNR}],r:0},{b:\"(\"+e.RSR+\"|\\\\b(case|return|throw)\\\\b)\\\\s*\",k:\"return throw case\",c:[e.CLCM,e.CBCM,e.RM,{b:/</,e:/>\\s*[);\\]]/,r:0,sL:\"xml\"}],r:0},{cN:\"function\",bK:\"function\",e:/\\{/,eE:!0,c:[e.inherit(e.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:\"params\",b:/\\(/,e:/\\)/,eB:!0,eE:!0,c:[e.CLCM,e.CBCM]}],i:/\\[|%/},{b:/\\$[(.]/},{b:\"\\\\.\"+e.IR,r:0},{bK:\"import\",e:\"[;$]\",k:\"import from as\",c:[e.ASM,e.QSM]},{cN:\"class\",bK:\"class\",e:/[{;=]/,eE:!0,i:/[:\"\\[\\]]/,c:[{bK:\"extends\"},e.UTM]}],i:/#/}});hljs.registerLanguage(\"ini\",function(e){var c={cN:\"string\",c:[e.BE],v:[{b:\"'''\",e:\"'''\",r:10},{b:'\"\"\"',e:'\"\"\"',r:10},{b:'\"',e:'\"'},{b:\"'\",e:\"'\"}]};return{aliases:[\"toml\"],cI:!0,i:/\\S/,c:[e.C(\";\",\"$\"),e.HCM,{cN:\"title\",b:/^\\s*\\[+/,e:/\\]+/},{cN:\"setting\",b:/^[a-z0-9\\[\\]_-]+\\s*=\\s*/,e:\"$\",c:[{cN:\"value\",eW:!0,k:\"on off true false yes no\",c:[{cN:\"variable\",v:[{b:/\\$[\\w\\d\"][\\w\\d_]*/},{b:/\\$\\{(.*?)}/}]},c,{cN:\"number\",b:/([\\+\\-]+)?[\\d]+_[\\d_]+/},e.NM],r:0}]}]}});hljs.registerLanguage(\"diff\",function(e){return{aliases:[\"patch\"],c:[{cN:\"chunk\",r:10,v:[{b:/^@@ +\\-\\d+,\\d+ +\\+\\d+,\\d+ +@@$/},{b:/^\\*\\*\\* +\\d+,\\d+ +\\*\\*\\*\\*$/},{b:/^\\-\\-\\- +\\d+,\\d+ +\\-\\-\\-\\-$/}]},{cN:\"header\",v:[{b:/Index: /,e:/$/},{b:/=====/,e:/=====$/},{b:/^\\-\\-\\-/,e:/$/},{b:/^\\*{3} /,e:/$/},{b:/^\\+\\+\\+/,e:/$/},{b:/\\*{5}/,e:/\\*{5}$/}]},{cN:\"addition\",b:\"^\\\\+\",e:\"$\"},{cN:\"deletion\",b:\"^\\\\-\",e:\"$\"},{cN:\"change\",b:\"^\\\\!\",e:\"$\"}]}});\nexports.hljs = hljs;\n", "type": "application/javascript", "title": "$:/plugins/tiddlywiki/highlight/highlight.js", "module-type": "library" }, "$:/plugins/tiddlywiki/highlight/highlight.css": { "text": "/*\n\nOriginal style from softwaremaniacs.org (c) Ivan Sagalaev <Maniac@SoftwareManiacs.Org>\n\n*/\n\n.hljs {\n display: block;\n overflow-x: auto;\n padding: 0.5em;\n background: #f0f0f0;\n -webkit-text-size-adjust: none;\n}\n\n.hljs,\n.hljs-subst,\n.hljs-tag .hljs-title,\n.nginx .hljs-title {\n color: black;\n}\n\n.hljs-string,\n.hljs-title,\n.hljs-constant,\n.hljs-parent,\n.hljs-tag .hljs-value,\n.hljs-rule .hljs-value,\n.hljs-preprocessor,\n.hljs-pragma,\n.hljs-name,\n.haml .hljs-symbol,\n.ruby .hljs-symbol,\n.ruby .hljs-symbol .hljs-string,\n.hljs-template_tag,\n.django .hljs-variable,\n.smalltalk .hljs-class,\n.hljs-addition,\n.hljs-flow,\n.hljs-stream,\n.bash .hljs-variable,\n.pf .hljs-variable,\n.apache .hljs-tag,\n.apache .hljs-cbracket,\n.tex .hljs-command,\n.tex .hljs-special,\n.erlang_repl .hljs-function_or_atom,\n.asciidoc .hljs-header,\n.markdown .hljs-header,\n.coffeescript .hljs-attribute,\n.tp .hljs-variable {\n color: #800;\n}\n\n.smartquote,\n.hljs-comment,\n.hljs-annotation,\n.diff .hljs-header,\n.hljs-chunk,\n.asciidoc .hljs-blockquote,\n.markdown .hljs-blockquote {\n color: #888;\n}\n\n.hljs-number,\n.hljs-date,\n.hljs-regexp,\n.hljs-literal,\n.hljs-hexcolor,\n.smalltalk .hljs-symbol,\n.smalltalk .hljs-char,\n.go .hljs-constant,\n.hljs-change,\n.lasso .hljs-variable,\n.makefile .hljs-variable,\n.asciidoc .hljs-bullet,\n.markdown .hljs-bullet,\n.asciidoc .hljs-link_url,\n.markdown .hljs-link_url {\n color: #080;\n}\n\n.hljs-label,\n.ruby .hljs-string,\n.hljs-decorator,\n.hljs-filter .hljs-argument,\n.hljs-localvars,\n.hljs-array,\n.hljs-attr_selector,\n.hljs-important,\n.hljs-pseudo,\n.hljs-pi,\n.haml .hljs-bullet,\n.hljs-doctype,\n.hljs-deletion,\n.hljs-envvar,\n.hljs-shebang,\n.apache .hljs-sqbracket,\n.nginx .hljs-built_in,\n.tex .hljs-formula,\n.erlang_repl .hljs-reserved,\n.hljs-prompt,\n.asciidoc .hljs-link_label,\n.markdown .hljs-link_label,\n.vhdl .hljs-attribute,\n.clojure .hljs-attribute,\n.asciidoc .hljs-attribute,\n.lasso .hljs-attribute,\n.coffeescript .hljs-property,\n.hljs-phony {\n color: #88f;\n}\n\n.hljs-keyword,\n.hljs-id,\n.hljs-title,\n.hljs-built_in,\n.css .hljs-tag,\n.hljs-doctag,\n.smalltalk .hljs-class,\n.hljs-winutils,\n.bash .hljs-variable,\n.pf .hljs-variable,\n.apache .hljs-tag,\n.hljs-type,\n.hljs-typename,\n.tex .hljs-command,\n.asciidoc .hljs-strong,\n.markdown .hljs-strong,\n.hljs-request,\n.hljs-status,\n.tp .hljs-data,\n.tp .hljs-io {\n font-weight: bold;\n}\n\n.asciidoc .hljs-emphasis,\n.markdown .hljs-emphasis,\n.tp .hljs-units {\n font-style: italic;\n}\n\n.nginx .hljs-built_in {\n font-weight: normal;\n}\n\n.coffeescript .javascript,\n.javascript .xml,\n.lasso .markup,\n.tex .hljs-formula,\n.xml .javascript,\n.xml .vbscript,\n.xml .css,\n.xml .hljs-cdata {\n opacity: 0.5;\n}\n", "type": "text/css", "title": "$:/plugins/tiddlywiki/highlight/highlight.css", "tags": "[[$:/tags/Stylesheet]]" }, "$:/plugins/tiddlywiki/highlight/highlightblock.js": { "text": "/*\\\ntitle: $:/plugins/tiddlywiki/highlight/highlightblock.js\ntype: application/javascript\nmodule-type: widget\n\nWraps up the fenced code blocks parser for highlight and use in TiddlyWiki5\n\n\\*/\n(function() {\n\n/*jslint node: true, browser: true */\n/*global $tw: false */\n\"use strict\";\n\nvar TYPE_MAPPINGS_BASE = \"$:/config/HighlightPlugin/TypeMappings/\";\n\nvar CodeBlockWidget = require(\"$:/core/modules/widgets/codeblock.js\").codeblock;\n\nvar hljs = require(\"$:/plugins/tiddlywiki/highlight/highlight.js\");\n\nhljs.configure({tabReplace: \" \"});\t\n\nCodeBlockWidget.prototype.postRender = function() {\n\tvar domNode = this.domNodes[0],\n\t\tlanguage = this.language,\n\t\ttiddler = this.wiki.getTiddler(TYPE_MAPPINGS_BASE + language);\n\tif(tiddler) {\n\t\tlanguage = tiddler.fields.text || \"\";\n\t}\n\tif(language && hljs.listLanguages().indexOf(language) !== -1) {\n\t\tdomNode.className = language.toLowerCase() + \" hljs\";\n\t\tif($tw.browser && !domNode.isTiddlyWikiFakeDom) {\n\t\t\thljs.highlightBlock(domNode);\t\t\t\n\t\t} else {\n\t\t\tvar text = domNode.textContent;\n\t\t\tdomNode.children[0].innerHTML = hljs.fixMarkup(hljs.highlight(language,text).value);\n\t\t\t// If we're using the fakedom then specially save the original raw text\n\t\t\tif(domNode.isTiddlyWikiFakeDom) {\n\t\t\t\tdomNode.children[0].textInnerHTML = text;\n\t\t\t}\n\t\t}\n\t}\t\n};\n\n})();\n", "title": "$:/plugins/tiddlywiki/highlight/highlightblock.js", "type": "application/javascript", "module-type": "widget" }, "$:/plugins/tiddlywiki/highlight/license": { "title": "$:/plugins/tiddlywiki/highlight/license", "type": "text/plain", "text": "Copyright (c) 2006, Ivan Sagalaev\nAll rights reserved.\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\n notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n * Neither the name of highlight.js nor the names of its contributors\n may be used to endorse or promote products derived from this software\n without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" }, "$:/plugins/tiddlywiki/highlight/readme": { "title": "$:/plugins/tiddlywiki/highlight/readme", "text": "This plugin provides syntax highlighting of code blocks using v8.8.0 of [[highlight.js|https://github.com/isagalaev/highlight.js]] from Ivan Sagalaev.\n\n! Usage\n\nWhen the plugin is installed it automatically applies highlighting to all codeblocks defined with triple backticks or with the CodeBlockWidget.\n\nThe language can optionally be specified after the opening triple braces:\n\n<$codeblock code=\"\"\"```css\n * { margin: 0; padding: 0; } /* micro reset */\n\nhtml { font-size: 62.5%; }\nbody { font-size: 14px; font-size: 1.4rem; } /* =14px */\nh1 { font-size: 24px; font-size: 2.4rem; } /* =24px */\n```\"\"\"/>\n\nIf no language is specified highlight.js will attempt to automatically detect the language.\n\n! Built-in Language Brushes\n\nThe plugin includes support for the following languages (referred to as \"brushes\" by highlight.js):\n\n* apache\n* bash\n* coffeescript\n* cpp\n* cs\n* css\n* diff\n* http\n* ini\n* java\n* javascript\n* json\n* makefile\n* markdown\n* nginx\n* objectivec\n* perl\n* php\n* python\n* ruby\n* sql\n* xml\n\nYou can also specify the language as a MIME content type (eg `text/html` or `text/css`). The mapping is accomplished via mapping tiddlers whose titles start with `$:/config/HighlightPlugin/TypeMappings/`.\n" }, "$:/plugins/tiddlywiki/highlight/styles": { "title": "$:/plugins/tiddlywiki/highlight/styles", "tags": "[[$:/tags/Stylesheet]]", "text": ".hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8;-webkit-text-size-adjust:none}.hljs-comment,.diff .hljs-header,.hljs-javadoc{color:#998;font-style:italic}.hljs-keyword,.css .rule .hljs-keyword,.hljs-winutils,.nginx .hljs-title,.hljs-subst,.hljs-request,.hljs-status{color:#333;font-weight:bold}.hljs-number,.hljs-hexcolor,.ruby .hljs-constant{color:teal}.hljs-string,.hljs-tag .hljs-value,.hljs-phpdoc,.hljs-dartdoc,.tex .hljs-formula{color:#d14}.hljs-title,.hljs-id,.scss .hljs-preprocessor{color:#900;font-weight:bold}.hljs-list .hljs-keyword,.hljs-subst{font-weight:normal}.hljs-class .hljs-title,.hljs-type,.vhdl .hljs-literal,.tex .hljs-command{color:#458;font-weight:bold}.hljs-tag,.hljs-tag .hljs-title,.hljs-rule .hljs-property,.django .hljs-tag .hljs-keyword{color:navy;font-weight:normal}.hljs-attribute,.hljs-variable,.lisp .hljs-body,.hljs-name{color:teal}.hljs-regexp{color:#009926}.hljs-symbol,.ruby .hljs-symbol .hljs-string,.lisp .hljs-keyword,.clojure .hljs-keyword,.scheme .hljs-keyword,.tex .hljs-special,.hljs-prompt{color:#990073}.hljs-built_in{color:#0086b3}.hljs-preprocessor,.hljs-pragma,.hljs-pi,.hljs-doctype,.hljs-shebang,.hljs-cdata{color:#999;font-weight:bold}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.diff .hljs-change{background:#0086b3}.hljs-chunk{color:#aaa}" }, "$:/plugins/tiddlywiki/highlight/usage": { "title": "$:/plugins/tiddlywiki/highlight/usage", "text": "! Usage\n\nFenced code blocks can have a language specifier added to trigger highlighting in a specific language. Otherwise heuristics are used to detect the language.\n\n```\n ```js\n var a = b + c; // Highlighted as JavaScript\n ```\n```\n! Adding Themes\n\nYou can add themes from highlight.js by copying the CSS to a new tiddler and tagging it with [[$:/tags/Stylesheet]]. The available themes can be found on GitHub:\n\nhttps://github.com/isagalaev/highlight.js/tree/master/src/styles\n" } } }
{ "tiddlers": { "$:/core/modules/savers/nodewebkit.js": { "text": "/*\\\ntitle: $:/core/modules/savers/nodewebkit.js\ntype: application/javascript\nmodule-type: saver\n\nHandles saving changes in the NW.js environment. Not required by TiddlyDesktop, which re-uses the TiddlyFox saver, but useful if you're embedding a single TiddlyWiki document into a NW.js app.\n\n\\*/\n(function(){\n\n/*jslint node: true, browser: true */\n/*global $tw: false, netscape: false, Components: false */\n\"use strict\";\n\nvar NodeWebKitSaver = function(wiki) {\n};\n\nNodeWebKitSaver.prototype.save = function(text,method,callback) {\n\t// Bail out unless this is a save (rather than a download)\n\tif(method !== \"save\") {\n\t\treturn false;\n\t}\n\t// Get the pathname of this document\n\tvar pathname = document.location.pathname;\n\t// Test for a Windows path of the form /x:/blah/blah\n\tif(/^\\/[A-Z]\\:\\//i.test(pathname)) {\n\t\t// Remove the leading slash\n\t\tpathname = pathname.substr(1);\n\t\t// Convert slashes to backslashes\n\t\tpathname = pathname.replace(/\\//g,\"\\\\\");\n\t}\n\t// Try to save\n\tvar fs = require(\"fs\");\n\tfs.writeFile(pathname,text,callback);\n\treturn true;\n};\n\n/*\nInformation about this saver\n*/\nNodeWebKitSaver.prototype.info = {\n\tname: \"nodewebkit\",\n\tpriority: 1700\n};\n\n/*\nStatic method that returns true if this saver is capable of working\n*/\nexports.canSave = function(wiki) {\n\t// Check if we're running under node-webkit\n\treturn (typeof process == \"object\");\n};\n\n/*\nCreate an instance of this saver\n*/\nexports.create = function(wiki) {\n\treturn new NodeWebKitSaver(wiki);\n};\n\n})();\n", "title": "$:/core/modules/savers/nodewebkit.js", "type": "application/javascript", "module-type": "saver" }, "$:/plugins/tiddlywiki/nodewebkitsaver/readme": { "title": "$:/plugins/tiddlywiki/nodewebkitsaver/readme", "text": "This plugin provides a ''saver'' module for saving changes when using TiddlyWiki directly under NW.js (previously known as node-webkit).\n\n[[Source code|https://github.com/Jermolene/TiddlyWiki5/blob/master/plugins/tiddlywiki/nodewebkitsaver]]\n" } } }
Documentation
REBOL
handy
needs
enable
no-value
Draw commands
no
yes
$:/core/ui/AdvancedSearch/System
$:/core/ui/MoreSideBar/Plugins/Languages
$:/core/ui/ControlPanel/Saving
$:/core/ui/ControlPanel/Saving/TiddlySpot
$:/core/ui/MoreSideBar/All
$:/core/ui/SideBar/Recent
hide
hide
hide
hide
hide
hide
hide
hide
hide
hide
hide
hide
hide
hide
hide
show
hide
hide
hide
hide
hide
<div class="tc-static-alert"><div class="tc-static-alert-inner">This page is part of a static HTML representation of the ~TiddlyWiki at http://tiddlywiki.com/dev/</div></div>
favicon
{ "tiddlers": { "$:/info/browser": { "title": "$:/info/browser", "text": "yes" }, "$:/info/node": { "title": "$:/info/node", "text": "no" }, "$:/info/url/full": { "title": "$:/info/url/full", "text": "http://rebol.tiddlyspot.com/" }, "$:/info/url/host": { "title": "$:/info/url/host", "text": "rebol.tiddlyspot.com" }, "$:/info/url/hostname": { "title": "$:/info/url/hostname", "text": "rebol.tiddlyspot.com" }, "$:/info/url/protocol": { "title": "$:/info/url/protocol", "text": "http:" }, "$:/info/url/port": { "title": "$:/info/url/port", "text": "" }, "$:/info/url/pathname": { "title": "$:/info/url/pathname", "text": "/" }, "$:/info/url/search": { "title": "$:/info/url/search", "text": "" }, "$:/info/url/origin": { "title": "$:/info/url/origin", "text": "http://rebol.tiddlyspot.com" } } }
$:/themes/tiddlywiki/snowwhite
{ "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" } } }
{ "tiddlers": { "$:/themes/tiddlywiki/readonly/styles.tid": { "title": "$:/themes/tiddlywiki/readonly/styles.tid", "tags": "[[$:/tags/Stylesheet]]", "text": "\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\n\nsvg.tc-image-new-button, svg.tc-image-options-button, svg.tc-image-save-button, svg.tc-image-edit-button, svg.tc-image-delete-button, svg.tc-image-cancel-button, svg.tc-image-done-button {\n\tdisplay: none;\t\n}\n" } } }
{ "tiddlers": { "$:/themes/tiddlywiki/seamless/base": { "title": "$:/themes/tiddlywiki/seamless/base", "tags": "[[$:/tags/Stylesheet]]", "list-after": "$:/themes/tiddlywiki/vanilla/base", "text": "\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\n\n/*\nRules copied from Snow White\n*/\n\n.tc-page-controls button svg, .tc-tiddler-controls button svg, .tc-topbar button svg {\n\t<<transition \"fill 150ms ease-in-out\">>\n}\n\n.tc-tiddler-controls button.tc-selected svg {\n\t<<filter \"drop-shadow(0px -1px 2px rgba(0,0,0,0.25))\">>\n}\n\n.tc-drop-down {\n\tborder-radius: 4px;\n\t<<box-shadow \"2px 2px 10px rgba(0, 0, 0, 0.5)\">>\n}\n\n.tc-block-dropdown {\n\tborder-radius: 4px;\n\t<<box-shadow \"2px 2px 10px rgba(0, 0, 0, 0.5)\">>\n}\n\n.tc-modal-displayed {\n\t<<filter \"blur(4px)\">>\n}\n\n.tc-modal {\n\tborder-radius: 6px;\n\t<<box-shadow \"0 3px 7px rgba(0,0,0,0.3)\">>\n}\n\n.tc-modal-footer {\n\tborder-radius: 0 0 6px 6px;\n\t<<box-shadow \"inset 0 1px 0 #fff\">>;\n}\n\n.tc-alert {\n\tborder-radius: 6px;\n\t<<box-shadow \"0 3px 7px rgba(0,0,0,0.6)\">>\n}\n\n.tc-notification {\n\tborder-radius: 6px;\n\t<<box-shadow \"0 3px 7px rgba(0,0,0,0.3)\">>\n\ttext-shadow: 0 1px 0 rgba(255,255,255, 0.8);\n}\n\n.tc-message-box img {\n\t<<box-shadow \"1px 1px 3px rgba(0,0,0,0.5)\">>\n}\n\n/*\nSeamless modifications\n*/\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\t/* Drop the tiddler frame padding */\n\tbody.tc-body .tc-tiddler-frame {\n\t\tpadding: 0;\n\t}\n\n\t/* Move the sidebar up so that the title lines up */\n\tbody.tc-body .tc-sidebar-scrollable {\n\t\tpadding: 43px 0 28px 42px;\n\t}\n\n\t/* Stop the tiddler info panel from bleeding into the tiddler frame padding */\n\tbody.tc-body .tc-tiddler-info {\n\t\tmargin: 0;\n\t}\n\n\t/* Stop message boxes from bleeding into the tiddler frame padding */\n\tbody.tc-body .tc-message-box {\n\t\tmargin: 21px 0 21px 0;\n\t}\n\n}\n\n/* Use the tiddler background colour for the page background */\nhtml body.tc-body {\n\tbackground-color: <<colour background>>;\n}\n\nhtml:-webkit-full-screen {\n\tbackground-color: <<colour background>>;\n}\n\n/* Adjust the colour of the page controls */\nbody.tc-body .tc-page-controls svg {\n\tfill: <<colour muted-foreground>>;\n}\n\n/* Adjust the colour of the sidebar selected tabs */\nbody.tc-body .tc-sidebar-lists .tc-tab-buttons button.tc-tab-selected {\n\tbackground-color: <<colour background>>;\n}\n" } } }
{ "tiddlers": { "$:/themes/tiddlywiki/snowwhite/base": { "title": "$:/themes/tiddlywiki/snowwhite/base", "tags": "[[$:/tags/Stylesheet]]", "text": "\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\n\n.tc-sidebar-header {\n\ttext-shadow: 0 1px 0 <<colour sidebar-foreground-shadow>>;\n}\n\n.tc-tiddler-info {\n\t<<box-shadow \"inset 1px 2px 3px rgba(0,0,0,0.1)\">>\n}\n\n@media screen {\n\t.tc-tiddler-frame {\n\t\t<<box-shadow \"1px 1px 5px rgba(0, 0, 0, 0.3)\">>\n\t}\n}\n\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\t.tc-tiddler-frame {\n\t\t<<box-shadow none>>\n\t}\n}\n\n.tc-page-controls button svg, .tc-tiddler-controls button svg, .tc-topbar button svg {\n\t<<transition \"fill 150ms ease-in-out\">>\n}\n\n.tc-tiddler-controls button.tc-selected,\n.tc-page-controls button.tc-selected {\n\t<<filter \"drop-shadow(0px -1px 2px rgba(0,0,0,0.25))\">>\n}\n\n.tc-tiddler-frame input.tc-edit-texteditor {\n\t<<box-shadow \"inset 0 1px 8px rgba(0, 0, 0, 0.15)\">>\n}\n\n.tc-edit-tags {\n\t<<box-shadow \"inset 0 1px 8px rgba(0, 0, 0, 0.15)\">>\n}\n\n.tc-tiddler-frame .tc-edit-tags input.tc-edit-texteditor {\n\t<<box-shadow \"none\">>\n\tborder: none;\n\toutline: none;\n}\n\ncanvas.tc-edit-bitmapeditor {\n\t<<box-shadow \"2px 2px 5px rgba(0, 0, 0, 0.5)\">>\n}\n\n.tc-drop-down {\n\tborder-radius: 4px;\n\t<<box-shadow \"2px 2px 10px rgba(0, 0, 0, 0.5)\">>\n}\n\n.tc-block-dropdown {\n\tborder-radius: 4px;\n\t<<box-shadow \"2px 2px 10px rgba(0, 0, 0, 0.5)\">>\n}\n\n.tc-modal {\n\tborder-radius: 6px;\n\t<<box-shadow \"0 3px 7px rgba(0,0,0,0.3)\">>\n}\n\n.tc-modal-footer {\n\tborder-radius: 0 0 6px 6px;\n\t<<box-shadow \"inset 0 1px 0 #fff\">>;\n}\n\n\n.tc-alert {\n\tborder-radius: 6px;\n\t<<box-shadow \"0 3px 7px rgba(0,0,0,0.6)\">>\n}\n\n.tc-notification {\n\tborder-radius: 6px;\n\t<<box-shadow \"0 3px 7px rgba(0,0,0,0.3)\">>\n\ttext-shadow: 0 1px 0 rgba(255,255,255, 0.8);\n}\n\n.tc-sidebar-lists .tc-tab-set .tc-tab-divider {\n\tborder-top: none;\n\theight: 1px;\n\t<<background-linear-gradient \"left, rgba(0,0,0,0.15) 0%, rgba(0,0,0,0.0) 100%\">>\n}\n\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button {\n\t<<background-linear-gradient \"left, rgba(0,0,0,0.01) 0%, rgba(0,0,0,0.1) 100%\">>\n}\n\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button.tc-tab-selected {\n\t<<background-linear-gradient \"left, rgba(0,0,0,0.05) 0%, rgba(255,255,255,0.05) 100%\">>\n}\n\n.tc-message-box img {\n\t<<box-shadow \"1px 1px 3px rgba(0,0,0,0.5)\">>\n}\n\n.tc-plugin-info {\n\t<<box-shadow \"1px 1px 3px rgba(0,0,0,0.5)\">>\n}\n" } } }
{ "tiddlers": { "$:/themes/tiddlywiki/starlight/arvo.woff": { "text": "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", "type": "application/font-woff", "title": "$:/themes/tiddlywiki/starlight/arvo.woff" }, "$:/themes/tiddlywiki/starlight/ltbg.jpg": { "text": "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PSIxLjAiIGVuY29kaW5nPSJVVEYtOCI/Pgo8IURPQ1RZUEUgcGxpc3QgUFVCTElDICItLy9BcHBsZS8vRFREIFBMSVNUIDEuMC8vRU4iICJodHRwOi8vd3d3LmFwcGxlLmNvbS9EVERzL1Byb3BlcnR5TGlzdC0xLjAuZHRkIj4KPHBsaXN0IHZlcnNpb249IjEuMCI+CjxkaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTUhvcml6b250YWxSZXM8L2tleT4KCTxkaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc+CgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCTxhcnJheT4KCQkJPGRpY3Q+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNSG9yaXpvbnRhbFJlczwva2V5PgoJCQkJPHJlYWw+NzI8L3JlYWw+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFnPC9rZXk+CgkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQk8L2RpY3Q+CgkJPC9hcnJheT4KCTwvZGljdD4KCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1PcmllbnRhdGlvbjwva2V5PgoJPGRpY3Q+CgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1PcmllbnRhdGlvbjwva2V5PgoJCQkJPGludGVnZXI+MTwvaW50ZWdlcj4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVNjYWxpbmc8L2tleT4KCTxkaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc+CgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCTxhcnJheT4KCQkJPGRpY3Q+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNU2NhbGluZzwva2V5PgoJCQkJPHJlYWw+MTwvcmVhbD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsUmVzPC9rZXk+Cgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc+Y29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk+CgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsUmVzPC9rZXk+CgkJCQk8cmVhbD43MjwvcmVhbD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsU2NhbGluZzwva2V5PgoJPGRpY3Q+CgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1WZXJ0aWNhbFNjYWxpbmc8L2tleT4KCQkJCTxyZWFsPjE8L3JlYWw+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFnPC9rZXk+CgkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQk8L2RpY3Q+CgkJPC9hcnJheT4KCTwvZGljdD4KCTxrZXk+Y29tLmFwcGxlLnByaW50LnN1YlRpY2tldC5wYXBlcl9pbmZvX3RpY2tldDwva2V5PgoJPGRpY3Q+CgkJPGtleT5QTVBQRFBhcGVyQ29kZU5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q+CgkJCQkJPGtleT5QTVBQRFBhcGVyQ29kZU5hbWU8L2tleT4KCQkJCQk8c3RyaW5nPkxldHRlcjwvc3RyaW5nPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PlBNVGlvZ2FQYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q+CgkJCQkJPGtleT5QTVRpb2dhUGFwZXJOYW1lPC9rZXk+CgkJCQkJPHN0cmluZz5uYS1sZXR0ZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFnPC9rZXk+CgkJCQkJPGludGVnZXI+MDwvaW50ZWdlcj4KCQkJCTwvZGljdD4KCQkJPC9hcnJheT4KCQk8L2RpY3Q+CgkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTUFkanVzdGVkUGFnZVJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTUFkanVzdGVkUGFnZVJlY3Q8L2tleT4KCQkJCQk8YXJyYXk+CgkJCQkJCTxyZWFsPjAuMDwvcmVhbD4KCQkJCQkJPHJlYWw+MC4wPC9yZWFsPgoJCQkJCQk8cmVhbD43MzQ8L3JlYWw+CgkJCQkJCTxyZWFsPjU3NjwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTUFkanVzdGVkUGFwZXJSZWN0PC9rZXk+CgkJCQkJPGFycmF5PgoJCQkJCQk8cmVhbD4tMTg8L3JlYWw+CgkJCQkJCTxyZWFsPi0xODwvcmVhbD4KCQkJCQkJPHJlYWw+Nzc0PC9yZWFsPgoJCQkJCQk8cmVhbD41OTQ8L3JlYWw+CgkJCQkJPC9hcnJheT4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFnPC9rZXk+CgkJCQkJPGludGVnZXI+MDwvaW50ZWdlcj4KCQkJCTwvZGljdD4KCQkJPC9hcnJheT4KCQk8L2RpY3Q+CgkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNUGFwZXJOYW1lPC9rZXk+CgkJPGRpY3Q+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJCTxzdHJpbmc+Y29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVBhcGVyTmFtZTwva2V5PgoJCQkJCTxzdHJpbmc+bmEtbGV0dGVyPC9zdHJpbmc+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCQk8L2RpY3Q+CgkJCTwvYXJyYXk+CgkJPC9kaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk+CgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8uUE1VbmFkanVzdGVkUGFnZVJlY3Q8L2tleT4KCQkJCQk8YXJyYXk+CgkJCQkJCTxyZWFsPjAuMDwvcmVhbD4KCQkJCQkJPHJlYWw+MC4wPC9yZWFsPgoJCQkJCQk8cmVhbD43MzQ8L3JlYWw+CgkJCQkJCTxyZWFsPjU3NjwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8uUE1VbmFkanVzdGVkUGFwZXJSZWN0PC9rZXk+CgkJPGRpY3Q+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJCTxzdHJpbmc+Y29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQkJCQk8YXJyYXk+CgkJCQkJCTxyZWFsPi0xODwvcmVhbD4KCQkJCQkJPHJlYWw+LTE4PC9yZWFsPgoJCQkJCQk8cmVhbD43NzQ8L3JlYWw+CgkJCQkJCTxyZWFsPjU5NDwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8ucHBkLlBNUGFwZXJOYW1lPC9rZXk+CgkJPGRpY3Q+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJCTxzdHJpbmc+Y29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5wcGQuUE1QYXBlck5hbWU8L2tleT4KCQkJCQk8c3RyaW5nPlVTIExldHRlcjwvc3RyaW5nPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuQVBJVmVyc2lvbjwva2V5PgoJCTxzdHJpbmc+MDAuMjA8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQudHlwZTwva2V5PgoJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mb1RpY2tldDwvc3RyaW5nPgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LkFQSVZlcnNpb248L2tleT4KCTxzdHJpbmc+MDAuMjA8L3N0cmluZz4KCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC50eXBlPC9rZXk+Cgk8c3RyaW5nPmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0VGlja2V0PC9zdHJpbmc+CjwvZGljdD4KPC9wbGlzdD4KOEJJTQPtAAAAAAAQAEgCTgABAAEASAJOAAEAAThCSU0EJgAAAAAADgAAAAAAAAAAAAA/gAAAOEJJTQQNAAAAAAAEAAAAHjhCSU0EGQAAAAAABAAAAB44QklNA/MAAAAAAAkAAAAAAAAAAAEAOEJJTQQKAAAAAAABAAA4QklNJxAAAAAAAAoAAQAAAAAAAAABOEJJTQP1AAAAAABIAC9mZgABAGxmZgAGAAAAAAABAC9mZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAABAC0AAAAGAAAAAAABOEJJTQP4AAAAAABwAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAADhCSU0ECAAAAAAAEAAAAAEAAAJAAAACQAAAAAA4QklNBB4AAAAAAAQAAAAAOEJJTQQaAAAAAANHAAAABgAAAAAAAAAAAAABVAAAAVQAAAAJAFAAaQBjAHQAdQByAGUAIAAyAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAFUAAABVAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAABAAAAABAAAAAAAAbnVsbAAAAAIAAAAGYm91bmRzT2JqYwAAAAEAAAAAAABSY3QxAAAABAAAAABUb3AgbG9uZwAAAAAAAAAATGVmdGxvbmcAAAAAAAAAAEJ0b21sb25nAAABVAAAAABSZ2h0bG9uZwAAAVQAAAAGc2xpY2VzVmxMcwAAAAFPYmpjAAAAAQAAAAAABXNsaWNlAAAAEgAAAAdzbGljZUlEbG9uZwAAAAAAAAAHZ3JvdXBJRGxvbmcAAAAAAAAABm9yaWdpbmVudW0AAAAMRVNsaWNlT3JpZ2luAAAADWF1dG9HZW5lcmF0ZWQAAAAAVHlwZWVudW0AAAAKRVNsaWNlVHlwZQAAAABJbWcgAAAABmJvdW5kc09iamMAAAABAAAAAAAAUmN0MQAAAAQAAAAAVG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAAAVQAAAAAUmdodGxvbmcAAAFUAAAAA3VybFRFWFQAAAABAAAAAAAAbnVsbFRFWFQAAAABAAAAAAAATXNnZVRFWFQAAAABAAAAAAAGYWx0VGFnVEVYVAAAAAEAAAAAAA5jZWxsVGV4dElzSFRNTGJvb2wBAAAACGNlbGxUZXh0VEVYVAAAAAEAAAAAAAlob3J6QWxpZ25lbnVtAAAAD0VTbGljZUhvcnpBbGlnbgAA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Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNC4xLWMwMzYgNDYuMjc2NzIwLCBNb24gRmViIDE5IDIwMDcgMjI6MTM6NDMgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhhcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOnhhcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iIHhhcDpDcmVhdGVEYXRlPSIyMDEwLTA4LTMwVDIzOjQ5OjE0LTA1OjAwIiB4YXA6TW9kaWZ5RGF0ZT0iMjAxMC0wOC0zMFQyMzo0OToxNC0wNTowMCIgeGFwOk1ldGFkYXRhRGF0ZT0iMjAxMC0wOC0zMFQyMzo0OToxNC0wNTowMCIgeGFwOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1MzIE1hY2ludG9zaCIgZGM6Zm9ybWF0PSJpbWFnZS9qcGVnIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0iaU1hYyIgcGhvdG9zaG9wOkhpc3Rvcnk9IiIgeGFwTU06SW5zdGFuY2VJRD0idXVpZDpFQjAwQjU5NDA4QjVERjExODdBNTlCQzExMkI0QjA2RSIgeGFwTU06RG9jdW1lbnRJRD0idXVpZDpFQTAwQjU5NDA4QjVERjExODdBNTlCQzExMkI0QjA2RSIgdGlmZjpPcmllbnRhdGlvbj0iMSIgdGlmZjpYUmVzb2x1dGlvbj0iNzIwMDkwLzEwMDAwIiB0aWZmOllSZXNvbHV0aW9uPSI3MjAwOTAvMTAwMDAiIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiIHRpZmY6TmF0aXZlRGlnZXN0PSIyNTYsMjU3LDI1OCwyNTksMjYyLDI3NCwyNzcsMjg0LDUzMCw1MzEsMjgyLDI4MywyOTYsMzAxLDMxOCwzMTksNTI5LDUzMiwzMDYsMjcwLDI3MSwyNzIsMzA1LDMxNSwzMzQzMjs3RUY4RDFBOTcwMjlCOUNFOTAwNkUzRDcxRjgwNDdFNSIgZXhpZjpQaXhlbFhEaW1lbnNpb249IjM0MCIgZXhpZjpQaXhlbFlEaW1lbnNpb249IjM0MCIgZXhpZjpDb2xvclNwYWNlPSItMSIgZXhpZjpOYXRpdmVEaWdlc3Q9IjM2ODY0LDQwOTYwLDQwOTYxLDM3MTIxLDM3MTIyLDQwOTYyLDQwOTYzLDM3NTEwLDQwOTY0LDM2ODY3LDM2ODY4LDMzNDM0LDMzNDM3LDM0ODUwLDM0ODUyLDM0ODU1LDM0ODU2LDM3Mzc3LDM3Mzc4LDM3Mzc5LDM3MzgwLDM3MzgxLDM3MzgyLDM3MzgzLDM3Mzg0LDM3Mzg1LDM3Mzg2LDM3Mzk2LDQxNDgzLDQxNDg0LDQxNDg2LDQxNDg3LDQxNDg4LDQxNDkyLDQxNDkzLDQxNDk1LDQxNzI4LDQxNzI5LDQxNzMwLDQxOTg1LDQxOTg2LDQxOTg3LDQxOTg4LDQxOTg5LDQxOTkwLDQxOTkxLDQxOTkyLDQxOTkzLDQxOTk0LDQxOTk1LDQxOTk2LDQyMDE2LDAsMiw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwyMCwyMiwyMywyNCwyNSwyNiwyNywyOCwzMDtGRTM2RkQ0MzU0NEI0ODUyODY3OEVERkZGOTk0MkMwRiI+IDx4YXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3hwYWNrZXQgZW5kPSJ3Ij8+/+IPJElDQ19QUk9GSUxFAAEBAAAPFGFwcGwCAAAAbW50clJHQiBYWVogB9oAAQAEAA8AMwADYWNzcEFQUEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1hcHBsWM2pk1LRLUWykThyCK1QdgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOclhZWgAAASwAAAAUZ1hZWgAAAUAAAAAUYlhZWgAAAVQAAAAUd3RwdAAAAWgAAAAUY2hhZAAAAXwAAAAsclRSQwAAAagAAAAOZ1RSQwAAAbgAAAAOYlRSQwAAAcgAAAAOdmNndAAAAdgAAAYSbmRpbgAAB+wAAAY+ZGVzYwAADiwAAABfZHNjbQAADowAAAA8bW1vZAAADsgAAAAoY3BydAAADvAAAAAkWFlaIAAAAAAAAHeaAABAmQAAAxlYWVogAAAAAAAAWO0AAKuMAAAXrVhZWiAAAAAAAAAmTgAAE/UAALheWFlaIAAAAAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAADAQAAAgAAAUUCyAQ5BZsHIQi8ClsL+w2ZDzsQ6hKXFEYWAhe5GVYa4xxxHfkfdSDyImcj0iU1JpAn5ikyKnkrvi0BLkEvgTC9MfkzNTRrNaE21DgHOTg6ZjuTPLw95D8MQDNBV0J5Q5pEuEXWRvJIDEklSjpL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", "type": "image/jpeg", "title": "$:/themes/tiddlywiki/starlight/ltbg.jpg" }, "$:/themes/tiddlywiki/starlight/styles.tid": { "title": "$:/themes/tiddlywiki/starlight/styles.tid", "tags": "[[$:/tags/Stylesheet]]", "text": "\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\n\n/*\nPlaceholder for a more thorough refinement of Snow White\n*/\n\n@font-face {\n font-family: \"Arvo\";\n font-style: normal;\n font-weight: 400;\n src: local(\"Arvo\"), url(<<datauri \"$:/themes/tiddlywiki/starlight/arvo.woff\">>) format(\"woff\");\n}\n\nhtml body, .tc-sidebar-scrollable-backdrop {\n\tfont-family: \"Arvo\", \"Times\";\n background: url(<<datauri \"$:/themes/tiddlywiki/starlight/ltbg.jpg\">>);\n}\n\n.tc-page-controls svg {\n <<filter \"drop-shadow(1px 1px 2px rgba(255,255,255,0.9))\">>\n}\n" }, "$:/themes/tiddlywiki/starlight/themetweaks": { "title": "$:/themes/tiddlywiki/starlight/themetweaks", "tags": "$:/tags/ControlPanel/Appearance", "caption": "Star Tweaks", "text": "Demo of a control panel tab dynamically loaded with a theme.\n" } } }
{ "tiddlers": { "$:/themes/tiddlywiki/tight/base": { "title": "$:/themes/tiddlywiki/tight/base", "tags": "[[$:/tags/Stylesheet]]", "text": "\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\n\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n}\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\thtml body.tc-body {\n\t\tfont-size: 13px;\n\t\tline-height: 16px;\n\t}\n\n\thtml body.tc-body h1,\n\thtml body.tc-body h2,\n\thtml body.tc-body h3,\n\thtml body.tc-body h4,\n\thtml body.tc-body p {\n\t\tmargin-top: 0.3em;\n\t\tmargin-bottom: 0.3em;\n\t}\n\n\thtml body.tc-body code {\n\t\tfont-size: 0.8em;\n\t}\n\n\thtml body.tc-body section.tc-story-river {\n\t\tpadding: 0px;\n\t}\n\n\thtml body.tc-body div.tc-tiddler-frame {\n\t\tpadding: 12px;\n\t}\n\n\thtml body.tc-body div.tc-sidebar-scrollable {\n\t\tpadding: 12px 0 12px 12px;\n\t}\n\n\thtml body.tc-body .tc-tiddler-frame .tc-subtitle {\n\t\tfont-size: 0.7em;\n\t\tfont-weight: 700;\n\t}\n\n\thtml body.tc-body .tc-tiddler-frame .tc-tags-wrapper {\n\t\tmargin: 0;\n\t}\n\n\thtml body.tc-body .tc-tiddler-frame button.tc-tag-label,\n\thtml body.tc-body .tc-tiddler-frame span.tc-tag-label {\n\t\tfont-size: 0.8em;\n\t}\n\n\thtml body.tc-body .tc-tiddler-frame .tc-tiddler-body h1 {\n\t\tfont-size: 1.5em;\n\t\tfont-weight: 500;\n\t}\n\n\thtml body.tc-body .tc-tiddler-frame .tc-tiddler-body h2 {\n\t\tfont-size: 1.3em;\n\t\tfont-weight: 500;\n\t}\n\n\thtml body.tc-body .tc-tiddler-frame .tc-tiddler-body h3 {\n\t\tfont-size: 1.2em;\n\t\tfont-weight: 500;\n\t}\n\n\thtml body.tc-body .tc-tiddler-frame .tc-tiddler-body h4 {\n\t\tfont-size: 1.1em;\n\t\tfont-weight: 500;\n\t}\n\n\thtml body.tc-body .tc-tiddler-frame .tc-improvement-banner {\n\t\tmargin-right: -15px;\n\t\tmargin-left: -10px;\n\t}\n\n\thtml body.tc-body .tc-tiddler-frame .tc-tiddler-info {\n\t margin: 0 -13px 0 -13px;\n\t}\n\n\thtml body.tc-body .tc-tiddler-frame .tc-fold-banner {\n\t width: 13px;\n\t margin-left: -15px;\n\t}\n\n\thtml body.tc-body .tc-tiddler-frame .tc-unfold-banner {\n\t margin-left: -13px;\n\t margin-top: -4px;\n\t}\n\n}\n" } } }
{ "tiddlers": { "$:/themes/tiddlywiki/vanilla/themetweaks": { "title": "$:/themes/tiddlywiki/vanilla/themetweaks", "tags": "$:/tags/ControlPanel/Appearance", "caption": "{{$:/language/ThemeTweaks/ThemeTweaks}}", "text": "\\define lingo-base() $:/language/ThemeTweaks/\n\n\\define replacement-text()\n[img[$(imageTitle)$]]\n\\end\n\n\\define backgroundimage-dropdown()\n<div class=\"tc-drop-down-wrapper\">\n<$button popup=<<qualify \"$:/state/popup/themetweaks/backgroundimage\">> class=\"tc-btn-invisible tc-btn-dropdown\">{{$:/core/images/down-arrow}}</$button>\n<$reveal state=<<qualify \"$:/state/popup/themetweaks/backgroundimage\">> type=\"popup\" position=\"belowleft\" text=\"\" default=\"\">\n<div class=\"tc-drop-down\">\n<$macrocall $name=\"image-picker\" actions=\"\"\"\n\n<$action-setfield\n\t$tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\"\n\t$value=<<imageTitle>>\n/>\n\n\"\"\"/>\n</div>\n</$reveal>\n</div>\n\\end\n\n\\define backgroundimageattachment-dropdown()\n<$select tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment\" default=\"scroll\">\n<option value=\"scroll\"><<lingo Settings/BackgroundImageAttachment/Scroll>></option>\n<option value=\"fixed\"><<lingo Settings/BackgroundImageAttachment/Fixed>></option>\n</$select>\n\\end\n\n\\define backgroundimagesize-dropdown()\n<$select tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize\" default=\"scroll\">\n<option value=\"auto\"><<lingo Settings/BackgroundImageSize/Auto>></option>\n<option value=\"cover\"><<lingo Settings/BackgroundImageSize/Cover>></option>\n<option value=\"contain\"><<lingo Settings/BackgroundImageSize/Contain>></option>\n</$select>\n\\end\n\n<<lingo ThemeTweaks/Hint>>\n\n! <<lingo Options>>\n\n|<$link to=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\"><<lingo Options/SidebarLayout>></$link> |<$select tiddler=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\"><option value=\"fixed-fluid\"><<lingo Options/SidebarLayout/Fixed-Fluid>></option><option value=\"fluid-fixed\"><<lingo Options/SidebarLayout/Fluid-Fixed>></option></$select> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/options/stickytitles\"><<lingo Options/StickyTitles>></$link><br>//<<lingo Options/StickyTitles/Hint>>// |<$select tiddler=\"$:/themes/tiddlywiki/vanilla/options/stickytitles\"><option value=\"no\">{{$:/language/No}}</option><option value=\"yes\">{{$:/language/Yes}}</option></$select> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/options/codewrapping\"><<lingo Options/CodeWrapping>></$link> |<$select tiddler=\"$:/themes/tiddlywiki/vanilla/options/codewrapping\"><option value=\"pre\">{{$:/language/No}}</option><option value=\"pre-wrap\">{{$:/language/Yes}}</option></$select> |\n\n! <<lingo Settings>>\n\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/fontfamily\"><<lingo Settings/FontFamily>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/settings/fontfamily\" default=\"\" tag=\"input\"/> | |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/codefontfamily\"><<lingo Settings/CodeFontFamily>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/settings/codefontfamily\" default=\"\" tag=\"input\"/> | |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\"><<lingo Settings/BackgroundImage>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimage\" default=\"\" tag=\"input\"/> |<<backgroundimage-dropdown>> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment\"><<lingo Settings/BackgroundImageAttachment>></$link> |<<backgroundimageattachment-dropdown>> | |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize\"><<lingo Settings/BackgroundImageSize>></$link> |<<backgroundimagesize-dropdown>> | |\n\n! <<lingo Metrics>>\n\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/fontsize\"><<lingo Metrics/FontSize>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/fontsize\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/lineheight\"><<lingo Metrics/LineHeight>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/lineheight\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize\"><<lingo Metrics/BodyFontSize>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/bodylineheight\"><<lingo Metrics/BodyLineHeight>></$link> |<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/bodylineheight\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storyleft\"><<lingo Metrics/StoryLeft>></$link><br>//<<lingo Metrics/StoryLeft/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storyleft\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storytop\"><<lingo Metrics/StoryTop>></$link><br>//<<lingo Metrics/StoryTop/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storytop\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storyright\"><<lingo Metrics/StoryRight>></$link><br>//<<lingo Metrics/StoryRight/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storyright\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/storywidth\"><<lingo Metrics/StoryWidth>></$link><br>//<<lingo Metrics/StoryWidth/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/storywidth\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth\"><<lingo Metrics/TiddlerWidth>></$link><br>//<<lingo Metrics/TiddlerWidth/Hint>>//<br> |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint\"><<lingo Metrics/SidebarBreakpoint>></$link><br>//<<lingo Metrics/SidebarBreakpoint/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint\" default=\"\" tag=\"input\"/> |\n|<$link to=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth\"><<lingo Metrics/SidebarWidth>></$link><br>//<<lingo Metrics/SidebarWidth/Hint>>// |^<$edit-text tiddler=\"$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth\" default=\"\" tag=\"input\"/> |\n" }, "$:/themes/tiddlywiki/vanilla/base": { "title": "$:/themes/tiddlywiki/vanilla/base", "tags": "[[$:/tags/Stylesheet]]", "text": "\\define custom-background-datauri()\n<$set name=\"background\" value={{$:/themes/tiddlywiki/vanilla/settings/backgroundimage}}>\n<$list filter=\"[<background>is[image]]\">\n`background: url(`\n<$list filter=\"[<background>!has[_canonical_uri]]\">\n<$macrocall $name=\"datauri\" title={{$:/themes/tiddlywiki/vanilla/settings/backgroundimage}}/>\n</$list>\n<$list filter=\"[<background>has[_canonical_uri]]\">\n<$view tiddler={{$:/themes/tiddlywiki/vanilla/settings/backgroundimage}} field=\"_canonical_uri\"/>\n</$list>\n`) center center;`\n`background-attachment: `{{$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment}}`;\n-webkit-background-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;\n-moz-background-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;\n-o-background-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;\nbackground-size:` {{$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize}}`;`\n</$list>\n</$set>\n\\end\n\n\\define if-fluid-fixed(text,hiddenSidebarText)\n<$reveal state=\"$:/themes/tiddlywiki/vanilla/options/sidebarlayout\" type=\"match\" text=\"fluid-fixed\">\n$text$\n<$reveal state=\"$:/state/sidebar\" type=\"nomatch\" text=\"yes\" default=\"yes\">\n$hiddenSidebarText$\n</$reveal>\n</$reveal>\n\\end\n\n\\define if-editor-height-fixed(then,else)\n<$reveal state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"fixed\">\n$then$\n</$reveal>\n<$reveal state=\"$:/config/TextEditor/EditorHeight/Mode\" type=\"match\" text=\"auto\">\n$else$\n</$reveal>\n\\end\n\n\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline macrocallblock\n\n/*\n** Start with the normalize CSS reset, and then belay some of its effects\n*/\n\n{{$:/themes/tiddlywiki/vanilla/reset}}\n\n*, input[type=\"search\"] {\n\tbox-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\t-webkit-box-sizing: border-box;\n}\n\nhtml button {\n\tline-height: 1.2;\n\tcolor: <<colour button-foreground>>;\n\tbackground: <<colour button-background>>;\n\tborder-color: <<colour button-border>>;\n}\n\n/*\n** Basic element styles\n*/\n\nhtml {\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/fontfamily}};\n\ttext-rendering: optimizeLegibility; /* Enables kerning and ligatures etc. */\n\t-webkit-font-smoothing: antialiased;\n\t-moz-osx-font-smoothing: grayscale;\n}\n\nhtml:-webkit-full-screen {\n\tbackground-color: <<colour page-background>>;\n}\n\nbody.tc-body {\n\tfont-size: {{$:/themes/tiddlywiki/vanilla/metrics/fontsize}};\n\tline-height: {{$:/themes/tiddlywiki/vanilla/metrics/lineheight}};\n\tword-wrap: break-word;\n\t<<custom-background-datauri>>\n\tcolor: <<colour foreground>>;\n\tbackground-color: <<colour page-background>>;\n\tfill: <<colour foreground>>;\n}\n\nh1, h2, h3, h4, h5, h6 {\n\tline-height: 1.2;\n\tfont-weight: 300;\n}\n\npre {\n\tdisplay: block;\n\tpadding: 14px;\n\tmargin-top: 1em;\n\tmargin-bottom: 1em;\n\tword-break: normal;\n\tword-wrap: break-word;\n\twhite-space: {{$:/themes/tiddlywiki/vanilla/options/codewrapping}};\n\tbackground-color: <<colour pre-background>>;\n\tborder: 1px solid <<colour pre-border>>;\n\tpadding: 0 3px 2px;\n\tborder-radius: 3px;\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/codefontfamily}};\n}\n\ncode {\n\tcolor: <<colour code-foreground>>;\n\tbackground-color: <<colour code-background>>;\n\tborder: 1px solid <<colour code-border>>;\n\twhite-space: {{$:/themes/tiddlywiki/vanilla/options/codewrapping}};\n\tpadding: 0 3px 2px;\n\tborder-radius: 3px;\n\tfont-family: {{$:/themes/tiddlywiki/vanilla/settings/codefontfamily}};\n}\n\nblockquote {\n\tborder-left: 5px solid <<colour blockquote-bar>>;\n\tmargin-left: 25px;\n\tpadding-left: 10px;\n\tquotes: \"\\201C\"\"\\201D\"\"\\2018\"\"\\2019\";\n}\n\nblockquote.tc-big-quote {\n\tfont-family: Georgia, serif;\n\tposition: relative;\n\tbackground: <<colour pre-background>>;\n\tborder-left: none;\n\tmargin-left: 50px;\n\tmargin-right: 50px;\n\tpadding: 10px;\n border-radius: 8px;\n}\n\nblockquote.tc-big-quote cite:before {\n\tcontent: \"\\2014 \\2009\";\n}\n\nblockquote.tc-big-quote:before {\n\tfont-family: Georgia, serif;\n\tcolor: <<colour blockquote-bar>>;\n\tcontent: open-quote;\n\tfont-size: 8em;\n\tline-height: 0.1em;\n\tmargin-right: 0.25em;\n\tvertical-align: -0.4em;\n\tposition: absolute;\n left: -50px;\n top: 42px;\n}\n\nblockquote.tc-big-quote:after {\n\tfont-family: Georgia, serif;\n\tcolor: <<colour blockquote-bar>>;\n\tcontent: close-quote;\n\tfont-size: 8em;\n\tline-height: 0.1em;\n\tmargin-right: 0.25em;\n\tvertical-align: -0.4em;\n\tposition: absolute;\n right: -80px;\n bottom: -20px;\n}\n\ndl dt {\n\tfont-weight: bold;\n\tmargin-top: 6px;\n}\n\ntextarea,\ninput[type=text],\ninput[type=search],\ninput[type=\"\"],\ninput:not([type]) {\n\tcolor: <<colour foreground>>;\n\tbackground: <<colour background>>;\n}\n\n.tc-muted {\n\tcolor: <<colour muted-foreground>>;\n}\n\nsvg.tc-image-button {\n\tpadding: 0px 1px 1px 0px;\n}\n\n.tc-icon-wrapper > svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\nkbd {\n\tdisplay: inline-block;\n\tpadding: 3px 5px;\n\tfont-size: 0.8em;\n\tline-height: 1.2;\n\tcolor: <<colour foreground>>;\n\tvertical-align: middle;\n\tbackground-color: <<colour background>>;\n\tborder: solid 1px <<colour muted-foreground>>;\n\tborder-bottom-color: <<colour muted-foreground>>;\n\tborder-radius: 3px;\n\tbox-shadow: inset 0 -1px 0 <<colour muted-foreground>>;\n}\n\n/*\nMarkdown likes putting code elements inside pre elements\n*/\npre > code {\n\tpadding: 0;\n\tborder: none;\n\tbackground-color: inherit;\n\tcolor: inherit;\n}\n\ntable {\n\tborder: 1px solid <<colour table-border>>;\n\twidth: auto;\n\tmax-width: 100%;\n\tcaption-side: bottom;\n\tmargin-top: 1em;\n\tmargin-bottom: 1em;\n}\n\ntable th, table td {\n\tpadding: 0 7px 0 7px;\n\tborder-top: 1px solid <<colour table-border>>;\n\tborder-left: 1px solid <<colour table-border>>;\n}\n\ntable thead tr td, table th {\n\tbackground-color: <<colour table-header-background>>;\n\tfont-weight: bold;\n}\n\ntable tfoot tr td {\n\tbackground-color: <<colour table-footer-background>>;\n}\n\n.tc-csv-table {\n\twhite-space: nowrap;\n}\n\n.tc-tiddler-frame img,\n.tc-tiddler-frame svg,\n.tc-tiddler-frame canvas,\n.tc-tiddler-frame embed,\n.tc-tiddler-frame iframe {\n\tmax-width: 100%;\n}\n\n.tc-tiddler-body > embed,\n.tc-tiddler-body > iframe {\n\twidth: 100%;\n\theight: 600px;\n}\n\n/*\n** Links\n*/\n\nbutton.tc-tiddlylink,\na.tc-tiddlylink {\n\ttext-decoration: none;\n\tfont-weight: normal;\n\tcolor: <<colour tiddler-link-foreground>>;\n\t-webkit-user-select: inherit; /* Otherwise the draggable attribute makes links impossible to select */\n}\n\n.tc-sidebar-lists a.tc-tiddlylink {\n\tcolor: <<colour sidebar-tiddler-link-foreground>>;\n}\n\n.tc-sidebar-lists a.tc-tiddlylink:hover {\n\tcolor: <<colour sidebar-tiddler-link-foreground-hover>>;\n}\n\nbutton.tc-tiddlylink:hover,\na.tc-tiddlylink:hover {\n\ttext-decoration: underline;\n}\n\na.tc-tiddlylink-resolves {\n}\n\na.tc-tiddlylink-shadow {\n\tfont-weight: bold;\n}\n\na.tc-tiddlylink-shadow.tc-tiddlylink-resolves {\n\tfont-weight: normal;\n}\n\na.tc-tiddlylink-missing {\n\tfont-style: italic;\n}\n\na.tc-tiddlylink-external {\n\ttext-decoration: underline;\n\tcolor: <<colour external-link-foreground>>;\n\tbackground-color: <<colour external-link-background>>;\n}\n\na.tc-tiddlylink-external:visited {\n\tcolor: <<colour external-link-foreground-visited>>;\n\tbackground-color: <<colour external-link-background-visited>>;\n}\n\na.tc-tiddlylink-external:hover {\n\tcolor: <<colour external-link-foreground-hover>>;\n\tbackground-color: <<colour external-link-background-hover>>;\n}\n\n/*\n** Drag and drop styles\n*/\n\n.tc-tiddler-dragger {\n\tposition: relative;\n\tz-index: -10000;\n}\n\n.tc-tiddler-dragger-inner {\n\tposition: absolute;\n\ttop: -1000px;\n\tleft: -1000px;\n\tdisplay: inline-block;\n\tpadding: 8px 20px;\n\tfont-size: 16.9px;\n\tfont-weight: bold;\n\tline-height: 20px;\n\tcolor: <<colour dragger-foreground>>;\n\ttext-shadow: 0 1px 0 rgba(0, 0, 0, 1);\n\twhite-space: nowrap;\n\tvertical-align: baseline;\n\tbackground-color: <<colour dragger-background>>;\n\tborder-radius: 20px;\n}\n\n.tc-tiddler-dragger-cover {\n\tposition: absolute;\n\tbackground-color: <<colour page-background>>;\n}\n\n.tc-dropzone {\n\tposition: relative;\n}\n\n.tc-dropzone.tc-dragover:before {\n\tz-index: 10000;\n\tdisplay: block;\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbackground: <<colour dropzone-background>>;\n\ttext-align: center;\n\tcontent: \"<<lingo DropMessage>>\";\n}\n\n.tc-droppable > .tc-droppable-placeholder {\n\tdisplay: none;\n}\n\n.tc-droppable.tc-dragover > .tc-droppable-placeholder {\n\tdisplay: block;\n\tborder: 2px dashed <<colour dropzone-background>>;\n}\n\n.tc-draggable {\n\tcursor: move;\n}\n\n/*\n** Plugin reload warning\n*/\n\n.tc-plugin-reload-warning {\n\tz-index: 1000;\n\tdisplay: block;\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbackground: <<colour alert-background>>;\n\ttext-align: center;\n}\n\n/*\n** Buttons\n*/\n\nbutton svg, button img, label svg, label img {\n\tvertical-align: middle;\n}\n\n.tc-btn-invisible {\n\tpadding: 0;\n\tmargin: 0;\n\tbackground: none;\n\tborder: none;\n cursor: pointer;\n}\n\n.tc-btn-boxed {\n\tfont-size: 0.6em;\n\tpadding: 0.2em;\n\tmargin: 1px;\n\tbackground: none;\n\tborder: 1px solid <<colour tiddler-controls-foreground>>;\n\tborder-radius: 0.25em;\n}\n\nhtml body.tc-body .tc-btn-boxed svg {\n\tfont-size: 1.6666em;\n}\n\n.tc-btn-boxed:hover {\n\tbackground: <<colour muted-foreground>>;\n\tcolor: <<colour background>>;\n}\n\nhtml body.tc-body .tc-btn-boxed:hover svg {\n\tfill: <<colour background>>;\n}\n\n.tc-btn-rounded {\n\tfont-size: 0.5em;\n\tline-height: 2;\n\tpadding: 0em 0.3em 0.2em 0.4em;\n\tmargin: 1px;\n\tborder: 1px solid <<colour muted-foreground>>;\n\tbackground: <<colour muted-foreground>>;\n\tcolor: <<colour background>>;\n\tborder-radius: 2em;\n}\n\nhtml body.tc-body .tc-btn-rounded svg {\n\tfont-size: 1.6666em;\n\tfill: <<colour background>>;\n}\n\n.tc-btn-rounded:hover {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tbackground: <<colour background>>;\n\tcolor: <<colour muted-foreground>>;\n}\n\nhtml body.tc-body .tc-btn-rounded:hover svg {\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-btn-icon svg {\n\theight: 1em;\n\twidth: 1em;\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-btn-text {\n\tpadding: 0;\n\tmargin: 0;\n}\n\n.tc-btn-big-green {\n\tdisplay: inline-block;\n\tpadding: 8px;\n\tmargin: 4px 8px 4px 8px;\n\tbackground: <<colour download-background>>;\n\tcolor: <<colour download-foreground>>;\n\tfill: <<colour download-foreground>>;\n\tborder: none;\n\tfont-size: 1.2em;\n\tline-height: 1.4em;\n\ttext-decoration: none;\n}\n\n.tc-btn-big-green svg,\n.tc-btn-big-green img {\n\theight: 2em;\n\twidth: 2em;\n\tvertical-align: middle;\n\tfill: <<colour download-foreground>>;\n}\n\n.tc-sidebar-lists input {\n\tcolor: <<colour foreground>>;\n}\n\n.tc-sidebar-lists button {\n\tcolor: <<colour sidebar-button-foreground>>;\n\tfill: <<colour sidebar-button-foreground>>;\n}\n\n.tc-sidebar-lists button.tc-btn-mini {\n\tcolor: <<colour sidebar-muted-foreground>>;\n}\n\n.tc-sidebar-lists button.tc-btn-mini:hover {\n\tcolor: <<colour sidebar-muted-foreground-hover>>;\n}\n\nbutton svg.tc-image-button, button .tc-image-button img {\n\theight: 1em;\n\twidth: 1em;\n}\n\n.tc-unfold-banner {\n\tposition: absolute;\n\tpadding: 0;\n\tmargin: 0;\n\tbackground: none;\n\tborder: none;\n\twidth: 100%;\n\twidth: calc(100% + 2px);\n\tmargin-left: -43px;\n\ttext-align: center;\n\tborder-top: 2px solid <<colour tiddler-info-background>>;\n\tmargin-top: 4px;\n}\n\n.tc-unfold-banner:hover {\n\tbackground: <<colour tiddler-info-background>>;\n\tborder-top: 2px solid <<colour tiddler-info-border>>;\n}\n\n.tc-unfold-banner svg, .tc-fold-banner svg {\n\theight: 0.75em;\n\tfill: <<colour tiddler-controls-foreground>>;\n}\n\n.tc-unfold-banner:hover svg, .tc-fold-banner:hover svg {\n\tfill: <<colour tiddler-controls-foreground-hover>>;\n}\n\n.tc-fold-banner {\n\tposition: absolute;\n\tpadding: 0;\n\tmargin: 0;\n\tbackground: none;\n\tborder: none;\n\twidth: 23px;\n\ttext-align: center;\n\tmargin-left: -35px;\n\ttop: 6px;\n\tbottom: 6px;\n}\n\n.tc-fold-banner:hover {\n\tbackground: <<colour tiddler-info-background>>;\n}\n\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\t.tc-unfold-banner {\n\t\tposition: static;\n\t\twidth: calc(100% + 59px);\n\t}\n\n\t.tc-fold-banner {\n\t\twidth: 16px;\n\t\tmargin-left: -16px;\n\t\tfont-size: 0.75em;\n\t}\n\n}\n\n/*\n** Tags and missing tiddlers\n*/\n\n.tc-tag-list-item {\n\tposition: relative;\n\tdisplay: inline-block;\n\tmargin-right: 7px;\n}\n\n.tc-tags-wrapper {\n\tmargin: 4px 0 14px 0;\n}\n\n.tc-missing-tiddler-label {\n\tfont-style: italic;\n\tfont-weight: normal;\n\tdisplay: inline-block;\n\tfont-size: 11.844px;\n\tline-height: 14px;\n\twhite-space: nowrap;\n\tvertical-align: baseline;\n}\n\nbutton.tc-tag-label, span.tc-tag-label {\n\tdisplay: inline-block;\n\tpadding: 0.16em 0.7em;\n\tfont-size: 0.9em;\n\tfont-weight: 400;\n\tline-height: 1.2em;\n\tcolor: <<colour tag-foreground>>;\n\twhite-space: nowrap;\n\tvertical-align: baseline;\n\tbackground-color: <<colour tag-background>>;\n\tborder-radius: 1em;\n}\n\n.tc-untagged-separator {\n\twidth: 10em;\n\tleft: 0;\n\tmargin-left: 0;\n\tborder: 0;\n\theight: 1px;\n\tbackground: <<colour tab-divider>>;\n}\n\nbutton.tc-untagged-label {\n\tbackground-color: <<colour untagged-background>>;\n}\n\n.tc-tag-label svg, .tc-tag-label img {\n\theight: 1em;\n\twidth: 1em;\n\tfill: <<colour tag-foreground>>;\n\tvertical-align: text-bottom;\n}\n\n.tc-tag-manager-table .tc-tag-label {\n\twhite-space: normal;\n}\n\n.tc-tag-manager-tag {\n\twidth: 100%;\n}\n\n/*\n** Page layout\n*/\n\n.tc-topbar {\n\tposition: fixed;\n\tz-index: 1200;\n}\n\n.tc-topbar-left {\n\tleft: 29px;\n\ttop: 5px;\n}\n\n.tc-topbar-right {\n\ttop: 5px;\n\tright: 29px;\n}\n\n.tc-topbar button {\n\tpadding: 8px;\n}\n\n.tc-topbar svg {\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-topbar button:hover svg {\n\tfill: <<colour foreground>>;\n}\n\n.tc-sidebar-header {\n\tcolor: <<colour sidebar-foreground>>;\n\tfill: <<colour sidebar-foreground>>;\n}\n\n.tc-sidebar-header .tc-title a.tc-tiddlylink-resolves {\n\tfont-weight: 300;\n}\n\n.tc-sidebar-header .tc-sidebar-lists p {\n\tmargin-top: 3px;\n\tmargin-bottom: 3px;\n}\n\n.tc-sidebar-header .tc-missing-tiddler-label {\n\tcolor: <<colour sidebar-foreground>>;\n}\n\n.tc-advanced-search input {\n\twidth: 60%;\n}\n\n.tc-search a svg {\n\twidth: 1.2em;\n\theight: 1.2em;\n\tvertical-align: middle;\n}\n\n.tc-page-controls {\n\tmargin-top: 14px;\n\tfont-size: 1.5em;\n}\n\n.tc-page-controls button {\n\tmargin-right: 0.5em;\n}\n\n.tc-page-controls a.tc-tiddlylink:hover {\n\ttext-decoration: none;\n}\n\n.tc-page-controls img {\n\twidth: 1em;\n}\n\n.tc-page-controls svg {\n\tfill: <<colour sidebar-controls-foreground>>;\n}\n\n.tc-page-controls button:hover svg, .tc-page-controls a:hover svg {\n\tfill: <<colour sidebar-controls-foreground-hover>>;\n}\n\n.tc-menu-list-item {\n\twhite-space: nowrap;\n}\n\n.tc-menu-list-count {\n\tfont-weight: bold;\n}\n\n.tc-menu-list-subitem {\n\tpadding-left: 7px;\n}\n\n.tc-story-river {\n\tposition: relative;\n}\n\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\t.tc-sidebar-header {\n\t\tpadding: 14px;\n\t\tmin-height: 32px;\n\t\tmargin-top: {{$:/themes/tiddlywiki/vanilla/metrics/storytop}};\n\t}\n\n\t.tc-story-river {\n\t\tposition: relative;\n\t\tpadding: 0;\n\t}\n}\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\t.tc-message-box {\n\t\tmargin: 21px -21px 21px -21px;\n\t}\n\n\t.tc-sidebar-scrollable {\n\t\tposition: fixed;\n\t\ttop: {{$:/themes/tiddlywiki/vanilla/metrics/storytop}};\n\t\tleft: {{$:/themes/tiddlywiki/vanilla/metrics/storyright}};\n\t\tbottom: 0;\n\t\tright: 0;\n\t\toverflow-y: auto;\n\t\toverflow-x: auto;\n\t\t-webkit-overflow-scrolling: touch;\n\t\tmargin: 0 0 0 -42px;\n\t\tpadding: 71px 0 28px 42px;\n\t}\n\n\thtml[dir=\"rtl\"] .tc-sidebar-scrollable {\n\t\tleft: auto;\n\t\tright: {{$:/themes/tiddlywiki/vanilla/metrics/storyright}};\n\t}\n\n\t.tc-story-river {\n\t\tposition: relative;\n\t\tleft: {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}};\n\t\ttop: {{$:/themes/tiddlywiki/vanilla/metrics/storytop}};\n\t\twidth: {{$:/themes/tiddlywiki/vanilla/metrics/storywidth}};\n\t\tpadding: 42px 42px 42px 42px;\n\t}\n\n<<if-no-sidebar \"\n\n\t.tc-story-river {\n\t\twidth: calc(100% - {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}});\n\t}\n\n\">>\n\n}\n\n@media print {\n\n\tbody.tc-body {\n\t\tbackground-color: transparent;\n\t}\n\n\t.tc-sidebar-header, .tc-topbar {\n\t\tdisplay: none;\n\t}\n\n\t.tc-story-river {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t}\n\n\t.tc-story-river .tc-tiddler-frame {\n\t\tmargin: 0;\n\t\tborder: none;\n\t\tpadding: 0;\n\t}\n}\n\n/*\n** Tiddler styles\n*/\n\n.tc-tiddler-frame {\n\tposition: relative;\n\tmargin-bottom: 28px;\n\tbackground-color: <<colour tiddler-background>>;\n\tborder: 1px solid <<colour tiddler-border>>;\n}\n\n{{$:/themes/tiddlywiki/vanilla/sticky}}\n\n.tc-tiddler-info {\n\tpadding: 14px 42px 14px 42px;\n\tbackground-color: <<colour tiddler-info-background>>;\n\tborder-top: 1px solid <<colour tiddler-info-border>>;\n\tborder-bottom: 1px solid <<colour tiddler-info-border>>;\n}\n\n.tc-tiddler-info p {\n\tmargin-top: 3px;\n\tmargin-bottom: 3px;\n}\n\n.tc-tiddler-info .tc-tab-buttons button.tc-tab-selected {\n\tbackground-color: <<colour tiddler-info-tab-background>>;\n\tborder-bottom: 1px solid <<colour tiddler-info-tab-background>>;\n}\n\n.tc-view-field-table {\n\twidth: 100%;\n}\n\n.tc-view-field-name {\n\twidth: 1%; /* Makes this column be as narrow as possible */\n\ttext-align: right;\n\tfont-style: italic;\n\tfont-weight: 200;\n}\n\n.tc-view-field-value {\n}\n\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\t.tc-tiddler-frame {\n\t\tpadding: 14px 14px 14px 14px;\n\t}\n\n\t.tc-tiddler-info {\n\t\tmargin: 0 -14px 0 -14px;\n\t}\n}\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\t.tc-tiddler-frame {\n\t\tpadding: 28px 42px 42px 42px;\n\t\twidth: {{$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth}};\n\t\tborder-radius: 2px;\n\t}\n\n<<if-no-sidebar \"\n\n\t.tc-tiddler-frame {\n\t\twidth: 100%;\n\t}\n\n\">>\n\n\t.tc-tiddler-info {\n\t\tmargin: 0 -42px 0 -42px;\n\t}\n}\n\n.tc-site-title,\n.tc-titlebar {\n\tfont-weight: 300;\n\tfont-size: 2.35em;\n\tline-height: 1.2em;\n\tcolor: <<colour tiddler-title-foreground>>;\n\tmargin: 0;\n}\n\n.tc-site-title {\n\tcolor: <<colour site-title-foreground>>;\n}\n\n.tc-tiddler-title-icon {\n\tvertical-align: middle;\n}\n\n.tc-system-title-prefix {\n\tcolor: <<colour muted-foreground>>;\n}\n\n.tc-titlebar h2 {\n\tfont-size: 1em;\n\tdisplay: inline;\n}\n\n.tc-titlebar img {\n\theight: 1em;\n}\n\n.tc-subtitle {\n\tfont-size: 0.9em;\n\tcolor: <<colour tiddler-subtitle-foreground>>;\n\tfont-weight: 300;\n}\n\n.tc-tiddler-missing .tc-title {\n font-style: italic;\n font-weight: normal;\n}\n\n.tc-tiddler-frame .tc-tiddler-controls {\n\tfloat: right;\n}\n\n.tc-tiddler-controls .tc-drop-down {\n\tfont-size: 0.6em;\n}\n\n.tc-tiddler-controls .tc-drop-down .tc-drop-down {\n\tfont-size: 1em;\n}\n\n.tc-tiddler-controls > span > button {\n\tvertical-align: baseline;\n\tmargin-left:5px;\n}\n\n.tc-tiddler-controls button svg, .tc-tiddler-controls button img,\n.tc-search button svg, .tc-search a svg {\n\tfill: <<colour tiddler-controls-foreground>>;\n}\n\n.tc-tiddler-controls button svg, .tc-tiddler-controls button img {\n\theight: 0.75em;\n}\n\n.tc-search button svg, .tc-search a svg {\n height: 1.2em;\n width: 1.2em;\n margin: 0 0.25em;\n}\n\n.tc-tiddler-controls button.tc-selected svg,\n.tc-page-controls button.tc-selected svg {\n\tfill: <<colour tiddler-controls-foreground-selected>>;\n}\n\n.tc-tiddler-controls button.tc-btn-invisible:hover svg,\n.tc-search button:hover svg, .tc-search a:hover svg {\n\tfill: <<colour tiddler-controls-foreground-hover>>;\n}\n\n@media print {\n\t.tc-tiddler-controls {\n\t\tdisplay: none;\n\t}\n}\n\n.tc-tiddler-help { /* Help prompts within tiddler template */\n\tcolor: <<colour muted-foreground>>;\n\tmargin-top: 14px;\n}\n\n.tc-tiddler-help a.tc-tiddlylink {\n\tcolor: <<colour very-muted-foreground>>;\n}\n\n.tc-tiddler-frame .tc-edit-texteditor {\n\twidth: 100%;\n\tmargin: 4px 0 4px 0;\n}\n\n.tc-tiddler-frame input.tc-edit-texteditor,\n.tc-tiddler-frame textarea.tc-edit-texteditor,\n.tc-tiddler-frame iframe.tc-edit-texteditor {\n\tpadding: 3px 3px 3px 3px;\n\tborder: 1px solid <<colour tiddler-editor-border>>;\n\tbackground-color: <<colour tiddler-editor-background>>;\n\tline-height: 1.3em;\n\t-webkit-appearance: none;\n}\n\n.tc-tiddler-frame .tc-binary-warning {\n\twidth: 100%;\n\theight: 5em;\n\ttext-align: center;\n\tpadding: 3em 3em 6em 3em;\n\tbackground: <<colour alert-background>>;\n\tborder: 1px solid <<colour alert-border>>;\n}\n\ncanvas.tc-edit-bitmapeditor {\n\tborder: 6px solid <<colour tiddler-editor-border-image>>;\n\tcursor: crosshair;\n\t-moz-user-select: none;\n\t-webkit-user-select: none;\n\t-ms-user-select: none;\n\tmargin-top: 6px;\n\tmargin-bottom: 6px;\n}\n\n.tc-edit-bitmapeditor-width {\n\tdisplay: block;\n}\n\n.tc-edit-bitmapeditor-height {\n\tdisplay: block;\n}\n\n.tc-tiddler-body {\n\tclear: both;\n}\n\n.tc-tiddler-frame .tc-tiddler-body {\n\tfont-size: {{$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize}};\n\tline-height: {{$:/themes/tiddlywiki/vanilla/metrics/bodylineheight}};\n}\n\n.tc-titlebar, .tc-tiddler-edit-title {\n\toverflow: hidden; /* https://github.com/Jermolene/TiddlyWiki5/issues/282 */\n}\n\nhtml body.tc-body.tc-single-tiddler-window {\n\tmargin: 1em;\n\tbackground: <<colour tiddler-background>>;\n}\n\n.tc-single-tiddler-window img,\n.tc-single-tiddler-window svg,\n.tc-single-tiddler-window canvas,\n.tc-single-tiddler-window embed,\n.tc-single-tiddler-window iframe {\n\tmax-width: 100%;\n}\n\n/*\n** Editor\n*/\n\n.tc-editor-toolbar {\n\tmargin-top: 8px;\n}\n\n.tc-editor-toolbar button {\n\tvertical-align: middle;\n\tbackground-color: <<colour tiddler-controls-foreground>>;\n\tfill: <<colour tiddler-controls-foreground-selected>>;\n\tborder-radius: 4px;\n\tpadding: 3px;\n\tmargin: 2px 0 2px 4px;\n}\n\n.tc-editor-toolbar button.tc-text-editor-toolbar-item-adjunct {\n\tmargin-left: 1px;\n\twidth: 1em;\n\tborder-radius: 8px;\n}\n\n.tc-editor-toolbar button.tc-text-editor-toolbar-item-start-group {\n\tmargin-left: 11px;\n}\n\n.tc-editor-toolbar button.tc-selected {\n\tbackground-color: <<colour primary>>;\n}\n\n.tc-editor-toolbar button svg {\n\twidth: 1.6em;\n\theight: 1.2em;\n}\n\n.tc-editor-toolbar button:hover {\n\tbackground-color: <<colour tiddler-controls-foreground-selected>>;\n\tfill: <<colour background>>;\n}\n\n.tc-editor-toolbar .tc-text-editor-toolbar-more {\n\twhite-space: normal;\n}\n\n.tc-editor-toolbar .tc-text-editor-toolbar-more button {\n\tdisplay: inline-block;\n\tpadding: 3px;\n\twidth: auto;\n}\n\n.tc-editor-toolbar .tc-search-results {\n\tpadding: 0;\n}\n\n/*\n** Adjustments for fluid-fixed mode\n*/\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n<<if-fluid-fixed text:\"\"\"\n\n\t.tc-story-river {\n\t\tpadding-right: 0;\n\t\tposition: relative;\n\t\twidth: auto;\n\t\tleft: 0;\n\t\tmargin-left: {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}};\n\t\tmargin-right: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}};\n\t}\n\n\t.tc-tiddler-frame {\n\t\twidth: 100%;\n\t}\n\n\t.tc-sidebar-scrollable {\n\t\tleft: auto;\n\t\tbottom: 0;\n\t\tright: 0;\n\t\twidth: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}};\n\t}\n\n\tbody.tc-body .tc-storyview-zoomin-tiddler {\n\t\twidth: 100%;\n\t\twidth: calc(100% - 42px);\n\t}\n\n\"\"\" hiddenSidebarText:\"\"\"\n\n\t.tc-story-river {\n\t\tpadding-right: 3em;\n\t\tmargin-right: 0;\n\t}\n\n\tbody.tc-body .tc-storyview-zoomin-tiddler {\n\t\twidth: 100%;\n\t\twidth: calc(100% - 84px);\n\t}\n\n\"\"\">>\n\n}\n\n/*\n** Toolbar buttons\n*/\n\n.tc-page-controls svg.tc-image-new-button {\n fill: <<colour toolbar-new-button>>;\n}\n\n.tc-page-controls svg.tc-image-options-button {\n fill: <<colour toolbar-options-button>>;\n}\n\n.tc-page-controls svg.tc-image-save-button {\n fill: <<colour toolbar-save-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-info-button {\n fill: <<colour toolbar-info-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-edit-button {\n fill: <<colour toolbar-edit-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-close-button {\n fill: <<colour toolbar-close-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-delete-button {\n fill: <<colour toolbar-delete-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-cancel-button {\n fill: <<colour toolbar-cancel-button>>;\n}\n\n.tc-tiddler-controls button svg.tc-image-done-button {\n fill: <<colour toolbar-done-button>>;\n}\n\n/*\n** Tiddler edit mode\n*/\n\n.tc-tiddler-edit-frame em.tc-edit {\n\tcolor: <<colour muted-foreground>>;\n\tfont-style: normal;\n}\n\n.tc-edit-type-dropdown a.tc-tiddlylink-missing {\n\tfont-style: normal;\n}\n\n.tc-edit-tags {\n\tborder: 1px solid <<colour tiddler-editor-border>>;\n\tpadding: 4px 8px 4px 8px;\n}\n\n.tc-edit-add-tag {\n\tdisplay: inline-block;\n}\n\n.tc-edit-add-tag .tc-add-tag-name input {\n\twidth: 50%;\n}\n\n.tc-edit-add-tag .tc-keyboard {\n\tdisplay:inline;\n}\n\n.tc-edit-tags .tc-tag-label {\n\tdisplay: inline-block;\n}\n\n.tc-edit-tags-list {\n\tmargin: 14px 0 14px 0;\n}\n\n.tc-remove-tag-button {\n\tpadding-left: 4px;\n}\n\n.tc-tiddler-preview {\n\toverflow: auto;\n}\n\n.tc-tiddler-preview-preview {\n\tfloat: right;\n\twidth: 49%;\n\tborder: 1px solid <<colour tiddler-editor-border>>;\n\tmargin: 4px 0 3px 3px;\n\tpadding: 3px 3px 3px 3px;\n}\n\n<<if-editor-height-fixed then:\"\"\"\n\n.tc-tiddler-preview-preview {\n\toverflow-y: scroll;\n\theight: {{$:/config/TextEditor/EditorHeight/Height}};\n}\n\n\"\"\">>\n\n.tc-tiddler-frame .tc-tiddler-preview .tc-edit-texteditor {\n\twidth: 49%;\n}\n\n.tc-tiddler-frame .tc-tiddler-preview canvas.tc-edit-bitmapeditor {\n\tmax-width: 49%;\n}\n\n.tc-edit-fields {\n\twidth: 100%;\n}\n\n\n.tc-edit-fields table, .tc-edit-fields tr, .tc-edit-fields td {\n\tborder: none;\n\tpadding: 4px;\n}\n\n.tc-edit-fields > tbody > .tc-edit-field:nth-child(odd) {\n\tbackground-color: <<colour tiddler-editor-fields-odd>>;\n}\n\n.tc-edit-fields > tbody > .tc-edit-field:nth-child(even) {\n\tbackground-color: <<colour tiddler-editor-fields-even>>;\n}\n\n.tc-edit-field-name {\n\ttext-align: right;\n}\n\n.tc-edit-field-value input {\n\twidth: 100%;\n}\n\n.tc-edit-field-remove {\n}\n\n.tc-edit-field-remove svg {\n\theight: 1em;\n\twidth: 1em;\n\tfill: <<colour muted-foreground>>;\n\tvertical-align: middle;\n}\n\n.tc-edit-field-add-name {\n\tdisplay: inline-block;\n\twidth: 15%;\n}\n\n.tc-edit-field-add-value {\n\tdisplay: inline-block;\n\twidth: 40%;\n}\n\n.tc-edit-field-add-button {\n\tdisplay: inline-block;\n\twidth: 10%;\n}\n\n/*\n** Storyview Classes\n*/\n\n.tc-storyview-zoomin-tiddler {\n\tposition: absolute;\n\tdisplay: block;\n\twidth: 100%;\n}\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\t.tc-storyview-zoomin-tiddler {\n\t\twidth: calc(100% - 84px);\n\t}\n\n}\n\n/*\n** Dropdowns\n*/\n\n.tc-btn-dropdown {\n\ttext-align: left;\n}\n\n.tc-btn-dropdown svg, .tc-btn-dropdown img {\n\theight: 1em;\n\twidth: 1em;\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-drop-down-wrapper {\n\tposition: relative;\n}\n\n.tc-drop-down {\n\tmin-width: 380px;\n\tborder: 1px solid <<colour dropdown-border>>;\n\tbackground-color: <<colour dropdown-background>>;\n\tpadding: 7px 0 7px 0;\n\tmargin: 4px 0 0 0;\n\twhite-space: nowrap;\n\ttext-shadow: none;\n\tline-height: 1.4;\n}\n\n.tc-drop-down .tc-drop-down {\n\tmargin-left: 14px;\n}\n\n.tc-drop-down button svg, .tc-drop-down a svg {\n\tfill: <<colour foreground>>;\n}\n\n.tc-drop-down button.tc-btn-invisible:hover svg {\n\tfill: <<colour foreground>>;\n}\n\n.tc-drop-down p {\n\tpadding: 0 14px 0 14px;\n}\n\n.tc-drop-down svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\n.tc-drop-down img {\n\twidth: 1em;\n}\n\n.tc-drop-down-language-chooser img {\n\twidth: 2em;\n\tvertical-align: baseline;\n}\n\n.tc-drop-down a, .tc-drop-down button {\n\tdisplay: block;\n\tpadding: 0 14px 0 14px;\n\twidth: 100%;\n\ttext-align: left;\n\tcolor: <<colour foreground>>;\n\tline-height: 1.4;\n}\n\n.tc-drop-down .tc-tab-set .tc-tab-buttons button {\n\tdisplay: inline-block;\n width: auto;\n margin-bottom: 0px;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.tc-drop-down .tc-prompt {\n\tpadding: 0 14px;\n}\n\n.tc-drop-down .tc-chooser {\n\tborder: none;\n}\n\n.tc-drop-down .tc-chooser .tc-swatches-horiz {\n\tfont-size: 0.4em;\n\tpadding-left: 1.2em;\n}\n\n.tc-drop-down .tc-file-input-wrapper {\n\twidth: 100%;\n}\n\n.tc-drop-down .tc-file-input-wrapper button {\n\tcolor: <<colour foreground>>;\n}\n\n.tc-drop-down a:hover, .tc-drop-down button:hover, .tc-drop-down .tc-file-input-wrapper:hover button {\n\tcolor: <<colour tiddler-link-background>>;\n\tbackground-color: <<colour tiddler-link-foreground>>;\n\ttext-decoration: none;\n}\n\n.tc-drop-down .tc-tab-buttons button {\n\tbackground-color: <<colour dropdown-tab-background>>;\n}\n\n.tc-drop-down .tc-tab-buttons button.tc-tab-selected {\n\tbackground-color: <<colour dropdown-tab-background-selected>>;\n\tborder-bottom: 1px solid <<colour dropdown-tab-background-selected>>;\n}\n\n.tc-drop-down-bullet {\n\tdisplay: inline-block;\n\twidth: 0.5em;\n}\n\n.tc-drop-down .tc-tab-contents a {\n\tpadding: 0 0.5em 0 0.5em;\n}\n\n.tc-block-dropdown-wrapper {\n\tposition: relative;\n}\n\n.tc-block-dropdown {\n\tposition: absolute;\n\tmin-width: 220px;\n\tborder: 1px solid <<colour dropdown-border>>;\n\tbackground-color: <<colour dropdown-background>>;\n\tpadding: 7px 0;\n\tmargin: 4px 0 0 0;\n\twhite-space: nowrap;\n\tz-index: 1000;\n\ttext-shadow: none;\n}\n\n.tc-block-dropdown.tc-search-drop-down {\n\tmargin-left: -12px;\n}\n\n.tc-block-dropdown a {\n\tdisplay: block;\n\tpadding: 4px 14px 4px 14px;\n}\n\n.tc-block-dropdown.tc-search-drop-down a {\n\tdisplay: block;\n\tpadding: 0px 10px 0px 10px;\n}\n\n.tc-drop-down .tc-dropdown-item-plain,\n.tc-block-dropdown .tc-dropdown-item-plain {\n\tpadding: 4px 14px 4px 7px;\n}\n\n.tc-drop-down .tc-dropdown-item,\n.tc-block-dropdown .tc-dropdown-item {\n\tpadding: 4px 14px 4px 7px;\n\tcolor: <<colour muted-foreground>>;\n}\n\n.tc-block-dropdown a:hover {\n\tcolor: <<colour tiddler-link-background>>;\n\tbackground-color: <<colour tiddler-link-foreground>>;\n\ttext-decoration: none;\n}\n\n.tc-search-results {\n\tpadding: 0 7px 0 7px;\n}\n\n.tc-image-chooser, .tc-colour-chooser {\n\twhite-space: normal;\n}\n\n.tc-image-chooser a,\n.tc-colour-chooser a {\n\tdisplay: inline-block;\n\tvertical-align: top;\n\ttext-align: center;\n\tposition: relative;\n}\n\n.tc-image-chooser a {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tpadding: 2px;\n\tmargin: 2px;\n\twidth: 4em;\n\theight: 4em;\n}\n\n.tc-colour-chooser a {\n\tpadding: 3px;\n\twidth: 2em;\n\theight: 2em;\n\tvertical-align: middle;\n}\n\n.tc-image-chooser a:hover,\n.tc-colour-chooser a:hover {\n\tbackground: <<colour primary>>;\n\tpadding: 0px;\n\tborder: 3px solid <<colour primary>>;\n}\n\n.tc-image-chooser a svg,\n.tc-image-chooser a img {\n\tdisplay: inline-block;\n\twidth: auto;\n\theight: auto;\n\tmax-width: 3.5em;\n\tmax-height: 3.5em;\n\tposition: absolute;\n\ttop: 0;\n\tbottom: 0;\n\tleft: 0;\n\tright: 0;\n\tmargin: auto;\n}\n\n/*\n** Modals\n*/\n\n.tc-modal-wrapper {\n\tposition: fixed;\n\toverflow: auto;\n\toverflow-y: scroll;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\tleft: 0;\n\tz-index: 900;\n}\n\n.tc-modal-backdrop {\n\tposition: fixed;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\tleft: 0;\n\tz-index: 1000;\n\tbackground-color: <<colour modal-backdrop>>;\n}\n\n.tc-modal {\n\tz-index: 1100;\n\tbackground-color: <<colour modal-background>>;\n\tborder: 1px solid <<colour modal-border>>;\n}\n\n@media (max-width: 55em) {\n\t.tc-modal {\n\t\tposition: fixed;\n\t\ttop: 1em;\n\t\tleft: 1em;\n\t\tright: 1em;\n\t}\n\n\t.tc-modal-body {\n\t\toverflow-y: auto;\n\t\tmax-height: 400px;\n\t\tmax-height: 60vh;\n\t}\n}\n\n@media (min-width: 55em) {\n\t.tc-modal {\n\t\tposition: fixed;\n\t\ttop: 2em;\n\t\tleft: 25%;\n\t\twidth: 50%;\n\t}\n\n\t.tc-modal-body {\n\t\toverflow-y: auto;\n\t\tmax-height: 400px;\n\t\tmax-height: 60vh;\n\t}\n}\n\n.tc-modal-header {\n\tpadding: 9px 15px;\n\tborder-bottom: 1px solid <<colour modal-header-border>>;\n}\n\n.tc-modal-header h3 {\n\tmargin: 0;\n\tline-height: 30px;\n}\n\n.tc-modal-header img, .tc-modal-header svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\n.tc-modal-body {\n\tpadding: 15px;\n}\n\n.tc-modal-footer {\n\tpadding: 14px 15px 15px;\n\tmargin-bottom: 0;\n\ttext-align: right;\n\tbackground-color: <<colour modal-footer-background>>;\n\tborder-top: 1px solid <<colour modal-footer-border>>;\n}\n\n/*\n** Notifications\n*/\n\n.tc-notification {\n\tposition: fixed;\n\ttop: 14px;\n\tright: 42px;\n\tz-index: 1300;\n\tmax-width: 280px;\n\tpadding: 0 14px 0 14px;\n\tbackground-color: <<colour notification-background>>;\n\tborder: 1px solid <<colour notification-border>>;\n}\n\n/*\n** Tabs\n*/\n\n.tc-tab-set.tc-vertical {\n\tdisplay: -webkit-flex;\n\tdisplay: flex;\n}\n\n.tc-tab-buttons {\n\tfont-size: 0.85em;\n\tpadding-top: 1em;\n\tmargin-bottom: -2px;\n}\n\n.tc-tab-buttons.tc-vertical {\n\tz-index: 100;\n\tdisplay: block;\n\tpadding-top: 14px;\n\tvertical-align: top;\n\ttext-align: right;\n\tmargin-bottom: inherit;\n\tmargin-right: -1px;\n\tmax-width: 33%;\n\t-webkit-flex: 0 0 auto;\n\tflex: 0 0 auto;\n}\n\n.tc-tab-buttons button.tc-tab-selected {\n\tcolor: <<colour tab-foreground-selected>>;\n\tbackground-color: <<colour tab-background-selected>>;\n\tborder-left: 1px solid <<colour tab-border-selected>>;\n\tborder-top: 1px solid <<colour tab-border-selected>>;\n\tborder-right: 1px solid <<colour tab-border-selected>>;\n}\n\n.tc-tab-buttons button {\n\tcolor: <<colour tab-foreground>>;\n\tpadding: 3px 5px 3px 5px;\n\tmargin-right: 0.3em;\n\tfont-weight: 300;\n\tborder: none;\n\tbackground: inherit;\n\tbackground-color: <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-right: 1px solid <<colour tab-border>>;\n\tborder-top-left-radius: 2px;\n\tborder-top-right-radius: 2px;\n}\n\n.tc-tab-buttons.tc-vertical button {\n\tdisplay: block;\n\twidth: 100%;\n\tmargin-top: 3px;\n\tmargin-right: 0;\n\ttext-align: right;\n\tbackground-color: <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n\tborder-right: none;\n\tborder-top-left-radius: 2px;\n\tborder-bottom-left-radius: 2px;\n}\n\n.tc-tab-buttons.tc-vertical button.tc-tab-selected {\n\tbackground-color: <<colour tab-background-selected>>;\n\tborder-right: 1px solid <<colour tab-background-selected>>;\n}\n\n.tc-tab-divider {\n\tborder-top: 1px solid <<colour tab-divider>>;\n}\n\n.tc-tab-divider.tc-vertical {\n\tdisplay: none;\n}\n\n.tc-tab-content {\n\tmargin-top: 14px;\n}\n\n.tc-tab-content.tc-vertical {\n\tdisplay: inline-block;\n\tvertical-align: top;\n\tpadding-top: 0;\n\tpadding-left: 14px;\n\tborder-left: 1px solid <<colour tab-border>>;\n\t-webkit-flex: 1 0 70%;\n\tflex: 1 0 70%;\n}\n\n.tc-sidebar-lists .tc-tab-buttons {\n\tmargin-bottom: -1px;\n}\n\n.tc-sidebar-lists .tc-tab-buttons button.tc-tab-selected {\n\tbackground-color: <<colour sidebar-tab-background-selected>>;\n\tcolor: <<colour sidebar-tab-foreground-selected>>;\n\tborder-left: 1px solid <<colour sidebar-tab-border-selected>>;\n\tborder-top: 1px solid <<colour sidebar-tab-border-selected>>;\n\tborder-right: 1px solid <<colour sidebar-tab-border-selected>>;\n}\n\n.tc-sidebar-lists .tc-tab-buttons button {\n\tbackground-color: <<colour sidebar-tab-background>>;\n\tcolor: <<colour sidebar-tab-foreground>>;\n\tborder-left: 1px solid <<colour sidebar-tab-border>>;\n\tborder-top: 1px solid <<colour sidebar-tab-border>>;\n\tborder-right: 1px solid <<colour sidebar-tab-border>>;\n}\n\n.tc-sidebar-lists .tc-tab-divider {\n\tborder-top: 1px solid <<colour sidebar-tab-divider>>;\n}\n\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button {\n\tdisplay: block;\n\twidth: 100%;\n\tbackground-color: <<colour sidebar-tab-background>>;\n\tborder-top: none;\n\tborder-left: none;\n\tborder-bottom: none;\n\tborder-right: 1px solid #ccc;\n\tmargin-bottom: inherit;\n}\n\n.tc-more-sidebar > .tc-tab-set > .tc-tab-buttons > button.tc-tab-selected {\n\tbackground-color: <<colour sidebar-tab-background-selected>>;\n\tborder: none;\n}\n\n/*\n** Manager\n*/\n\n.tc-manager-wrapper {\n\t\n}\n\n.tc-manager-controls {\n\t\n}\n\n.tc-manager-control {\n\tmargin: 0.5em 0;\n}\n\n.tc-manager-list {\n\twidth: 100%;\n\tborder-top: 1px solid <<colour muted-foreground>>;\n\tborder-left: 1px solid <<colour muted-foreground>>;\n\tborder-right: 1px solid <<colour muted-foreground>>;\n}\n\n.tc-manager-list-item {\n\n}\n\n.tc-manager-list-item-heading {\n display: block;\n width: 100%;\n text-align: left;\t\n\tborder-bottom: 1px solid <<colour muted-foreground>>;\n\tpadding: 3px;\n}\n\n.tc-manager-list-item-heading-selected {\n\tfont-weight: bold;\n\tcolor: <<colour background>>;\n\tfill: <<colour background>>;\n\tbackground-color: <<colour foreground>>;\n}\n\n.tc-manager-list-item-heading:hover {\n\tbackground: <<colour primary>>;\n\tcolor: <<colour background>>;\n}\n\n.tc-manager-list-item-content {\n\tdisplay: flex;\n}\n\n.tc-manager-list-item-content-sidebar {\n flex: 1 0;\n background: <<colour tiddler-editor-background>>;\n border-right: 0.5em solid <<colour muted-foreground>>;\n border-bottom: 0.5em solid <<colour muted-foreground>>;\n white-space: nowrap;\n}\n\n.tc-manager-list-item-content-item-heading {\n\tdisplay: block;\n\twidth: 100%;\n\ttext-align: left;\n background: <<colour muted-foreground>>;\n\ttext-transform: uppercase;\n\tfont-size: 0.6em;\n\tfont-weight: bold;\n padding: 0.5em 0 0.5em 0;\n}\n\n.tc-manager-list-item-content-item-body {\n\tpadding: 0 0.5em 0 0.5em;\n}\n\n.tc-manager-list-item-content-item-body > pre {\n\tmargin: 0.5em 0 0.5em 0;\n\tborder: none;\n\tbackground: inherit;\n}\n\n.tc-manager-list-item-content-tiddler {\n flex: 3 1;\n border-left: 0.5em solid <<colour muted-foreground>>;\n border-right: 0.5em solid <<colour muted-foreground>>;\n border-bottom: 0.5em solid <<colour muted-foreground>>;\n}\n\n.tc-manager-list-item-content-item-body > table {\n\tborder: none;\n\tpadding: 0;\n\tmargin: 0;\n}\n\n.tc-manager-list-item-content-item-body > table td {\n\tborder: none;\n}\n\n.tc-manager-icon-editor > button {\n\twidth: 100%;\n}\n\n.tc-manager-icon-editor > button > svg,\n.tc-manager-icon-editor > button > button {\n\twidth: 100%;\n\theight: auto;\n}\n\n/*\n** Alerts\n*/\n\n.tc-alerts {\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\tmax-width: 500px;\n\tz-index: 20000;\n}\n\n.tc-alert {\n\tposition: relative;\n\tmargin: 28px;\n\tpadding: 14px 14px 14px 14px;\n\tborder: 2px solid <<colour alert-border>>;\n\tbackground-color: <<colour alert-background>>;\n}\n\n.tc-alert-toolbar {\n\tposition: absolute;\n\ttop: 14px;\n\tright: 14px;\n}\n\n.tc-alert-toolbar svg {\n\tfill: <<colour alert-muted-foreground>>;\n}\n\n.tc-alert-subtitle {\n\tcolor: <<colour alert-muted-foreground>>;\n\tfont-weight: bold;\n}\n\n.tc-alert-highlight {\n\tcolor: <<colour alert-highlight>>;\n}\n\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\n\n\t.tc-static-alert {\n\t\tposition: relative;\n\t}\n\n\t.tc-static-alert-inner {\n\t\tposition: absolute;\n\t\tz-index: 100;\n\t}\n\n}\n\n.tc-static-alert-inner {\n\tpadding: 0 2px 2px 42px;\n\tcolor: <<colour static-alert-foreground>>;\n}\n\n/*\n** Control panel\n*/\n\n.tc-control-panel td {\n\tpadding: 4px;\n}\n\n.tc-control-panel table, .tc-control-panel table input, .tc-control-panel table textarea {\n\twidth: 100%;\n}\n\n.tc-plugin-info {\n\tdisplay: block;\n\tborder: 1px solid <<colour muted-foreground>>;\n\tbackground-colour: <<colour background>>;\n\tmargin: 0.5em 0 0.5em 0;\n\tpadding: 4px;\n}\n\n.tc-plugin-info-disabled {\n\tbackground: -webkit-repeating-linear-gradient(45deg, #ff0, #ff0 10px, #eee 10px, #eee 20px);\n\tbackground: repeating-linear-gradient(45deg, #ff0, #ff0 10px, #eee 10px, #eee 20px);\n}\n\n.tc-plugin-info-disabled:hover {\n\tbackground: -webkit-repeating-linear-gradient(45deg, #aa0, #aa0 10px, #888 10px, #888 20px);\n\tbackground: repeating-linear-gradient(45deg, #aa0, #aa0 10px, #888 10px, #888 20px);\n}\n\na.tc-tiddlylink.tc-plugin-info:hover {\n\ttext-decoration: none;\n\tbackground-color: <<colour primary>>;\n\tcolor: <<colour background>>;\n\tfill: <<colour foreground>>;\n}\n\na.tc-tiddlylink.tc-plugin-info:hover .tc-plugin-info > .tc-plugin-info-chunk > svg {\n\tfill: <<colour foreground>>;\n}\n\n.tc-plugin-info-chunk {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n\n.tc-plugin-info-chunk h1 {\n\tfont-size: 1em;\n\tmargin: 2px 0 2px 0;\n}\n\n.tc-plugin-info-chunk h2 {\n\tfont-size: 0.8em;\n\tmargin: 2px 0 2px 0;\n}\n\n.tc-plugin-info-chunk div {\n\tfont-size: 0.7em;\n\tmargin: 2px 0 2px 0;\n}\n\n.tc-plugin-info:hover > .tc-plugin-info-chunk > img, .tc-plugin-info:hover > .tc-plugin-info-chunk > svg {\n\twidth: 2em;\n\theight: 2em;\n\tfill: <<colour foreground>>;\n}\n\n.tc-plugin-info > .tc-plugin-info-chunk > img, .tc-plugin-info > .tc-plugin-info-chunk > svg {\n\twidth: 2em;\n\theight: 2em;\n\tfill: <<colour muted-foreground>>;\n}\n\n.tc-plugin-info.tc-small-icon > .tc-plugin-info-chunk > img, .tc-plugin-info.tc-small-icon > .tc-plugin-info-chunk > svg {\n\twidth: 1em;\n\theight: 1em;\n}\n\n.tc-plugin-info-dropdown {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tmargin-top: -8px;\n}\n\n.tc-plugin-info-dropdown-message {\n\tbackground: <<colour message-background>>;\n\tpadding: 0.5em 1em 0.5em 1em;\n\tfont-weight: bold;\n\tfont-size: 0.8em;\n}\n\n.tc-plugin-info-dropdown-body {\n\tpadding: 1em 1em 1em 1em;\n}\n\n/*\n** Message boxes\n*/\n\n.tc-message-box {\n\tborder: 1px solid <<colour message-border>>;\n\tbackground: <<colour message-background>>;\n\tpadding: 0px 21px 0px 21px;\n\tfont-size: 12px;\n\tline-height: 18px;\n\tcolor: <<colour message-foreground>>;\n}\n\n.tc-message-box svg {\n\twidth: 1em;\n\theight: 1em;\n vertical-align: text-bottom;\n}\n\n/*\n** Pictures\n*/\n\n.tc-bordered-image {\n\tborder: 1px solid <<colour muted-foreground>>;\n\tpadding: 5px;\n\tmargin: 5px;\n}\n\n/*\n** Floats\n*/\n\n.tc-float-right {\n\tfloat: right;\n}\n\n/*\n** Chooser\n*/\n\n.tc-chooser {\n\tborder: 1px solid <<colour table-border>>;\n}\n\n.tc-chooser-item {\n\tborder: 8px;\n\tpadding: 2px 4px;\n}\n\n.tc-chooser-item a.tc-tiddlylink {\n\tdisplay: block;\n\ttext-decoration: none;\n\tcolor: <<colour tiddler-link-foreground>>;\n\tbackground-color: <<colour tiddler-link-background>>;\n}\n\n.tc-chooser-item a.tc-tiddlylink:hover {\n\ttext-decoration: none;\n\tcolor: <<colour tiddler-link-background>>;\n\tbackground-color: <<colour tiddler-link-foreground>>;\n}\n\n/*\n** Palette swatches\n*/\n\n.tc-swatches-horiz {\n}\n\n.tc-swatches-horiz .tc-swatch {\n\tdisplay: inline-block;\n}\n\n.tc-swatch {\n\twidth: 2em;\n\theight: 2em;\n\tmargin: 0.4em;\n\tborder: 1px solid #888;\n}\n\n/*\n** Table of contents\n*/\n\n.tc-sidebar-lists .tc-table-of-contents {\n\twhite-space: nowrap;\n}\n\n.tc-table-of-contents button {\n\tcolor: <<colour sidebar-foreground>>;\n}\n\n.tc-table-of-contents svg {\n\twidth: 0.7em;\n\theight: 0.7em;\n\tvertical-align: middle;\n\tfill: <<colour sidebar-foreground>>;\n}\n\n.tc-table-of-contents ol {\n\tlist-style-type: none;\n\tpadding-left: 0;\n}\n\n.tc-table-of-contents ol ol {\n\tpadding-left: 1em;\n}\n\n.tc-table-of-contents li {\n\tfont-size: 1.0em;\n\tfont-weight: bold;\n}\n\n.tc-table-of-contents li a {\n\tfont-weight: bold;\n}\n\n.tc-table-of-contents li li {\n\tfont-size: 0.95em;\n\tfont-weight: normal;\n\tline-height: 1.4;\n}\n\n.tc-table-of-contents li li a {\n\tfont-weight: normal;\n}\n\n.tc-table-of-contents li li li {\n\tfont-size: 0.95em;\n\tfont-weight: 200;\n\tline-height: 1.5;\n}\n\n.tc-table-of-contents li li li a {\n\tfont-weight: bold;\n}\n\n.tc-table-of-contents li li li li {\n\tfont-size: 0.95em;\n\tfont-weight: 200;\n}\n\n.tc-tabbed-table-of-contents {\n\tdisplay: -webkit-flex;\n\tdisplay: flex;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents {\n\tz-index: 100;\n\tdisplay: inline-block;\n\tpadding-left: 1em;\n\tmax-width: 50%;\n\t-webkit-flex: 0 0 auto;\n\tflex: 0 0 auto;\n\tbackground: <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item > a,\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item-selected > a {\n\tdisplay: block;\n\tpadding: 0.12em 1em 0.12em 0.25em;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item > a {\n\tborder-top: 1px solid <<colour tab-background>>;\n\tborder-left: 1px solid <<colour tab-background>>;\n\tborder-bottom: 1px solid <<colour tab-background>>;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item > a:hover {\n\ttext-decoration: none;\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n\tbackground: <<colour tab-border>>;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item-selected > a {\n\tborder-top: 1px solid <<colour tab-border>>;\n\tborder-left: 1px solid <<colour tab-border>>;\n\tborder-bottom: 1px solid <<colour tab-border>>;\n\tbackground: <<colour background>>;\n\tmargin-right: -1px;\n}\n\n.tc-tabbed-table-of-contents .tc-table-of-contents .toc-item-selected > a:hover {\n\ttext-decoration: none;\n}\n\n.tc-tabbed-table-of-contents .tc-tabbed-table-of-contents-content {\n\tdisplay: inline-block;\n\tvertical-align: top;\n\tpadding-left: 1.5em;\n\tpadding-right: 1.5em;\n\tborder: 1px solid <<colour tab-border>>;\n\t-webkit-flex: 1 0 50%;\n\tflex: 1 0 50%;\n}\n\n/*\n** Dirty indicator\n*/\n\nbody.tc-dirty span.tc-dirty-indicator, body.tc-dirty span.tc-dirty-indicator svg {\n\tfill: <<colour dirty-indicator>>;\n\tcolor: <<colour dirty-indicator>>;\n}\n\n/*\n** File inputs\n*/\n\n.tc-file-input-wrapper {\n\tposition: relative;\n\toverflow: hidden;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n\n.tc-file-input-wrapper input[type=file] {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tfont-size: 999px;\n\tmax-width: 100%;\n\tmax-height: 100%;\n\tfilter: alpha(opacity=0);\n\topacity: 0;\n\toutline: none;\n\tbackground: white;\n\tcursor: pointer;\n\tdisplay: inline-block;\n}\n\n/*\n** Thumbnail macros\n*/\n\n.tc-thumbnail-wrapper {\n\tposition: relative;\n\tdisplay: inline-block;\n\tmargin: 6px;\n\tvertical-align: top;\n}\n\n.tc-thumbnail-right-wrapper {\n\tfloat:right;\n\tmargin: 0.5em 0 0.5em 0.5em;\n}\n\n.tc-thumbnail-image {\n\ttext-align: center;\n\toverflow: hidden;\n\tborder-radius: 3px;\n}\n\n.tc-thumbnail-image svg,\n.tc-thumbnail-image img {\n\tfilter: alpha(opacity=1);\n\topacity: 1;\n\tmin-width: 100%;\n\tmin-height: 100%;\n\tmax-width: 100%;\n}\n\n.tc-thumbnail-wrapper:hover .tc-thumbnail-image svg,\n.tc-thumbnail-wrapper:hover .tc-thumbnail-image img {\n\tfilter: alpha(opacity=0.8);\n\topacity: 0.8;\n}\n\n.tc-thumbnail-background {\n\tposition: absolute;\n\tborder-radius: 3px;\n}\n\n.tc-thumbnail-icon svg,\n.tc-thumbnail-icon img {\n\twidth: 3em;\n\theight: 3em;\n\t<<filter \"drop-shadow(2px 2px 4px rgba(0,0,0,0.3))\">>\n}\n\n.tc-thumbnail-wrapper:hover .tc-thumbnail-icon svg,\n.tc-thumbnail-wrapper:hover .tc-thumbnail-icon img {\n\tfill: #fff;\n\t<<filter \"drop-shadow(3px 3px 4px rgba(0,0,0,0.6))\">>\n}\n\n.tc-thumbnail-icon {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tdisplay: -webkit-flex;\n\t-webkit-align-items: center;\n\t-webkit-justify-content: center;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.tc-thumbnail-caption {\n\tposition: absolute;\n\tbackground-color: #777;\n\tcolor: #fff;\n\ttext-align: center;\n\tbottom: 0;\n\twidth: 100%;\n\tfilter: alpha(opacity=0.9);\n\topacity: 0.9;\n\tline-height: 1.4;\n\tborder-bottom-left-radius: 3px;\n\tborder-bottom-right-radius: 3px;\n}\n\n.tc-thumbnail-wrapper:hover .tc-thumbnail-caption {\n\tfilter: alpha(opacity=1);\n\topacity: 1;\n}\n\n/*\n** Errors\n*/\n\n.tc-error {\n\tbackground: #f00;\n\tcolor: #fff;\n}" }, "$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize": { "title": "$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize", "text": "15px" }, "$:/themes/tiddlywiki/vanilla/metrics/bodylineheight": { "title": "$:/themes/tiddlywiki/vanilla/metrics/bodylineheight", "text": "22px" }, "$:/themes/tiddlywiki/vanilla/metrics/fontsize": { "title": "$:/themes/tiddlywiki/vanilla/metrics/fontsize", "text": "14px" }, "$:/themes/tiddlywiki/vanilla/metrics/lineheight": { "title": "$:/themes/tiddlywiki/vanilla/metrics/lineheight", "text": "20px" }, "$:/themes/tiddlywiki/vanilla/metrics/storyleft": { "title": "$:/themes/tiddlywiki/vanilla/metrics/storyleft", "text": "0px" }, "$:/themes/tiddlywiki/vanilla/metrics/storytop": { "title": "$:/themes/tiddlywiki/vanilla/metrics/storytop", "text": "0px" }, "$:/themes/tiddlywiki/vanilla/metrics/storyright": { "title": "$:/themes/tiddlywiki/vanilla/metrics/storyright", "text": "770px" }, "$:/themes/tiddlywiki/vanilla/metrics/storywidth": { "title": "$:/themes/tiddlywiki/vanilla/metrics/storywidth", "text": "770px" }, "$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth": { "title": "$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth", "text": "686px" }, "$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint": { "title": "$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint", "text": "960px" }, "$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth": { "title": "$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth", "text": "350px" }, "$:/themes/tiddlywiki/vanilla/options/stickytitles": { "title": "$:/themes/tiddlywiki/vanilla/options/stickytitles", "text": "no" }, "$:/themes/tiddlywiki/vanilla/options/sidebarlayout": { "title": "$:/themes/tiddlywiki/vanilla/options/sidebarlayout", "text": "fixed-fluid" }, "$:/themes/tiddlywiki/vanilla/options/codewrapping": { "title": "$:/themes/tiddlywiki/vanilla/options/codewrapping", "text": "pre-wrap" }, "$:/themes/tiddlywiki/vanilla/reset": { "title": "$:/themes/tiddlywiki/vanilla/reset", "type": "text/plain", "text": "/*! normalize.css v3.0.0 | MIT License | git.io/normalize */\n\n/**\n * 1. Set default font family to sans-serif.\n * 2. Prevent iOS text size adjust after orientation change, without disabling\n * user zoom.\n */\n\nhtml {\n font-family: sans-serif; /* 1 */\n -ms-text-size-adjust: 100%; /* 2 */\n -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/**\n * Remove default margin.\n */\n\nbody {\n margin: 0;\n}\n\n/* HTML5 display definitions\n ========================================================================== */\n\n/**\n * Correct `block` display not defined in IE 8/9.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n/**\n * 1. Correct `inline-block` display not defined in IE 8/9.\n * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n */\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; /* 1 */\n vertical-align: baseline; /* 2 */\n}\n\n/**\n * Prevent modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n/**\n * Address `[hidden]` styling not present in IE 8/9.\n * Hide the `template` element in IE, Safari, and Firefox < 22.\n */\n\n[hidden],\ntemplate {\n display: none;\n}\n\n/* Links\n ========================================================================== */\n\n/**\n * Remove the gray background color from active links in IE 10.\n */\n\na {\n background: transparent;\n}\n\n/**\n * Improve readability when focused and also mouse hovered in all browsers.\n */\n\na:active,\na:hover {\n outline: 0;\n}\n\n/* Text-level semantics\n ========================================================================== */\n\n/**\n * Address styling not present in IE 8/9, Safari 5, and Chrome.\n */\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n/**\n * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.\n */\n\nb,\nstrong {\n font-weight: bold;\n}\n\n/**\n * Address styling not present in Safari 5 and Chrome.\n */\n\ndfn {\n font-style: italic;\n}\n\n/**\n * Address variable `h1` font-size and margin within `section` and `article`\n * contexts in Firefox 4+, Safari 5, and Chrome.\n */\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n/**\n * Address styling not present in IE 8/9.\n */\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n/**\n * Address inconsistent and variable font size in all browsers.\n */\n\nsmall {\n font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` affecting `line-height` in all browsers.\n */\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n/* Embedded content\n ========================================================================== */\n\n/**\n * Remove border when inside `a` element in IE 8/9.\n */\n\nimg {\n border: 0;\n}\n\n/**\n * Correct overflow displayed oddly in IE 9.\n */\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n/* Grouping content\n ========================================================================== */\n\n/**\n * Address margin not present in IE 8/9 and Safari 5.\n */\n\nfigure {\n margin: 1em 40px;\n}\n\n/**\n * Address differences between Firefox and other browsers.\n */\n\nhr {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n height: 0;\n}\n\n/**\n * Contain overflow in all browsers.\n */\n\npre {\n overflow: auto;\n}\n\n/**\n * Address odd `em`-unit font size rendering in all browsers.\n */\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n/* Forms\n ========================================================================== */\n\n/**\n * Known limitation: by default, Chrome and Safari on OS X allow very limited\n * styling of `select`, unless a `border` property is set.\n */\n\n/**\n * 1. Correct color not being inherited.\n * Known issue: affects color of disabled elements.\n * 2. Correct font properties not being inherited.\n * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; /* 1 */\n font: inherit; /* 2 */\n margin: 0; /* 3 */\n}\n\n/**\n * Address `overflow` set to `hidden` in IE 8/9/10.\n */\n\nbutton {\n overflow: visible;\n}\n\n/**\n * Address inconsistent `text-transform` inheritance for `button` and `select`.\n * All other form control elements do not inherit `text-transform` values.\n * Correct `button` style inheritance in Firefox, IE 8+, and Opera\n * Correct `select` style inheritance in Firefox.\n */\n\nbutton,\nselect {\n text-transform: none;\n}\n\n/**\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n * and `video` controls.\n * 2. Correct inability to style clickable `input` types in iOS.\n * 3. Improve usability and consistency of cursor style between image-type\n * `input` and others.\n */\n\nbutton,\nhtml input[type=\"button\"], /* 1 */\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; /* 2 */\n cursor: pointer; /* 3 */\n}\n\n/**\n * Re-set default cursor for disabled elements.\n */\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n/**\n * Remove inner padding and border in Firefox 4+.\n */\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n/**\n * Address Firefox 4+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\n\ninput {\n line-height: normal;\n}\n\n/**\n * It's recommended that you don't attempt to style these elements.\n * Firefox's implementation doesn't respect box-sizing, padding, or width.\n *\n * 1. Address box sizing set to `content-box` in IE 8/9/10.\n * 2. Remove excess padding in IE 8/9/10.\n */\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; /* 1 */\n padding: 0; /* 2 */\n}\n\n/**\n * Fix the cursor style for Chrome's increment/decrement buttons. For certain\n * `font-size` values of the `input`, it causes the cursor style of the\n * decrement button to change from `default` to `text`.\n */\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n/**\n * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.\n * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome\n * (include `-moz` to future-proof).\n */\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; /* 1 */\n -moz-box-sizing: content-box;\n -webkit-box-sizing: content-box; /* 2 */\n box-sizing: content-box;\n}\n\n/**\n * Remove inner padding and search cancel button in Safari and Chrome on OS X.\n * Safari (but not Chrome) clips the cancel button when the search input has\n * padding (and `textfield` appearance).\n */\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/**\n * Define consistent border, margin, and padding.\n */\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n/**\n * 1. Correct `color` not being inherited in IE 8/9.\n * 2. Remove padding so people aren't caught out if they zero out fieldsets.\n */\n\nlegend {\n border: 0; /* 1 */\n padding: 0; /* 2 */\n}\n\n/**\n * Remove default vertical scrollbar in IE 8/9.\n */\n\ntextarea {\n overflow: auto;\n}\n\n/**\n * Don't inherit the `font-weight` (applied by a rule above).\n * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n */\n\noptgroup {\n font-weight: bold;\n}\n\n/* Tables\n ========================================================================== */\n\n/**\n * Remove most spacing between table cells.\n */\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n" }, "$:/themes/tiddlywiki/vanilla/settings/fontfamily": { "title": "$:/themes/tiddlywiki/vanilla/settings/fontfamily", "text": "\"Helvetica Neue\", Helvetica, Arial, \"Lucida Grande\", \"DejaVu Sans\", sans-serif" }, "$:/themes/tiddlywiki/vanilla/settings/codefontfamily": { "title": "$:/themes/tiddlywiki/vanilla/settings/codefontfamily", "text": "Monaco, Consolas, \"Lucida Console\", \"DejaVu Sans Mono\", monospace" }, "$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment": { "title": "$:/themes/tiddlywiki/vanilla/settings/backgroundimageattachment", "text": "fixed" }, "$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize": { "title": "$:/themes/tiddlywiki/vanilla/settings/backgroundimagesize", "text": "auto" }, "$:/themes/tiddlywiki/vanilla/sticky": { "title": "$:/themes/tiddlywiki/vanilla/sticky", "text": "<$reveal state=\"$:/themes/tiddlywiki/vanilla/options/stickytitles\" type=\"match\" text=\"yes\">\n``\n.tc-tiddler-title {\n\tposition: -webkit-sticky;\n\tposition: -moz-sticky;\n\tposition: -o-sticky;\n\tposition: -ms-sticky;\n\tposition: sticky;\n\ttop: 0px;\n\tbackground: ``<<colour tiddler-background>>``;\n\tz-index: 500;\n}\n``\n</$reveal>\n" } } }
"Georgia", serif
rebol
Here's a blank extension that does nothing useful, but shows the general format: ``` #include "reb-c.h" #include "reb-ext.h" const char *init_block = "REBOL [\n" "Title: {Blank extension}\n" "Type: module\n" "Exports: [nothing]\n" "]\n" "nothing: command [{Does nothing.}]\n" ; RXIEXT const char *RX_Init(int opts, RL_LIB *lib) { RL = lib; if (!CHECK_STRUCT_ALIGN) return 0; return init_block; } RXIEXT int RX_Quit(int opts) { return 0; } RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { return RXR_NONE } ``` !!!!! ''Format of the examples'' Each example section below will show the REBOL code and the C code as separate sections. To fully understand the details of this code, read the extensions: [[making extensions|Concepts: Extensions: Making Extensions]] section. For example, if the REBOL module code is: ``` REBOL [ Title: "Add two integers" Type: module Export: [addi] ] addi: command [i1 [integer!] i2 [integer!] and the C code is: RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { RXA_INT64(frm,1) = RXA_INT64(frm, 1) + RXA_INT64(frm, 2); return RXR_VALUE; } ``` The extension source code would be: ``` #include "reb-c.h" #include "reb-ext.h" const char *init_block = "REBOL [\n" "Title: {Add two integers}\n" "Type: module\n" "Export: [addi]\n" "]\n" "addi: command [i1 [integer!] i2 [integer!]\n" ; RXIEXT const char *RX_Init(int opts, RL_LIB *lib) { RL = lib; if (!CHECK_STRUCT_ALIGN) return 0; return 0; } RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { RXA_INT64(frm,1) = RXA_INT64(frm, 1) + RXA_INT64(frm, 2); return RXR_VALUE; } ``` !!!!! ''A script to build the init block'' Once you go beyond a simple init block, it gets tedious to maintain it as C strings. To make it easier to build the `init_block` text, we provide the `make-ext.r` script. Using this script will convert the `extension .r` source file into a C data statement (as UTF-8). It will also create the exports block and will generate an enum constant for each command. ``` #include "reb-c.h" #include "reb-ext.h" #include "ext-data.h" RXIEXT const char *RX_Init(int opts, RL_LIB *lib) { RL = lib; if (!CHECK_STRUCT_ALIGN) return 0; return init_block; } RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { switch (cmd) { case CMD_MY_CMD1: ... case CMD_MY_CMD2: ... ```
A common mistake is to add a second block to if or forget the second block on either. These are both wrong, but they may or may not cause a run-time error: ``` if n > 50 [print "greater"] [print "not greater"] ; extra block! either age > 50 [print "greater"] ; missing a block! ``` <<< Watch out! Such errors can be difficult to find. If you are editing code, and you modify an if or either, be sure to check the expression. <<<
Each time REBOL is started, it reads the user.r file to find its network settings. These settings are made with the `[bad-link:functions/set-net.txt]` function. Scripts have access to these settings through the `system/schemes` object. ``` system/user/email ; used for email from and reply system/schemes/default/host - your primary server system/schemes/pop/host - your POP server system/schemes/default/proxy/host - proxy server system/schemes/default/proxy/port-id - proxy port system/schemes/default/proxy/type - proxy type ``` Below is a function that returns a block containing the network settings in the same order as `[bad-link:functions/set-net.txt]` accepts them: ``` get-net: func [][ reduce [ system/user/email system/schemes/default/host system/schemes/pop/host system/schemes/default/proxy/host system/schemes/default/proxy/port-id system/schemes/default/proxy/type ] ] probe get-net ```
If you write an extension to accesses external APIs including standard OS libraries, you will need to be careful. ''R3 in general uses an asynchronous model for I/O''. If you call APIs that perform I/O which may block, then your REBOL process will also block during that I/O. This cause your GUI to block or for other pending I/O operations to overflow or fail. If the external API does not block, then it's probably fine to call it. However, for blocking functions, a better solution is to write them as an ''asynchronous R3 device''. This is a special type of extension. (As of this 1.0 draft release, this is not available, we want to make you aware of it.)
The extension library provides functions for accessing and creating strings and blocks. These functions are access via macros that use the library pointer passed in `RX_Init`. |''RL_MAKE_BLOCK'' |make a new block of given length| |''RL_MAKE_STRING'' |make a new string of given length and width| |''RL_MAP_WORDS'' |map a block of words to their canonical symbol identifiers| |''RL_FIND_WORD'' |find word in an array of symbol identifiers| |''RL_SERIES_INFO'' |get series info: length, size, etc.| |''RL_GET_CHAR'' |get a char from a string| |''RL_SET_CHAR'' |set a char in a string| |''RL_GET_VALUE'' |get a value from a block| |''RL_SET_VALUE'' |set a value in a block| |''RL_GET_STRING'' |get string as an array| It is likely that more functions will be added as needed. Note: allocation GC concerns
An input is parsed by attempting different rules. If a rule fails, a backtrack happens and the next alternate rule is attempted. |''Symbol'' |''Description''|h |`"|"` |alternate rule - if rule is true up to this point, the `"|"` forces the end of the current rule block (no other alternatives are tested.) Otherwise, the parser skips forward from the failure point to the next alternative (marked with an `"|"` bar).| |then |branching rule - when reached (because the rule is true up to this point), the ? will cause the next alternative rule to be skipped if the rest of the rule is false (if it's true, then the full rule is true, and no alternates are needed). This implements a branch because the success or failure of the rule up to the ? will determine which alternate will be tried next.|
Here's what a typical REBOL script looks like. Note the header at the top, and also that the script can hold nicely formatted data, multi-line text. It's easy to read and nicely formatted. ``` REBOL [ Title: "REBOL Ale" Date: 30-Oct-1998 File: %beer.r Purpose: "Recipe for a rich, malty, copper brew." Author: "Anonymous" ] Ingredients: [ 0.5 lb. "Toasted malted barley" 7 lb. "Amber malt extract" 1 lb. "Crystal malt" 1.5 oz. "Northern brewer hops" 1 oz. "Cascade hops" 1 pkg. "Ale yeast" 5 gal. "Sassenranch water" ] Instructions: { After toasting barley to red color (15 minutes), boil it in 1/3 of the water for 10 minutes along with the crystal malt. Add malt extract and brewer hops, then cook 55 minutes. Add cascade hops and remove from heat. Sparge into remaining cold water. Add yeast when cool. Rack twice. Wait four weeks. Cheers to the revolution! } ;-- Conversion to Metric Units: Equivalent: [ gal. 3.8 l. ; liters per gallon lb. 0.45 kg. oz. 28.3 g. ] foreach [amount units description] Ingredients [ conversion: find equivalent units either conversion [ print [ amount * second conversion third conversion description ] ][ print [amount units description] ] ] print instructions ``` To see hundreds of other examples, visit the [[REBOL.org archive|http://www.rebol.org]].
The [[any|Functions: any]] and [[all|Functions: all]] functions are used quite often and let you evaluate multiple conditions in an easy way. The are also more efficient for many types of expressions. The [[any|Functions: any]] function will evaluate a block of expressions until one is `true` (is not `[bad-link:functions/false.txt]` or `[bad-link:functions/none.txt]`). The [[all|Functions: all]] function requires that all the expressions are `true`. An example of any is: ``` n: -10 if any [n < 0 n > 100] [print "out of range"] out of range ``` And all is: ``` n: 10 if all [n > 0 n < 100] [print "in range"] in range ``` You can see that these are like doing or and and functions, but we call them shortcut functions, because they only evaluate as much as they need. Here is a very common programming pattern: ``` name: "Bob" if all [ string? name not empty? name find ["Bob" "Ned" "Sam"] name ][ print "found name" ] found name ``` Also, any and and return useful results. When successful, they return a value. When they fail, they return none. ``` name: "Sam" print all [ string? name spot: find ["Bob" "Ned" "Sam"] name index? spot ] 3 ``` This example also shows how all is used to replace an if without adding extra code. See [[Expressions: Conditionals|Concepts: Expressions: Conditional]] for more details.
The [[any and all functions|Any and all]] offer a shortcut to evaluating some types of conditional expressions. These functions can be used in a number of ways:either in conjunction with [[if|Functions: if]], [[either|Functions: either]], and other conditional functions, or separately. Both [[any|Functions: any]] and [[all|Functions: all]] accept a block of expressions, which is evaluated one expression at a time. The any function returns on the first true expression, and the [[all|Functions: all]] function returns on the first false expression. Keep in mind that a `false` expression can also be [[none!|Datatypes: None!]], and that a true expression is any value other than false or none!. The [[any|Functions: any]] function returns the first value that is not `false`, otherwise it returns [[none!|Datatypes: None!]]. The [[all|Functions: all]] function returns the last value if [[all|Functions: all]] the expressions are not `false`, otherwise it returns [[none!|Datatypes: None!]]. Both the [[any and all functions|Any and all]] only evaluate as much as they need. For example, once any has found a `true` expression, none of the remaining expressions are evaluated. Here is an example of using [[any|Functions: any]] : ``` size: 50 if any [size < 10 size > 90] [ print "Size is out of range." ] ``` The behavior of [[any|Functions: any]] is also useful for setting default values. For example, the following lines set a number to 100, but only when its value is [[none! |Datatypes: None!]] : ``` number: none print number: any [number 100] 100 ``` Similarly, if you have various potential values, you can use the first one that actually has a value (is not [[none! |Datatypes: None!]]): ``` num1: num2: none num3: 80 print number: any [num1 num2 num3] 80 ``` You can use [[any|Functions: any]] with functions like [[find|Functions: find]] to always return a valid result: ``` data: [123 456 789] print any [find data 432 999] 999 ``` Similarly, [[all|Functions: all]] can be used for conditions that require all expressions to be `true` : ``` if all [size > 10 size < 90] [print "Size is in range"] Size is in range ``` You can verify that values have been set up before evaluating a function: ``` a: "REBOL/" b: none probe all [string? a string? b append a b] none ``` ``` b: "Core" probe all [string? a string? b append a b] REBOL/Core ```
Functions usually require arguments of a specific datatype. For example, the first argument to the `[bad-link:functions/send.txt]` function can only be an email address or block of email addresses. Any other type of value will produce an error: ``` send 1234 "numbers" ** Script Error: send expected address argument of type: email block. ** Where: send 1234 "numbers" ``` In the previous example, the error message is telling you that the address argument of the `[bad-link:functions/send.txt]` function needs to be either an email address or a block. A quick way to find out what types of arguments are accepted by a function is to type the following at the console prompt: ``` help send USAGE: SEND address message /only /header header-obj DESCRIPTION: Send a message to an address (or block of addresses) SEND is a function value. ARGUMENTS: address -- An address or block of addresses (Type: email block) message -- Text of message. First line is subject. (Type: any) REFINEMENTS: /only -- Send only one message to multiple addresses /header -- Supply your own custom header header-obj -- The header to use (Type: object) ``` The ARGUMENTS section indicates the datatype of each argument. Notice that the second argument can be of any datatype. So, it is valid to write: ``` send luke@rebol.com $1000.00 ```
Functions receive arguments and return results. Most functions require one or more arguments; although, some functions, such as now (current date and time), do not require any arguments. The arguments that are supplied to a function are processed by the interpreter and then passed to the function. Arguments are processed in the same way, regardless of the type of function called, be it a native function, operator, user-defined function, or otherwise. For example, the `[bad-link:functions/send.txt]` function expects two arguments: ``` friend: luke@rebol.com message: "message in a bottle" send friend message ``` The word `friend` is first evaluated and its value `luke@rebol.com` is provided as the first argument to `[bad-link:functions/send.txt]`. Next, the word message is evaluated, and its value becomes the second argument. Think of the values of the `friend` and `message` variables as being substituted into the line before `[bad-link:functions/send.txt]` is done: ``` send luke@rebol.com "message in a bottle" ``` If you provide too few arguments to a function, an error message is returned. For example, the send function expects two arguments and if you send one, an error is returned ``` send friend ** Script Error: send is missing its message argument. ** Where: send friend ``` If too many arguments are provided, the extra values are ignored. ``` send friend message "urgent" ``` In the previous example, `[bad-link:functions/send.txt]` already has two arguments, so the string, which is the third argument, is ignored. Notice that no error message occurs. In this case, there were no functions expecting the third argument. However, in some cases the third argument may belong to another function that was evaluated before `[bad-link:functions/send.txt]`. Arguments to a function are evaluated from left to right. This order is followed even when the arguments themselves are functions. For example, if you write: ``` send friend detab copy message ``` the second argument must be computed by evaluating the detab function and the copy function. The result of the copy will be passed to detab, and the result of detab will be passed to `[bad-link:functions/send.txt]`. In the previous example, the copy function is taking a single argument, the message, and returns a copy of it. The copied message is passed to the detab function, which removes the tab characters and returns the detabbed message, which is passed to the `[bad-link:functions/send.txt]` function. Notice how the results of functions flow from right to left as the expression is evaluated. The evaluation that is happening here can be shown by using parentheses to clarify what is evaluated first. (However, the parentheses are not required, and actually slow down the evaluation slightly.) ``` send friend (detab (copy message)) ``` The cascading effect of results passed to functions is quite useful. Here is an example that uses [[insert|Functions: insert]] twice within the same expression: ``` file: %image insert tail insert file %graphics/ %.jpg print file graphics/image.jpg ``` In the following example, a directory name and a suffix are added to the base file name. Parentheses can be used to clarify the order of evaluation: ``` insert (tail (insert file %graphics/)) %.jpg ``` <<< A Note About Parentheses Parentheses make good "training wheels" to get started in writing REBOL. However, it won't take long before you can shed this aid and write the expressions directly without the parentheses. Not using parentheses lets the interpreter evaluate expressions quicker. <<<
REBOL source code has no official MIME type association (nor do most other interpreted language source formats.) MIME types are often used for web servers and browsers to identify a medium in order to provide the correct presentation and application association. Unofficially we have used: ``` text/rebol ``` This media type can be justified because REBOL source is textual data and it's meaning is interpreted (not pre-compiled into binary). The data may be source code, but it may also be GUI code, a presentation, descriptions, databases, or various other datatypes. So, we place it in the same MIME class as XML and HTML
Another common case... ``` #!rebol -s REBOL [Title: "example program"] print "This file has a preface before the header" ```
The last example in the previous section would fail if the filename had more than one period. For instance: ``` filename: %new.script.txt print find filename "." .script.txt ``` In this example we want the last occurrence of the period in the string, which can be found using the `/last` refinement. The `/last` refinement searches backward through a series. ``` print find/last filename "." .txt ``` The `/last` refinement can be combined with `/tail` to produce: ``` print find/last filename "." txt ``` If you want to continue to search backward through the string, you need the `/reverse` refinement. This refinement performs a search from the current position backward toward the head, rather than forward toward the tail. ``` where: find/last filename "." print where .txt ``` ``` print find/reverse where "." .script.txt ``` Notice that `/reverse` continues the search just before the position of the last match. This prevents it from finding the same period again.
When you run REBOL the first time, you re prompted for the necessary network settings, which is stored in the user.r file. REBOL uses this file to load the required network settings each time it is started. If a `user.r` is not created and REBOL cannot find an existing `user.r` file in its paths, no settings are loaded. See the chapter on `[bad-link:concepts/operation.txt]` for more information. To change the network settings, type set-user at the prompt. This runs the same network configuration script that ran when REBOL first started. This script is loaded from the rebol.r file. If that file cannot be found, or if you want to edit the setting directly, you can use a text editor on the user.r file. Within the user.r file the network settings are found in a block that follows the `[bad-link:functions/set-net.txt]` function. At a minimum the block should contain two items: Your email address for use in the from and reply fields of email and for anonymous FTP login Your default server; this is also your primary email server In addition, you can specify a few other items: * A different incoming email server (for POP) * A proxy server (for connecting to the network) * A proxy port number * A proxy type (see `[bad-link:concepts/proxy.txt]` Settings below). You can also add lines after the `[bad-link:functions/set-net.txt]` function to configure other protocol values. For instance you can set the timeout values for protocols, set the FTP passive mode, set the HTTP user-agent identifier, set up separate proxies for different protocols, and more. An example of `[bad-link:functions/set-net.txt]` is: ``` set-net [user@domain.dom mail.server.dom] ``` The first field specifies your email from address, and the second field indicates your default server (notice that it does not need quotes here). For most networks, this is enough and no other settings are necessary (unless you require a proxy). Also your default server is used whenever a specific server is not provided. In addition, if you use a POP server (for incoming email) that is different from your SMTP server (for outgoing email), you can specify that as well: ``` set-net [ user@domain.dom mail.server.dom pop.server.dom ] ``` However, if your SMTP and POP servers are the same, then this is not necessary.
Callbacks let you invoke REBOL-based functions from the C code of an extension module. This can be useful if you use operating system or other external libraries that require callbacks to process results or signal completion of external operations. Two callback mechanisms are provided: |''Synchronous'' |Where the callback function in invoked immediately.| |''Asynchronous'' |Where the callback function is queued as an event and will be processed later.| !!!!! ''Synchronous Callbacks'' A synchronous callback passes control back through the REBOL Extension API, which generates the necessary stack frame and re-enters the interpreter's function evaluator. It's like calling a function `via apply`. With this kind of callback, you can allocate the required structures on the C stack, and pass them to the callback. But, be aware that the C stack holds data from both the REBOL and C environments. An exception, such as an ERROR in the callback, will throw the C stack back to a prior location, perhaps even beyond where your extension code was running. If your C code had any cleanup or deallocation to do, it won't happen. !!!!! ''Asynchronous Callbacks'' An event can be used to trigger a callback in an asynchronous fashion. This method allows C code to use C-based callbacks within an operating system that execute callbacks in a fashion similar to an interrupt. Your C code calls the extension API which builds an event to hold callback information. The event is queued to the System Port's event list. Later, when events are processed, the event is passed to the Callback Port which will invoke your callback function. When running asynchronous, the callback function return values is stored in a structure that you allocated earlier, but if you need results on the REBOL side, the callback function must be store it in an object or block for later retrieval. It should be mentioned that REBOL I/O devices (stdio, files, networking, timers, GUI events) use the same event-driven mechanism for all asynchronous I/O operations. That means that events are queued in the order they happen, including callback events. That's generally considered the best method, otherwise it's possible for a specific callback to be called before its related I/O may have finished.
Binary values are byte strings of any length. They can be encoded directly as hexadecimal or base-64. For example: ``` #{42652061205245424F4C} 64#{UkVCT0wgUm9ja3Mh} ```
f a block is provided for make (and also several of the other bitset-related functions) it represents bit settings in the following way: !!!! ''Accepted datatypes'' |''Datatype'' |''Example'' |''Description''|h |[[integer!|Datatypes: Integer!]] |123 |the bit associated with the integer 123 (or part of a range)| |[[char!|Datatypes: Char!]] |#"a" |the bit associated with character code "a" (or part of a range)| |[[string!|Datatypes: String!]] |"abc" |multiple bits, each character specifies a bit| |[[binary!|Datatypes: Binary!]] |#{010203} |multiple bits, each byte specifies a single bit to be set| !!!! ''Bit ranges'' Note that characters and integers can specify inclusive ranges using a dash `-`. ''Do not forget the spaces around it. Spaces are required to delimit it''. ``` [0 - 99] ; bits 0 to 99 inclusive [#"A" - #"Z"] ; bits associated with A to Z, inclusive ``` More examples are shown below. !!!! ''Complement (not) bitsets'' Bitsets can be complements, meaning that each bit is inverted (a logical [[not|Functions: not]].) In order to specify such bitsets, a specification block can begin with the keyword `not`. Here are examples: ``` no-space: make bitset! [not #" "] no-whitespace: make bitset! [not "^-^/ "] no-ctrl-space: make bitset! [not 0 - #" "] ``` !!!! ''Binaries as bits'' It should be noted that these two lines are not equivalent: ``` make bitset! #{01FF} make bitset! [#{01FF}] ``` The first sets bits 7 through 15. The second sets bits 1 and 255. This difference occurs because the mold function outputs bitsets in a binary form that indicates what specific bits are set (the first line.) However, within a block, this binary form can also be used if the bits keyword is used. These lines are equivalent: ``` make bitset! #{0060000080} make bitset! [bits #{0060000080}] ``` And for the complement, these lines are also equivalent: ``` complement make bitset! #{0060000080} make bitset! [not bits #{0060000080}] ``` <<< MOLD output When mold is used on a complemented bitset, in order to preserve the complement, the bitset must be output as a block in the form: ``` make bitset! [not bits #{...}] ``` This is necessary in order to include the complement indication. <<< !!!! ''Examples'' Create a bitset with the bit associated with #"a" set: ``` bits: make bitset! #"a" ``` Create a bitset large enough to holds bits up to 1000 and set bit 1000: ``` bits: make bitset! [1000] ; note that bit 1000 is set ``` Create a bitset large enough to hold the bits for each character of `AxZ3?` and set each of those: ``` bits: make bitset! "AxZ3?" ``` Note that upper and lower case bits are different. A block allows multiple bits to be specified using one or more combination of the above. For example: ``` bits: make bitset! [#"?" #"A" - #"Z" "!@#$" 201 - 220] ``` If the contents of bitset block needs to be computed, use reduce or compose first. For example: ``` start: 200 len: 50 bits: make bitset! reduce [start '- start + len] ```
!!!!! ''Sum of numeric values'' This extension shows how to handle values within a block. It provides a function that returns a sum of all integer and decimal values within the block. If the block contains other datatypes, they are ignored. The REBOL extension module definition: ``` REBOL [ Title: {Sum a block of integers and decimals} Type: module Exports: [sum-nums] ] sum-nums: command [blk [block!]] ``` The C code: ``` RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { switch (cmd) { case 0: { i32 idx, tail, type; REBDEC sum = 0.0; REBSER *ser; RXIARG val; ser = RXA_SERIES(frm, 1); idx = RXA_INDEX(frm, 1); tail = RXI_SERIES_INFO(ser, RXI_INFO_TAIL); for (; idx < tail; idx++) { type = RXI_GET_VALUE(ser, idx, &val); if (type == RXT_INTEGER) sum += (REBDEC)val.int64; else if (type == RXT_DECIMAL) sum += val.dec64; // else skip it } RXA_DEC64(frm, 1) = sum; RXA_TYPE(frm, 1) = RXT_DECIMAL; break; } default: return RXR_NO_COMMAND; } return RXR_VALUE; } ``` Here's some test code: ``` probe sum-nums [] 0.0 ``` ``` probe sum-nums [1 2 3] 6.0 ``` ``` probe sum-nums [1 2.3 4 5.6] 12.9 ``` !!!!! ''Reverse a block'' Although REBOL provides the [[reverse|Functions: reverse]] function, here's a simple example that helps show how blocks can be modified. ''Note that this code only works for values that extensions are allowed to access''. See the list in the prior section. The REBOL extension module definition: ``` REBOL [ Title: {Block example} Type: module Exports: [reverse-blk] ] reverse-blk: command [blk [block!]] ``` The C code: ``` RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { switch (cmd) { case 0: { u32 idx, tail, type1, type2; REBSER *ser; RXIARG arg1, arg2; ser = RXA_SERIES(frm, 1); idx = RXA_INDEX(frm, 1); tail = RXI_SERIES_INFO(ser, RXI_INFO_TAIL); if (tail > 0) tail--; for (; idx < tail; idx++, tail--) { type1 = RXI_GET_VALUE(ser, idx, &arg1); type2 = RXI_GET_VALUE(ser, tail, &arg2); RXI_SET_VALUE(ser, idx, arg2, type2); RXI_SET_VALUE(ser, tail, arg1, type1); } break; // returns same block } default: return RXR_NO_COMMAND; } return RXR_VALUE; } ``` The test code: ``` probe reverse-blk [] [] ``` ``` probe reverse-blk [1] [1] ``` ``` probe reverse-blk [1 2] [2 1] ``` ``` probe reverse-blk [1 2 3] [3 2 1] ``` ``` probe reverse-blk [1 2 3 4] [4 3 2 1] ``` ``` probe head reverse-blk next [1 2] [1 2] ``` ``` probe head reverse-blk next [1 2 3] [1 3 2] ``` ``` probe head reverse-blk next [1 2 3 4] [1 4 3 2] ```
|''Block Type'' |''Description''|h |[[block!|Datatypes: Block!]] |Blocks of values| |[[paren!|Datatypes: Paren!]] |Blocks of values enclosed in parentheses| |[[path!|Datatypes: Path!]] |Paths of values| |[[list!|Datatypes: List!]] |Linked lists| |[[hash!|Datatypes: Hash!]] |Associative arrays|
`Words` and `values` are grouped into` blocks`, enclosed in square brackets `[]`. Within a block, values and words can be organized in any order and can span any number of lines. Example blocks: ``` [1 2 3 4.0 5% $6.00] [white red green blue yellow orange black] ["Spielberg" "Back to the Future" 1:56:20 MCA] [ "Bill" billg@ms.com #315-555-1234 "Steve" jobs@apl.com #408-555-4321 "Ted" ted@gw2.com #213-555-1010 ] [ "John" 6894 0:55:68 "Dion" 68861 0:61:35 "Floyd" 46001 0:50:12 ] if time > 10:30 [send jim news] loop 100 [print/only "*"] sites: [ http://www.rebol.com [save %reb.html data] http://www.cnn.com [print data] ftp://www.amiga.com [send cs@org.foo data] ] foreach [site action] sites [ data: read site do action ] ``` You can see that both code and data use blocks. <<< Why brackets, not braces? REBOL uses square brackets because they are un-shifted on the US keyboard. Basically, they are easier to type. (Of course, that's not true on non-US keyboards, where it's probably best to setup a keyboard macro for [ and ].) Also, they seemed easier to read than braces (because they render as a cleaner glyph.) Also, REBOL's design was influenced just a small amount by Logo, the language from MIT created to help teach programming in schools. <<<
Blocks are not always evaluated. In many cases blocks may be skipped, due to the result of an expression. For example, in this case: ``` if 4 > 10 [print 1 + 2] ``` no result is printed. The block is not evaluated because the if condition is false. Or, if you wrote: ``` loop 0 [print 1 + 2] ``` Nothing happens. The block is never evaluated. Actually, it turns out, if you enter that line into the console, you will see: ``` if 4 > 10 [print 1 + 2] none ``` As we said above, every block returns a result. The above line is actually: ``` do [if 4 > 10 [print 1 + 2]] none ``` so, the result of if is none when the condition is `false`. The importance of this feature will become more clear once you learn a bit more about the language.
The examples above all use [[print|Functions: print]] to display their results. That was done to make them clear, but the print hides an important fact: ''when evaluated, every block returns a result''. The example code: ``` print 1 + 2 3 ``` could also be written as simply: ``` 1 + 2 3 ``` We see the 3 here because the console automatically prints all resulting values. But, in more precise terms, this is true too: ``` do [1 + 2] 3 ``` The result of blocks is often used in code, and you will be seeing it in many examples ahead. For example, take special note of this case: ``` if 10 > 4 [1 + 2] 3 ``` What happens when the conditional is not true? Read the next section.
You can stop the repeated evaluation of a block with the [[break|Functions: break]] function. The [[break|Functions: break]] function is useful when a special condition is encountered and the loop must be stopped. The [[break|Functions: break]] function works with all types of loops. In the following example, the loop will break if a number is greater than 5. ``` repeat count 10 [ if (random count) > 5 [break] print "testing" ] testing testing testing ``` The[[break|Functions: break]] function does not return a value from the loop unless a `/return` refinement is used: ``` print repeat count 10 [ if (random count) > 5 [break/return "stop here"] print "testing" "normal exit" ] testing testing testing stop here ``` In the above example, if the repeat terminates without the condition occurring, the block returns the string `normal` exit. Otherwise, `break/return` will `return` the string stop here.
In many languages, it is common to stack `if` and `else` statements in a pattern like: ``` if ... else if ... else if ... else ... ``` In REBOL, you can do that with [[either|Functions: either]], but generally we avoid it and use [[case|Functions: case]] instead. It has the general form: ``` case [ condition1 [expression1] condition2 [expression2] ... ] ``` For example: ``` n: 10 case [ n > 100 [print "too large"] n > 20 [print "still too large"] n < 0 [print "too small"] true [print "in range"] ] in range ``` Note the use of `true` for the last case, evaluated when all the others fail. And, because [[case|Functions: case]] is a function that returns a result, the above example could be written: ``` n: 10 print case [ n > 100 ["too large"] n > 20 ["still too large"] n < 0 ["too small"] true ["in range"] ] in range ``` It turns out that [[case|Functions: case]] does not require blocks for simple values, so you can further reduce this down to: ``` n: 10 print case [ n > 100 "too large" n > 20 "still too large" n < 0 "too small" true "in range" ] in range ``` The [[case|Functions: case]] function also has a refinement that lets you evaluate all the conditional expressions. See the function description for more detail.
In REBOL, file names are ''not'' case-sensitive by default. However, when new files are created by the language, they keep the case they were typed in: ``` write %Script-File.r file-data ``` The above example creates the file name with the `S` and `F` in uppercase. In addition, when file names are read from directories, the case is preserved: ``` print read %/home ``` For case-sensitive systems, such as UNIX, REBOL finds the closest case match to the specified file. For example, if a script asks to read %test.r, but only finds `%TEST.r`, the `%TEST.r` file is read. This behavior is necessary to allow machine-independent scripts.
To change the current directory, use: ``` change-dir %new-path/to-dir/ ``` If the trailing slash is not included, the function adds it.
One additional set of functions is provided for changing values in a series. The [[change|Functions: change]] function replaces one or more values with new values. Although this can be accomplished by removing and inserting values, it is more efficient to use change. Defining the block: ``` colors: [blue red green gold] ``` Its second value could be changed with the line: ``` change next colors 'yellow ``` And it would become: The block would now become: ``` probe colors [blue yellow green gold] ``` The [[poke|Functions: poke]] function allows you to specify that the change occur at a particular position relative to the `colors` variable. The [[poke|Functions: poke]] function is similar to the [[pick|Functions: pick]] function described earlier. ``` poke colors 3 'red ``` The block is now: As proven by: ``` probe colors [blue yellow red gold] ``` The [[change|Functions: change]] function has additional refinements that are described later in this chapter.
The [[parse|Functions: parse]] operations allowed for blocks are those that deal with specific characters. For instance, a match cannot be specified to the first letter of a word or string, nor to spacing or newline characters.
The [[checksum|Functions: checksum]] returns the checksum of the string value. There are three types of checksum that can be computed: |''CRC'' |24 bit circular redundancy checksum| |''TCP'' |standard Internet 16 bit checksum| |''Secure'' |a cryptographically secure checksum| By default, the CRC checksum is computed: ``` print checksum "hello" 52719 ``` ``` print checksum (read http://www.rebol.com/) 356358 ``` To compute a TCP 16-bit checksum, use the /tcp refinement: ``` print checksum/tcp "hello" 10943 ``` A secure checksum will return a binary value, not an integer. Use the `/secure` refinement to compute a secure checksum: ``` print checksum/secure "hello" #{AAF4C61DDCC5E8A2DABEDE0F3B482CD9AEA9434D} ```
There are a lot of editing programs out there, and some are better than others. Basically, any editor that can edit and save text files will work. Just be sure that you save the file in ASCII or UTF-8 text format. (If you must use a word processor for some reason, don't save as a .doc.) In addition, if your editor supports code, then it can help with indentation. It may also provide syntax coloring which can be helpful for noticing problems, like missing quotes. It also helps save development time if your editor supports a keyboard shortcut to run REBOL with the current script as input. For example, we like to use CTRL-E to mean save and evaluate a script. !!! ''List of editors'' {{List of editors}} !!! ''Is there IDE support?'' {{Is there IDE support?}}
In REBOL, ''blocks are used for both code and data''. In fact, code is just data. This is a key concept of REBOL that you must keep in mind: * Code blocks hold data that is directly interpreted (evaluated) by REBOL. * Data blocks are not directly evaluated, but your program will in-directly evaluate or manipulate that data. Starting with the example above, now look at what you can do: ``` blk: [print 1 + 2] if 10 > 4 blk 3 ``` ``` loop 3 blk 3 3 3 ``` ``` print length? blk 4 ``` ``` first blk print ``` ``` last blk 2 ``` ``` reverse blk [2 + 1 print] ``` This concept makes the language extremely flexible, and as you will see later, gives it great power many expressions with very little code. The importance of this concept will become a lot more clear as you learn more about the language.
When you type a line into the console: ``` print 1 + 2 ``` you are actually creating the code block: ``` [print 1 + 2] ``` and that block gets evaluated to produce the result. Although the brackets are not required for your line when you type it, it is implied: the line is a block. In fact, when you type that line at the console, it is a shortcut for: ``` do [print 1 + 2] ``` This is important to realize, because ''you use blocks in a similar way for all code''. For example: ``` if 10 > 4 [print 1 + 2] 3 ``` The if function evaluates the block, because its conditional expression is true. Another example: ``` loop 3 [print 1 + 2] 3 3 3 ``` The loop function is just like do, except it evaluates the block three times here.
The native functions defined within a extension are called ''commands''. They are similar to the native functions found in REBOL, and evaluate at the full speed of the CPU. Each command has two parts: |''spec'' |the interface specification (in REBOL format) that provides a help string (title) and lists the arguments for the function.| |''body'' |the C code that makes the command do its job.| In the example above, the spec for the `add-mul` command was defined by this line: ``` add-mul: command [{Add and multiply integers.} a b c] ``` You will note that this is identical to the function definition methods used throughout REBOL. And, it should be noted that the command word is a specially defined function itself, similar to func and function used for defining other functions. More information about how command works is described below. The body of the `add-mul` function is found in this code: ``` RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { RXA_INT64(frm, 1) = (RXA_INT64(frm, 1) + RXA_INT64(frm, 2)) * RXA_INT64(frm, 3); return RXR_VALUE; } ``` The details of the RXIFRM structure will be explained below. Also, this example is a bit simplistic because the extension only handles a single command (add_mul). More examples will be shown below. !!!!! ''Qualifying arguments'' In the code above, the `add-mul` command arguments have no datatype qualifier; however, for most code you will want to provide a list of one or more valid datatypes. This makes it possible for the datatype to be verified prior to calling your native code. It also makes error messages easier to understand. For example, here is a better definition for the add-mul command: ``` add-mul: command [ {Add and multiply integers.} a [integer!] b [integer!] c [integer!] ] ``` If an attempt is made to pass a datatype other than integer, the normal error message will be thrown. You can also accept multiple datatypes for the arguments of your function. For example, if you want to accept integer and decimal: ``` add-mul: command [ {Add and multiply integers.} a [integer! decimal!] b [integer! decimal!] c [integer! decimal!] ] ``` Of course, now the C code body of your function will need to check which datatype is being passed. The datatypes allowed for commands are listed in the Datatypes section below. !!!!! ''Command dispatching'' Within the DLL, the `RX_Call` function dispatches command functions. For extensions with only a few commands, all of the related code can be put into the same RX_Call function. For extensions with many commands, you may want to build a function table and redirect to sub-functions. In the arguments to `RX_Call` the `cmd` arg provides the index number for the command, and you can use `if` or `switch` statements to process the correct command. If you only have a few commands, `if` is probably faster. If you have several commands, `switch` will be faster. ``` RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { if (cmd == 0) { } else if (cmd == 1) { } ... } RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { switch (cmd) { case 0: <command code> break; case 1: <command code> break; case 2: ... } } ``` If you have a larger number of commands, you will want to create an `enum` to help relate command numbers to their function names. !!!!! ''Argument access'' Command arguments are passed to `RX_Call` in an argument frame (a structure) accessed via the frm pointer which is of the RXIFRM type. A frame consists of two parts: |''types'' |a byte array of datatypes. The zeroth byte provides the number of arguments. The size of this array is the number of arguments rounded up to a multiple of eight. Normally, it only occupies 64 bits (enough to support seven function arguments.)| |''values'' |64 bit values. The format of each value is dependent on the argument's datatype. For example, if the datatype is an integer, it's value is a 64 bit integer. If the datatype is a decimal, the value is a 64 bit IEEE float (double). The RXIARG typedef provides a union to properly access each type of value.| Graphically, a frame looks like this: |''Command frame''|h |type array (64 bits)| |argument 1 (64 bits)| |argument 2 (64 bits)| |argument 3 (64 bits)| |...| To make it easier to access argument related information, macros are provided: ``` RXA_COUNT(frm) returns the arg count RXA_TYPE(frm,n) returns the datatype for the n-th arg ``` To access a specific argument, such as an integer, you write: ``` RXA_INT64(frm, n) ``` Where the value of n normally begins with 1 (because the 0 slot is the type array) Here is a list of these datatype specific macros: ``` RXA_INT64(f,n) integer! RXA_DEC64(f,n) decimal! and percent! RXA_LOGIC(f,n) logic! RXA_CHAR(f,n) char! (32 bits) RXA_TIME(f,n) time! RXA_DATE(f,n) date! (encoded) RXA_WORD(f,n) word! (all) RXA_PAIR_X(f,n) pair! RXA_PAIR_Y(f,n) pair! RXA_TUPLE(f,n) tuple! RXA_SERIES(f,n) series! (reference) RXA_INDEX(f,n) series! (index) RXA_HANDLE(f,n) any pointer (32 bit address) ``` In addition, this macro is provided: ``` RXA_REF(f,n) refinement flag ``` Refinements are discussed below. !!!!! ''Multi-typed arguments'' Similar to other functions, commands can accept multiple datatypes for a single argument. Within your C code you will need to be able to detect which datatype has been passed, and access its value properly. Here is an example command that allow both an integer and a decimal for its argument: ``` cmd: command [n [integer! decimal!]] ``` The body code would be something like: ``` RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { i64 i; d64 d; if (cmd == 1) { if (RXA_TYPE(frm, 1) == RXT_INTEGER) { i = RXA_INT64(frm, 2); } else { d = RXA_DEC64(frm, 1); } ... } } ``` Note that the `i64` and `d64` are general typedefs used to abstract compiler differences (e.g. on older MSVC the use of _int64 for 64 bit integers.) Many examples are provided in the [[extensions: example|Concepts: Extensions: Example extensions]] extensions section. !!!!! ''Refinements'' As with other functions, commands are allowed to accept refinements are arguments. Such refinements are passed as normal arguments with a value of `none` or `true`. A simple test will determine if the refinement has been specified. For example, if you write a special trigonometric function, you may want to provide a refinement to specify either radians rather than degrees: ``` hyper-sine: command [d [decimal!] /radians] ``` This code will handle the refinement flag: ``` d = RXA_DEC64(frm, 1); if (RXA_REF(frm, 2)) rads = TRUE; ... ``` Note that you do not need to check the datatype of the argument. The REBOL extension caller will assure that none has a zero 32 bit value, and that true has a non-zero 32 bit value. !!!!! ''Command results'' The integer return code from `RX_Call` determines what the command returns. Like other functions, a command can return none, one, or multiple results. An enum of results is defined. The constants are: |''RXR_UNSET'' |Do not return a value.| |''RXR_NONE'' |A shortcut for returning NONE.| |''RXR_TRUE'' |A shortcut for returning TRUE.| |''RXR_FALSE'' |A shortcut for returning FALSE.| |''RXR_VALUE'' |Return a single value (that found in the arg[1] position).| |''RXR_BLOCK'' |A shortcut method to return multiple values. See below.| |''RXR_ERROR'' |Return an error (special case.)| |''RXR_BAD_ARGS'' |Throws the error: Bad command arguments. This is a generic result you can return for errors in simple functions.| |''RXR_NO_COMMAND'' |Throws the error: The command at that index is not implemented. The first few are shortcuts to make your code simpler and smaller for such cases.| `RXR_VALUE` indicates that you want to return the first argument of the frame as the result using its indicated datatype. For example, take this code that adds the first and second argument, then returns the first: ``` RXA_INT64(frm, 1) += RXA_INT64(frm, 2); return RXR_VALUE; ``` As a variation, in this code the arguments are integers, but it returns a decimal result: ``` RXA_DEC64(frm, 1) = (d64)(RXA_INT64(frm, 1) + RXA_INT64(frm, 2)); RXA_TYPE(frm, 1) = RXT_DECIMAL; return RXR_VALUE; ``` When multiple results are needed, the command must return a block. Often, you command will only need to return just a few values, so a shortcut technique is provided. If you store your results within the argument slots of the frame, and also set their datatypes within the type array, they will be considered a block if you return the `RXR_BLOCK` return code. You must also indicate how many values are within the block. Here's an example that returns three values, an integer, decimal, and a time: ``` RXA_COUNT[frm] = 3; RXA_INT64(frm, 1) = 1; RXA_TYPE(frm, 1) = RXT_INTEGER; RXA_INT64(frm, 3) = 2.2; RXA_TYPE(frm, 2) = RXT_DECIMAL; RXA_INT64(frm, 3) = 1200000000; RXA_TYPE(frm, 3) = RXT_TIME; return RXR_BLOCK; ``` You can only return up to ''seven values in this way''. Beyond that, you must use the `RL_Make_Block` function and append each value into the new block. !!!!! ''Extended frames'' The examples shown above are valid for the most common command frame, those with less than seven arguments. It is very rare to require more than seven arguments to a function, and in general programming practice, if you find that necessary, then it may be better to pass your arguments encapsulated within a block. Although the initial implementation of commands does not support extended frames, we may add it in the future if it seems important for some reason. For frames larger than seven arguments, the type array is expanded in increments of 8 bytes. This means that argument references would be shifted by the appropriate amount. To better abstract such offsets, new macros would be provided to account for those offsets. !!!!! ''How COMMAND Works'' As described above the `command` word is a special function that creates new command functions within an extension module. Basically, `command` calls make on the [[command!|Datatypes: Command!]] datatype, in the general form: ``` make command! reduce [args module index] ``` where: |''args'' |is the argument spec for the new function.| |''module'' |is the extension module context and is used to reference back to the extension dispatcher.| |''index'' |is the dispatch index for a specific command.| You can directly create commands using this make method; however, in addition to the argument spec, you will need to provide the module and correct dispatch index each time. To make extension modules easier to read, the command function method was created. This function is defined within the context of the extension module allowing the module argument to be implied (with `self`.) In addition, the command dispatch index can be a module local variable that is auto-incremented for each new command. This mechanism simplifies command definitions and requires very little code to do so. Here's the code that the module system automatically inserts into each module: ``` cmd-index: 0 command: func [ "Define a new command for an extension." args [block!] ][ make command! reduce [args self ++ cmd-index] ] ``` To work properly, this code must be bound to the context of the module. That is why it resides within the module itself. It should be noted that other fields are also inserted into the extension module. The `system/standard/extension` object defines those fields and is used by the system's `[bad-link:functions/load-extension.txt]` native function.
A single-line comment is made with a semicolon. Everything following the semicolon to the end of the line is part of the comment: ``` ; Settings follow below: quality: 100 ; set to the highest quality ``` Another form of comments also exists. See [[Scripts: Comments|Concepts: Scripts: Comments]] for more.
Many years of debugging REBOL code have shown us some of the best ways to debug code. Here are the main ideas. !!!! ''Print'' {{Print}} !!!! ''The ?? function'' {{The ?? function}} !!!! ''Probing code and data'' {{Probing code and data}} !!!! ''Trace'' {{Trace}}
Here we point out some of the most common mistakes users make in their code. !!!! ''Missing brackets or quotes'' {{Missing brackets or quotes}} !!!! ''Missing arguments'' {{Missing arguments}} !!!! ''Extra arguments ignored'' {{Extra arguments ignored}} !!!! ''Conditional values other than TRUE and FALSE'' {{Conditional values other than TRUE and FALSE}}
The REBOL community is also a good way to learn more and get some answers to questions. It's easy to access directly from R3 with the chat function. Chat has two modes: command line interface and graphical graphical user interface. Both are useful. (For example, if your SSH'd onto a server, you'll need the command line mode.) Here's an example (showing the command line mode): ``` >> chat Fetching chat... Script: "RebDev Command Line Interface" Version: 0.4.19 Date: 20-Aug-2009/0:00 --- Note: login initiated --- Note: fetching user list --- Note: checking for new messages --- Note: there are new messages 5786 message records Alerts: 141 ! Enter 140 for chat about chat. 140 Carl 280d Top headings: 2 H Server admin 0 admin 5:15h 4 H User messages 0 admin 40d 5 H General 0 Kaj 3:31h 14 H R3 0 Steeve 3:49h 15 H R2 0 maxim 61d 16 H Tools 0 DideC 46d 17 H Websites 0 Henrik 32d > 18 H Community 0 maxim 39d Hint: n = new messages, who = users online, ? = help, ?? = list commands. ... ``` Use ? to get help, and N to view the newest messages.
The `/compare` refinement allows you to perform custom comparisons on the data being sorted. This refinement takes an additional argument, which is the comparison function to use for ordering the data. A comparison function is written as a regular function that takes two arguments. These arguments are the values to be compared. A comparison function returns true if the first value should be placed before the second value and `false` if the first value should be placed after the second value. A normal comparison places data in ascending order: ``` ascend: func [a b] [a < b] ``` If the first value is less than the second, then `true` is returned from the function and the first value is placed before the second value. ``` data: [100 101 -20 37 42 -4] probe sort/compare data :ascend [-20 -4 37 42 100 101] ``` Similarly: ``` descend: func [a b] [a > b] ``` If the first value is greater than the second value, then `true` is returned and the data is sorted with greater values first. The sort will descend from greater values. ``` probe sort/compare data :descend [101 100 42 37 -4 -20] ``` Notice that in both cases the comparison function is passed by providing its name preceded with a colon. The name preceded with a colon causes the function to be passed to sort without first being evaluated. The comparison function could also be provided directly with: ``` probe sort/compare data func [a b] [a > b] [101 100 42 37 -4 -20] ```
The [[compress|Functions: compress]] function will compress a string and return a binary datatype. In the following example, a small file is compressed by reading its contents, compressing them, then writing it back to disk: ``` Str: {I wanted the gold, and I sought it, I scrabbled and mucked like a slave. Was it famine or scurvy -- I fought it; I hurled my youth into a grave. I wanted the gold, and I got it -- Came out with a fortune last fall, -- Yet somehow life's not what I thought it, And somehow the gold isn't all.} print [size? str "bytes"] 306 bytes ``` ``` bin: compress str print [size? bin "bytes"] 156 bytes ``` Note that the result of the compression is a binary datatype. The [[decompress|Functions: decompress]] function decompresses a previously compressed string. ``` print decompress bin I wanted the gold, and I sought it, I scrabbled and mucked like a slave. Was it famine or scurvy -- I fought it; I hurled my youth into a grave. I wanted the gold, and I got it -- Came out with a fortune last fall, -- Yet somehow life's not what I thought it, And somehow the gold isn't all. ``` <<< Save Your Data Always keep an uncompressed backup of compressed data. If you lose only one byte from a compressed binary, it can be difficult to recover the data. Do not store file archives in a compressed format unless you have copies that are not compressed. <<<
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Blocks are used to hold both code and data. They are a fundamental concept in REBOL, and it is important to know how to create and manipulate blocks.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Blocks are used for arrays. An example of a statically defined two dimensional array is: ``` arr: [ [1 2 3 ] [a b c ] [$10 $20 $30] ] ``` You can obtain the values of an array with the series extraction functions: ``` probe first arr [1 2 3] ``` ``` probe pick arr 3 [$10.00 $20.00 $30.00] ``` ``` probe first first arr 1 ``` You can also use paths to obtain values from the array: ``` probe arr/1 [1 2 3] ``` ``` probe arr/3 [$10.00 $20.00 $30.00] ``` ``` probe arr/3/2 $20.00 ``` Paths can also be used to change the values in an array: ``` arr/1/2: 20 probe arr/1 [1 20 3] ``` ``` arr/3/2: arr/3/1 + arr/3/3 probe arr/3/2 $40.00 ``` ''Creating Arrays'' The [[array|Functions: array]] function creates arrays dynamically. The function takes an argument that is either an integer or a block of integers and returns a block that is the array. By default, the cells of an array are initialized to none!. To initialize array cells to some other value, use the `/initial` refinement explained in the next section. When array is supplied with a single integer, a one-dimensional array of that size is returned: ``` arr: array 5 probe arr [none none none none none] ``` When a block of integers is provided, the array has multiple dimensions. Each integer provides the size of the corresponding dimension. Here is an example of a two dimensional array that has six cells, two rows of three columns: ``` arr: array [2 3] probe arr [[none none none] [none none none]] ``` This can be made into a three dimensional array by adding another integer to the block: ``` arr: array [2 3 2] foreach lst arr [probe lst] [[none none] [none none] [none none]] [[none none] [none none] [none none]] ``` The block of integers that is passed to array can be as big as your memory will support. ''Initial Values'' To initialize the cells of an array to a value other than [[none!|Datatypes: None!]], use the `/initial` refinement. This refinement takes one argument: the initial value. Here are some examples: ``` arr: array/initial 5 0 probe arr [0 0 0 0 0] ``` ``` arr: array/initial [2 3] 0 probe arr [[0 0 0] [0 0 0]] ``` ``` arr: array/initial 3 "a" probe arr ["a" "a" "a"] ``` ``` arr: array/initial [3 2] 'word probe arr [[word word] [word word] [word word]] ``` ``` arr: array/initial [3 2 1] 11:11 probe arr [[[11:11] [11:11]] [[11:11] [11:11]] [[11:11] [11:11]]] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< When a block appears as a value within another block, it counts as a single value regardless of how many values it contains. For example: ``` values: [ "new" [1 2] %file1.txt ["one" ["two" %file2.txt]] ] probe values ["new" [1 2] %file1.txt ["one" ["two" %file2.txt]]] ``` The [[length?|Functions: length?]] of values is four. The second and fourth `values` are counted as single `values`: ``` print length? values 4 ``` The block values within the values block can be used as a block as well. In the following examples, The [[second|Functions: second]] is used to extract the second value from values. To print the block, type: ``` probe second values [1 2] ``` To get the length of the block, type: ``` print length? second values 2 ``` To print the datatype of the block, type: ``` print type? second values block ``` In the same way, series operations can be performed on other types of series values in blocks. In the following examples, [[pick|Functions: pick]] is used to extract `%file1.txt` from values. To look at the value, type: ``` probe pick values 3 %file1.txt ``` To get the length of the value: ``` print length? pick values 3 9 ``` to see the datatype of the value: ``` print type? pick values 3 file ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The [[compose|Functions: compose]] function is handy for creating blocks from dynamic values. It can be used for creating both data and code. The [[compose|Functions: compose]] function takes a block as an argument and returns a block that has each value in the argument block. Values in parentheses are evaluated before the block is returned. For example: ``` probe compose [1 2 (3 + 4)] [1 2 7] ``` ``` probe compose ["The time is" (now/time)] ["The time is" 10:32:45] ``` If the values in parentheses return a block, that block's individual values are used: ``` probe compose [a b ([c d])] [a b c d] ``` To prevent this, you need to enclose the result in an extra block: ``` probe compose [a b ([[c d]])] [a b [c d]] ``` An empty block inserts nothing: ``` probe compose [a b ([]) c d] [a b c d] ``` When compose is given a block that contains sub-blocks, the sub-blocks are not evaluated, even if they contain parentheses: ``` probe compose [a b [c (d e)]] [a b [c (d e)]] ``` If you would like the sub-blocks to be evaluated, use the `/deep` refinement. The `/deep` refinement causes all parentheses to be evaluated, regardless of where they are: ``` probe compose/deep [a b [c (d e)]] [a b [c d e]] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Contents'' * [[Join]] * [[Rejoin]] * [[Form]] * [[Reform]] * [[Mold]] * [[Remold]] * [[String Spacing Functions]] ** Trim ** Detab and Entab * [[Uppercase and Lowercase]] * [[Checksum]] * [[Compression and Decompression]] * [[Number Base Conversion]] * [[Internet Hexadecimal Decoding]] !!! ''Join'' {{Join}} !!! ''Rejoin'' {{Rejoin}} !!! ''Form'' {{Form}} !!! ''Reform'' {{Reform}} !!! ''Mold'' {{Mold}} !!! ''Remold'' {{Remold}} !!! ''String Spacing Functions'' {{String Spacing Functions}} !!! ''Uppercase and Lowercase'' {{Uppercase and Lowercase}} !!! ''Checksum'' {{Checksum}} !!! ''Compression and Decompression'' {{Compression and Decompression}} !!! ''Number Base Conversion'' {{Number Base Conversion}} !!! ''Internet Hexadecimal Decoding'' {{Internet Hexadecimal Decoding}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The path notation is useful for nested blocks. The fourth value in values is a block containing another block. The following examples use a path to get information about this value. To look at nested values, type: ``` probe values/4 ["one" ["two" %file2.txt]] ``` ``` probe values/4/2 ["two" %file2.txt] ``` To get the lengths of nested values, type: ``` print length? values/4 2 ``` ``` print length? values/4/2 2 ``` To see what the datatype of a nested value, type: ``` print type? values/4 block ``` ``` print type? values/4/2 block ``` The two series values in the fourth value's block can also be accessed. To look at the values, type: ``` probe values/4/2/1 two ``` ``` probe values/4/2/2 %file2.txt ``` To get the lengths of the values: ``` print length? values/4/2/1 3 ``` ``` print length? values/4/2/2 9 ``` To see what datatype the values are: ``` print type? values/4/2/1 string ``` ``` print type? values/4/2/2 file ``` To modify the values: ``` change (next values/4/2/1) "o" probe values/4/2/1 too ``` ``` change/part (next find values/4/2/2 ".") "r" 3 probe values/4/2/2 %file2.r ``` The above examples illustrate REBOL's ability to operate on values nested inside blocks. Note that in the last series of examples, [[change|Functions: change]] is used to modify a string and file series three layers deep in values. Printing out the values block produces: ``` probe values ["new" [1 2] %file1.txt ["one" ["too" %file2.r]]] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< There are a wide variety of functions that operate on or produce strings. Functions are available for modifying strings, searching strings, compressing and decompressing strings, changing the spacing of strings, parsing strings, and converting strings. These functions operate on all string related datatypes, such as [[string!|Datatypes: String!]], [[binary!|Datatypes: Binary!]], [[tag!|Datatypes: Tag!]], [[file!|Datatypes: File!]], [[url!|Datatypes: Url!]], [[email!|Datatypes: Email!]], and [[issue!|Datatypes: Issue!]]. The string creation, modification and search functions are covered in the [[series|Concepts: Series]] chapter. They include the items listed in `[bad-link:concepts/string.txt]` Functions. |[[copy|Functions: copy]] |copy all or part of a string| |[[make|Functions: make]] |allocate storage for a string| |[[insert|Functions: insert]] |insert a character or substring into another string| |[[remove|Functions: remove]] |remove one or more characters from a string| |[[change|Functions: change]] |change one or more characters in a string| |[[append|Functions: append]] |insert a character or substring at the tail of a string| |[[find|Functions: find]] |find or match a character or string in another string| |[[replace|Functions: replace]] |find a string and replace it with another string| In addition, the series traversing functions like [[next|Functions: next]], [[back|Functions: back]], [[head|Functions: head]], and [[tail|Functions: tail]] were covered. They are used to reposition in strings. In addition, the series test functions allow you to determine your position within a string. This chapter will introduce functions that convert REBOL values into strings. These functions are used often, and they are also used by the [[print|Functions: print]] and [[probe|Functions: probe]] functions. They include: |[[form|Functions: form]] |convert values with spaces and in human readable format| |[[mold|Functions: mold]] |convert values in REBOL readable format| |[[join|Functions: join]] |convert values with no spaces| |[[reform|Functions: reform]] |reduces values before forming them| |[[remold|Functions: remold]] |reduces values before molding them| |[[rejoin|Functions: rejoin]] |reduces values before joining them| This chapter will also describes these string functions: |[[detab|Functions: detab]] |replace tabs with spaces| |[[entab|Functions: entab]] |replace spaces with tabs| |[[trim|Functions: trim]] |remove white space or lines around strings| |[[uppercase|Functions: uppercase]] |convert string to uppercase| |[[lowercase|Functions: lowercase]] |convert string to lowercase| |[[checksum|Functions: checksum]] |compute a checksum for string| |[[compress|Functions: compress]] |compress string| |[[decompress|Functions: decompress]] |decompress string| |[[enbase|Functions: enbase]] |convert a string to base value| |[[debase|Functions: debase]] |convert an enbased string to a string| |[[dehex|Functions: dehex]] |convert hexadecimal ASCII values to characters|
''Overview'' Errors are exceptions that occur when certain irregular conditions occur. These conditions range from syntax errors to file or network access errors. Here are a few examples: ``` 12-30 ** Syntax error: invalid "date" -- "12-30" ** Near: (line 1) 12-30 ``` ``` 1 / 0 ** Math error: attempt to divide by zero ** Where: / ** Near: / 0 ``` ``` read %nofile.r ** Access error: cannot open: %nofile.r reason: -3 ** Where: read ** Near: read %nofile.r ``` Errors are processed within the system as values of the [[error!|Datatypes: Error!]] datatype. An error is an object that, if evaluated, will print an error message and halt. You can also catch errors and handle them in your script. Errors can be passed to functions, returned from functions, and assigned to variables.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''The TRY function'' You can catch errors with the [[try|Functions: try]] function. The [[try|Functions: try]] function is similar to the [[do|Functions: do]] function. It evaluates a block, but always returns a value, even when an error occurs. When no error occurs, try returns the value of a block. For example: ``` print try [100 / 10] 10 ``` When an error occurs, try returns the error. If you write: ``` print try [100 / 0] ** Math Error: Attempt to divide by zero. ** Where: 100 / 0 ``` the error is returned from the [[try|Functions: try]] and the [[print|Functions: print]] function cannot handle it. To handle errors in a script, you must prevent REBOL from evaluating the error. You can prevent an error from being evaluated by passing it to a function. For instance, the error? function will return true when it is passed an error: ``` print error? try [100 / 0] true ``` You can also [print|Functions: print]] the datatype of the value returned from a [[try|Functions: try]]: ``` print type? try [100 / 0] error! ``` The [[disarm|Functions: disarm]] function converts an error to an error object that can be examined. In the example below, the error variable holds an error object: ``` error: disarm try [100 / 0] ``` When an error is disarmed, it will be an [[object!|Datatypes: Object!]] datatype, not an [[error!|Datatypes: Error!]] datatype. Evaluating the disarmed object will not cause an error: ``` probe disarm try [100 / 0] make object! [ code: 400 type: 'math id: 'zero-divide arg1: none arg2: none arg3: none near: [100 / 0] where: none ] ``` Error values can be set to a word before they are disarmed. To set a word to an error, it must be preceded by a function that prevents the error from propagating further. For example: ``` disarm err: try [100 / 0] ``` Setting a variable enables you to access the value of the block later. The example below will print an error or non-error value: ``` either error? result: try [100 / 0] [ probe disarm result ][ print result ] ``` ''The ATTEMPT Function'' The [[attempt|Functions: attempt]] function can also be used for error handling, but rather than return an error, it returns none when an error occurs. ``` value: attempt [read %value.r] ``` The value will be set to none if a read error occurs, normally because the file does not exist.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< There are several categories of errors. ''Contents'' * Syntax Errors * Script Errors * Math Errors * Access Errors * User Errors * Internal Errors * Syntax Errors Syntax errors occur when a script uses REBOL syntax incorrectly. For instance, if a closing bracket is missing or a string is missing its closing quote, a syntax error will occur. These errors only occur during the load or evaluation of a file or string. ''Script Errors'' Script errors are general run-time errors. For instance, an invalid argument to a function will cause a script error. ''Math Errors'' Math errors occur when a math operation cannot be processed. For instance, when attempting to divide by zero an error will occur. ''Access Errors'' Access errors occur when a problem occurs with a file, port or network access. For example, an access error will occur when attempting to read a file that does not exist. ''User Errors'' User errors are generated explicitly by a script by creating an error value and returning it. ''Internal Errors'' Internal errors occur within the REBOL interpreter.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The error object shown above has the structure: ``` make object! [ code: 400 type: 'math id: 'zero-divide arg1: none arg2: none arg3: none near: [100 / 0] where: none ] ``` Where the fields are: |''code'' |The error code number. These are obsolete and should not be used.| |''type'' |The type field identifies the error category. It is always a word datatype of syntax, script, math, access, user, and internal.| |''id'' |The id field is the name for the error as a word. It identifies the specific error that occurred within the error category.| |''arg1'' |This field holds the first argument to the error message. For instance, it may include the datatype of the value that caused the error.| |''arg2'' |This field holds the second argument to the error message.| |''arg3'' |This field holds the third argument to the error message.| |''near'' |The near field is a code fragment that shows where the error occurred.| |''where'' |The where field is reserved.| You can write code that checks any of the error object fields. In this example, the error is printed only when the error id indicates a divide by zero error: ``` error: disarm try [1 / 0] if error/id = 'zero-divide [ print {It is a Divide by Zero error} ] It is a Divide by Zero error ``` The error id word also provides the error block that will be printed by the interpreter. For example: ``` error: disarm try [print zap] probe get error/id [:arg1 "has no value"] ``` This block is defined by the `system/errors` object.
Pending Revision This document was written for R2 and has yet to be revised for R3. User errors can be generated. The simplest way to generate an error is make it. Here is an example: ``` make error! "this is an error" ** User Error: this is an error. ** Where: make error! "this is an error" ``` Any of the existing errors can be generated by making the error with a block argument. This block contains the error category name and the error message id name. If the error requires arguments, the arguments follow the message `id` name. The arguments are what define the `arg1`, `arg2` and `arg3` values in the error object. Here is an example: ``` make error! [script expect-set series! number!] ** Script Error: Expected one of: series! - not: number!. ** Where: make error! [script expect-set series! number!] ``` Custom errors can be entered into the `system/error` object's user category. This is done by making a new user category with new entries. These entries are used when generating errors. For instance, the following example enters an error into the user category: ``` system/error/user: make system/error/user [ my-error: "a simple error" ] ``` Now an error can be generated using the `my-error` message id: ``` if error? err: try [ make error! [user my-error] ] [probe disarm err] make object! [ code: 803 type: 'user id: 'my-error arg1: none arg2: none arg3: none near: [make error! [user my-error]] where: none ] ``` To create more informative errors, define an error that uses data available when it is generated. This data is included in the disarmed error object and printed as part of the error message. For instance, to use all three argument spaces in an error object: ``` system/error/user: make system/error/user [ my-error: [:arg1 "doesn't go into" :arg2 "using" :arg3] ] if error? err: try [ make error! [user my-error [this] "that" my-function] ] [probe disarm err] make object! [ code: 803 type: 'user id: 'my-error arg1: [this] arg2: "that" arg3: 'my-function near: [make error! [user my-error [this] "that" my-function]] where: none ] ``` The error message generated for my-error can be printed without stopping the script: ``` disarmed: disarm err print bind (get disarmed/id) (in disarmed 'id) this doesn't go into that using my-function ``` A new library category may be created if there is a need to group a series of errors together by making a new category in `system/error`: ``` system/error: make system/error [ my-errors: make object! [ code: 1000 type: "My Error Category" error1: "a simple error" error2: [:arg1 "doesn't go into" :arg2 "using" :arg3] ] ] ``` The `type` defined in the error object will be the error type printed when the error is generated. The following example illustrates generating an error from both `error1` and `error2` in the my-error category. Generating an error from `error1`. This error requires no arguments: ``` disarmed: disarm try [make error! [my-errors error1]] print get disarmed/id a simple error ``` Generating an error from `error2` requires three arguments: ``` disarmed: disarm try [ make error! [my-errors error2 [this] "that" my-function]] print bind (get disarmed/id) (in disarmed 'id) this doesn't go into that using my-function ``` Finally, the description that returns the errors defined in `my-errors` may be obtained with: ``` probe get in get disarmed/type 'type My Error Category ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Overview'' The foremost goal of REBOL is to establish a standard method of communication that spans all computer systems. REBOL provides a simple, direct means of expressing any kind of information with optimal flexibility and minimal syntax. For example, examine the following line: ``` Sell 100 shares of "Acme" at $47.97 per share ``` The line looks a lot like English making it easy to compose if you are sending it and easy to understand if you are receiving it. However, this line is actually a valid expression in REBOL, so your computer could also understand and act on it. (Note that the line is a "dialect" of REBOL. It can be in-directly evaluated. More on this concept below.) REBOL provides a common language between you and your computer. In addition, if your computer sends this expression to your stock broker's computer, which is also running REBOL, your stock broker's computer can understand the expression and act on it. So, REBOL provides a common language between computers. And, the line could be sent to millions of other computer systems that could also act on it. The following line is another example of a REBOL expression: ``` Reschedule exam for 2-January-1999 at 10:30 ``` The expression shown in the above example (written in another dialect) may have come from your doctor typing it, or perhaps it originated from an application that was run by your doctor. It does not matter. What is important is that the expression can be acted upon regardless of the type of computer, hand-held device, kiosk, or television console you are using. The data values (numbers, strings, prices, dates, and times) in all of the expressions shown in the previous examples are standardized valid REBOL formats. The words, however, depend on a specific context of interpretation to convey their meaning. Words such as `sell`, [[at|Functions: at]], and [[read|Functions: read]] have different meanings in different contexts. The words are relative expressions -- their meaning is context dependent. Expressions can be processed in one of two ways: ''directly'' by the REBOL interpreter, or indirectly by a REBOL script. An expression processed indirectly is called a ''dialect''. The previous examples are dialects, so they are processed by a script. The following example is not a dialect and is processed directly by the REBOL interpreter: ``` send master@rebol.com read http://www.rebol.com ``` In this example the words `[bad-link:functions/send.txt]` and read are functions that are processed by the REBOL interpreter. The distinction REBOL makes is that ''information'' is either directly or indirectly interpreted. ''The distinction is not whether information is code or data, but how it is processed. In REBOL code is often handled as data and data is frequently processed as code, so the traditional division between code and data blurs. How information is processed determines whether it is code or data''.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< REBOL Expressions are based on this concept: you combine `values` and `words` into `blocks`. In scripts, a block is normally enclosed with square brackets `[ ]`. Everything within the square brackets is part of the block. The block contents can span any number of lines, and its format is completely freeform. The following examples show various ways of formatting block content: ``` [white red green blue yellow orange black] ["Spielberg" "Back to the Future" 1:56:20 MCA] [ "Bill" billg@ms.dom #315-555-1234 "Steve" jobs@apl.dom #408-555-4321 "Ted" ted@gw2.dom #213-555-1010 ] sites: [ http://www.rebol.com [save %reb.html data] http://www.cnn.com [print data] ftp://www.amiga.com [send cs@org.foo data] ] ``` Some blocks do not require square brackets, because they are implied. For example, in a REBOL script, there are no brackets around the entire script, however, the script content is a block. The square brackets of an outer-block of the script are implied. The same is true for expressions typed at the command prompt or for REBOL messages sent between computers--each is an implied block. Another important aspect of blocks is that they imply additional information. Blocks group a set of values in a particular order. That is, a block can be used as a data set as well as a sequence. This will be described in more detail in the [[series|Concepts: Series]] Chapter.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< As previously mentioned, blocks are not normally evaluated. A do function is required to force a block to be evaluated. There are times when you may need to conditionally evaluate a block. The following section describes several ways to do this. ''Contents'' * [[Conditional Blocks]] * [[Any and All]] * [[Conditional Loops|Concepts: Expressions: Conditional: Conditional Loops]] !!! ''Conditional Blocks'' {{Conditional Blocks}} !!! ''Any and All'' {{Any and All}} !!! ''Conditional Loops'' {{Concepts: Expressions: Conditional: Conditional Loops}}
The [[until|Functions: until]] and [[while|Functions: while]] functions repeat the evaluation of a block until a condition is met. The [[until|Functions: until]] function repeats a block until the evaluation of the block returns `true` (that is, not `false` or [[none!|Datatypes: None!]] ). The evaluation block is always evaluated at least once. The [[until|Functions: until]] function returns the value of its block. The example below will print each word in the color block. The block begins by printing the first word of the block. It then moves to the next color for each color in the block. The [[tail?|Functions: tail?]] function checks for the end of the block, and will return true, which will cause the [[until|Functions: until]] function to exit. ``` color: [red green blue] until [ print first color tail? color: next color ] red green blue ``` The [[break|Functions: break]] function can be used to escape from the until loop at any time. The while function repeats the evaluation of its two block arguments while the first block returns true. The first block is the condition block, the second block is the evaluation block. When the condition block returns `false` or [[none!|Datatypes: None!]], the expression block will no longer be evaluated and the loop terminates. Here is a similar example to that show above. The while loop will continue to print a color while there are still colors to print. ``` color: [red green blue] while [not tail? color] [ print first color color: next color ] red green blue ``` The condition block can contain any number of expressions, so long as the last expression returns the condition. To illustrate this, the next example adds a print to the condition block. This will print the index value of the color. It will then check for the tail of the color block, which is the condition used for the loop. ``` color: [red green blue] while [ print index? color not tail? color ][ print first color color: next color ] 1 red 2 green 3 blue 4 ``` The last value of the block is returned from the [[while|Functions: while]] function. A [[break|Functions: break]] can be used to escape from the loop at any time.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< To ''evaluate'' an expression is to compute its value. REBOL operates by evaluating the series of expressions constituting a script and then returning the result. Evaluating is also called running, processing, or executing a script. Evaluation is performed on blocks. Blocks can be typed at the console or loaded from a script file. Either way, the process of evaluation is the same. ''Contents'' * [[Evaluating Console Input]] * [[Evaluating Simple Values]] * [[Evaluating Blocks]] * [[Reducing Blocks]] * [[Evaluating Scripts]] * [[Evaluating Strings]] * [[Evaluation Errors]] !!! ''Evaluating Console Input'' {{Evaluating Console Input}} !!! ''Evaluating Simple Values'' {{Evaluating Simple Values}} !!! ''Evaluating Blocks'' {{Evaluating Blocks}} !!! ''Reducing Blocks'' {{Reducing Blocks}} !!! ''Evaluating Scripts'' {{Evaluating Scripts}} !!! ''Evaluating Strings'' {{Evaluating Strings}} !!! ''Evaluation Errors'' {{Evaluation Errors}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The while and until functions above where used to loop until a condition was met. There are also several functions that let you loop for a specified a number of times. ''Contents'' * Loop * Repeat * For * Foreach * Forall and Forskip * Forever * Break ''Loop'' The [[loop|Functions: loop]] function evaluates a block a specified number of times. The following example prints a line of 40 dashes: ``` loop 40 [prin "-"] ==========================- ``` Note that the [[prin|Functions: prin]] function is similar to the [[print|Functions: print]] function, but prints its argument without a line termination. The [[loop|Functions: loop]] function returns the value of the final evaluation of the block: ``` i: 0 print loop 40 [i: i + 10] 400 ``` ''Repeat'' The [[repeat|Functions: repeat]] function extends loop by allowing you to monitor the loop counter. The [[repeat|Functions: repeat]] function's first argument is a word that will be used to hold the count value: ``` repeat count 3 [print ["count:" count]] count: 1 count: 2 count: 3 ``` The final block value is also returned: ``` i: 0 print repeat count 10 [i: i + count] 55 ``` In the previous examples, the count word only has its value within the repeat block. In other words, the value of count is local to the block. After repeat finishes, count returns to any previous set value. ''For'' The [[for|Functions: for]] function extends repeat by allowing the starting value, the ending value, and the increment to the value to be specified. Any of the values can be positive or negative. The example below begins at zero and counts to 50 by incrementing 10 each time through the loop. ``` for count 0 50 10 [print count] 0 10 20 30 40 50 ``` The [[for|Functions: for]] function cycles through the loop up to and including the ending value. However, if the count exceeds the ending value, the loop is still terminated. The example below specifies an ending value of 55. That value will never be hit because the loop increments by 10 each time. The loop stops at 50. ``` for count 0 55 10 [prin [count " "]] 0 10 20 30 40 50 ``` The next example shows how to count down. It begins at four and counts down to zero one at a time. ``` for count 4 0 -1 [print count] 4 3 2 1 0 ``` The [[for|Functions: for]] function also works for decimal numbers, money, times, dates, series, and characters. Be sure that both the starting and ending values are of the same datatype. Here are several examples of using the for loop with other datatypes. ``` for count 10.5 0.0 -1 [prin [count " "]] 10.5 9.5 8.5 7.5 6.5 5.5 4.5 3.5 2.5 1.5 0.5 ``` ``` for money $0.00 $1.00 $0.25 [prin [money " "]] $0.00 $0.25 $0.50 $0.75 $1.00 ``` ``` for time 10:00 12:00 0:20 [prin [time " "]] 10:00 10:20 10:40 11:00 11:20 11:40 12:00 ``` ``` for date 1-jan-2000 4-jan-2000 1 [prin [date " "]] 1-Jan-2000 2-Jan-2000 3-Jan-2000 4-Jan-2000 ``` ``` for char #"a" #"z" 1 [prin char] abcdefghijklmnopqrstuvwxyz ``` The [[for|Functions: for]] function also works on series. The following example uses for on a string value. The word end is defined as the string with its current index at the `d` character. The [[for|Functions: for]] function moves through the string series one character at a time and stops when it reaches the character position defined to end: ``` str: "abcdef" end: find str "d" for s str end 1 [print s] abcdef bcdef cdef def ``` ''Foreach'' The [[foreach|Functions: foreach]] function provides a convenient way to repeat the evaluation of a block for each element of a series. It works for all types of block and string series. In the example below, each word in the block will be printed: ``` colors: [red green blue] foreach color colors [print color] red green blue ``` In the next example, each character in a string will be printed: ``` string: "REBOL" foreach char string [print char] R E B O L ``` In the example below, each filename in a directory block will be printed: ``` files: read %. foreach file files [ if find file ".t" [print file] ] file.txt file2.txt newfile.txt output.txt ``` When a block contains groups of values that are related, the foreach function can fetch all the values of the group at the same time. For example, here is a block that contains a time, string, and price. By providing the foreach function with a block of words for the group, each of their values can be fetched and printed. ``` movies: [ 8:30 "Contact" $4.95 10:15 "Ghostbusters" $3.25 12:45 "Matrix" $4.25 ] foreach [time title price] movies [ print ["watch" title "at" time "for" price] ] watch Contact at 8:30 for $4.95 watch Ghostbusters at 10:15 for $3.25 watch Matrix at 12:45 for $4.25 ``` In the above example, the foreach value block, `[''time title price]`, specifies that three values are to be fetched from movies for each evaluation of the block. The variables used to hold the [[foreach|Functions: foreach]] values are local to the block. Their value are only set within the block that is being repeated. Once the loop has exited, the variables return to their previously set values. ''Forall and Forskip'' Similar to [[foreach|Functions: foreach]], the [[forall|Functions: forall]] function evaluates a block for every value in a series. However, there are some important differences. The [[forall|Functions: forall]] function is handed the series that is set to the beginning of the loop. As it proceeds through the loop, [[forall|Functions: forall]] modifies the position within the series. ``` colors: [red green blue] forall colors [print first colors] red green blue ``` In the above example, after each evaluation of the block, the series is advanced to its next position. When [[forall|Functions: forall]] returns, the `color` index is at the tail of the series. To continue to use the series you will need to return it to its head position with the following line: ``` colors: head colors ``` The [[forskip|Functions: forskip]] function evaluates a block for groups of values in a series. The second argument to [[forskip|Functions: forskip]] is the count of how many elements to move forward after each cycle of the loop. Like [[forall|Functions: forall]], [[forskip|Functions: forskip]] is handed the series with the series index set to where it is to begin. Then, forskip modifies the index position as it continues the loop. After each evaluation of the body block, the series index is advanced by the skip amount to its next index position. The following example demonstrates [[forskip|Functions: forskip]] : ``` movies: [ 8:30 "Contact" $4.95 10:15 "Ghostbusters" $3.25 12:45 "Matrix" $4.25 ] forskip movies 3 [print second movies] Contact Ghostbusters Matrix ``` In the above example, [[forskip|Functions: forskip]] returns with the movies series at its tail position. You will need to use the [[head|Functions: head]] function to return the series back to its head position. ''Forever'' The [[forever|Functions: forever]] function evaluates a block endlessly or until a it encounters the [[break|Functions: break]] function. The following example uses [[forever|Functions: forever]] to check for the existence of a file every ten minutes: ``` forever [ if exists? %datafile [break] wait 0:10 ] ``` ''Break'' You can stop the repeated evaluation of a block with the [[break|Functions: break]] function. The [[break|Functions: break]] function is useful when a special condition is encountered and the loop must be stopped. The [[break|Functions: break]] function works with all types of loops. In the following example, the loop will [[break|Functions: break]] if a number is greater than 5. ``` repeat count 10 [ if (random count) > 5 [break] print "testing" ] testing testing testing ``` The [[break|Functions: break]] function does not return a value from the loop unless a `/return` refinement is used: ``` print repeat count 10 [ if (random count) > 5 [break/return "stop here"] print "testing" "normal exit" ] testing testing testing stop here ``` In the above example, if the repeat terminates without the condition occurring, the block returns the string `normal` exit. Otherwise, `break/return` will return the string stop here.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< There are several methods to selectively evaluate expressions in REBOL. These methods provide a way for evaluation to branch many different ways, based on a key value. ''Contents'' * Select * Switch ** Default Case ** Common Cases ** Other Cases ''Select'' The [[select|Functions: select]] is often used to obtain a particular value or block, given a target value. If you define a block of values and actions, you can use select to search for the action that corresponds to a value. ``` cases: [ center [print "center"] right [print "right"] left [print "left"] ] action: select cases 'right if action [do action] right ``` In the previous example, the select function finds the word right and returns the block that follows it. (If for some reason the block was not found, then [[none!|Datatypes: None!]] would have been returned.) The block is then evaluated. The values used in the example are words, but they can be any kind of value: ``` cases: [ 5:00 [print "everywhere"] 10:30 [print "here"] 18:45 [print "there"] ] action: select cases 10:30 if action [do action] here ``` ''Switch'' The [[select|Functions: select]] function is used so often that there is a special version of it called switch, which includes the evaluation of the resulting block. The [[switch|Functions: switch]] function makes it easier to perform inline selective evaluation. For instance, to switch on a simple numeric case: ``` switch 22 [ 11 [print "here"] 22 [print "there"] ] there ``` The [[switch|Functions: switch]] function also returns the value of the block it evaluates, so the previous example can also be written as: ``` str: copy "right " print switch 22 [ 11 [join str "here"] 22 [join str "there"] ] right there ``` and: ``` car: pick [Ford Chevy Dodge] random 3 print switch car [ Ford [351 * 1.4] Chevy [454 * 5.3] Dodge [154 * 3.5] ] 2406.2 ``` The cases can be any valid datatype, including numbers, strings, words, dates, times, urls, and files. Here are some examples: Strings: ``` person: "kid" switch person [ "dad" [print "here"] "mom" [print "there"] "kid" [print "everywhere"] ] everywhere ``` Words: ``` person: 'kid switch person [ dad [print "here"] mom [print "there"] kid [print "everywhere"] ] everywhere ``` Datatypes: ``` person: 123 switch type?/word [ string! [print "a string"] binary! [print "a binary"] integer! [print "an integer number"] decimal! [print "a decimal number"] ] an integer number ``` Files: ``` file: %rebol.r switch file [ %user.r [print "here"] %rebol.r [print "everywhere"] %file.r [print "there"] ] everywhere ``` URLs: ``` url: ftp://ftp.rebol.org switch url [ http://www.rebol.com [print "here"] http://www.cnet.com [print "there"] ftp://ftp.rebol.org [print "everywhere"] ] everywhere ``` Tags: ``` tag: <LI> print switch tag [ <PRE> ["Preformatted text"] <TITLE> ["Page title"] <LI> ["Bulleted list item"] ] Bulleted list item ``` Times: ``` time: 12:30 switch time [ 8:00 [send wendy@domain.dom "Hey, get up"] 12:30 [send cindy@rebol.dom "Join me for lunch."] 16:00 [send group@every.dom "Dinner anyone?"] ] ``` !!!!! ''Default Case'' A default case can be specified when none of the other cases match. Use the default refinement to specify a default:. ``` time: 7:00 switch/default time [ 5:00 [print "everywhere"] 10:30 [print "here"] 18:45 [print "there"] ] [print "nowhere"] nowhere ``` !!!!! ''Common Cases'' If you have common cases, where the result would be the same for several values, you can define a word to hold a common block of code: ``` case1: [print length? url] ; the common block url: http://www.rebol.com switch url [ http://www.rebol.com case1 http://www.cnet.com [print "there"] ftp://ftp.rebol.org case1 ] 20 ``` !!!!! ''Other Cases'' More than just blocks can be evaluated for cases. This example evaluates the file that corresponds to a day of the week: ``` switch now/weekday [ 1 %monday.r 5 %friday.r 6 %saturday.r ] ``` So, if it's Friday, the `friday.r` file is evaluated and its result is returned from the switch. This type of evaluation also works for URLs: ``` switch time [ 8:30 ftp://ftp.rebol.org/wakeup.r 10:30 http://www.rebol.com/break.r 18:45 ftp://ftp.rebol.org/sleep.r ] ``` The cases for [[switch|Functions: switch]] are enclosed in a block, and therefore can be defined apart from the switch statement: ``` schedule: [ 8:00 [send wendy@domain.dom "Hey, get up"] 12:30 [send cindy@dom.dom "Join me for lunch."] 16:00 [send group@every.dom "Dinner anyone?"] ] switch 8:00 schedule ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Evaluation of a script can be stopped at any time by pressing the escape key (ESC) on the keyboard or by using the [[halt|Functions: halt]] and [[quit|Functions: quit]] functions. The [[halt|Functions: halt]] function stops evaluation and returns you to the REBOL console prompt: ``` if time > 12:00 [halt] ``` The [[quit|Functions: quit]] function stops evaluation and exits the REBOL interpreter: ``` if error? try [print test] [quit] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< There are times when you want to evaluate a block, but should an error occur, you do not want to stop the evaluation of the rest of your script. For example, you might be performing a number division, but do not want your script to stop if a divide-by-zero occurs. The [[try|Functions: try]] function allows you to catch errors during the evaluation of a block. It is almost identical to do. The try function will normally return the result of the block; however, if an error occurs, it will return an error value instead. In the following example, when the divide by zero occurs, the script will pass an error back to the try function, and evaluation will continue from that point. ``` for num 5 0 -1 [ if error? try [print 10 / num] [print "error"] ] 2 2.5 3.33333333333333 5 10 error ``` More about error handling can be found in the [[errors|Concepts: Errors]] Appendix.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< REBOL provides a built-in set of values that can be expressed and exchanged between all systems. Values are the primary elements for composing all REBOL expressions. ''Contents'' * [[Direct and Indirect Values]] * [[Datatypes of Values]] * [[Table of common datatypes]] !!! ''Direct and Indirect Values'' {{Direct and Indirect Values}} !!! ''Datatypes of Values'' {{Datatypes of Values}} !!! ''Table of common datatypes'' {{Table of common datatypes}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Expressions are built from values and words. Words are used to represent meaning. A word can represent an idea or it can represent a specific value. In the previous examples in this chapter, a number of words were used within expressions without explanation. For instance, the do, reduce, and try words are used, but not explained. Words are evaluated somewhat differently than directly expressed values. When a word is evaluated, its value is looked up, evaluated, and returned as a result. For example, if you type the following word: ``` zero 0 ``` the value 0 is returned. The word zero is predefined to be the number zero. When the word is looked up, a zero is found and is returned. When words like do and print are looked up, their values are found to be functions, rather than simple values. In such cases, the function is evaluated, and the result of the function is returned. ''Contents'' * [[Word Names|Concepts: Expressions: Words: Word Names]] * [[Word Usage]] * [[Setting Words]] * [[Getting Words]] * [[Literal Words]] * [[Unset Words]] * [[Protecting Words]] !!! ''Word Names'' {{Concepts: Expressions: Words: Word Names}} !!! ''Word Usage'' {{Word Usage}} !!! ''Setting Words'' {{Setting Words}} !!! ''Getting Words'' {{Getting Words}} !!! ''Literal Words'' {{Literal Words}} !!! ''Unset Words'' {{Unset Words}} !!! ''Protecting Words'' {{Protecting Words}}
Words are composed of alphabetic characters, numbers, and any of the following characters: ``` ? ! . ' + - * & | = _ ~ ``` A word cannot begin with a number, and there are also some restrictions on words that could be interpreted as numbers. For example, -1 and +1 are numbers, not words. The end of a word is marked by a space, a new line, or one of the following characters: ``` [ ] ( ) { } " : ; / ``` Thus, the brackets of a block are not part of a word. For example, the following block contains the word test : ``` [test] ``` The following characters are not allowed in words as they cause words to be misinterpreted or to generate an error: ``` @ # $ % ^ , ``` Words can be of any length, but words cannot extend past the end of a line: ``` this-is-a-very-long-word-used-as-an-example ``` The following lines provide examples of valid words: ``` Copy print test number? time? date! image-files l'image ++ -- == +- ***** *new-line* left&right left|right ``` REBOL is not case sensitive. The following words all refer to the same word: ``` blue Blue BLUE ``` The case of a word is preserved when it is printed. Words can be reused. The meaning of a word is dependent on its context, so words can be reused in different contexts. There are no keywords in REBOL. You can reuse any word, even those that are predefined in REBOL. For instance, you can use the word if in your code differently than the REBOL interpreter uses this word. <<< Pick Good Words Pick the words you use carefully. Words are used to associate meaning. If you pick your words well, it will be easier for you and others to understand your scripts. <<<
''Definition'' Extensions let you extend REBOL by packaging a mix of REBOL code and data along with native code and data. Extensions are built on top of modules and can export an API, including high-performance native functions, as well as package together images, sounds, and other data into a single loadable file. An important goal of the extensions design was to keep it simple and smart. We wanted programmers to be productive with their time, efficiently adding useful features, not wasting effort dealing with complex APIs, includes, classes, models, or other interface issues. This section of the manual covers: * [[extensions: using extensions|Concepts: Extensions: Using Extensions]] - how to import and access extension modules. * [[extensions: making extensions|Concepts: Extensions: Making Extensions]] - how to create your own extension modules. * [[extensions: host/extension api|Concepts: Extensions: Host/Extension API]] - extension interface function descriptions * [[extensions: example extensions|Concepts: Extensions: Example extensions]] - various examples you can use to get started. * [[extensions: embedded extensions|Concepts: Extensions: Embedded Extensions]] - how to add extensions within an executable program. * [[extensions: callback functions|Concepts: Extensions: Callback Functions]] - describes how to call REBOL from C code ''Special notes'' !!!!! ''Compatibility'' By their very nature, extensions that make use of native code are OS and machine dependent. In order to run across a wide variety of systems, they must be compiled for each of those systems. If you need to build machine-independent programs, it is best to avoid using extensions. If there are specific low-level needs for your program, please do not hesitate to suggest them to REBOL Technologies or to the REBOL development community. If it makes sense to add your suggestion as a general feature to REBOL, it can be done quickly in many cases, depending on the availability of the code and its licensing. !!!!! ''Security'' ''It should also be noted here that the extension modules described here are, by definition, not secure''. That's because they can run any type of low level code. Like any external code, do not run extension modules unless you trust their source. (In a later release we will add a signing mechanism, so at least you can be sure that the code of a extension has not been tampered with since it was published by its author.) When you run R3 with its default secure options, it will not allow you to import a extension. You must first lower the security level for a extension to be loaded and imported.
''How to write C functions that call REBOL functions''. <<< Editor note: Under development. Rough draft for eager developers. <<< See also http://www.rebol.net/wiki/External_Callbacks, and you can put your comments there as well during this development stage. ''Contents'' * [[Basics]] ** Synchronous Callbacks ** Asynchronous Callbacks * [[Example Callbacks]] * [[Details of a Callback]] ** Allocating the CBI ** Setting the Function ** Setting the Mode ** Setting the Arguments ** Calling the Function ** Return Value ** Deallocating the CBI * [[Special Issues]] ** Allocation and GC ** Struct Passing *** Clips pending !!! ''Basics'' {{Basics}} !!! ''Example Callbacks'' {{Example Callbacks}} !!! ''Details of a Callback'' {{Details of a Callback}} !!! ''Special Issues'' {{Special Issues}}
''Explains how to embed extensions into a REBOL executable (using the host-kit)''. ''Contents'' * Basics * Steps * Example ''Basics'' This feature allows you to extend REBOL by embedding your own native and mezzanine code and data within a REBOL executable program. Embedding an extension makes it possible to use the extension and its native command functions without requiring a separate DLL library to accompany your executable program. <<< Not always necessary If your embedded module consists entirely of REBOL code (no native commands), it's not required that you embed it in the way described here. Instead, you can add it to the host bundled source code which initialized in the host in the line: ``` RL_Do_Binary(Reb_Init_Code, REB_INIT_SIZE, 0, 0); ``` More on this is described in the [[host-kit documentation|http://www.rebol.com/r3/docs/concepts/host-kit.html]]. <<< ''Steps'' If you already know how to make an extension (from prior pages), embedding it is trivial. The steps are: # Create a new extension as described in previous sections. It is only necessary to create the `RX_Call` function. The `RX_Init` and `RX_Quit` functions are not required. # Add one or more extensions by calling the `RL_Extend` function. This can be done directly in `host-main.c` or via a function called from that module. This function is defined as: ``` RL_API void *RL_Extend(REBYTE *source, RXICAL call); ``` It accepts as arguments the UTF-8/ASCII source code for a module, along with a pointer to its command dispatcher function. These values are added to the system/catalog/boot-exts block. Later in the boot process, the boot-exts block is processed to import each of its embedded modules. <<< Future Features In the future, it may be possible to provide embedded extensions that do not automatically import on boot. Such extensions would be added to the module list, but would not be otherwise initialized. Later, a program could call import with the module name to initialize access to it. <<< ''Example'' We define an extension module: ``` char *ext = "REBOL [\n" "Title: {Hosted extension}\n" "Name: hosted\n" "Type: module\n" "Exports: [add-mul]\n" "]\n" "add-mul: command [{Add and multiply integers.} a b c]\n" ; ``` and a simple call dispatcher function: ``` RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { RXA_INT64(frm, 1) = (RXA_INT64(frm, 1) + RXA_INT64(frm, 2)) * RXA_INT64(frm, 3); return RXR_VALUE; } ``` We then call the `RL_Extend` function to add it during boot. This is done in the host-main.c code before (or after, it's your choice) the bundled source code init call: ``` RL_Extend(hext, &RX_Call); // Initialize host bundled source code: RL_Do_Binary(Reb_Init_Code, REB_INIT_SIZE, 0, 0); ``` After REBOL boots, we can call the add-mul command that was provided: ``` print add-mul 1 2 3 9 ``` Note that multiple embedded extensions can be added in the same way. <<< Editor note: how to use the make-ext tool for creating it. Also, mention the host-ext-test.c example. <<<
<<< Editor note: This page has fallen out of date with recent changes. <<< ''Contents'' * [[Quick start package]] * [[A blank extension]] ** Format of the examples ** A script to build the init block * [[Returning different values]] * [[Math functions]] ** Fibonacci and factorial * [[String functions]] ** Checksum of characters ** Reverse a string]] * [[Block functions]] ** Sum of numeric values ** Reverse a block !!! ''Quick start package'' {{Quick start package}} !!! ''A blank extension'' {{A blank extension}} !!! ''Returning different values'' {{Returning different values}} !!! ''Math functions'' {{Math functions}} !!! ''String functions'' {{String functions}} !!! ''Block functions'' {{Block functions}}
''Updated for A104 on 31-Aug-2010'' ''Describes the functions of reb-lib, the REBOL API (both the DLL and extension library.)'' <<< Editor note: This document is auto-generated and changes should not be made within this wiki. <<< <<< WARNING: PRELIMINARY Documentation This API is under development and subject to change. Various functions may be moved, removed, renamed, enhanced, etc. <<< Also note: the formatting of this document will be enhanced in future revisions. ''Contents'' !!!!! ''Concept'' The REBOL API provides common API functions needed by the Host-Kit and also by REBOL extension modules. This interface is commonly referred to as "reb-lib". There are two methods of linking to this code: # Direct calls as you would use functions within any DLL. # Indirect calls through a set of macros (that use a structure pointer to the library.) !!!!! ''Functions'' * [[RL_Version]] * [[RL_Init]] * [[RL_Start]] * [[RL_Reset]] * [[RL_Extend]] * [[RL_Escape]] * [[RL_Do_String]] * [[RL_Do_Binary]] * [[RL_Do_Block]] * [[RL_Do_Commands]] * [[RL_Print]] * [[RL_Print_TOS]] * [[RL_Event]] * [[RL_Make_Block]] * [[RL_Make_String]] * [[RL_Make_Image]] * [[RL_Protect_GC]] * [[RL_Get_String]] * [[RL_Map_Word]] * [[RL_Map_Words]] * [[RL_Word_String]] * [[RL_Find_Word]] * [[RL_Series]] * [[RL_Get_Char]] * [[RL_Set_Char]] * [[RL_Get_Value]] * [[RL_Set_Value]] * [[RL_Words_Of_Object]] * [[RL_Get_Field]] * [[RL_Set_Field]] * [[RL_Callback]]
''The previous sections defined [[extensions|Concepts: Extensions]] as a package that can contain both REBOL and C code and data, and showed you [[how to use them|Concepts: Extensions: Using Extensions]]. This section explains how to make your own extensions.'' ''Contents'' * [[Overview]] * [[Example extension]] * [[How extensions work]] * [[Command functions]] ** Qualifying arguments ** Command dispatching ** Argument access ** Multi-typed arguments ** Refinements ** Command results ** Extended frames ** How COMMAND Works * [[Datatypes supported]] ** Immediate datatypes ** Series datatypes ** Special datatypes * [[Referencing words]] * [[Accessing strings and blocks]] * [[Accessing external APIs]] * [[Summary of Prefix Names]] * [[Notes]] !!! ''Overview'' {{Overview}} !!! ''Example extension'' {{Example extension}} !!! ''How extensions work'' {{How extensions work}} !!! ''Command functions'' {{Command functions}} !!! ''Datatypes supported'' {{Datatypes supported}} !!! ''Referencing words'' {{Referencing words}} !!! ''Accessing strings and blocks'' {{Accessing strings and blocks}} !!! ''Accessing external APIs'' {{Accessing external APIs}} !!! ''Summary of Prefix Names'' {{Summary of Prefix Names}} !!! ''Notes'' {{Notes}}
''The previous section defined [[extensions|Concepts: Extensions]] as a package that can contain both REBOL and C code and data. This section explains how to import and use extensions.'' ''Importing a extension'' Extensions work like [[modules|Concepts: Modules]] : you import them before they can be used. When you import an extension, you load its code and data, which can include both REBOL or C code, as well as any data they might need, such as graphics, images, sounds, tables, or whatever. To import an extension called example you would write: ``` import %example.dll ``` Notice that the file suffix is `.dll` - a dynamically loaded library. This is how native functions and their data are able to be loaded by your operating system. The line above will perform these steps to import the extension: * request the operating system to load the example.dll file. * verify that the dll is a valid R3 extension module and of a compatible version. * initialize the REBOL code found within the module, including definitions for native functions (called "commands"). * export all functions (and values) that are listed in the module's exports list. See [[modules|Concepts: Modules]] for more detailed information about how some of these steps are processed. ''Example usage'' Once an extension has been imported, you can use its exported function as you would any other type of function: ``` import %example.dll ; exports add-mul print add-mul 1 2 3 9 ``` If you want to see the exported definition of the example extension, just type: ``` probe import %example.dll ``` This will show you the module header and a list of all its functions and data. Also, just like modules, you can explicitly reference a command function with an extension: ``` mysql: import %r3-mysql.dll sql: mysql/open %books.db mysql/select sql * 'authors ``` This is identical to how you reference a field of an object.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< An important aspect of REBOL's power is its ability to manipulate files and directories. REBOL provides a wide range of functions designed to allow operations ranging from simple file reads to direct access to files and directories. For more information on direct access to files and directories, see the [[ports|Concepts: Ports]] Chapter.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Text files can be easily accessed and managed as individual lines of text, rather than as a single series of characters. For example, to read a file as a block of lines: ``` lines: read/lines %service.txt ``` The above example returns a block containing a series of strings (one for each line) without line terminators. Empty lines are represented by empty strings. To print a specific line you use the following code: ``` print first lines print last lines print pick lines 100 print lines/500 ``` To print all of the lines of a file, use the following line of code: ``` foreach line lines [print line] I wanted the gold, and I sought it, I scrabbled and mucked like a slave. Was it famine or scurvy -- I fought it; I hurled my youth into a grave. I wanted the gold, and I got it -- Came out with a fortune last fall, -- Yet somehow life's not what I thought it, And somehow the gold isn't all. ``` To print all of the lines that contain the string `gold`, use the following line of code: ``` foreach line lines [ if find line "gold" [print line] ] I wanted the gold, and I sought it, I wanted the gold, and I got it -- And somehow the gold isn't all. ``` You can write the text file out as lines using the [[write|Functions: write]] function: ``` write/lines %output.txt lines ``` To write out specific lines from a block, use: ``` write/lines %output.txt [ "line one" "line two" "line three" ] ``` In fact, the functions `read/lines` and `write/lines` can be combined to process files one line at a time. For example the following code removes all of the comments from a REBOL script: ``` script: read/lines %script.r foreach line script [ where: find line ";" if where [clear where] ] write/lines %script1.r script ``` * The sample script in the above example is for demonstration purposes only. In addition to removing comments, the sample script would also remove valid semicolons in quoted strings. Files can be read as lines from a network as well: ``` data: read/lines http://www.rebol.com print pick (read/lines ftp://ftp.rebol.com/test.txt) 3 new ``` The `/lines` refinement can be used with the [[open|Functions: open]] function to read a line at a time from console input. See the chapter on [[ports|Concepts: Ports]] for more information. In addition `/lines` can be used with `/append` to append lines from a block to a file.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< There are several easy-to-use functions for reading directories, managing subdirectories, making new directories, renaming files, and deleting files. In addition, there are standard functions for getting, changing, and listing the current directory. For more information on direct access to directories, see the [[ports|Concepts: Ports]] Chapter. ''Contents'' * [[Reading a Directory]] * [[Making a Directory]] * [[Renaming Directories and Files]] * [[Deleting Directories and Files]] * [[Current Directory]] * [[Changing the Current Directory]] * [[Listing the Current Directory]] !!! ''Reading a Directory'' {{Reading a Directory}} !!! ''Making a Directory'' {{Making a Directory}} !!! ''Renaming Directories and Files'' {{Renaming Directories and Files}} !!! ''Deleting Directories and Files'' {{Deleting Directories and Files}} !!! ''Current Directory'' {{Current Directory}} !!! ''Changing the Current Directory'' {{Changing the Current Directory}} !!! ''Listing the Current Directory'' {{Listing the Current Directory}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< There are a number of functions that provide useful information about a file, such as whether it exists, its file size in bytes, when it was last modified, and whether it is a directory. ''Contents'' * [[Directory Check]] * [[File Existence]] * [[File Size]] * [[File Modification Date]] * [[Directory Information]] !!! ''Directory Check'' {{Directory Check}} !!! ''File Existence'' {{File Existence}} !!! ''File Size'' {{File Size}} !!! ''File Modification Date'' {{File Modification Date}} !!! ''Directory Information'' {{Directory Information}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< When a file is read as text, all line terminators are converted to newline (line feed) characters. Line feeds (used as line terminators on Amiga, Linux, and UNIX systems), carriage returns (used as line terminators on Macintosh), and the CR/LF combination (PC and Internet) are all converted to the equivalent `newline` characters. Using a standard line terminator within scripts allows them to operate in a machine-independent fashion. For example, to search for and count all newline characters within a text file: ``` text: read %file.txt count: 0 while [spot: find text newline][ count: count + 1 text: next spot ] ``` The line conversion is also useful for reading network files: ``` text: read ftp://ftp.rebol.com/test.txt ``` When a file is written, the newline character is converted to the line termination style standard for the operating system being used. For instance, the `newline` character is converted to a CRLF on the PC, LF on UNIX or Amiga, or CR for a Macintosh. Network files are written with CRLF. The following function converts any text file with any terminator style to that used by the local operating system: ``` convert-lines: func [file] [write file read file] ``` The file is read and all line terminators are converted, then the file is written and newline characters are converted to the local operating system style. Line conversion can be disabled by reading the file as binary. For instance, the following line: ``` write/binary %newfile.txt read/binary %oldfile.txt ``` preserves the line terminators of the text file.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< REBOL provides a standard, machine independent file and path naming convention. ''Contents'' * [[File Names]] * [[Path Strings]] * [[Case Sensitivity]] * [[File Name Functions]] !!! ''File Names'' {{File Names}} !!! ''Path Strings'' {{Path Strings}} !!! ''Case Sensitivity'' {{Case Sensitivity}} !!! ''File Name Functions'' {{File Name Functions}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Files are read as a series of text characters or as binary bytes. The source of the file is either a local file on your system or a file from the network. ''Contents'' * [[Reading Text Files]] * [[Reading Binary Files]] * [[Reading Over the Network]] !!! ''Reading Text Files'' {{Reading Text Files}} !!! ''Reading Binary Files'' {{Reading Binary Files}} !!! ''Reading Over the Network'' {{Reading Over the Network}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< You can write a file as a series of text characters or as binary bytes. The location of the file can be either a local file on your system or a file on a network. ''Contents'' * [[Writing Text Files]] * [[Writing Binary Files]] * [[Writing Files to a Network]] !!! ''Writing Text Files'' {{Writing Text Files}} !!! ''Writing Binary Files'' {{Writing Binary Files}} !!! ''Writing Files to a Network'' {{Writing Files to a Network}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Types'' There are several kinds of functions provided by REBOL: |''Native'' |A function that is evaluated directly by the processor. These are the lowest level functions of the language.| |''Function'' |A higher level function that is defined by a block and is evaluated by evaluating the functions within the block. Also called user-defined functions.| |''Mezzanine'' |A name for higher level functions that are a standard part of the language. These are not native functions.| |''Operator'' |A function that is used as an infix operator. Examples are `+`, `-`, `[bad-link:functions/z-gtb-lt.txt]` and `/`.| |''Routine'' |A function that is used to call external library functions (`REBOL/Command` feature).|
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Because functions are created dynamically by evaluation, you can determine how you want a function created, based on other information. This is a way to provide conditional code as is found in the macro or preprocessor sub-languages of other programming languages. Within the REBOL language this type of conditional code is done with normal REBOL code. For instance, you may want to create a debugging version of a function that prints additional information: ``` test-mode: on timer: either test-mode [ func [delay] [ print "delaying..." wait delay print "resuming" ] ][ func [delay] [wait delay] ] ``` Here you will create one of two functions, based on the test-mode you are running. This can also be written shorter as: ``` timer: func [delay] either test-mode [[ print "delaying..." wait delay print "resuming" ]][[wait delay]] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< You can define functions that work in the same way as native functions. These are called ''user-defined'' functions. User-defined functions are of the [[function!|Datatypes: Function!]] datatype. You can make simple functions that require no arguments with the [[does|Functions: does]] function. This example defines a new function that prints the current time: ``` print-time: does [print now/time] print-time 10:30 ``` The does function returns a value, which is the new function. In the example, the `print-time` word is set to the function. However, this function value can be set to a word, passed to another function, returned as the result of a function, saved in a block, or immediately evaluated. Functions that require arguments are made with the [[func|Functions: func]] function, which accepts two arguments: ``` func spec body ``` The first argument is a block that specifies the interface to the function. It includes a description of the function, its arguments, the types allowed for arguments, descriptions of the arguments, and other items. The second argument is a block of code that is evaluated whenever the function is evaluated. Here is an example of a new function called sum: ``` sum: func [arg1 arg2] [arg1 + arg2] ``` The newly defined function accepts two arguments, as specified in the first block. The second block is the body of the function, which, when evaluated, adds the two arguments together. The new function is returned as a value from func and the sum word is set to it. Here it is in use: ``` print sum 123 321 444 ``` The result of `arg1` being added to `arg2` is returned and printed. <<< Func is Defined in REBOL `'Func` is a function that makes other functions. It performs a make on the function! datatype. func is defined as: ``` func: make function! [args body] [ make function! args body ] ``` <<< ''Contents'' * [[Interface Specifications]] * [[Literal Arguments]] * [[Get Arguments]] * [[Defining Refinements]] * [[Local Variables]] * [[Local Variables Containing Series]] * [[Returning a Value]] * [[Returning Multiple Values]] !!! ''Interface Specifications'' {{Interface Specifications}} !!! ''Literal Arguments'' {{Literal Arguments}} !!! ''Get Arguments'' {{Get Arguments}} !!! ''Defining Refinements'' {{Defining Refinements}} !!! ''Local Variables'' {{Local Variables}} !!! ''Local Variables Containing Series'' {{Local Variables Containing Series}} !!! ''Returning a Value'' {{Returning a Value}} !!! ''Returning Multiple Values'' {{Returning Multiple Values}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The way function arguments are evaluated dictates the general order of words and values in the language. This section goes into more detail on how functions are evaluated. ''Contents'' * [[Arguments]] * [[Argument DataTypes]] * [[Refinements]] * [[Function Values]] !!! ''Arguments'' {{Arguments}} !!! ''Argument DataTypes'' {{Argument DataTypes}} !!! ''Refinements'' {{Refinements}} !!! ''Function Values'' {{Function Values}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Sometimes a script needs to refer to a function before it has been defined. This can be done as long as the variable for the function is not evaluated before it is defined. ``` buy: func [item] [ append own item sell head item ; appears before it is defined ] sell: func [item] [ remove find own item ] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Function attributes provide control over specific function behaviors, such as the method a function uses to handle errors or to exit. The attributes are an optional block of words within the interface specifications. There are currently two function attributes: [[catch|Functions: catch]] and [[throw|Functions: throw]]. Error messages typically are displayed when they occur within the function. If the [[catch|Functions: catch]] attribute is specified, errors that are thrown within the function are caught automatically by the function. The errors are not displayed within the function but at the point where the function was used. This is useful if you are providing a function library (mezzanine functions) and don't want the error to be displayed within your function, but where it was called: ``` root: func [[catch] num [number!]] [ if num < 0 [ throw make error! "only positive numbers" ] square-root num ] root 4 2 ``` ``` root -4 **User Error: only positive numbers **Where: root -4 ``` Notice that in this example, the error occurs where root was called even though the actual error was generated in the body of the function. This is because the [[catch|Functions: catch]] attribute was used. Without the [[catch|Functions: catch]] attribute, the error would occur within the `root` function: ``` root: func [num [number!]] [ square-root num ] root -4 ** Math Error: Positive number required. ** Where: square-root num ``` The user may not know anything about the internals of the `root` function. So the error message would be confusing. The user only knows about `root`, but the error was in [[square-root|Functions: square-root]]. Do not get the [[catch|Functions: catch]] attribute mixed up with the [[catch|Functions: catch]] function. Although they are similar, the [[catch|Functions: catch]] function can be applied to any block that is evaluated. The [[throw|Functions: throw]] attribute allows you to write your own control functions, such as [[for|Functions: for]], [[foreach|Functions: foreach]], [[if|Functions: if]], [[loop|Functions: loop]], and [[forever|Functions: forever]], by allowing your functions to pass the [[return|Functions: return]] and [[exit|Functions: exit]] operations. For example, this loop function: ``` loop-time: func [time block] [ while [now/time < time] block ] ``` evaluates a block until a specific time has been reached or passed. This loop can then be used within a function: ``` do-job: func [job][ loop-time 10:30 [ if error? try [page: read http://www.rebol.com] [return none] ] page ] ``` Now, what happens when the return `[bad-link:datatypes/none].txt]` block is evaluated? Because this block is evaluated by the `loop-time` function, the return occurs in that function, not in `do-job`. This can be prevented with the [[throw|Functions: throw]] attribute: ``` loop-time: func [[throw] time block] [ while [now/time < time] block ] ``` The [[throw|Functions: throw]] attribute causes a [[return|Functions: return]] or [[exit|Functions: exit]] that has occurred within the block to be thrown up to the previous level, which is the next function causing `do-job` to return.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Functions can define other functions. The sub-functions can be global, local, or returned as a result, depending on their purpose. For example, to create a global function from within a function, assign it to a global variable: ``` make-timer: func [code] [ timer: func [time] code ] make-timer [wait time] timer 5 ``` To make a local function, assign it to a local variable: ``` do-timer: func [code delay /local timer] [ timer: func [time] code timer delay timer delay ] do-timer [wait time] 5 ``` The `timer` function only exists during the period when the `do-timer` function is being evaluated. To return a function as a result: ``` make-timer: func [code] [ func [time] code ] timer: make-timer [wait time] timer 5 ``` <<< Use Correct Local Variables You should avoid using variables that are local to the top level function as an unevaluated part of the nested function. For example: ``` make-timer: func [code delay] [ timer: func [time] [wait time + delay] ] ``` In the example, the delay word dynamically belongs to the `make-timer` function. This should be avoided, as the delay value will change in subsequent calls to make-timer. <<<
<<< Pending Revision This [[document was written for R2|Online help]] and has yet to be revised for R3. <<< Useful information about all functions of the system can be retrieved with the [[help|Functions: help]] function: ``` help send USAGE: SEND address message /only /header header-obj DESCRIPTION: Send a message to an address (or block of addresses) SEND is a function value. ARGUMENTS: address -- An address or block of addresses (Type: email block) message -- Text of message. First line is subject. (Type: any) REFINEMENTS: /only -- Send only one message to multiple addresses /header -- Supply your own custom header header-obj -- The header to use (Type: object) ``` All of this information comes from the definition of the function. Help can be obtained for all types of functions, not just natives or built-in functions. The help function can also be used for user-defined functions. The documentation that is displayed about a function is provided when the function is defined. You can also search for help on functions that contain various patterns. For instance, at the command prompt, you could type ``` Help "path" Found these words: clean-path (function) lit-path! (datatype) lit-path? (action) path! (datatype) path-thru (function) path? (action) set-path! (datatype) set-path? (action) split-path (function) to-lit-path (function) to-path (function) to-set-path (function) ``` to display all the words that contain the string [[path!|Datatypes: Path!]]. To view a list of all functions available in REBOL, type [[what|Functions: what]] at the command prompt. ``` what * [value1 value2] ** [number exponent] + [value1 value2] - [value1 value2] / [value1 value2] // [value1 value2] < [value1 value2] <= [value1 value2] <> [value1 value2] = [value1 value2] == [value1 value2] =? [value1 value2] > [value1 value2] >= [value1 value2] ? ['word] ?? ['name] about [] abs [value] absolute [value] ... ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The specification of all functions can be obtained and manipulated during run-time. For example, you can print the specification block for a function with: ``` probe third :if [ "If condition is TRUE, evaluates the block." condition then-block [block!] /else "If not true, evaluate this block" else-block [block!] ] ``` The body code of functions can be obtained with: ``` probe second :append [ head either only [ insert/only tail series :value ][ insert tail series :value ] ] ``` Functions can be dynamically queried during evaluation. This is how the [[help|Functions: help]] and [[source|Functions: source]] functions work and how errors messages are formatted. In addition, this feature is useful for creating your own unique versions of existing functions. For example, a user-defined print function can be created that has exactly the same specification as [[print|Functions: print]], but sends its output to a string rather than the display: ``` output: make string! 1000 print-str: func third :print [ repend output [reform :value newline] ] ``` The name of the argument used for print-str is obtained from the interface specification for print. You can examine that specification with: ``` probe third :print [ "Outputs a value followed by a line break." value "The value to print" ] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The context of variables is called their `scope`. The broad scope of variables is that of global and local. REBOL uses a form of static scoping, which is called `definitional` scoping. The scope of a variable is determined when its context is defined. In the case of a function, it is determined by when the function is defined. All of the local variables defined within a function are scoped relative to that function. Nested functions and objects are able to access their parent's words. ``` a-func: func [a] [ print ["a:" a] b-func: func [b] [ print ["b:" b] print ["a:" a] print a + b ] b-func 10 ] a-func 11 a: 11 b: 10 a: 11 21 ``` Note here that the `b-func` has access to the `a-func` variable. Words that are bound outside of a function maintain those bindings even when evaluated within a function. This is the result of static scoping, and it allows you to write your own block evaluation functions (like [[if|Functions: if]], [[while|Functions: while]], [[loop|Functions: loop]] ). For example, here is a signed [[if|Functions: if]] function that evaluates one of three blocks based on the sign of a conditional value: ``` ifs: func [ "If positive do block 1, zero do block 2, minus do 3" condition block1 block2 block3 ][ if positive? condition [return do block1] if negative? condition [return do block3] return do block2 ] print ifs 12:00 - now/time ["morning"]["noon"]["night"] night ``` The blocks passed may contain the same words used within the `ifs` function without interfering with the words defined local to the function. This is because the words passed to the function are not bound to the function. The next example passes the words `block1`, `block2` and `block3` to `ifs` as pre-defined words. The `ifs` function does not get confused between the words passed as arguments and the words of the same name defined locally: ``` block1: "morning right now" block2: "just turned noon" block3: "evening time" print ifs (12:00 - now/time) [block1][block2][block3] evening time ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Function names are variables. In REBOL, a variable is a variable, regardless of what it holds. There is nothing special about function variables. Furthermore, functions do not require names. You can create a function and immediately evaluate it, store it in a block, pass it as an argument to a function, or return it as a result from a function. Such functions are unnamed. Here is an example that creates a block of unnamed functions: ``` funcs: [] repeat n 10 [ append funcs func [t] compose [t + (n * 100)] ] print funcs/1 10 110 ``` ``` print funcs/5 10 510 ``` Functions can also be created and passed to other functions. For instance, when you use [[sort|Functions: sort]] with your own comparison, you provide a function as an argument: ``` sort/compare data func [a b] [a > b] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Another technique for learning about REBOL and for saving time in writing your own function is to look at how many of the REBOL mezzanine functions are defined. You can use the [[source|Functions: source]] function to do this. ``` source source source: func [ "Prints the source code for a word." 'word [word!] ][ prin join word ": " if not value? word [print "undefined" exit] either any [native? get word op? get word action? get word] [ print ["native" mold third get word] ] [print mold get word] ] ``` Here the [[source|Functions: source]] function is used to print its own source code. Note that you cannot see the source code for native functions because they exist only as machine code. However, the source function will display the native function interface specification. For example: ``` source add add: native [ "Returns the result of adding two values." value1 [number! pair! char! money! date! time! tuple!] value2 [number! pair! char! money! date! time! tuple!] ] ```
This document is a summary of the REBOL 3.0 GUI. The current developmental documentation can be found at http://www.rebol.com/r3/docs/gui/gui.html To serve as an introduction (to the above more detailed docs), this section is divided into: [[gui: main concepts and terms|Concepts: Gui: Main concepts and terms]] that provides the main ideas and terminology.
''Categories'' Graphics is divided into a few categories (sub-systems): |''GUI'' |The graphical user interface. This is a top level layer to make it it easier to generate and display user interfaces.| |''View'' |The windowing system. This opens windows and handles their events (at the top level). Can be used with the GUI or directly.| |''GOB'' |Low-level graphical objects. These are 2D objects used to generate, composite (layers), and display graphics.| |''Events'' |Event processing. How mouse movement, button clicks, and keyboard keys are handled.| |''Draw'' |A way of specifying scalar vector graphics. This is how lines, boxes, shading, and other images are specified and rendered.| |''Richtext'' |The text system. How fonts and text are rendered and displayed.| |''Effects'' |Special image processing. For example, how to colorize, tint, scale, and blend images.| ''Main links'' The primary documentation for these sections is kept on the DocBase wiki on REBOL.net. The documentation provided here (in this doc wiki) are quick overviews of that information. Here are a few shortcut links to current documents: * [[GUI|http://www.rebol.com/how-to.html]] * [[GOB (graphical object)|http://www.rebol.com/r3/docs/view/gobs.html]] * [[Draw commands]] * [[Event handling|http://www.rebol.com/docs/view-face-events.html]] * [[View|View - Graphical Objects]]
This is a summary of the basic ideas of the GUI. Precise details and changes can be found on [[Graphical User Interface (GUI)]] . ''Goal'' ''The main goal of the R3 GUI is to provide a simple way to create a wide range of user interfaces''. We achieve this goal by providing a set of standard GUI elements, an easy way to arrange them in a window, and a quick way to associate user interactions with a common set of desired results. It is best to think of the REBOL GUI system sort of like HTML, where you provide ''descriptions of content'', rather than calls to functions that generate content. Of course, REBOL is more concise than normal markup languages, and it can generate a wider variety of results and actions with a lot less verbiage and clutter. <<< Different from R2 The R3 GUI is an entirely new design with many improvements, new features, and easier methods that those provided in the R2 VID GUI. Although R3 uses many similar concepts, it is not generally compatible with R2. However, it is our intention that you will find building GUI's in R3 to be a lot easier and faster than R2. <<< ''Structure'' Here is a nutshell summary of the system: * A GUI is displayed in one or more ''windows'' on a computer screen. * Each window is composed of a ''panel''. * Each panel holds one or more ''faces'' (think of them as "widgets"). * Each face has a look and feel defined by its ''style''. * User interaction happens through ''events'' from the mouse or keyboard. * Events trigger ''reactors'' that make actions happen. Each of these elements can be specified, generated, and processed separately, but for most small programs they are specified together in a shorthand form. ''Common terms'' In this documentation we will use specific terms such as viewing a panel. Here are some of the important ones: |''view'' |We say that we ''view'' a window to display it. We use the view function to do that. Sometimes we talk about viewing a panel or viewing a layout, which simply means to view the panel in a window (because a window is defined by a panel).| |''layout'' |We often talk about a ''layout''. It's just a collection of faces that we put into a panel, arranged a certain way. Here we use the layout function. It takes a description (called a dialect) of how the faces are organized. The the layout function is also built into view, so we can skip a step for convenience.| |''show'' |To update a window, panel, or face we ''show'' it. This action causes a "refresh" or "redraw" of the related pixels of the window. In most cases there is no need to call the show function, because to be efficient, the system collects several independent show requests, and displays them all at once.| |''do'' |When a user clicks a button, we ''do'' it. More precisely, we evaluate its reactor, the action we want to happen. For example, the user clicks on a button, and we do a reactor that submits a message to a server, opens a file requestor box, or sends an email.| |''stylize'' |To define a new face style we ''stylize''. For most small programs, you probably won't need to create entirely new styles. You will create styles simply by stylizing from existing styles.| |''facets'' |Attributes used by faces and styles are called ''facets''. For example, the area-color of a button is one facet of the button. There are a few ways to modify facets when you stylize or when you specify a face in a layout.|
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< REBOL provides a comprehensive set of mathematical and trigonometric operations. Many of these operators can handle multiple datatypes, including integer, decimal, money, tuple, time, and date. Some of these datatypes may even be mixed, or coerced.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< All comparison functions return either true or false. ''Contents'' * equal * greater * greater-or-equal * lesser * lesser-or-equal * not equal to * same * strict-equal * strict-not-equal ''equal'' The expressions: ``` value1 = value2 equal? value1 value2 ``` return `true` if the first and second values are equal. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[date!|Datatypes: Date!]], [[tuple!|Datatypes: Tuple!]], [[char! |Datatypes: Char!]] and `[bad-link:datatypes/series.txt]` datatypes. ``` print 11-11-99 = 11-11-99 true ``` ``` print equal? 111.112.111.111 111.112.111.111 true ``` ``` print #"B" = #"B" true ``` ``` print equal? "a b c d" "A B C D" true ``` ''greater'' The expressions: ``` value1 > value2 greater? value1 value2 ``` return `true` if the first value is greater than the second value. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[date!|Datatypes: Date!]], [[tuple!|Datatypes: Tuple!]], [[char! |Datatypes: Char!]] and `[bad-link:datatypes/series.txt]` datatypes. ``` print 13-11-99 > 12-11-99 true ``` ``` print greater? 113.111.111.111 111.112.111.111 true ``` ``` print #"C" > #"B" true ``` ``` print greater? [12 23 34] [12 23 33] true ``` ''greater-or-equal'' The expressions: ``` value1 >= value2 greater-or-equal? value1 value2 ``` return `true` if the first value is greater than or equal to the second value. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[date!|Datatypes: Date!]], [[tuple!|Datatypes: Tuple!]], [[char! |Datatypes: Char!]] and `[bad-link:datatypes/series.txt]` datatypes. ``` print 11-12-99 >= 11-11-99 true ``` ``` print greater-or-equal? 111.112.111.111 111.111.111.111 true ``` ``` print #"B" >= #"A" true ``` ``` print greater-or-equal? [b c d e] [a b c d] true ``` ''lesser'' The expressions: ``` value1 < value2 lesser? value1 value2 ``` return `true` if the first value is less than second value. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[date!|Datatypes: Date!]], [[tuple!|Datatypes: Tuple!]], [[char! |Datatypes: Char!]] and `[bad-link:datatypes/series.txt]` datatypes. ``` print 25 < 50 true ``` ``` print lesser? 25.3 25.5 true ``` ``` print $2.00 < $2.30 true ``` ``` print lesser? 00:10:11 00:11:11 true ``` ''lesser-or-equal'' The expressions: ``` value1 <= value2 lesser-or-equal? value1 value2 ``` return `true` if the first value is less than or equal to the second value. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[date!|Datatypes: Date!]], [[tuple!|Datatypes: Tuple!]], [[char! |Datatypes: Char!]] and `[bad-link:datatypes/series.txt]` datatypes. ``` print 25 <= 25 true ``` ``` print lesser-or-equal? 25.3 25.5 true ``` ``` print $2.29 <= $2.30 true ``` ``` print lesser-or-equal? 11:11:10 11:11:11 true ``` ''not equal to'' The expressions: ``` value1 <> value2 not-equal? value1 value2 ``` return `true` if the first and second values are not equal. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[date!|Datatypes: Date!]], [[tuple!|Datatypes: Tuple!]], [[char! |Datatypes: Char!]] and `[bad-link:datatypes/series.txt]` datatypes. ``` print 26 <> 25 true ``` ``` print not-equal? 25.3 25.5 true ``` ``` print $2.29 <> $2.30 true ``` ``` print not-equal? 11:11:10 11:11:11 true ``` ''same'' The expressions: ``` value1 =? value2 same? value1 value2 ``` return `true` if two words refer to the same value. For instance, when you want to see if two words are referencing the same index in a series. Work with all datatypes. ``` reference-one: "abcdef" reference-two: reference-one print same? reference-one reference-two true ``` ``` reference-one: next reference-one print same? reference-one reference-two false ``` ``` reference-two: next reference-two print same? reference-one reference-two true ``` ``` reference-two: copy reference-one print same? reference-one reference-two false ``` ''strict-equal'' The expressions: ``` value1 == value2 strict-equal? value1 value2 ``` return `true` if the first and second values are strictly the same. Can be used as a case-sensitive version of the [[equal?|Functions: equal?]] `' =` operator for strings and to differentiate between integers and decimals when their values are the same. Works with all datatypes. ``` print strict-equal? "abc" "ABC" false ``` ``` print equal? "abc" "ABC" true ``` ``` print strict-equal? "abc" "abc" true ``` ``` print strict-equal? 1 1.0 false ``` ``` print equal? 1 1.0 true ``` ``` print strict-equal? 1.0 1.0 true ``` ''strict-not-equal'' The expression: ``` strict-not-equal? value1 value2 ``` returns `true` if the first and second values are strictly not the same. Can be used as a case-sensitive version of the [[not-equal?|Functions: not-equal?]] `' <>` operator for strings and to differentiate between integers and decimals when their values are the same. Works with all datatypes. ``` print strict-not-equal? "abc" "ABC" true ``` ``` print not-equal? "abc" "ABC" false ``` ``` print strict-not-equal? "abc" "abc" false ``` ``` print strict-not-equal? 1 1.0 true ``` ``` print not-equal? 1 1.0 false ``` ``` print strict-not-equal? 1.0 1.0 false ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Math errors are reported when an illegal operation is performed or when an overflow or underflow occurs. The following errors may be encountered in math operations. ''Contents'' * Attempt to divide by zero * Math or number overflow * Positive number required * Cannot use operator on datatype! value ''Attempt to divide by zero'' An attempt was made to divide a number by 0. ``` 1 / 0 ** Math Error: Attempt to divide by zero ** Where: connect-to-link ** Near: 1 / 0 ``` ''Math or number overflow'' An attempt was made to process a number too large for REBOL to handle. ``` 1E+300 + 1E+400 ** Math Error: Math or number overflow ** Where: connect-to-link ** Near: 1 / 0 ``` ''Positive number required'' An attempt was made to process a negative number with a math operator that accepts only positive numbers. ``` log-10 -1 ** Math Error: Positive number required ** Where: connect-to-link ** Near: log-10 -1 ``` ''Cannot use operator on datatype! value'' An attempt was made to process incompatible datatypes. The datatype of the second argument in the operation is returned as listed. ``` 10:30 + 1.2.3 ** Script Error: Cannot use add on time! value ** Where: connect-to-link ** Near: 10:30 + 1.2.3 ```
Pending Revision This document was written for R2 and has yet to be revised for R3. There are two rules to remember when evaluating mathematical expressions: * ''Expressions'' are evaluated from left to right. * ''Operators'' take precedence over functions. The evaluation of expressions from left to right is independent of the type of operator that is used. For example: ``` print 1 + 2 * 3 9 ``` In the example above, notice that the result is not seven, as would be the case if multiplication took precedence over addition. <<< Important Note The way mathematical expressions are evaluated from left to right regardless of the operator is different than many other computer languages. Many languages have rules of precedence that you must remember that determine the order of evaluation of operators. For example, a multiply is done before an add. Some languages have 10 or more such rules. In REBOL, rather than requiring users to remember the precedence of operators, you only need to remember the left-to-right rule. More importantly, for advanced code such as expressions that handle expressions (in reflection, for example) you do not need to reorder terms based on precedence. The evaluation order is kept simple. For most math expressions, the left-to-right evaluation rule works quite well and is easy to remember. However, because this rule is different from other languages, it can be a source of programming errors, so watch out. The best solution is to check your work. You can also use parentheses if necessary to clarify your expression (see below), and you can always type your expression at the console to verify your result. <<< If you need to evaluate in some other order, reorder the expression or use parentheses: ``` print 2 * 3 + 1 7 ``` ``` print 1 + (2 * 3) 7 ``` When functions are mixed with operators, the operators are evaluated first, then the functions: ``` print absolute -10 + 5 5 ``` In the above example, the addition is performed first, and its result is provided to the absolute function. In the next example: ``` print 10 + sine 30 + 60 11 30 + 60 => 90 sine 90 => 1 10 + 1 => 11 print ``` To change the order such that the sine of 30 is done first, use parentheses: ``` print 10 + (sine 30) + 60 70.5 ``` or reorder the expression: ``` print 10 + 60 + sine 30 70.5 ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Contents'' * exp * log-10 * log-2 * log-e * power * square-root ''exp'' The expression: ``` exp value ``` raises E (natural number) to the power of `value`. ''log-10'' The expression: ``` log-10 value ``` returns the base-10 logarithm of `value`. ''log-2'' The expression: ``` log-2 value ``` returns the base-2 logarithm of `value`. ''log-e'' The expression: ``` log-e value ``` returns the base-E (natural number) log. of `value`. ''power'' The expressions: ``` value1 ** value2 power value1 value2 ``` return the result of raising `value1` to `value2` power. ''square-root'' The expression: ``` square-root value ``` returns the square root of `value`.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Logic functions can be performed on logic values and on some scalar values including [[integer!|Datatypes: Integer!]], [[char!|Datatypes: Char!]], [[tuple!|Datatypes: Tuple!]], and [[bitset!|Datatypes: Bitset!]]. When working with logic values, the logic functions return boolean values. When working with other types of values, the logic functions on the bits. ''Contents'' * and * or * xor * complement * not ''and'' The [[and|Functions: and]] function compares two logic values and returns true if they are both true' : ``` print (1 < 2) and (2 < 3) true ``` ``` print (1 < 2) and (4 < 3) false ``` When used with integers, the [[and|Functions: and]] function compares bit for bit and returns 1 if both bits are 1, or 0 if neither bit is 1 : ``` print 3 and 5 1 ``` ''or'' The [[or|Functions: or]] function compares two logic values and returns `true` if either of them are true or `false` or if both are false : ``` print (1 < 2) or (2 < 3) true ``` ``` print (1 < 2) or (4 < 3) true ``` ``` print (3 < 2) or (4 < 3) false ``` When used with integers, [[or|Functions: or]] compares bit for bit and returns 1 if either bit is 1 or 0 if both bits are 0: ``` print 3 or 5 7 ``` ''xor'' The [[xor|Functions: xor]] function compares two logic values and returns `true` if and only if one of the values is true and the other is false. ``` print (1 < 2) xor (2 < 3) false ``` ``` print (1 < 2) xor (4 < 3) true ``` ``` print (3 < 2) xor (4 < 3) false ``` When used with integers, [[xor|Functions: xor]] compares bit for bit and returns 1 if and only if one bit is 1 and the other 0 . Otherwise, it returns 0 : ``` print 3 xor 5 6 ``` ''complement'' The [[complement|Functions: complement]] function returns the logic or bitwise complement of a value. It is used for bitmask integer numbers and inverting bitsets. ``` print complement true false ``` ``` print complement 3 -4 ``` ''not'' For a logic value [[not|Functions: not]] returns `true` if the value is false and `false` if the value is true. It does not perform numerical bitwise operations. ``` print not true false ``` ``` print not false true ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The mathematical functions of REBOL operate in a consistent manner over a wide range of scalar (numerical) datatypes. These datatypes include: |''Datatype'' |''Description''|h |`'Integer!` |32 bit numbers without decimal point| |`'Decimal!` |64 bit floating point numbers| |`'Money!` |currency with 64 bit floating point number| |`'Time!` |hours, minutes, seconds, and sub-seconds| |`'Date!` |day, month, year, time, time zone| |`'Pair!` |graphical position or size| |`'Tuple!` |versions, colors, network addresses| The following are a few examples that show a range of math operations over the scalar datatypes. Notice that operators produce useful results for each datatype. The [[integer!|Datatypes: Integer!]] and[[ decimal!|Datatypes: Decimal!]] datatypes: ``` print 2 + 1 3 ``` ``` print 2 - 1 1 ``` ``` print 2 * 10 20 ``` ``` print 20 / 10 2 ``` ``` print 21 // 10 1 ``` ``` print 2.2 + 1 3.2 ``` ``` print 2.2 - 1 1.2 ``` ``` print 2.2 * 10 22 ``` ``` print 2.2 / 10 0.22 ``` ``` print random 10 5 ``` The [[time!|Datatypes: Time!]] datatype: ``` print 2:20 + 1:40 4:00 ``` ``` print 2:20 + 5 2:20:05 ``` ``` print 2:20 + 60 2:21 ``` ``` print 2:20 + 2.2 2:20:02.2 ``` ``` print 2:20 - 1:20 1:00 ``` ``` print 2:20 - 5 2:19:55 ``` ``` print 2:20 - 120 2:18 ``` ``` print 2:20 * 2 4:40 ``` ``` print 2:20 / 2 1:10 ``` ``` print 2:20:01 / 2 1:10:00.5 ``` ``` print 2:21 // 2 0:00 ``` ``` print - 2:20 -2:20 ``` ``` print random 10:00 5:30:52 ``` The [[date!|Datatypes: Date!]] datatype: ``` print 1-Jan-2000 + 1 2-Jan-2000 ``` ``` print 1-Jan-2000 - 1 31-Dec-1999 ``` ``` print 1-Jan-2000 + 31 1-Feb-2000 ``` ``` print 1-Jan-2000 + 366 1-Jan-2001 ``` ``` birthday: 7-Dec-1944 print ["I've lived" (now/date - birthday) "days."] I've lived 20305 days. ``` ``` print random 1-1-2000 29-Apr-1695 ``` The [[money!|Datatypes: Money!]] datatype: ``` print $2.20 + $1 $3.20 ``` ``` print $2.20 + 1 $3.20 ``` ``` print $2.20 + 1.1 $3.30 ``` ``` print $2.20 - $1 $1.20 ``` ``` print $2.20 * 3 $6.60 ``` ``` print $2.20 / 2 $1.10 ``` ``` print $2.20 / $1.10 2 ``` ``` print $2.21 // 2 $0.21 ``` ``` print random $10.00 $6.00 ``` The [[pair!|Datatypes: Pair!]] datatype: ``` print 100x200 + 10x20 110x220 ``` ``` print 10x10 + 3 13x13 ``` ``` print 10x20 * 2x4 20x80 ``` ``` print 100x100 * 3 300x300 ``` ``` print 100x30 / 10x3 10x10 ``` ``` print 100x30 / 10 10x3 ``` ``` print 101x32 // 10x3 1x2 ``` ``` print 101x32 // 10 1x2 ``` ``` print random 100x20 67x12 ``` The [[tuple!|Datatypes: Tuple!]] datatype: ``` print 1.2.3 + 3.2.1 4.4.4 ``` ``` print 1.2.3 - 1.0.1 0.2.2 ``` ``` print 1.2.3 * 3 3.6.9 ``` ``` print 10.20.30 / 10 1.2.3 ``` ``` print 11.22.33 // 10 1.2.3 ``` ``` print 1.2.3 * 1.2.3 1.4.9 ``` ``` print 10.20.30 / 10.20.30 1.1.1 ``` ``` print 1.2.3 + 7 8.9.10 ``` ``` print 1.2.3 - 1 0.1.2 ``` ``` print random 10.20.30 8.18.12 ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< This section describes the standard math functions and operators used in REBOL. ''Contents'' * absolute * add * complement * divide * multiply * negate * random * remainder * subtract ''absolute'' The expressions: ``` absolute value abs value ``` return the absolute value of `value`. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[pair!|Datatypes: Pair!]] datatypes. ``` print absolute -10 10 ``` ``` print absolute -1.2 1.2 ``` ``` print absolute -$1.2 $1.20 ``` ``` print absolute -10:20 10:20 ``` ``` print absolute -10x-20 10x20 ``` ''add'' The expressions: ``` value1 + value2 add value1 value2 ``` return the result of adding `value1` to `value2`. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[tuple!|Datatypes: Tuple!]], [[pair!|Datatypes: Pair!]], [[date!|Datatypes: Date!]], [[char!|Datatypes: Char!]] datatypes. ``` print 1 + 2 3 ``` ``` print 1.2 + 3.4 4.6 ``` ``` print 1.2.3 + 3.4.5 4.6.8 ``` ``` print $1 + $2 $3.00 ``` ``` print 1:20 + 3:40 5:00 ``` ``` print 10x20 + 30x40 40x60 ``` ``` print #"A" + 10 K ``` ``` print add 1 2 3 ``` ''complement'' The expression: ``` complement value ``` returns the numeric complement (bitwise complement) of a `value`. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[tuple!|Datatypes: Tuple!]] datatypes. ``` print complement 10 -11 ``` ``` print complement 10.5 -11 ``` ``` print complement 100.100.100 155.155.155 ``` ''divide'' The expressions: ``` value1 / value2 divide value1 value2 ``` return the result of dividing `value1` by `value2`. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[tuple!|Datatypes: Tuple!]], [[pair!|Datatypes: Pair!]], [[char!|Datatypes: Char!]] datatypes. ``` print 10 / 2 5 ``` ``` print 1.2 / 3 0.4 ``` ``` print 11.22.33 / 10 1.2.3 ``` ``` print $12.34 / 2 $6.17 ``` ``` print 1:20 / 2 0:40 ``` ``` print 10x20 / 2 5x10 ``` ``` print divide 10 2 5 ``` ''multiply'' The expressions: ``` value1 * value2 multiply value1 value2 ``` return the result of multiplying `value1` by `value2`. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[tuple!|Datatypes: Tuple!]], [[pair!|Datatypes: Pair!]], [[char!|Datatypes: Char!]] datatypes. ``` print 10 * 2 20 ``` ``` print 1.2 * 3.4 4.08 ``` ``` print 1.2.3 * 3.4.5 3.8.15 ``` ``` print $10 * 2 $20.00 ``` ``` print 1:20 * 3 4:00 ``` ``` print 10x20 * 3 30x60 ``` ``` print multiply 10 2 20 ``` ''negate'' The expressions: ``` - value negate value ``` change the sign of the `value`. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[pair!|Datatypes: Pair!]], [[char!|Datatypes: Char!]] datatypes. ``` <A name=_Toc487519923>print - 10 -10 ``` ``` print - 1.2 -1.2 ``` ``` print - $10 -$10.00 ``` ``` print - 1:20 -1:20 ``` ``` print - 10x20 -10x-20 ``` ``` print negate 10 -10 ``` ''random'' The expression: ``` random value ``` returns a random value that is less than or equal to value given. Note that for integers[[ random|Functions: random]] begins at 1, not 0, and is inclusive of the value given. This allows random to be used directly with functions like [[pick|Functions: pick]]. When a decimal is used the result is a decimal datatype rounded to an integer. The `/seed` refinement restarts the random generator. Use the `/seed` refinement with random first it if you want unique random number generation. You can use the current date and time to make the seed more random: ``` random/seed now ``` Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[tuple!|Datatypes: Tuple!]], [[pair!|Datatypes: Pair!]], [[date!|Datatypes: Date!]], [[char!|Datatypes: Char!]], [[string!|Datatypes: String!]], [[block!|Datatypes: Block!]] datatypes. ``` print random 10 5 ``` ``` print random 10.5 2 ``` ``` print random 100.100.100 79.95.66 ``` ``` print random $100 $32.00 ``` ``` print random 10:30 6:37:33 ``` ``` print random 10x20 2x4 ``` ``` print random 30-Jun-2000 27-Dec-1171 ``` ''remainder'' The expressions: ``` value1 // value2 remainder value1 value2 ``` return the remainder of dividing `value1` by `value2`. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[tuple!|Datatypes: Tuple!]], [[pair!|Datatypes: Pair!]] datatypes. ``` print 11 // 2 1 ``` ``` print 11.22.33 // 10 1.2.3 ``` ``` print 11x22 // 2 1x0 ``` ``` print remainder 11 2 1 ``` ''subtract'' The expressions: ``` value1 - value2 subtract value1 value2 ``` return the result of subtracting `value2` from `value1`. Works with [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], [[money!|Datatypes: Money!]], [[time!|Datatypes: Time!]], [[tuple!|Datatypes: Tuple!]], [[pair!|Datatypes: Pair!]], [[date!|Datatypes: Date!]], [[char!|Datatypes: Char!]] datatypes. ``` print 2 - 1 1 ``` ``` print 3.4 - 1.2 2.2 ``` ``` print 3.4.5 - 1.2.3 2.2.2 ``` ``` print $2 - $1 $1.00 ``` ``` print 3:40 - 1:20 2:20 ``` ``` print 30x40 - 10x20 20x20 ``` ``` print #"Z" - 1 Y ``` ``` print subtract 2 1 1 ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The trigonometric functions deal in degrees. Use the `/radians` refinement with any of the trigonometric functions to operate in and return radians. ''Contents'' * arccosine * arcsine * arctangent * cosine * sine * tangent ''arccosine'' The expression: ``` arccosine value ``` returns the trigonometric arccosine of `value`. ''arcsine'' The expression: ``` arcsine value ``` returns the trigonometric arcsine of `value`. ''arctangent'' The expression: ``` arctangent value ``` returns the trigonometric arctangent of `value`. ''cosine'' The expression: ``` cosine value ``` returns the trigonometric cosine of `value`. ''sine ''The expression: ``` sine value ``` returns the trigonometric sine of `value`. ''tangent'' The expression: ``` tangent value ``` returns the trigonometric tangent of `value`.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< When math operations are performed between datatypes, normally the non-integer or non-decimal datatype is returned. When integers are combined with decimals, a decimal datatype is returned.
One of the primary REBOL principles is to keep simple things simple. With that in mind REBOL was designed so most programs do not require you to load external modules, libraries, or use include files. The most important features and functions are included by default. However, when programs get larger, or require more special types of features, it helps to divide the program into smaller pieces: modules. In REBOL a ''module is just a file or block that by default has its own global namespace''. Variables defined in a module, even at the top level, will not interfere with variables defined in the system or in other modules. They are isolated in their own special context (very similar to an object.) This section includes: * [[modules: loading modules|Concepts: Modules: Loading Modules]] - how to load existing modules from files or over the internet, how to specify version numbers and validate that the module is what you expect it to be. * [[modules: defining modules|Concepts: Modules: Defining Modules]] - how to define new modules, either as a file or as an embedded part of your program. * [[modules: special notes|Concepts: Modules: Special Notes]] - special notes about modules. <<< Released in A40 The module features discussed here were added in the R3-A40 release. You can try the examples using that version or greater. <<<
''Contents'' * [[Creating a module]] * [[Modules as files]] ** The specification header ** The body block * [[Making modules dynamically]] * [[Module locations]] * [[Module namespaces]] !!! ''Creating a module'' {{Creating a module}} !!! ''Modules as files'' {{Modules as files}} !!! ''Making modules dynamically'' {{Making modules dynamically}} !!! ''Module locations'' {{Module locations}} !!! ''Module namespaces'' {{Module namespaces}}
Contents * [[Summary of methods]] * [[Specifying modules in headers]] ** Types of module identifiers ** Searching for modules ** Example ** Specifying a module version ** Validating modules with a hash checksum * [[Importing modules directly]] ** Return value ** Useful refinements ** When to use IMPORT ** Doing modules * [[Explicit references into modules]] * [[Dynamic (embedded) modules]] !!! ''Summary of methods'' {{Summary of methods}} !!! ''Specifying modules in headers'' {{Specifying modules in headers}} !!! ''Importing modules directly'' {{Importing modules directly}} !!! ''Explicit references into modules'' {{Explicit references into modules}} !!! ''Dynamic (embedded) modules'' {{Dynamic (embedded) modules}}
<<< Editor note: This section is new or has has recently changed and is still under construction. <<< ''Bindings'' prior bindings are wiped so don't waste time on it do not try to prebind and avoid complicated bindings Isolated bindings for shared system functions How modules exported values are applied to the current context
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Objects group values into a common context. An object can include scalar values, series, functions, and other objects. Objects are useful in dealing with complex structures as they allow related data and code to be encapsulated and passed as a single value to functions.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Variables within objects are accessed with paths. The path consists of the object name followed by the name of the variable. For example, the following code accesses the variables in the example object: ``` example/var1 example/var2 ``` Here are examples using the bank-account object: ``` print luke/last-name Lakeswimmer ``` ``` print fred/balance $510.00 ``` Using a path, the variables of an object can also be modified: ``` fred/balance: $1000.00 print fred/balance $1000.00 ``` You can use the in function to access object variables by fetching their words from within their object context: ``` print in fred 'balance balance ``` The balance word returned has the object fred as its context. You can get the value it holds by using get: ``` print get in fred 'balance $1000.00 ``` The second argument to the [[in|Functions: in]] function is a literal word. This allows you to dynamically change words depending on what is needed: ``` words: [first-name last-name balance] foreach word words [print get in fred word] FredSmith $1000.00 ``` Each word in the block is used to obtain its value in the object. The [[in|Functions: in]] function can also be used to set object variables. ``` set in fred 'balance $20.00 print fred/balance $20.00 ``` If a word is not defined within an object, the [[in|Functions: in]] function returns [[none!|Datatypes: None!]] . This is useful for detecting when a variable exists within an object. ``` if get in fred 'bank [print fred/bank] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< When you use a parent object to make a new object, the parent object is cloned rather than inherited. This means that if the parent object is modified, it has no effect on the child object. As an example, the following code creates a bank account object, whose variables are blank: ``` bank-account: make object! [ first-name: last-name: account: balance: none ] ``` To use the new object, values can be provided to create an account for a customer: ``` luke: make bank-account [ first-name: "Luke" last-name: "Lakeswimmer" account: 89431 balance: $1204.52 ] ``` Since new accounts are made on a regular basis, it helps to use a function and some global variables to create them: ``` last-account: 89431 bank-bonus: $10.00 make-account: func [ "Returns a new account object" f-name [string!] "First name" l-name [string!] "Last name" start-balance [money!] "Starting balance" ][ last-account: last-account + 1 make bank-account [ first-name: f-name last-name: l-name account: last-account balance: start-balance + bank-bonus ] ] ``` Now a new account object for `Fred` would only require: ``` fred: make-account "Fred" "Smith" $500.00 ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< An object provides a good way to encapsulate a group of variables that should not appear at the global level. When function variables are defined as globals, they can unintentionally be modified by other functions. The solution to this problem of global variables is to wrap an object around both the variables and the function. When that is done, the function can still access the variables, but the variables cannot be accessed globally. For example: ``` Bank: make object! [ last-account: 89431 bank-bonus: $10.00 set 'make-account func [ "Returns a new account object" f-name [string!] "First name" l-name [string!] "Last name" start-balance [money!] "Starting balance" ][ last-account: last-account + 1 make bank-account [ first-name: f-name last-name: l-name account: last-account balance: start-balance + bank-bonus ] ] ] ``` In this example, the variables are safe from accidental modification. Notice that the `make-account` function was set to a variable using the [[set|Functions: set]] function, rather than using a variable definition. This was done to make it a global function. The function can be used in the same way as functions set with a variable definition, but does not require an object path: ``` bob: make-account "Bob" "Baker" $4000 ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< New objects are created with the [[make|Functions: make]] function. The [[make|Functions: make]] function function requires two arguments and returns a new object. The format of the [[make|Functions: make]] function function is: ``` new-object: make parent-object new-values ``` The first argument, `parent-object` , is the parent object from which the new object is made. If no parent object is available, as when defining an initial object, use the [[object!|Datatypes: Object!]] datatype, as shown below: ``` new-object: make object! new-values ``` The second argument, `new-values` , is a block that defines additional variables and initial values for the new object. Each variable that is defined within the block is an instance variable of the object. For example, if the block contained two variable definitions, then they would be variables of the object: ``` example: make object! [ var1: 10 var2: 20 ] ``` The example object has two variables that hold two integers. The block is evaluated, so it can include any type of expression to compute the values of the variables: ``` example: make object! [ var1: 10 var2: var1 + 10 var3: now/time ] ``` Once an object has been made, it can serve as a prototype for creating new objects: ``` example2: make example [] ``` The above example makes a second instance of the example object. The new object is a clone of the first object. New values for the second object are set in the block: ``` example2: make example [ var1: 30 var2: var1 + 10 ] ``` In the example above, the `example2` object has different values than the original example object for two of its variables. The `example2` object can also extend the object definition by adding new variables to it: ``` example2: make example [ var4: now/date var5: "example" ] ``` The result is an object that has five variables: Three that came from the original object, example , and two new ones. The process of extending the definition of an object can be repeated any number of times. You can also create an object that contains variables that are initialized to some common value. This can be done using a cascaded set of word definitions: ``` example3: make object! [ var1: var2: var3: var4: none ] ``` In the example above, the four variables are set to none! within the new object. To summarize, the process of creating an object involves these steps: * Use [[make|Functions: make]] to create a new object based on a parent object or the [[object!|Datatypes: Object!]] datatype. * Add any new variables that are defined in the block to the new object. * Evaluate the block, which causes the variables defined in the block to be set to the values in the new object. * The new object is returned as a result.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< An object can contain variables that refer to functions that are defined within the context of the object. This is useful because the functions are encapsulated within the context of the object, and can access the other variables of the object directly, without a need for a path. As a simple example, the example object can include functions for computing new values within the object: ``` example: make object! [ var1: 10 var2: var1 + 10 var3: now/time set-time: does [var3: now/time] calculate: func [value] [ var1: value var2: value + 10 ] ] ``` Notice in the example that the functions are able to refer to the variables of the object directly, rather than as paths. That is possible because the functions are defined within the same context as the variables they access. To set a new time, use: ``` example/set-time ``` This example evaluates the function that sets `var3` to the current time. To calculate new values for `var1` and `var2` , use: ``` example/calculate 100 print example/var2 110 ``` In the case of the b`ank-account` object, the functions for `deposit` and `withdraw` can be added to the current definition: ``` bank-account: make bank-account [ deposit: func [amount [money!]] [ balance: balance + amount ] withdraw: func [amount [money!]] [ either negative? balance [ print ["Denied. Account overdrawn by" absolute balance] ][balance: balance - amount] ] ] ``` In the example, notice that the functions are able to refer to the `balance` directly within the object. That's because the functions are part of the object's context. Now if a new account is made, it will contain functions for depositing and withdrawing money. For example: ``` lily: make-account "Lily" "Lakeswimmer" $1000 print lily/balance $1010.00 ``` ``` lily/deposit $100 print lily/balance $1110.00 ``` ``` lily/withdraw $2000 print lily/balance -$890.00 ``` ``` lily/withdraw $2.10 Denied. Account overdrawn by $890.00 ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Any object can serve as a prototype for making new objects. For instance, the `lily` account object previously defined can be used to make new objects with a line such as: ``` maya: make lily [] ``` This makes an instance of an object. The object is a copy of the customer object and has identical values: ``` print lily/balance -$890.00 ``` ``` print maya/balance -$890.00 ``` You can modify the new object while making it by providing the new values within the definition block: ``` maya: make lily [ first-name: "Maya" balance: $10000 ] print maya/balance $10000.00 ``` ``` maya/deposit $500 print maya/balance $10500.00 ``` ``` print maya/first-name Maya ``` The `lily` object serves as a prototype for creating the new object. Any words that are not redefined for the new object continue to have the values of the old object: ``` print maya/last-name Lakeswimmer ``` New words are added to the object in a similar way: ``` maya: make lily [ email: maya@example.com birthdate: 4-July-1977 ] ```
''Contents'' * Concept * Example * Special Notes ** Nested Objects ** Modules ** Non-Object Contexts ''Concept'' ''Within an [[object!|Datatypes: Object!]] or [[module!|Datatypes: Module!]] the word `self` is pre-defined to refer to that context''. The self word makes it possible to refer to the object without knowing its name. You can use it as you would any object reference, passing it as an argument to functions, using it in paths, or returning it as the result of a function. ''Example'' In the following example, the `when?` function will show the date field, and the `dump` function will display the entire contents of the object. ``` example: make object! [ name: "test" date: now dump: does [probe self] when?: does [print self/date] ] example/when 27-Apr-2010/14:45:52-7:00 ``` ``` example/dump make object! [ name: "test" date: 27-Apr-2010/14:45:52-7:00 ``` ''Special Notes'' !!!!! ''Nested Objects'' When using `self` within an object within an object, keep in mind that `self` normally refers to the innermost object. In this code, `self` refers to `obj2` : ``` obj1: make object! [ name: "test" obj2: make object! [ name: "idea" who?: does [probe self/name] ] ] obj1/obj2/who? idea ``` But, what if you need to refer to the outer object? To do so, you will need to define another field in the outer object to make the reference possible. ``` obj1: make object! [ name: "test" myself: self obj2: make object! [ name: "idea" who?: does [probe myself/name] ] ] obj1/obj2/who? test ``` !!!!! ''Modules'' The `self` word is also used in modules exactly in the same way that it's used in object. In fact, in R3 because your code is always running within a module, when used within the standard context of your code, it refers to your global context. For example, start R3 and type: ``` probe words-of self [system probe words-of] ``` What you're seeing here is a list of words bound to your global (user) context. As you type or run more code, you'll see those words as well. The module context automatically expands as needed. This can be useful if you need to explicitly refer to a global variable that has the same name as a local variable. Fortunately, this situation is rare, but this is a good way to handle it. Example: ``` cp: func [copy] [self/copy copy] a: cp "test" ``` Here, `copy` is used as an argument name, so to refer to the [[copy|Functions: copy]] function, we use the `self` word, which is the user module (global environment) for the program. !!!!! ''Non-Object Contexts'' Contexts are environments where words are bound to values. Objects and modules are contexts, but so are functions and closures. However, it should be noted that ''R3 does not predefine the `self` word within these other contexts''. This makes it easier for object-relative functions to refer to the `self` of their related objects (not to themselves as functions.) In addition, when you use loop functions like [[repeat|Functions: repeat]], [[foreach|Functions: foreach]], [[for|Functions: for]], and others, a special loop-context is created for the variables of the loop. The `self` word is not predefined here either because such loops may often be used within object-based functions, where access to the object is needed. <<< Changed in A98 The A98 release is an attempt to formalize and finalize the definition of the `self` word. Prior releases may differ. <<<
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< As with many other REBOL datatypes, you can access the components of objects in a manner that allows you to write useful tools and utilities for creating, monitoring, and debugging them. The [[first|Functions: first]] and second functions allow you to access the components of an object. The [[first|Functions: first]] function returns the words defined for an object. The [[second|Functions: second]] function returns the values that the objects are set to. The following diagram shows the relationship between the return values of `first` and `second`: The advantage to using [[first|Functions: first]] is that it allows you to obtain a list of the words for the function without knowing anything else about the function: ``` probe first luke [self first-name last-name account balance] ``` In the above example, notice that the list contains the word, `self` , which is a reference to the object itself. You can exclude `self` when getting an object's word list by using `next`: ``` probe next first luke [first-name last-name account balance] ``` Now you have a way to write a function that can probe the contents of an object: ``` probe-object: func [object][ foreach word next first object [ print rejoin [word ":" tab get in object word] ] ] probe-object fred first-name: Luke last-name: Lakeswimmer account: 89431 balance: $1204.52 ``` When accessing objects in this fashion, care should be taken to avoid infinite loops. For instance, if you attempt to probe certain objects that contain references to themselves, your code may begin an endless loop. This is the reason why you cannot probe the `system` object directly. The `system` object contains many references to itself.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Overview'' Parsing splits a sequence of characters or values into smaller parts. It can be used for recognizing characters or values that occur in a specific order. In addition to providing a powerful, readable, and maintainable approach to regular expression pattern matching, parsing enables you to create your own custom languages for specific purposes. The parse function has the general form: ``` parse series rules ``` The `series` argument is the input that is parsed and can be a string or a block. If the argument is a string, it is parsed by character. If the argument is a block, it is parsed by value. The `rules` argument specifies how the `series` argument is parsed. The `rules` argument can be a string for simple types of parsing or a block for sophisticated parsing. The parse function also accepts two refinements: `/all` and `/case`. The `/all` refinement parses all the characters within a string, including all delimiters, such as space, tab, newline, comma, and semicolon. The /case refinement parses a string based on case. When `/case` is not specified, upper and lower cases are treated the same.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The [[parse|Functions: parse]] function normally ignores all intervening whitespace between patterns that it scans. For instance, the rule: ``` ["a" "b" "c"] ``` returns strings that match: ``` abc a bc ab c a b c a b c ``` and other similarly spaced combinations. To enforce a specific spacing convention, use parse with the `/all` refinement. In the preceeding example, this refinement causes parse to only match the first case (abc). ``` parse/all "abc" ["a" "b" "c"] ``` Specifying the `/` all refinement forces every character in the input stream to be dealt with, including the default delimiters, such as space, tab, newline. To handle spaces in your rules, create a character set that specifies the valid space characters: ``` spacer: charset reduce [tab newline #" "] ``` If you want a single space character between each letter write: ``` ["a" spacer "b" spacer "c"] ``` To allow multiple space characters, write: ``` spaces: [some spacer] ["a" spaces "b" spaces "c"] ``` For more sophisticated grammars, create a character set that lets you scan a string up to a space character. ``` non-space: complement spacer to-space: [some non-space | end] words: make block! 20 parse/all text [ some [copy word to-space (append words word) spacer] ] ``` The preceding example builds a block of all of its words. The complement function inverts the character set. Now it contains everything except the spacing characters you defined earlier. The `non-space` character set contains all characters except space characters. The `to-space` rule accepts one or more characters up to a space character or the end of the input stream. The main rule expects to begin with a word, copy that word up to a space, then skip the space character and begin the next word.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Normally, you parse a string to produce some result. You want to do more than just verify that the string is valid, you want to do something as it is parsed. For instance, you may want to pick out substrings from various parts of the string, create blocks of related values, or compute a value. ''Contents'' * [[Return Value]] * [[Expressions in Rules]] * [[Copying the Input]] * [[Marking the Input]] * [[Modifying the String]] * [[Using Objects]] * [[Debugging]] !!! ''Return Value'' {{Return Value}} !!! ''Expressions in Rules'' {{Expressions in Rules}} !!! ''Copying the Input'' {{Copying the Input}} !!! ''Marking the Input'' {{Marking the Input}} !!! ''Modifying the String'' {{Modifying the String}} !!! ''Using Objects'' {{Using Objects}} !!! ''Debugging'' {{Debugging}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The parse function accepts grammar rules that are written in a dialect of REBOL. Dialects are sub-languages of REBOL that use the same lexical form for all datatypes, but allow a different ordering of the values within a block. Within this dialect the grammar and vocabulary of REBOL is altered to make it similar in structure to the well known BNF (Backus-Naur Form) which is commonly used to specify language grammars, network protocols, header formats, etc. To define rules, use a block to specify the sequence of the inputs. For instance, if you want to parse a string and return the characters "the phone", you can use a rule: ``` parse string ["the phone"] ``` To allow any number of spaces or no spaces between the words, write the rule like this: ``` parse string ["the" "phone"] ``` You can indicate alternate rules with a vertical bar `|`. For example: ``` ["the" "phone" | "a" "radio"] the phone a radio ``` A rule can contain blocks that are treated as sub-rules. The following line: ``` [ ["a" | "the"] ["phone" | "radio"] ] a phone a radio the phone the radio ``` For increased readability, write the sub-rules as a separate block and give them a name to help indicate their purpose: ``` article: ["a" | "the"] device: ["phone" | "radio"] parse string [article device] ``` In addition to matching a single instance of a string, you can provide a count or a range that repeats the match. The following example provides a count: ``` [3 "a" 2 "b"] aaabb ``` The next example provides a range: ``` [1 3 "a" "b"] ab aab aaab ``` The starting point of a range can be zero, meaning that it is optional. ``` [0 3 "a" "b"] b ab aab aaab ``` Use some to specify that one or more characters are matched. Use any to specify that zero or more characters are matched. For example, some used in the following line: ``` [some "a" "b"] ab aab aaab aaaab ``` The next example uses any: ``` [any "a" "b"] b ab aab aaab aaaab ``` The words some and any can also be used on blocks. For example: ``` [some ["a" | "b"]] ``` accepts strings that contain any combination of the characters `a` and `b`. Another way to express that a character is optional is to provide an alternate choice of none: ``` ["a" | "b" | none] ``` This example accepts strings that contain `a` or `b` or [[none!|Datatypes: None!]]. The[[none!|Datatypes: None!]] is useful for specifying optional patterns or for catching error cases when no pattern matches.
Pending Revision This document was written for R2 and has yet to be revised for R3. When parsing strings, these datatypes and words can be used to match characters in the input string: |''Match Type'' |''Description''|h |`'"abc"` |match the entire string| |`'#"c" `|match a single character| |`'tag` |match a tag string| |`'end` |match to the end of the input| |`'(bitset)` |match any specified char in the set| To use all of these words (except bitset, which is explained below) in a single rule, use: ``` [<B> ["excellent" | "incredible"] #"!" </B> end] ``` This example parses the input strings: ``` <B>excellent!</B> <B>incredible!</B> ``` The `end` specifies that nothing follows in the input stream. The entire input has been parsed. It is optional depending on whether the parse function's return value is to be checked. Refer to the `[bad-link:concepts/evaluation.txt]` section below for more information. The [[bitset!|Datatypes: Bitset!]] datatype deserves more explanation. Bitsets are used to specify collections of characters in an efficient manner. The charset function enables you to specify individual characters or ranges of characters. For example, the line: ``` digit: charset "0123456789" ``` defines a character set that contains digits. This allows rules like: ``` [3 digit "-" 3 digit "-" 4 digit] 707-467-8000 ``` To accept any number of digits, it is common to write the rule: ``` digits: [some digit] ``` A character set can also specify ranges of characters. For instance, the digit character set could have be written as: ``` digit: charset [#"0" - #"9"] ``` Alternatively, you can combine specific characters and ranges of characters: ``` the-set: charset ["+-." #"0" - #"9"] ``` To expand on this, here is the alphanumeric set of characters: ``` alphanum: charset [#"0" - #"9" #"A" - #"Z" #"a" - #"z"] ``` Character sets can also be modified with the insert and remove functions, or combinations of sets can be created with the union and intersect functions. This line copies the digit character set and adds a dot to it: ``` digit-dot: insert copy digit "." ``` The following lines define useful character sets for parsing: ``` digit: charset [#"0" - #"9"] alpha: charset [#"A" - #"Z" #"a" - #"z"] alphanum: union alpha digit ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Blocks are parsed similar to strings. A set of rules specify the order of expected values. However, unlike the parsing of strings, the parsing of blocks is not concerned with characters or delimiters. Parsing of blocks is done at the value level, making the grammar rules easier to specify and operation many times faster. Block parsing is the easiest way to create REBOL ''dialects''. Dialects are sub-languages of REBOL that use the same lexical form for all datatypes but allow a different ordering of the values within a block. The values do not need to conform to the normal order required by REBOL function arguments. Dialects are able to provide greater expressive power for specific domains of use. For instance, the parser rules themselves are specified as a dialect. ''Contents'' * [[Matching Words]] * [[Matching Datatypes]] * [[Characters Not Allowed]] * [[Dialect Examples]] * [[Parsing Sub-blocks]] !!! ''Matching Words'' {{Matching Words}} !!! ''Matching Datatypes'' {{Matching Datatypes}} !!! ''Characters Not Allowed'' {{Characters Not Allowed}} !!! ''Dialect Examples'' {{Dialect Examples}} !!! ''Parsing Sub-blocks'' {{Parsing Sub-blocks}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Here is an example of rule set that parses mathematical expressions and gives a precedence (a priority) to the math operators used: ``` expr: [term ["+" | "-"] expr | term] term: [factor ["*" | "/"] term | factor] factor: [primary "**" factor | primary] primary: [some digit | "(" expr ")"] digit: charset "0123456789" ``` Now we can parse many types of math expressions. The following examples return `true`, indicating that the expressions were valid: ``` probe parse "1 + 2 * ( 3 - 2 ) / 4" expr true ``` ``` probe parse "4/5+3**2-(5*6+1)" expr true ``` Notice in the examples that some of the rules refer to themselves. For instance, the `expr` rule includes `expr`. This is a useful technique for defining repeating sequences and combinations. The rule is recursive --it refers to itself. When using recursive rules, care is required to prevent endless recursion. For instance: ``` expr: [expr ["+" | "-"] term] ``` creates an infinite loop because the first thing `expr` does is use `expr` again.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< A simple form of parse is for splitting strings: ``` parse string none ``` The [[parse|Functions: parse]] function splits the input argument, [[string!|Datatypes: String!]], into a block of multiple strings, breaking each string wherever it encounters a delimiter, such as a space, tab, newline, comma, or semicolon. The [[none!|Datatypes: None!]] argument indicates that no other delimiters other than these. For example: ``` probe parse "The trip will take 21 days" none ["The" "trip" "will" "take" "21" "days"] ``` Similarly, ``` probe parse "here there,everywhere; ok" none ["here" "there" "everywhere" "ok"] ``` In the example above, notice that the commas and semicolons have been removed from the resulting strings. You can specify your own delimiters in the second argument to parse. For example, the following code parses a telephone number with dash `-` delimiters: ``` probe parse "707-467-8000" "-" ["707" "467" "8000"] ``` The next example uses equal `=` and double quote `"` as the delimiters: ``` probe parse <IMG SRC="test.gif" WIDTH="123"> {="} ["IMG" "SRC" "test.gif" "WIDTH" "123"] ``` The next example parses a string based on commas only; any other delimiters are ignored. Consequently, the spaces within the strings are not removed: Normally when you parse strings, any whitespace (space, tab, lines) are automatically processed as delimiters. To avoid that action, you can use the /any refinement. Compare these two examples: ``` parse "Test This" "" ["Test" "This"] ``` ``` parse/all "Test This" "" ["Test This"] ``` In the second, you can see that the space was not treated as a delimiter. Here is another example: ``` probe parse/all "Harry, 1011 Main St., Ukiah" "," ["Harry" " 1011 Main St." " Ukiah"] ``` You can also parse strings that contain null characters as separators (such as certain types of data files): ``` parse/all nulled-string "^(null)" ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The [[skip|Functions: skip]], [[to|Functions: to]], and `thru` words allow input to be skipped. Use [[skip|Functions: skip]] to skip a single character, or use it with a [[repeat|Functions: repeat]] to skip over multiple characters: ``` ["a" skip "b"] ["a" 10 skip "b"] ["a" 1 10 skip] ``` To skip until a specific character is found, use `to`: ``` ["a" to "b"] ``` The previous example starts parsing at `a` and ends at `b` but does not include `b`. To include the ending character, use `thru`: ``` ["a" thru "b"] ``` The previous example starts parsing at `a`, ends at `b`, and includes `b`. The following rule finds the title of an HTML page and prints it: ``` page: read http://www.rebol.com/ parse page [thru <title> copy text to </title>] print text REBOL Technologies ``` The first `thru` finds the title tag and goes immediately past it. Next, the input string is copied into a variable called `text` until the ending tag is found (but it doesn't go past it, or the text would include the tag).
''Contents'' * [[Input datatypes]] * [[General parse rules]] * [[List of keywords]] * [[Words and paths as variables]] * [[Match rules]] * [[Alternate rules]] * [[Skipping input]] * [[Optional or repeated rules]] * [[Storing input]] * [[Modifying input]] * [[Input position must change]] * [[Evaluating expressions (productions)]] !!! ''Input datatypes'' {{Input datatypes}} !!! ''General parse rules'' {{General parse rules}} !!! ''List of keywords'' {{List of keywords}} !!! ''Words and paths as variables'' {{Words and paths as variables}} !!! ''Match rules'' {{Match rules}} !!! ''Alternate rules'' {{Alternate rules}} !!! ''Skipping input'' {{Skipping input}} !!! ''Optional or repeated rules'' {{Optional or repeated rules}} !!! ''Storing input'' {{Storing input}} !!! ''Modifying input'' {{Modifying input}} !!! ''Input position must change'' {{Input position must change}} !!! ''Evaluating expressions (productions)'' {{Evaluating expressions (productions)}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Overview'' Ports access external series such as files, networks, consoles, events, databases, data encoders, and data decoders. Port data is processed using the standard REBOL series functions as described in the [[series|Concepts: Series]] Chapter. Ports are used for both input and output. The type of data a port handles depends on how the port is opened. Three types of data are possible: |''String'' |a series of bytes, converts line breaks (default)| |''Binary'' |a series of bytes, no conversion of the data| |''Block'' |a series of REBOL values| A port can be opened in one of two buffering modes: |''Buffered'' |all of the data is held in memory (default)| |''Direct'' |data is not held in memory| In addition, a port can be opened with: |''Wait'' |port will wait for data (default)| |''No-wait'' |port will not wait for data|
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Access to a port is terminated with the [[close|Functions: close]] function. All buffered data that has not been saved will be written to the target file. The example below will close a port opened earlier: ``` close fp ``` If you attempt to close a port that is not open, an error will occur. A port that is closed can be reopened again with the [[open|Functions: open]] function: ``` open fp ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Directory ports allow you to open direct access to file directories. Within the system, this is how most other directory functions are created. When you open a directory, you gain direct access to the directory as a block of filenames: ``` mydir: open %intro/ forall mydir [print first mydir] CVS/ history.t intro.t overview.t quick.t ``` ``` close mydir ``` You can advance to a specific position within a directory series and remove a file with code such as: ``` dir: open %. remove next dir close dir ``` This deletes the second file in the current directory. Similarly, ``` remove at dir 5 ``` would delete the fifth file in the directory, and: ``` clear dir ``` would delete all of the files in the directory. To delete all files that contain with the word "junk", you can write: ``` dir: open %intro/ while [not tail? dir] [ either find first dir "junk" [remove dir][ dir: next dir ] ] close dir ``` The changes made to a directory are made when the directory is closed or when it is updated. To force the action to occur immediately use a line such as: ``` update dir ``` The method of directory access can also be used for changing the names of files. After the [[open|Functions: open]], the line: ``` change at dir 3 %newname.txt ``` will rename the third file in the directory. Similarly, the names of any of the files in the directory can be changed. Here is an example that renames all of the files in a directory by adding the word REBOL to their names: ``` dir: open %intro/ forall dir [insert first dir "REBOL"] close dir ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< When files are created by REBOL, default access permissions are set. On Windows and Macintosh systems files are created with full access privileges. On UNIX systems files are created with the permissions set to the current umask setting. When using open or write to access a file the `/allow` refinement is used to set file access permissions. The `/allow` refinement takes a block as an argument. This block can consist of any or all of the three words read, write and execute. <<< Operating System Restrictions The `/allow` refinement will only set permissions on operating systems supporting the specified permission setting. If the operating system does not support a permission setting used, the setting will be ignored. For instance, files on UNIX systems may be set as executable (' execute ), but the Windows and Macintosh operating systems don't support this. When dealing with UNIX systems, permissions set `using /allow` will only set the user permissions. `Using / allow` will cause all access permissions to be removed for users and others. <<< To make a file read only, use `open/allow`, or `write/allow` with a read block. ``` write/allow %file.txt [read] ``` To make a file readable and executable: ``` open/allow %file.txt [read execute] ``` You can set similar permissions for write access: ``` write/allow %file.txt [read write] ``` To prevent any access to a file (for operating systems where this would make a difference) provide an empty permissions block: ``` write/allow %file.txt [] ``` To permit full access: ``` write/allow %file [read write execute] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''The Open Function'' The [[open|Functions: open]] function initializes access to a port according to specified parameters. The function can be supplied with a filename, a URL, or an object. In addition, there are several refinements that will affect the open operation or the access to the port's data. The simplest method of using open is to provide it with a filename or URL as its argument. In the example below, a file port is opened: ``` fp: open %file.txt ``` The fp variable refers to the port. If the port did not open, an error will occur. If necessary, the error can be caught with the try function. By default the file is opened as buffered. This means that the file is accessed and modified in memory and changes to the file are not written out until the port is closed or updated. For files, the open function will automatically create the file if it does not already exist. ``` close open %somefile.txt if exists? %somefile.txt [print "somefile exists"] somefile exists ``` The `/new` refinement can be used to overwrite an existing file. ``` write %somefile.txt "text in some file" print read %somefile.txt text in some file ``` ``` close insert open/new %somefile.txt "new data" print read %somefile.txt new data ``` Once a port is open, the series operations such as copy, insert, remove, clear, first, next, and [[length?|Functions: length?]] can be used to access and change the contents the port. ''Open Refinements'' The [[open|Functions: open]] function accepts a number of refinements that can be used to modify its operation: |`/binary` |port data is binary| |`/string` |port data is text, translate all line terminators| |`/with` |specify an alternate line termination| |`/lines` |handle data a line at a time or as a block of lines| |`/direct` |do not buffer the port| |`/new` |create or recreate the target of the port| |`/read` |open for read only operation| |`/write` |open for write only operation| |`/no-wait` |do not wait for data| |`/skip` |skip part of the data| |`/allow` |specify protection attributes of files| |`/custom` |allow special refinements|
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Contents'' * [[Line Mode]] * [[Read and Write Only]] * [[Direct Port Access]] * [[Skipping Data]] !!! ''Line Mode'' {{Line Mode}} !!! ''Read and Write Only'' {{Read and Write Only}} !!! ''Direct Port Access'' {{Direct Port Access}} !!! ''Skipping Data'' {{Skipping Data}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The series [[copy|Functions: copy]] function is used to read data from an open port: ``` print copy fp I wanted the gold, and I sought it,I scrabbled and mucked like a slave.... ``` This function will wait for the port data. If you don't want to wait for the data, open the port with the `/no-wait` refinement. To read only a portion of the port data, use `copy/part`: ``` print copy/part fp 35 I wanted the gold, and I sought it, ``` Note that the second argument to copy can be a length or a position within the port. You can use the series [[find|Functions: find]] and [[copy|Functions: copy]] functions to read just part of the port's data: ``` a: find fp "famine" print copy/part a find a newline famine or scurvy -- I fought it; ``` The first, next, and other positional series functions can also be used on the port: ``` print first fp I ``` ``` print first next next fp w ``` The [[copy|Functions: copy]] function will return [[none!|Datatypes: None!]] when all data have been read from a port. When running in `/no-wait` mode, the [[copy|Functions: copy]] function will return an empty string if no data is available for the port. ``` tp: open/direct/binary/no-wait tcp://system:8000 content: make binary! 1000 while [wait tp data: copy tp] [append content data] close tp ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The [[update|Functions: update]] function forces a port to update its status with respect to the external device. For example, when writing a buffered file, the update function can be used to force the data buffer out to the file. When reading, the [[update|Functions: update]] function can be used to be certain that any pending data has been read into memory. ``` update fp ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The [[wait|Functions: wait]] function is essential to programs that need to handle asynchronous data transfers. With [[wait|Functions: wait]], you can wait for data on one or more ports, or for a timeout to occur. The [[wait|Functions: wait]] function will accept a single port: ``` wait port ``` or, an entire block of ports can be provided: ``` wait [port1 port2 port3] ``` In addition, a timeout value can be provided as a number of seconds or as a time value: ``` wait [port1 port2 10] wait [port1 port2 0:00:05] ``` The first example will time out in ten seconds. The second example will timeout in five seconds. The [[wait|Functions: wait]] function will return the port that is ready or [[none!|Datatypes: None!]] if the timeout occurred. ``` ready: wait [port1 port2 10] if ready [data: copy ready] ``` The above example will read data from the first ready port if a timeout did not occur. To obtain a block of all ports that are ready, use the `/all` refinement. ``` ready: wait/all [port1 port2 10] if ready [ foreach port ready [ append data copy port ] ] ``` This example would append data from all ready ports into a single series. You can also use the `[bad-link:functions/dispatch.txt]` function to evaluate a block or function based on the results of a [[wait|Functions: wait]] on multiple ports. ``` dispatch [ port1 [print "port1 awake"] port2 [print "port2 awake"] 10 [print "timeout!"] ] ``` <<< Use `/No-wait` and `/Direct` To use wait with most ports, you will need to specify the `/no-wait` and `/direct` refinements as part of the open. This indicates that the normal data access functions should not block and that data is not buffered. <<< ``` port1: open/no-wait/direct tcp://system:8000 ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The [[insert|Functions: insert]] function is used to write to a port. ``` insert fp "I was a fool to seek it." ``` If the port is buffered, the change will occur externally when the port is closed or updated (with the [[update|Functions: update]] function). If the port is opened with `/direct`, then the change will occur immediately. All of the insert refinements can be used on the port. For example, to write 20 spaces into a port: ``` insert/dup fp " " 20 ``` You can also use the [[remove|Functions: remove]], [[clear|Functions: clear]], [[change|Functions: change]], [[append|Functions: append]], [[replace|Functions: replace]], and other series modifying functions on the port. For example, to remove a single character or a number of characters: ``` remove fp remove/part fp 20 ``` and to remove all remaining characters, write: ``` clear fp ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Overview'' REBOL includes several of the primary Internet service protocols built-in. These protocols are easy to use within your scripts; they require no extra libraries or include files, and many useful operations can be done with only a single line of source code. The protocols listed in `[bad-link:concepts/network.txt]` Protocols are supported: |[[DNS]] |Domain Name Service: translates computer names into addresses and addresses into names.| |[[Finger]] |Obtains information about a user from their profile.| |[[Whois]] |Obtains information about domain registration.| |[[Daytime]] |Network Time Protocol. Gets the time from a server.| |[[HTTP]] |Hypertext Transfer Protocol. Used for the Web.| |[[SMTP]] |Simple Mail Transfer Protocol. Used for sending email.| |[[POP]] |Post Office Protocol. Used for fetching email.| |[[FTP]] |File Transfer Protocol. Exchanges files with a server.| |[[NNTP]] |Network News Transfer Protocol. Posts or reads Usenet news.| |[[TCP]] |Transmission Control Protocol. Basic Internet protocol.| |''UDP'' |[[User Datagram Protocol|https://en.wikipedia.org/wiki/User_Datagram_Protocol]]. Packet-based protocol.| In addition, you can create handlers for other Internet protocols or make your own custom protocols.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< We use the word script to refer to code and data in general. A script can be a program (evaluated code) or data. So, script can refer to: * sources stored as REBOL files * sources embedded in other types of files (like web pages) * sources passed in messages between systems * fragments of source text, such as examples in a document This section covers: * [[Scripts: File suffix|Concepts: Scripts: File Suffix]] that are used * [[Scripts: Structure|Concepts: Scripts: Structure]] of a script file * [[Scripts: Headers|Concepts: Scripts: Headers]] header at top of file * [[Scripts: Script arguments|Concepts: Scripts: Script Arguments]] arguments to scripts * [[Scripts: Program options|Concepts: Scripts: Program Options]] special options * [[Scripts: Running scripts|Concepts: Scripts: Running Scripts]] from inside and out * [[Scripts: Loading scripts|Concepts: Scripts: Loading Scripts]] for data and code * [[Scripts: Saving scripts|Concepts: Scripts: Saving Scripts]] fast data storage * [[Scripts: Storing data|Concepts: Scripts: Storing Data]] * [[Scripts: Comments|Concepts: Scripts: Comments]] * [[Scripts: Script cleanup|Concepts: Scripts: Script Cleanup]] * [[Scripts: Style guide|Concepts: Scripts: Style Guide]] * [[Scripts: Embedding scripts|Concepts: Scripts: Embedding Scripts]] within other files
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Commenting is useful for clarifying the purpose of sections of a script. ''Contents'' * [[Types of comments]] * [[Lexical comments]] * [[Embedded comments]] !!! ''Types of comments'' {{Types of comments}} !!! ''Lexical comments'' {{Lexical comments}} !!! ''Embedded comments'' {{Embedded comments}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The REBOL header makes it possible for you to embed a REBOL script within other text, such as a web page, and REBOL is still able to find and evaluate it. ''Contents'' * [[Text before header]] * [[As a Unix shell command]] * [[Text before and after]] !!! ''Text before header'' {{Text before header}} !!! ''As a Unix shell command'' {{As a Unix shell command}} !!! ''Text before and after'' {{Text before and after}}
Pending Revision This document was written for R2 and has yet to be revised for R3. !!! ''Contents'' * [[The convention]] * [[R3 convention (pending)]] * [[File associations]] * [[As a MIME type]] !!! ''The convention'' {{The convention}} !!! ''R3 convention (pending)'' {{R3 convention (pending)}} !!! ''File associations'' {{File associations}} !!! ''As a MIME type'' {{As a MIME type}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Directly preceding the script body, every script must have a header that identifies its purpose and other script attributes. A header can contain the script name, author, date, version, file name, and additional information. REBOL data files that are not intended for direct evaluation do not require a header. Headers are useful for several reasons. * They identify a script as being valid source text for the REBOL interpreter. * The interpreter uses the header to print out the script's title and determines what resources and versions it needs before evaluating the script. * Headers provide a standard way to communicate the title, purpose, author, and other details of scripts. You can often determine from a script's header if a script interests you. * Script archives and web sites use headers for generating script directories, categories, and cross references. * Some text editors access and update a script's header to keep track of information such as the author, date, version, and history. The general form of a script header is: ``` REBOL [block] ``` For the interpreter to recognize the header, the block must immediately follow the word REBOL. Only white space (spaces, tabs, and lines) is permitted between the word REBOL and the block. The block that follows the REBOL word is an object definition that describes the script. The preferred minimal header is: ``` REBOL [ Title: "Scan Web Sites" Date: 2-Feb-2000 File: %webscan.r Author: "Jane Doer" Version: 1.2.3 ] ``` When a script is loaded, the header block is evaluated and its words are set to their defined values. These values are used by the interpreter and can also be used by the script itself. Note that words defined as a single value can also be defined as multiple values by providing them in a block: ``` REBOL [ Title: "Scan Web Sites" Date: 12-Nov-1997 Author: ["Ema User" "Wasa Writer"] ] ``` Headers can be more complex, providing information about the author, copyright, formatting, version requirements, revision history, and more. Because the block is used to construct the header object, it can also be extended with new information. This means that a script can extend the header as needed, but it should be done with care to avoid ambiguous or redundant information. A full header might look something like this: ``` REBOL [ Title: "Full REBOL Header Example" Date: 8-Sep-1999 Name: 'Full-Header ; For window title bar Version: 1.1.1 File: %headfull.r Home: http://www.rebol.com/rebex/ Author: "Carl Sassenrath" Owner: "REBOL Headquarters" Rights: "Copyright (C) Carl Sassenrath 1999" Needs: [2.0 ODBC] Tabs: 4 Purpose: { The purpose or general reason for the program should go here. } Note: { An important comment or notes about the program can go here. } History: [ 0.1.0 [5-Sep-1999 "Created this example" "Carl"] 0.1.1 [8-Sep-1999 {Moved the header up, changed comment on extending the header, added advanced user comment.} "Carl"] ] Language: 'English ] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Script files can be loaded as data with the [[load|Functions: load]] function. This function reads the script and translates the script into values, words, and blocks, but does not evaluate the script. The result of the [[load|Functions: load]] function is a block, unless only a single value was loaded, then that value is returned. The script argument to the [[load|Functions: load]] function is a file name, URL, or a string. ``` load %script.r load %datafile.txt load http://www.rebol.org/script.r load "print now" ``` The load function performs the following steps: * Reads the text from the file, URL, or string. * Searches for a script header, if present. * Translates data beginning after the header, if found. * Returns a block containing the translated values. For example, if a script file buy.r contained the text: ``` Buy 100 shares at $20.00 per share ``` it could be loaded with the line: ``` data: load %buy.r ``` which would result in a block: ``` probe data [Buy 100 shares at $20.00 per share] ``` <<< It should be noted that the "Buy" example above is a dialect of REBOL, not directly executable code. See Chapter 4 on Expressions or Chapter 15 on Parsing for more information. <<< Note that a file does not require a header to be loaded. The header is necessary only if the file is to be run as a script. The load function supports a few refinements. The load Function Refinements lists the refinements and a description of their functionality: |`/header` |Includes the header if present.| |`/next` |Loads only the next value, one value at a time. This is useful for parsing REBOL scripts.| |`/markup` |Treats the file as an HTML or XML file and returns a block that holds its tags and text.| Normally, load does not return the header from the script. But, if the `/header` refinement is used the returned block contains the header object as its first argument. The `/next` refinement loads the next value and returns a block containing two values. The first returned value is the next value from the series. The second returned value is the string position immediately following the last item loaded. The `/markup` refinement loads HTML and XML data as a block of tags and strings. All tags are tag data types. All other data are treated as strings. If the following file contents where loaded with load/markup: ``` <title>This is an example</title> ``` a block would be produced: ``` probe data [<title> "This is an example" </title>] ```
Scripts also have access to the options provided to the REBOL interpreter when it was started. These are found in the `system/options` object. |''boot'' |The file path to the REBOL executable that you are currently running.| |''home'' |The file path as determined by your operating system's environment. This is the path set in the HOME environment variable or system registry for systems that support it. This is the path used to find the rebol.r and user.r files.| |''path'' |The file path to the current directory.| |''script'' |The file name of the initial script provided when the interpreter was launched.| |''args'' |The initial arguments provided to the interpreter on the command line.| |''do-arg'' |The string provided as an argument to the --do option on the command line.| The `system/options` object also contains additional options that were provided on the command line. Type ``` probe system/options ``` to examine the contents of the options object. Examples: ``` print system/options/script probe system/options/args print read system/options/home/user.r ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< There are two ways to run a script: as the initial script when the REBOL interpreter is started, or from the do function. To run a script when starting the interpreter, provide the script name on the command line following the REBOL program name: ``` rebol script.r ``` As soon as the interpreter initializes, the script is evaluated. From the do function, provide the script file name or URL as an argument. The file is loaded into the interpreter and evaluated: ``` do %script.r do http://www.rebol.com/script.r ``` The do function returns the result of the script when it finishes evaluation. Note that the script file must include a valid REBOL header.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Data can be saved to a script file in a format that can be loaded into REBOL with the [[load|Functions: load]] function. This is a useful way to save data values and blocks of data. In this fashion, it is possible to create entire mini-databases. The save function expects two arguments: a file name and either a block or a value to be saved: ``` data: [Buy 100 shares at $20.00 per share] save %data.r data ``` The data is written out in REBOL source text format, which can be loaded later with: ``` data: load %data.r ``` Simple values can also be saved and loaded. For instance, a date stamp can be saved with: ``` save %date.r now ``` and later reloaded with: ``` stamp: load %date.r ``` In the previous example, because stamp is a single value, it is not enclosed in a block when loaded. To save a script file with a header, the header can be provided in a refinement as either an object or a block: ``` header: [Title: "This is an example"] save/header %data.r data header ``` ``` !save/all ``` ``` !save/flat ``` ``` !save/only ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< When a script is evaluated, it has access to information about itself. This is found in the `system/script` object. The object contains the fields listed in `[bad-link:concepts/object.txt]` Fields for system/script. |''Header'' |The header object of the script. This can be used to access the script's title, author, version, date, and other fields.| |''Parent'' |If the script was evaluated from another script, this is the system/script object for the parent script.| |''Path'' |The file directory path or URL to the script being evaluated.| |''Args'' |The arguments to the script. These are passed from the operating system command line or from the do function that was used to evaluate the script.| Examples of using the script object are: ``` print system/script/title print system/script/header/date do system/script/args do system/script/path/script.r ``` The last example evaluates a script called script.r in the same directory as the script that is currently running.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Here is a short script that can be used to clean up the indentation of a script. It works by parsing the REBOL syntax and reconstructing each line of the script. This example can be found in the REBOL Script Library at www.REBOL.com. ``` out: none ; output text spaced: off ; add extra bracket spacing indent: "" ; holds indentation tabs emit-line: func [] [append out newline] emit-space: func [pos] [ append out either newline = last out [indent] [ pick [#" " ""] found? any [ spaced not any [find "[(" last out find ")]" first pos] ] ] ] emit: func [from to] [ emit-space from append out copy/part from to ] clean-script: func [ "Returns new script text with standard spacing." script "Original Script text" /spacey "Optional spaces near brackets/parens" /local str new ] [ spaced: found? spacey out: append clear copy script newline parse script blk-rule: [ some [ str: newline (emit-line) | #";" [thru newline | to end] new: (emit str new) | [#"[" | #"("] (emit str 1 append indent tab) blk-rule | [#"]" | #")"] (remove indent emit str 1) | skip (set [value new] load/next str emit str new) :new ] ] remove out ; remove first char ] script: clean-script read %script.r write %new-script.r script ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Files are often used for data storage. Format is similar. SAVE and LOAD header not required Use load/all
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The term script refers not only to single files that are evaluated but also to source text embedded within other types of files (such as, web pages), or fragments of source text that are saved as data files or passed as messages. ''Free-form'' The structure of a script is free-form. Indentation and spacing can be used to clarify the structure and content of the script. In addition, you are encouraged to use the standard scripting style to make scripts more universally readable. See [[scripts: style guide|Concepts: Scripts: Style Guide]] for more information. ''Editor note: This section is new or has has recently changed and is still under construction.'' header / body including files forward references data creation in script Unicode encoding, BOM
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< REBOL scripts are free-form. You can write a script using the indenting, spacing, line length, and line terminators you prefer. You can put each word on a separate line or join them together on one long line. While the formatting of your script does not affect the interpreter, it does affect its human readability. Because of this, REBOL Technologies encourages you to follow the standard scripting style described in this section. Of course, you don't have to follow any of these suggestions. However, scripting style is more important than it first seems. It can make a big difference in the readability and reuse of scripts. Users may judge the quality of your scripts by the clarity of their style. Sloppy scripts often mean sloppy code. Experienced script writers usually find that a clean, consistent style makes their code easier to produce, maintain, and revise. ''Contents'' * [[Formatting]] ** Indent Content for Clarity ** Standard Tab Size ** Detab Before Posting ** Limit Line Lengths to 80 Characters * [[Word Names|Concepts: Scripts: Style Guide: Word Names]] ** Use the Shortest Word that Communicates the Meaning ** Use Whole Words Where Possible ** Hyphenate Multiple Word Names ** Begin Function Names with a Verb ** Begin Data Words with Nouns ** Use Standard Names * [[Script Headers]] * [[Function Headers]] * [[Script File Names]] * [[Embedded Examples]] * [[Embedded Debugging]] * [[Minimize Globals]] !!! ''Formatting'' {{Formatting}} !!! ''Word Names'' {{Concepts: Scripts: Style Guide: Word Names}} !!! ''Script Headers'' {{Script Headers}} !!! ''Function Headers'' {{Function Headers}} !!! ''Script File Names'' {{Script File Names}} !!! ''Embedded Examples'' {{Embedded Examples}} !!! ''Embedded Debugging'' {{Embedded Debugging}} !!! ''Minimize Globals'' {{Minimize Globals}}
Words are a user's first exposure to your code, so it is critical to choose words carefully. A script should be clear and concise. When possible, the words should relate to their English or other human language equivalent, in a simple, direct way. The following are standard naming conventions for REBOL. !!!!! ''Use the Shortest Word that Communicates the Meaning'' Short, crisp words work best where possible: ``` size time send wait make quit ``` Local words can often be shortened to a single word. Longer, more descriptive words are better for global words. !!!!! ''Use Whole Words Where Possible'' What you save when abbreviating a word is rarely worth it. Type date not dt, or image-file not imgfl. !!!!! ''Hyphenate Multiple Word Names'' The standard style is to use hyphens, not character case, to distinguish words. ``` group-name image-file clear-screen bake-cake ``` !!!!! ''Begin Function Names with a Verb'' Function names begin with a verb and are followed by a noun, adverb, or adjective. Some nouns can also be used as verbs. ``` make print scan find show hide take rake-coals find-age clear-screen ``` Avoid unnecessary words. For instance, quit is just as clear as quit-system. When using a noun as a verb, use special characters such as ? where applicable. For instance, the function for getting the length of a series is length?. Other REBOL functions using this naming convention are: ``` size? dir? time? modified? ``` !!!!! ''Begin Data Words with Nouns'' Words for objects or variables that hold data should begin with a noun. They can include modifiers (adjectives) as needed: ``` image sound big-file image-files start-time ``` !!!!! ''Use Standard Names'' There are standard names in REBOL that should be used for similar types of operations. For instance: ``` make-blub ;creating something new free-blub ;releasing resources of something copy-blub ;copying the contents of something to-blub ;converting to it insert-blub ;inserting something remove-blub ;removing something clear-blub ;clearing something ``` !!!!! ''Script Headers'' The advantage of using headers is clear. Headers give users a summary of a script and allow other scripts to process the information (like a cataloging script). A minimum header provides a title, date, file name and purpose. Other fields can also be provided such as author, notes, usage, and needs. ``` REBOL [ Title: "Local Area Defringer" Date: 1-Jun-1957 File: %defringe.r Purpose: { Stabilize the wide area ignition transcriber using a double ganged defringing algorithm. } ] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The concept of a `series` is fundamental in REBOL. You need to know it if you are going to be productive with REBOL. ''Definition'' A series is an ordered sequence of values. The these values can be characters, as found in a [[string!|Datatypes: String!]], or they can be values as found in a [[block!|Datatypes: Block!]] series. There are other types of series too, but they are similar to strings and blocks. For example, a [[file!|Datatypes: File!]] and a [[url!|Datatypes: Url!]] are other types of string series. A [[path!|Datatypes: Path!]] and a [[paren!|Datatypes: Paren!]] are [[block!|Datatypes: Block!]] series. Example series: ``` string series: "ABCD" file series: %example.txt URL series: http://www.rebol.com block series: [1 2 3 4] paren series: (1 + 2) path series: system/options ``` There several other series datatypes as well, but they are similar to strings or blocks. ''Order of values'' Editor note: This section is new or has has recently changed and is still under construction. ''Main functions'' Editor note: This section is new or has has recently changed and is still under construction.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Contents'' * [[Making a new series]] * [[Copying a series]] * [[Partial Copies]] * [[Deep Copies]] * [[Initial Copies]] !!! ''Making a new series'' {{Making a new series}} !!! ''Copying a series'' {{Copying a series}} !!! ''Partial Copies'' {{Partial Copies}} !!! ''Deep Copies'' {{Deep Copies}} !!! ''Initial Copies'' {{Initial Copies}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The [[change|Functions: change]], [[insert|Functions: insert]], and [[remove|Functions: remove]] functions can take additional refinements to modify their operation. ''Contents'' * [[Part]] * [[Only]] * [[Dup]] !!! ''Part'' {{Part}} !!! ''Only'' {{Only}} !!! ''Dup'' {{Dup}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Multiple variables can refer to the same series. For instance: ``` data: [1 2 3 4 5] start: find data 3 end: find start 4 print first start 2 ``` ``` print first end 4 ``` Both the `start` and `end` variables refer to the series. They have different positions, but the series they reference is the same. If an [[insert|Functions: insert]] or [[remove|Functions: remove]] function is performed on a series, the values in the series will shift and the `start` and end variables may no longer refer to the same values. For instance, if a value is removed from the series at the start position: ``` remove start print first start 3 ``` ``` print first end 5 ``` The series has shifted to the left and the variables now refer to different values. Notice that the index positions of the variables have not changed, but the values in the series have changed. The same situation would occur when using [[insert|Functions: insert]]. Sometimes this side effect will work to your advantage. Sometimes it will not, and you will need to correct for it in your code.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The [[find|Functions: find]] function searches through block or string series for a value or pattern. This function has many refinements that permit a wide range of variations in search parameters. ''Contents'' * [[Simple Find]] * [[Refinement Summary]] * [[Partial Searches]] * [[Tail Positions]] * [[Backward Searches]] * [[Repeated Searches]] * [[Matching]] * [[Wildcard Searches]] * [[Select]] * [[Search and Replace]] !!! ''Simple Find'' {{Simple Find}} !!! ''Refinement Summary'' {{Refinement Summary}} !!! ''Partial Searches'' {{Partial Searches}} !!! ''Tail Positions'' {{Tail Positions}} !!! ''Backward Searches'' {{Backward Searches}} !!! ''Repeated Searches'' {{Repeated Searches}} !!! ''Matching'' {{Matching}} !!! ''Wildcard Searches'' {{Wildcard Searches}} !!! ''Select'' {{Select}} !!! ''Search and Replace'' {{Search and Replace}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< There are a few functions that operate on series as data sets. These functions allow you to perform operations such as finding the union or intersection between two series. ''Contents'' * [[Unique]] * [[Intersect]] * [[Union]] * [[Exclude]] * [[Difference]] !!! ''Unique'' {{Unique}} !!! ''Intersect'' {{Intersect}} !!! ''Union'' {{Union}} !!! ''Exclude'' {{Exclude}} !!! ''Difference'' {{Difference}} --- A variation of the [[difference|Functions: difference]] function is the [[exclude|Functions: exclude]] function. It returns the values that are in the first series but not found in the second series. For example: ``` probe exclude [1 2 3 4] [1 2 3 5] [4] ``` Notice that the above result does not contain 5, as was the case with difference in the prior section. ``` probe exclude [Bill Bob Bart] [Bob Ted Fred] [Bill Bart] ``` ``` probe exclude "abcde" "ace" "bd" ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< All series datatypes can be divided into two broad classes. Each includes a datatype value and a type test function. ''Contents'' * [[Block Types]] * [[String Types]] * [[Pseudo-types]] * [[Type Test Functions]] !!! ''Block Types'' {{Block Types}} !!! ''String Types'' {{String Types}} !!! ''Pseudo-types'' {{Pseudo-types}} !!! ''Type Test Functions'' {{Type Test Functions}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< Here is a summary of the functions that operate on series. Most of these were described in detail in the previous section. Others will be covered in more detail in this section. ''Contents'' * [[Creation Functions]] * [[Navigation Functions]] * [[Information Functions]] * [[Extraction Functions]] * [[Modification Functions]] * [[Search Functions]] * [[Ordering Functions]] * [[Data Set (Group) Functions]] !!! ''Creation Functions'' {{Creation Functions}} !!! ''Navigation Functions'' {{Navigation Functions}} !!! ''Information Functions'' {{Information Functions}} !!! ''Extraction Functions'' {{Extraction Functions}} !!! ''Modification Functions'' {{Modification Functions}} !!! ''Search Functions'' {{Search Functions}} !!! ''Ordering Functions'' {{Ordering Functions}} !!! ''Data Set (Group) Functions'' {{Data Set (Group) Functions}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Contents'' * Length? * Head? * Tail? * Index? * Offset? ''Length?'' The length of a series is the number of items (values for a block or characters for a string) from the current position to the [[tail|Functions: tail]]. If the current position is the head of the series, then the length is the number of items in the entire series. The [[length?|Functions: length?]] function returns the number of items to the tail. ``` colors: [blue red green] print length? colors 3 ``` All three values are part of the length: If the position of the `color` variable is advanced to the next value: ``` color: next color print length? color 2 ``` the [[length?|Functions: length?]] becomes two: Other examples of [[length?|Functions: length?]]: ``` print length? "Ukiah" 5 ``` ``` print length? [] 0 ``` ``` print length? "" 0 ``` ``` data: [1 2 3 4 5 6 7 8] print length? data 8 ``` ``` data: next data print length? data 7 ``` ``` data: skip data 5 print length? data 2 ``` ''Head?'' The head of a series is the position of its first value. If a series is at its head, the head? function returns true: ``` data: [1 2 3 4 5] print head? data true ``` ``` data: next data print head? data false ``` ''Tail?'' The tail of a series is the position `immediately` following the last value. If a series variable is at the tail, the [[tail?|Functions: tail?]] function returns true: ``` data: [1 2 3 4 5] print tail? data false ``` ``` data: tail data print tail? data true ``` The [[empty?|Functions: empty?]] function is equivalent to the [[tail?|Functions: tail?]] function. ``` print empty? data true ``` If [[empty?|Functions: empty?]] returns `true`, it means there are no values between the current position and the [[tail|Functions: tail]]; however, there still may be values in the series. Values can still be present before the current position. If you need to determine if the series is empty from head to tail, use: ``` print empty? head data false ``` ''Index?'' The `index` is the position in a series relative to the head of the series. To determine the index position for a series variable, use the [[index?|Functions: index?]] function: ``` data: [1 2 3 4 5] print index? data 1 ``` ``` data: next data print index? data 2 ``` ``` data: tail data print index? data 6 ``` ''Offset?'' The distance between two positions in a series can be determined with the [[offset?|Functions: offset?]] function. ``` data: [1 2 3 4] data1: next data data2: back tail data print offset? data1 data2 4 ``` In this example, the offset is the difference between position 2 and position 4:
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< You can use a loop to traverse a series. There are a few loop functions that can help automate the iteration process. ''Contents'' * [[Foreach Loop]] * [[While Loop]] * [[Forall Loop]] * [[Forskip Loop]] * [[The Break Function]] !!! ''Foreach Loop'' {{Foreach Loop}} !!! ''While Loop'' {{While Loop}} !!! ''Forall Loop'' {{Forall Loop}} !!! ''Forskip Loop'' {{Forskip Loop}} !!! ''The Break Function'' {{The Break Function}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< The [[sort|Functions: sort]] function offers a simple, quick method of sorting series. It is most useful for blocks of data, but can also be used on strings of characters. ''Contents'' * [[Simple Sorting]] * [[Group Sorting]] * [[Comparison Functions]] !!! ''Simple Sorting'' {{Simple Sorting}} !!! ''Group Sorting'' {{Group Sorting}} !!! ''Comparison Functions'' {{Comparison Functions}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Contents'' * [[Traversing a Series]] * [[Skipping Around]] * [[Extracting Values]] * [[Extracting a Sub-series]] * [[Inserting and Appending]] * [[Removing Values]] * [[Changing Values]] !!! ''Traversing a Series'' {{Traversing a Series}} !!! ''Skipping Around'' {{Skipping Around}} !!! ''Extracting Values'' {{Extracting Values}} !!! ''Extracting a Sub-series'' {{Extracting a Sub-series}} !!! ''Inserting and Appending'' {{Inserting and Appending}} !!! ''Removing Values'' {{Removing Values}} !!! ''Changing Values'' {{Changing Values}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< <<< OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. <<< This chapter provides a quick way to familiarize yourself with the REBOL language. Using examples, this chapter presents the basic concepts and structure of the language, illustrating everything from data values to performing network operations.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ``` OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. ``` REBOL is composed by grouping values and words into ''blocks''. Blocks are used for code, lists, arrays, tables, directories, associations, and other sequences. A block is a type of series which is a ''collection of values'' organized in a ''specific order''. A block is enclosed in square brackets [ ]. Within a block, values and words can be organized in any order and can span any number of lines. The following examples illustrate the valid forms of blocks: ``` [white red green blue yellow orange black] ["Spielberg" "Back to the Future" 1:56:20 MCA] [ Ted ted@gw2.dom #213-555-1010 Bill billg@ms.dom #315-555-1234 Steve jobs@apl.dom #408-555-4321 ] [ "Elton John" 6894 0:55:68 "Celine Dion" 68861 0:61:35 "Pink Floyd" 46001 0:50:12 ] ``` Blocks are used for code as well as for data, as shown in the following examples: ``` loop 10 [print "hello"] if time > 10:30 [send jim news] sites: [ http://www.rebol.com [save %reb.html data] http://www.cnn.com [print data] ftp://www.amiga.com [send cs@org.foo data] ] foreach [site action] sites [ data: read site do action ] ``` A script file itself also is a block. Although it does not include the brackets, the block is implied. For example, if the lines below were put in a script file: ``` red green blue yellow ``` When the file is loaded, it will be a block that contains the words red, green, blue, and yellow. It is equivalent to writing: ``` [red green blue yellow] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< <<< OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. <<< Blocks are evaluated to compute their results. When a block is evaluated the values of its variables are obtained. The following examples evaluate the variables age, `snack-time`, `birthda`y, and `friends` that were defined in the previous section: ``` print age 22 ``` ``` if current-time > snack-time [print snack-time] 12:32 ``` ``` print third friends Georgia ``` A block can be evaluated multiple times by using a loop, as shown in the following examples: ``` loop 10 [prin "*"] ;("prin" is not a typo, see manual) ********** ``` ``` loop 20 [ wait 8:00 send friend@rebol.com read http://www.cnn.com ] repeat count 3 [print ["count:" count]] count: 1 count: 2 count: 3 ``` The evaluation of a block returns a result. In the following examples, 5 and PM are the results of evaluating each block: ``` print do [2 + 3] 5 ``` ``` print either now/time < 12:00 ["AM"]["PM"] PM ``` In REBOL there are no special operator precedence rules for evaluating blocks. The values and words of a block are always evaluated from first to last, as shown in the following example: ``` print 2 + 3 * 10 50 ``` Parentheses can be used to control the order of evaluation, as shown in the following examples: ``` 2 + (3 * 10) 32 ``` ``` (length? "boat") + 2 6 ``` You can also evaluate a block and return each result that was computed within it. This is the purpose of the reduce function: ``` reduce [1 + 2 3 + 4 5 + 6] 3 7 11 ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< <<< OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. <<< In REBOL, files are easily accessed. The following table describes some of the ways to access files. You can read a text file with: ``` data: read %plan.txt ``` You can display a text file with: ``` print read %plan.txt ``` To write a text file: ``` write %plan.txt data ``` For instance, you could write out the current time with: ``` write %plan.txt now ``` You can also easily append to the end of a file: ``` write/append %plan data ``` Binary files can be read and written with: ``` data: read/binary %image.jpg write/binary %new.jpg data ``` To load a file as a REBOL block or value: ``` data: load %data.r ``` Saving a block or a value to a file is just as easy: ``` save %data.r data ``` To evaluate a file as a script (it needs a header to do this.): ``` do %script.r ``` You can read a file directory with: ``` dir: read %images/ ``` and, you can then display the file names with: ``` foreach file dir [print file] ``` To make a new directory: ``` make-dir %newdir/ ``` To find out the current directory path: ``` print what-dir ``` If you need to delete a file: ``` delete %oldfile.txt ``` You can also rename a file with: ``` rename %old.txt %new.txt ``` To get information about a file: ``` print size? %file.txt print modified? %file.txt print dir? %image ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< <<< OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. <<< A function is a block with variables that are given new values each time the block is evaluated. These variables are called the arguments of the function. In the following example, the word sum is set to refer to a function that accepts two arguments, `a` and `b` : ``` sum: func [a b] [a + b] ``` In the above example, func is used to define a new function. The first block in the function describes the arguments of the function. The second block is the block of code that gets evaluated when the function is used. In this example, the second block adds two values and returns the result. The next example illustrates one use of the function sum that was defined in the previous example: ``` print sum 2 3 5 ``` Some functions need local variables as well as arguments. To define this type of function, use [[function!|Datatypes: Function!]], instead of [[func|Functions: func]], as shown in the following example: ``` average: function [series] [total] [ total: 0 foreach value series [total: total + value] total / (length? series) ] print average [37 1 42 108] 47 ``` In the above example, the word [[series|Concepts: Series]] is an argument and the word `total` is a local variable used by the function for calculation purposes. The function argument block can contain strings to describe the purpose of a function and its argument, as shown in the following example: ``` average: function [ "Return the numerical average of numbers" series "Numbers to average" ] [total] [ total: 0 foreach value series [total: total + value] total / (length? series) ] ``` These descriptive strings are kept with the function and can be viewed by asking for help about the function, as shown below: ``` help average USAGE: AVERAGE series DESCRIPTION: Return the numerical average of numbers AVERAGE is a function value. ARGUMENTS: series -- Numbers to average (Type: any) ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< <<< OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. <<< There are a number of Internet protocols built into REBOL. These protocols are easy to use and require very little knowledge of networking. ''Contents'' * [[HTTP]] * [[FTP]] * [[SMTP]] * [[POP]] * [[NNTP]] * [[Daytime]] * [[Whois]] * [[Finger]] * [[DNS]] * [[TCP]] !!! ''HTTP'' {{HTTP}} !!! ''FTP'' {{FTP}} !!! ''SMTP'' {{SMTP}} !!! ''POP'' {{POP}} !!! ''NNTP'' {{NNTP}} !!! ''Daytime'' {{Daytime}} !!! ''Whois'' {{Whois}} !!! ''Finger'' {{Finger}} !!! ''DNS'' {{DNS}} !!! ''TCP'' {{TCP}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< <<< OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. <<< An object is a set of variables that have specific values in a context. Objects are used for managing data structures and more complex behavior. The following example shows how a bank account is set up as an object to specify its attributes and functions: ``` account: make object! [ name: "James" balance: $100 ss-number: #1234-XX-4321 deposit: func [amount] [balance: balance + amount] withdraw: func [amount] [balance: balance - amount] ] ``` In the above example, the words name, `balance`, `ss-number`, `deposit`, and `withdraw` are local variables of the account object. The `deposit` and `withdraw` variables are functions that are defined within the object. The variables of the account can be accessed with a path, as shown in the next example: ``` print account/balance $100.00 ``` ``` account/deposit $300 print ["Balance for" account/name "is" account/balance] Balance for James is $400.00 ``` The next example shows how to make another account with a new balance but with all other values remaining the same: ``` checking-account: make account [ balance: $2000 ] ``` Notice that the new object is called checking-account, and it shares the values of the original account, but provides a new balance amount. Just as easily you can create a new account object that extends the old account object, adding new variables for the bank name and last activity date: ``` account: make account [ bank: "Savings Bank" last-active: 20-Jun-2000 ] print account/balance $400.00 ``` ``` print account/bank Savings Bank ``` ``` print account/last-active 20-Jun-2000 ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< <<< OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. <<< If you are using files and URLs, then you are already familiar with the concept of paths. A path provides a set of values that are used to navigate from one point to another. In the case of a file, a path specifies the route through a set of directories to the location of the file. In REBOL, the values in a path are called [[refinements|/local refinement]]. A slash `/` is used to separate words and values in a path, as shown in the following examples of a file path and a URL path: ``` %source/images/globe.jpg http://www.rebol.com/examples/simple.r ``` Paths can also be used to select values from blocks, pick characters from strings, access variables in objects, and refine the operation of a function, as shown in the following examples: ``` USA/CA/Ukiah/size (block selection) names/12 (string position) account/balance (object function) match/any (function option) ``` The print function in next example shows the simplicity of using a path to access a mini-database created from a few blocks: ``` towns: [ Hopland [ phone #555-1234 web http://www.hopland.ca.gov ] Ukiah [ phone #555-4321 web http://www.ukiah.com email info@ukiah.com ] ] print towns/ukiah/web http://www.ukiah.com ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< <<< OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. <<< A script is a file that holds a block that can be loaded and evaluated. The block can contain code or data, and typically contains a number of sub-blocks. Scripts require a header to identify the presence of code. The header can include the script title, date, and other information. In the following example of a script, the first block contains the header information: ``` REBOL [ Title: "Web Page Change Detector" File: %webcheck.r Author: "Reburu" Date: 20-May-1999 Purpose: { Determine if a web page has changed since it was last checked, and if it has, send the new page via email. } Category: [web email file net 2] ] page: read http://www.rebol.com page-sum: checksum page if any [ not exists? %page-sum.r page-sum <> (load %page-sum.r) ][ print ["Page Changed" now] save %page-sum.r page-sum send luke@rebol.com page ] ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ``` OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. ``` A script is written with a sequence of values. A wide variety of values exist and you are familiar with many of them from daily experience. When possible, REBOL also allows the use of international formats for values such as decimal numbers, money, time, and date. ''Contents'' * [[Numbers]] * [[Times]] * [[Dates]] * [[Money]] * [[Tuples]] * [[Strings]] * [[Tags]] * [[Email Addresses]] * [[URLs]] * [[Filenames]] * [[Pairs]] * [[Issues]] * [[Binary]] !!! ''Numbers'' {{Numbers}} !!! ''Times'' {{Times}} !!! ''Dates'' {{Dates}} !!! ''Money'' {{Money}} !!! ''Tuples'' {{Tuples}} !!! ''Strings'' {{Strings}} !!! ''Tags'' {{Tags}} !!! ''Email Addresses'' {{Email Addresses}} !!! ''URLs'' {{URLs}} !!! ''Filenames'' {{Filenames}} !!! ''Pairs'' {{Pairs}} !!! ''Issues'' {{Issues}} !!! ''Binary'' {{Binary}}
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< <<< OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. <<< Words can be used as variables that refer to values. To define a word as a variable, follow the word with a colon `:`, then the value to which the variable refers as shown in the following examples:. ``` age: 22 snack-time: 12:32 birthday: 20-Mar-1997 friends: ["John" "Paula" "Georgia"] ``` A variable can refer to any type of value, including functions (see `[bad-link:concepts/functions.txt]`) and objects (see [[objects|Concepts: Objects]]). A variable refers to a specific value only within a defined context, such as a block, a function, or an entire program. Outside that context the variable can refer to some other value or to no value at all. The context of a variable can span an entire program or it can be restricted to a particular block, function, or object. In other languages, the context of a variable is often referred to as the scope of a variable.
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< <<< OLD DOCS This section is obsolete and being replaced. It is kept only as a source for new content. <<< Words are the symbols used by REBOL. A word may or may not be a variable, depending on how it is used. Words are also used directly as symbols. ``` show next image Install all files here Country State City Street Zipcode on off true false one none ``` REBOL has no keywords; there are no restrictions on what words are used or how they are used. For instance, you can define your own function called [[print|Functions: print]] and use it instead of the predefined function for printing values. Words are not case sensitive and can include hyphens and a few other special characters such as: ``` + - ` * ! ~ & ? | ``` The following examples illustrate valid words: ``` number? time? date! image-files l'image ++ -- == +- ***** *new-line* left&right left|right ``` The end of a word is indicated by a space, a line break, or one of the following characters: ``` [ ] ( ) { } " : ; / ``` The following characters are not allowed in words: ``` @ # $ % ^ , ```
The [[if|Functions: if]] function takes two arguments. The first argument is a condition and the second argument is a block. If the condition is `true` , the block is evaluated, otherwise it is not evaluated. ``` if now/time > 12:00 [print "past noon"] past noon ``` The condition is normally an expression that evaluates to `true` or `false` ; however, other values can also be supplied. Only a `false` or a [[ none!|Datatypes: None!]] value prevents the block from being evaluated. All other values (including zero) are treated as true, and cause the block to be evaluated. This can be useful for checking the results of [[find|Functions: find]], [[select|Functions: select]], [[next|Functions: next]], and other functions that return [[ none!|Datatypes: None!]] : ``` string: "let's talk about REBOL" if find string "talk" [print "found"] found ``` The [[either|Functions: either]] function extends [[if|Functions: if]] to include a third argument, which is the block to evaluate if the condition is `false`: ``` either now/time > 12:00 [ print "after lunch" ][ print "before lunch" ] after lunch ``` The [[either|Functions: either]] function also interprets a [[none!|Datatypes: None!]] value as `false`. Both the [[if|Functions: if]] and [[either|Functions: either]] functions return the result of evaluating their blocks. In the case of an if, the block value is only returned if the block is evaluated; otherwise, a [[none!|Datatypes: None!]] is returned. The [[if|Functions: if]] function is useful for conditional initialization of variables: ``` flag: if time > 13:00 ["lunch eaten"] print flag lunch eaten ``` Making use of the result of the [[either|Functions: either]] function, the previous example could be rewritten as follows: ``` print either now/time > 12:00 [ "after lunch" ][ "before lunch" ] ``` after lunch Since both [[if|Functions: if]] and [[either|Functions: either]] are functions, their block arguments can be any expression that results in a block when evaluated. In the following examples, words are used to represent the block argument for [[if|Functions: if]] and [[either|Functions: either]]. ``` notice: [print "Wake up!"] if now/time > 7:00 notice Wake up! ``` ``` notices: [ [print "It's past sunrise!"] [print "It's past noon!"] [print "It's past sunset!"] ] if now/time > 12:00 second notices It's past noon! ``` ``` sleep: [print "Keep sleeping"] either now/time > 7:00 notice sleep Wake up! ``` The conditional expressions used for the first argument of both [[if|Functions: if]] and [[either|Functions: either]] can be composed from a wide variety of comparison and logic functions. Refer to the [[math|Concepts: Math]] Chapter for more information. <<< Avoid This Common Mistake The most commonly made mistake in REBOL is to forget the second block on [[either|Functions: either]] or add a second block to [[if|Functions: if]]. These examples both creator hard-to-find errors: ``` either age > 10 [print "Older"] if age > 10 [print "Older"] [print "Younger"] ``` These types of errors may be difficult to detect, so keep this in mind if these functions do not seem to be doing what you expect. <<<
Conditional functions provide a shortcut that lets you use values other than [[logic!|Datatypes: Logic!]] as their condition. This done quite often. In such cases, the condition is only false when it returns `false` or [[none!|Datatypes: None!]], and they are true when they return any other value. Below, all of the conditional expressions act like `true`, ''even the zero and empty block values''. ``` if true [print "yep"] yep ``` ``` if 1 [print "yep"] yep ``` ``` if 0 [print "yep"] ; C programmers - watch out! yep ``` ``` if [] [print "yep"] yep ``` Here the expressions are false : ``` if false [print "yep"] if none [print "yep"] ``` So, be sure never to enclose the conditional in a block. The block is not evaluated, it just acts like a value, which will be TRUE: ``` if [false] [print "yep"] yep ``` The blocks act like true is simple. This style of coding is used quite often: ``` if find block item [print "found"] ``` This is an example of two functions (''if'' and ''find'') being "compounded" together. Let's break that compound set of functions down. * The ''if'' function needs two arguments (the condition, and then-block when condition is true). * The next word ''find'' is itself a function and it needs two arguments (the series to look through, and the value to look for). * (Let's assume that ''block'' and ''item'' have been previously resolved sometime earlier.) When the [[find|Functions: find]] function finds the item, it turns a [[block!|Datatypes: Block!]] series (at the location of the item). If it fails to find the item, it returns `none`. When ''find block item'' is resolved to a value, it then becomes the condition argument for the ''if'' function, and ''[print "found"]'' will become the then-block argument. The use of compound functions is one of the strengths of Rebol. It is easier and more efficient to code that way than to use temporary arguments like this: ``` temp: find block item if temp [print "found"] ```
For a word to have meaning, its context must be known. That context can be the meaning of the word: * relative to you. That is, as interpreted by a human. * relative to REBOL. Interpreted by its definition within a section of the code, such as a function or an object. * relative to a dialect. Interpreted by other code written in REBOL. Let's clarify this with three examples. First, take this example: ``` sizes: [large medium small] print sizes large medium small ``` The words large, medium, and small are just symbols. Defined this way, they are not variables, and they have no meaning to REBOL, only meaning to you, the reader. Second, look at this: ``` large: 1000 medium: 100 small: 10 print [large medium small] 1000 100 10 ``` Here, the words have been defined to have specific values within the scope that is known when the [[print|Functions: print]] function is evaluated by REBOL. These words are used as variables. And, the third example is: ``` rules: ['data 'is ['large | 'medium | 'small]] parse [data is medium] rules true ``` ``` parse [data is huge] rules false ``` As in the first example, the words large, medium, and small are symbols, but their meaning is defined by the rules provided to [[parse.|Functions: parse]] Their meaning is relative to those ''rules''. They define a dialect of the language (although a trivial one at that.)
The [[continue|Functions: continue]] function will cause a loop to jump back to the top. <<< ''Editor note: This section is new or has has recently changed and is still under construction.'' <<<
In order to copy to and paste from the clipboard easily in the XP console, you need to enable Quick Edit mode in the properties menu. Here's how to enable it: # Right click the title bar, or left click on the icon at the upper left corner of the window, and select Properties. # In the Options panel, turn on "Quick Edit Mode" and "Insert Mode" and click the OK button. # If you start the program from a shortcut you can save these settings by selecting "Modify the shortcut that started this window" in the popup window that follows. Now you can select text by dragging with the left button down. Note that the text is selected in a rectangular block rather than by line. You must ''right click to copy text to the clipboard''. To paste from the clipboard, ''right click''. Note: Quick Edit mode is enabled by default in Windows Server 2003.
The [[copy|Functions: copy]] function creates a new series by copying an existing series: ``` string: copy "Message in a bottle" new-string: copy string block: copy [1 2 3 4 5] new-block: copy block ``` Copying is also important for use with functions that modify the contents of a series. For instance, if you want to change the case of a string without modifying the original, use the `copy`: ``` string: uppercase copy "Message in a bottle" ```
The most common action done with parse is to pick up parts of the string being parsed. This is done with copy, and it is followed by the name of a variable to which you want to copy the string. The following example parses the title of a web page: ``` parse page [thru <title> copy text to </title>] print text REBOL/Core Dictionary ``` The example works by skipping over text until it finds the `<title>` tag. That's where it starts making a copy of the input stream and setting a variable called `text` to hold it. The copy operation continues until the closing `<title>` tag is found. The copy action also can be used with entire rule blocks. For instance, for the rule: ``` [copy heading ["H" ["1" | "2" | "3"]] ``` the heading string contains the entire H1, H2, or H3 string. This also works for large multi-block rules.
Modules have been designed to be easy to create in order to help you better organize and structure your programs. To create a module you need to define two blocks: |''spec'' |a specification block that describes the module. It is usually quite small, just a few lines to specify the title, name, and version of your module, and its exported functions. It's format is the same the headers you use for programs.| |''body'' |a block of code that is initialized when the module is created. It is used to create functions, data, objects and other values needed by the module.|
New bitsets are created with [[make|Functions: make]], which accepts several datatypes as arguments, including a bitset specification block as described below. Bitsets can also be created from [[copy|Functions: copy]] and [[complement|Functions: complement]]. !!!! ''Using MAKE'' The standard method of creating bitsets is by providing make with a datatype and argument: ``` bits: make bitset! arg ``` The argument can be one of several datatypes, providing a range of possible results. If arg is an [[integer!|Datatypes: Integer!]], a bitset of at least that size in bits is allocated: ``` bits: make bitset! 1000 ``` If arg is a [[binary!|Datatypes: Binary!]], the bitset is initialized according to the bits that are set within its bytes. This is common when mold was used to output the bitset or to-binary was used to convert it to binary. ``` bits: make bitset! #{0F0016} ``` In addition, the spec can be a [[char!|Datatypes: Char!]], any [[string!|Datatypes: String!]], or a [[block!|Datatypes: Block!]]. ``` bits: make bitset! #"A" bits: make bitset! "ABC" bits: make bitset! [...] ; see below ``` <<< Zero based Unlike other series datatypes, bitsets are zero-based. This allows the NULL character to be included in the bitset and tested: ``` if find bits #"^(null)" [...] ``` <<< !!!! ''Unicode'' Bitsets are not limited to just ASCII characters. Unicode characters can also be specified. You can write them directly within the UTF-8 encoding of REBOL source, or you can write them as: ``` other: make bitset! [#"^(02FF)" - #"^(0FFF)"] ``` or even as integers: ``` other: make bitset! [612 - 990] ``` Bitsets will only allocate as many bits as necessary to reach the upper limit of the specified range. The bitset example above will require 124 bytes of memory storage. !!!! ''The CHARSET helper'' Because bitsets are so commonly used for character maps, the [[charset|Functions: charset]] helper function is also provided for creating bitsets. ``` digits: charset "0123456789" alpha: charset [#"A" - #"Z" #"a" - #"z"] ```
|''Function'' |''Description''|h |[[make|Functions: make]] |Makes a new series of the given type.| |[[copy|Functions: copy]] |Copies a series.|
Use the [[what-dir|Functions: what-dir]] function to determine the current directory: ``` print what-dir /work/REBOL/ ``` The what-dir function refers to the current script's directory path, as found in `system/script/path`.
Cygwin includes a package, ''rxvt'' which includes a split-personality mode when running without an X11 server. It looks nice and if you start the alpha with ``` $ rlwrap rebhost.exe ``` you'll also have access to cursor key command recall. ''rlwrap'' comes with the GNU readline utilities within Cygwin. Cygwin can be found at [[Cygwin Home|http://www.cygwin.com]]. The rxvt package needs to be included separately after the Base install. Tests ok under Win98 and Windows Vista and does not require the X11 server. Note: The rxvt console is not great for stdio redirection so fallback to the Windows console for testing anything not pure REBOL. Also, bugs should always be verified in the default Windows console before reporting.
|''Function'' |''Description''|h |[[unique|Functions: unique]] |Returns a unique set of values, removing duplicates.| |[[intersect|Functions: intersect]] |Returns only the values found in both series.| |[[union|Functions: union]] |Returns the combined values from two series.| |[[exclude|Functions: exclude]] |Returns one series less another.| |[[difference|Functions: difference]] |Returns the values not found in either series.|
Every REBOL value is of a particular ''datatype''. The datatype of a value defines: * The range of possible values for the datatype. For example, the logic datatype can only be true or false. * The operations that can be performed. For example, you can add two integers, but you cannot add two logical values. * The way in which the values are stored in memory. Some datatypes can be stored directly (such as numbers), while others are stored indirectly (such as strings). By convention, REBOL datatype words are followed by an exclamation point (!) to help make them stand out. For example: ``` integer! char! word! string! ``` <<< Datatype Words are Just Words The words used for datatypes are just like any other words in REBOL. There is nothing magic about the ! used to represent them. <<<
These datatypes are currently supported for commands. !!!!! ''Immediate datatypes'' |''Name'' |''Description''|h |logic |An integer representing TRUE and FALSE.| |integer |A 64-bit integer.| |decimal |64-bit IEEE floating point (double).| |percent |64-bit IEEE floating point (double).| |char |A character as a 32 bit code point.| |pair |Two 32 bit signed integers for x and y.| |tuple |A length byte followed by seven bytes. (Note truncation.)| |time |A 64 bit time in nano-seconds.| |date |A 32 bit encoded date and time zone.| |word |A 32 bit identifier for a word.| |set-word |A 32 bit identifier for a word.| |get-word |A 32 bit identifier for a word.| |lit-word |A 32 bit identifier for a word.| |refinement |A 32 bit identifier for a word.| !!!!! ''Series datatypes'' The series datatypes are indirect datatypes and can be divided into these general groups: |''Group'' |''Description''|h |strings |Including: string, file, email, url, tag, and issue.| |blocks |Including: block, paren, path, set-path, get-path, and lit-path.| |special |Including: binary, bitset, image, and vector.| !!!!! ''Special datatypes'' A few special datatypes are also allowed: |''Name'' |''Description''|h |unset |Means that a variable is not initialized or a function returned no result.| |none |No value. (For example, a find found no match.)| |handle |A way to store code and data pointers.|
''Concept'' This is a variant of a [[native!|Datatypes: Native!]] function that is standardized across datatypes. (They implement a set of common polymorphic functions.) For example, the insert function is an `action!` function. It performs the same abstract operation over a variety of datatypes: ``` insert "string" 123 insert [a b c] 123 ``` The same is true for the add action (which implements the + operator): ``` add 1 2 add 1:11 2:22 add 1.2.3 4.5.6 add 80% 10% ``` Note that not all actions apply to all datatypes. For example, insert is not used for integer! types and add is not used for string! types. Action functions are optimized, and new actions cannot be added to the system. ''List of Actions'' A complete list of action functions can be found in `system/catalog/actions`. They are listed below. * ''Magnitude (scalar) oriented'': [[add|Functions: add]], [[subtract|Functions: subtract]], [[multiply|Functions: multiply]], [[divide|Functions: divide]], [[remainder|Functions: remainder]], [[power|Functions: power]], [[and~|Functions: and~]], [[or~|Functions: or~]], [[xor~|Functions: xor~]], [[negate|Functions: negate]], [[complement|Functions: complement]], [[absolute|Functions: absolute]], [[random|Functions: random]], [[round|Functions: round]], [[odd?|Functions: odd?]], [[even?|Functions: even?]] * ''Series oriented'': [[head|Functions: head]], [[tail|Functions: tail]], [[head?|Functions: head?]], [[tail?|Functions: tail?]], [[past?|Functions: past?]], [[next|Functions: next]], [[back|Functions: back]], [[skip|Functions: skip]], [[at|Functions: at]], [[index?|Functions: index?]], [[length?|Functions: length?]], [[pick|Functions: pick]], [[find|Functions: find]], [[select|Functions: select]], [[reflect|Functions: reflect]], [[make|Functions: make]], [[to|Functions: to]], [[copy|Functions: copy]], [[take|Functions: take]], [[insert|Functions: insert]], [[append|Functions: append]], [[remove|Functions: remove]], [[change|Functions: change]], [[poke|Functions: poke]], [[clear|Functions: clear]], [[trim|Functions: trim]], [[swap|Functions: swap]], [[reverse|Functions: reverse]], [[sort|Functions: sort]] * ''Port oriented'': [[create|Functions: create]], [[delete|Functions: delete]], [[open|Functions: open]], [[close|Functions: close]], [[read|Functions: read]], [[write|Functions: write]], [[open?|Functions: open?]], [[query|Functions: query]], `bad-link:functions/modify.txt`, [[update|Functions: update]], [[rename|Functions: rename]]
<<< Different from R2 ''The binary datatype has changed significantly in REBOL 3.'' * ''operations on binary have a different meaning''. The biggest change is that a single element of a binary series is an integer ranging from 0-255, not a char! datatype. That is, if you get a single byte (e.g. pick) you'll get an integer. If you insert or poke an binary, an integer value is will taken as-is, not converted to a character representation. * a [[string!|Datatypes: String!]] ''datatype may be Unicode'' so converting a string containing non-ASCII characters will result in a binary string that is UTF-8 encoded. For example a string of length five may produce an output larger than five bytes. ''We plan to add a lot more documentation to this page to explain how to properly use the binary datatype for releases beyond R3-A98''. <<< ''Contents'' * Concept * Format * Creation * Related !!! ''Concept'' The `binary!` datatype is a [[series|Concepts: Series]] of bytes (8-bits each, octets). Binary is the ''raw storage format'' for all files and networking. It holds encoded data such as images, sounds, strings (in formats like UTF-8 and others), movies, compressed data, encrypted data, and others. The meaning of an specific binary value depends on what it holds. For example, if you read a JPEG image, it's just a sequence of bytes. Once you've decoded those bytes, it becomes an image! datatype. !!! ''Format'' The source format for binary data can be base-2 (binary), base-16 (hex), and base-64. The default base for binary data in REBOL is base-16. Binary strings are written as a number sign (#) followed by a string enclosed in braces. The characters within the string are encoded in one of several formats as specified by an optional number prior to the number sign. Base-16 is the default format. ``` #{3A18427F 899AEFD8} ; default base-16 2#{10010110110010101001011011001011} ; base-2 64#{LmNvbSA8yw9CB0aGvXmgUkVCu2Uz934b} ; base-64 ``` Spaces, tabs and newlines are permitted within the string. Binary data can span multiple lines. ``` probe #{ 3A 18 92 56 } #{3A189256} ``` Strings should contain the correct number of characters to create a binary result which is an integral number of bytes (integral multiple of 8 bits). !!! ''Creation'' The to-binary function converts data to the binary! datatype at the default base set in `system/options/binary-base`: ``` probe to-binary "123" #{313233} ``` ``` probe to-binary "today is the day..." #{746F64617920697320746865206461792E2E2E} ``` To convert an integer into its binary value, pass it in a block: ``` probe to-binary [1] #{01} ``` ``` probe to-binary [11] #{0B} ``` Converting a series of integers into a binary, returns the bit conversion for each integer concatenated into a single binary value: ``` probe to-binary [1 1 1 1] #{01010101} ``` !!! ''Related'' Use [[binary?|Functions: binary?]] determine whether a value is an `binary!` datatype. ``` probe binary? #{616263} true ``` Binary values are a type of series: ``` probe series? #{616263} true ``` ``` probe length? #{616263} ; three hex values in this binary 3 ``` Closely related to working with `binary!` datatypes are the functions enbase and debase. The enbase function converts strings to their base-2, base-16 or base-64 representations as strings. The debase function converts enbased strings to a binary value of the base specified in `system/options/binary-base`.
''Contents'' !!! ''Concept'' Bitsets are bit-based data sets, [[logic!|Datatypes: Logic!]] bitmaps. They map collections of integer and character values to true and false. For example, bitsets define character classes used with the parse or find functions. They are also commonly used for allocation maps and search hash markers. More information about bitsets, including details of changes from R2 to R3 can be found on the ''DocBase Bitsets'' page. * [[Creating bitsets]] ** Using MAKE ** Unicode ** The CHARSET helper * [[Bitset specification block]] ** Accepted datatypes ** Bit ranges ** Complement (not) bitsets ** Binaries as bits ** Examples * [[Supported actions]] * [[Using bitsets]] ** Examples of character bitsets ** Examples using integer bitsets ** Examples using path selection ** Bitsets for character classes ** Character casing * ''Modification'' ** Appending bits ** Removing bits ** Clearing all bits ** Complementing bitsets ** Logical operations ** Using set-path notation * ''Special notes'' ** Virtual length ** Binary conversion !!! ''Modification'' You can modify the bits specified by a bitset in a few ways. !!!! ''Appending bits'' You can add bits to a bitset with the append function: ``` spaces: make bitset! " " append spaces "^-^/" ``` The append function will also accept a bitset specification block: ``` letters: make bitset! [#"A" - #"Z"] append letters [#"a" - #"z"] ``` The insert function is synonymous with append. !!!! ''Removing bits'' You can remove bits from a bitset with the remove function. In order to specify the bits to be removed, the `/part` refinement is necessary. ``` spaces: make bitset! "^-^/ " remove/part spaces #" " ``` The remove function will also accept a bitset specification block: ``` letters: make bitset! [#"A" - #"Z" #"a" - #"z"] remove/part letters [#"a" - #"z"] ``` If `/part` is not given, an error will result: ``` remove spaces #" " ** Script error: missing a required argument or refinement ``` Also, note that remove only "unsets" bits, it does does not modify the size of the bitset. !!!! ''Clearing all bits'' The [[clear|Functions: clear]] function will clear all bits for a bitset: ``` bits: make bitset! "abc" clear bits append bits "d" probe bits make bitset! #{00000000000000000000000008} ``` Note that a complemented bitset remains complemented. The clear function does not reset the flag. !!!! ''Complementing bitsets'' As mentioned above, bitsets can be complemented. A complement provides the logical not of each bit. Complemented bitsets are nothing more than a normal bitset with a complement flag used to indicate that the bits are inverted. To create a complement bitset, use the complement function. It returns a new bitset with the complement flag set: ``` no-space: complement make bitset! #" " if find no-space "a" [print "not a space"] not a space ``` Other examples: ``` no-whitespace: complement make bitset! "^-^/ " no-ctrl-space: complement make bitset! [0 - #" "] ``` If you mold a complemented bitset, you will see a not indicator: ``` print mold no-space make bitset! [not bits #{0000000080}] ``` For more information, see the notes in the above sections. !!!! ''Logical operations'' You can use and, or, and xor to create new bitsets. For example: ``` b1: make bitset! "abc" b2: make bitset! "cdef" probe b1 or b2 make bitset! #{0000000000000000000000007E} ``` ``` probe b1 and b2 make bitset! #{00000000000000000000000010} ``` Note that the resultant bitset will always be minimized (trimmed): ``` b3: make bitset! [0 30 60] b4: make bitset! [0 1 2] probe b3 and b4 make bitset! #{80} ``` !!!! ''Using set-path notation'' Bitsets can also be modified using path notation. ``` bits: make bitset! "abc" bits/#"d": true bits/#"c": false bits/0: true ``` Variables can also be used: ``` s: "abc" bits/:s: false ``` !!! ''Special notes'' !!!! ''Virtual length'' You have always been able to define bitsets of any reasonable length, but now the length is more automatic: * Bitsets are only as long as needed. * Virtual bits outside physical range are valid. * Bitsets will auto expand if necessary. For example, in R2 if you created a bitset: ``` bits: make bitset! 160 ``` a 160 bit set would be created. However, if you wrote: ``` space: make bitset! " ^-^/" ``` a 256 bitset would be created (because it assumed you wanted an 8-bit character-based bitset). In R3, this is no longer true. A bitset is only as long as needed to hold its maximum bit value. The line: ``` space: make bitset! " ^-^/" ``` creates a 40 bit set that looks like this: ``` make bitset! #{0060000080} ``` The bitset is only as long as it needs to be. If you check for a bit outside its range, such a request is valid: ``` if find space "a" [print "found"] ``` In R2, this line would have caused an error, but it is fine in R3. All virtual bits are zero. In addition, a bitset will auto-extend as needed. For example: ``` append space ".:;" ``` will expand the space bitset to be: ``` make bitset! #{006000008002} ``` Again, it is only as long as needed to hold the largest bit. The above examples show only string bit values, but these rules apply to bitsets that are accessed with CHAR! and INTEGER! bit values as well. !!!! ''Binary conversion'' The binary representation for bitsets has changed compared to R2. It is now left-to-right bit continuous (as if bits were written in binary as big-endian values.) For example, in R3: ``` >> make bitset! "abcd" == make bitset! #{00000000000000000000000078} ``` but, in R2: ``` >> make bitset! "abcd" == make bitset! #{ 0000000000000000000000001E00000000000000000000000000000000000000 } ``` Also, complemented bitsets do not use complemented bitmasks. ``` >> to-binary complement make bitset! " " == #{0000000080} ``` For such conversions, the complement state is lost (similar to how width and height are lost for a conversion of an [[image!|Datatypes: Image!]] to [[binary!|Datatypes: Binary!]].) If you want to preserve that information, you must use [[mold|Functions: mold]].
''Contents'' * Concept * Format * Creation * Related !!! ''Concept'' Blocks are groups of values and words. Blocks are used everywhere, from a script itself to blocks of data and code provided in a script. Block values are indicated by opening and closing square brackets `[ ]` with any amount of data contained between them. ``` [123 data "hi"] ; block with data [] ; empty block ``` Blocks can hold records of information: ``` woodsmen: [ "Paul" "Bunyan" paul@bunyan.dom "Grizzly" "Adams" grizzly@adams.dom "Davy" "Crocket" davy@crocket.dom ] ``` Blocks can contain code: ``` [print "this is a segment of code"] ``` Blocks are a type of series and thus anything that can be done with a series can be done with a block value. Blocks can be searched: ``` probe copy/part (find woodsmen "Grizzly") 3 [ "Grizzly" "Adams" grizzly@adams.dom] ``` Blocks can be modified: ``` append woodsmen [ "John" "Muir" john@muir.dom ] probe woodsmen [ "Paul" "Bunyan" paul@bunyan.dom "Grizzly" "Adams" grizzly@adams.dom "Davy" "Crocket" davy@crocket.dom "John" "Muir" john@muir.dom ] ``` Blocks can be evaluated: ``` blk: [print "data in a block"] do blk data in a block ``` Blocks can contain blocks: ``` blks: [ [print "block one"] [print "block two"] [print "block three"] ] foreach blk blks [do blk] block one block two block three ``` !!! ''Format'' Blocks can contain any number of values or no values at all. They can extend over multiple lines and can include any type of value, including other blocks. An empty block: ``` [ ] ``` A block of integers: ``` [24 37 108] ``` A REBOL header: ``` REBOL [ Title: "Test Script" Date: 31-Dec-1998 Author: "Ima User" ] ``` The condition and evaluation block of a function: ``` while [time < 10:00] [ print time time: time + 0:10 ] ``` Words in a block need not be defined: ``` blk: [undefined words in a block] probe value? pick blk 1 false ``` Blocks allow any number of lines, spaces, or tabs. Lines and spaces can be placed anywhere within the block, so long as they do not divide a single value. !!! ''Creation'' The to-block function converts data to the `block!` datatype: ``` probe to-block luke@rebol.com [luke@rebol.com] ``` ``` probe to-block {123 10:30 "string" luke@rebol.com} [123 10:30 "string" luke@rebol.com] ``` !!! ''Related'' Use [[block?|Functions: block?]] to determine whether a value is an `block!` datatype. ``` probe block? [123 10:30] true ``` As blocks are a subset of the `series!` typeset, use [[series?|Functions: series?]] to check this: ``` probe series? [123 10:30] true ``` Using [[form|Functions: form]] on a block value creates a string from the contents contained in the block: ``` probe form [123 10:30] 123 10:30 ``` Using [[mold|Functions: mold]] on a block value creates a string from the block value and it's contents, thus allowing it to be reloaded as a REBOL block value: ``` probe mold [123 10:30] [123 10:30] ```
This datatype has not yet been documented for R3. !!! ''Contents'' * Concept * Format * Creation * Related !!! ''Concept'' Characters are not strings; they are the individual values from which strings are constructed. A character can be printable, unprintable, or a control symbol. !!! ''Format'' A `char!` value is written as a number sign (#) followed by a string enclosed in double quotes. The number sign is necessary to distinguish a character from a string: ``` #"R" ; the single character: R "R" ; a string with the character: R ``` Characters can include escape sequences that begin with a caret(^)and are followed by one or more characters of encoding. This encoding can include the characters #"^A'" to #"^Z'" for `control A` to `control Z` (upper and lower case are the same): ``` #"^A" #"^Z" ``` In addition, if parens are used within the character, they specify a special value. For example, null can be written as: ``` "^@" "^(null)" "^(00)" ``` The last line is written in hex format (base 16). Up to 4 hex digits can be provided, to cover all 16 bit Unicode characters (code-points). Following is a table of control characters that can be used in REBOL. |''Character'' |''Definition''|h |`#"^(null)"` or `#"^@"` |null (zero)| |`#"^(line)",` or `#"^/"` |new line| |`#"^(tab)"` or `#"^-"` |horizontal tab| |`#"^(page)"` |new page (and page eject)| |`#"^(esc)"` |escape| |`#"^(back)"` |backspace| |`#"^(del)"` |delete| |`#"^^"` |caret character| |`#"^""` |quotation mark| |`#"(0)" to #"(FFFF)"` |hex forms of characters| !!! ''Creation'' Characters can be converted to and from other datatypes with the to-char function: ``` probe to-char "a" #"a" ``` ``` probe to-char "z" #"z" ``` Characters follow the ASCII standard and can be constructed by specifying a character's numeric equivalent: ``` probe to-char 65 #"A" ``` ``` probe to-char 52 #"4" ``` ``` probe to-char 52.3 #"4" ``` Another method of obtaining a character is to get the first character from a string: ``` probe first "ABC" #"A" ``` While characters in strings are not case sensitive, comparison between individual characters is case sensitive: ``` probe "a" = "A" true ``` ``` probe #"a" = #"A" false ``` However, when used in many types of functions, the comparison is not case sensitive unless you specify that option. Examples are: ``` select [#"A" 1] #"a" 1 ``` ``` select/case [#"A" 1] #"a" none ``` ``` find "abcde" #"B" "bcde" ``` ``` find/case "abcde" #"B" none ``` ``` switch #"A" [#"a" [print true]] true ``` !!! ''Related'' Use [[char?|Functions: char?]] to determine whether a value is a `char!` datatype. ``` probe char? "a" false ``` ``` probe char? #"a" true ``` Use the form function to print a character without the number sign: ``` probe form #"A" "A" ``` Use mold on to print a character with the number sign and double quotes (and escape sequences for those characters that require it.): ``` probe mold #"A" {#"A"} ```
A `closure!` is a special type of function that has persistent local variables (indefinite extent). ''Concept'' Normally, a function takes a set of arguments, computes with them, then returns a result. There are several types of functions, depending on how they are implemented. The most common function type is function!, and they are created with code such as: ``` add2: func [a b] [a + b] ``` These functions are efficient and work well for most code. But note, the variables (a and b) of the function are valid only within the body of the function. If you try to use those variables outside of the function, an error will occur. For example, this case returns a block that contains the variables. If after the function returns, you try to access (in this case DO) the variables, you get into trouble: ``` >> add2: func [c d] [[c + d]] >> do add2 1 2 ** Script error: c word is not bound to a context ``` This happens because the variables are locally bound (locally scoped) to the function. They only have values for the period of time during which the function is evaluating. They have no meaning outside the function. A closure! function solves this problem. With a closure you can write: ``` >> add2: closure [c d] [[c + d]] >> do add2 1 2 == 3 ``` This works because the variables of a closure remain valid, even outside the closure after it has been called. Such variables have ''indefinite extent''. They are not limited to the lifetime of the function. Note, however, that the luxury provided by closures is not without its costs. Closures require more time to evaluate as well as more memory space. ''More detail'' In essence a closure is an object. When you define the closure, it constructs a prototype object, and each time you call the closure, the prototype object is instantiated and the body code is evaluated within that context. Here is another usage example: ``` >> make-adder: closure[x] [func [y] [x + y]] == closure! >> add-10: make-adder 10 == function! >> add-2: make-adder 2 == function! >> add-10 5 == 15 >> add-2 3 == 5 ``` ''Editor note: Add more on:'' closure mezzanine function closure? and any-function? USE implemented as closure actions that work on the closure datatype passing closures as values [[More about function closures|http://en.wikipedia.org/wiki/Closure_(computer_science)]]
A `command!` is a type of native external function used by extensions. ''Concept'' ''Editor note: details go here''
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' type of datatype ''Format'' ''Creation''
''Contents'' * Concept * Format * Access * Creation * Disabling timezone or using UTC * Related !!! ''Concept'' Around the world, dates are written in a variety of formats. However, most countries use the `day-month-year` format. One of the few exceptions is the United States, which commonly uses a month-day-year format. For example, a date written numerically as 2/1/1999 is ambiguous. The month could be interpreted as either February or January. Some countries use a dash (-), some use a forward slash (/), and others use a period (.) as a separator. Finally, computer people often prefer dates in the year-month-day (ISO) format so they can be easily sorted. !!! ''Format'' The REBOL language is flexible, allowing date! datatypes to be expressed in a variety of formats. For example, the first day of March can be expressed in any of the following formats: ``` probe 1/3/1999 1-Mar-1999 ``` ``` probe 1-3-1999 1-Mar-1999 ``` `probe 1999-3-1 ;ISO format 1-Mar-1999` The year can span up to 9999 and down to 1. Leap days (February 29) can only be written for leap years: ``` probe 29-2-2000 29-Feb-2000 ``` The fields of dates can be separated with forward slashes (/) or dashes (-). Dates can be written in either a year-month-day format or a day-month-year format: ``` probe 1999-10-5 5-Oct-1999 ``` ``` probe 1999/10/5 5-Oct-1999 ``` ``` probe 5-10-1999 5-Oct-1999 ``` ``` probe 5/10/1999 5-Oct-1999 ``` Because the international date formats that are not widely used in the USA, a month name or month abbreviation can also be used: ``` probe 5/Oct/1999 5-Oct-1999 ``` ``` probe 5-October-1999 5-Oct-1999 ``` ``` probe 1999/oct/5 5-Oct-1999 ``` When the year is the last field, it can be written as either a four digit or two digit number: ``` probe 5/oct/99 5-Oct-1999` ``` ``` probe 5/oct/1999 5-Oct-1999 ``` However, it is preferred to write the year in full. Otherwise, problems occur with date comparison and sorting operations. While two digits can be used to express a year, the interpretation of a two-digit year is relative to the current year and is only valid for 50 years in the future or in the past: ``` probe 28-2-66 ; refers to 1966 28-Feb-1966 ``` ``` probe 12-Mar-20 ; refers to 2020 12-Mar-2020 ``` ``` probe 11==45 ; refers to 2045, not 1945 11-Mar-2045 ``` It is recommended to use a four-digit year to avoid potential problems. To represent dates in the first century (which is rarely done because the Gregorian calendar did not exist), use leading zeros to represent the century (as in 9-4-0029). Dates can also include an optional time field and an optional time zone. The time is separated from the date with a forward slash (/). The time zone is appended using a plus (+) or minus (-), and no spaces are allowed. Time zones are written as a time shift (plus or minus) from GMT. The resolution of the time zone is to the half hour. If the time shift is an integer, it is assumed to be hours: `probe 4/Apr/2000/6:00+8:00 4-Apr-2000/6:00+8:00` ``` probe 1999-10-2/2:00-4:00 2-Oct-1999/2:00-4:00 ``` ``` probe 1/1/1990/12:20:25-6 1-Jan-1990/12:20:25 ``` There can be no spaces within the date. For example: `10 - 5 - 99` would be interpreted as a subtraction expression, not a date. !!! ''Access'' Refinements can be used with a date value to get any of its defined fields: |''Refinement'' |''Description''|h |`/day` |Gets the day.| |`/month` |Gets the month.| |`/year` |Gets the year.| |`/yearday` |Gets the day of the year.| |`/weekday` |Gets the weekday (1 for Mon, 7 for Sun).| |`/time` |Gets the time (if present).| |`/hour` |Gets the time's hour (if present)| |`/minute` |Gets the time's minute (if present).| |`/second` |Gets the time's second (if present).| |`/zone` |Gets the time zone (if present).| |`/utc` |Returns the UTC (universal) time.| Here's how these refinements work: ``` some-date: 29-Feb-2000 probe some-date/day 29 ``` ``` probe some-date/month 2 ``` ``` probe some-date/year 2000 ``` ``` days: ["Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"] probe pick days some-date/weekday Tue ``` When a time is present, the time related refinements can be used. The `/hour`, `/minute` and `/second` refinements are used with the /time refinement that isolates the time segment of the date value for them to work on, but they can also be used alone: ``` lost-time: 29-Feb-2000/11:33:22.14-8:00 probe lost-time/time 11:33:22.14 ``` ``` probe lost-time/time/hour 11 ``` ``` probe lost-time/hour 11 ``` ``` probe lost-time/minute 33 ``` ``` probe lost-time/second 22.14 ``` ``` probe lost-time/zone -8:00 ``` Note that dates are normalized when any field of their time values is set. The date will be adjusted accordingly to make the time a valid 24 hour value. ``` print d: now 23-Oct-2009/3:34:45-4:00 ``` ``` d/time: 50:00 print d 25-Oct-2009/2:00-4:00 ``` !!! ''Creation'' Use the [[to-date|Functions: to-date]] function to convert values to a `date!`: ``` probe to-date "5-10-1999" 5-Oct-1999 ``` ``` probe to-date "5 10 1999 10:30" 5-Oct-1999/10:30 ``` ``` probe to-date [1999 10 5] 5-Oct-1999 ``` ``` probe to-date [5 10 1999 10:30 -8:00] 5-Oct-1999/10:30-8:00 ``` [!Note When converting to a date!, the year must be specified as four digits. Conversions can be applied to various math operations on dates: ``` probe 5-Oct-1999 + 1 6-Oct-1999 ``` ``` probe 5-10-1999 - 10 25-Sep-1999 ``` ``` probe 5-Oct-1999/23:00 + 5:00 6-Oct-1999/4:00 ``` !!! ''Disabling timezone or using UTC'' To disable the timezone, just set it to [[none!|Datatypes: None!]] : ``` date/zone: none ``` However, since this normally indicates a UTC datestamp, it is better to use the `/utc` refinement. You can write: ``` date: date/utc ``` For example: ``` date: now 19-Sep-2009/20:04:26-7:00 ``` ``` date: date/utc 20-Sep-2009/3:04:26 ``` Note that the timezone is gone. A REBOL 2 compatible way to do this is: ``` date: now 19-Sep-2009/20:04:26-7:00 ``` ``` date: date - date/zone 20-Sep-2009/3:04:26-7:00 ``` ``` date/zone: none none ``` ``` date 20-Sep-2009/3:04:26 ``` !!! ''Related'' Use [[date?|Functions: date?]] to determine whether a value is a `date!` datatype. ``` probe date? 5/1/1999 true ``` The related function `[bad-link:functions/to-idate.txt]` returns a standard Internet date string. The Internet date format is day, date, month, year, time (24-hour clock), and time zone offset from GMT. ``` probe to-idate now Fri, 30 Jun 2000 14:42:26 -0700 ``` The now function returns the current date and time in full format including the time zone offset: ``` probe now 30-Jun-2000/14:42:26-7:00 ```
''Contents'' * Concept * Format * Creation * Related !!! ''Concept'' The `decimal!` datatype is based on 64-bit standard IEEE 754 binary floating point numbers. They are distinguished from integer numbers by a decimal point (a period or a comma is allowed for international usage, see the notes below). !!! ''Format'' Decimal values are a sequence of numeric digits, followed by a decimal point, which can be a period (.) or a comma (,), followed by more digits. A plus (+) or minus (-) immediately before the first digit indicates sign. Leading zeros before the decimal point are ignored. Extra spaces, commas, and periods are not allowed. ``` 1.23 123. 123.0 0.321 0.123 1234.5678 ``` A comma can be used in place of a period to represent the decimal point (which is the standard in many countries): ``` 1,23 0,321 1234,5678 ``` Use a single quote `'` to separate the digits in long decimals. Single quotes can appear anywhere after the first digit in the number, but not before the first digit. ``` 100'234'562.3782 100'234'562,3782 ``` Do not use commas or periods to separate the digits in a decimal value. Scientific notation can be used to specify the exponent of a number by appending the number with the letter E or e followed by a sequence of digits. The exponent can be a positive or negative number. ``` 1.23E10 1.2e007 123.45e-42 56,72E300 -0,34e-12 0.0001e-001 ``` Decimal numbers span from 2.2250738585072e-308 up to 1.7976931348623e+308 and can contain up to 15 digits of precision. !!! ''Creation'' Use the [[to-decimal|Functions: to-decimal]] function to convert [[string!|Datatypes: String!]], [[integer!|Datatypes: Integer!]], [[block!|Datatypes: Block!]], or `decimal!` datatypes to a decimal number: ``` probe to-decimal "123.45" 123.45 ``` ``` probe to-decimal 123 123 ``` ``` probe to-decimal [-123 45] -1.23E+47 ``` ``` probe to-decimal [123 -45] 1.23E-43 ``` ``` probe to-decimal -123.8 -123.8 ``` ``` probe to-decimal 12.3 12.3 ``` If a decimal and integer are combined in an expression, the integer is converted to a decimal number: ``` probe 1.2 + 2 3.2 ``` ``` probe 2 + 1.2 3.2 ``` ``` probe 1.01 > 1 true ``` ``` probe 1 > 1.01 false ``` !!! ''Related'' Use [[decimal?|Functions: decimal?]] to determine whether a value is an `decimal!` datatype. ``` print decimal? 0.123 true ``` Use the [[form|Functions: form]], [[print|Functions: print]], and [[mold|Functions: mold]] functions with a decimal argument to print a decimal value in its simplest form: * integer. If it can be represented as one. * decimal without exponent. If it's not too big or too small. * scientific notation. If it's too big or small. For example, ``` probe mold 123.4 123.4 ``` ``` probe form 2222222222222222 2.22222222222222E+15 ``` ``` print 1.00001E+5 100001 ``` Single quotes `'` and a leading plus sign `+` do not appear in decimal output: ``` print +1'100'200.222'112 1100200.222112 ```
''Contents'' * Concept * Format * Access * Creation * Related !!! ''Concept'' An email address is a datatype. The `email!` datatype allows for easy expression of email addresses: ``` send luke@rebol.com {some message} emails: [ john@keats.dom lord@byron.dom edger@guest.dom alfred@tennyson.dom ] ``` ``` mesg: {poetry reading at 8:00pm!} foreach email emails [send email mesg] ``` Email is also one of the [[series|Concepts: Series]] datatypes, so the same rules that apply to series apply to emails: ``` probe head change/part jane@doe.dom "john" 4 john@doe.dom ``` !!! ''Format'' The standard format of an email address is a name, followed by an at sign (@), followed by a domain. An email address can be of any length, but must not include any of restricted characters, such as square brackets, quotes, braces, spaces, newlines, etc.. The following email! datatype formats are valid: ``` info@rebol.com 123@number-mail.org my-name.here@an.example-domain.com ``` Upper and lower cases are preserved in email addresses. !!! ''Access'' Refinements can be used with an email value to get the user name or domain. The refinements are: * `'/user` - Get the user name. * `'/host` - Get the domain. Here's how these refinements work: ``` email: luke@rebol.com probe email/user luke ``` ``` probe email/host rebol.com ``` !!! ''Creation'' The [[to-email|Functions: to-email]] function converts data to the `email!` datatype: ``` probe to-email "info@rebol.com" info@rebol.com ``` ``` probe to-email [info rebol.com] info@rebol.com ``` ``` probe to-email [info rebol com] info@rebol.com ``` ``` probe to-email [user some long domain name out there dom] user@some.long.domain.name.out.there.dom ``` !!! ''Related'' Use [[email?|Functions: email?]] to determine whether a value is an `email!` datatype. ``` probe email? luke@rebol.com true ``` As emails are part of the series! typeset, use series? to determine whether the value is a series: ``` probe series? luke@rebol.com true ``` ``` probe pick luke@rebol.com 5 #"@" ```
''Concept'' This is a'' special internal datatype that should never appear in user code''. It is a marker used for end-of-block.
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' errors and throws ''Format'' ''Creation''
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' user interface event (efficiently sized) ''Format'' ''Creation''
''Contents'' * Concept * Format * Creation * Related !!! ''Concept'' The `file!` datatype can be a file name, directory name, or directory path. ``` %file.txt %directory/ %directory/path/to/some/file.txt ``` File values are a subset of series, and thus can be manipulated as a series: ``` probe find %dir/path1/path2/file.txt "path2" %path2/file.txt ``` ``` f: %dir/path/file.txt probe head remove/part (find f "path/") (length? "path/") %dir/file.txt ``` !!! ''Format'' Files are designated with a percent sign `%` followed by a sequence of characters: ``` load %image.jpg prog: load %examples.r save %this-file.txt "This file has few words." files: load %../programs/ ``` Unusual characters in file names must be encoded with a `%` hexadecimal number, which is an Internet convention. A file name with a space (hexadecimal 20) would look like: ``` probe %cool%20movie%20clip.mpg %cool%20movie%20clip.mpg ``` ``` print %cool%20movie%20clip.mpg cool movie clip.mpg ``` Another format is to enclose the file name in quotes: ``` probe %"cool movie clip.mpg" %cool%20movie%20clip.mpg ``` ``` print %"cool movie clip.mpg" cool movie clip.mpg ``` The standard character for separating directories in a path is the forward slash `/`, not the backslash `\`. However, the REBOL language automatically converts backslashes found in file names to forward slashes: ``` probe %\some\path\to\some\where\movieclip.mpg %/some/path/to/some/where/movieclip.mpg ``` !!! ''Creation'' The [[to-file|Functions: to-file]] function converts data to the `file!` datatype: ``` probe to-file "testfile" %testfile ``` When passed a block, elements in the block are concatenated into a file path with the final element used as the file name: ``` probe to-file [some path to a file the-file.txt] %some/path/to/a/file/the-file.txt ``` !!! ''Related'' Use [[file?|Functions: file?]] to determine whether a value is an `file!` datatype. ``` probe file? %rebol.r true ``` As files are a subset of the series! pseudotype, use [[series?|Functions: series?]] to check this: ``` probe series? %rebol.r true ```
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' internal context frame ''Format'' ''Creation''
''Contents'' * Concept * Format * Creation !!! ''Concept'' The REBOL language contains a few different types of functions, including [[native!|Datatypes: Native!]], [[action!|Datatypes: Action!]], `function!`, and [[closure!|Datatypes: Closure!]]. The main thing that makes them different is how they are evaluated. The `function!` datatype is a higher level function that is interpreted. They are also called ''user-defined'' functions, and system functions defined this way are called ''mezzanine'' functions. !!! ''Format'' Functions consist of a specification and a body block. The specification part provides the interface specification and any embedded documentation. The body is the code of the function. The formal definition of function is: ``` make function! [[specs] [body]] ``` (However, functions are normally created using helper functions. See below.) <<< Changed from R2 Note that this format changed from REBOL V2. This change was necessary because make accepts only two arguments. Therefore, the second argument contains the specs block and the body block. <<< The function specs block holds: |''arguments'' |the arguments passed to the function.| |''datatypes'' |optional datatype specifications for each argument.| |''refinements'' |optional variations in the behavior and arguments of a function.| |''doc strings'' |embedded documentation for the function and its arguments.| For every argument it is possible to define how the argument is passed to the function using one of the formats: |''Notation'' |''Meaning''|h |`word` |The argument expression is evaluated before it is passed to the function.| |`'word` |The argument expression is evaluated only if it starts with a get-word! or a paren!.| |`:word` |The argument expression is not evaluated. The very next value is used.| |`word:` |Reserved. Used to define variations.| !!! ''Creation'' Normally, you create a function! using a helper function. There are a few choices: |[[func|Functions: func]] |Is the most common function defining function.| |[[funct|Functions: funct]] |Is similar to func, but by default makes internal variables locals.| |[[has|Functions: has]] |Is for creating functions that have no formal arguments, only local variables.| |[[does|Functions: does]] |Is for creating functions that have no variables at all.| More about functions is found in [[code: defining functions|Guide: Code: Defining functions]].
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' the value of a path ''Format'' ''Creation''
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' the value of a word (variable) ''Format'' ''Creation''
''Concept'' A GOB is a low-level graphical object. GOBs are used for for constructing windows, panels, images, text, and drawings. They support two dimensional compositing with transparency (alpha channel), scalar vector graphics, image effects, and rich-text. A GOB is a highly optimized native datatype. It has been designed to provide the primary features required for graphics, but substantially reduce the memory footprint and processing overhead required. As a result, complex displays, such as animations, simulations, or video games can be created that are composed of thousands of individual GOB elements. Full details about GOBs can be found on the [[R3 View - Graphical Objects|View - Graphical Objects]] page.
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' arbitrary internal object or value ''Format'' ''Creation''
''Concept'' This REBOL 2 datatype has not been implemented in REBOL 3. A request to re-introduce it has been made in [[Curecode|http://curecode.org/rebol3/ticket.rsp?id=1494]]
''Contents'' * Concept * Format * Creation * Related ''Concept'' The `image!` datatype is a series that holds RGBA images. This datatype is used with REBOL/View. The external image formats supported are GIF, JPEG, PNG and BMP. The loaded image can be manipulated as a series. ''Format'' Images are normally loaded from a file. However, they can be expressed in source code as well by making an image. The block provided includes the image size and its RGBA data. ``` image: make image! [192x144 #{ B34533B44634B44634B54735B7473 84836B84836B84836BA4837BA4837 BC4837BC4837BC4837BC4837BC483 ... } ``` ''Creation'' Empty images can be created using [[make|Functions: make]] or [[to-image|Functions: to-image]]: ``` empty-img: make image! 300x300 empty-img: to-image 150x300 ``` The size of the image is provided. Images can also be made from snapshots of a face object. This is also done using [[make|Functions: make]] or to-image: ``` face-shot: make image! face face-shot: to-image face ``` Use [[load|Functions: load]] to load an image file. If the image's format is not supported, it will fail to load. Loading an image: ``` img: load %bay.jpg ``` ''Related'' Use [[image?|Functions: image?]] to determine whether a value is the `image!` datatype: ``` probe image? img ``` Images are included in the series! typeset: ``` probe series? img ``` Use the `/size` refinement to return the pixel size of an image as a pair value: ``` probe img/size ``` Use the `/rgb` and `/alpha` refinements to get the RGB and A component separately as binary values. ``` probe img/rgb probe img/alpha ``` The pixel values of an image are obtained using pick and changed using [[poke|Functions: poke]]. The value returned by [[pick|Functions: pick]] is an RGBA tuple value. The value replaced with poke also should be a tuple value of length 4. Picking specific pixels: ``` probe pick img 1 probe pick img 1500 ``` Poking specific pixels: ``` poke img 1 255.255.255.0 probe pick img 1 poke img 1500 0.0.0.0 probe pick img 1500 ```
''Contents'' * * Concept * Format * Conversion * Type Coercion * Related ''Concept'' In R3 the `integer!` datatype has been expanded to be a 64-bit value. It ranges from: ``` Minimum: -9223372036854775808 Maximum: 9223372036854775807 ``` ''Format'' Integer values consist of a sequence of numeric digits. A plus (+) or minus (-) immediately before the first digit indicates sign. (There cannot be a space between the sign and the first digit.) Leading zeros are ignored. ``` 0 1234 +1234 -1234 00012 -0123 ``` Do not use commas or periods in integers. If a comma or period is found within an integer it is interpreted as a decimal value. However, you can use a single quote `'` to separate the digits in long integers. Single quotes can appear anywhere after the first digit in the number, but not before the first digit. ``` 2'147'483'647 ``` ''Conversion'' Use the to function can convert a [[string!|Datatypes: String!]], [[logic!|Datatypes: Logic!]], [[decimal!|Datatypes: Decimal!]], or `integer!` datatype to an integer: ``` to integer! "123" 123 ``` ``` to integer! false 0 ``` ``` to integer! true 1 ``` Conversion from [[decimal!|Datatypes: Decimal!]] will be truncated towards zero: ``` to integer! 123.8 123 ``` ``` to integer! -123.8 -123 ``` Use the round function if you desire some other behavior. To convert a [[binary!|Datatypes: Binary!]] to an `integer!` value: ``` to integer! #{1000} 4096 ``` Note that the conversion treats the string in network-byte-order (big-endian) and it is not sign extended: ``` to integer! #{8000} 32768 ``` To convert from an `integer!` to a [[binary!|Datatypes: Binary!]] (in network-byte-order): ``` to binary! 32768 #{0000000000008000} ``` Note that the full hex bit pattern (8 bytes) is output. As expected, negative values will set the first bit: ``` to binary! -1 #{FFFFFFFFFFFFFFFF} ``` As a convenience for HTML color values, conversions from [[issue!|Datatypes: Issue!]] values are also allowed: ``` to integer! #8855DD 8934877 ``` Note that to obtain the individual RGB color values, you might want to use a [[tuple!|Datatypes: Tuple!]] value instead: ``` rgb: to tuple! #8855DD 136.85.221 ``` ``` rgb/2 85 ``` <<< Special Note Note that for RGB values the above hex conversion is not reversible. That's because the intended use of the integer is not known (to be an RGB value.) However, you can define your own function for this conversion: ``` to-rgb-str: func [n] [take/last/part to-hex n 6] ``` This method is preferred because it does not depend on the zero padding at the head of the string, making it work for 32-bit versions of REBOL as well. Here's an example: ``` to-rgb-str to integer! #A8446C #A8446C ``` <<< ''Type Coercion'' If a decimal and integer are combined in an expression, the integer is converted to a decimal: ``` 1.2 + 2 3.2 ``` ``` 2 + 1.2 3.2 ``` ``` 1.01 > 1 true ``` ``` 0 < .001 true ``` ''Related'' Use [[integer?|Functions: integer?]] to determine whether a value is an `integer!` datatype. ``` integer? -1234 true ``` Use the [[form|Functions: form]], [[print|Functions: print]], and [[mold|Functions: mold]] functions with an integer argument to print a integer value as a string: ``` mold 123 123 ``` ``` form 123 123 ``` ``` print 123 123 ```
<<< As of alpha 106, `issue!` is part of `any-word!`. The description below is now obsolete and needs to be updated. <<< ''Contents'' * Concept * Format * Creation * Related ''Concept'' An `issue!` is a series of characters used to sequence symbols or identifiers for things like telephone numbers, model numbers, serial numbers, and credit card numbers. Issue values are a subset of series, and thus can be manipulated as series: ``` probe copy/part find #888-555-1212 "555" 3 #555 ``` ''Format'' Issues start with a number sign (#) and continue until the first delimiting character (such as a space) is reached. ``` #707-467-8000 #A-0987654321-CD-09876 #1234-5678-4321-8765 #MG82/32-7 ``` Values that contain delimiting characters should be written as strings rather than issues. ''Creation'' The [[to-issue|Functions: to-issue]] function converts data to the `issue!` datatype: ``` probe to-issue "1234-56-7890" #1234-56-7890 ``` ''Related'' Use [[issue?|Functions: issue?]] to determine whether a value is an issue! datatype. ``` probe issue? #1234-56-7890 true ``` As issues are a subset of the series pseudotype, use [[series?|Functions: series?]] to check this: ``` probe series? #1234-56-7890 true ``` The [[form|Functions: form]] function returns an issue as a string without the number sign (#): ``` probe form #1234-56-7890 1234-56-7890 ``` The [[mold|Functions: mold]] function returns an issue as a string that can be read by REBOL as an issue value: ``` probe mold #1234-56-7890 #1234-56-7890 ``` The [[print|Functions: print]] function prints an issue to standard output after doing a reform on it: ``` print #1234-56-7890 1234-56-7890 ```
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' external library reference ''Format'' ''Creation''
''Concept'' This REBOL 2 datatype has not been implemented in REBOL 3.
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' literal path value ''Format'' ''Creation''
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' literal word value ''Format'' ''Creation''
''Contents'' * Concept * Format * Creation * Related ''Concept'' The `logic!` datatype consists of two states representing `true` and `false`. They are often returned from comparisons such as: ``` age: 100 probe age = 100 true ``` ``` time: 10:31:00 probe time < 10:30 false ``` ``` str: "this is a string" probe (length? str) > 10 true ``` The `logic!` datatype is most commonly used as parameters to conditional functions such as [[if|Functions: if]], [[while|Functions: while]], and `until`: ``` if age = 100 [print "Centennial human"] Centennial human ``` ``` while [time > 6:30] [ send person "Wake up!" wait [0:10] ] ``` The complement of a logic value is obtained from the [[not|Functions: not]] function: ``` there: place = "Ukiah" if not there [...] ``` ''Format'' Normally, logic values are retrieved from the evaluation of comparison expressions. However, words can be set to a logic value and used to turn the word `on` or` off`: ``` print-me: false print either print-me ["turned on"]["turned off"] turned off ``` ``` print-me: true print either print-me ["turned on"]["turned off"] turned on ``` The `false` value is not equivalent to integer zero or [[none!|Datatypes: None!]]. However, in conditional expressions `false` and [[none!|Datatypes: None!]] have the same effect: `print-me: none print either print-me ["turned on"]["turned off"] turned off` Just about any value assigned to a word has the same effect as `true`: `print-me: "just a string" print either print-me ["turned on"]["turned off"] turned on` ``` print-me: 11-11-1999 print either print-me ["turned on"]["turned off"] turned on ``` The following words are predefined to hold logic values: ``` true on ;same as true yes ;same as true false off ;same as false no ;same as false ``` So, instead of `true` and `false`, when it makes sense, the words `on` and `off`, or yes and `no` can be used instead: ``` print-me: yes print either print-me ["turned on"]["turned off"] turned on ``` ``` print-me: no print either print-me ["turned on"]["turned off"] turned off ``` ``` print-me: on print either print-me ["turned on"]["turned off"] turned on ``` ``` print-me: off print either print-me ["turned on"]["turned off"] turned off ``` ''Creation'' The [[to-logic|Functions: to-logic]] function converts [[integer!|Datatypes: Integer!]] or [[none!|Datatypes: None!]] values to the `logic!` datatype: ``` probe to-logic 0 false ``` ``` probe to-logic 200 true ``` ``` probe to-logic none false ``` ``` probe to-logic [] true ``` ``` probe to-logic "a" true ``` ``` probe to-logic none false ``` ''Related'' Use [[logic?|Functions: logic?]] to determine whether a value is a `logic!` datatype. ``` probe logic? 1 false ``` ``` probe logic? on true ``` ``` probe logic? false true ``` Use the functions [[form|Functions: form]], [[print|Functions: print]], and [[mold|Functions: mold]] to print a logic value: ``` probe form true true ``` ``` probe mold false false ``` ``` print true true ```
This datatype has not yet been documented for R3. ''Contents'' <<< Concept Format Creation <<< ''Concept'' name-value pairs (hash associative) <<< Size Limit Currently, maps are limited to 2^26 - 1 (67'108'863) entries. <<< ''Format'' ''Creation''
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' loadable context of code and data ''Format'' ''Creation''
''Contents'' * Concept * Format * Creation * Related ''Concept'' There is a wide variety of international symbols for monetary denominations. Some symbols are used before the amount and some after. As a standard for representing international monetary values, the REBOL language uses the United States monetary format, but allows the inclusion of specific denominations. ''Format'' The money! datatype uses standard IEEE floating point numbers allowing up to 15 digits of precision including cents. The language limits the length to 64 characters. Values that are out of range or cannot be represented in 64 characters are flagged as an error. Monetary values are prefixed with an optional currency designator, followed by a dollar sign ($). A plus (+) or minus (-) can appear immediately before the first character (currency designator or dollar sign) to indicate sign. ``` $123 -$123 $123.45 US$12 US$12.34 -US$12.34 $12,34 -$12,34 DEM$12,34 ``` To break long numbers into readable segments, a single quote `'` can be placed anywhere between two digits within the amount, but not before the amount. ``` probe $1'234.56 $1234.56 ``` ``` probe $1'234'567,89 $1234567.89 ``` Do not use commas and periods to break up large amounts, as both these characters represent decimal points. 'The `money!` datatype is a hybrid datatype. Conceptually money is scalar--an amount of money. However, because the currency designation is stored as a string, the money! datatype has two elements: * 'string! - The currency designator string, which can have 3 characters maximum. * 'decimal! - The money amount. To demonstrate this, the following money is specified with the USD prefix: ``` my-money: USD$12345.67 ``` Here are the two components: ``` probe first my-money USD ``` ``` probe second my-money 12345.67 ``` ``` probe pick my-money 3 ; only two components none ``` If no currency designator is used, the currency designator string is empty: ``` my-money: $12345.67 probe first my-money "" ``` ``` probe second my-money 12345.67 ``` Various international currencies can be specified in the currency designator, such as: ``` my-money: DKM$12'345,67 probe first my-money DKM ``` ``` probe second my-money 12345.67 ``` ''Creation'' Use the [[to-money|Functions: to-money]] function to convert money from a [[string!|Datatypes: String!]], [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], or [[block!|Datatypes: Block!]]. ``` probe to-money 123 $123.00 ``` ``` probe to-money "123" $123.00 ``` ``` probe to-money 12.34 $12.34 ``` ``` probe to-money [DEM 12.34] DEM$12.34 ``` ``` probe to-money [USA 12 34] USA$12.34 ``` Money can be added, subtracted, and compared with other money of the same currency. An error occurs if a different currency is used for such operations (automatic conversions are not currently supplied). ``` probe $100 + $10 $110.00 ``` ``` probe $100 - $50 $50.00 ``` ``` probe equal? DEM$100.11 DEM$100.11 true ``` Money can be multiplied and divided by integers and decimals. Money can also be divided by money, resulting in an integer or decimal. ``` probe $100 + 11 $111.00 ``` ``` probe $100 / 4 $25.00 ``` ``` probe $100 * 5 $500.00 ``` ``` probe $100 - 20.50 $79.50 ``` ``` probe 10 + $1.20 $11.20 ``` ``` probe 10 - $0.25 $9.75 ``` ``` probe $10 / .50 $20.00 ``` ``` probe 10 * $0.75 $7.50 ``` ''Related'' Use [[money?|Functions: money?]] to determine whether a value is an `money!` datatype. probe money? USD$12.34 true Use the [[form|Functions: form]], [[print|Functions: print]], and [[mold|Functions: mold]] functions with a money argument to print a money value with the currency designator and dollar sign ($), as a decimal number with two digits of decimal precision. ``` probe form USD$12.34 USD$12.34 ``` ``` probe mold USD$12.34 USD$12.34 ``` ``` print USD$12.34 USD$12.34 ```
This datatype has not yet been documented for R3. !!! ''Contents'' * Concept * Format * Creation !!! ''Concept'' direct CPU evaluated function !!! ''Format'' !!! ''Creation''
''Contents'' * Concept * Format * Creation * Related ''Concept'' The `none!` datatype contains a single value that represents nothing or no value. The concept of none is not the same as an empty block, empty string, or null character. It is an actual value that represents non-existence. A `none!` value can be returned from various functions, primarily those involving series (for example, [[pick|Functions: pick]] and [[find|Functions: find]]). The REBOL word none! is defined as a `none!` datatype and contains a `none!` value. The word `none!` is not equivalent to `zero` or `false`. However, none! is interpreted as `false` by many functions. A `none!` value has many uses such as a return value from series functions like [[pick|Functions: pick]], [[find|Functions: find]] and `select`: ``` if (pick series 30) = none [...] ``` In databases, a `none!` can be a placeholder for missing values: ``` email-database: [ "Bobby" bob@rebol.com 40 "Linda" none 23 "Sara" sara@rebol.net 33 ] ``` It also can be used as a logic value: ``` secure none ``` ''Format'' The word `none!` is predefined to hold a `none!` value. Although `none!` is not equivalent to `zero` or `false`, it is valid within conditional expressions and has the same effect as `false`: ``` probe find "abcd" "e" none ``` ``` if find "abcd" "e" [print "found"] ``` ''Creation'' The [[to-none|Functions: to-none]] function always returns `none!`. ''Related'' Use [[none?|Functions: none?]] to determine whether a value is a `none!` datatype. print none? 1 false print none? find [1 2 3] 4 true The [[form|Functions: form]], [[print|Functions: print]], and [[mold|Functions: mold]] functions print the value `none!` when passed a `none!` argument. ``` probe form none none ``` ``` probe mold none none ``` ``` print none none ```
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' context of names with values ''Format'' ''Creation'' There are a couple issues to be addressed with object creation: # Should objects deep copy values found in their body (init) blocks? # Should objects deep copy values found in their parent object? The best way to analyze this situation is to create a test case. The test below determines how the major aggregate types are handled: ``` b1: reduce/no-set [ str: "abc" bin: #{010203} blk: [a b c] vec: make vector! [integer! 32 [1 2 3 4]] img: make image! [2x1 #{010101 020202}] obj: make object! [data: "abc"] ] o1: make object! b1 o2: make object! b1 o3: make o1 [] o4: make o1 b1 compare: func ['a 'b][ print ["comparing" a "to" b] a: get a b: get b foreach [word val] a [ if same? :val get in b word [ print [" " word "field is shared"] ] ] print "" ] compare o1 o2 compare o1 o3 compare o1 o4 ``` In A79, the results are: ``` comparing o1 to o2 str field is shared bin field is shared blk field is shared vec field is shared img field is shared obj field is shared comparing o1 to o3 vec field is shared img field is shared comparing o1 to o4 str field is shared bin field is shared blk field is shared vec field is shared img field is shared obj field is shared ``` So, the values of the object body block are not copied, but the values of parent fields are copied, with the exception of vectors and images. Comparing with R2 the difference (other than `vector!` missing in R2) is in the second case: ``` comparing o1 to o3 obj field is shared ``` So, even the image is copied (although there is a bug in R2 in this regard.) It should also be noted that block values are deep copied in both R2 and R3. If our goal for R3 is to remain "almost compatible" with R2, then we need to copy images and not copy objects. Also, to be consistent so that users don't have to remember extra rules, we should also copy vectors. We can now ask these questions: # What if the user does not want any copying? # What if the user wants to copy everything? Clearly, we need a few other options. How best to provide them? If we don't want to add refinements to [[make|Functions: make]], then perhaps we can use [[copy|Functions: copy]] to provide some of the functionality? If we [[copy|Functions: copy]] of an object and do not specify `/deep` then the object is copied but none of its values are copied. Everything is shared. If we use `/deep`, then all of the source object's values are deep copied. (But, it should be noted that nothing is rebound to the new object. You would need to do that step manually.) In summary: * [[make|Functions: make]] will deep copy all values, except objects * [[copy|Functions: copy]] will shallow copy the object only * [[copy|Functions: copy]] `/deep` will deep copy the entire object, including sub-objects
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' infix operator (special evaluation exception) ''Format'' ''Creation''
''Contents'' * Concept * Format * Creation * Related ''Concept'' A `pair!` datatype is used to indicate spatial coordinates, such as positions on a display. They are used for both positions and sizes. Pairs are used primarily in REBOL/View. ''Format'' A pair is specified as integers separated by an `x` character. ``` 100x50 1024x800 -50x200 ``` ''Creation'' Use [[to-pair|Functions: to-pair]] to convert block or string values into a `pair!` datatype: ``` p: to-pair "640x480" probe p 640x480 ``` ``` p: to-pair [800 600] probe p 800x600 ``` ''Related'' Use [[pair?|Functions: pair?]] to determine whether a value is a `pair!` datatype: ``` probe pair? 400x200 true ``` ``` probe pair? pair true ``` Pairs can be used with most integer math operators: ``` 100x200 + 10x20 10x20 * 2x4 100x30 / 10x3 100x100 * 3 10x10 + 3 ``` Pairs can be viewed by their individual coordinates: ``` pair: 640x480 probe first pair 640 ``` ``` probe second pair 480 ``` All pair values support the `/x` and `/y` refinements. These refinements allow the viewing and manipulation of individual pair coordinates. Viewing individual coordinates: ``` probe pair/x 640 ``` ``` probe pair/y 480 ``` Modifying individual coordinates: ``` pair/x: 800 pair/y: 600 probe pair 800x600 ```
''Contents'' * Concept * Format * Creation * Related ''Concept'' A `paren!` datatype is a block that is immediately evaluated. It is identical to a block in every way, except that it is evaluated when it is encountered and its result is returned. When used within an evaluated expression, a `paren!` allows you to control the order of evaluation: ``` print 1 + (2 * 3) 7 ``` ``` print 1 + 2 * 3 9 ``` The value of a `paren!` can be accessed and modified in the same way as any block. However, when referring to a `paren!`, care must be taken to prevent if from being evaluated. If you store a paren in a variable, you will need to use a get-word form (:word) to prevent it from being evaluated. Parens are a type of series, thus anything that can be done with a series can be done with paren values. ``` paren: first [(1 + 2 * 3 / 4)] print type? :paren paren! ``` ``` print length :paren 7 ``` ``` print first :paren 1 ``` ``` print last :paren 4 ``` ``` insert :paren [10 + 5 *] probe :paren (10 + 5 * 1 + 2 * 3 / 4) ``` ``` print paren 12.75 ``` ''Format'' Parens are identified by their open and closing parenthesis. They can span multiple lines and contain any data, including other paren values. ''Creation'' The [[make|Functions: make]] function can be used to allocate a paren value: ``` paren: make paren! 10 insert :paren 10 insert :paren `+ insert :paren 20 print :paren 20 + 10 ``` ``` print paren 30 ``` The [[to-paren|Functions: to-paren]] function converts data to the `paren!` datatype: ``` probe to-paren "123 456" (123 456) ``` ``` probe to-paren [123 456] (123 456) ``` ''Related'' Use [[paren?|Functions: paren?]] to test the datatype. ``` blk: [(3 + 3)] probe pick blk 1 (3 + 3) ``` ``` probe paren? pick blk 1 true ``` As parens are a subset of the `[bad-link:datatypes/series.txt]` pseudotype, use [[series?|Functions: series?]] to check this: ``` probe series? pick blk 1 true ``` Using [[form|Functions: form]] on a paren value creates a string from the contents contained in the paren: ``` probe form pick blk 1 3 + 3 ```
''Contents'' * Concept * Format * Creation * Related ''Concept'' Paths are a collection of words and values delineated with forward slashes `/`. Paths are used to navigate to or find something. Paths can be used on series, maps, functions, and objects. How a path operates depends on the datatype being used. Thus aths can be used to select values from blocks, pick characters from strings, access variables in objects, refine the operation of a function: ``` USA/CA/Ukiah/size (block selection) names/12 (string position) account/balance (object function) match/any (function option) ``` The example below shows the simplicity of using a path to access a mini-database created from a few blocks: ``` towns: [ Hopland [ phone #555-1234 web http://www.hopland.ca.gov ] Ukiah [ phone #555-4321 web http://www.ukiah.com email info@ukiah.com ] ] print towns/ukiah/web http://www.ukiah.com ``` Summary of path constructs: |''Action'' |''Type Word'' |''Type Test'' |''Conversion''|h |`root/word:` |set-path! |set-path? |to-set-path| |`:root/word` |get-path! |get-path? |to-get-path| |`root/word` |path! |path? |to-path| |`'root/word` |lit-path! |lit-path? |to-lit-path| Examples of paths: Evaluate an object's function: ``` obj: make object! [ hello: func [] [print "hello! hello!"] ] obj/hello hello! hello! ``` Evaluate an object's word: ``` obj: make object! [ text: "do you believe in magic?" ] probe obj/text do you believe in magic? ``` Function refinements: ``` hello: func [/again] [ print either again ["hello again!"]["hello"] ] hello/again hello again! ``` Select from blocks, or multiple blocks: ``` USA: [ CA [ Ukiah [ population 15050 elevation [610 feet] ] Willits [ population 5073 elevation [1350 feet] ] ] ] print USA/CA/Ukiah/population 15050 ``` ``` print form USA/CA/Willits/elevation 1350 feet ``` Pick elements from series and embedded series by their numeric position: ``` string-series: "abcdefg" block-series: ["John" 21 "Jake" 32 "Jackson" 43 "Joe" 52] block-with-sub-series: [ "abc" [4 5 6 [7 8 9]]] probe string-series/4 #"d" ``` ``` probe block-series/3 Jake ``` ``` probe block-series/6 43 ``` ``` probe block-with-sub-series/1/2 #"b" ``` ``` probe block-with-sub-series/2/2 5 ``` ``` probe block-with-sub-series/2/4/2 8 ``` The words supplied as path selectors are symbolic and therefore unevaluated. This is necessary to allow the most intuitive form for object referencing. To use a word's reference, an explicit word value reference is required: ``` city: 'Ukiah probe USA/CA/:city [ population 15050 elevation "610 feet" ] ``` Paths in blocks, maps and objects are evaluated by matching the word at the top level of the path, and verifying the word as a` [bad-link:datatypes/series.txt]`, map! or object! value. Then the next value in the path is sought and an implicit select is performed. The value following the matched value is returned. When the returned value is a block, map, or object, the path can be extended: Getting the value associated with `CA` in `USA`: ``` probe USA/CA [ Ukiah [ population 15050 elevation "610 feet" ] Willits [ population 9935 elevation "1350 feet" ] ] ``` Getting the value associated with `Willits` in `USA/CA`: ``` probe USA/CA/Willits [ population 9935 elevation "1350 feet" ] ``` Getting the value associated with population in `USA/CA/Willits`: ``` probe USA/CA/Willits/population 9935 ``` When a value is used in a path that does not exist at the given point in the structure, an error is produced: ``` probe USA/CA/Mendocino ** Script Error: Invalid path value: Mendocino. ** Where: probe USA/CA/Mendocino ``` Paths can be used to change values in series, maps and objects: ``` USA/CA/Willits/elevation: "1 foot, after the earthquake" probe USA/CA/Willits [ population 9935 elevation "1 foot, after the earthquake" ] ``` ``` obj/text: "yes, I do believe in magic." probe obj make object! [ text: "yes, I do believe in magic." ] ``` Series, functions, and objects can be mixed in paths. Selecting from elements in a block inside an object: ``` obj: make object! [ USA: [ CA [ population "too many" ] ] ] probe obj/USA/CA/population too many ``` Using function refinements within an object: ``` obj: make object! [ hello: func [/again] [ print either again [ "hello again" ] [ "oh, hello" ] ] ] obj/hello/again hello again ``` Paths are themselves type of series, thus anything that can be done with a series can be done with path values: ``` root: [sub1 [sub2 [ word "a word at the end of the path" num 55 ] ] ] path: 'root/sub1/sub2/word probe :path root/sub1/sub2/word ``` In the previous example, the :path notation was used to get the path itself, not the path's value: ``` probe path a word at the end of the path ``` Looking at how long a path is: ``` probe length? :path 4 ``` Finding a word within a path: ``` probe find :path 'sub2 sub2/word ``` Changing a word in a path: ``` change find :path 'word 'num probe :path root/sub1/sub2/num ``` ``` probe path 55 ``` ''Format'' Paths are expressed relative to a root word by providing a number of selection expressions, each separated by a forward slash `/`. These expressions can be words or values. Their specific interpretation vary depending on the datatype of the root value. The words supplied as selection expressions in paths are symbolic and are not evaluated. This is necessary to allow the most intuitive form for object referencing. To use a word's reference, an explicit word value reference is required: ``` root/:word ``` This example uses the value of the variable, rather than it name. ''Creation'' You can [[make|Functions: make]] an empty path of a given size with: ``` path: make path! 10 insert :path 'test insert tail :path 'this print :path test/this ``` The [[to-path|Functions: to-path]] function converts data to the `path!` datatype: ``` probe to-path [root sub] root/sub ``` ``` probe to-path "root sub" root/sub ``` The [[to-set-path|Functions: to-set-path]] function converts other values to the [[set-word!|Datatypes: Set-word!]] datatype. ``` probe to-set-path "root sub" root/sub: ``` The [[to-get-path|Functions: to-get-path]] function converts other values to the [[set-word!|Datatypes: Set-word!]] datatype. ``` probe to-get-path "root sub" :root/sub ``` The [[to-lit-path|Functions: to-lit-path]] function converts other values to the [[lit-word!|Datatypes: Lit-word!]] datatype. ``` probe to-lit-path "root sub" 'root/sub ``` ''Related'' Use [[path?|Functions: path?]], [[set-path?|Functions: set-path?]], [[get-path?|Functions: get-path?]], and [[lit-path?|Functions: lit-path?]] to determine the datatype of a value. ``` probe path? second [1 two "3"] false ``` ``` blk: [sub1 [sub2 [word 1]]] blk2: [blk/sub1/sub2/word: 2] if set-path? (pick blk2 1) [print "it is set"] it is set ``` ``` probe lit-path? first ['root/sub] true ``` As paths are a subset of the `series!` typeset, use [[series?|Functions: series?]] to check this: ``` probe series? pick [root/sub] 1 true ``` Use [[form|Functions: form]] on a path value creates a string from the path: ``` probe form pick [root/sub] 1 root/sub ``` Use [[mold|Functions: mold]] on a path value creates a string of the path value itself, thus allowing it to be reloaded as a REBOL path value: ``` probe mold pick [root/sub] 1 root/sub ```
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' special form of decimals (used mainly for layout) ''Format'' ''Creation''
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' external series, an I/O channel ''Format'' ''Creation''
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' virtual machine function ''Format'' ''Creation''
''Contents'' * Concept * Format * Creation * Related !!! ''Concept'' Refinements are modifiers, similar to adjectives used in natural (human) languages. A refinement indicates a variation in the use of, or extension in the meaning of, a function, object, filename, URL, or path. Refinements are always symbolic in their value. Refinements are used for functions: ``` block: [1 2] append/only block [3 4] ``` objects: ``` print system/version ``` files: ``` dir: %docs/core print read dir/file.txt ``` urls: ``` site: http://www.rebol.com print read site/index.html ``` !!! ''Format'' Refinements are composed with a slash followed by a valid REBOL word (see the words section below for definition). Examples are: ``` /only /test1 /save-it ``` Refinements are usually joined to other words, such as in the case of: ``` port: open/binary file ``` But refinements can also be written alone, as is done when specifying refinements to a function: ``` save-data: function [file data /limit /reload] ... ``` !!! ''Creation'' Refinements can be created literally in source code: ``` /test ``` or can be composed from the to-refinement word: ``` probe to-refinement "test" /test ``` !!! ''Related'' To test for a refinement, use the refinement? function: ``` probe refinement? /test true ``` ``` probe refinement? 'word false ```
''Concept'' This datatype has not been implemented in REBOL 3. See [[library!|Datatypes: Library!]].
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' definition of a path's value ''Format'' ''Creation''
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' definition of a word's value ''Format'' ''Creation''
''Contents'' * Concept * Format * Creation * Related ''Concept'' Strings are a series of characters. All operations performable on series values can be performed on strings. ''Format'' String values are written as a sequence of characters surrounded by double quotes `" "` or braces `{}`. Strings enclosed in double quotes are restricted to a single line and must not contain unprintable characters. ``` "This is a short string of characters." ``` Strings enclosed in braces are used for larger sections of text that span multiple lines. All of the characters of the string, including spaces, tabs, quotes, and newlines are part of the string. ``` {This is a long string of text that will not easily fit on a single line of source. These are often used for documentation purposes.} ``` Braces are counted within the string, so a string can include other braces as long as the number of closing braces matches the number of opening braces. ``` { This is another long string of text that would never fit on a single line. This string also includes braces { a few layers deep { and is valid because there are as many closing braces } as there are open braces } in the string. } ``` You can include special characters and operations in strings by prefixing them with a caret (^). Special characters include: |''Character'' |''Definition''|h |`^"` |Inserts a double quote (").| |`^}` |Inserts a closing brace (}).| |`^^` |Inserts a caret (^).| |`^/` |Starts a new line.| |`^(line)` |Starts a new line.| |`^-` |Inserts a tab.| |`^(tab)` |Inserts a tab.| |`^(page)` |Starts a new page.| |`^(back)` |Erases one character to the left of the insertion point.| |`^(null)` |Inserts a null character.| |`^(escape)` |Inserts an escape character.| |`^(letter)` |Inserts control-letter (A-Z).| |`^(xx)` |Inserts an ASCII character by hexidecimal (xx) number. his format allows for expansion into unicode characters in the future.| ''Creation'' Use make to create a pre-allocated amount of space for an empty string: ``` make string! 40'000 ; space for 40k characters ``` The [[to-string|Functions: to-string]] function converts data of other datatypes to a `string!` datatype: ``` probe to-string 29-2-2000 "29-Feb-2000" ``` ``` probe to-string 123456.789 "123456.789" ``` ``` probe to-string #888-555-2341 "888-555-2341" ``` Converting a block of data to a string with [[to-string|Functions: to-string]] has the effect of doing a [[rejoin|Functions: rejoin]], but without evaluating the block's contents: ``` probe to-string [123 456] "123456" ``` ``` probe to-string [225.225.225.0 none true 'word] "225.225.225.0nonetrueword" ``` ''Related'' Use [[string?|Functions: string?]] or series? to determine whether a value is an `string!` datatype: ``` print string? "123" true ``` ``` print series? "123" true ``` The functions form and mold are closely related to strings, as they create strings from other datatypes. The form function makes a human readable version of a specified datatype, while mold makes a REBOL readable version. ``` probe form "111 222 333" "111 222 333" ``` ``` probe mold "111 222 333" {"111 222 333"} ```
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' native structure definition ''Format'' ''Creation''
''Contents'' * Concept * Format * Creation * Related ''Concept'' Tags are used in HTML and other markup languages to indicate how text fields are to be treated. For example, the tag <;HTML> at the beginning of a file indicates that it should be parsed by the rules of the Hypertext Markup Language. A tag with a forward slash (/), such as <;/HTML>, indicates the closing of the tag. Tags are a subset of series, and thus can be manipulated as such: ``` a-tag: <img src="mypic.jpg"> probe a-tag <img src="mypic.jpg"> ``` ``` append a-tag { alt="My Picture!"} probe a-tag <img src="mypic.jpg" alt="My Picture!"> ``` ''Format'' Valid tags begin with an open angle bracket (<) and end with a closing bracket (>). For example: ``` <a href="index.html"> <img src="mypic.jpg" width="150" height="200"> ``` ''Creation'' The [[to-tag|Functions: to-tag]] function converts data to the` tag!` datatype: ``` probe to-tag "title" <title> ``` Use `[bad-link:functions/build-tag.txt]` to construct tags, including their attributes. The` [bad-link:functions/build-tag.txt]` function takes one argument, a block. In this block, the first word is used as the tag name and the remaining words are processed as attribute value pairs: ``` probe build-tag [a href http://www.rebol.com/] <a href="http://www.rebol.com/"> ``` ``` probe build-tag [ img src %mypic.jpg width 150 alt "My Picture!" ] <img src="mypic.jpg" width="150" alt="My Picture!"> ``` ''Related'' Use [[tag?|Functions: tag?]] to determine whether a value is an `tag!` datatype. ``` probe tag? <a href="http://www.rebol.com/"> true ``` As tags are a subset of the series pseudotype, use [[series?|Functions: series?]] to check this: ``` probe series? <a href="http://www.rebol.com/"> true ``` The [[form|Functions: form]] function returns a tag as a string: ``` probe form <a href="http://www.rebol.com/"> {<a href="http://www.rebol.com/">} ``` The [[mold|Functions: mold]] function returns a tag as a string: ``` probe mold <a href="http://www.rebol.com/"> {<a href="http://www.rebol.com/">} ``` The [[print|Functions: print]] function prints a tag to standard output after doing a [[reform|Functions: reform]] on it: ``` print <a href="http://www.rebol.com/"> <a href="http://www.rebol.com/"> ```
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' evaluation environment ''Format'' ''Creation''
''Contents'' * Concept * Format * Access * Creation * Related ''Concept'' The REBOL language supports the standard expression of time in hours, minutes, seconds, and subseconds. Both positive and negative times are permitted. The `time!` datatype uses relative rather than absolute time. For example, 10:30 is 10 hours and 30 minutes rather than the time of 10:30 A.M. or P.M. ''Format'' Times are expressed as a set of integers separated by colons (:).. Hours and minutes are required, but seconds are optional. Within each field, leading zeros are ignored: ``` 10:30 0:00 18:59 23:59:50 8:6:20 8:6:2 ``` The minutes and seconds fields can contain values greater than 60. Values greater than 60 are automatically converted. For instance 0:120:00 is the same as 2:00. ``` probe 00:120:00 2:00 ``` Subseconds are specified using a decimal in the seconds field. Use either a period or a comma as the decimal point. The hours and minutes fields become optional when the decimal is present. Subseconds are encoded to the nano-second, or one billionth (- US, one milliardth - GB) of a second: ``` probe 32:59:29.5 32:59:29.5 ``` ``` probe 1:10,25 0:01:10.25 ``` ``` probe 0:0.000000001 0:00:00.000000001 ``` ``` probe 0:325.2 0:05:25.2 ``` Times can be followed by AM or PM, but no space is permitted. PM adds 12 hours to the time: ``` probe 10:20PM 22:20 ``` ``` probe 3:32:20AM 3:32:20 ``` Times are output in a standard hours, minutes, seconds, and subseconds format, regardless of how they are entered: ``` probe 0:87363.21 24:16:03.21 ``` ''Access'' Time values have three refinements that can be used to return specific information about the value: |''Refinement'' |''Description''|h |`'/hour` |Gets the value's hour.| |`'/minute` |Gets the value's minute.| |`'/second` |Gets the value's second.| Here's how to use a time value's refinements: ``` lapsed-time: 91:32:12.14 probe lapsed-time/hour 91 ``` ``` probe lapsed-time/minute 32 ``` ``` probe lapsed-time/second 12.14 ``` Times with time zones can only be used with the [[date!|Datatypes: Date!]]. Creation Times can be converted using the [[to-time|Functions: to-time]] function: ``` probe to-time "10:30" 10:30 ``` ``` probe to-time [10 30] 10:30 ``` ``` probe to-time [0 10 30] 0:10:30 ``` ``` probe to-time [10 30 20.5] 10:30:20.5 ``` In the previous examples, the values are not evaluated. To evaluate values as mathematical expressions, use the reduce function: ``` probe to-time reduce [10 30 + 5] 10:35 ``` In various math operations involving time values, the time values, integers, or decimals are converted as shown below: ``` probe 10:30 + 1 10:30:01 ``` ``` probe 10:00 - 10 9:59:50 ``` ``` probe 0:00 - 10 -0:00:10 ``` ``` probe 5:10 * 3 15:30 ``` ``` probe 0:0:0.000000001 * 1'500'600 0:00:00.0015006 ``` ``` probe 8:40:20 / 4 2:10:05 ``` ``` probe 8:40:20 / 2:20:05 3 ``` ``` probe 8:40:20 // 4:20 0:00:20 ``` ''Related'' Use [[time?|Functions: time?]] to determine whether a value is a `time!` datatype: ``` probe time? 10:30 true ``` ``` probe time? 10.30 false ``` Use the [[now|Functions: now]] function with the `/time` refinement to return the current local date and time: ``` print now/time 14:42:15 ``` Use the [[wait|Functions: wait]] function to wait for a duration, port, or both. If a value is a `time!` datatype, [[wait|Functions: wait]] delays for that period of time. If a value is a `date!/time!`, [[wait|Functions: wait]] waits until the indicated date and time. If the value is an [[integer!|Datatypes: Integer!]] or [[decimal!|Datatypes: Decimal!]], the function waits the indicated number of seconds. If the value is a [[port!|Datatypes: Port!]], the function will wait for an event from that port. If a block is specified, it will wait for any of the times or ports to occur. It returns the port that caused the wait to complete or returns none! if the timeout occurred. For example, ``` probe now/time 14:42:16 ``` ``` wait 0:00:10 probe now/time 14:42:26 ```
''Contents'' * Concept * Format * Creation * Related ** Auto Clipping ''Concept'' It is common to represent version numbers, Internet addresses, and RGB color values as a sequence of three or four integers. These types of numbers are called a tuple! (as in quintuple) and are represented as a set of integers separated by periods. ``` 1.3.0 2.1.120 1.0.2.32 ; version 199.4.80.250 255.255.255.0 ; net addresses/masks 0.80.255 200.200.60 ; RGB colors ``` ''Format'' Each integer field of a `tuple!` datatype can range between 0 and 255. Negative integers produce an error. Three to ten integers can be specified in a tuple. In the case where only two integers are given, there must be at least two periods, otherwise the value is treated as a decimal. ``` probe 1.2 ; is decimal 1.2 ``` ``` probe type? 1.2 decimal! ``` ``` probe 1.2.3 ; is tuple 1.2.3 ``` ``` probe 1.2. ; is tuple 1.2.0 ``` ``` probe type? 1.2. tuple! ``` ''Creation'' Use the [[to-tuple|Functions: to-tuple]] function to convert data to the `tuple!` datatype: ``` probe to-tuple "12.34.56" 12.34.56 ``` ``` probe to-tuple [12 34 56] 12.34.56 ``` ''Related'' Use [[tuple?|Functions: tuple?]] to determine whether a value is a `tuple!` datatype. ``` probe tuple? 1.2.3.4 true ``` Use the [[form|Functions: form]] function to print a tuple as a string: ``` probe form 1.2.3.4 1.2.3.4 ``` Use the [[mold|Functions: mold]] function to convert a tuple into a string that can be read back into REBOL as a tuple: ``` probe mold 1.2.3.4 1.2.3.4 ``` Use the [[print|Functions: print]] function to print a tuple to standard output after using the reform function: ``` print 1.2.3.4 1.2.3.4 ``` !!!!! ''Auto Clipping'' During math operations, elements of a tuple will clip at 0 and 255. This is done to make math easier for common tuple operations such generating as color values. ``` print navy 0.0.128 ``` ``` print navy * 2 0.0.255 ``` ``` print gray 128.128.128 ``` ``` print gray + green 128.255.128 ```
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' set of datatypes ''Format'' ''Creation''
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation * ''Concept'' no value returned or set ''Format'' ''Creation''
''Contents'' * Concept * Format * Creation * Related ''Concept'' URL is an acronym for Uniform Resource Locator, an Internet standard used to access resources such as web pages, images, files, and email across the network. The best known URL scheme is that used for web locations such as http://www.REBOL.com. URL values are a subset of series, and thus can be manipulated as series: ``` url: http://www.rebol.com/reboldoc.html probe to-file find/reverse (tail url) "rebol" %reboldoc.html ``` ''Format'' The first part of a URL indicates its communications protocol, called a scheme. The language supports several schemes, including: web pages ('HTTP:), file transfer ('FTP:), newsgroups ('NNTP:), email ('MAILTO:), files ('FILE:), finger ('FINGER:), whois ('WHOIS:), small network time ('DAYTIME:), post office ('POP:), transmission control ('TCP:) and domain name service ('DNS:). These scheme names are followed by characters that are dependent on which scheme being used. ``` http://host.dom/path/file ftp://host.dom/path/file nntp://news.some-isp.net/some.news.group mailto:name@domain file://host/path/file finger://user@host.dom whois://rebol@rs.internic.net daytime://everest.cclabs.missouri.edu pop://user:passwd@host.dom/ tcp://host.dom:21 dns://host.dom ``` Some fields are optional. For instance, the host can be followed by a port number if it differs from the default. An FTP URL supplies a default password if one is not specified: ``` ftp://user:password@host.dom/path/file ``` Characters in a URL must conform to Internet standards. Restricted characters must be encoded in hexadecimal by preceding them with the escape character %: ``` probe http://www.somesite.dom/odd%28dir%29/odd%7Bfile%7D.txt http://www.somesite.dom/odd%28dir%29/odd%7Bfile%7D.txt ``` ``` print http://www.somesite.dom/odd%28dir%29/odd%7Bfile%7D.txt http://www.somesite.dom/odd(dir)/odd{file}.txt ``` ''Creation'' The [[to-url|Functions: to-url]] function converts blocks to the `url!` datatype, the first element in the block is the scheme, the second element is the domain (with or without user:pass and port) the remaining elements are the path and file: ``` probe to-url [http www.rebol.com reboldoc.html] http://www.rebol.com/reboldoc.html ``` ``` probe to-url [http www.rebol.com %examples "websend.r"] http://www.rebol.com/examples/websend.r ``` ``` probe to-url [http usr:pass@host.com:80 "(path)" %index.html] http://usr:pass@host.com:80/%28path%29/index.html ``` ''Related'' The datatype word is `url!`. Use [[url?|Functions: url?]] to test the datatype. ``` probe url? ftp://ftp.rebol.com/ true ``` As urls are a subset of the series pseudotype, use [[series?|Functions: series?]] to check this: ``` probe series? http://www.rebol.com/ true ``` ``` ```
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' user defined datatype ''Format'' ''Creation''
This datatype has not yet been documented for R3. ''Contents'' * Concept * Format * Creation ''Concept'' high performance arrays (single datatype) ''Format'' ''Creation''
''Contents'' * Concept * Formats * Related functions * Format * Creation * Related ''Concept'' Words are the symbols used by REBOL. A word may or may not be a variable, depending on how it is used. Words are quite often used directly as symbols, rather than variables. It is important to understand the difference. REBOL does not use keywords -- those specific words that can only be used in one way. For example, in C code, an if statement may be written: ``` if (n > 1) n = 0; ``` The word `if` is a keyword. You cannot use it in any other way or for any other purpose. In REBOL, words are symbols defined within dynamically created contexts. There are no restrictions on what words are used or how they are used. For example, the word `if` is used several ways here: ``` if n > 1 [n: 0] words: [if while loop until] help if obj: object [ if: 12 fi: 21 print if ] ``` So, the context defines the word's value and its usage. ''Formats'' There are a few different formats for words, depending on their intended usage: |Notation |Meaning|h |`word` |Get the natural value of the word. (If the value is a function, evaluate it, otherwise return it.)| |`word:` |Sets the word (like assignment) to a value.| |`:word` |Gets the word's value without evaluating it. (Useful for getting the value of a function.)| |`'word` |Treat word as a value (a word symbol). Does not evaluate it.| |`/word` |Treat the word as a refinement. Used mainly for optional arguments.| ''Related functions'' |''Action'' |''Type Word'' |''Type Test'' |''Conversion''|h |`word:`|set-word!|set-word?|to-set-word| |`:word`|get-word!|get-word?|to-get-word| |`word`|word!|word?|to-word| |`'word`|lit-word!|lit-word?|to-lit-word| ''Format'' Words are composed of alphabetic characters, numbers, and any of the following characters: ``` ? ! . ' + - * & | = _ ~ ``` A word cannot begin with a number, and there are also some restrictions on words that could be interpreted as numbers. For instance, -1 and +1 are numbers, not words. The end of a word is marked by a space, a newline, or one of the following characters: ``` [ ] ( ) { } " : ; / ``` Thus, the square brackets of a block are not part of a word: ``` [test] ``` The following characters are not allowed in words: ``` @ # $ % ^ , ``` Words can be of any length, but cannot extend past the end of a line. ``` this-is-a-very-long-word-used-as-an-example ``` Sample words are: ``` Copy print test number? time? date! image-files l'image ++ -- == +- ***** *new-line* left&right left|right ``` The REBOL language is not case-sensitive. The words following words: ``` blue Blue BLUE ``` all refer to the same word. The case of the word is preserved when it is printed. Words can be reused. The meaning of a word is dependent on its context, so words can be reused in different contexts. You can reuse any word, even predefined REBOL words. For instance, the REBOL word [[if|Functions: if]] can be used in your code differently than how it is used by the REBOL interpreter. ''Creation'' The [[to-word|Functions: to-word]] function converts values to the `word!` datatype. ``` probe to-word "test" test ``` The [[to-set-word|Functions: to-set-word]] function converts values to the [[set-word!|Datatypes: Set-word!]] datatype. ``` probe make set-word! "test" test: ``` The [[to-get-word|Functions: to-get-word]] function converts values to the [[get-word!|Datatypes: Get-word!]] datatype. ``` probe to-get-word "test" :test ``` The [[to-lit-word|Functions: to-lit-word]] function converts values to the [lit-word!|Datatypes: Lit-word!]] datatype. ``` probe to-lit-word "test" 'test ``` ''Related'' Use [[word?|Functions: word?]], [[set-word?|Functions: set-word?]], [[get-word?|Functions: get-word?]], and [[lit-word?|Functions: lit-word?]] to test the datatype. ``` probe word? second [1 two "3"] true ``` ``` if set-word? first [word: 10] [print "it is set"] it is set ``` ``` probe get-word? second [pr: :print] true ``` ``` probe lit-word? first ['foo bar] true ```
Dates are written in either international format: day-month-year or year-month-day. A date can also include a time and a time zone. The name or abbreviation of a month can be used to make its format more identifiable in the United States. For example: ``` 20-Apr-1998 20/Apr/1998 (USA friendly) 20-4-1998 1998-4-20 (international) 1980-4-20/12:32 (date with time) 1998===20/8:32-8:00 (with time zone) ```
The following example gets the current time from a server: ``` print read daytime://everest.cclabs.missouri.edu ```
As rules are written, there are times debugging is needed. Specifically, you may want to know how far you got in the parsing of a rule. The [[trace|Functions: trace]] function can be used to watch the parse operation progress, but this can output thousands of lines that are difficult to review. A better way is to insert debugging expressions into the parse rules. As an example, to debug the rule: ``` [to "<IMG" "SRC" "=" filename ">"] ``` insert a the [[print|Functions: print]] function after key sections to monitor your progress through the rule: ``` [to "<IMG" (print 1) "SRC" "=" (print 2) filename (print 3) ">"] ``` This example prints 1, 2, and 3 as the rule is processed. Another approach is to print out part of the input string as the parse happens: ``` [ to "<IMG" here: (print here) "SRC" "=" here: (print here) filename here: (print here) ">" ] ``` If this is done often, you can create a rule for it: ``` here: [where: (print where)] [ to "<IMG" here "SRC" "=" here filename here ">" ] ``` The copy function can also be used to indicate what substrings were parsed as the rule was handled.
Many blocks contain other blocks and strings. When such a block is copied, its sub-series are not copied. The sub-series are referred to directly and are the same series data as the original block. If you modify any of these sub-series, you modify them in the original block as well. The `copy/deep` refinement forces a copy of all series values within a block: ``` blk-one: ["abc" [1 2 3]] probe blk-one ["abc" [1 2 3]] ``` The next example assigns a normal copy of `blk-one` to `blk-two`: ``` blk-two: copy blk-one probe blk-one ["abc" [1 2 3]] ``` ``` probe blk-two ["abc" [1 2 3]] ``` If either the string or block contained in `blk-two` is modified, the series values in `blk-one` are also modified. ``` append blk-two/1 "DEF" append blk-two/2 [4 5 6] probe blk-one ["abcDEF" [1 2 3 4 5 6]] ``` ``` probe blk-two ["abcDEF" [1 2 3 4 5 6]] ``` Using `copy/deep` makes a copy of all series values found in the block: ``` blk-two: copy/deep blk-one append blk-two/1 "ghi" append blk-two/2 [7 8 9] probe blk-one ["abcDEF" [1 2 3 4 5 6]] ``` ``` probe blk-two ["abcDEFghi" [1 2 3 4 5 6 7 8 9]] ```
There are many types of functions and a variety of ways to define them. The most common way to define a function is with func. Here is a simple example: ``` sum2: func [a b] [a + b] ``` Now you can call the new function with a line like: ``` print sum2 10 20 30 ``` !!!! ''General form'' {{Defining functions: General form}} !!!! ''Other methods'' {{Other methods}}
As shown above, func takes two blocks as arguments: ``` func [specification] [body] ``` where: |''specification'' |defines the function's interface, including arguments, local variables, and documentation.| |''body'' |provides the code that is evaluated when the function is called.| After the new function is created, it is returned from [[func|Functions: func]]. In the example the `sum2` variable is set to it.
Refinements can be used to specify variation in the normal evaluation of a function as well as provide optional arguments. Refinements are added to the function specification block as a word preceded by a forward slash `/`. Within the body of the function, the refinement word is used as a logic value to determine if the refinement was provided when the function was called. For example, the following code adds a refinement to the sum function, which was defined in a previous example: ``` sum: func [ "Return the sum of two numbers." arg1 [number!] "first number" arg2 [number!] "second number" /average "return the average of the numbers" ][ either average [arg1 + arg2 / 2][arg1 + arg2] ] ``` The `sum` function specifies the `/average` refinement. In the body of the function, the word is tested with the either function, which returns true when the refinement is specified. ``` print sum/average 123 321 222 ``` To specify a refinement that accepts additional arguments, follow the refinement with the arguments definitions: ``` sum: func [ "Return the sum of two numbers." arg1 [number!] "first number" arg2 [number!] "second number" /times "multiply the result" amount [number!] "how many times" ][ either times [arg1 + arg2 * amount][arg1 + arg2] ] ``` The amount is only valid when the times refinement is true. Here is an example: ``` print sum/times 123 321 10 4440 ``` Do not forget to check the refinement word before using the additional arguments. If a refinement argument is used without the refinement being specified, it will have a none! value.
Files can be deleted using the [[delete|Functions: delete]] function: ``` delete %file ``` The file to delete can include a path: ``` delete %source/docs/file.txt ``` A block of files within the same directory can also be deleted: ``` delete [%file1 %file2 %file3] ``` A group of files can be deleted using a wildcard character and the `/any` refinement: ``` delete/any %file* delete/any %secret.? ``` The asterisk `()` ''wildcard character matches all characters, and the question mark'' (?) ''wildcard character matches a single character''. To delete a directory, provide a trailing forward slash: ``` delete %dir/ delete %../docs/old/ ``` If the file cannot be deleted, an error will occur. The error can be caught with the [[try|Functions: try]] function.
The basic callback mechanism involves setting up to call this specific RXI API function: ``` n = RL_CALLBACK(cbi); ``` Here, the cbi argument is a RXICBI structure that includes: |''obj'' |the object context of the function| |''word'' |the function's name, a word id| |''args'' |the RXIARG argument array to hold input arguments| |''result'' |space to hold the result of the callback| |''flags'' |for special options (and future controls)| The way this structure is allocated is important, depending on what type of callback you are using. For asynchronous callbacks, this structure must not be local to the stack, because the stack frame is popped before the function is run. It's best to allocate it in memory. The `RL_CALLBACK` function returns an unsigned integer: # For a synchronous function, this is the datatype enum of the returned value. # For an asynchronous function, this value is simply TRUE or FALSE. If FALSE, it means that the event could not be queued (most likely because the event queue has reached its maximum.) !!!!! ''Allocating the CBI'' As mentioned earlier, the way you allocate the CBI (callback information structure) is important. The most general way is to allocate it from the heap. You can use it once and free it, or store it for reuse multiple times (as long as not recursively, of course.) Here's an example that allocates the CBI and an argument frame for NARGS of args: ``` #define NARGS 4 RXICBI *cbi; cbi = MAKE_NEW(*cbi); CLEAR(cbi, sizeof(cbi)); cbi->args = MAKE_MEM(sizeof(RXIARG) * NARGS); CLEAR(cbi->args, sizeof(RXIARG) * NARGS); ``` Of course, you could also allocate it on the stack for calling synchronous callbacks: ``` #define NARGS 4 RXICBI cbi; RXIARG args[NARGS]; CLEAR(&cbi, sizeof(cbi)); cbi.args = &args[0]; CLEAR(cbi.args, sizeof(args)); ``` !!!!! ''Setting the Function'' To set the function, your C code must have a pointer to the object where it resides (an object you made or some other system context) and the name of the function, as a word id. Set those in the CBI (using the allocated form of the CBI structure): ``` cbi->obj = obj; cbi->word = word; ``` <<< Editor note: Add a note about why this technique is used. <<< !!!!! ''Setting the Mode'' Next, if your callback must run as a queued event, you will need to set a flag: ``` SET_FLAG(cbi->flags, RXC_ASYNC); ``` !!!!! ''Setting the Arguments'' The argument array has exactly the same format as other extension command! arguments. You will need to set the argument count, the datatypes, and the values. Here's an example that puts a single [[integer!|Datatypes: Integer!]] argument into the argument frame: ``` RXI_COUNT(args) = 1; RXI_TYPE(args, 1) = RXT_INTEGER; args[1].int64 = 123; ``` !!!!! ''Calling the Function'' You're now ready to call the function or queue it (if it's asynchronous): ``` n = RL_CALLBACK(cbi); ``` If n is zero, then an error has occurred, and you may need to process it. !!!!! ''Return Value'' The return value is stored in the cbi result field. If this value is a series or other non-immediate datatype, then it is volatile and may be garbage collected if you don't store it in a block or object that is referenced from some other part of your code. !!!!! ''Deallocating the CBI'' If you no longer need the CBI or argument array, you can free them or add them to your own pool for later reuse. For synchronous callbacks, you can do this anytime after the callback has returned: ``` free(cbi->args); free(cbi); ``` To help manage the pooling of asynchronous CBI data, a CBI flag is set once the callback has completed and the data is no longer in use. Code like this could be added to a pooling check function: ``` if (GET_FLAG(cbi->flags, RXC_DONE)) { free(cbi->args); free(cbi); } ``` Don't forget to copy out your result if you need to use it later.
A few concise examples help illustrate the parsing of blocks: ``` block: [when 10:30] print parse block ['when 10:30] print parse block ['when time!] parse block ['when set time time! (print time)] ``` Notice that a specific word can be matched by using its literal word in the rule (as in the case of `'when` ). A datatype can be specified rather than a value, as in the lines above containing [[time!|Datatypes: Time!]]. In addition, a variable can be set to a value with the set operation. As with strings, alternate rules can be specified when parsing blocks: ``` rule: [some [ 'when set time time! | 'where set place string! | 'who set persons [word! | block!] ]] ``` These rules allow information to be entered in any order: ``` parse [ who Fred where "Downtown Center" when 9:30 ] rule print [time place persons] ``` This example could have used variable assignment, but it illustrates how to provide alternate input ordering. Here's another example that evaluates the results of the parse: ``` rule: [ set count integer! set str string! (loop count [print str]) ] parse [3 "great job"] rule parse [3 "hut" 1 "hike"] [some rule] ``` Finally, here is a more advanced example: ``` rule: [ set action ['buy | 'sell] set number integer! 'shares 'at set price money! (either action = 'sell [ print ["income" price * number] total: total + (price * number) ][ print ["cost" price * number] total: total - (price * number) ] ) ] total: 0 parse [sell 100 shares at $123.45] rule print ["total:" total] total: 0 parse [ sell 300 shares at $89.08 buy 100 shares at $120.45 sell 400 shares at $270.89 ] [some rule] print ["total:" total] ``` It should be noted that this is one way how expressions that use the ''dialect'' concept first described in Chapter 4 can be'' evaluated''.
The [[difference|Functions: difference]] function takes two series and returns a series that contains all of the values not in common with both series. Examples: ``` probe difference [1 2 3 4] [1 2 3 5] [4 5] ``` ``` probe difference [Bill Bob Bart] [Bob Ted Fred] [Bill Bart Ted Fred] ``` ``` lunch: [ham cheese bread carrot] dinner: [ham salad carrot rice] probe difference lunch dinner [cheese bread salad rice] ``` ``` string1: "CBAD" ; A B C D scrambled string2: "EDCF" ; C D E F scrambled print sort difference string1 string2 ABEF ``` The `/case` refinement allows case-sensitive differences. ``` probe difference/case [Bill bill Bob bob] [Bart bart bill Bob] [Bill bob Bart bart] ```
Values can be ''directly'' or ''indirectly'' expressed. A directly expressed value is ''known'' as it is lexically, or literally, written. For instance, the number 10 or the time 10:30 are directly expressed values. An indirectly expressed value is ''unknown'' until it is evaluated. The values [[none!|Datatypes: None!]], `true`, and `false` all require words to represent them. These values are indirectly expressed because they must be evaluated for their values to be known. This is also true of other values, such as lists, hashes, functions, objects.
The `/direct` refinement opens an unbuffered port. This is useful to access files a portion at a time, such as when a file is too large to be held in memory. ``` fp: open/direct %file.txt ``` Reading the data with a [[copy|Functions: copy]] function will move the port's head forward: ``` print copy/part fp 40 I wanted the gold, and I sought it,^/ I ``` ``` print copy/part fp 40 scrabbled and mucked like a slave.^/Was i ``` In direct mode, the port will always be at its head position: ``` print head? fp true ``` The [[copy|Functions: copy]] function will return none! when the port has reached its end. Here is an example that uses direct ports to copy a file of any size: ``` from-port: open/direct %a-file.jpg to-port: open/direct %a-file.jpg while [data: copy/part from-port 100000 ][ append to-port data ] close from-port close to-port ```
To determine if a file name is that of a directory, use the [[dir?|Functions: dir?]] function: ``` print dir? %file.txt false print dir? %. true ``` The [[dir?|Functions: dir?]] function works with some network protocols as well: ``` print dir? ftp://www.rebol.com/pub/ true ```
The [[info?|Functions: info?]] function obtains all file directory information at the same time. The information is returned as an object: ``` probe info? %file.txt make object! [ size: 306 date: 30-Jun-2000/14:41:55-7:00 type: 'file ] ``` To print information about all files in the current directory, use: ``` foreach file read %. [ info: info? file print [file info/size info/date info/type] ] build-guide.r 22334 30-Jun-2000/14:24:43-7:00 file code/ 11 11-Oct-1999/18:37:04-7:00 directory data.r 41 30-Jun-2000/14:41:36-7:00 file file.txt 306 30-Jun-2000/14:41:55-7:00 file ``` The [[info?|Functions: info?]] function also works with some network protocols: ``` probe info? ftp://www.rebol.com/file.txt ```
`REBOL/Core` includes these primary distribution files: |''rebol (.exe)'' |An executable program that starts the REBOL console.| |''rebol.r'' |A system bootstrap file. (Not required to run REBOL.)| |''setup.html'' |Information about set-up and installation.| |''changes.html'' |Changes found in recent releases.| |''license.txt'' |REBOL license agreement.| Other files may be provided, depending on the REBOL product and version.
The following example determines an Internet address from a domain name and a domain name from an address: ``` print read dns://www.rebol.com print read dns://207.69.132.8 ```
''Contents'' * Concept * Arc * Circle * Curve * Ellipse * Spline ''Concept'' This section describes draw commands that are related to curves and ellipses. All of these are part of the draw dialect, a REBOL sub-language for describing scalar vector graphics (SVG). The dialect consists of a number of command keywords, as listed in this document below. Each command can be followed by its arguments, all of which are optional. Their names, datatypes, and descriptions are provided in the "argument" table for each command section below. ''Arc'' The ARC command draws a partial section of an ellipse or circle. |Argument |Datatype |Description|h |center |pair! |The center of the circle| |radius |pair! |The radius of the circle| |angle-begin |decimal! |The angle where the arc begins, in degrees| |angle-length |decimal! |The length of the arc in degrees| |closed |word! |Optional, must be the word closed closed - close the arc| For angle-begin 0 degrees is to right of the center point, on the horizontal axis. Arcs are drawn in a clockwise direction from the angle-begin point. Simple open arcs beginning at 0 degrees. ``` arc 200x25 100x100 0 90 arc 200x125 100x100 0 135 arc 200x250 100x100 0 180 arc example 1 arc example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/arc-1.png"/> Simple open arcs beginning at different angles, but all with the same length. ``` arc 200x25 100x100 0 120 arc 200x125 100x100 45 120 arc 200x250 100x100 90 120 arc example 2 arc example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/arc-2.png"/> A closed arc. The arcs is closed by drawing lines to the center point of the circle that defines the arc. ``` arc 100x100 100x100 0 90 closed arc example 3 arc example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/arc-3.png"/> ``` fill-pen red arc 100x100 90x90 135 180 fill-pen green arc 300x100 90x90 225 180 fill-pen blue arc 100x300 90x90 45 180 fill-pen yellow arc 300x300 90x90 315 180 arc example 4 arc example 4 ``` <img src="http://www.rebol.com/r3/docs/graphics/arc-4.png"/> ``` fill-pen red arc 150x250 90x90 0 180 fill-pen green arc 150x150 90x90 90 180 fill-pen blue arc 250x150 90x90 180 180 fill-pen yellow arc 250x250 90x90 270 180 arc example 5 arc example 5 ``` <img src="http://www.rebol.com/r3/docs/graphics/arc-5.png"/> Closed arcs are an easy way to draw wedges for pie charts. ``` fill-pen red arc 200x200 90x90 0 90 closed fill-pen green arc 200x200 90x90 90 90 closed fill-pen blue arc 200x200 90x90 180 90 closed fill-pen yellow arc 200x200 90x90 270 90 closed arc example 6 arc example 6 ``` <img src="http://www.rebol.com/r3/docs/graphics/arc-6.png"/> By changing the center point, you can draw exploded pie charts. ``` pen white line-width 2 fill-pen red arc 204x204 150x150 0 90 closed fill-pen green arc 196x204 150x150 90 30 closed fill-pen blue arc 180x190 150x150 120 150 closed fill-pen yellow arc 204x196 150x150 270 90 closed arc example 7 arc example 7 ``` <img src="http://www.rebol.com/r3/docs/graphics/arc-7.png"/> ''Circle'' Draws a circle or ellipse. |Argument |Datatype |Description|h |center |Pair! | |radius-x |decimal! |Used for both X and Y radii if radius-y isn't provided| |radius-y |decimal! |Optional. Used to create an ellipse| A simple circle ``` pen yellow line-width 5 circle 200x200 150 circle example 1 circle example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/circle-1.png"/> A circle using an image as the pen ``` pen logo.gif circle 200x200 150 circle example 2 circle example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/circle-2.png"/> A circle using an image as the fill-pen ``` line-width 2 pen yellow fill-pen logo.gif circle 200x200 150 circle example 3 circle example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/circle-3.png"/> ''Curve'' Draws a smooth Bézier curve to fit the points provided. |Argument |Datatype |Description|h |point1 |pair! |End point A| |point2 |pair! |Control point A| |point3 |pair! |End point B, or control point B| |point4 |pair! |End point B| Either three or four points should be specified. With three points, it is a cubic Bézier curve with two endpoints and one control point. With four points it allows two control points, and it can create more complicated curves such as circular and elliptical arcs. A curve with one control point ``` curve 20x150 60x250 200x50 curve example 1 curve example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/curve-1.png"/> A curve with two control points ``` curve 20x20 80x300 140x20 200x300 curve example 2 curve example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/curve-2.png"/> A thick curve with a patterened line ``` pen yellow line-pattern red 5 5 line-width 4 curve 20x150 60x250 200x50 curve example 3 curve example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/curve-3.png"/> A thick curve with two control points, a patterened line, and a fill pen. ``` pen yellow line-pattern red 5 5 line-width 4 fill-pen blue curve 20x20 80x300 140x20 200x300 curve example 4 curve example 4 ``` <img src="http://www.rebol.com/r3/docs/graphics/curve-4.png"/> ''Ellipse'' Draws an ellipse |Argument |Datatype |Description|h |upper-left-point |pair! |The upper-left-point of the ellipse bounding box| |diameter |pair! |X and Y diameter is specified by a pair! which is different than the CIRCLE command| Three overlapping ellipses ``` fill-pen red ellipse 50x25 100x200 fill-pen white ellipse 100x100 200x200 fill-pen blue ellipse 175x250 200x100 ellipse example 1 ellipse example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/ellipse-1.png"/> ''Spline'' The spline command lets you draw a curve through any number of points. The smoothness of the curve will be determined by the segment factor that you specify. |Argument |Datatype |Description|h |segmentation |integer! |Optional. Number of segments between each point; default is 1.| |closed |word! |Optional. 'closed will cause the path to be closed between the start and end points.| ``` point1 pair! point2 pair! ... pair! none spline 20x20 200x70 150x200 50x230 50x300 80x300 200x200 spline example 1 spline example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/spline-1.png"/> ``` spline 3 20x20 200x70 150x200 50x230 50x300 80x300 200x200 spline example 2 spline example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/spline-2.png"/> ``` spline 10 20x20 200x70 150x200 50x230 50x300 80x300 200x200 spline example 3 spline example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/spline-3.png"/> ``` spline 10 closed 20x20 200x70 150x200 50x230 50x300 80x300 200x200 spline example 4 spline example 4 ``` <img src="http://www.rebol.com/r3/docs/graphics/spline-4.png"/>
''Contents'' * Concept * Arrow * Box * Line * Line-cap * Line-join * Line-pattern * Line-width * Polygon * Shape * Triangle ''Concept'' This section describes draw commands that are related to lines, line segments, vertices, polygons and basic shapes. All of these are part of the draw dialect, a REBOL sub-language for describing scalar vector graphics (SVG). The dialect consists of a number of command keywords, as listed in this document below. Each command can be followed by its arguments, all of which are optional. Their names, datatypes, and descriptions are provided in the "argument" table for each command section below. ''Arrow'' Set the `arrow` mode. |Argument |Datatype |Description|h |arrow-mode |pair! |Possible numbers for combination. 0 for none, 1 for head, 2 for tail.| |arrow-color |tuple! |color of the head/tail of the arrow| The arrow-mode numbers can be: Arrow marks are drawn at end-points, but not between the line that closes polygons, closed splines, etc. ``` arrow 1x2 line 20x20 100x100 arrow example 1 arrow example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/arrow-1.png"/> ``` arrow 1x2 curve 50x50 300x50 50x300 300x300 arrow example 2 arrow example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/arrow-2.png"/> ``` arrow 1x2 spline 3 20x20 200x70 150x200 50x300 80x300 200x200 arrow example 3 arrow example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/arrow-3.png"/> ``` arrow 1x2 spline closed 3 20x20 200x70 150x200 50x300 80x300 200x200 arrow example 4 arrow example 4 ``` <img src="http://www.rebol.com/r3/docs/graphics/arrow-4.png"/> ``` arrow 1x2 polygon 20x20 200x70 150x200 50x300 arrow example 5 arrow example 5 ``` <img src="http://www.rebol.com/r3/docs/graphics/arrow-5.png"/> ``` arrow 1x2 box 20x20 150x200 arrow example 6 arrow example 6 ``` <img src="http://www.rebol.com/r3/docs/graphics/arrow-6.png"/> ''Box'' The box command provides a shortcut for a rectangular polygon. Only the upper-left and lower-right points are needed to draw the box. |Argument |Datatype |Description|h |upper-left-point |pair! || |lower-right-point |pair! || |corner-radius |decimal! |Rounds corners| A solid fill-pen will fill the box with that color. ``` fill-pen blue box 20x20 200x200 box example 1 box example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/box-1.png"/> An image used as the fill-pen will be repeated as the background. ``` fill-pen logo.gif box 20x20 200x200 box example 2 box example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/box-2.png"/> line widths, patterns, joins are fully supported. ``` pen red line-pattern yellow 50 30 line-width 30 line-join round box 50x50 350x350 box example 3 box example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/box-3.png"/> ''Line'' The line command draws a line between two points using the current pen, line-width, and line-pattern (if it is set). |Argument |Datatype |Description|h |point1 |pair! |Starting point| |point2 |pair! |End point or vertex point| |point3 |pair! |Next point| |... |pair! |More points| ``` line 10x10 100x50 line example 1 line example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/line-1.png"/> If more than two points are given multiple lines are drawn in a connected fashion: ``` line 10x10 20x50 30x0 4x40 line example 2 line example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/line-2.png"/> Note that the end point is not connected to the first point. To do that, see the polygon command. An example using pens and line attributes: ``` pen yellow line-width 8 line-pattern red 5 5 line 10x10 20x50 30x0 4x40 pen yellow line-width 5 line-cap round line 100x100 100x200 200X100 200X200 line example 3 line example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/line-3.png"/> ''Line-cap'' Sets the style that will be used when drawing the ends of lines. |Argument |Datatype |Description|h |mode |word! |Cap style| The cap style can be: butt, square, or rounded. ``` line-cap butt pen yellow line-width 1 line 20x20 150x20 line-width 3 line 20x40 150x40 line-width 5 line 20x60 150x60 line-width 7 line 20x80 150x80 line-width 9 line 20x100 150x100 line-width 11 line 20x120 150x120 translate 0x140 line-cap square pen yellow line-width 1 line 20x20 150x20 line-width 3 line 20x40 150x40 line-width 5 line 20x60 150x60 line-width 7 line 20x80 150x80 line-width 9 line 20x100 150x100 line-width 11 line 20x120 150x120 translate 160x-70 line-cap rounded pen yellow line-width 1 line 20x20 150x20 line-width 3 line 20x40 150x40 line-width 5 line 20x60 150x60 line-width 7 line 20x80 150x80 line-width 9 line 20x100 150x100 line-width 11 line 20x120 150x120 line-cap example 1 line-cap example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/line-cap-1.png"/> ''Line-join'' Sets the style that will be used where lines are joined. |Argument |Datatype |Description|h |mode |word! |Join style| The join style can be: miter, miter-bevel, round, and bevel. ``` pen yellow line-width 15 line-join miter polygon 20x20 180x130 10x100 translate 0x140 line-join miter-bevel polygon 20x20 180x130 10x100 translate 200x-140 line-join round polygon 20x20 180x130 10x100 translate 0x140 line-join bevel polygon 20x20 180x130 10x100 line-join example 1 line-join example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/line-join-1.png"/> Additional notes about LINE-CAP and LINE-JOIN How are lines drawn: * line draws single lines (even if multiple line points is specified) * spline draws 'connected' lines but the 'head' and 'tail' is splitted (until you specify CLOSED keyword) * polygon always draws 'connected' lines in form of closed shape Effects of LINE-CAP and LINE-JOIN: * line shape of 'head' and 'tail' is affected by LINE-CAP mode * spline shape of 'line joins' is affected by LINE-JOIN mode; if CLOSED is defined shape of 'head' and 'tail' is affected by LINE-CAP mode * polygon shape of all 'line joins' is affected by LINE-JOIN mode ''Line-pattern'' Set the line pattern. The line pattern will remain in effect until it is set to a new value or disabled using off. |Argument |Datatype |Description|h |dash-color |tuple! || |stroke-size |decimal! || |dash-size |decimal! || |stroke-size |decimal! || |dash-size |decimal! || |... |decimal! || Set it to 5 of yellow and 5 of red. ``` anti-alias off pen yellow line-pattern red 5 5 line-width 3 box 20x20 200x200 line-pattern example 1 line-pattern example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/line-pattern-1.png"/> To draw a dashed line, with a transparent pen, the off pen color must come first. To clear the current line pattern, set it to off. ``` anti-alias off pen off line-width 4 line-pattern yellow 7 2 box 20x20 200x200 line-pattern off box 40x40 240x240 pen blue box 60x60 260x260 line-pattern example 2 line-pattern example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/line-pattern-2.png"/> Complex patterns can be specified by repeating values for stroke and dash sizes ``` anti-alias off line-width 4 pen blue line-pattern red 7 2 4 4 3 6 box 20x20 380x380 pen red line-pattern yellow 1 5 box 40x40 360x360 line-pattern off box 60x60 340x340 line-pattern blue 10 20 40 80 box 80x80 320x320 line-pattern green 1 4 4 4 box 100x100 300x300 line-pattern yellow 4 8 12 16 box 120x120 280x280 line-pattern yellow 4 4 box 140x140 260x260 line-pattern example 3 line-pattern example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/line-pattern-3.png"/> ''Line-width'' Sets the line width. |Argument |Datatype |Description|h |width |number! |Zero, or negative values, produce a line-width of 1.| |fixed-width |word! |If fixed is specified. Line width is not changed during scaling.| Default dynamic line width example: ``` line-width 3 pen yellow reset-matrix scale 1.5 1.5 translate 100x100 polygon 50x5 62x40 95x40 68x60 80x95 50x74 20x95 32x60 5x40 38x40 reset-matrix translate 100x100 polygon 50x5 62x40 95x40 68x60 80x95 50x74 20x95 32x60 5x40 38x40 reset-matrix scale .5 .5 translate 100x100 polygon 50x5 62x40 95x40 68x60 80x95 50x74 20x95 32x60 5x40 38x40 reset-matrix scale .2 .2 translate 100x100 polygon 50x5 62x40 95x40 68x60 80x95 50x74 20x95 32x60 5x40 38x40 line-width example 1 line-width example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/line-width-1.png"/> Fixed line width example: ``` line-width 3 fixed pen yellow reset-matrix scale 1.5 1.5 translate 100x100 polygon 50x5 62x40 95x40 68x60 80x95 50x74 20x95 32x60 5x40 38x40 reset-matrix translate 100x100 polygon 50x5 62x40 95x40 68x60 80x95 50x74 20x95 32x60 5x40 38x40 reset-matrix scale .5 .5 translate 100x100 polygon 50x5 62x40 95x40 68x60 80x95 50x74 20x95 32x60 5x40 38x40 reset-matrix scale .2 .2 translate 100x100 polygon 50x5 62x40 95x40 68x60 80x95 50x74 20x95 32x60 5x40 38x40 line-width example 2 line-width example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/line-width-2.png"/> ''Polygon'' The polygon command lets you draw a closed area of line segments. It is similar to the line command, but the first and last points are connected. |Argument |Datatype |Description|h |point1 |pair! || |point2 |pair! || |point3 |pair! || ``` ... pair! polygon 100x100 100x200 200X100 200X200 polygon example 1 polygon example 1 <img src="http://www.rebol.com/r3/docs/graphics/polygon-1.png"/> pen yellow fill-pen orange line-width 5 line-join round polygon 100x100 100x200 200X100 200X200 polygon example 2 polygon example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/polygon-2.png"/> ''Shape'' Draws shapes using the SHAPE sub-dialect |Argument |Datatype |Description|h |shape-cmd-block |block! |For a description of the SHAPE sub-commands along with many examples, see R3 Draw - Shape Sub-Commands.| A selected example is: ``` pen yellow line-width 3 shape [ move 0x399 line 42x357 arc 84x315 25 20 -45 sweep line 126x273 arc 168x231 25 40 -45 sweep line 210x189 arc 252x147 25 60 -45 sweep line 294x105 arc 336x63 25 80 -45 sweep line 399x0 move 0x0 ] Shape example Shape example ``` <img src="http://www.rebol.com/r3/docs/graphics/sarc-4.png"/> ''Triangle'' The TRIANGLE command provides a shortcut for a triangular polygon with optional shading parameters (Gouraud shading). The three vertices of the triangle are used to specify it. |Argument |Datatype |Description|h |vertex1 |pair!|| |vertex2 |pair!|| |vertex3 |pair!|| |color1 |tuple!|| |color2 |tuple!|| |color3 |tuple!|| |dilation |decimal! |This is useful for eliminating anitaliased edges| Simple triangle: ``` fill-pen red triangle 50x150 150x50 150x150 triangle example 1 triangle example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/triangle-1.png"/> A group of triangles. This should make it easy to see where each triangle is: ``` pen off triangle 50x150 150x50 150x150 red green blue triangle 150x50 250x150 150x150 green yellow blue triangle 250x150 150x350 150x150 yellow orange blue triangle 150x350 50x150 150x150 orange red blue translate 200x-15 triangle example 2 triangle example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/triangle-2.png"/> The same triangle group but slightly rotated to show for what the dilation parameter can be used: ``` pen off rotate 5 triangle 50x150 150x50 150x150 red green blue triangle 150x50 250x150 150x150 green yellow blue triangle 250x150 150x350 150x150 yellow orange blue triangle 150x350 50x150 150x150 orange red blue translate 200x-15 triangle 50x150 150x50 150x150 red green blue 0.33 triangle 150x50 250x150 150x150 green yellow blue 0.33 triangle 250x150 150x350 150x150 yellow orange blue 0.33 triangle 150x350 50x150 150x150 orange red blue 0.33 triangle example 3 triangle example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/triangle-3.png"/> This gives you a much more subtle blending in the middle: ``` pen off triangle 50x150 150x50 150x150 red green gray triangle 150x50 250x150 150x150 green yellow gray triangle 250x150 150x350 150x150 yellow orange gray triangle 150x350 50x150 150x150 orange red gray triangle example 4 triangle example 4 ``` <img src="http://www.rebol.com/r3/docs/graphics/triangle-4.png"/> And this shows simple highlighting/shading: ``` pen off triangle 50x150 150x50 150x150 water sky sky triangle 150x50 250x150 150x150 water coal sky triangle 250x150 150x350 150x150 coal coal sky triangle 150x350 50x150 150x150 coal water sky triangle example 5 triangle example 5 ``` <img src="http://www.rebol.com/r3/docs/graphics/triangle-5.png"/>
''Contents'' * Concept * Anti-alias * Clip * Fill-pen * Fill-rule * Gamma * Grad-pen * Invert-matrix * Matrix * Pen * Push * Reset-matrix * Rotate * Scale * Skew * Transform * Translate ''Concept'' This section describes draw commands related to special attributes, matrix setup and various transformations. All of these are part of the draw dialect, a REBOL sub-language for describing scalar vector graphics (SVG). The dialect consists of a number of command keywords, as listed in this document below. Each command can be followed by its arguments, all of which are optional. Their names, datatypes, and descriptions are provided in the "argument" table for each command section below. ''Anti-alias'' Turns anti-aliasing on or off. The default is on. |Argument |Datatype |Description|h |active |logic! |The new value for anti-aliasing behavior| Compare this: ``` anti-alias off line-width 10 circle 200x200 100 anti-alias example 1 anti-alias example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/anti-alias-3.png"/> to this: ``` anti-alias on line-width 10 circle 200x200 100 anti-alias example 2 anti-alias example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/anti-alias-3.png"/> The ANTI-ALIAS command can be used multiple times in the draw block to switch between rendering modes. ``` anti-alias off line-width 10 circle 150x150 100 anti-alias on line-width 10 circle 250x250 100 anti-alias example 3 anti-alias example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/anti-alias-3.png"/> ''Clip'' Specifies a clipping region; drawing will only occur inside the region. |Argument |Datatype |Description|h |upper-left-point |pair! |The upper-left point of the bounding box defining the clipping region.| |lower-right-point |pair! |The lower-right point of the bounding box defining the clipping region.| The box would go to 200x200, but we clip it. ``` line-width 2 pen yellow fill-pen blue clip 10x10 70x90 box 20x20 200x200 clip example 1 clip example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/clip-1.png"/> Clipping other shapes can produce interesting effects. ``` pen yellow fill-pen red clip 50x50 125x200 circle 50x50 100 clip example 2 clip example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/clip-2.png"/> To turn clipping off, use off as the argument to clip. ``` pen yellow fill-pen red clip 50x50 125x200 circle 50x50 100 pen green fill-pen blue clip off circle 125x75 50 clip example 3 clip example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/clip-3.png"/> ''Fill-pen'' Sets the color or image pattern for area filling. The fill-pen color will remain in effect until it is set again, disabled by off keyword or overriden by grad-pen command. |Argument |Datatype |Description|h |color |tuple! || |image |image! |Fill pattern| Simple color fill ``` fill-pen blue box 100x100 300x300 fill-pen example 1 fill-pen example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/fill-pen-1.png"/> Image pattern fill ``` fill-pen logo.gif box 100x100 300x300 fill-pen example 2 fill-pen example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/fill-pen-2.png"/> Switching the fill-pen states ``` fill-pen blue box 100x100 300x300 fill-pen logo.gif box 150x150 250x250 fill-pen off box 50x50 350x350 fill-pen example 3 fill-pen example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/fill-pen-3.png"/> ''Fill-rule'' Determines the algorithm used to determine what area to fill, if a path that intersects itself or one subpath encloses another. For non-intersecting paths, you shouldn't need to use this. |Argument |Datatype |Description|h |mode |word! |Fill algorithm non-zero - This rule determines the "insideness" of a point on the canvas by drawing a ray from that point to infinity in any direction and then examining the places where a segment of the shape crosses the ray. Starting with a count of zero, add one each time a path segment crosses the ray from left to right and subtract one each time a path segment crosses the ray from right to left. After counting the crossings, if the result is zero then the point is outside the path. Otherwise, it is inside. even-odd - This rule determines the "insideness" of a point on the canvas by drawing a ray from that point to infinity in any direction and counting the number of path segments from the given shape that the ray crosses. If this number is odd, the point is inside; if even, the point is outside.| The following page has drawings that drawing illustrates the rules: Fill Properties ''Gamma'' Sets the gamma correction value. Useful for antialiased graphics. |Argument |Datatype |Description|h |gamma-value |decimal! || See also: [[Linear and nonlinear coding|http://poynton.ca/notes/Timo/index.html]] ''Grad-pen'' Sets the color gradient for area filling. The gradient can be defined by up to 256 colors. Each defined color can have specified color offset for creating gradients with asymmetric color ranges. |Argument |Datatype Description|h |grad-type |word! |The gradient type radial conic diamond linear diagonal cubic| |grad-mode |word! |The gradient rendering mode normal repeat reflect| |grad-offset |pair! |offset from where should the gradient be rendered| |grad-start-rng |decimal! |beginning of the gradient range| |grad-stop-rng |decimal! |end of the gradient range| |grad-angle |decimal! |rotation of the gradient in degrees| |grad-scale-x |decimal! |scale X factor| |grad-scale-y |decimal! |scale Y factor| |grad-colors |block! |block containing up to 256 gradient colors (optionally with color offsets)| The grad-colors block can be in the form: ``` [color1 [pair! color2 [pair! color3 [pair! ...] ``` or: ``` [color1 [pair! offset1 [decimal! color2 [pair! offset3 [decimal! color3 [pair! offset3 [decimal! ...] ``` NOTE: At the moment the color values inside the block have to be reduced in case of word! references are used for colors. Simple linear gradient ``` grad-pen linear 100x100 0 200 [255.0.0 0.255.0 0.0.255] box 100x100 300x300 grad-pen example 1 grad-pen example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/grad-pen-1.png"/> Linear gradient with compressed range ``` grad-pen linear 100x100 0 50 [255.0.0 0.255.0 0.0.255] box 100x100 300x300 grad-pen example 2 grad-pen example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/grad-pen-2.png"/> Linear gradient in repeat mode ``` grad-pen linear repeat 100x100 0 50 [255.0.0 0.255.0 0.0.255] box 100x100 300x300 grad-pen example 3 grad-pen example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/grad-pen-3.png"/> Linear gradient in reflect mode ``` grad-pen linear reflect 100x100 0 50 [255.0.0 0.255.0 0.0.255] box 100x100 300x300 grad-pen example 4 grad-pen example 4 ``` <img src="http://www.rebol.com/r3/docs/graphics/grad-pen-4.png"/> Linear gradient with more colors ``` grad-pen linear 100x100 0 200 [255.0.0 255.255.0 0.255.0 0.255.255 0.0.255 255.0.255] box 100x100 300x300 grad-pen example 5 grad-pen example 5 ``` <img src="http://www.rebol.com/r3/docs/graphics/grad-pen-5.png"/> Linear gradient with color offsets ``` grad-pen linear 100x100 0 200 [255.0.0 0.1 255.255.0 0.2 0.255.0 0.4 0.255.255 0.8 0.0.255 .9 255.0.255 1.0] box 100x100 300x300 grad-pen example 6 grad-pen example 6 ``` <img src="http://www.rebol.com/r3/docs/graphics/grad-pen-6.png"/> Simple radial gradient ``` grad-pen radial 200x200 0 100 [255.0.0 0.255.0 0.0.255] box 100x100 300x300 grad-pen example 7 grad-pen example 7 ``` <img src="http://www.rebol.com/r3/docs/graphics/grad-pen-7.png"/> Diamond gradient with applied rotation ``` grad-pen diamond 200x200 0 100 30 [255.0.0 0.255.0 0.0.255] box 100x100 300x300 grad-pen example 8 grad-pen example 8 ``` <img src="http://www.rebol.com/r3/docs/graphics/grad-pen-8.png"/> Diamond gradient with applied rotation and scaling ``` grad-pen diamond 200x200 0 100 30 3.0 1.5 [255.0.0 0.255.0 0.0.255] box 100x100 300x300 grad-pen example 9 grad-pen example 9 ``` <img src="http://www.rebol.com/r3/docs/graphics/grad-pen-9.png"/> To disable the grad-pen set it to off. After that latest fill-pen state is used for filling the areas. ``` fill-pen red grad-pen linear 100x100 0 200 [255.0.0 0.255.0 0.0.255] box 100x100 300x300 grad-pen off box 150x150 250x250 grad-pen example 10 grad-pen example 10 ``` <img src="http://www.rebol.com/r3/docs/graphics/grad-pen-10.png"/> Mention DIAGONAL, CONIC, CUBIC gradient here. ''Invert-matrix'' Applies an algebraic matrix inversion operation on the current transformation matrix. This command has no arguments. ''Matrix'' Premultiply the current transformation matrix with the given block. |Argument |Datatype |Description|h |matrix-setup |block! |content must be 6 numbers| MATRIX [a b c d e f] The block values are used internally for building following transformation matrix: |a |c |e| |b |d |f| |0 |0 |1| For more information about transformations see: SVG Coordinates. ''Pen'' Sets the color or image for outline rendering. |Argument |Datatype |Description|h |stroke-color |tuple! |Primary line color| |dash-color |tuple! |Used for patterned lines| |image |image! || The colors can include an alpha channel value for transparency. Setting pen to off will disable the pen color to fully transparent. ``` line-width 3 pen yellow box 20x20 200x200 pen off fill-pen blue box 50x50 250x250 pen logo.gif fill-pen off box 100x100 300x300 pen example 1 pen example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/pen-1.png"/> ''Push'' Stores the current attribute setup in stack. |Argument |Datatype |Description|h |draw-block |block! || The PUSH command stores the whole DRAW attribute settings (including matrix and pen settings) into the stack. You can then change the current transformation matrix, pens etc. inside the PUSH command block but all commands AFTER the PUSH command block will use the attribute setup setup stored by the PUSH command. ``` line-width 3 pen red transform 200x200 30 1 1 0x0 box 100x100 300x300 push [ reset-matrix pen green box 100x100 300x300 transform 200x200 60 1 1 0x0 pen blue box 100x100 300x300 ] box 180x180 220x220 pen white box 150x150 250x250 push example 1 push example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/push-1.png"/> ''Reset-matrix'' Resets the current transformation matrix to its default values. The default transformation matrix is a unit matrix. That is: |1 |0 |0| |0 |1 |0| |0 |0 |1| If you make changes with scale, skew, or rotate, this is how you would reset them. ''Rotate'' Sets the clockwise rotation, in degrees, for drawing commands. |Argument |Datatype |Description|h |angle |decimal! |The angle in degrees.| Negative numbers can be used for counter-clockwise rotation. ``` fill-pen blue box 100x100 300x300 rotate 30 fill-pen red box 100x100 300x300 rotate -60 fill-pen yellow box 100x100 300x300 rotate example 1 rotate example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/rotate-1.png"/> Scale Sets the scale for drawing commands. |Argument |Datatype |Description|h |scale-x |decimal! || |scale-y |decimal! || The values given are multipliers; use values greater than one to increase the scale; use values less than one to decrease it. ``` fill-pen blue box 100x100 200x200 scale 2 .5 fill-pen red box 100x100 200x200 reset-matrix ; Reset the scale. scale .5 1.5 fill-pen yellow box 100x100 200x200 scale example 1 scale example 1 Another way to reset the scale is to use the PUSH command: <img src="http://www.rebol.com/r3/docs/graphics/scale-1.png"/> fill-pen blue box 100x100 200x200 push [scale 2 .5 fill-pen red box 100x100 200x200] scale .5 1.5 fill-pen yellow box 100x100 200x200 scale example 2 scale example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/scale-2.png"/> For more information about transformations see: [[SVG Coordinates|https://www.w3.org/TR/SVG/coords.html#EstablishingANewUserSpace]]. ''Skew'' Sets a coordinate system skewed from the original by the given number of degrees. |Argument |Datatype |Description|h |val |decimal! || Positive numbers skew to the right; negative numbers skew to the left. Note: Currently the skewing transformation has effect on the line width in case fixed is not specified: ``` line-width 1 fixed pen white fill-pen blue box 120x20 220x120 skew 15 fill-pen red box 120x125 220x225 reset-matrix skew -15 fill-pen yellow box 120x230 220x330 skew example 1 skew example 1 ``` Another way to reset the skew is to use the PUSH command: <img src="http://www.rebol.com/r3/docs/graphics/skew-1.png"/> ``` line-width 1 fixed pen white fill-pen blue box 120x20 220x120 push [ skew 15 fill-pen red box 120x125 220x225 ] skew -15 fill-pen yellow box 120x230 220x330 skew example 2 skew example 2 ``` ''Transform'' <img src="http://www.rebol.com/r3/docs/graphics/skew-2.png"/> You can apply a transformation such as translation, scaling, and rotation to any DRAW result. |Argument |Datatype |Description|h |angle |decimal! || |center |pair! || |scale-x |decimal! || |scale-y |decimal! || |translation |pair! || ''Translate'' Sets the origin for drawing commands. |Argument |Datatype |Description|h |offset |pair! || Multiple translate commands will have a cumulative effect: ``` fill-pen blue box 50x50 150x150 translate 50x50 fill-pen red box 50x50 150x150 translate 50x50 fill-pen yellow box 50x50 150x150 translate example 1 translate example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/translate-1.png"/> You can use RESET-MATRIX to avoid that if you want: ``` fill-pen blue box 50x50 150x150 translate 50x50 fill-pen red box 50x50 150x150 reset-matrix translate 50x50 fill-pen yellow box 100x100 300x300 translate example 2 translate example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/translate-2.png"/> Another way to reset the matrix is to use the PUSH command: ``` fill-pen blue box 50x50 150x150 push [translate 50x50 fill-pen red box 50x50 150x150] translate 50x50 fill-pen yellow box 100x100 300x300 translate example 3 translate example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/translate-3.png"/>
''Contents'' * Concept * Arc * Close * Curv * Curve * Hline * Line * Move * Qcurv * Qcurve * Vline ''Concept'' This section describes special commands optimized for describing shapes. All of these commands are used withing the shape argument block and should not be used separately. ''Arc'' Draws an elliptical arc from the current point. |Argument |Datatype |Description|h |end-point |pair! || |radius-x |decimal! || |radius-y |decimal! || |angle |decimal! || |sweep |word! |the arc will be drawn in a "positive angle" direction sweep|| |large |word! |one of the large arc sweeps will be chosen large| Simple arc example: ``` pen yellow line-width 3 shape [ move 100x200 arc 300x200 120 50 0 ] arc example 1 arc example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/sarc-1.png"/> Set SWEEP to draw arcs in a "positive-angle" direction: ``` pen yellow line-width 3 shape [ move 100x200 arc 300x200 120 50 0 sweep ] arc example 2 arc example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/sarc-2.png"/> Set LARGE for arc sweeps greater than 180 degrees: ``` pen yellow line-width 3 shape [ move 100x200 arc 300x200 120 50 0 sweep large ] arc example 3 arc example 3 ``` <img src="http://www.rebol.com/r3/docs/graphics/sarc-3.png"/> More complex usage of arc: ``` pen yellow line-width 3 shape [ move 0x399 line 42x357 arc 84x315 25 20 -45 sweep line 126x273 arc 168x231 25 40 -45 sweep line 210x189 arc 252x147 25 60 -45 sweep line 294x105 arc 336x63 25 80 -45 sweep line 399x0 move 0x0 ] arc example 4 arc example 4 ``` <img src="http://www.rebol.com/r3/docs/graphics/sarc-4.png"/> Same complex example but with relative positioning commands: ``` pen red line-width 3 translate 0x399 shape [ move 0x0 'line 42x-42 'arc 42x-42 25 20 -45 sweep 'line 42x-42 'arc 42x-42 25 40 -45 sweep 'line 42x-42 'arc 42x-42 25 60 -45 sweep 'line 42x-42 'arc 42x-42 25 80 -45 sweep 'line 63x-63 move 0x0 ] arc example 5 arc example 5 ``` <img src="http://www.rebol.com/r3/docs/graphics/sarc-5.png"/> ''Close'' Closes previously defined set of lines in the SHAPE block. This command has no arguments. In some case it is easier to use the CLOSE command as a shortcut instead of calculating the closing lines. This is without CLOSE commands: ``` line-width 3 pen yellow shape [ move 100x100 hline 50 arc 100x50 50 50 0 large move 75x75 vline 25 arc 25x75 50 50 0 move 0x160 line 200x160 200x0 0x0 ] close example 1 close example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/close-1.png"/> And here with CLOSE commands: ``` line-width 3 pen yellow shape [ move 100x100 hline 50 arc 100x50 50 50 0 large close move 75x75 vline 25 arc 25x75 50 50 0 close move 0x160 line 200x160 200x0 0x0 ] close example 2 close example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/close-2.png"/> ''Curv'' Smooth CURVE command shortcut. |Argument |Datatype |Description|h |point1 |pair! || |point2 |pair! || |point1 |pair! || |... |pair! || From http://www.w3.org/TR/SVG11/paths.html: "The first control point is assumed to be the reflection of the second control point on the previous command relative to the current point. (If there is no previous curve command, the first control point is the current point.)" Simple example: ``` line-width 3 pen yellow shape [ move 100x50 vline 150 curv 300x150 300x50 move 0x0 ] curv example 1 curv example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/curv-1.png"/> Same example but with relative positioning commands: ``` line-width 3 pen red shape [ 'move 100x50 'vline 100 'curv 200x0 200x-100 move 0x0 ] curv example 2 curv example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/curv-2.png"/> ''Curve'' Draws a cubic Bézier curve. |Argument |Datatype |Description|h |point1 |pair! || |point2 |pair! || |point3 |pair! || |point4 |pair! || |... |pair! || A cubic Bézier curve is defined by a start point, an end point, and two control points. ``` line-width 3 pen yellow shape [ move 100x50 curve 100x150 300x150 300x50 move 0x0 ] curve example 1 curve example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/scurve-1.png"/> Same example but with relative positioning commands: ``` line-width 3 pen red shape [ move 100x50 'curve 0x100 200x100 200x0 move 0x0 ] curve example 2 curve example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/scurve-2.png"/> ''Hline'' Draws a horizontal line from the current point. |Argument |Datatype |Description|h |end-x |decimal! || Using absolute coordinates: ``` pen yellow line-width 4 shape [ move 100x100 hline 300 move 100x150 hline 250 move 100x200 hline 200 ] hline example 1 hline example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/hline-1.png"/> Using relative coordinates: ``` pen red line-width 4 shape [ move 100x100 'hline 200 'move -200x50 'hline 150 'move -150x50 'hline 100 ] hline example 2 hline example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/hline-2.png"/> ''Line'' Draws a line from the current point through the given points, the last of which becomes the new current point. |Argument |Datatype |Description|h |point1 |pair! || |point2 |pair! || |point3 |pair! || |point4 |pair! || |... |pair! || Using absolute coordinates: ``` pen yellow line-width 4 shape [ move 50x50 line 300x120 50x120 300x50 move 0x0 ] line example 1 line example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/sline-1.png"/> Using relative coordinates: ``` pen red line-width 4 shape [ move 50x50 move 50x50 'line 250x70 -250x0 250x-70 move 0x0 ] line example 2 line example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/sline-2.png"/> ''Move'' Set's the starting point for a new path without drawing anything. |Argument |Datatype |Description|h |point1 |pair! || The effect is as if the "pen" were lifted and moved to a new location. Used at the end of a SHAPE command, MOVE prevents the shape from being drawn as a closed polygon. Note: Every path defined in SHAPE block is automatically closed. To disable the auto-close feature just put at the end of the SHAPE block: move 0x0 ``` line-width 4 pen red shape [ move 100x100 line 20x20 150x50 move 0x0 ] pen blue shape [ move 100x200 line 20x120 150x150 ] move example 1 move example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/move-1.png"/> Using relative coordinates for the second shape: ``` line-width 4 pen red shape [ move 100x100 line 20x20 150x50 move 0x0 ] pen blue shape [ move 100x100 'move 0x100 'line -80x-80 130x30 'move 0x0 ] move example 2 move example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/move-2.png"/> ''Qcurv'' Smooth QCURVE command shortcut. |Argument |Datatype |Description|h |point1 |pair! || Draws a cubic Bézier curve from the current point to point1. See: http://www.w3.org/TR/SVG11/paths.html and CURV Using absolute coordinates: ``` pen yellow line-width 4 shape [ move 0x150 qcurve 100x250 200x150 qcurv 400x150 move 0x0 ] qcurv example 1 qcurv example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/qcurv-2.png"/> Using relative coordinates: ``` pen red line-width 4 shape [ move 0x150 'qcurve 100x100 200x0 'qcurv 200x0 move 0x0 ] qcurv example 2 qcurv example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/qcurv-2.png"/> ''Qcurve'' Draws quadratic Bézier curve. |Argument |Datatype |Description|h |point1 |pair! || |point2 |pair! || |point3 |pair! || |... |pair! || A quadratic Bézier curve is defined by a start point, an end point, and one control point. Using absolute coordinates: ``` pen yellow line-width 4 shape [ move 100x50 qcurve 200x150 300x50 move 0x0 ] qcurve example 1 qcurve example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/qcurve-2.png"/> Using relative coordinates: ``` pen red line-width 4 shape [ move 100x50 'qcurve 100x100 200x0 move 0x0 ] qcurve example 2 qcurve example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/qcurve-2.png"/> ''Vline'' Draws a vertical line from the current point. |Argument |Datatype |Description|h |end-y |decimal! || Using absolute coordinates: ``` pen yellow line-width 4 shape [ move 100x100 vline 300 move 150x100 vline 250 move 200x100 vline 200 ] vline example 1 vline example 1 ``` <img src="http://www.rebol.com/r3/docs/graphics/vline-1.png"/> Using relative coordinates: ``` pen red line-width 4 shape [ move 100x100 'vline 200 'move 50x-200 'vline 150 'move 50x-150 'vline 100 ] vline example 2 vline example 2 ``` <img src="http://www.rebol.com/r3/docs/graphics/vline-2.png"/>
http://www.rebol.com/view/docs/developer/draw-commands.txt ``` DRAW-BLOCK COMMANDS (23-Jun-2005/15:13:00) ----------------------------------------------- Command Arguments Note ANTI-ALIAS disable [logic!] ARC center [pair!] radius [pair!] angle-begin [decimal!] angle-length [decimal!] closed [word!] ARROW arrow-mode [pair!] possible numbers for combination in pair!:0-none 1-head 2-tail BOX upper-left-point [pair!] lower-right-point [pair!] corner-radius [decimal!] specify only when need rounded-box result CIRCLE center [Pair!] radius-x [decimal!] radius-y [decimal!] CLIP upper-left-point [pair!] lower-right-point [pair!] CURVE point1 [pair!] point2 [pair!] point3 [pair!] point4 [pair!] ELLIPSE center [pair!] radius [pair!] note: X and Y radius is specified by pair! unlike in CIRCLE command FILL-PEN color [tuple!] grad-mode [word!] possible modes: radial conic diamond linear (x) diagonal (xy) cubic (square-root xy) grad-offset [pair!] grad-start-rng [decimal!] grad-stop-rng [decimal!] grad-angle [decimal!] grad-scale-x [decimal!] grad-scale-y [decimal!] grad-color1 [tuple!] grad-color2 [tuple!] grad-color3 [tuple!]... image [image!] uses image as filling pattern FILL-RULE mode [word!] possible modes: non-zero even-odd FONT font-object [object!] GAMMA gamma-value [decimal!] INVERT-MATRIX IMAGE image [image!] upper-left-point [pair!] upper-right-point [pair!] lower-left-point [pair!] lower-right-point [pair!] key-color [tuple!] border [word!] IMAGE-FILTER filter-type [word!] modes: nearest bilinear LINE point1 [pair!] point2 [pair!] point3 [pair!] ... LINE-CAP mode [word!] modes: butt square round LINE-JOIN mode [word!] modes: miter miter-bevel round bevel LINE-PATTERN stroke-size [decimal!] dash-size [decimal!] stroke-size [decimal!] dash-size [decimal!] ... LINE-WIDTH width [decimal!] MATRIX matrix-setup [block!] PEN stroke-color [tuple!] dash-color [tuple!] image [image!] POLYGON point1 [pair!] point2 [pair!] point3 [pair!] ... PUSH draw-block [block!] note: stores matrix setup in stack POP RESET-MATRIX ROTATE angle [decimal!] SCALE scale-x [decimal!] scale-y [decimal!] SHAPE shape-cmd-block [block!] SKEW val [decimal!] SPLINE segmentation [integer!] closed [word!] point1 [pair!] point2 [pair!] ... TEXT text-string [string!] offset [pair!] render-mode [word!] modes: anti-aliased vectorial (can be transformed and with possible stroke/dashes etc.) aliased TRANSFORM angle [decimal!] center [pair!] scale-x [decimal!] scale-y [decimal!] translation [pair!] TRANSLATE offset [pair!] TRIANGLE vertex1 [pair!] vertex2 [pair!] vertex3 [pair!] color1 [tuple!] color2 [tuple!] color3 [tuple!] dilatation [decimal!] this is useful to eliminate anitaliased edges in some cases SHAPE-BLOCK COMMANDS -------------------- Command Arguments Note ARC point1 [pair!] LARGE and SWEEP should be keywords too radius-x [decimal!] radius-y [decimal!] angle [decimal!] sweep [logic!] large [logic!] CURV point1 [pair!] point2 [pair!] point1 [pair!] ... CURVE point1 [pair!] point2 [pair!] point3 [pair!] point1 [pair!] ... HLINE length [decimal!] LINE point1 [pair!] point2 [pair!] point3 [pair!] point4 [pair!] ... MOVE point1 [pair!] QCURV point1 [pair!] QCURVE point1 [pair!] point2 [pair!] point1 [pair!] ... VLINE length [decimal!] ```
The `/dup` refinement changes or inserts a value a specified number of times. Examples: ``` str: "abcdefghi" blk: [1 2 3 4 5 6] ``` You can change the first four values in a string or block series to an asterisk `()` ''with'': ``` change/dup str "*" 4 probe str ****efghi ``` ``` change/dup blk "*" 4 probe blk ["*" "*" "*" "*" 5 6] ``` To insert a dash `-` four times before the last value in a string or block: ``` insert/dup (back tail str) #"-" 4 probe str ****efgh==-i ``` ``` insert/dup (back tail blk) #"-" 4 probe blk ["*" "*" "*" "*" 5 #"-" #"-" #"-" #"-" 6] ```
Modules are also allowed to be created dynamically by a program. This is normally done for two reasons: * The modules are used to isolate separate parts of a program's namespace (similar to how objects have been used in the past). * The program has been constructed by combining multiple source files, some of which are modules. The modules are within the body of the file, rather than loaded as separate files at run time. For more about these types of modules, see [[modules: defining modules|Concepts: Modules: Defining Modules]].
For large output, REBOL provides an echo mode. You can enable it with: ``` echo on ``` to produce a file called output.txt or you can write: ``` echo %textfile.txt ``` for any filename you want. Use: ``` echo off ``` to close the file. It is also closed when you exit REBOL.
The [[either|Functions: either]] function is used to evaluate one of two blocks. It's what you use for an if-else type of expression. (REBOL does not use else.) The either function takes one condition and two blocks: ``` n: 10 print either n > 20 ["greater"] ["not greater"] not greater ``` Any condition that is false or none will evaluate the second block. And like [[if|Functions: if]], [[either|Functions: either]] returns a value, depending on which block it evaluated: ``` print either n > 20 ["greater"] ["not greater"] not greater ``` Also, the block values can be variables, defined earlier or even returned as results from other functions: ``` then-block: [n - 2] else-block: [n + 2] n: 10 print either n > 20 then-block else-block 12 ```
Both code and data are combinations of elements called |''values'' |the datatypes of the language| Important values are |''words'' |notated in a few ways.| |''blocks'' |combinations of values.| There are also |''comments'' |text that is ignored by the language|
Email addresses are written directly in REBOL. They must include an at sign (@). For example: ``` info@rebol.com pres-bill@oval.whitehouse.gov ```
You can also use strings for comments. For instance, you can create multi-line comments with a string enclosed in braces: ``` { This is a long multilined comment. } ``` This technique of commenting works only when the string is not interpreted as an argument to a function. If you want to make sure that a multi-line comment is recognized as a comment and is not interpreted as code, precede the string with the word comment : ``` comment { This is a long multilined comment. } ``` The [[comment|Functions: comment]] function tells REBOL to ignore the following block or string. <<< Watch out String and block comments are actually part of the script block. Care should be taken to avoid placing them in data blocks, because they would appear as part of the data. <<<
It is often useful to build in debugging functions as part of the script. This is especially true of networking and file handling scripts where it is not desirable to send and write files while running in test mode. Such tests can be enabled with a control variable at the head of the script. ``` verbose: on check-data: off ```
While you're in the process of creating the function, it is useful to add a few documentation strings to the definition. For example: ``` sum2: func [ "Adds two numbers and returns the result." a [number!] "The first number" b [number!] "The second number" ] [ a + b ] ``` You can now ask for [[help|Functions: help]] about the `sum2` function: ``` ? sum2 USAGE: SUM2 a b DESCRIPTION: Adds two numbers and returns the result. SUM2 is a function value. ARGUMENTS: a -- The first number (number!) b -- The second number (number!) ``` A little documentation can go a long way.
Where appropriate, provide examples within a script to show how the script operates and to give users a quick way of verifying that the script works correctly on their system.
A malformed file path was used. Message: ``` ["Bad file path:" :arg1] ``` Example: ``` filter-error try [read %/] ```
Specific documentation on this error has yet to be provided. Message: ``` "access error" ``` Example: ``` (you can provide one) ```
An attempt was made to close a port that had already been closed. Message: ``` ["Port" :arg1 "already closed"] ``` Example: ``` p: open %file.txt close p filter-error try [close p] ** Access Error: Port file.txt not open ** Where: close p ```
An attempt was made to open a port that was already open. Message: ``` ["Port" :arg1 "already open"] ``` Example: ``` p: open %file.txt filter-error try [open p] ** Access Error: Port file.txt already open ** Where: open p ```
An attempt was made to [[alias|Functions: alias]] a word that had already been aliased. Message: ``` ["Alias word is already in use:" :arg1] ``` Example: ``` alias 'print "prink" filter-error try [alias 'probe "prink"] ** Script Error: Alias word is already in use: prink ** Where: alias 'probe "prink" ```
The [[assert|Functions: assert]] function has thrown an error. (See that function for more information.) Message: ``` ["assertion failed for:" :arg1] ``` Example: ``` num: 10 assert [num > 20] ** Script error: assertion failed for: [num > 20] ** Where: assert ** Near: assert [num > 20] ```
This is a general error for any function that needs it, including external modules or other subsystems. Message: ``` [:arg1 "error:" :arg2] ``` Example: ``` cause-error 'script 'bad-bad [decoder "data in wrong format"] ** script error: decoder error: "data in wrong format" ```
A word that is being constructed with [[make|Functions: make]] or to contains invalid characters. Message: ``` ["invalid character in:" :arg1] ``` Remedy: Words must be valid UTF-8. If the word is constructed from a Unicode string, it must result in correct conversion to UTF-8.
Specific documentation on this error has yet to be provided. Message: ``` "invalid command format (extension function)" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "missing or unsupported encoding marker" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["invalid extension format:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["cannot set" :arg1 "field to" :arg2 "datatype"] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["bad file mode:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["bad file path:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["function argument" :arg1 "is not valid"] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["invalid function definition:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["invalid or missing intrinsic function:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["cannot MAKE/TO" :arg1 "from:" :arg2] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["bad media data (corrupt image, sound, video)"] ``` Example: ``` (you can provide one) ```
A path was evaluated that began with an invalid word. Message: ``` ["Bad path:" arg1] ``` Example: ``` path: make path! [1 2 3] filter-error try [path] ** Internal Error: Bad path: 1 ** Where: path ```
Specific documentation on this error has yet to be provided. Message: ``` ["cannot set" :arg2 "in path" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["path" :arg1 "is not valid for" :arg2 "type"] ``` Example: ``` (you can provide one) ```
An attempt was made to perform an unsupported action on a port. For instance, when trying to use find on a TCP port. Message: ``` ["Cannot use" :arg1 "on this type port"] ```
An attempt was made to decompress a binary value that was corrupt or not a compressed format. Message: ``` ["Invalid compressed data - problem:" :arg1] ``` Example: ``` compressed: compress {some data} change compressed "1" filter-error try [decompress compressed] ** Script Error: Invalid compressed data - problem: -3 ** Where: decompress compressed ```
Specific documentation on this error has yet to be provided. Message: ``` ["incompatible refinement:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "incompatible or invalid refinements" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "invalid series" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "expected block of lines" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["external process failed:" :arg1] ``` Example: ``` (you can provide one) ```
A file could not be accessed. This could be a local or network file. Most common reason for this error is a nonexistent directory. Message: ``` ["Cannot open" :arg1] ``` Example: ``` filter-error try [read %/c/path-not-here] ** Access Error: Cannot open /c/path-not-here ** Where: read %/c/path-not-here ```
An attempt was made to perform an operation on a value of an incompatible datatype. For instance, when attempting to add a string to a number. Message: ``` ["Cannot use" :arg1 "on" :arg2 "value"] ``` Example: ``` filter-error try [1 + "1"] ** Script Error: Cannot use add on string! value ** Where: 1 + "1" ```
Specific documentation on this error has yet to be provided. Message: ``` "deprecated function not allowed" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["incorrect" :arg1 "dialect usage at:" :arg2] ``` Example: ``` (you can provide one) ```
A function was evaluated that had multiple occurrences of a word defined in its specification block. For instance, if the word arg was defined as both argument one and two. Message: ``` ["Duplicate function value:" :arg1] ``` Example: ``` filter-error try [f: func [a /local a][print a]] ** Script Error: Duplicate function value: a ** Where: func [a /local a] [print a] ```
Specific documentation on this error has yet to be provided. Message: ``` "ELSE is obsolete - use the EITHER function" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["exit occurred"] ``` Example: ``` (you can provide one) ```
A function was provided an argument of a datatype it wasn't expecting. Message: ``` [:arg1 "expected" :arg2 "argument of type:" :arg3] ``` Example: ``` f: func [b [block!]][probe b] filter-error try [f "string"] ** Script Error: f expected b argument of type: block ** Where: f "string" ```
Two series values were used together in a way that was not compatible. For instance, when trying to do a union between a string and a block. Message: ``` ["Expected one of:" :arg1 "- not:" :arg2] ``` Example: ``` filter-error try [union [a b c] "a b c"] ** Script Error: Expected one of: block! - not: string! ** Where: union [a b c] "a b c" ```
Specific documentation on this error has yet to be provided. Message: ``` [:arg1 :arg2 "field must be of type" :arg3] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["expected" :arg1 "not" :arg2] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["extension cannot be initialized (check version):" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "feature not available" ``` Example: ``` (you can provide one) ```
The maximum allowable number of defined global words has been exceeded. Message: ``` ["No more global variable space"] ```
An attempt was made to evaluate a file as a REBOL script and the file did not have a REBOL header. Message: ``` Script is missing a REBOL header ``` Example: ``` write %no-header.r {print "data"} filter-error try [do %no-header.r] ** Syntax Error: Script is missing a REBOL header ** Where: do %no-header.r ```
Specific documentation on this error has yet to be provided. Message: ``` "not allowed - would expose or modify hidden values" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "internal error" ``` Example: ``` (you can provide one) ```
Data could not be translated into a valid REBOL datatype. In other words, a malformed value was evaluated. Message: ``` ["Invalid" :arg1 "--" :arg2] ``` Example: ``` filter-error try [load "1024AD"] ** Syntax Error: Invalid integer -- 1024AD ** Where: (line 1) 1024AD ```
Specific documentation on this error has yet to be provided. Message: ``` ["invalid port actor (must be native or object)"] ``` Example: ``` (you can provide one) ```
This is a generic error for handling values that were used improperly. For instance, when a set-word is used inside of a function's specification block. Message: ``` ["Invalid argument:" :arg1] ``` Example: ``` filter-error try [f: func [word:][probe word]] ** Script Error: Invalid argument: word ** Where: func [word:] [probe word] ```
Specific documentation on this error has yet to be provided. Message: ``` "contains invalid characters" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["invalid checksum (tampered file):" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["cannot compare" :arg1 "with" :arg2] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["data not in correct format:" :arg1] ``` Example: ``` (you can provide one) ```
An attempt was made to use an operator that had been redefined. The operator used is no longer a valid operator. Message: ``` ["Invalid operator:" :arg1] ``` Example: ``` *: "operator redefined to a string" filter-error try [5 * 10] ** Script Error: Invalid operator: * ** Where: 5 * 10 ```
Specific documentation on this error has yet to be provided. Message: ``` ["invalid /part count:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["invalid port object (invalid field values)"] ``` Example: ``` (you can provide one) ```
An attempt was made to create a port with make using a specification that a port could not be built from. Message: ``` ["Invalid port spec:" :arg1] ``` Example: ``` filter-error try [p: make port! [scheme: 'naughta]] ** Access Error: Invalid port spec: scheme naughta ** Where: p: make port! [scheme: 'naughta] ```
Specific documentation on this error has yet to be provided. Message: ``` [:arg1 "type is not allowed here"] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["internal limit reached:" :arg1] ``` Example: ``` (you can provide one) ```
An attempt was made to modify a protected word. The word will have been protected with the protect function. Message: ``` ["Word" :arg1 "is protected, cannot modify"] ``` Example: ``` my-word: "data" protect 'my-word filter-error try [my-word: "new data"] ** Script Error: Word my-word is protected, cannot modify ** Where: my-word: "new data" ```
The format of a source code datatype constructor was incorrect and cannot be loaded. Message: ``` ["invalid constructor:" :arg1] ``` Remedy: Most datatypes don't require the `#[]` constructor format. It's used for special literal values or values that include internal information such as series with index offsets. Try using load `[bad-link:functions/moldall.txt]` on the value to determine if the original value can be reloaded or if some other construction method is necessary.
Specific documentation on this error has yet to be provided. Message: ``` "math error" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "too many natives" ``` Example: ``` (you can provide one) ```
A block, string or paren expression was left unclosed. Message: ``` ["Missing" :arg2 "at" :arg1] ``` Example: ``` filter-error try [load "("] ** Syntax Error: Missing ) at end-of-script ** Where: (line 1) ( ```
Specific documentation on this error has yet to be provided. Message: ``` "missing a required argument or refinement" ``` Example: ``` (you can provide one) ```
An attempt was made to define a word to nothing. A set-word was used without an argument. Message: ``` [:arg1 "needs a value"] ``` Example: ``` filter-error try [set-to-nothing:] ** Script Error: set-to-nothing needs a value ** Where: set-to-nothing: ```
An attempt was made within a script to change the security to a lower level of security that was denied. This is to say, whenever a script requests a lower security setting and the user denies the request, this error is thrown. Message: ``` ["Attempt to change security level to" :arg1] ``` Example: ``` secure quit filter-error try [secure none] ; denied request secure none ```
A function was evaluated without providing it with all the arguments it was expecting. Message: ``` [:arg1 "is missing its" :arg2 "argument"] ``` Example: ``` f: func [b][probe b] filter-error try [f] ** Script Error: f is missing its b argument ** Where: f ```
Specific documentation on this error has yet to be provided. Message: ``` ["port has no data buffer:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["cannot decode or encode (no codec):" :arg1] ``` Example: ``` (you can provide one) ```
A connection to another host failed. This is generic error covering a range of reasons for the connection failure. When more information is known about the reason for the connection failure, a more specific error will be thrown. Message: ``` ["Cannot connect to" :arg1] ``` Example: ``` filter-error try [read http://www.host.dom/] ** Access Error: Cannot connect to www.host.dom ** Where: read http://www.host.dom/ ```
Specific documentation on this error has yet to be provided. Message: ``` ["cannot create:" :arg1] ``` Example: ``` (you can provide one) ```
An attempt was made to delete a file that was either locked or protected. Message: ``` ["Cannot delete" :arg1] ``` Example: ``` p: open %file.txt filter-error try [delete %file.txt] ** Access Error: Cannot delete file.txt ** Where: delete %file.txt ```
Specific documentation on this error has yet to be provided. Message: ``` ["cannot open extension:" :arg1] ``` Example: ``` (you can provide one) ```
The file to be evaluated is missing its REBOL header. Message: ``` ["script is missing a REBOL header:" :arg1] ``` Details: To evaluate a file as code, a header is required. The header provides information like the title, date, author, and much more. See [[scripts: headers|Concepts: Scripts: Headers]] for more detail.
Specific documentation on this error has yet to be provided. Message: ``` ["cannot load: " :arg1] ``` Example: ``` (you can provide one) ```
An attempt was made to create a directory in a file path that did not exist or was write protected. Message: ``` ["Cannot make directory" :arg1] ``` Example: ``` filter-error try [make-dir %/c/no-path/dir] ** Access Error: Cannot make directory /c/no-path/dir/ ** Where: m-dir path return path ```
The system ran out of memory while trying to complete an operation. Message: ``` Not enough memory ```
Specific documentation on this error has yet to be provided. Message: ``` "not enough memory" ``` Example: ``` (you can provide one) ```
A math or comparison operator was used without providing the second argument. Message: ``` Operator is missing an argument ``` Example: ``` filter-error try [1 +] ** Script Error: Operator is missing an argument ** Where: 1 + ```
Specific documentation on this error has yet to be provided. Message: ``` ["this port does not support:" :arg1] ``` Example: ``` (you can provide one) ```
An attempt was made to use a function refinement that didn't exist for that function. Message: ``` [:arg1 "has no refinement called" :arg2] ``` Example: ``` f: func [/a] [if a [print "a"]] filter-error try [f/b] ** Script Error: f has no refinement called b ** Where: f/b ```
An attempt was made to rename a file that was either locked or protected. Message: ``` ["Cannot rename" :arg1] ``` Example: ``` p: open %file.txt filter-error try [rename %file.txt %new-name.txt] ** Access Error: Cannot rename file.txt ** Where: rename %file.txt %new-name.txt ```
A function expecting a block to return a value did not return anything. For instance, when using the [[while or until function|While and until]]. Message: ``` Block did not return a value ``` Examples: ``` filter-error try [ ; first block returns nothing while [print 10][probe "ten"] ] 10 ** Script Error: Block did not return a value ** Where: while [print 10] [probe "ten"] ``` ``` filter-error try [ until [print 10] ; block returns nothing ] 10 ** Script Error: Block did not return a value ** Where: until [print 10] ```
Specific documentation on this error has yet to be provided. Message: ``` ["missing port scheme:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["new scheme must have a name:" :arg1] ``` Example: ``` (you can provide one) ```
''Summary'' This is a very common error. It means that your code tried to evaluate a word that was not defined. Simply, it had no value associated with it, as explained in [[expressions: values|Concepts: Expressions: Values]]. If you are sure that the word was defined, then the problem could be that the word was defined in a different context than where it was used. ''Examples'' For example, if `foo` is not defined in the global context: ``` >> foo ** Script Error: foo has no value ``` Here foo is defined in an [[object!|Datatypes: Object!]], but still not in the global context: ``` >> test: object [foo: 10] >> foo ** Script Error: foo has no value ``` Similarly for foo when defined in a [[function!|Datatypes: Function!]], but an attempt is made to use it outside that function: ``` >> test: func [arg /local foo] [arg + foo] >> foo ** Script Error: foo has no value ``` ''Related'' You can use [[value?|Functions: value?]] to check if a word has been defined in context.
Specific documentation on this error has yet to be provided. Message: ``` ["port is not connected:" :arg1] ``` Example: ``` (you can provide one) ```
A word used was not defined within any context. Message: ``` [:arg1 "is not defined in this context"] ```
Specific documentation on this error has yet to be provided. Message: ``` "reserved for future use (or not yet implemented)" ``` Example: ``` (you can provide one) ```
An attempt was made to use a `REBOL/Command` or `REBOL/View` feature from `REBOL/Core`. Message: ``` [arg1 "not supported on your system"] ```
Specific documentation on this error has yet to be provided. Message: ``` [:arg1 "is not in the specified context"] ``` Example: ``` (you can provide one) ```
An attempt was made to use a port that was closed. Message: ``` ["Port" :arg1 "not open"] ``` Example: ``` p: open %file.txt close p filter-error try [copy p] ** Access Error: Port file.txt not open ** Where: copy p ```
Specific documentation on this error has yet to be provided. Message: ``` ["incompatible argument for" :arg1 "of" :arg2] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "values must be of the same type" ``` Example: ``` (you can provide one) ```
A warning message only.
An attempt was made to modify an invalid series index. Message: ``` ["Value out of range:" :arg1] ``` Example: ``` blk: [1 2 3] filter-error try [poke blk 5 "five"] ** Script Error: Value out of range: 5 ** Where: poke blk 5 "five" ```
Specific documentation on this error has yet to be provided. Message: ``` "math or number overflow" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["PARSE - command cannot be used as variable:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["PARSE - unexpected end of rule after:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["PARSE - invalid rule or usage of rule:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["PARSE - input must be a series:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["PARSE - expected a variable, not:" :arg1] ``` Example: ``` (you can provide one) ```
An attempt was made to access series data beyond the length of the series. Message: ``` Out of range or past end ``` Example: ``` blk: [1 2 3] filter-error try [print fourth blk] ** Script Error: Out of range or past end ** Where: print fourth blk ```
Specific documentation on this error has yet to be provided. Message: ``` "positive number required" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "protected value or series - cannot modify" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["protocol error:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["read failed:" :arg1 "reason:" :arg2] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["read-only - write not allowed:" :arg1] ``` Example: ``` (you can provide one) ```
These are errors that occur at runtime.
An attempt was made to access a block or object value using a path that did not exist within that block or object. Message: ``` ["Invalid path value:" :arg1] ``` Example: ``` blk: [a "a" b "b"] filter-error try [print blk/c] ** Script Error: Invalid path value: c ** Where: print blk/c ``` ``` obj: make object! [a: "a" b: "b"] filter-error try [print obj/d] ** Script Error: Invalid path value: d ** Where: print obj/d ```
An attempt was made to run a script that needed either a new version of REBOL or a file that couldn't be found. This information will be found in the script's REBOL header. Message: ``` ["Script needs:" :arg1] ```
Specific documentation on this error has yet to be provided. Message: ``` "script error" ``` Example: ``` (you can provide one) ```
A security violation occurred. This will happen when an attempt is made to access a file or the network when the secure setting is set to throw. Message: ``` REBOL - Security Violation ``` Example: ``` secure throw filter-error try [open %file.txt] ** Access Error: REBOL - Security Violation ** Where: open %file.txt ``` ``` secure none ```
Specific documentation on this error has yet to be provided. Message: ``` ["invalid security policy:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["attempt to lower security to" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "cannot set self - it is protected" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["maximum limit reached:" :arg1] ``` Example: ``` (you can provide one) ```
The operating system ran out of sockets to allocate. Message: ``` ["Error opening socket" :arg1] ```
The system's memory stack overflowed while trying to perform an operation. Message: ``` ["Stack overflow"] ``` Example: ``` call-self: func [][call-self] filter-error try [call-self] ** Internal Error: Stack overflow ** Where: call-self ```
These errors occur during scanning of REBOL source code.
Indicates that to run a program, some resource requirement cannot be met. Message: ``` ["this script needs" :arg1 :arg2 "or better to run correctly"] ``` Remedy: The needs field of a program's header indicates its requirements. If this error occurs, examine its header (plain text) to see determine the problem.
The timeout period elapsed while waiting to for a response from another host. This timeout is set in the port's `timeout` attribute. Message: ``` Network timeout ```
Specific documentation on this error has yet to be provided. Message: ``` "content too long" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "content too short (or just whitespace)" ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` [:arg1 "overflow/underflow"] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` ["write failed:" :arg1 "reason:" :arg2] ``` Example: ``` (you can provide one) ```
A math operation was performed on money values of two different denominations. For instance, when trying to add USD$1.00 to DEN$1.50. Message: ``` [:arg1 "not same denomination as" :arg2] ``` Example: ``` filter-error try [US$1.50 + DM$1.50] ** Script Error: US$1.50 not same denomination as DM$1.50 ** Where: US$1.50 + DM$1.50 ```
Specific documentation on this error has yet to be provided. Message: ``` ["datatype assertion failed for:" :arg1] ``` Example: ``` (you can provide one) ```
Specific documentation on this error has yet to be provided. Message: ``` "attempt to divide by zero" ``` Example: ``` (you can provide one) ```
Normally, blocks are not evaluated. For example, typing the following block: ``` [1 + 2] [1 + 2] ``` The block is ''not'' evaluated; it is simply treated as data. To evaluate a block, use the [[do|Functions: do]] function, as shown in the following example: ``` do [1 + 2] 3 ``` The [[do|Functions: do]] function returns the result of the evaluation. In the previous example, the number 3 is returned. If a block contains multiple expressions, only the result of the last expression is returned: ``` do [ 1 + 2 3 + 4 ] 7 ``` In this example, both expressions are evaluated, but only the result of the 3 + 4 expression is returned. There are a number of functions such as [[if|Functions: if]], [[loop|Functions: loop]], [[while|Functions: while]], and [[foreach|Functions: foreach]] that evaluate a block as part of their function. These functions are discussed in detail later in this chapter, but here are a few examples: ``` if time > 12:30 [print "past noon"] past noon ``` ``` loop 4 [print "looping"] looping looping looping looping ``` This is important to remember: blocks are treated as data until they are explicitly evaluated by a function. Only a function can cause them to be evaluated.
Any expression that can be evaluated in a script, can also be evaluated from the REBOL prompt, providing a simple means of testing individual expressions in a script. For example, if you type the following expression at the console prompt: ``` >> 1 + 2 == 3 ``` <<< About The Code Examples... In the example above, the console prompt (>>) and result indicator (==) are shown to give you an idea of how they appear in the console. For the examples that follow, the prompt and result strings are not shown. However, you can assume that these examples can be typed into the console to verify their results. <<<
A [[paren!|Datatypes: Paren!]] found anywhere within the flow of parsing will be evaluated. Normally this is done as part of processing the correct branch of the parse tree; however, it can also be done in preparation sections and elsewhere. Note that for the `quote` command, a [[paren!|Datatypes: Paren!]] must return a value that will be used for matching the input.
The [[do|Functions: do]] function can be used to evaluate entire scripts. Normally, do evaluates a block, as shown in the following example: ``` do [print "Hello!"] Hello! ``` But, when [[do|Functions: do]] evaluates a file name instead of a block, the file will be loaded into the interpreter as a block, then evaluated as shown in the following example: ``` do %script.r ``` <<< A REBOL Header is Required For a script file to be evaluated, it must include a valid REBOL header, which is described in the scripts Chapter. The header identifies that the file contains a [[script|Concepts: Scripts]] and not just random text. <<<
Since the value of directly expressed values is known, they simply return their values. For example, if you type the following line: ``` 10:30 ``` the value 10:30 is returned. This is the behavior of all directly expressed values. It includes: ``` integer 1234 decimal 12.34 string "REBOL world!" time 13:47:02 date 30-June-1957 tuple 199.4.80.1 money $12.49 pair 100x200 char #"A" binary #{ab82408b} email info@rebol.com issue #707-467-8000 tag <IMG SRC="xray.jpg"> file %xray.jpg url http://www.rebol.com/ block [milk bread butter] ```
The [[do|Functions: do]] function can be used to evaluate expressions that are found within text strings. For example, the following expression: ``` do "1 + 2" 3 ``` returns the result 3. First the string is converted to a block, then the block is evaluated. Evaluating strings can be handy at times, but it should be done only when necessary. For example, to create a REBOL console line processor, type the following expression: ``` forever [probe do ask "=> "] ``` The above expression would prompt you with => and wait for you to type a line of text. The text would then be evaluated, and its result would be printed. (Of course, it's not really quite this simple, because the script could have produced an error.) Unless it is necessary, evaluating strings is not generally a good practice. Evaluating strings is less efficient than evaluating blocks, and the context of words in a string is not known. For example, the following expression: ``` do form ["1" "+" "2"] ``` is much less efficient than typing: ``` do [1 + 2] ``` REBOL blocks can be constructed just as easily as strings, and blocks are better for expressions that need to be evaluated.
Errors may occur for many different reasons during evaluation. For example, if you divide a number by zero, evaluation is stopped and an error is displayed ``` 100 / 0 ** Math Error: Attempt to divide by zero. ** Where: 100 / 0 ``` A common error is using a word before it has been defined: ``` size + 10 ** Script Error: size has no value. ** Where: size + 10 ``` Another common error is not providing the proper values to a function in an expression: ``` 10 + [size] ** Script Error: Cannot use add on block! value. ** Where: 10 + [size] ``` Sometimes errors are not so obvious, and you will need to experiment to determine what is causing the error.
In [[Code: Evaluating blocks|Guide: Code: Evaluating blocks]] you learned that code is held in data blocks that get directly evaluated. In general, ''expressions are evaluated from left to right''; however, within each expression ''evaluation occurs from right to left''. Take this example: ``` print length? join "exam" "ple" ``` The print and [[length?|Functions: length?]] functions require one argument. The [[join|Functions: join]] function requires two arguments. You can divide the line into separate sections that are each evaluated. We start with: ``` print length? join "exam" "ple ``` which evaluates to: ``` print length? "example" ``` and finally to: ``` print 7 ``` This is called the ''substitution method'' of understanding evaluation. It is handy to remember. <<< What, no expression separators? For programmers who know other languages, it may seem odd that REBOL combines these into a single expression. We have no need for extra parentheses, commas, or other punctuation. All we can say is ''don't worry! We've found it works quite well''. Your brain is tuned for parsing sentences, and it will parse REBOL expressions equally well, once you get used to it. <<<
REBOL evaluates blocks of values and words to produce one or more results. We use the term evaluate rather than execute. When using REBOL, think about computing values instead of executing steps or instructions. REBOL is a functional language. Here are some examples of evaluating blocks of values and words: ``` print 1 + 2 3 ``` ``` print length? "example" 7 ``` ``` print 1 + length? "example" 8 ``` In those lines the values are 1, 2, and "example", and the words are: print, length?, and +. Those words are associated with functions that perform various computations and return results. For instance, above, length? returns the length of the string.
An example callback is included in the `host-ext-test.c` file within the R3 host-kit distribution. This file includes tests for various extension functions including both callback mechanisms. To enable the test code add `host-ext-test.c` to your makefile and within `host-main.c` uncomment this line: ``` #define TEST_EXTENSIONS ``` Build the host, run it, and at the REBOL prompt type: ``` xtest ``` to run the test code that is found within the `host-ext-test.c` file. A few callbacks will be called as part of the test. The [[wait|Functions: wait]] that is called at the end of the test allows event-driven callbacks to be processed before the test returns to the console (which blocks, and does not let events happen.) Note: this file does not use the `make-host-ext.r` script in order to make it clear what the test code is actually doing in the C file.
To give you a general idea for what a extension looks like, here is an example (written in the C language but, a similar technique can be done in any compiled language.) ``` #include "reb-c.h" #include "reb-ext.h" const char *init_block = "REBOL [\n" "Title: {Example Extension Module}\n" "Name: example\n" "Type: module\n" "Exports: [add-mul]\n" "]\n" "add-mul: command [{Add and multiply integers.} a b c]\n" ; RXIEXT const char *RX_Init(int opts, RL_LIB *lib) { RXI = lib; if (!CHECK_STRUCT_ALIGN) exit(100); return 0; } RXIEXT int RX_Call(int cmd, RXIFRM *frm) { RXA_INT64(frm, 1) = (RXA_INT64(frm, 1) + RXA_INT64(frm, 2)) * RXA_INT64(frm, 3); return RXR_VALUE; } ``` After compiling that code into a DLL, you can use it in your REBOL code: ``` import %example.dll print add-mul 1 2 3 9 ``` The speed of function evaluation is about the same as other REBOL native functions. (Normally within 5%.)
The [[exclude|Functions: exclude]] function takes two series and returns a series that contains all the values of the first series, less the values of the second. ``` probe exclude [1 2 3 4] [1 2 3 5] [4] ``` ``` probe exclude [Bill Bob Bart] [Bob Ted Fred] [Bill Bart] ``` ``` lunch: [ham cheese bread carrot] dinner: [ham salad carrot rice] probe exclude lunch dinner [cheese bread] ``` ``` string1: "CBAD" ; A B C D scrambled string2: "EDCF" ; C D E F scrambled print sort difference string1 string2 AB ``` The `/case` refinement allows case-sensitive exclusion: ``` probe exclude/case [Bill bill Bob bob] [Bart bart bill Bob] [Bill bob] ```
What happens when an imported module uses the same global variable name as one you define in your program? Here is an example. A program loads a module that exports the function `select-data`: ``` import %database.r ``` But, the program defines it's own function: ``` select-data: func [database selector] ... ``` Both of the functions can't use the same name as global variables. This situation can be solved by using the result of the import function as a way to reference its specific values. Here's an example: ``` db-mod: import %database.r ; Define our own local function: select-data: func [database selector] ... ; To use the module's function: db-mod/select-data ... ``` This is identical to how you reference a field of an object.
Within a rule, you can include a REBOL expression to be evaluated when [[parse|Functions: parse]] reaches that point in the rule. Parentheses are used to indicate such expressions: ``` string: "there is a phone in this sentence" probe parse string [ to "a" to "phone" (print "found phone") to end ] found phone true ``` The example above parses the string a phone and prints the message found phone after the match is complete. If the strings a or phone are missing and the parse can not be done, the expression is not evaluated. Expressions can appear anywhere within a rule, and multiple expressions can occur in different parts of a rule. For instance, the following code prints different strings depending on what inputs were found: ``` parse string [ "a" | "the" to "phone" (print "answer") | to "radio" (print "listen") | to "tv" (print "watch") ] answer ``` ``` string: "there is the radio on the shelf" parse string [ "a" | "the" to "phone" (print "answer") | to "radio" (print "listen") | to "tv" (print "watch") ] listen ``` Here is an example that counts the number of times the HTML pre-format tag appears in a text string: ``` count: 0 page: read http://www.rebol.com/docs/dictionary.html parse page [any [thru <pre> (count: count + 1)]] print count 777 ```
If you provide too many arguments, they may be ignored. For example, the [[if|Functions: if]] takes two arguments as shown with here: ``` ? if USAGE: IF condition then-block ``` If you write: ``` if a > 10 [a: 1] [b: 2] ``` The second block is never used, because [[if|Functions: if]] does not require it. Although it does not cause an error, your code will not produce the correct results when the [[if|Functions: if]] condition is false.
You can extract multiple values from a series with the copy function. To do so, use [[copy|Functions: copy]] with the `/part` refinement, which specifies the number of values that you want to extract: ``` colors: [red green blue] sub-colors: copy/part colors 2 probe sub-colors [red green] ``` Graphically, this would look like: To copy a sub-series from any position within the series, first traverse to the starting position. The following example moves forward to the second position in the series using [[next|Functions: next]] before performing the copy: ``` sub-colors: copy/part next colors 2 probe sub-colors [green blue] ``` This would be diagrammed as: The length of the series to copy can be specified as an ending position, as well as a copy count. Note that the position indicates `where` the copy should stop, not the ending position. ``` probe copy/part colors next colors [red] ``` ``` probe copy/part colors back tail colors [red green] ``` ``` probe copy/part next colors back tail colors [green] ``` This can be useful when the ending position is found as the result of the [[find|Functions: find]] function: ``` file: %image.jpg print copy/part file find file "." image ```
Some of the previous examples made use of the [[first|Functions: first]] and second` ordinal` functions to extract specific values from a series. The full set of ordinal functions is: ``` first second third fourth fifth last ``` Ordinal functions are provided as a convenience, and are used for picking values from the most common position in a series. Here are some examples: ``` colors: [red green blue gold indigo teal] print first colors red ``` ``` print third colors blue ``` ``` print fifth colors indigo ``` ``` print last colors teal ``` To extract from a numeric position, use the pick function: ``` print pick colors 3 blue ``` ``` print pick colors 5 indigo ``` A shorthand notation for pick is to use a path: ``` print colors/3 blue ``` ``` print colors/5 indigo ``` Remember, as shown earlier, extraction is performed `relative` to the series variable that you provide. If the `colors` variable were at another position in the series, the results would be different. Extracting a value past the end of its series generates an error in the case of the ordinal functions and returns [[none!|Datatypes: None!]] in the case of the pick function or a pick path: ``` print pick colors 10 none ``` ``` print colors/10 none ```
|''Function'' |''Description''|h |[[pick|Functions: pick]] |Extracts a single value from a position in a series.| |[[copy/part|Functions: copy]] |Extracts a sub-series from a series.| |[[first|Functions: first]] |Extracts the first value from a series.| |[[second|Functions: second]] |Extracts the second value from a series.| |[[third|Functions: third]] |Extracts the third value from a series.| |[[fourth|Functions: fourth]] |Extracts the fourth value from a series.| |[[fifth|Functions: fifth]] |Extracts the fifth value from a series.| |[[last|Functions: last]] |Extracts the last value from a series.|
Operating systems can associate a suffix with specific applications for actions like "open" and "edit". For example, MS Windows does this via registry entries. The REBOL install function provides a quick way to setup these default association between .r and REBOL. Doing so also requires that REBOL be located in a standard directory, so install also takes care of that. Associating .r on other operating systems is not currently supported, but if you have the know-how and would like to see it supported, please contact us.
To determine if a file exists, use the [[exists?|Functions: exists?]] function: ``` print exists? %file.txt ``` To determine if a file exists before you read it, use: ``` if exists? file [text: read file] ``` To avoid overwriting a file you can check it with, use: ``` if not exists? file [write file data] ``` The [[exists?|Functions: exists?]] function also works with some network protocols: ``` print exists? ftp://www.rebol.com/file.txt ```
To obtain the last modification date of a file, use the [[modified?|Functions: modified?]] function: ``` print modified? %file.txt 30-Jun-2000/14:41:55-7:00 ``` Not all operating systems keep track of the creation date of a file, so to keep REBOL scripts operating system independent only the last modification date is accessible. The [[modified?|Functions: modified?]] function also works with some network protocols: ``` print modified? ftp://www.rebol.com/file.txt ```
Various functions are provided to help you create file names and paths. These are listed below in `[bad-link:concepts/file.txt]` Name Functions. |[[to-file|Functions: to-file]] |Converts strings and blocks into a file name or file path.| |[[split-path|Functions: split-path]] |Splits a path into its directory part and its file name.| |[[clean-path|Functions: clean-path]] |Returns the absolute path that is equivalent to any given path containing double dot `..` or dot `.`.| |[[what-dir|Functions: what-dir]] |Returns the absolute path to the current directory.|
In scripts, file names and paths are written with a percent sign `%` followed by a sequence of characters: ``` %examples.r %big-image.jpg %graphics/amiga.jpg %/c/plug-in/video.r %//sound/goldfinger.mp3 ``` The percent sign is necessary to prevent file names from being interpreted as words within the language. Although it is not a good practice, spaces can be included in file names by enclosing the file name in double quotes `" "`. The double quotes prevent the file name from being interpreted as multiple words: ``` %"this file.txt" %"cool movie clip.mpg" ``` The standard Internet convention of using a percent sign `%` and a hex code is also allowed for character encoding. When this is done, quotes are not required. The above file names could also be written as: ``` %this%20file.txt %cool%20movie%20clip.mpg ``` Note that the standard file suffix for REBOL scripts is `.r`. On systems where this convention collides with another file type, a `.reb` suffix can be used instead.
On most systems, it is possible to redirect standard input and output from and to files. The example: ``` rebol -w script.r > output-file ``` redirects output to a file. Similarly, ``` rebol -w script.r < input-file ``` redirects input from a file. <<< When Redirecting File IO... Use the -w option to prevent the REBOL console window from opening, as it interferes with standard input and output redirection. <<<
To obtain the byte size of a file, use the [[size?|Functions: size?]] function: ``` print size? %file.txt ``` The [[size?|Functions: size?]] function also works with some network protocols: ``` print size? ftp://www.rebol.com/file.txt ```
R3 files are stored in ASCII text or UTF-8 formats and use a .r suffix (file extension). However, the .r suffix is not critical, and it's not enforced. For example, your file can be .txt, .cgi, or even .html and as long as a REBOL header can be found, it will be loaded. Note that suffix is often useful for file associations or MIME types that can automatically run your scripts or open the preferred text editors. These associations are supported when you install REBOL, but that is an option, not a requirement. <<< Not in R3 R3 does not support install at this time, but it will be added. <<<
Filenames are preceded by a percent sign to distinguish them from other words. For example: ``` %data.txt %images/photo.jpg %../scripts/*.r ```
REBOL 3.0 accepts UTF-8 encoded scripts, and because UTF-8 is a superset of ASCII, that standard is also accepted. If you are not familiar with the [[UTF-8 Unicode standard|https://en.wikipedia.org/wiki/UTF-8]], it is an 8 bit encoding that accepts ASCII directly (no special encoding is needed), but allows the full Unicode character set by encoding them with characters that have values 128 or greater. Most modern text editors handle UTF-8. If your editor does not support it, then you may need to stick with only ASCII characters. Also note: do not write scripts with Latin-1 or other "code-page" encodings. They will not work properly.
The following example gets user information with the finger protocol: ``` print read finger://username@host.dom ```
The [[for|Functions: for]] function is rarely used in REBOL code, because other types of loops are easier to write. However, [[for|Functions: for]] basically extends [[repeat|Functions: repeat]] by allowing a starting value, the ending value, and specification of the increment amount. The example below begins at zero and counts to 50, incrementing by 10 each time through the loop: ``` for count 0 50 10 [print count] 0 10 20 30 40 50 ``` Notice that the [[for|Functions: for]] function iterates the loop up to and including the ending value. However, if the count exceeds the ending value, the loop is terminated. The example below specifies an ending value of 55. That value will never be hit because the loop increments by 10 each time. The loop stops at 50. ``` for count 0 55 10 [prin [count " "]] 0 10 20 30 40 50 ``` The next example shows how to count down. It begins at four and counts down to zero one at a time. ``` for count 4 0 -1 [print count] 4 3 2 1 0 ``` The [[for|Functions: for]] function also works for decimal numbers, money, times, dates, series, and characters. Be sure that both the starting and ending values are of the same datatype. Here are several examples of using the [[for|Functions: for]] loop with other datatypes. ``` for count 10.5 0.0 -1 [prin [count " "]] 10.5 9.5 8.5 7.5 6.5 5.5 4.5 3.5 2.5 1.5 0.5 ``` ``` for money $0.00 $1.00 $0.25 [prin [money " "]] $0.00 $0.25 $0.50 $0.75 $1.00 ``` ``` for time 10:00 12:00 0:20 [prin [time " "]] 10:00 10:20 10:40 11:00 11:20 11:40 12:00 ``` ``` for date 1-jan-2000 4-jan-2000 1 [prin [date " "]] 1-Jan-2000 2-Jan-2000 3-Jan-2000 4-Jan-2000 ``` ``` for char #"a" #"z" 1 [prin char] abcdefghijklmnopqrstuvwxyz ``` The [[for|Functions: for]] function also works on series. The following example uses [[for|Functions: for]] on a string value. The word end is defined as the string with its current index at the `d` character. The [[for|Functions: for]] function moves through the string series one character at a time and stops when it reaches the character position defined to `end`: ``` str: "abcdef" end: find str "d" for s str end 1 [print s] abcdef bcdef cdef def ```
Similar to [[foreach|Functions: foreach]], the [[forall|Functions: forall]] function evaluates a block for every value in a series. However, there are some important differences. The [[forall|Functions: forall]] function is handed the series that is set to the beginning of the loop. As it proceeds through the loop, [[forall|Functions: forall]] modifies the position within the series. ``` colors: [red green blue] forall colors [print first colors] red green blue ``` In the above example, after each evaluation of the block, the series is advanced to its next position. When [[forall|Functions: forall]] returns, the `color` index is at the tail of the series. To continue to use the series you will need to return it to its head position with the following line: ``` colors: head colors ``` The [[forskip|Functions: forskip]] function evaluates a block for groups of values in a series. The second argument to [[forskip|Functions: forskip]] is the count of how many elements to move forward after each cycle of the loop. Like [[forall|Functions: forall]], [[forskip|Functions: forskip]] is handed the series with the series index set to where it is to begin. Then, [[forskip|Functions: forskip]] modifies the index position as it continues the loop. After each evaluation of the body block, the series index is advanced by the skip amount to its next index position. The following example demonstrates [[forskip|Functions: forskip]] : ``` movies: [ 8:30 "Contact" $4.95 10:15 "Ghostbusters" $3.25 12:45 "Matrix" $4.25 ] forskip movies 3 [print second movies] Contact Ghostbusters Matrix ``` In the above example, [[forskip|Functions: forskip]] returns with the movies series at its tail position. You will need to use the head function to return the series back to its head position.
The [[forall|Functions: forall]] loop is similar to the while loop, but eliminates some of the effort required. The [[forall|Functions: forall]] loop starts from the current index and advances through a series to its tail evaluating a block for every value. The [[forall|Functions: forall]] loop takes two arguments: a series variable and a block to evaluate for each iteration. ``` colors: [red green blue yellow orange] forall colors [print first colors] red green blue yellow orange ``` The [[forall|Functions: forall]] advances the variable position through the series, so when it returns the variable is left at its tail: ``` print tail? colors true ``` Therefore, the variable must be reset before it is used again: ``` colors: head colors ``` Also, if the block modifies the series, be careful to avoid missing or repeating a value. The [[forall|Functions: forall]] loop works in some cases; however, if you are uncertain, use the [[while|Functions: while]] loop instead. ``` forall colors [ if colors/1 = 'blue [remove colors] print first colors ] red green yellow orange ```
The [[foreach|Functions: foreach]] function provides a convenient way to repeat the evaluation of a block for each element of a series. It works for all types of block and string series. In the example below, each word in the block will be printed: ``` colors: [red green blue] foreach color colors [print color] red green blue ``` In the next example, each character in a string will be printed: ``` string: "REBOL" foreach char string [print char] R E B O L ``` In the example below, each filename in a directory block will be printed: ``` files: read %. foreach file files [ if find file ".t" [print file] ] file.txt file2.txt newfile.txt output.txt ``` When a block contains groups of values that are related, the [[foreach|Functions: foreach]] function can fetch all the values of the group at the same time. For example, here is a block that contains a time, string, and price. By providing the foreach function with a block of words for the group, each of their values can be fetched and printed. ``` movies: [ 8:30 "Contact" $4.95 10:15 "Ghostbusters" $3.25 12:45 "Matrix" $4.25 ] foreach [time title price] movies [ print ["watch" title "at" time "for" price] ] watch Contact at 8:30 for $4.95 watch Ghostbusters at 10:15 for $3.25 watch Matrix at 12:45 for $4.25 ``` In the above example, the foreach value block, `[''time title price]`, specifies that three values are to be fetched from movies for each evaluation of the block. The variables used to hold the [[foreach|Functions: foreach]] values are local to the block. Their value are only set within the block that is being repeated. Once the loop has exited, the variables return to their previously set values.
The [[foreach|Functions: foreach]] loop moves through a series setting a word or multiple words in to the values in the series. The [[foreach|Functions: foreach]] loop takes three arguments: a word or a block of words that holds the values for each iteration, a series, and a block to evaluate for each iteration. ``` colors: [red green blue yellow orange gold] foreach color colors [print color] red green blue yellow orange gold ``` ``` foreach [c1 c2] colors [print [c1 c2]] red green blue yellow orange gold ``` ``` foreach [c1 c2 c3] colors [print [c1 c2 c3]] red green blue yellow orange gold ``` This is very useful with blocks that contain related values: ``` people: [ "Bob" bob@example.com 12 "Tom" tom@example.net 40 "Sam" sam@example.org 22 ] foreach [name email age] people [ print [name email age] ] Bob bob@example.com 12 Tom tom@example.net 40 Sam sam@example.org 22 ``` Note that the [[foreach|Functions: foreach]] loop does not advance the current index through the series, so there is no need to reset its series variable.
The [[forever|Functions: forever]] function evaluates a block endlessly or until a it encounters the break function. The following example uses forever to check for the existence of a file every ten minutes: ``` forever [ if exists? %datafile [break] wait 0:10 ] ```
The [[form|Functions: form]] function converts a value to a string: ``` print form $1.50 $1.50 ``` ``` print type? $1.50 money ``` ``` print type? form $1.50 string ``` The following example uses [[form|Functions: form]] to find a number by its decimal value: ``` blk: [11.22 44.11 11.33 11.11] foreach num blk [if find form num ".11" [print num]] 44.11 11.11 ``` When [[form|Functions: form]] is used on a block, all values in the block are converted to string values with spaces between each value: ``` print form [11.22 44.11 11.33] 11.22 44.11 11.33 ``` The [[form|Functions: form]] function does not evaluate the values of a block. This results in words being converted to string values: ``` print form [a block of undefined words] a block of undefined words ``` ``` print form [33.44 num "-- unevaluated string:" str] 33.44 num -- unevaluated string: str ```
Use the following guidelines for formatting REBOL scripts for clarity. !!!!! ''Indent Content for Clarity'' The contents of a block are indented, but the block's enclosing square brackets `[ ]` are not. That's because the square brackets belong to the prior level of syntax, as they define the block but are not contents of the block. Also, it's easier to spot breaks between adjacent blocks when the brackets stand out. Where possible, an opening square bracket remains on the line with its associated expression. The closing bracket can be followed by more expressions of that same level. These same rules apply equally to parenthesis `( )` and braces `{ }`. ``` if check [do this and that] if check [ do this and do that do another thing do a few more things ] either check [do something short][ do something else] either check [ when an expression extends past the end of a block... ][ this helps keep things straight ] while [ do a longer expression to see if it's true ][ the end of the last block and start of the new one are at the WHILE level ] adder: func [ "This is an example function" arg1 "this is the first arg" arg2 "this is the second arg" ][ arg1 + arg2 ] ``` An exception is made for expressions that normally belong on a single line, but extend to multiple lines: ``` if (this is a long conditional expression that breaks over a line and is indented )[ so this looks a bit odd ] ``` This also applies to grouped values that belong together, but must be wrapped to fit on the line: ``` [ "Hitachi Precision Focus" $1000 10-Jul-1999 "Computers Are Us" "Nuform Natural Keyboard" $70 20-Jul-1999 "The Keyboard Store" ] ``` !!!!! ''Standard Tab Size'' REBOL standard tab size is four spaces. Because people use different editors and readers for scripts, you can elect to use spaces rather than tabs. !!!!! ''Detab Before Posting'' The tab character (ASCII 9) does not indent four spaces in many viewers, browsers, or shells, so use an editor or REBOL to detab a script before publishing it to the net. The following function detabs a file with standard four-space tabs: ``` detab-file: func [file-name [file!]] [ write file-name detab read file-name ] detab-file %script.r ``` The following function converts an eight-space tabs to four-space tabs: ``` detab-file: func [file-name [file!]] [ write file-name detab entab/size read file-name 8 ] ``` !!!!! ''Limit Line Lengths to 80 Characters'' For ease of reading and portability among editors and email readers, limit lines to 80 characters. Long lines that get wrapped in the wrong places by email clients are difficult to read and have problems loading.
Similar to [[forall|Functions: forall]], the [[forskip|Functions: forskip]] loop advances through a series starting at the current position, but skips the specified number of values each time. The [[forskip|Functions: forskip]] loop takes three arguments: a series variable, the skip between each iteration, and a block to evaluate for each iteration. ``` colors: [red green blue yellow orange] forskip colors 2 [print first colors] red blue orange ``` The [[forskip|Functions: forskip]] loop leaves the series at its tail, requiring you to reset it. ``` print tail? colors true ``` ``` colors: head colors ```
The following reads and writes files to a server using the file transfer protocol (FTP): ``` file: read ftp://ftp.rebol.com/test.txt write ftp://user:pass@site.dom/test.txt file ``` The next example gets a directory listing from FTP: ``` print read ftp://ftp.rebol.com/pub ```
It is useful to provide a description in function specification blocks. Limit such text to one line of 70 characters or less. Within the description, mention what type of value the function normally returns. ``` defringe: func [ "Return the defringed localization radius." area "Topo area to defringe" time "Time allotted for operation" /cost num "Maximum cost permitted" /compound "Compound the calculation" ][ ...code... ] ```
Sometimes you find you need some optional variations in the behavior of your functions. In REBOL we add a refinement! for each such option. A simple example helps show it. Take the above code again, but this time add a refinement that indicates you want only a truncated integer result: ``` sum2: func [ "Adds two numbers and returns the result." a [number!] "The first number" b [number!] "The second number" /int "Return integer only (truncated)" ] [ either int [to integer! a + b] [a + b] ] ``` We've added `/int` as a refinement and provided a help string for it. Now you can write: ``` sum2 1.2 3.9 5.1 ``` ``` sum2/int 1.2 3.9 5 ```
The previous examples describe how functions return values when they are evaluated. Sometimes, however, you want to obtain the function as a value, not the value it returns. This can be done by preceding the function name with a colon or using the get function. For example, to set a word, `pr`, to the [[print|Functions: print]] function, you would write: ``` pr: :print ``` You could also write: ``` pr: get `print ``` Now pr is equivalent to the [[print|Functions: print]] function: ``` pr "this is a test" this is a test ```
``` - value1 value2 ``` Returns the second value subtracted from the first. ``` Arguments: value1 [scalar! date!] value2 [scalar! date!] ``` See also: [[+|Functions: +]] [[add|Functions: add]] [[subtract|Functions: subtract]] [[negate|Functions: negate]] [[absolute|Functions: absolute]] Description If used with only a single value, it negates the value (unary minus). When subtracting values of different datatypes, the values must be compatible. ``` print 123 - 1 122 ``` ``` print -123 ; a negative number -123 print - 123 ; negating a positive number (unary) ``` ``` print 12:00 - 11:00 1:00 ``` ``` print 1-Jan-2000 - 1 31-Dec-1999 ``` ``` print 1.2.3.4 - 1.0.3.0 0.2.0.4 ```
``` -- word Decrement an integer or series index. Return its prior value. Arguments: word [word!] - Integer or series variable ``` ''Description'' No description provided.
``` ! value Returns the logic complement. Arguments: value - (Only FALSE and NONE return TRUE) ``` See also: [[not|Functions: not]] ''Description'' A synonym for the not function.
``` != value1 value2 Returns TRUE if the values are not equal. Arguments: value1 value2 ``` See also: [[=|Functions: =]] [[<>|Functions: <>]] [[!==|Functions: !==]] ''Description'' This word is provided because it is so commonly used in programming languages. It is a synonym for `<>` the [[op!|Datatypes: Op!]] that calls the [[not-equal?|Functions: not-equal?]] [[action!|Datatypes: Action!]].
``` !== value1 value2 Returns TRUE if the values are not strictly equal. Arguments: value1 value2 ``` See also: [[==|Functions: ==]] [[=|Functions: =]] [[<>|Functions: <>]] [[!=|Functions: !=]] ''Description'' This word is provided as an [[op!|Datatypes: Op!]] for the [[strict-not-equal?|Functions: strict-not-equal?]] [[action!|Datatypes: Action!]].
``` ? word /doc Prints information about words and values. Arguments: word [any-type!] Refinements: /doc - Open web browser to related documentation. ``` See also: [[help|Functions: help]] [[what|Functions: what]] [[source|Functions: source]] [[why?|Functions: why?]] ''Description'' Synonym for [[help|Functions: help]]. ''Example'': ``` >> ? switch USAGE: SWITCH value cases /default case /all DESCRIPTION: Selects a choice and evaluates the block that follows it. SWITCH is a native value. ARGUMENTS: value -- Target value cases -- Block of cases to check (block!) REFINEMENTS: /default case -- Default case if no others found /all -- Evaluate all matches (not just first one) ```
``` ?? name Debug print a word, path, or block of such, followed by its molded value. Arguments: name - Word, path, and block to obtain values. ``` See also: [[probe|Functions: probe]] [[help|Functions: help]] [[?|Functions: ?]] [[mold|Functions: mold]] [[source|Functions: source]] ''Description'' The `??` function prints the variable named, followed by its value. It also returns the value. It is a quite useful for debugging. ``` a: 10 ?? a a: 10 ``` Like probe, `??` can be inserting into code with minimal effect: ``` a: 10 b: 20 a + ?? b b: 20 30 ``` If a block is provided, then each value is printed: ``` ?? [a b] a: 10 b: 20 Warning: effect on functions ``` If you use `??` in front of a function, the function value is returned. The function is not evaluated. ``` >> ?? find "abc" "a" find: make action! [[ {Finds a value in a series and returns the series at the start of it.} series [series! gob! port! bitset! typeset! object! none!] value [any-type!] /part "Limits the search to a given length or position" ... ```
''Description'' The datatype of the second value may be restricted to INTEGER or DECIMAL, depending on the datatype of the first value (e.g. the first value is a time). ``` print 123 * 10 1230 print 12.3 * 10 123.0 print 3:20 * 3 10:00 ```
''Description'' Note that this is the infix op! (operator) form of the power function. ``` print power 10 2 100.0 ``` The result is always [[decimal!|Datatypes: Decimal!]]. ``` print 10 ** 2 100.0 ``` The [[log-10|Functions: log-10]] function does the inverse: ``` print 10 ** 3 1000.0 print log-10 1000 3.0 ```
``` / value1 value2 ``` Returns the first value divided by the second. ``` Arguments: value1 [scalar!] value2 [scalar!] ``` See also: [[//|Functions: //]] [[divide|Functions: divide]] Description An error will occur if the second value is zero. When dividing values of different datatypes they must be compatible. ``` print 123 / 10 12.3 ``` ``` print 12.3 / 10 1.23 ``` ``` print 1:00 / 60 0:01 ```
``` // value1 value2 ``` Returns the remainder of first value divided by second. ``` Arguments: value1 [scalar!] value2 [scalar!] ``` See also: [[/|Functions: /]] [[remainder|Functions: remainder]] Description Returns the value of the remainder after the first number is divided by the second. If the second number is zero, an error will occur. ``` print 123 // 10 3 ``` ``` print 25:32 // 24:00 1:32 ``` If the first value is positive, then the returned remainder is nonnegative. If the first value is negative, then the returned remainder is nonpositive.
``` + value1 value2 ``` Returns the result of adding two values. ``` Arguments: value1 [scalar! date!] value2 ``` See also: [[-|Functions: -]] [[add|Functions: add]] [[subtract|Functions: subtract]] Description When adding values of different datatypes, the values must be compatible. ``` print 123 + 1 124 ``` ``` print 12:00 + 11:00 23:00 ``` ``` print 31-Dec-1999 + 1 1-Jan-2000 ``` ``` print 1.2.3.4 + 4.3.2.1 5.5.5.5 ```
``` ++ word Increment an integer or series index. Return its prior value. Arguments: word [word!] - Integer or series variable ``` ''Description'' No description provided.
``` < value1 value2 Returns TRUE if the first value is less than the second value. Arguments: value1 value2 ``` See also: [[lesser?|Functions: lesser?]] [[<=|Functions: <=]] [[>|Functions: >]] [[>=|Functions: >=]] [[=|Functions: =]] [[<>|Functions: <>]] [[min|Functions: min]] [[max|Functions: max]] ''Description'' Returns FALSE for all other values. An error will occur if the values are not of the same datatype. For string-based datatypes, the sorting order is used for comparison with character casing ignored ([[uppercase = lowercase|Uppercase and Lowercase]]). ``` print "abc" < "abcd" true print 12-June-1999 < 10-June-1999 false print 1.2.3.4 < 4.3.2.1 true print 1:30 < 2:00 true print [1 2 3] < [1 5 3] true ```
``` <= value1 value2 Returns TRUE if the first value is less than or equal to the second value. Arguments: value1 value2 ``` See also: [[lesser-or-equal?|Functions: lesser-or-equal?]] [[<|Functions: <]] [[>|Functions: >]] [[>=|Functions: >=]] [[=|Functions: =]] [[<>|Functions: <>]] [[min|Functions: min]] [[max|Functions: max]] '' Description'' Returns FALSE for all other values. For string-based datatypes, the sorting order is used for comparison with character casing ignored ([[uppercase = lowercase|Uppercase and Lowercase]]). ``` print "abc" <= "abd" true print 10-June-1999 <= 12-june-1999 true print 4.3.2.1 <= 1.2.3.4 false print 1:23 <= 10:00 true ```
``` <> value1 value2 Returns TRUE if the values are not equal. Arguments: value1 value2 ``` See also: [[=|Functions: =]] [[==|Functions: ==]] [[not-equal?|Functions: not-equal?]] ''Description'' This word is provided as an op! for the [[not-equal?|Functions: not-equal?]] [[action!|Datatypes: Action!]]. Please consult the documentation of [[not-equal?|Functions: not-equal?]] for details. ``` print "abc" <> "abcd" true print [1 2 4] <> [1 2 3] true print 12-sep-98 <> 10:30 true ```
``` = value1 value2 Returns TRUE if the values are equal. Arguments: value1 value2 ``` See also: [[<>|Functions: <>]] [[==|Functions: ==]] [[equal?|Functions: equal?]] ''Description'' This word is provided as an [[op!|Datatypes: Op!]] for the [[equal?|Functions: equal?]] [[action!|Datatypes: Action!]]. Please consult the documentation of [[equal?|Functions: equal?]] for details. ``` print 123 = 123 true print "abc" = "abc" true print [1 2 3] = [1 2 4] false print 12-june-1998 = 12-june-1999 false print 1.2.3.4 = 1.2.3.0 false print 1:23 = 1:23 true ```
``` =? value1 value2 Returns TRUE if the values are identical. Arguments: value1 value2 ``` See also: [[=|Functions: =]] [[==|Functions: ==]] [[same?|Functions: same?]] ''Description'' This function returns true if two values are the same. That is, there is no way to distinguish between them. For instance, in the case of a string, they would occupy the same memory. ``` a: "apple" b: a print a =? b true b: tail a print a =? (head b) true print "apple" =? "apple" false ```
``` == value1 value2 Returns TRUE if the values are strictly equal. Arguments: value1 value2 ``` See also: [[=|Functions: =]] [[<>|Functions: <>]] [[ strict-equal?|Functions: strict-equal?]] ''Description'' This word is provided as an op! for the [[strict-equal?|Functions: strict-equal?]] [[action!|Datatypes: Action!]]. Please consult the documentation of [[strict-equal?|Functions: strict-equal?]] for details. ``` print 123 == 123 true print "abc" == "ABC" false ```
``` > value1 value2 Returns TRUE if the first value is greater than the second value. Arguments: value1 value2 ``` See also: [[greater?|Functions: greater?]] [[<|Functions: <]] [[<=|Functions: <=]] [[>=|Functions: >=]] [[=|Functions: =]] [[<>|Functions: <>]] [[min|Functions: min]] [[max|Functions: max]] ''Description'' Returns FALSE for all other values. The values must be of the same datatype or an error will occur. For string-based datatypes, the sorting order is used for comparison with character casing ignored ([[uppercase = lowercase|Uppercase and Lowercase]]). ``` print "abc" > "abb" true print 16-June-1999 > 12-june-1999 true print 4.3.2.1 > 1.2.3.4 true print 11:00 > 12:00 false print [1 2 3] > [1 1 3] true ```
``` >= value1 value2 Returns TRUE if the first value is greater than or equal to the second value. Arguments: value1 value2 ``` See also: [[greater-or-equal?|Functions: greater-or-equal?]] [[<|Functions: <]] [[<=|Functions: <=]] [[>|Functions: >]] [[=|Functions: =]] [[<>|Functions: <>]] [[min|Functions: min]] [[max|Functions: max]] '' Description'' Returns FALSE for all other values. The values must be of the same datatype or an error will occur. For string-based datatypes, the sorting order is used for comparison with character casing ignored ([[uppercase = lowercase|Uppercase and Lowercase]]). ``` print "abc" >= "abb" true print 16-June-1999 >= 12-june-1999 true print 1.2.3.4 >= 4.3.2.1 false print 11:00 >= 11:00 true ```
''about'' Information about REBOL See also: [[license|Functions: license]] [[usage|Functions: usage]] [[help|Functions: help]] !!! ''Description'' Displays REBOL title and version information on the REBOL console. ``` >> about ****************************************** REBOL 3.0 [Alpha Test] Copyright: 2009 REBOL Technologies All rights reserved. Website: www.REBOL.com Version: 2.100.82.3.1 Build: 4-Sep-2009/6:35:16 Warning: For testing purposes only. Use at your own risk. Language: English Locale: United States Home: C:\rebol\ ****************************************** ```
``` abs value ``` Returns the absolute value. Arguments: ``` value [number! pair! money! time!] ``` See also: [[absolute|Functions: absolute]] [[sign?|Functions: sign?]] [[negate|Functions: negate]] [[-|Functions: -]] Description Note: A short form for absolute. Returns a positive value equal in magnitude. ``` print abs -123 123 ``` ``` print abs -1:23 1:23 ``` ``` print abs -1x4 1x4 ```
``` abs value ``` Returns the absolute value. Arguments: ``` value [number! pair! money! time!] ``` See also: [[abs|Functions: abs]] [[sign?|Functions: sign?]] [[negate|Functions: negate]] [[-|Functions: -]] Description Note: A short form for absolute. Returns a positive value equal in magnitude. ``` print abs -123 123 ``` ``` print abs -1:23 1:23 ``` ``` print abs -1x4 1x4 ```
``` action? value ``` Returns TRUE if it is this type. ``` Arguments: value [any-type!] ``` See also: [[function?|Functions: function?]] [[op?|Functions: op?]] [[native?|Functions: native?]] [[any-function?|Functions: any-function?]] [[type?|Functions: type?]] Description Actions are special functions that operate with datatypes. See [[action!|Datatypes: Action!]] for more. ``` print action? :add true ``` ``` print action? :append true ``` ``` print action? :+ false ``` ``` print action? "add" false ```
``` add value1 value2 ``` Returns the result of adding two values. ``` Arguments: value1 [scalar! date!] value2 ``` See also: [[+|Functions: +]] [[-|Functions: -]] [[subtract|Functions: subtract]] Description Note: The [[+|Functions: +]] operator is a special infix form for this function. Many different datatypes support addition. ``` print add 123 1 124 ``` ``` print add 1.23 .004 1.234 ``` ``` print add 1.2.3.4 4.3.2.1 5.5.5.5 ``` ``` print add $1.01 $0.0000000001 $1.0100000001 ``` ``` print add 3:00 -4:00 -1:00 ``` ``` print add 31-Dec-1999 1 1-Jan-2000 ``` When adding values of different datatypes, the values must be compatible. Auto conversion of the values will occur into the datatype that has the most expansive representation. For example an integer added to a decimal will produce a decimal.
``` ajoin block Reduces and joins a block of values into a new string. Arguments: block [block!] ``` See also: [[join|Functions: join]] [[rejoin|Functions: rejoin]] [[form|Functions: form]] [[reform|Functions: reform]] [[append|Functions: append]] ''Description'' The join and rejoin functions return the same datatype as their first element, be it a string!, file!, binary!, tag!, email! or whatever. However, there are times when you just want to construct a string!, and that's the purpose of ajoin. ''For example'': ``` ajoin ["test" 123] "test123" ``` It is similar to reform but does not insert spaces between values: ``` reform ["test" 123] "test 123" ``` Note that the block is always evaluated: ``` time: 10:30 ajoin [time/hour "h" time/minute "m"] "10h30m" ``` The ajoin function is equivalent to: ``` to-string reduce block ``` ''How it differs'' Here are examples that show how ajoin differs from join and rejoin. ''Compare'': ``` ajoin [<test> 123] "<test>123" ``` with: ``` rejoin [<test> 123] <test123> ``` and: ``` join <test> 123 <test123> ``` Notice that the last two examples return a [[tag!|Datatypes: Tag!]], not a [[string!|Datatypes: String!]].
``` alias word name Creates an alternate spelling for a word. Arguments: word [word!] - Word to alias name [string!] - Name of alias ``` See also: [[set|Functions: set]] [[get|Functions: get]] ''Description'' <<< Warning: The alias function is an advanced feature, and must be used with care. It creates a symbolic equivalence not an additional variable. Be careful not to confuse alias with setting another word to the same value. <<< Create an alias for a word. The alias will be identical in every respect to the aliased word, including symbol comparison and value referencing. ``` alias 'print "pr" pr "testing" testing ``` You can see that they refer to the same value: ``` same? :print :pr true ``` But, it goes deeper than that, because: ``` 'print = 'pr true ``` <<< Special notes The alias cannot be set if the word already appears anywhere within the script or has been used in any way prior to being aliased. Normally you will need to load aliases from a separate file or string. Aliases are special because they work at the symbol table level, allowing them to be used for refinements and dialect words as well. <<<
``` all block Shortcut AND. Evaluates and returns at the first FALSE or NONE. Arguments: block [block!] - Block of expressions ``` See also: [[any|Functions: any]] [[and|Functions: and]] [[or|Functions: or]] [[case|Functions: case]] [[switch|Functions: switch]] ''Description'' The all function is the most common way to test multiple conditions, such as in the line: ``` if all [num > 1 num < 1000] [do something] ``` It works by evaluating each expression in a block until one of the expressions returns none! or false, in which case a none! is returned. Otherwise, the value of the last expression will be returned. ``` print all [1 none] none print all [none 1] none print all [1 2] 2 print all [10 > 1 "yes"] yes print all [1 > 10 "yes"] none time: 10:30 if all [time > 10:00 time < 11:00] [print "time is now"] time is now ``` No other expressions are evaluated beyond the point where a value fails: ``` a: 0 all [none a: 2] print a 0 a: 0 all [1 a: 2] print a 2 day: 10 time: 9:45 ready: all [day > 5 time < 10:00 time: 12:00] print time 12:00 ``` The [[any|Functions: any]] function is a companion of all to test for the opposite condition, where [[any|Functions: any]] one of the values will result in a `true` result.
``` also value1 value2 Returns the first value, but also evaluates the second. Arguments: value1 [any-type!] value2 [any-type!] ``` See also: [[if|Functions: if]] [[either|Functions: either]] [[any|Functions: any]] [[all|Functions: all]] ''Description'' The `also` function lets you evaluate two expressions, but return the first, rather than the second. This function may seem a bit odd at first, but in many cases it can save you from needing another temporary variable. Consider the case where you want to evaluate a block and return its result, but before returning the result, you want to change directories. You could write: ``` result: do block change-dir old-dir return result ``` Or, you could write ``` return also do block change-dir old-dir ``` In fact, that's actually what happens in the [[in-dir|Functions: in-dir]] function. Another case might be an I/O port used by a function that wants to return the port's data but also close it: ``` return also port/locals/buffer close port ``` If you close the port first, the buffer cannot be accessed.
``` alter series value /case If a value is not found in a series, append it; otherwise, remove it. Returns true if added. (Modifies) Arguments: series [series! port! bitset!] value Refinements: /case - Case-sensitive comparison ``` See also: [[find|Functions: find]] [[remove|Functions: remove]] [[insert|Functions: insert]] [[unique|Functions: unique]] [[intersect|Functions: intersect]] [[exclude|Functions: exclude]] [[difference|Functions: difference]] ''Description'' The `alter` function helps you manage small data-sets. It either adds or removes a value depending on whether the value is already included. (The word alter is short for the word "alternate", the action taking place.) For example, let's say you want to keep track of a few options used by your code. The options may be: flour, sugar, salt, and pepper. The following code will create a new block (to hold the data set) and add to it: ``` options: copy [] alter options 'salt probe options [salt] alter options 'sugar probe options [salt sugar] ``` You can use functions like find to test the presence of an option in the set: ``` if find options 'salt [print "Salt was found"] Salt was found ``` If you use alter a second time for the same option word, it will be removed: ``` alter options 'salt probe options [sugar] ``` Normally `alter` values are symbolic words (such as those shown above) but any datatype can be used such as integers, strings, etc. ``` alter options 120 alter options "test" probe options [sugar 120 "test"] ``` Also, `alter` returns true if the value was added to the series, or false if the value was removed.
``` and value1 value2 Returns the first value ANDed with the second. Arguments: value1 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] value2 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] ``` See also: [[or|Functions: or]] [[all|Functions: all]] [[not|Functions: not]] [[xor|Functions: xor]] [[logic?|Functions: logic?]] [[integer?|Functions: integer?]] ''Description'' For [[logic!|Datatypes: Logic!]] values, both values must be `true` to return `true`, otherwise a `false` is returned. AND is an infix operator. ``` print true and true true print true and false false print (10 < 20) and (20 > 15) true ``` ''Programming style'' It's usually better to use all for anding conditional logic, such as the example above. ``` if all [10 < 20 20 > 15] ... ``` For [[integer!|Datatypes: Integer!]], [[tuple!|Datatypes: Tuple!]], [[binary!|Datatypes: Binary!]], and other datatypes, each bit is separately anded. ``` print 123 and 1 1 print 1.2.3.4 and 255.0.255.0 1.0.3.0 ```
``` and~ value1 value2 ``` Returns the first value ANDed with the second. ``` Arguments: value1 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] value2 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] ``` See also: [[and|Functions: and]] [[or|Functions: or]] [[xor|Functions: xor]] [[or~|Functions: or~]] [[xor~|Functions: xor~]] Description This is the primary function behind the [[and|Functions: and]] operator. It can be used where you want prefix rather than infix notation: ``` bits: and~ mask 3 ```
``` any block Shortcut OR. Evaluates and returns the first value that is not FALSE or NONE. Arguments: block [block!] - Block of expressions ``` See also: [[all|Functions: all]] [[or|Functions: or]] [[and|Functions: and]] [[case|Functions: case]] [[switch|Functions: switch]] ''Description'' The `any` function is the most common way to test for one of multiple conditions, such as in the line: ``` if any [a > 10 b > 20 c > 30] [do something] ``` Here, if any one of the conditions produces a true result, the if will evaluate the block. This function works by evaluating each expression in a block until one of the expressions returns a value other than none! or false, in which case the value is returned. Otherwise, none! will be returned. Examples to help show how it works: ``` print any [1 none] 1 print any [none 1] 1 print any [none none] none print any [false none] none print any [true none] true time: 10:30 if any [time > 10:00 time < 11:00] [print "time is now"] time is now ``` No other expressions are evaluated beyond the point where a successful value is found. This can be useful. For example: ``` a: 0 any [none a: 2] print a 2 a: 0 any [1 a: 2] print a 0 day: 10 time: 9:45 ready: any [day > 5 time < 10:00 time: 12:00] print time 9:45 ``` The `any` function is also useful for setting default values. For example: size: any [size 100] If size was none!, then it gets set to 100. This works even better if there are alternative defaults: size: any [size prefs/size 100] Another use for any is to emulate a sequence of if...elseif...elseif...else. Instead of writing: either cond-1 [ code-1 ] [ either cond-2 [ code-2 ] [ either cond-3 ... ] ] it is possible to write: any [ if cond-1 [ code-1 true ; in case code-1 returns FALSE or NONE ] if cond-2 [ code-2 true ] ... ] Also see the case function for more about this code pattern. The [[all|Functions: all]] function is a companion of any to test for the opposite condition, where all of the values must be `true` to return a `true` result.
``` any-block? value Return TRUE if value is any type of block. Arguments: value [any-type!] ``` See also: [[block?|Functions: block?]] [[paren?|Functions: paren?]] [[path?|Functions: path?]] [[any-function?|Functions: any-function?]] [[any-string?|Functions: any-string?]] [[any-word?|Functions: any-word?]] ''Description'' Returns` true` only if the value is a [[block!|Datatypes: Block!]] (any kind of block) and `false` for all other values. ``` print any-block? [1 2] true print any-block? first [(1 2) 3] true print any-block? 'a/b/c true print any-block? 12 false ``` To learn what datatypes are blocks: ``` print any-block! block! paren! path! set-path! get-path! lit-path! ```
``` any-function? value Return TRUE if value is any type of function. Arguments: value [any-type!] ``` See also: [[function?|Functions: function?]] [[native?|Functions: native?]] [[op?|Functions: op?]] [[any-block?|Functions: any-block?]] [[any-string?|Functions: any-string?]] [[any-word?|Functions: any-word?]] ''Description'' Returns `true` if the value is any type of function and returns false for all other values. ``` print any-function? :find true print any-function? :+ true print any-function? func [] [print "hi"] true print any-function? 123 false ``` To learn what datatypes are functions: ``` print any-function! native! action! rebcode! command! op! closure! function! ```
``` any-path? value Return TRUE if value is any type of path. Arguments: value [any-type!] ``` ''Description'' Returns `true` if the value is any type of [[path!|Datatypes: Path!]] and returns false for all other values. ``` print any-path? 'test/this true print any-path? first [example/item: 10] true print any-path? second [print :example/item] true print any-path? 123 false ``` To learn what datatypes are paths: ``` print any-path! path! set-path! get-path! lit-path! ```
``` any-string? value Return TRUE if value is any type of string. Arguments: value [any-type!] ``` See also: [[string?|Functions: string?]] [[file?|Functions: file?]] [[email?|Functions: email?]] [[url?|Functions: url?]] [[any-block?|Functions: any-block?]] [[any-function?|Functions: any-function?]] ''Description'' Returns `true` for any type of string, and `false` for all other values. ``` if any-string? "Hello" [print "a string"] a string probe any-string? email@rebol.com true probe any-string? ftp://ftp.rebol.com true probe any-string? %dir/file.txt true probe any-string? 11-Jan-2000 false ``` To see what datatypes are strings: ``` print any-string! string! file! email! url! tag! issue! ```
``` any-word? value Return TRUE if value is any type of word. Arguments: value [any-type!] ``` See also: [[any-block?|Functions: any-block?]] [[any-function?|Functions: any-function?]] [[any-string?|Functions: any-string?]] ''Description'' Returns `true` for any type of word and `false` for all other values. ``` print any-word? 'word true print any-word? /word true print any-word? first [set-word: 'lit-word :get-word] true print any-word? second [set-word: 'lit-word :get-word] true print any-word? third [set-word: 'lit-word :get-word] true print any-word? 123 false ``` To see what datatypes are words: ``` print any-word! word! set-word! get-word! lit-word! refinement! ```
``` append series value /part length /only /dup count Inserts a value at tail of series and returns the series at head. (Modifies) Arguments: series [series! port! map! gob! object! bitset!] - Series at point to insert value [any-type!] - The value to insert Refinements: /part - Limits to a given length or position length [number! series! pair!] /only - Only insert a block as a single value (not the contents of the block) /dup - Duplicates the insert a specified number of times count [number! pair!] ``` See also: [[insert|Functions: insert]] [[change|Functions: change]] [[remove|Functions: remove]] [[repend|Functions: repend]] ''Description'' The append function is a shortcut for doing an insert at the tail of any type of series and returning the head: ``` head insert tail series value ``` Basic examples: ``` string: copy "hello" probe append string " there" "hello there" file: copy %file probe append file ".txt" %file.txt url: copy http:// probe append url "www.rebol.com" http://www.rebol.com ``` The `/only` refinement forces a block to be appended as a single block element, rather than appending the separate elements of the block: ``` block: copy [1 2 3] probe append block [4 5 6] [1 2 3 4 5 6] block: copy [1 2 3] probe append/only block [4 5 6] [1 2 3 [4 5 6]] ``` To learn more about the operation of the other refinements, see the [[insert|Functions: insert]] function.
``` apply func block /only Apply a function to a reduced block of arguments. Arguments: func [any-function!] - Function value to apply block [block!] - Block of args, reduced first (unless /only) Refinements: /only - Use arg values as-is, do not reduce the block ``` See also: [[do|Functions: do]] [[switch|Functions: switch]] [[case|Functions: case]] ''Description'' When you evaluate a function, you normally provide any arguments directly in-line with its call: ``` append data 123 ``` However, there are times when you want to store the arguments as a single block and pass them to the function. This is the purpose of the apply function. The above example can be written as: ``` apply :append [data 123] ``` or, using a variable to hold the block: ``` args: [data 123] apply :append args ``` If any arguments are missing from the block, a none! is passed instead: ``` data: [456] apply :append [data] probe data [456 none] ``` Function refinements can also be passed in the order they are specified by the arguments spec block. For example, we can see: ``` >> ? append USAGE: APPEND series value /part length /only /dup count ``` So in this example we use the /dup refinement: ``` data: [456] apply :append [data 1 none none none true 3] probe data [456 1 1 1] ``` Note that the refinement itself must be set to true.
``` arccosine value /radians Returns the trigonometric arccosine (in degrees by default). Arguments: value [number!] Refinements: /radians - Returns result in radians ``` See also: [[arcsine|Functions: arcsine]] [[arctangent|Functions: arctangent]] [[cosine|Functions: cosine]] [[exp|Functions: exp]] [[log-10|Functions: log-10]] [[log-2|Functions: log-2]] [[log-e|Functions: log-e]] [[power|Functions: power]] [[sine|Functions: sine]] [[square-root|Functions: square-root]] [[tangent|Functions: tangent]] ''Description'' The arccosine provides the inverse of the [[cosine|Functions: cosine]] function. ``` print arccosine .5 60.0 ``` Note that `arccosine` goes to infinity at 90 degrees and will cause a numeric overflow.
``` arcsine value /radians Returns the trigonometric arcsine (in degrees by default). Arguments: value [number!] Refinements: /radians - Returns result in radians ``` See also: [[arccosine|Functions: arccosine]] [[arctangent|Functions: arctangent]] [[cosine|Functions: cosine]] [[exp|Functions: exp]] [[log-10|Functions: log-10]] [[log-2|Functions: log-2]] [[log-e|Functions: log-e]] [[power|Functions: power]] [[sine|Functions: sine]] [[square-root|Functions: square-root]] [[tangent|Functions: tangent]] ''Description'' The `arcsine` provides the inverse of the [[sine|Functions: sine]] function. ``` print arcsine .5 30.0 ``` Note that arccsine goes to infinity at 0 and each 180 degrees and will cause a numeric overflow.
``` arctangent value /radians Returns the trigonometric arctangent (in degrees by default). Arguments: value [number!] Refinements: /radians - Returns result in radians ``` See also: [[arccosine|Functions: arccosine]] [[arcsine|Functions: arcsine]] [[cosine|Functions: cosine]] [[exp|Functions: exp]] [[log-10|Functions: log-10]] [[log-2|Functions: log-2]] [[log-e|Functions: log-e]] [[power|Functions: power]] [[sine|Functions: sine]] [[square-root|Functions: square-root]] [[tangent|Functions: tangent]] ''Description'' The `arctangent` function provides the inverse of the [[tangent|Functions: tangent]] function. ``` print arctangent .22 12.40741852740074 ```
``` array size /initial value Makes and initializes a series of a given size. Arguments: size [integer! block!] - Size or block of sizes for each dimension Refinements: /initial - Specify an initial value for all elements value - Initial value (will be called each time if a function) ``` See also: [[make|Errors: no-make-dir]] [[pick|Functions: pick]] [[poke|Functions: poke]] ''Description'' In REBOL, arrays are simply blocks that are initialized to a specific size with all elements set to an initial value (v:none by default). The [[array|Functions: array]] function is used to create and initialize arrays. Supplying a single integer as the argument to array will create an array of a single dimension. The example below creates a five element array with values set to `none`: ``` block: array 5 probe block [none none none none none] ``` ``` print length? block 5 ``` To initialize an array to values other than NONE, use the `/initial` refinement. The example below intializes a block with zero values: ``` block: array/initial 5 0 probe block [0 0 0 0 0] ``` To create an array of multiple dimensions, provide a block of integers as the argument to the [[array|Functions: array]] function. Each integer specifies the size of that dimension of the array. (In REBOL, such multidimensional arrays are created using blocks of blocks.) ``` xy-block: array [2 3] probe xy-block [[none none none] [none none none]] ``` ``` xy-block: array/initial [2 3] 0 probe xy-block [[0 0 0] [0 0 0]] ``` Once an array has been created, you can use paths or the [[pick|Functions: pick]] and [[poke|Functions: poke]] functions to set and get values of the block based on their indices: ``` block/3: 1000 poke block 5 now probe block [0 0 1000 0 12-Feb-2009/17:46:59-8:00] ``` ``` probe block/3 1000 ``` ``` repeat n 5 [poke block n n] probe block [1 2 3 4 5] ``` ``` xy-block/2/1: 1.2.3 xy-block/1/3: copy "test" probe xy-block [[0 0 "test"] [1.2.3 0 0]] ``` ``` probe xy-block/2/1 1.2.3 ``` ``` repeat y 2 [ dim: pick xy-block y repeat x 3 [poke dim x to-pair reduce [x y]] ] probe xy-block ``` ''Coding Style Notes'' REBOL uses the concept of expandable series for holding and manipulating data, rather than the concept of fixed size arrays. For example, in REBOL you would normally write: ``` block: copy [] repeat n 5 [append block n] ``` rather than: ``` block: array 5 repeat n 5 [poke block n n] ``` In other words, REBOL does not require you to specify the size of data arrays (blocks, bytes, or strings) in advance. They are dynamic.
''Description'' <<< Editor note: This function no longer exist in REBOL 3. `as-binary` converts a string datatype to a binary datatype but without copying the contents of the string. Normally, if you use to-binary, a new string will be created. <<< This function is most useful if you have large strings that you need to access or modify using binary operations. ``` print as-binary "Testing 1...2...3" print as-binary #ABC-def-xyz print as-binary %test-file.txt ```
``` as-pair x y Combine X and Y values into a pair. Arguments: x [number!] y [number!] ``` See also: [[to-pair|Functions: to-pair]] [[pair?|Functions: pair?]] ''Description'' Provides a shortcut for creating pair! values from separate X and Y integers. ``` print as-pair 100 50 100x50 ``` See the [[pair!|Datatypes: Pair!]] word for more detail.
''Description'' <<< Editor note: This function no longer exists in REBOL 3 as-string converts a binary datatype to a string datatype but without copying the contents of the binary string. Normally, if you use to-string, a new string will be created. <<< This function is most useful if you have large binary strings that you need to access or modify using other string operations. ``` data: as-string read/binary %bin-file print as-string #{54657374696E6720312E2E2E322E2E2E33} print as-string #{4142432D6465662D78797A} print as-string #{746573742D66696C652E747874} ```
``` ascii? value Returns TRUE if value or string is in ASCII character range (below 128). Arguments: value [any-string! char! integer!] ``` ''Description'' No description provided.
``` ask question /hide Ask the user for input. Arguments: question [series!] - Prompt to user Refinements: /hide - mask input with * ``` See also: [[confirm|Functions: confirm]] [[input|Functions: input]] [[prin|Functions: prin]] [[print|Functions: print]] ''Description'' Provides a common prompting function that is the same as a prin followed by an input. The resulting input will have spaces trimmed from its head and tail. The /hide refinement hides input with "*" characters. The function returns a string!. Example, where the user enters Luke as input: ``` ask "Your name, please? " Your name, please? Luke == "Luke" ```
``` assert conditions /type Assert that condition is true, else throw an assertion error. Arguments: conditions [block!] Refinements: /type - Safely check datatypes of variables (words and paths) ``` See also: [[all|Functions: all]] [[try|Functions: try]] ''Contents'' * Description * Asserting truth * Asserting datatypes ''Description'' In code, it is common to check conditions that should always be valid or true. For example, a check may be made for a value to be in range or of a given datatype. Since the conditions are always supposed to be true, it's often not worth the effort to provide a detailed error message or explanation if the condition fails, and often such information would only be meaningful to the programmer, not the end user. To make it easier to check such conditions, the assert function is provided. `Assert` can check "truth" conditions, or with a refinement, it can check datatype validity conditions. ''Asserting truth'' To check truth conditions, the argument of assert is a block of one or more conditions, and each is checked (similar to all) to be true: ``` num: 10 assert [num > 20] ** Script error: assertion failed for: [num > 20] ** Where: assert ** Near: assert [num > 20] ``` Note that for compound assertions, the error message will indicate the assertion that failed: ``` num: 10 age: 20 assert [num > 0 age > 50] ** Script error: assertion failed for: [age > 50] ** Where: assert ** Near: assert [num > 0 age > 50] ``` Look at the error line closely, and you can tell which one failed. Note: only the first three elements of the failed assertion will be shown (to help avoid long error lines.) ''Asserting datatypes'' It is also common to validate datatypes using the /type refinement: ``` age: "37" name: "Bob" assert/type [age integer! name string!] ** Script error: datatype assertion failed for: age ** Where: assert ** Near: assert/type [age integer! name string!] ``` It fails because age is actually a string, not an integer. The `assert` function is useful for validating value before a section of code that depends on those value: ``` assert/type [ spec object! body block! spec/size number! spec/name [string! none!] spec/options [block! none!] ] ``` Note that assert is safe to use on all function datatypes. The functions will not be evaluated as part of the process; therefore, assert is an easy way to prevent function passage in unwanted cases.
``` at series index Returns the series at the specified index. Arguments: series [series! gob! port!] index [number! logic! pair!] ``` See also: [[skip|Functions: skip]] [[pick|Functions: pick]] [[head|Functions: head]] [[tail|Functions: tail]] ''Description'' Provides a simple way to index into any type of series. at returns the series at the new index point. Note that the operation is relative to the current position within the series. A positive integer N moves to the position N in the series: ``` numbers: [11 22 33] print at numbers 2 22 33 ``` An index of 0 is the same as an index of 1: ``` print at numbers 0 11 22 33 ``` Using a negative index N, you can go N values backwards in a series: ``` numbers: at numbers 3 print numbers 33 print at numbers -1 22 33 ``` More examples, combined with other series functions: ``` words: [grand grape great good] print first at words 2 grape remove at words 2 insert at words 3 [super] probe words [grand great super good] ```
``` attempt block Tries to evaluate a block and returns result or NONE on error. Arguments: block [block!] ``` See also: [[try|Functions: try]] [[error?|Functions: error?]] ''Description'' The `attempt` function is a shortcut for the frequent case of: ``` error? try [block] ``` More accurately, this is performed: ``` if not error? try [set/any 'val block] [val] ``` The format for attempt is: ``` attempt [block] ``` `attempt` is useful where you either do not care about the error result or you want to make simple types of decisions based on the error. ``` attempt [make-dir %fred] ``` `attempt` returns the result of the block if an error did not occur. If an error did occur, a none is returned. In the line: ``` value: attempt [load %data] probe value none ``` the value is set to none if the `%data` file cannot be loaded (e.g. it is missing or contains an error). This allows you to write conditional code such as: ``` if not value: attempt [load %data] [print "Problem"] Problem ``` Or code such as: ``` value: any [attempt [load %data] [12 34]] probe value [12 34] ```
``` back series Returns the series at its previous position. Arguments: series [series! gob! port!] ``` See also: [[next|Functions: next]] [[last|Functions: last]] [[head|Functions: head]] [[tail|Functions: tail]] [[head?|Functions: head?]] [[tail?|Functions: tail?]] ''Description'' Works on any type of series. If the series is at its head, it will remain at its head. back will not go past the head, nor will it wrap to the tail. ``` print back tail "abcd" d str: tail "time" until [ str: back str print str head? str ] e me ime time blk: tail [1 2 3 4] until [ blk: back blk print first blk head? blk ] 4 3 2 1 ```
``` binary? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. ``` print binary? #{13ff acd0} true print binary? 1234 false ```
``` bind words context /copy /only /new /set Binds words to the specified context. (Modifies) Arguments: words [block! any-word!] - A block of words or single word (returned) context [any-word! any-object!] - A reference to the target context Refinements: /copy - Deep copy block before binding it /only - Bind only first block (not deep) /new - Add to context any new words found /set - Add to context any new set-words found ``` See also: [[bind?|Functions: bind?]] [[use|Functions: use]] [[do|Functions: do]] [[func|Functions: func]] [[function|Functions: function]] [[does|Functions: does]] [[make|Functions: make]] [[import|Functions: import]] ''Description'' Binds meaning to words in a block. That is, it gives words a context in which they can be interpreted. This allows blocks to be exchanged between different contexts, which permits their words to be understood. For instance a function may want to treat words in a global database as being local to that function. The second argument to bind is a word from the context in which the block is to be bound. Normally, this is a word from the local context (e.g. one of the function arguments), but it can be a word from any context within the system. bind will modify the block it is given. To avoid that, use the /copy refinement. It will create a new block that is returned as the result. ``` words: [a b c] fun: func [a b c][print bind words 'a] fun 1 2 3 fun "hi" "there" "fred" hi there fred words: [a b c] object: make object! [ a: 1 b: 2 c: 3 prove: func [] [print bind words 'a] ] object/prove 1 2 3 settings: [start + duration] schedule: function [start] [duration] [ duration: 1:00 do bind settings 'start ] print schedule 10:30 11:30 ``` Editor note: Describe `/new` here Editor note: Describe `/set` here
``` bind? words Returns the context in which a word is bound. Arguments: words [any-word!] ``` See also: [[bind|Functions: bind]] [[value?|Functions: value?]] ''Description'' The `bind?` function can tell whether words are bound to a context or not. This tells you if the word has a value related to it. For example, let's say that obtain the list of the words used by a function (its arguments, refinements, and local variables): ``` words: words-of :append [series value /part length /only /dup count] ``` If you try to get the value of one of those words, you will find that it is not bound. For example, try to get the value of series, the first word: ``` get first words ** Script error: series word is not bound to a context ** Where: get ** Near: get first words ``` The error occurs because the words that represent the arguments of the append are not bound (have no context) within the block. They are unbound. But, with bind?, you can check a word before you get it: ``` bind? first words none ``` Now you can write: ``` value: all [bind? first words get first words] ``` In REBOL 3, you should know that there are two types of bindings: |absolute |a word is bound to a context such as an object, module, or closure. For those, `bind?` returns the object of a word.| |relative a |word is bound to a function stack frame. For those, bind? returns true. (It cannot return a context, because for functions contexts are put on the program stack, which is volatile.)| Here is an example of using bind? for object words (absolute bindings): ``` obj: make object! [ a: 10 b: "test" c: now ] blk: [a b] bind blk obj probe reduce blk [10 "test"] probe body-of bind? first blk [ a: 10 b: "test" c: 9-Dec-2005/9:03:36-8:00 ] ``` When used for function words, bind? only tells you if the word is bound: ``` test: func [arg] [ if bind? 'arg [print "the word is bound"] ] test 123 "the word is bound" ```
``` bitset? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[charset|Functions: charset]] ''Description'' Returns FALSE for all other values. ``` print bitset? make bitset! "abc" true print bitset? charset "abc" true print bitset? 123 false ```
``` block? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. ``` print block? [1 2 3] true print block? "1 2 3" false data: load "1 2 3" ; converts "1 2 3" into a block if block? data [print data] 1 2 3 ```
``` body-of value Returns a copy of the body of a function, object, or module Arguments: value ``` See also: [[reflect|Functions: reflect]] [[spec-of|Functions: spec-of]] [[title-of|Functions: title-of]] [[types-of|Functions: types-of]] [[values-of|Functions: values-of]] [[words-of|Functions: words-of]] ''Description'' No description provided.
``` break /return value Breaks out of a loop, while, until, repeat, foreach, etc. Refinements: /return - Forces the loop function to return a value value [any-type!] ``` See also: [[continue|Functions: continue]] [[catch|Functions: catch]] [[exit|Functions: exit]] [[return|Functions: return]] [[loop|Functions: loop]] [[repeat|Functions: repeat]] [[for|Functions: for]] [[forall|Functions: forall]] [[foreach|Functions: foreach]] [[forever|Functions: forever]] [[forskip|Functions: forskip]] [[while|Functions: while]] [[until|Functions: until]] ''Description'' The `break` function stops loop functions. For example: ``` repeat n 5 [ print n if n > 2 [break] ] 1 2 3 ``` The current loop is immediately terminated and evaluation resumes after the repeat function. ''Return Value'' The `break /return` refinement will return a value from a loop. It is commonly used to return a specific value or pass to a conditional expression when the loop is terminated early. Here's an example: ``` print repeat n 5 [ if n > pi [break/return n] none ] 4 ``` An example using foreach : ``` values: [8:30 breakfast 12:00 lunch 5:00 dinner] meal: foreach [time event] [ if time > 14:00 [break/return event] none ] probe meal dinner ``` ''Important Scoping Rule'' The `break` function acts immediately on the "closest block". Although break can be placed anywhere within the block being repeated, even within a sub-block or function, because break is a function that is not directly bound to the loop, it will break the closest loop, not necessarily the intended loop. This does not affect most programs but could affect custom-made loop functions. In this example, even though the break appears in the repeat loop, it applies to the a-loop loop block and has no effect on the outer repeat loop. ``` a-loop: func [count block] [loop count block] repeat a 3 [ print a a-loop 4 [break] ] 1 2 3 ```
``` browse url Open web browser to a URL or local file. Arguments: url [url! file! none!] ``` ''Description'' If the browser cannot be found, nothing will happen.
``` bugs View bug database. ``` ''Description'' No description provided.
``` call command Run another program; return immediately. Arguments: command [string!] - An OS-local command line, quoted as necessary ``` See also: [[do|Functions: do]] [[launch|Functions: launch]] Note this special requirement: <<< Security In order to use call, you must have secure call enabled. <<< ''Description'' The `call` function interfaces to the operating system's command shell to execute programs, shell commands, and redirect command input and output. `call` is normally blocked by the security level specified with the secure function. To use it, you must change your secure settings or run the script with reduced security (at your own risk): ``` secure call ``` The `call` function accepts one argument, which can be a string or a block specifying a shell command and its arguments. The following example shows a string as the call argument. ``` call "cp source.txt dest.txt" ``` Use a block argument with call when you want to include REBOL values in the call to a shell command, as shown in the following example: ``` source: %source.txt dest: %dest.txt call reduce ["cp" source dest] ``` The `call` function translates the file names in a block to the notation used by the shell. For example: ``` [dir %/c/windows] ``` will convert the file name to windows shell syntax before doing it. When shell commands are called, they normally run as a separate process in parallel with REBOL. They are asynchronous to REBOL. However, there are times when you want to wait for a shell command to finish, such as when you are executing multiple shell commands. In addition, every shell command has a return code, which normally indicates the success or failure of the command. Typically, a shell command returns zero when it is successful and a non-zero value when it is unsuccessful. The `/wait` refinement causes the call function to wait for a command's return code and return it to the REBOL program. You can then use the return code to verify that a command executed successfully, as shown in the following example: ``` if zero? call/wait "dir" [ print "worked" ] ``` In the above example, call successfully executes the Windows dir command, which is indicated by the zero return value. However, in the next example, call is unsuccessful at executing the xcopy command, which is indicated by the return value other than zero. ``` if not zero? code: call/wait "xcopy" [ print ["failed:" code] ] ``` In Windows and Unix (Linux), input to a shell command can be redirected from a file, URL, string, or port. By default, a shell command's output and errors are ignored by REBOL. However, shell command output and errors can be redirected to a file, URL, port, string, or the REBOL console. ``` instr: "data" outstr: copy "" errstr: copy "" call/input/output/error "sort" instr outstr errstr print [outstr errstr] ``` See the REBOL Command Shell Interface documentation for more details. Editor note: Proper link to the REBOL Command Shell Interface?
''Description'' This function is provided to convert from a string character index position to an xy offset within the text of a face. This is used primarily for text editing or for text mapping operations such as for creating colored or hyperlinked text. ``` out: layout [ bx: box 10x15 red tx: body 100x100 ] tx/text: {This is an example character string.} xy: caret-to-offset tx at tx/text 14 bx/offset: tx/offset + xy view out ``` The resulting offset xy was added to the face position tx/offset to find the correct position to locate the box bx. In the above example the caret-to-offset function was used on a face that have not yet been shown. This makes pre-display processing, colored text, and hyperlinking possible using this function in combination with size-text. The function can also be used after a face has been shown. <<< Remember that when making changes to the contents of strings that are longer than 200 characters, you must set the text face line-list to none to force the recomputation of all line breaks. <<< Editor note: Need example for setting text face line-list to none See the [[offset-to-caret|Functions: offset-to-caret]] function for the reverse conversion.
``` case block /all Evaluates each condition, and when true, evaluates what follows it. Arguments: block [block!] - Block of cases (conditions followed by values) Refinements: /all - Evaluate all cases (do not stop at first true case) ``` See also: [[switch|Functions: switch]] [[if|Functions: if]] [[either|Functions: either]] [[select|Functions: select]] [[find|Functions: find]] ''Description'' The `case` function provides a useful way to evaluate different expressions depending on specific conditions. It differs from the switch function because the conditions are evaluated and can be an expression of any length. The basic form of case is: ``` case [ cond1 [code1] cond2 [code2] cond3 [code3] ] ``` The if a condition is `true` (that is, it is not `false` or `none` ) then the block that follows it is evaluated, otherwise the next condition is evaluated. ``` num: 50 case [ num < 10 [print "small"] num < 100 [print "medium"] num < 1000 [print "large"] ] medium ``` To create a default `case`, simply use true as your last condition: ``` num: 10000 case [ num < 10 [print "small"] num < 100 [print "medium"] num < 1000 [print "large"] true [print "huge"] ] huge ``` ''Return Value'' The case function will return the value of the last expression it evaluated. This can come in handy: ``` num: 50 value: case [ num < 10 [num + 2] num < 100 [num / 2] true [0] ] print value 25 ``` ''Evaluating All'' Normally the `case` function stops after the first true condition is found and its block evaluated. However, the `/all` option forces case to evaluate the expressions for all `true` conditions. ``` num: 50 case/all [ num < 10 [print "small"] num < 100 [print "medium"] num < 1000 [print "large"] ] medium large ```
``` catch block /name word /quit Catches a throw from a block and returns its value. Arguments: block [block!] - Block to evaluate Refinements: /name - Catches a named throw word [word! block!] - One or more names /quit - Special catch for QUIT native ``` See also: [[throw|Functions: throw]] [[do|Functions: do]] [[try|Functions: try]] ''Description'' `catch` and [[throw|Functions: throw]] go together. They provide a way to exit from a block without evaluating the rest of the block. To use it, provide catch with a block to evaluate. If within that block a throw is evaluated, it will return from the catch at that point. The result of the catch will be whatever was passed as the argument to the throw. ``` write %file.txt "i am a happy little file with no real purpose" print catch [ if exists? %file.txt [throw "Doc found"] "Doc not found" ] Doc not found ``` When using multiple `catch` functions, provide them with a name using the `/name` refinement to identify which one will catch which throw. <<< Editor note: Example with `/name` Editor note: Example of using catch in a function spec. <<<
``` cause-error err-type err-id args Causes an immediate error throw with the provided information. Arguments: err-type [word!] err-id [word!] args ``` ''Description'' * Editor note: Description is a stub. * `cause-error` constructs and immediately throws an [[error!|Datatypes: Error!]]. * Editor note: Link to concept of error types? * Editor note: Argument description is a stub. * The `err-type` argument controls the general type of error to construct, valid values are the words of the `system/catalog/errors` object. The `err-id` argument selects a specific error type within the `err-type` class of errors. The args argument is used to pass error-specific values * Editor note: Description of error IDs is a stub. All information about the currently available error types can be found in `system/catalog/errors`: ``` >> words-of system/catalog/errors == [Throw Note Syntax Script Math Access Command resv700 User Internal] ``` The specific errors within a given class can be inspected similarly: ``` >> ? system/catalog/errors/math SYSTEM/CATALOG/ERRORS/MATH is an object of value: code integer! 400 type string! "math error" zero-divide string! "attempt to divide by zero" overflow string! "math or number overflow" positive string! "positive number required" ``` All words except for code and type within an error type are possible specific errors. Their associated value is part of the error message that will displayed to the user if the error remains unhandled. Some errors take arguments: ``` >> ? system/catalog/errors/script/no-value SYSTEM/CATALOG/ERRORS/SCRIPT/NO-VALUE is a block of value: [:arg1 "has no value"] ``` As an example, this no-value error which takes a single argument can be caused as follows: ``` >> cause-error 'script 'no-value 'Foo ** script error: Foo has no value ``` Similarly, the two-argument no-arg error can be caused as follows: ``` >> cause-error 'script 'no-arg [Foo bar] ** script error: Foo is missing its bar argument ```
``` cd path Change directory (shell shortcut function). Arguments: path [file! word! path! unset! string!] - Accepts %file, :variables and just words (as dirs) ``` See also: [[change-dir|Functions: change-dir]] [[delete|Functions: delete]] [[ls|Functions: ls]] [[list-dir|Functions: list-dir]] [[make-dir|Functions: make-dir]] [[mkdir|Functions: mkdir]] [[pwd|Functions: pwd]] [[rm|Functions: rm]] [[what-dir|Functions: what-dir]] ''Description'' Variant of [[change-dir|Functions: change-dir]] for shell use. Supports inputting words as directory names: ``` cd .. cd somewhere ```
``` change series value /part length /only /dup count Changes a value in a series and returns the series after the change. (Modifies) Arguments: series [series! gob! port!] - Series at point to change value [any-type!] - The new value Refinements: /part - Limits the amount to change to a given length or position length [number! series! pair!] /only - Only change a block as a single value (not the contents of the block) /dup - Duplicates the change a specified number of times count [number! pair!] ``` See also: [[append|Functions: append]] [[clear|Functions: clear]] [[insert|Functions: insert]] [[remove|Functions: remove]] [[sort|Functions: sort]] ''Contents'' * Description * Result * Partial changes * Duplication * Description The [[change|Functions: change]] function modifies any type of series, such as a [[string!|Datatypes: String!]] or [[block!|Datatypes: Block!]], at its current index position. It has many variations, but let's take a simple example that modifies a string! series: ``` name: "bog" change name "d" probe name "dog" ``` ``` change next name "i" probe name "dig" ``` ``` change tail name "it" probe name "digit" ``` Here is an example that changes a [[block!|Datatypes: Block!]] series: ``` colors: [red green blue] change colors 'gold probe colors [gold green blue] ``` ``` change at colors 3 [silver orange teal] probe colors [gold green silver orange teal] ``` As you can see, if the second argument is a single value, it will replace the value at the current position in the first series. However, if the second argument is a series compatible with the first (block or string-based datatype), all of its values will replace those of the first argument or series. ''Result'' ''Be sure to note that [[change|Functions: change]] returns the series position just past the modification''. This allows you to cascade multiple changes. For example: test: "abcde" change change test "1" "23" probe test "123de" So, you must use head if you need the string at its starting position: ``` probe head change "bog" "d" "dog" ``` ``` probe head change [1 4 5] [1 2 3] [1 2 3] ``` ``` probe head change [123 "test"] "the" ["the" "test"] ``` ''Partial changes'' The /PART refinement changes a specified number of elements within the target series. In this line, the 2 indicates that the "ab" are both replaced with the new string, "123": ``` probe head change/part "abcde" "123" 2 "123cde" ``` ''Duplication'' ``` probe head change/dup "abc" "->" 5 "->->->->->" ``` <<< Editor note: This section is new or has has recently changed and is still under construction. <<< ``` title: copy "how it REBOL" change title "N" probe title "Now it REBOL" ``` ``` change find title "t" "s" probe title "Now is REBOL" ``` ``` blk: copy ["now" 12:34 "REBOL"] change next blk "is" probe blk ["now" "is" "REBOL"] ``` ``` probe head change/only [1 4 5] [1 2 3] [[1 2 3] 4 5] ``` ``` probe head change/only [1 4 5] [[1 2 3]] [[[1 2 3]] 4 5] ``` ``` string: copy "crush those grapes" change/part string "eat" find/tail string "crush" probe string "eat those grapes" ```
``` change-dir path Changes the current directory path. Arguments: path [file!] ``` See also: [[make-dir|Functions: make-dir]] [[what-dir|Functions: what-dir]] [[list-dir|Functions: list-dir]] ''Description'' Changes the value of `system/script/path`. This value is used for file-related operations. Any file path that does not begin with a slash `/` will be relative to the path in system/script/path. When a script file is executed using the do native, the path will automatically be set to the directory containing the path. When REBOL starts, it is set to the current directory where REBOL is started. ``` current: what-dir make-dir %./rebol-temp/ probe current %/C/REBOL/3.0/docs/scripts/ change-dir %./rebol-temp/ probe what-dir %/C/REBOL/3.0/docs/scripts/rebol-temp/ change-dir current delete %./rebol-temp/ probe what-dir %/C/REBOL/3.0/docs/scripts/ Note that the shorter shell friendly cd also exists. ```
``` char? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description '' Returns FALSE for all other values. ``` print char? #"1" true print char? 1 false ```
``` charset chars /length len Makes a bitset of chars for the parse function. Arguments: chars [string! block! binary! char! integer!] Refinements: /length - Preallocate this many bits len [integer!] - Must be > 0 ``` See also: [[complement|Functions: complement]] [[char?|Functions: char?]] ''Description'' The charset function is a shortcut for: ``` make bitset! value ``` It is used often for character based bitsets. ``` chars: charset "aeiou" print find chars "o" true print find "there you go" chars ere you go digits: charset "0123456789" area-code: ["(" 3 digits ")"] phone-num: [3 digits "-" 4 digits] print parse "(707)467-8000" [[area-code | none] phone-num] true ```
``` chat Open REBOL DevBase forum/BBS. ``` ''Description'' Downloads and opens the [[DevBase|http://www.rebol.com/r3/docs/r3-funcs.html]] developer forum. This is the primary BBS for REBOL discussions. See [[Chat Quick Start|http://www.rebol.net/wiki/RebDev_Quick_Start]] for the basics and links to other information. Example: ``` >> chat Fetching chat... Script: "RebDev Command Line Interface" Version: 0.3.2 Date: 26-Jan-2009 --- Note: login initiated --- Note: fetching user list --- Note: checking for new messages --- Note: there are new messages 852 message records Alerts: 139 A Added www.rebol.net/wiki/RebDev_Quick_Star 87 Carl 13 days 141 A Enter 140 for chat about chat. 140 Carl 13 days 466 A You can now MOVE and REMOVE posts. 87 Carl 5 days Top headings: > 2 H Server admin 0 admin 1:23 hours 4 H User messages 0 admin 1:23 hours 5 H General 0 admin 12 days 14 H R3 0 Carl 24 mins 15 H R2 0 Carl 1:54 hours 16 H Tools 0 Carl 2:01 hours 17 H Websites 0 Carl 4 days 18 H Community 0 Carl 2:13 hours --- Note: Use ? for help and n for new messages. ```
``` checksum data /tcp /secure /hash size /method word /key key-value Computes a checksum, CRC, or hash. Arguments: data [binary!] - Byte string to checksum Refinements: /tcp - Returns an Internet TCP 16-bit checksum /secure - Returns a cryptographically secure checksum /hash - Returns a hash value size [integer!] - Size of the hash table /method - Method to use word [word!] - Method: SHA1 MD5 /key - Returns keyed HMAC value key-value [any-string!] - Key to use ``` See also: [[string?|Functions: string?]] [[any-string?|Functions: any-string?]] ''Description'' Generally, a checksum is a number which accompanies data to verify that the data has not changed (did not have errors). <<< Editor note: R3 does not yet allow string! for checksums. print checksum "now is the dawning" <<< ``` print checksum "how is the dawning" ``` The `/secure` refinement creates a binary string result that is cryptographically secure: ``` print checksum/secure "fred-key" print checksum/secure form now ``` The `/tcp` refinement is used to compute the standard TCP networking checksum. This is a weak but fast checksum method. ``` print checksum/tcp "now is the dawning" print checksum/tcp "how is the dawning" ```
``` clean-path file /only /dir Returns new directory path with //, . and .. processed. Arguments: file [file! url! string!] Refinements: /only - Do not prepend current directory /dir - Add a trailing / if missing ``` See also: [[split-path|Functions: split-path]] [[change-dir|Functions: change-dir]] [[dir?|Functions: dir?]] [[list-dir|Functions: list-dir]] ''Description'' Rebuilds a directory path after decoding parent `(..)` and current `(.)` path indicators. ``` probe clean-path %com/www/../../../graphics/image.jpg %/C/REBOL/3.0/docs/graphics/image.jpg messy-path: %/rebol/scripts/neat-stuff/../../experiments/./tests neat-path: clean-path messy-path probe neat-path %/rebol/experiments/tests ``` URLs are returned unmodified (because the true paths may not be known).
``` clear series Removes all values. For series, removes from current index to tail and returns tail. (Modifies) Arguments: series [series! port! map! gob! bitset! none!] ``` See also: [[remove|Functions: remove]] [[append|Functions: append]] [[change|Functions: change]] [[insert|Functions: insert]] [[sort|Functions: sort]] ''Description'' `clear` is similar to remove but removes through the end of the series rather than just a single value. It returns at the current index position in the series. ``` str: copy "with all things considered" clear skip str 8 print str with all str: copy "get there quickly" clear find str "qui" print str get there head clear find %file.txt %.txt %file ```
``` close port Closes a port. Arguments: port [port!] ``` See also: [[open|Functions: open]] [[load|Functions: load]] [[do|Functions: do]] ''Description'' Closes a port opened earlier with the [[open|Functions: open]] function. Any changes to the port data that have been buffered will be written. ``` port: open %test-file.txt insert port "Date: " insert port form now insert port newline close port print read %test-file.txt read ```
``` closure spec body Defines a closure function. Arguments: spec [block!] - Help string (opt) followed by arg words (and opt type and string) body [block!] - The body block of the function ``` See also: [[closure?|Functions: closure?]] [[does|Functions: does]] [[func|Functions: func]] [[function|Functions: function]] [[has|Functions: has]] ''Description'' A `closure` is a special type of function that has persistent variables. With a closure you can write a block inside the closure body and the block will remain persistent: ``` add2: closure [c d] [[c + d]] do add2 1 2 3 ``` This works because the variables of a closure remain valid, even outside the closure after it has been called. Such variables have indefinite extent. They are not limited to the lifetime of the function. Note, however, that this luxury provided by closures is not without its costs. Closures require more time to evaluate as well as more memory space. In essence a closure is an object. When you define the closure, it constructs a prototype object, and each time you call the closure, the prototype object is instantiated and the body code is evaluated within that context. More about closures [[here|http://www.rebol.net/wiki/Closures]]. More about the benefits and costs of closures [[here|http://www.rebol.net/wiki/R2_vs._R3_Contexts]].
``` closure? value ``` Returns TRUE if it is this type. ``` Arguments: value [any-type!] ``` See also: [[function?|Functions: function?]] ''Description'' Returns true if the input is a closure! ``` closure? make closure! [[][]] true ``` <<< Editor note: Are there better examples? <<<
``` collect body /into output Evaluates a block, storing values via KEEP function, and returns block of collected values. Arguments: body [block!] - Block to evaluate Refinements: /into - Insert into a buffer instead (returns position after insert) output [series!] - The buffer series (modified) ``` ''Description'' Using the internal keep function, will collect values spread around a block to be stored in another block and returned: ``` collect [keep 1 2 3 keep 4] [1 4] ``` Can also be used with the [[parse|Functions: parse]] function: ``` collect [ parse [a b c d e] [ any ['c | 'e | set w word! (keep w)] ] ] [a b d] ``` Blocks are collected and appended to the output as a series of values: ``` collect [keep 1 keep [2 3]] [1 2 3] ``` The keep function has a refinement `/only` to append blocks as blocks to the output: ``` collect [keep 1 keep/only [2 3]] [1 [2 3]] ```
``` comment value Ignores the argument value and returns nothing. Arguments: value - A string, block, or any other value ``` See also: [[do|Functions: do]] ''Description'' This function can be used to add comments to a script or to remove a block from evaluation. Note that this function is only effective in evaluated code and has no effect in data blocks. That is, within a data block comments will appear as data. In many cases, using comment is not necessary. Placing braces around any expression will prevent if from being evaluated (so long as it is not part of another expression). ``` comment "This is a comment." comment [print "As a comment, this is not printed"] ``` <<< Note also that if the expression can't be loaded using load, the expression can't be commented out: ``` comment [a,b] ** Syntax error: invalid "word" -- "a,b" ** Near: (line 1) comment [a,b] ``` <<<
``` complement value Returns the one's complement value. Arguments: value [logic! integer! tuple! binary! bitset! typeset! image!] ``` See also: [[negate|Functions: negate]] [[not|Functions: not]] [[and|Functions: and]] [[or|Functions: or]] [[xor|Functions: xor]] [[charset|Functions: charset]] ''Description'' The complement function is used for bit-masking [[integer!|Datatypes: Integer!]] and [[tuple!|Datatypes: Tuple!]] values or inverting [[bitset!|Datatypes: Bitset!]] values (charsets). ``` complement 0 -1 complement -1 0 complement 0.255.0 255.0.255 chars: complement charset "ther " find "there it goes" chars it goes ```
``` compose value /deep /only /into out Evaluates a block of expressions, only evaluating parens, and returns a block. Arguments: value - Block to compose Refinements: /deep - Compose nested blocks /only - Insert a block as a single value (not the contents of the block) /into - Output results into a block with no intermediate storage out [any-block!] ``` See also: [[reduce|Functions: reduce]] [[append|Functions: append]] [[repend|Functions: repend]] [[rejoin|Functions: rejoin]] [[insert|Functions: insert]] ''Description'' The `compose` function builds a block of values, evaluating [[paren!|Datatypes: Paren!]] expressions and inserting their results. It is a very useful method of building new blocks. ``` compose [result of 1 + 2 = (1 + 2)] [result of 1 + 2 = 3] ``` Notice that only the paren! expression is evaluated. All other values are left unchanged. Here's another example, as might be used to create a header block (that has field names): ``` compose [time: (now/time) date: (now/date)] [time: 17:47:13 date: 12-Feb-2009] ``` ''Sub-Blocks'' If the result of an expression is a block, then the elements of that block are inserted into the output block: ``` colors: ["red" "green" "blue"] compose [1 2 3 (colors)] [1 2 3 "red" "green" "blue"] ``` If you want to insert the actual block, rather than its elements, there are a couple ways to do so. You can use the `/only` refinement: ``` colors: ["red" "green" "blue"] compose/only [1 2 3 (colors)] [1 2 3 ["red" "green" "blue"]] ``` Or, you can add a reduce to put the block within another block: ``` colors: ["red" "green" "blue"] compose [1 2 3 (reduce [colors])] [1 2 3 ["red" "green" "blue"]] ``` ''Evaluating All Parens'' To evaluate all paren expressions, regardless of how deep the are nested within blocks, use the `/deep` refinement: ``` compose/deep [1 [2 [(1 + 2) 4]]] [1 [2 [3 4]]] ``` You can use `/deep` and `/only` together: ``` colors: ["red" "green" "blue"] compose [1 2 3 [4 (colors)]] [1 2 3 [4 "red" "green" "blue"]] ``` ''Memory usage for large blocks'' For most blocks you don't need to worry about memory because REBOL's automatic storage manager will efficiently handle it; however, when building large block series with compose, you can manage memory even more carefully. For example, you might write: ``` append series compose [a (b) (c)] ``` The word a and the evaluated results of b and c are appended to the series. If this is done a lot, a large number of temporary series are generated, which take memory and also must be garbage collected later. The `/into` refinement helps optimize the situation: ``` compose/into [a (b) (c)] tail series ``` It requires no intermediate storage.
``` compress data Compresses a string series and returns it. Arguments: data [binary! string!] - If string, it will be UTF8 encoded ``` See also: [[decompress|Functions: decompress]] ''Description'' Editor note: Describe the method that compress uses to compress data ``` print compress "now is the dawning" #{789CCBCB2F57C82C5628C9485548492CCFCBCC4B07003EB606BA12000000} string: form first system/words print length? string 8329 small: compress string print length? small 3947 ``` As with all compressed files, keep an uncompressed copy of the original data file as a backup.
``` confirm question /with choices Confirms a user choice. Arguments: question [series!] - Prompt to user Refinements: /with choices [string! block!] ``` See also: [[ask|Functions: ask]] [[input|Functions: input]] [[prin|Functions: prin]] ''Description'' This function provides a method of prompting the user for a `true` ("y" or "yes") or `false` ("n" or "no") response. Alternate responses can be identified with the `/with` refinement. ``` confirm "Answer: 14. Y or N? " confirm/with "Use A or B? " ["A" "B"] ```
``` construct block /with object /only Creates an object with scant (safe) evaluation. Arguments: block [block! string! binary!] - Specification Refinements: /with - Default object object [object!] /only - Values are kept as-is ``` See also: [[make|Functions: make]] [[context|Functions: context]] ''Description'' This function creates new objects but without evaluating the object's specification (as is done in the make and context functions). When you construct an object, only literal types are accepted. Functional evaluation is not performed. This allows your code to directly import objects (such as those sent from unsafe external sources such as email, cgi, etc.) without concern that they may include "hidden" side effects using executable code. construct is used in the same way as the context function: ``` obj: construct [ name: "Fred" age: 27 city: "Ukiah" ] probe obj make object! [ name: "Fred" age: 27 city: "Ukiah" ] ``` But, very limited evaluation takes place. That means object specifications like: ``` obj: construct [ name: uppercase "Fred" age: 20 + 7 time: now ] probe obj make object! [ name: 'uppercase age: 20 time: 'now ] ``` do not produce evaluated results. Except with the `/only` refinement, the `construct` function does perform evaluation on the words `true`, on, yes, `false`, off, no and none to produce their expected values. Literal words and paths will also be evaluated to produce their respective words and paths. For example: ``` obj: construct [ a: yes b: none c: 'word ] probe obj make object! [ a: true b: none c: word ] type? obj/a logic! type? obj/c word! ``` The `construct` function is useful for importing external objects, such as preference settings from a file, CGI query responses, encoded email, etc. To provide a template object that contains default variable values (similar to make), use the `/with` refinement. The example below would use an existing object called standard-prefs as the template. ``` prefs: construct/with load %prefs.r standard-prefs ```
``` context blk Defines a unique object. Arguments: blk [block!] - Object words and values. ``` See also: [[make|Functions: make]] ''Description'' This function creates a unique new object. It is just a shortcut for make [[object!|Datatypes: Object!]]. ``` person: context [ name: "Fred" age: 24 birthday: 20-Jan-1986 language: "REBOL" ] probe person make object! [ name: "Fred" age: 24 birthday: 20-Jan-1986 language: "REBOL" ] person2: make person [ name "Bob" ] probe person2 make object! [ name: "Bob" age: 24 birthday: 20-Jan-1986 language: "REBOL" ] ```
``` continue Throws control back to top of loop. ``` See also: [[break|Functions: break]] [[catch|Functions: catch]] [[exit|Functions: exit]] [[return|Functions: return]] [[loop|Functions: loop]] [[repeat|Functions: repeat]] [[for|Functions: for]] [[forall|Functions: forall]] [[foreach|Functions: foreach]] [[forever|Functions: forever]] [[forskip|Functions: forskip]] [[while|Functions: while]] [[until|Functions: until]] ''Description'' The `continue` function is the opposite of [[break|Functions: break]]. It jumps back to the top of the loop instead of exiting the loop. For example: ``` repeat n 5 [ if n < 3 [continue] print n ] 3 4 5 ```
``` copy value /part length /deep /types kinds Copies a series or object. Arguments: value [series! port! map! object! bitset! any-function!] Refinements: /part - Limits to a given length or position length [number! series! pair!] /deep - Also copies series values within the block /types - What datatypes to copy kinds [typeset! datatype!] ``` See also: [[make|Functions: make]] [[form|Functions: form]] [[mold|Functions: mold]] [[join|Functions: join]] [[ajoin|Functions: ajoin]] [[rejoin|Functions: rejoin]] ''Description'' ``` The copy function will copy any series, such as string! or block!, and most other compound datatypes such as object! or function!. It is not used for immediate datatypes, such as integer!, decimal!, time!, date!, and others. ``` ''How it Works'' It is important to understand copy to program in REBOL properly. To save memory, all strings, blocks, and other series are accessed by reference (e.g. as pointers.) If you need to modify a series, and you do not want it to change in other locations, you must use copy first. Note that some functions, such as [[join|Functions: join]] and [[rejoin|Functions: rejoin]], will copy automatically. That's because they are constructing new values. This example shows what happens if you don't copy: ``` name: "Tesla" print name Tesla name2: name insert name2 "Nicola " print name2 Nicola Tesla print name Nicola Tesla ``` That's because, it's the same string: ``` same? name name2 true ``` Here's the example using copy for the second string: ``` name: "Tesla" print name Tesla name2: copy name insert name2 "Nicola " print name2 Nicola Tesla print name Tesla same? name name2 false ``` The same behavior is also `true` for blocks. This example shows various results: ``` block1: [1 2 3] block2: block1 block3: copy block1 append block1 4 append block2 5 append block4 6 probe block1 [1 2 3 4 5] probe block2 [1 2 3 4 5] probe block3 [1 2 3 6] ``` There will be times in your code where you'll want to append to or insert in a string or other series. You will need to think about what result you desire. Compare this example: `str1: "Nicola" str2: append str1 " Tesla" print str1 Nicola Tesla print str2 Nicola Tesla` with this example that uses the copy function: ``` str1: "Nicola" str2: append copy str1 " Tesla" print str1 Nicola print str2 Nicola Tesla ``` ''Copy Part'' It is fairly common to copy just a sub-string or sub-block. To do so, use the `/part` refinement. The length of the result is determined by an integer size or by the ending position location. ``` name: "Nicola Tesla" copy/part name 6 "Nicola" copy/part skip name 7 5 "Tesla" copy/part find name "Tesla" tail name "Tesla" ``` Notice that the ending position can be a length or a position within the string (as shown by the tail example above.) ''About Substrings'' If you use other languages, you will notice that this result is similar to what a substr function provides. Although we recommend using copy with /part, you can easily define your own substr function this way: ``` substr: func [arg [series!] start length] [ copy/part skip arg start length ] ``` For example: `substr "string example" 7 7 "example"` We should explain why we don't normally define a substr function. Most of the time when you're extracting substrings, you are either using a function like find or you're using a loop of some kind. Therefore, you don't really care about the starting offset of a string, you only care about the current location. For example: ``` str: "This is an example string." str2: copy/part find str "ex" 7 ``` And, in fact, it's common to write use two find functions in this way: ``` start: find str "ex" end: find start "le" str2: copy/part start end ``` which advanced users often write in one line this way: ``` str2: copy/part s: find str "ex" find s "le" ``` Of course, if the string might not be found, this is a helpful pattern to use: ``` str2: all [ start: find str "ex" end: find start "le" copy/part start end ] ``` If the start or end are not found, then str2 is set to none. Here's an example of a simple loop that finds substrings: ``` str: "this example is an example" pat: "example" while [str: find str pat] [ print copy/part str length? pat str: skip str length? pat ] ``` ''Copy Deep'' When copying blocks, keep in mind that simple use of the copy function does not make copies of series values within a block. Notice that the copy here does not copy the name string: ``` person1: ["Tesla" 10-July-1856 Serbian] person2: copy person1 insert person/2 "Nicola " probe person1 ["Nicola Tesla" 10-July-1856 Serbian] ``` If you need to copy both the block and all series values within it, use copy with the /deep refinement: ``` person1: ["Tesla" 10-July-1856 Serbian] person2: copy/deep person1 insert person/2 "Nicola " probe person1 ["Tesla" 10-July-1856 Serbian] probe person2 ["Nicola Tesla" 10-July-1856 Serbian] ``` Here both the block and the string are separate series. Also be aware that if your block contains other blocks, they will be deep copied as well, including all strings and other series within them. If you want to deep copy only a specific datatype, such as just strings or just blocks, you can use the `/types` refinement. Here are a few examples of its usage: ``` copy/deep/types block string! copy/deep/types block any-string! copy/deep/types block make typeset! [string! url! file!] ``` ''Copy Objects'' If you use copy on an object, a copy of the object is returned. This can be useful when objects are used only as simple storage structures. Note that rebinding is not done; therefore, do not use copy on objects when that is required. ''Helpful Hint'' To see a list of functions that modify their series (not copy), type this line: ``` ? modifies Found these related words: alter function! If a value is not found in a series, append i... append action! Inserts a value at tail of series and returns... bind native! Binds words to the specified context. (Modifi... change action! Changes a value in a series and returns the s... clear action! Removes all values. For series, removes from ... decloak native! Decodes a binary string scrambled previously ... deline native! Converts string terminators to standard forma... detab native! Converts tabs in a string to spaces (default ... encloak native! Scrambles a binary string based on a key. (Mo... enline native! Converts standard string terminators to curre... entab native! Converts spaces in a string to tabs (default ... insert action! Inserts into a series and returns the series ... lowercase native! Converts string of characters to lowercase. (... ... ```
``` cosine value /radians Returns the trigonometric cosine. Arguments: value [number!] - In degrees by default Refinements: /radians - Value is specified in radians ``` See also: [[arccosine|Functions: arccosine]] [[arcsine|Functions: arcsine]] [[arctangent|Functions: arctangent]] [[sine|Functions: sine]] [[tangent|Functions: tangent]] ''Description'' Ratio between the length of the adjacent side to the length of the hypotenuse of a right triangle. ``` print cosine 90 0.0 print (cosine 45) = (sine 45) true print cosine/radians pi -1.0 ```
``` create port Send port a create request. Arguments: port [port! file! url! block!] ``` ''Description'' Creates the file or URL object that is specified. ``` create %testfile.txt read %./ [%testfile.txt] ```
''Description'' This only works in a View window. ``` cursor 1 cursor 2 cursor 3 cursor 4 cursor 5 cursor 6 ``` Editor note: Describe all cursors here
``` datatype? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns `false` for all other values. ``` print datatype? integer! true print datatype? 1234 false ```
``` date? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns `false` for all other values. ``` print date? 1/3/69 true print date? 12:39 false ```
``` debase value /base base-value Decodes binary-coded string (BASE-64 default) to binary value. Arguments: value [binary! string!] - The string to decode Refinements: /base - Binary base to use base-value [integer!] - The base to convert from: 64, 16, or 2 ``` See also: [[enbase|Functions: enbase]] [[dehex|Functions: dehex]] ''Description'' Converts from an encoded string to the binary value. Primarily used for BASE-64 decoding. The `/base` refinement allows selection of number base as 64, 16, 2. Default is base64. ``` probe debase "MTIzNA==" #{31323334} ``` ``` probe debase/base "12AB C456" 16 #{12ABC456} ``` ``` enbased: probe enbase "a string of text" "YSBzdHJpbmcgb2YgdGV4dA==" ``` ``` probe string? enbased ; enbased value is a string true ``` ``` debased: probe debase enbased ; converts to binary value probe to-string debased ; converts back to original string ``` If the input value cannot be decoded (such as when missing the proper number of characters), a none is returned. ``` probe debase "100" probe debase "1001" #{D74D35} ```
``` decimal? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[number?|Functions: number?]] [[type?|Functions: type?]] ''Description'' Returns `false` for all other values. ``` print decimal? 1.2 true print decimal? 1 false ```
``` decloak data key /with Decodes a binary string scrambled previously by encloak. (Modifies) Arguments: data [binary!] - Binary to descramble key [string! binary! integer!] - Encryption key or pass phrase Refinements: /with - Use a string! key as-is (do not generate hash) ``` See also: [[encloak|Functions: encloak]] ''Description'' `decloak` is a low strength decryption method that is used with encloak. See the [[encloak|Functions: encloak]] function for a complete description and examples.
``` decode type data Decodes a series of bytes into the related datatype (e.g. image!). Arguments: type [word!] - Media type (jpeg, png, etc.) data [binary!] - The data to decode ``` See also: [[encode|Functions: encode]] [[load|Functions: load]] [[enbase|Functions: enbase]] [[debase|Functions: debase]] ''Description'' Used to call codecs to decode binary data (bytes) into related datatypes. Codecs are identified by words that symbolize their types. For example the word png is used to identify the PNG codec. See the `system/codecs` for a list of loaded codecs. Codecs can be native (built-in), externally loaded, or even coded in REBOL. [[More about Encode and Decode|http://www.rebol.net/cgi-bin/r3blog.r?view=0184]] Examples The line: ``` image: load %photo.jpg ``` is roughly equivalent to: ``` data: read %photo.jpg ; returns binary data image: decode 'jpeg data ```
``` decode-url url none Arguments: url ``` ''Description'' This is a `handy` function that saves you the effort of writing your own URL parser. ``` probe decode-url http://user:pass@www.rebol.com/file.txt [scheme: 'http pass: "pass" user: "user" host: "www.rebol.com" path: "/file.txt"] ```
``` decompress data /limit size Decompresses data. Result is binary. Arguments: data [binary!] - Data to decompress Refinements: /limit size - Limit the result to this maximum size ``` See also: [[compress|Functions: compress]] [[enbase|Functions: enbase]] [[debase|Functions: debase]] ''Description'' Examples: ``` write %file.txt read http://www.rebol.net size? %file.txt 5539 save %file.comp compress read %file.txt size? %file.comp 2119 write %file.decomp decompress load %file.comp size? %file.decomp 5539 ``` If the data passed to the decompress function has been altered or corrupted, a decompression error will occur. A typical error is out of memory, if the decompressed file length appears to be wrong (perhaps several gigabytes instead of 5539 bytes) to decompress. Using the `/limit` refinement, puts a hard limit to the size of the decompressed file: ``` decompress/limit read %file.comp 5000 ** Script error: maximum limit reached: 5539 ** Where: decompress ** Near: decompress/limit read %file.comp 5000 ``` This can [[help|Functions: help]] avoiding that a decompress operation on a corrupt file suddenly eats all system resources. <<< Special Notes decompress can decompress any ZLIB data as long as the data has the length of the uncompressed data in binary little-endian representation appended: ``` zlib-decompress: func [ zlib-data [binary!] length [integer!] "known uncompressed zlib data length" ][ decompress head insert tail zlib-data third make struct! [value [integer!]] reduce [length] ] ``` <<<
``` default word value Set a word to a default value if it hasn't been set yet. Arguments: word [word! set-word! lit-word!] - The word (use :var for word! values) value - The value ``` See also: [[value?|Functions: value?]] [[any|Functions: any]] [[all|Functions: all]] ''Description'' The default function is a clear way to indicate that you want a variable set to a default value if it's not already been set. For example: ``` default size 100 ``` would set size to 100 if it's not already been set to some other value. You can think of default as a shortcut for any when used like this: ``` size: any [size 100] ``` However, `default` avoids the need to specify the size word twice and also makes the intention of your code more clear. It's `quite` often used for global configuration variables that may or may not have been set by prior code.
``` dehex value Converts URL-style hex encoded (%xx) strings. Arguments: value [any-string!] - The string to dehex ``` See also: [[to-hex|Functions: to-hex]] [[debase|Functions: debase]] [[enbase|Functions: enbase]] ''Description'' Converts the standard URL hex sequence that begins with a % followed by a valid hex value. Otherwise, the sequence is not converted and will appear as written. ``` print dehex "www.com/a%20dir/file" www.com/a dir/file print dehex "ABCD%45" ABCDE ```
``` delect dialect input output /in where /all Parses a common form of dialects. Returns updated input block. Arguments: dialect [object!] - Describes the words and datatypes of the dialect input [block!] - Input stream to parse output [block!] - Resulting values, ordered as defined Refinements: /in - Search for var words in specific objects (contexts) where [block!] - Block of objects to search (non objects ignored) /all - Parse entire block, not just one command at a time ``` See also: [[parse|Functions: parse]] ''Description'' DELECT stands for DEcode diaLECT. It is used to implement REBOL's internal dialects such as DRAW, EFFECT, RICH TEXT, SECURE, and VID, but its function is available to all users. This is used for parsing unordered dialects. In unordered dialects, the order of arguments is less important than their type. Here's a simple example. First the dialect is specified as a context: ``` dialect: context [ default: [tuple!] single: [string!] double: [integer! string!] ] ``` Then an input and output block is specified. The input block contains the data to parse. The output block stores the result: ``` inp: [1.2.3 single "test" double "test" 123] out: make block! 4 ; (any initial size works) Now the input is processed using delect, one step at a time: while [inp: delect dialect inp out] [ ?? out ?? inp ] ``` To read more about delect, see [[here|http://rebol.net/wiki/Delect]].
``` delete port Send port a delete request. Arguments: port [port! file! url! block!] ``` See also: [[create|Functions: create]] [[exists?|Functions: exists?]] ''Description'' Deletes the file or URL object that is specified. If the file or URL refers to an empty directory, then the directory will be deleted. ``` write %delete-test.r "This file is no longer needed." delete %delete-test.r write ```
``` deline string /lines Converts string terminators to standard format, e.g. CRLF to LF. (Modifies) Arguments: string [any-string!] Refinements: /lines - Return block of lines (works for LF, CR, CR-LF endings) (does not modify) ``` See also: [[enline|Functions: enline]] [[read|Functions: read]] ''Description'' Useful for converting OS dependent string terminators to LF. CRLF string termination: ``` deline "a^M^/b" ; Windows, DOS, CP/M, OS/2, Symbian "a^/b" ``` CR string termination: ``` deline "a^Mb" ; MacOS 1-9 "a^/b" ``` LF string termination: ``` deline "a^/b" ; MacOSX, AmigaOS, FreeBSD, GNU/Linux, BeOS, RiscOS "a^/b" ``` When using the `/LINES` refinement, the string will be split in blocks of strings per line: ``` deline/lines "a^M^/b" [ "a" "b" ] ``` Note that when reading from disk, READ/STRING provides the same functionality. The file `%/c/text.txt` was first saved with WIndows XP Notepad, which gives CRLF. When read, it gives: ``` read/string %/c/text.txt "Windows text^/file" ```
``` delta-profile block Delta-profile of running a specific block. Arguments: block [block!] ``` See also: [[delta-time|Functions: delta-time]] [[dp|Functions: dp]] [[dt|Functions: dt]] ''Description'' Provides detailed profiling information captured during the evaluation of a block. See [[Profiler|Functions: delta-profile]] for detailed examples. Simple example: ``` >> dp [loop 10 [next "a"]] == make object! [ timer: 39 evals: 31 eval-natives: 14 eval-functions: 1 series-made: 1 series-freed: 0 series-expanded: 0 series-bytes: 432 series-recycled: 0 made-blocks: 1 made-objects: 0 recycles: 0 ] ```
``` delta-time block Delta-time - return the time it takes to evaluate a block. Arguments: block [block!] ``` See also: [[delta-profile|Functions: delta-profile]] [[dt|Functions: dt]] [[dp|Functions: dp]] ''Description'' Returns the amount of time required to evaluate a given block. Example: ``` >> dt [loop 1000000 [next "a"]] 0:00:00.25 ``` See [[Profiler|Functions: delta-profile]] for detailed information about timing and profiling.
``` demo Run R3 demo. ``` ''Description'' Downloads and runs the current REBOL demo. In some releases, the `demo` may be disabled while various system-level changes are being made.
``` detab string /size number Converts tabs in a string to spaces (default tab size 4). (Modifies) Arguments: string [any-string!] Refinements: /size - Specifies the number of spaces per tab number [integer!] ``` See also: [[entab|Functions: entab]] ''Description'' The REBOL language default tab size is four spaces. detab will remove tabs from the entire string even beyond the first non-space character. The series passed to this function is modified as a result. ``` text: "^-lots^-^-of^-^-tabs^-^-^-^-here" print detab copy text lots of tabs here ``` Use the /size refinement for other sizes such as eight: ``` print detab/size text 8 lots of tabs here ```
``` difference set1 set2 /case /skip size Returns the difference of two data sets or dates. Arguments: set1 [block! string! binary! bitset! date! typeset!] - First data set set2 [block! string! binary! bitset! date! typeset!] - Second data set Refinements: /case - Uses case-sensitive comparison /skip - Treat the series as records of fixed size size [integer!] ``` See also: [[intersect|Functions: intersect]] [[union|Functions: union]] [[exclude|Functions: exclude]] [[unique|Functions: unique]] ''Description'' Returns the elements of two series that are not present in both. Both series arguments must be of the same datatype (string, block, etc.) Newer versions of REBOL also let you use difference to compute the difference between date/times. ``` lunch: [ham cheese bread carrot] dinner: [ham salad carrot rice] probe difference lunch dinner [cheese bread salad rice] probe difference [1 3 2 4] [3 5 4 6] [1 2 5 6] string1: "CBAD" ; A B C D scrambled string2: "EDCF" ; C D E F scrambled probe difference string1 string2 "BAEF" ``` Date differences produce a time in hours: ``` probe difference 1-Jan-2002/0:00 1-Feb-2002/0:00 -744:00 probe difference 1-Jan-2003/10:30 now -59449:55:14 ``` This is different from when using subtract, which returns the difference in days: ``` probe subtract 1-Jan-2002/0:00 1-Feb-2002/0:00 -31 probe subtract 1-Jan-2003/10:30 now -2477 ``` There is a limit to the time period that can be differenced between dates (determined by the internal size of the [[time!|Datatypes: Time!]] datatype). Note that performing this function over very large data sets can be CPU intensive.
``` dir? target Returns TRUE if the file or url ends with a slash (or backslash). Arguments: target [file! url!] ``` See also: [[make-dir|Functions: make-dir]] [[modified?|Functions: modified?]] [[ exists?|Functions: exists?]] ''Description'' ''Under Review'' This function is under review for redefinition. Returns false if it is not a directory. ``` print dir? %file.txt false print dir? %. true ``` Note that the file that is input, is read from disk, if it exists. The function returns true, when the input either ends in `/` or if the name exists on disk as a directory.
``` dirize path Returns a copy of the path turned into a directory. Arguments: path [file! string! url!] ``` ''Description'' Convert a file name to a directory name. For example: ``` probe dirize %dir %dir/ ``` It is useful in cases where paths are used: ``` dir: %files/examples new-dir: dirize dir/new-code probe new-dir %files/examples/new-code/ ``` This is useful because the PATH notation does not allow you to write: ``` new-dir: dirize dir/new-code/ ```
``` disarm value Deprecated function for converting error objects. Not used in R3. Arguments: value [any-type!] ``` See also: [[error?|Functions: error?]] [[try|Functions: try]] [[attempt|Functions: attempt]] ''Description'' <<< Not used in R3 The disarm function is not used in R3. That's because the error! datatype is not "hot" like it is in R2. In R3, it acts like other datatypes, and can be set to variables, passed to functions, and returned as results without triggering a throw exception. <<< <<< Description for R2 DISARM allows access to the values of an error object. If the error is not disarmed, it will occur again immediately. <<< ``` probe disarm try [1 + "x"] make object! [ code: 308 type: 'Script id: 'cannot-use arg1: 'add arg2: string! arg3: none near: [+ "x"] where: [+ try do attempt if emit parse foreach catch if either if do begin do] ] ``` The error object returned from DISARM can be used to determine the type of error and its arguments. For example in the case of a divide by zero error: ``` probe disarm try [1 / 0] make object! [ code: 400 type: 'Math id: 'zero-divide arg1: none arg2: none arg3: none near: [/ 0] where: [/ try do attempt if emit parse foreach catch if either if do begin do] ] ``` You might write a TRY block that handles the error after it has happened: ``` if error? err: try [ value: 1 / 0 ][ err: disarm err either err/id = 'zero-divide [value: 0] [probe err quit] ] print value 0 ```
``` divide value1 value2 ``` Returns the first value divided by the second. ``` Arguments: value1 [scalar!] value2 [scalar!] ``` See also: [[/|Functions: /]] [[//|Functions: //]] [[multiply|Functions: multiply]] Description If the second value is zero, an error will occur. Examples: ``` print divide 123.1 12 10.25833333333333 ``` ``` print divide 10:00 4 2:30 ``` When dividing values of different datatypes, they must be compatible: ``` divide 4x5 $2.7 ** Script error: incompatible argument for divide of pair! ** Where: divide ** Near: divide 4x5 $2.7 ```
``` do value /args arg /next var Evaluates a block, file, URL, function, word, or any other value. Arguments: value [any-type!] - Normally a file name, URL, or block Refinements: /args - If value is a script, this will set its system/script/args arg - Args passed to a script (normally a string) /next - Do next expression only, return it, update block variable var [word!] - Variable updated with new block position ``` See also: [[reduce|Functions: reduce]] [[load|Functions: load]] [[import|Functions: import]] [[loop|Functions: loop]] [[repeat|Functions: repeat]] [[call|Functions: call]] [[launch|Functions: launch]] ''Description'' The `do` function evaluates a script file or a series of expressions and returns a result. It performs the fundamental interpretive action of the REBOL language and is used internally within many other functions such as if, case, while, loop, repeat, foreach, and others. ''Most Common Use'' Most of the time `do` is used to evaluate a script from a [[file!|Datatypes: File!]] or [[url!|Datatypes: Url!]] as shown in these examples: ``` do %setup.r Settings done. do http://www.rebol.com/speed.r Console: 0:00:01.609 - 314 KC/S Processor: 0:00:00.406 - 2128 RHz (REBOL-Hertz) Memory: 0:00:00.657 - 72 MB/S Disk/File: 0:00:00.234 - 130 MB/S ``` Note that do of a [[file!|Datatypes: File!]] or [[url!|Datatypes: Url!]] requires that the script contain a valid REBOL header; otherwise, you'll get an "Script is missing a REBOL header" error. <<< Warning Only `do` a [[url!|Datatypes: Url!]] script that you have reason to trust. It is advised that you read a script first and examine it closely to make sure it is safe to evaluate. <<< ''Other Uses'' The `do` function can also be called to evaluate other types of arguments such as a [[block!|Datatypes: Block!]], [[path!|Datatypes: Path!]], [[string!|Datatypes: String!]], or [[function!|Datatypes: Function!]]. ``` do [1 + 2] 3 do "1 + 2" ; see special note below 3 ``` Expressions are evaluated left to right and the final result is returned. For example: ``` do [1 + 2 3 * 4] 12 ``` To obtain all results, use the reduce function instead. ``` print reduce [1 + 2 3 * 4] 3 12 ``` ''Other Examples'' Selecting a block to evaluate: ``` blk: [ [print "test"] [loop 3 [print "loop"]] ] do first blk test do second blk loop loop loop ``` ''Refinements'' The `/args` refinement allows you to pass arguments to another script and is used with a file, or URL. Arguments passed with `/args` are stored in `system/script/args` within the context of the loaded script. The `/next` refinement returns a block consisting of two elements. The first element is the evaluated return of the first expression encountered. The second element is the original block with the current index placed after the last evaluated expression. ''Special Notes'' Evaluating strings is much slower than evaluating blocks and values. That's because REBOL is a symbolic language, not a string language. It is considered bad practice to convert values to strings and join them together to pass to do for evaluation. This can be done directly without strings. For example, writing code like this is a poor practice: ``` str: "1234 + " code: join str "10" do code 1244 ``` Instead, just use: ``` blk: [1234 +] code: join blk 10 do code 1244 ``` In other words, you can join values in blocks just as easily as strings.
``` do-codec handle action data Evaluate a CODEC function to encode or decode media types. Arguments: handle [handle!] - Internal link to codec action [word!] - Decode, encode, identify data [binary! image!] ``` See also: [[decode|Functions: decode]] [[encode|Functions: encode]] ''Description'' This is an internal native function used to call codecs. It is normally called by the [[encode|Functions: encode]] and [[decode|Functions: decode]] functions. See the `system/catalog/codecs` for a list of loaded codecs. Codecs can be native (built-in), externally loaded, or coded in REBOL.
``` do-commands commands Evaluate a block of extension module command functions (special evaluation rules.) Arguments: commands [block!] - Series of commands and their arguments ``` See also: [[do|Functions: do]] [[reduce|Functions: reduce]] ''Description'' High speed [[command!|Datatypes: Command!]] block evaluation for extensions. Originally created to evaluate graphics rendering commands, it can be used for any external sequence of commands that require maximum speed (e.g. high speed math processing such as FFTs, image processing, audio processing.) ''Special Evaluation Method'' The greater speed of command blocks is obtained through the use of a special evaluation method: Evaluation is strictly linear. Sub-expressions, control branching, and recursion are not allowed so no stack management is required. Arguments are already reduced to their final values (or variables that hold those values.) Special variations of function arguments are not allowed. Only word and 'word forms are allowed. Arguments must appear in the correct order and no optional arguments are allowed. Arguments are placed directly within the command argument frame, not on the primary evaluator stack. ''Why is it Useful?'' In subsystems like the R3 GUI, graphical elements are rendered by generating semi-static draw blocks either during style definition (definition of a button), face instantiation (creating an instance of a button), or face state modification (eg. hovering over a button). The advantage of the static form of such draw blocks is that they require no further evaluation, hence take no additional memory or CPU time. In fact, the state of the GUI at any specific time is simply a sequence of draw block renderings. Therefore, a fast method of calling draw functions can greatly speed-up the rendering time of the GUI. For special draw dialects (like the one used in the GUI) where optional or datatype-ordered arguments are allowed, a conversion from the dialect block to the command block is required. However, this conversion was already being performed in order to reduce the run-time overhead of the dialects (to avoid the `NxM` argument reordering penalty), so no additional overhead is incurred. ''General Form'' The general form is: ``` do-commands [ command1 arg11 arg12 command2 arg21 arg22 arg23 result: command3 arg31 ... ] ``` Notice that set-words for results are allowed. In addition, the result of the final command will be returned from the [[do-commands|Functions: do-commands]] function. ''Argument Requirements'' Command blocks are written in a reduced minimal form. They consist of one or more commands followed by their arguments. The arguments must be actual values or variables; sub-expressions and operators are not allowed. If necessary, use reduce with `/only` or compose to preprocess command blocks. For example, you can write: ``` line 0x0 100x100 line 100x100 200x200 ``` and the command can also be variables: ``` line start1 end1 line start2 end2 ``` Sub expressions are not allowed: ``` line 0x0 base + 10 ; error line 0x0 add base 10 ; error ``` However, if necessary you can escape to parens for sub-expressions, but it reduces run-time performance: ``` line 0x0 (base + 10) ; ok, but slow ``` ''Errors'' An error will occur if any value other than a command is found: ``` multiply 10 20 ** Script error: expected command! not multiply ``` An error will also occur if an argument is not of the correct datatype, or if the block ends before all of its actual arguments are provided.
''Description'' Process user events in GUI windows. When this function is called the program becomes event driven. This function does not return until all windows have been closed.
``` docs Browse on-line documentation. ``` ''Description'' The `docs` function opens the default web browser to the main R3 documentation page.
``` does body A shortcut to define a function that has no arguments or locals. Arguments: body [block!] - The body block of the function ``` See also: [[closure|Functions: closure]] [[exit|Functions: exit]] [[func|Functions: func]] [[function|Functions: function]] [[has|Functions: has]] [[return|Functions: return]] [[use|Functions: use]] ''Description'' `does` provides a shortcut for defining functions that have no arguments or local variables. ``` rand10: does [random 10] print rand10 5 this-month: does [now/month] print this-month 2 ``` This function is provided as a coding convenience and it is otherwise identical to using [[func|Functions: func]] or [[function|Functions: function]].
``` dp block Delta-profile of running a specific block. Arguments: block [block!] ``` See also: [[delta-profile|Functions: delta-profile]] [[delta-time|Functions: delta-time]] [[dt|Functions: dt]] ''Description'' A shortcut for [[delta-profile|Functions: delta-profile]].
The `draw` function renders a scalable vector graphics drawing into an image buffer. It allows `draw` commands to be created without needing a [[gob!|Datatypes: Gob!]] and the [[to-image|Functions: to-image]] function. With it, users can easily prebuild vector graphics, and if the image is static, it is more efficient too (because the vector graphics are regenerated each time the [[gob!|Datatypes: Gob!]] is refreshed). The function can take an existing image and draw on top of it or create a new image of a given size. This example draws into an existing image: ``` image: draw logo [box 20x20 40x40] ``` This example creates a new image of the given size and draws into it: ``` image: draw 300x300 [box 20x20 40x40 line 0x0 300x300] ``` Transparency is supported. The resulting image will use the alpha channel. To read about the all the commands in the DRAW dialect, see [[here|http://rebol.net/wiki/Draw]].
dt block Delta-time - return the time it takes to evaluate a block. Arguments: block [block!] See also: delta-time delta-profile dp Description A shortcut function for delta-time.
``` dump v Temporary debug dump Arguments: v ``` ''Description'' No description provided.
``` dump-obj obj /match pat Returns a block of information about an object or port. Arguments: obj [object! port!] Refinements: /match - Include only those that match a string or datatype pat ``` See also: [[help|Functions: help]] [[?|Functions: ?]] [[??|Functions: ??]] ''Description'' This function provides an easy way to view the contents of an object. The function is friendly to print. It is an alternative to mold and probe which may display too much information for deeply structured objects. ``` print dump-obj system/intrinsic do function! Called for DO on datatypes that require more ... make-module function! [ spec [block!] "As [spec-block body-block]" ... make-port function! Creates a new port from a scheme specificatio... parse-url object! [digit digits alpha-num scheme-char path-char... begin function! Called once boot is complete. Handles argumen... ```
``` echo target Copies console output to a file. Arguments: target [file! none! logic!] ``` See also: [[print|Functions: print]] [[trace|Functions: trace]] ''Description'' Write output to a file in addition to the user console. The previous contents of a file will be overwritten. The `echo` can be stopped with `echo` `none` or by starting another `echo`. ``` echo %helloworld.txt print "Hello World!" echo none Hello World! ```
''Description'' This applies an effect to an existing or new image using the built in effect dialect. In this example, using a size of 50x50 produces a black image of the size 50x50. When applying the invert effect, the image turns white: ``` effect 50x50 [invert] make image! [50x50 #{ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF... ``` To read more about the effect dialect commands, see [[here|http://rebol.net/wiki/Effect]].
``` eighth value Returns the eighth value of a series. Arguments: value ``` See also: [[first|Functions: first]] [[second|Functions: second]] [[third|Functions: third]] [[pick|Functions: pick]] ''Description'' This is an ordinal. See the [[first|Functions: first]] function for examples. If no value is found, none is returned.
``` either condition true-block false-block If condition is TRUE, evaluates the first block, else evaluates the second. Arguments: condition true-block [block!] false-block [block!] ``` See also: [[if|Functions: if]] [[any|Functions: any]] [[all|Functions: all]] [[unless|Functions: unless]] [[case|Functions: case]] [[switch|Functions: switch]] [[pick|Functions: pick]] ''Description'' The either function will evaluate one block or the other depending on a condition. This function provides the same capability as the if-else statements found in other languages. Because REBOL is a functional language, it is not desirable to use the word else within the expression. Here's an example: ``` either 2 > 1 [print "greater"] [print "not greater"] greater either 1 > 2 [print "greater"] [print "not greater"] not greater ``` The condition can be the result of several expressions within [[any|Functions: any]] or [[all|Functions: all]], or any other function that produces a result: ``` either all [ time > 10:20 age > 20 find users "bob" ] [print "that's true"] [print "that's false"] that's true ``` In addition, it can be pointed out that the evaluated blocks can be within a variable: ``` blk1: [print "that's true"] blk2: [print "that's false"] either 2 > 1 blk1 blk2 that's true ``` ''Return Value'' The either function returns the result of the block that it evaluates. ``` print either 2 > 1 ["greater"] ["not greater"] greater ``` ''Simplification'' The above example is pretty common, but it should be noted that it can be easily refactored: ``` either 2 > 1 [print "greater"] [print "not greater"] ``` is better written as: ``` print either 2 > 1 ["greater"] ["not greater"] ``` or even better written as: print pick ["greater" "not greater"] 2 > 1 The importance of this is that you're picking from a choice of two strings, and you're doing it here with one less block than the code above it. Be careful with this last method. The pick function only allows true and false, not none. See either for more details. ''A Common Error'' A common error is to forget to provide the second block to the either function. This usually happens when you simplify an expression, and forget to change the either to an if function. <<< This is wrong: ``` either 2 > 1 [print "greater"] ``` and it may become quite confusing as to why your program isn't working correctly. You should have written: ``` if 2 > 1 [print "greater"] ``` <<<
''Description'' See the [[either|Functions: either]] function for `if-then-else` conditions. ``` either now/time > 10:30 [ print "later" ][ print "earlier" ] later ```
``` email? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns false for all other values. ``` print email? info@rebol.com true print email? http://www.REBOL.com false ```
``` empty? series Returns TRUE if empty or NONE, or for series if index is at or beyond its tail. Arguments: series [series! gob! port! bitset! map! none!] ``` See also: [[tail?|Functions: tail?]] [[none?|Functions: none?]] [[found?|Functions: found?]] ''Description'' This is a synonym for tail? The check is made relative to the current location in the series. ``` print empty? [] true print empty? [1] false ``` The `empty?` function is useful for all types of series. For instance, you can use it to check a string returned from the user: ``` str: ask "Enter name:" if empty? str [print "Name is required"] ``` It is often used in conjunction with trim to remove black spaces from the ends of a string before checking it: ``` if empty? trim str [print "Name is required"] ```
``` enbase value /base base-value Encodes a string into a binary-coded string (BASE-64 default). Arguments: value [binary! string!] - If string, will be UTF8 encoded Refinements: /base - Binary base to use base-value [integer!] - The base to convert to: 64, 16, or 2 ``` See also: [[debase|Functions: debase]] [[dehex|Functions: dehex]] ''Description'' Converts from a string or binary into an encode string value. Primarily used for BASE-64 encoding. The `/base` refinement allows selection of base as 64, 16, 2. Default is base64. ``` print enbase "Here is a string." SGVyZSBpcyBhIHN0cmluZy4= ``` ``` print enbase/base #{12abcd45} 16 12ABCD45 ``` The debase function is used to convert the binary back again. For example: ``` bin: enbase "This is a string" print debase bin #{54686973206973206120737472696E67} ```
``` encloak data key /with Scrambles a binary string based on a key. (Modifies) Arguments: data [binary!] - Binary to scramble key [string! binary! integer!] - Encryption key or pass phrase Refinements: /with - Use a string! key as-is (do not generate hash) ``` See also: [[decloak|Functions: decloak]] ''Description'' `encloak` is a low strength encryption method that can be useful for hiding passwords and other such values. It is not a replacement for AES or Blowfish, but works for noncritical data. <<< Do not use it for top secret information! <<< To cloak a binary string, provide the binary string and a cloaking key to the encloak function: ``` bin: encloak #{54686973206973206120737472696E67} "a-key" ``` To cloak a string of characters, convert it using to-binary : ``` bin: encloak to-binary "This is a string" "a-key" ``` The result is an encrypted binary value which can be decloaked with the line: ``` print decloak bin "a-key" ``` The stronger your key, the better the encryption. For important data use a much longer key that is harder to guess. Also, do not forget your key, or it may be difficult or impossible to recover your data. Now you have a simple way to save out a hidden string, such as a password: ``` key: ask "Cloak key? (do not forget it) " data: to-binary "string to hide" save %data encloak data key ``` To read the data and decloak it: ``` key: ask "Cloak key? " data: load %data data: to-string decloak data key ``` Of course you can cloak any kind of data using these functions, even non-character data such as programs, images, sounds, etc. In those cases you do not need the to-binary conversion shown above. Note that by default, the cloak functions will hash your key strings into 160 bit SHA1 secure cryptographic hashes. If you have created your own hash key (of any length), you use the `/with` refinement to provide it.
``` encode type data /options opts Encodes a datatype (e.g. image!) into a series of bytes. Arguments: type [word!] - Media type (jpeg, png, etc.) data [image! binary! string!] - The data to encode Refinements: /options opts [block!] - Special encoding options ``` See also: [[decode|Functions: decode]] [[load|Functions: load]] [[enbase|Functions: enbase]] [[debase|Functions: debase]] ''Description'' Used to call codecs to encode datatypes into [[binary|Datatypes: Binary!]] data (bytes). Codecs are identified by words that symbolize their types. For example the word png is used to identify the PNG codec. See the `system/codecs` for a list of loaded codecs. Codecs can be native (built-in), externally loaded, or even coded in REBOL. Examples The line: ``` save %photo.bmp image ``` Is roughly equivalent to: ``` data: encode 'bmp image write %photo.bmp data ```
``` enline series Converts standard string terminators to current OS format, e.g. LF to CRLF. (Modifies) Arguments: series [any-string! block!] ``` See also: [[deline|Functions: deline]] ''Description'' Basic example: ``` enline "a^/b" "a^/M^/b" ``` To convert from any string termination format to, use enline after the [[deline|Functions: deline]] function: ``` enline deline "a^Mb" "a^/M^/b" ``` See deline for more information about string termination formats.
``` entab string /size number Converts spaces in a string to tabs (default tab size 4). (Modifies) Arguments: string [any-string!] Refinements: /size - Specifies the number of spaces per tab number [integer!] ``` See also: [[detab|Functions: detab]] ''Description'' The REBOL language default tab-size is four spaces. Use the `/size` refinement for other sizes such as eight. `entab` will only place tabs at the beginning of the line (prior to the first non-space character). The series passed to this function is modified as a result. ``` text: { no tabs in this sentence } remove head remove back tail text probe text { no tabs in this sentence} probe entab copy text {^-no tabs in this sentence} print entab copy text no tabs in this sentence probe entab/size copy text 2 {^-^-no ^- tabs ^- in ^- this ^- sentence} print entab/size copy text 2 no tabs in this sentence ``` The opposite function is [[detab|Functions: detab]] which converts tabs back to spaces: ``` probe entab text {^-no tabs in this sentence} probe detab text { no tabs in this sentence} ```
``` equal? value1 value2 Returns TRUE if the values are equal. Arguments: value1 value2 ``` See also: [[=|Functions: =]] [[<>|Functions: <>]] [[==|Functions: ==]] [[=?|Functions: =?]] [[not-equal?|Functions: not-equal?]] [[strict-equal?|Functions: strict-equal?]] ''Description'' String-based datatypes are considered equal when they are identical or differ only by character casing ([[uppercase = lowercase|Uppercase and Lowercase]]). Use [[==|Functions: ==]] or `find/match/case` to compare strings by casing. ``` print equal? 123 123 true print equal? "abc" "abc" true print equal? [1 2 3] [1 2 4] false print equal? 12-june-1998 12-june-1999 false print equal? 1.2.3.4 1.2.3.0 false print equal? 1:23 1:23 true ```
``` error? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns false for all other values. This is useful for determining if a try function returned an error. ``` if error? try [1 + "x"][ print "Did not work." ] Did not work. ```
``` eval value ``` Evaluates a block, file, URL, function, word, or any other value. ``` Arguments: value - Normally a file name, URL, or block ``` ''Description'' ``` eval [2 + 2] 4 ``` This is a simpler, faster version of [[do|Functions: do]].
``` even? number Returns TRUE if the number is even. Arguments: number [number! char! date! money! time! pair!] ``` See also: [[odd?|Functions: odd?]] [[zero?|Functions: zero?]] ''Description'' Returns `true` only if the argument is an even integer value. If the argument is a decimal, only its integer portion is examined. ``` print even? 100 true print even? 7 false ```
``` event? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns` true` if the value is an [[event|Datatypes: Event!]] datatype.
``` evoke chant Special guru meditations. (Not for beginners.) Arguments: chant [word! block! integer!] - Single or block of words ('? to list) ``` ''Description'' This is useful for analyzing hard REBOL crashes that lead to assertion errors and other crashes that aren't related to your script errors, but directly exposes bugs in the REBOL kernel. This is helpful information for REBOL Technologies to fix these bugs. To enable this kind of analysis, have this at the beginning of your program: ``` secure [debug allow] evoke 'crash-dump ``` If REBOL crashes, you will get a stack dump. You can force a crash using: ``` evoke 'crash --REBOL Kernel Dump-- Evaluator: Cycles: 110001 Counter: 4907 Dose: 10000 Signals: #00000000 Sigmask: #FFFFFFFF DSP: 5 DSF: 1 Memory/GC: Ballast: 1709360 Disable: 1 Protect: 1 Infants: 1 STACK[5] evoke[1] native! chant: crash ``` ''Special Notes'' Common for all operations with evoke is that debugging must be allowed using: ``` secure [debug allow] ``` `evoke` also allows other debug output, mostly used internally by REBOL Technologies to help test REBOL 3. The function can also be used to monitor the garbage collector: ``` evoke 'watch-recycle or to monitor object copying: evoke 'watch-obj-copy or to set the stack size: evoke 'stack-size 2000000 or to debug delect information: evoke 'delect ```
``` exclude set1 set2 /case /skip size Returns the first data set less the second data set. Arguments: set1 [block! string! binary! bitset! typeset!] - First data set set2 [block! string! binary! bitset! typeset!] - Second data set Refinements: /case - Uses case-sensitive comparison /skip - Treat the series as records of fixed size size [integer!] ``` See also: [[difference|Functions: difference]] [[intersect|Functions: intersect]] [[union|Functions: union]] [[unique|Functions: unique]] ''Description'' Returns the elements of the first set less the elements of the second set. In other words, it removes from the first set all elements that are part of the second set. ``` lunch: [ham cheese bread carrot] dinner: [ham salad carrot rice] probe exclude lunch dinner [cheese bread] probe exclude [1 3 2 4] [3 5 4 6] [1 2] string1: "CBAD" ; A B C D scrambled string2: "EDCF" ; C D E F scrambled probe exclude string1 string2 "BA" items: [1 1 2 3 2 4 5 1 2] probe exclude items items ; get unique set [] str: "abcacbaabcca" probe exclude str str "" ``` <<< Note that performing this function over very large data sets can be CPU intensive. <<<
``` exists? target Returns the type of a file or URL if it exists, otherwise none. Arguments: target [file! url!] ``` See also: [[read|Functions: read]] [[write|Functions: write]] [[delete|Functions: delete]] [[modified?|Functions: modified?]] [[size?|Functions: size?]] ''Description'' Returns `false` if the file does not exist. ``` print exists? %file.txt false print exists? %doc.r false ```
``` exit Exits a function, returning no value. ``` See also: [[return|Functions: return]] [[catch|Functions: catch]] [[break|Functions: break]] ''Description'' `exit` is used to return from a function without returning a value. ``` test-str: make function! [str] [ if not string? str [exit] print str ] test-str 10 test-str "right" ``` Note: Use [[quit|Functions: quit]] to exit the interpreter.
``` exp power Raises E (natural number) to the power specified. Arguments: power [number!] ``` See also: [[log-10|Functions: log-10]] [[log-2|Functions: log-2]] [[log-e|Functions: log-e]] [[power|Functions: power]] ''Description'' The exp function returns the exponential value of the argument provided. ``` print exp 3 20.08553692318766 ``` On overflow, an error is returned (which can be trapped with the try function). On underflow, a `0` is returned.
``` extend obj word val Extend an object, map, or block type with word and value pair. Arguments: obj [object! map! block! paren!] word [any-word!] val ``` See also: [[context|Functions: context]] ''Description'' This function is useful to extend object!, map! or block! values using a `word/value` pair. It returns the input value. It performs no copy. Examples: ``` a: [b: 1 c: 2] extend a 'd 3 = 3 probe a [b: 1 c: 2 d: 3] a: make object! [b: 1 c: 2] extend a 'd 3 3 probe a make object! [ b: 1 c: 2 d: 3 ] a: make map! [b: 1 c: 2] extend a 'd 3 3 probe a make map! [ b: 1 c: 2 d: 3 ] ```
``` extract series width /index pos /default value /into output Extracts a value from a series at regular intervals. Arguments: series [series!] width [integer!] - Size of each entry (the skip) Refinements: /index - Extract from an offset position pos - The position(s) [number! logic! block!] /default - Use a default value instead of none value - The value to use (will be called each time if a function) /into - Insert into a buffer instead (returns position after insert) output [series!] - The buffer series (modified) ``` ''Description'' Returns a series of values from regularly spaced positions within a specified series. For example: ``` data: ["Dog" 10 "Cat" 15 "Fish" 20] probe extract data 2 ["Dog" "Cat" "Fish"] ``` Essentially, extract lets you access a series as a record or "row" of a given length (specified by the width argument). The default, as shown above, extracts the first value. If you wanted to extract the second value (the second "column" of data): ``` data: ["Dog" 10 "Cat" 15 "Fish" 20] probe extract/index data 2 2 [10 15 20] ``` In the example below, the width of each row is three: ``` people: [ 1 "Bob" "Smith" 2 "Cat" "Walker" 3 "Ted" "Jones" ] block: extract people 3 probe block [ 1 2 3 ] block: extract/index people 3 2 probe block ["Bob" "Cat" "Ted"] ``` Of course, extract works on any series, not just those that appear in a row format (such as that above). The example below creates a block containing every other word from a string: ``` str: "This is a given block here" blk: parse str none probe blk ["This" "is" "a" "given" "block" "here"] probe extract blk 2 ["This" "a" "block"] probe extract/index blk 2 2 ["is" "given" "here"] ``` Here is an example that uses extract to obtain the names of all the predefined REBOL/View VID styles: ``` probe extract system/view/vid/vid-styles 2 ```
``` fifth value Returns the fifth value of a series. Arguments: value ``` See also: [[pick|Functions: pick]] [[first|Functions: first]] [[second|Functions: second]] [[third|Functions: third]] [[fourth|Functions: fourth]] ''Description'' This is an ordinal. See the [[first|Functions: first]] function for examples. If no value is found, none is returned. ``` print fifth "REBOL" L print fifth [11 22 33 44 55 66] 55 ```
``` file? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns `false` for all other values. Note that file? does not check for the existence of a file, but whether or not a value is the FILE! datatype. ``` print file? %file.txt true print file? "REBOL" false ``` Note also this is not a direct opposite to the [[dir?|Functions: dir?]] function as dir? does not test against a datatype, where [[file?|Functions: file?]] does.
``` find series value /part length /only /case /any /with wild /skip size /last /reverse /tail /match Finds a value in a series and returns the series at the start of it. Arguments: series [series! gob! port! bitset! typeset! object! none!] value [any-type!] Refinements: /part - Limits the search to a given length or position length [number! series! pair!] /only - Treats a series value as only a single value /case - Characters are case-sensitive /any - Enables the * and ? wildcards /with - Allows custom wildcards wild [string!] - Specifies alternates for * and ? /skip - Treat the series as records of fixed size size [integer!] /last - Backwards from end of series /reverse - Backwards from the current position /tail - Returns the end of the series /match - Performs comparison and returns the tail of the match ``` See also: [[select|Functions: select]] [[pick|Functions: pick]] ''Description'' Returns [[none!|Datatypes: None!]] if the value was not found. Otherwise, returns a position in the series where the value was found. Many refinements to this function are available. ''Refinements'' Use `/tail` to return the position just past the match. Use `/case` to specify that the search should be case sensitive. Note that using find on a binary string will do a case-insensitive search. The `/match` refinement can be used to perform a character by character match of the input value to the series. The position just past the match is returned. Wildcards can be specified with `/any`. The `/only` refinement applies to block values and is ignored for strings. The `/last` refinement causes find to search from the tail of the series toward the head. And, `/reverse` searches backwards from the current position toward the head. ``` probe find "here and now" "and" "and now" probe find/tail "here and now" "and" " now" probe find [12:30 123 c@d.com] 123 [123 c@d.com] probe find [1 2 3 4] 5 none probe find/match "here and now" "here" " and now" probe find/match "now and here" "here" none probe find [1 2 3 4 3 2 1] 2 [2 3 4 3 2 1] probe find/last %file.fred.txt "." %.txt probe find/last [1 2 3 4 3 2 1] 2 [2 1] probe find/any "here is a string" "s?r" none ```
''Description'' Editor note: This function does not exist in current REBOL 3 builds (A88)
``` find-script script Find a script header within a binary string. Returns starting position. Arguments: script [binary!] ``` ''Description'' This is a high-speed lower level function to scan UTF-8 for a REBOL script signature, useful during loading of scripts and to ensure that scripts are proper UTF-8. Editor note: Not sure about the description
``` first value Returns the first value of a series. Arguments: value ``` See also: [[pick|Functions: pick]] [[second|Functions: second]] [[third|Functions: third]] [[fourth|Functions: fourth]] [[fifth|Functions: fifth]] ''Description'' This is an ordinal. It returns the first value in any type of series at the current position. If no value is found, none is returned. ``` print first "REBOL" R print first [11 22 33 44 55 66] 11 print first 1:30 1 print first 199.4.80.1 199 print first 12:34:56.78 12 ```
``` first+ word Return FIRST of series, and increment the series index. Arguments: word [word!] - Word must be a series ``` ''Description'' Example: ``` blk: [a b c] first+ blk a first+ blk b first+ blk c first+ blk none ```
``` for word start end bump body Evaluate a block over a range of values. (See also: REPEAT) Arguments: word [word!] - Variable to hold current value start [series! number!] - Starting value end [series! number!] - Ending value bump [number!] - Amount to skip each time body [block!] - Block to evaluate ``` See also: [[loop|Functions: loop]] [[repeat|Functions: repeat]] [[forall|Functions: forall]] [[foreach|Functions: foreach]] [[forever|Functions: forever]][[Functions: forever]] [[forskip|Functions: forskip]] [[map-each|Functions: map-each]] [[remove-each|Functions: remove-each]] ''Description'' The first argument is used as a local variable to keep track of the current value. It is initially set to the START value and after each evaluation of the block the BUMP value is added to it until the END value is reached (inclusive). ``` for num 0 30 10 [ print num ] 30 for num 4 -37 -15 [ print num ] -26 ```
``` forall word body Evaluates a block for every value in a series. Arguments: word [word!] - Word that refers to the series, set to each position in series body [block!] - Block to evaluate each time ``` See also: [[for|Functions: for]] [[foreach|Functions: foreach]] [[forskip|Functions: forskip]] [[forever|Functions: forever]] [[while|Functions: while]] [[until|Functions: until]] ''Description'' The `forall` function moves through a series one value at a time. The word argument is a variable that moves through the series. Prior to evaluation, the word argument must be set to the desired starting position within the series (normally the head, but any position is valid). After each evaluation of the block, the word will be advanced to the next position within the series. ``` cities: ["Eureka" "Ukiah" "Santa Rosa" "Mendocino"] forall cities [print first cities] Eureka Ukiah Santa Rosa Mendocino chars: "abcdef" forall chars [print first chars] a b c d e f ``` When `forall` finishes the word is reset to the starting position of the series. ``` chars: next "abcdef" "bcdef" forall chars [] chars "bcdef" ``` The result of `forall` is the result of the last expression of the block: ``` chars: "abcdef" forall chars [first chars] #"f" ``` Or the result of a `break/return` from the block: ``` chars: "abcdef" forall chars [break/return 5] 5 ``` The `forall` function can be thought of as a shortcut for: ``` [ original: series while [not tail? series] [ x: (your code) series: next series ] series: original :x ] ```
``` foreach word data body Evaluates a block for each value(s) in a series. Arguments: word [word! block!] - Word or block of words to set each time (local) data [series! any-object! map! none!] - The series to traverse body [block!] - Block to evaluate each time ``` See also: [[remove-each|Functions: remove-each]] [[map-each|Functions: map-each]] [[for|Functions: for]] [[forall|Functions: forall]] [[forskip|Functions: forskip]] [[repeat|Functions: repeat]] ''Description'' The `foreach` function repeats the evaluation of a block for each element of a series. It is used often in programs. Example: ``` values: [11 22 33] foreach value values [print value] 11 22 33 ``` Another example that prints each word in a block along with its value: ``` colors: [red green blue] foreach color colors [print [color get color]] red 255.0.0 green 0.255.0 blue 0.0.255 ``` If the series is a string, each character will be fetched: ``` string: "REBOL" foreach char string [print char] R E B O L ``` This example will print each filename from a directory block: ``` files: read %. foreach file files [ if find file ".t" [print file] ] file.txt file2.txt newfile.txt output.txt ``` ''Local Variables'' The variables used to hold the foreach values are local to the block. Their value are only set within the block that is being repeated. Once the loop has exited, the variables return to their previously set values. ''Multiple Elements'' When a block contains groups of values that are related, foreach function can fetch all elements at the same time. For example, here is a block that contains a time, string, and price. By providing the foreach function with a block of words for the group, each of their values can be fetched and printed. ``` movies: [ 8:30 "Contact" $4.95 10:15 "Ghostbusters" $3.25 12:45 "Matrix" $4.25 ] foreach [time title price] movies [ print ["watch" title "at" time "for" price] ] watch Contact at 8:30 for $4.95 watch Ghostbusters at 10:15 for $3.25 watch Matrix at 12:45 for $4.25 ``` In the above example, the foreach value block: ``` [time title price] ``` specifies that three values are to be fetched from movies for each evaluation of the block. ''Series Reference'' To reference the series itself during foreach you can use a set-word! within the variable block. This operation is similar to the forall and forskip functions. Example: ``` foreach [v1: v2] [1 2 3] [?? [v1 v2]] v1: [1 2 3] v2: 1 v1: [2 3] v2: 2 v1: [3] v2: 3 ``` Notice that the `v1` set-word does not affect the index position. If you are using this option to remove values, please see the remove-each function which is many times faster for large series. ''Foreach of Objects and Maps'' The foreach function can also be used with object! and map! datatypes. When using a single word argument, foreach will obtain the object field name or map key. ``` fruits: make object! [apple: 10 orange: 12 banana: 30] foreach field fruits [print field] apple orange banana ``` Note that each word is bound back to the object, and can be used to access the field value with get and set. If a second word argument is provided, it will obtain the value of each entry: ``` foreach [field value] fruits [print [field value]] apple 10 orange 12 banana 30 ``` The same behavior applies to the map! datatype, except that empty keys (those set to none) will be skipped. When a [[set-word!|Datatypes: Set-word!]] is used in the variables block, it will obtain the object value itself.
``` forever body Evaluates a block endlessly. Arguments: body [block!] - Block to evaluate each time ``` See also: [[loop|Functions: loop]] [[repeat|Functions: repeat]] [[for|Functions: for]] [[while|Functions: while]] [[until|Functions: until]] ''Description'' Evaluates a block continuously, or until a break or error condition is met. ``` forever [ if (random 10) > 5 [break] ] ```
``` form value Converts a value to a string. Arguments: value [any-type!] - The value to form ``` See also: [[print|Functions: print]] [[reform|Functions: reform]] [[mold|Functions: mold]] [[remold|Functions: remold]] [[ajoin|Functions: ajoin]] [[join|Functions: join]] [[rejoin|Functions: rejoin]] ''Description'' The form function converts a value to a human readable string. It is commonly used by print for output. ``` form 1234 "1234" form 10:30 "10:30" form %image.jpg "image.jpg" ``` When given a block of values, spaces are inserted between each values (except after a newline). ``` form [1 2 3] "1 2 3" ``` To avoid the spaces between values use [[ajoin|Functions: ajoin]], [[join|Functions: join]], or [[rejoin|Functions: rejoin]] . The [[reform|Functions: reform]] function combines reduce with `form` to evaluate values: ``` reform [1 + 2 3 + 4] "3 7" ``` To produce REBOL-readable output, use the [[mold|Functions: mold]] function.
``` format rules values /pad p Format a string according to the format dialect. Arguments: rules - A block in the format dialect. E.g. [10 -10 #"-" 4] values Refinements: /pad p ``` ''Description'' This is useful for table output in the console, where fixed-width fonts are used. It can also be used to specially format numbers or complex values. The first input, is the dialect. It's a combination of positive or negative formatting integers and strings or chars, that are to be inserted between the integers. A positive integer N, means the value will be left adjusted with N chars for space. A negative integer N, means the value will be right adjusted with N chars for space. In both cases, a value that takes up more space than N, is truncated to N chars. The second input is the values, either as a block or as a single value. Example: format [-3 -3 -4] [1 2 3] " 1 2 3" Format a time value `using /pad` to add zeroes: ``` format/pad [-2 ":" -2 ":" -2] [12 47 9] 0 "12:47:09" ``` It can also be used to pad zeroes to a single numeric value: ``` format/pad [-8] 5125 0 "00005125" ```
``` forskip word size body Evaluates a block for periodic values in a series. Arguments: word [word!] - Word that refers to the series, set to each position in series size [integer! decimal!] - Number of positions to skip each time body [block!] - Block to evaluate each time ``` See also: [[for|Functions: for]] [[forall|Functions: forall]] [[foreach|Functions: foreach]] [[skip|Functions: skip]] ''Description'' Prior to evaluation, the word must be set to the desired starting position within the series (normally the head, but any position is valid). After each evaluation of the block, the word's position in the series is changed by skipping the number of values specified by the second argument (see the skip function). ``` areacodes: [ "Ukiah" 707 "San Francisco" 415 "Sacramento" 916 ] forskip areacodes 2 [ print [ first areacodes "area code is" second areacodes] ] Sacramento area code is 916 ```
``` found? value Returns TRUE if value is not NONE. Arguments: value ``` See also: [[find|Functions: find]] [[pick|Functions: pick]] ''Description'' Returns `false` for all other values. Not usually required because most conditional function will accept a none as false and all other values as `true`, except `pick`. ``` if found? find luke@rebol.com ".com" [print "found it"] found it ```
``` fourth value Returns the fourth value of a series. Arguments: value ``` See also: [[first|Functions: first]] [[second|Functions: second]] [[third|Functions: third]] [[fifth|Functions: fifth]] [[pick|Functions: pick]] ''Description'' This is an ordinal. See the [[first|Functions: first]] function for examples. If no value is found, none is returned. ``` print fourth "REBOL" O print fourth [11 22 33 44 55 66] 44 print fourth 199.4.80.1 1 ```
``` frame? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' No description provided.
``` func spec body Defines a user function with given spec and body. Arguments: spec [block!] - Help string (opt) followed by arg words (and opt type and string) body [block!] - The body block of the function ``` See also: [[closure|Functions: closure]] [[does|Functions: does]] [[has|Functions: has]] [[funco|Functions: funco]] [[funct|Functions: funct]] [[function|Functions: function]] [[use|Functions: use]] [[make|Functions: make]] [[ function?|Functions: function?]] [[return|Functions: return]] [[exit|Functions: exit]] ''Description'' The `func` function creates new functions from a spec block and a body block. ''General form'': ``` name: func [spec] [body] ``` The spec block specifies the interface to the function. It can begin with an optional title string which used by the help function. That is followed by words that specify the arguments to the function. Each of argument can include an optional block of datatypes to specify the valid datatypes for the argument. Each may be followed by a comment string which describes the argument in more detail. The argument words may also specify a few variations on the way the argument will be evaluated. The most common is 'word which indicates that a word is expected that should not be evaluated (the function wants its name, not its value). A :word may also be given which will get the value of the argument, but not perform full evaluation. To add refinements to a function supply a slash `/` in front of an argument's word. Within the function the refinement can be tested to determine if the refinement was present. If a refinement is followed by more arguments, they will be associated with that refinement and are only evaluated when the refinement is present. Local variables are specified after a `/local` refinement. A function returns the last expression it evaluated. You can also use return and `exit` to exit the function. A return is given a value to return. exit returns no value. ``` sum: func [a b] [a + b] print sum 123 321 444 sum: func [nums [block!] /average /local total] [ total: 0 foreach num nums [total: total + num] either average [total / (length? nums)][total] ] print sum [123 321 456 800] print sum/average [123 321 456 800] 425 print-word: func ['word] [print form word] print-word testing testing ```
``` funco spec body Defines a function, but does not copy spec or body. Arguments: spec [block!] - Help string (opt) followed by arg words (and opt type and string) body [block!] - The body block of the function ``` See also: [[closure|Functions: closure]] [[does|Functions: does]] [[has|Functions: has]] [[func|Functions: func]] [[funct|Functions: funct]] [[function|Functions: function]] [[use|Functions: use]] [[make|Functions: make]] [[function?|Functions: function?]] [[return|Functions: return]] [[exit|Functions: exit]] ''Description'' Similar to [[func|Functions: func]], except the spec or body is not copied.
``` funct spec body /with object Defines a function with all set-words as locals. Arguments: spec [block!] - Help string (opt) followed by arg words (and opt type and string) body [block!] - The body block of the function Refinements: /with - Define or use a persistent object (self) object [object! block! map!] - The object or spec ``` ''Description'' This is similar to [[func|Functions: func]], except all set-words are assumed locals. This way, it's not necessary to specify the `/local` part of the spec, although you still can. Example: ``` f: funct [a] [ b: a ] f 7 7 b ** Script error: b has no value ``` If you still desire to create non-local values in the function, use set to set words: ``` f: funct [a] [ b: a set 'c b / 2 ] f 7 3.5 c 3.5 ``` If c still needs to be local, you can add the local refinement: ``` unset 'c ; make sure it's not set f: funct [a /local c] [ b: a set 'c b / 2 ] f 7 3.5 c ** Script error: c has no value ```
``` function spec vars body Defines a user function with local words. Arguments: spec [block!] - Optional help info followed by arg words (and optional type and string) vars [block!] - List of words that are local to the function body [block!] - The body block of the function ``` See also: [[func|Functions: func]] [[does|Functions: does]] [[has|Functions: has]] [[make|Functions: make]] [[use|Functions: use]] [[function?|Functions: function?]] [[return|Functions: return]] [[exit|Functions: exit]] ''Description'' <<< Warning! The descripton of function given below is up-to-date, however the spec shown above is not current. function was recently adapted from a 3-argument to a 2-argument variant. This is similar to func, except all set-words are assumed locals. This way, it's not necessary to specify the `/local` part of the spec, although you still can. <<< Example: ``` average: function [block] [ total: 0 foreach number block [total: number + total] total / (length? block) ] print average [1 10 12.34] 7.78 total ** Script error: total has no value ``` If you still desire to create non-local values in the function, use set to set words: ``` f: function [a] [ b: a set 'c b / 2 ] f 7 3.5 c 3.5 ``` If `c` still needs to be local, you can add the local refinement: ``` unset 'c ; make sure it's not set f: function [a /local c] [ b: a set 'c b / 2 ] f 7 3.5 c ** Script error: c has no value ```
``` function? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[any-function?|Functions: any-function?]] [[type?|Functions: type?]] ''Description'' Returns `false` for all other values. ``` print function? :func true print function? "test" false ```
''Description'' Editor note: This function is no longer in R3.
``` get word /any Gets the value of a word, path, or values of an object. Arguments: word - Word, path, object to get Refinements: /any - Allows word to have no value (be unset) ``` See also: [[set|Functions: set]] [[value?|Functions: value?]] [[in|Functions: in]] ''Description'' The argument to `get` must be a word, so the argument must be quoted or extracted from a block. To get the value of a word residing in an object, use the [[in|Functions: in]] function. ``` value: 123 print get 'value 123 print get second [the value here] 123 print get in system/console 'prompt >> ``` If the argument to `get` is an object, the result is the same as that of [[values-of|Functions: values-of]].
``` get-env var Returns the value of an OS environment variable (for current process). Arguments: var [any-string! any-word!] ``` See also: [[list-env|Functions: list-env]] ''Description'' This function will return the string associated with an OS environment variable. ``` probe get-env "COMPUTERNAME" "BIGBOY" ``` To obtain a list of all environment variables and their values, use [[list-env|Functions: list-env]] .
``` get-path? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[path?|Functions: path?]] [[set-path?|Functions: set-path?]] [[lit-path?|Functions: lit-path?]] ''Description'' Returns `false` for all other values. ``` get-path? to-get-path 'path/to/somewhere true ```
``` get-word? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[word?|Functions: word?]] [[set-word?|Functions: set-word?]] [[lit-word?|Functions: lit-word?]] ''Description'' Returns `false` for all other values. ``` print get-word? second [pr: :print] true ```
``` gob? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns `false` for all other values. ``` gob? make gob! [text: "this is a gob!"] true ```
``` greater-or-equal? value1 value2 Returns TRUE if the first value is greater than or equal to the second value. Arguments: value1 value2 ``` See also: [[>=|Functions: >=]] [[<|Functions: <]] [[<=|Functions: <=]] [[>|Functions: >]] [[=|Functions: =]] [[<>|Functions: <>]] [[equal?|Functions: equal?]] [[lesser-or-equal?|Functions: lesser-or-equal?]] [[min|Functions: min]] [[max|Functions: max]] [[not-equal?|Functions: not-equal?]] ''Description'' Returns `false` for all other values. Both values must be of the same datatype or an error will occur. For string-based datatypes, the sorting order is used for comparison with character casing ignored ([[uppercase = lowercase|Uppercase and Lowercase]]). ``` print greater-or-equal? "abc" "abb" true print greater-or-equal? 16-June-1999 12-june-1999 true print greater-or-equal? 1.2.3.4 4.3.2.1 false print greater-or-equal? 1:00 11:00 false ```
``` greater? value1 value2 Returns TRUE if the first value is greater than the second value. Arguments: value1 value2 ``` See also: [[>|Functions: >]] [[<|Functions: <]] [[<=|Functions: <=]] [[>=|Functions: >=]] [[=|Functions: =]] [[<>|Functions: <>]] [[lesser?|Functions: lesser?]] [[min|Functions: min]] [[max|Functions: max]] ''Description'' Returns `false` for all other values. The values must be of the same datatype or an error will occur. For string-based datatypes, the sorting order is used for comparison with character casing ignored ([[uppercase = lowercase|Uppercase and Lowercase]]). ``` print greater? "abc" "abb" true print greater? 16-June-1999 12-june-1999 true print greater? 4.3.2.1 1.2.3.4 true print greater? 11:00 12:00 false ```
``` halt Stops evaluation and returns to the input prompt. ``` See also: [[quit|Functions: quit]] [[break|Functions: break]] [[exit|Functions: exit]] [[catch|Functions: catch]] ''Description'' Useful for program debugging. ``` div: 10 if error? try [100 / div] [ print "math error" halt ] ```
''Description'' This is used internally in the view function.
``` handle? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns false for all other values. Editor note: Need example.
``` has vars body A shortcut to define a function that has local variables but no arguments. Arguments: vars [block!] - List of words that are local to the function body [block!] - The body block of the function ``` See also: [[func|Functions: func]] [[function|Functions: function]] [[does|Functions: does]] [[exit|Functions: exit]] [[return|Functions: return]] [[use|Functions: use]] ''Description'' Defines a function that consists of local variables only. This is a shortcut for [[func|Functions: func]] and [[function|Functions: function]]. For example: ``` ask-name: has [name] [ name: ask "What is your name?" print ["Hello" name] ] ask-name Hello Luke ``` The example above is a shortcut for: ``` ask-name: func [/local name] [...] ```
``` head series Returns the series at its head. Arguments: series [series! gob! port!] ``` See also: [[head?|Functions: head?]] [[tail|Functions: tail]] [[tail?|Functions: tail?]] ''Description'' The [[insert|Functions: insert]] function returns at the current string position, so `head` adjusts the index back to the head: ``` str: "all things" print head insert str "with " with all things ``` Now here is not at the head: ``` here: find str "all" print here all things ``` Now we print at the head: ``` print head here with all things ```
``` head? series Returns TRUE if a series is at its head. Arguments: series [series! gob! port!] ``` See also: [[head|Functions: head]] [[tail|Functions: tail]] [[tail?|Functions: tail?]] ''Description'' ``` cds: [ "Rockin' REBOLs" "Carl's Addiction" "Jumpin' Jim" ] print head? cds true cds: tail cds print head? cds false until [ cds: back cds print first cds head? cds ] Rockin' REBOLs ```
``` help word /doc Prints information about words and values. Arguments: word [any-type!] Refinements: /doc - Open web browser to related documentation. ``` See also: [[?|Functions: ?]] [[what|Functions: what]] [[??|Functions: ??]] [[docs|Functions: docs]] ''Description'' The `help` function provides information about words and values. Type `help` or [[?|Functions: ?]] at the console prompt to view a summary of help: ``` >> help ``` To use HELP, supply a word or value as an argument: ``` help insert ``` Also, the [[?|Functions: ?]] is a shortcut for help: ``` ? insert ? system ? system/options ``` To search all internal `help` strings and values: ``` help "insert" help to- ; (a partial word) ``` To see detailed online web docs for a function: ``` help/doc forall ``` For all on-line web documentation, just type: ``` docs ``` To see words with values of a specific datatype: ``` help native! help function! help datatype! ``` Other debug functions: ``` ? self - show words and values (in context) ?? - display a variable and its value probe - print a value (molded) source func - show source code of func trace - trace evaluation steps what - show a list of known functions why? - explain more about last error (via web) ``` Other information: ``` chat - open DevBase developer forum/BBS docs - open DocBase document wiki website bugs - open CureCore bug database website demo - run demo launcher (from rebol.com) about - see general product info upgrade - check for newer versions changes - show changes for recent version install - install (when applicable) license - show user license usage - view program options ``` ''Help about a Function'' If you provide a function word as an argument, help prints all of the information related to that function. For instance, if you type: ``` >> help insert ``` you will see: ``` USAGE: INSERT series value /part range /only /dup count DESCRIPTION: Inserts into a series and returns the series after the insert. (Modifies) INSERT is an action value. ARGUMENTS: series -- Series at point to insert (series! port! map! gob! object! bitset! port!) value -- The value to insert (any-type!) REFINEMENTS: /part -- Limits to a given length or position. length (number! series! pair!) /only -- Only inserts a block as a single value (not the contents of the block) /dup -- Duplicates the insert a specified number of times. count (number! pair!) ``` For more detailed information, you can use the doc refinement: ``` >> help/doc insert ``` to open the web browser to the page related to that function. ''Help about Datatypes'' All datatypes are explained through `help`. To obtain a list of all REBOL datatypes, type: ``` >> ? datatype! Found these related words: action! datatype! datatype native function (standard polymorphic) binary! datatype! string series of bytes bitset! datatype! set of bit flags block! datatype! series of values char! datatype! 8bit and 16bit character ... ``` For help on a specific datatype: ``` help integer! integer! is a datatype It is defined as a 64 bit integer It is of the general type scalar Found these related words: zero integer! 0 ``` To list all words that are [[function!|Datatypes: Function!]] datatypes, type: ``` >> ? function! ``` and the result would be: ``` Found these related words: ? function! Prints information about words and values. ?? function! Debug print a word, path, or block of such, f... about function! Information about REBOL alter function! If a value is not found in a series, append i... any-block? function! Return TRUE if value is any type of block. any-function? function! Return TRUE if value is any type of function. any-object? function! Return TRUE if value is any type of object. any-path? function! Return TRUE if value is any type of path. any-string? function! Return TRUE if value is any type of string. any-word? function! Return TRUE if value is any type of word. array function! Makes and initializes a series of a given siz... as-pair function! Combine X and Y values into a pair. ask function! Ask the user for input. ... ``` ''Help Search'' The `help` function also finds words that contain a specified string. For example, to find all of the words that include the string [[path!|Datatypes: Path!]], type: ``` >> ? "path" ``` and the result will be: ``` Found these related words: ?? function! Debug print a word, path, or block of such, f... any-path! typeset! [path! set-path! get-path! lit-path!] any-path? function! Return TRUE if value is any type of path. assert native! Assert that condition is true, else throw an ... cd function! Change directory (shell shortcut function). change-dir native! Changes the current directory path. clean-path function! Returns new directory path with //, . and .. ... dirize function! Returns a copy of the path turned into a dire... file! datatype! file name or path ... ``` ''Help on Objects'' If you use help on an object, it will list a summary of the object's fields. ``` >> ? system SYSTEM is an object of value: product word! core version tuple! 2.100.90.3.1 build date! 14-Oct-2009/22:40:04 license string! {Alpha prototype version. For testing only. U... catalog object! [datatypes actions natives errors reflectors ... contexts object! [root system exports user] state object! [note last-error] intrinsic object! [do make-module make-port parse-url begin] modules block! length: 3 ... ``` ''Help on Errors'' There is a special mechanism for getting help on errors. When you get an error message at the console, you can type [[why?|Functions: why?]] to see info about that specific error. For example: ``` >> test ** Script error: test has no value >> why? Opening web browser... ``` and, this page, no-value, would be displayed. See [[why?|Functions: why?]] for more about this function.
``` if condition then-block /else else-block If condition is TRUE, evaluates the block. Arguments: condition then-block [block!] Refinements: /else - If not true, evaluate this block else-block [block!] ``` See also: [[either|Functions: either]] [[any|Functions: any]] [[all|Functions: all]] [[unless|Functions: unless]] [[switch|Functions: switch]] [[select|Functions: select]] ''Description'' The `if` function will evaluate the block when its first argument is true. `True` is defined to be any value that is not `false` or `none`. ``` if 2 > 1 [print "that's true"] that's true ``` The condition can be the result of several expressions within any or and, or any other function that produces a result: ``` if all [ time > 10:20 age > 20 find users "bob" ] [print "that's true"] that's true ``` In addition, it can be pointed out that the block can be in a variable also: ``` blk: [print "that's true"] if 2 > 1 blk that's true ``` ''Return Value'' When the condition is `true`, the `if` function returns the value that is the result of evaluating the block. Otherwise, it returns none. This is a useful feature. For example: ``` print if 2 > 1 [1 + 2] 3 print if 1 > 2 [1 + 2] none names: ["Carl" "Brian" "Steve"] print if find names "Carl" ["Person found"] Person found ``` ''Where's the Else?'' Unlike most other languages, REBOL uses functions, not commands to evaluate all expressions. Therefore, it's not desirable to use the word else if you need that behavior. Instead, use the [[either|Functions: either]] function: ``` either 2 > 1 [print "greater"] [print "not greater"] greater either 1 > 2 [print "greater"] [print "not greater"] not greater ``` ''Simplification'' The above example is pretty common, but it should be noted that it can be easily refactored: ``` either 2 > 1 [print "greater"] [print "not greater"] is better written as: print either 2 > 1 ["greater"] ["not greater"] or even better written as: print pick ["greater" "not greater"] 2 > 1 ``` The importance of this is that you're picking from a choice of two strings, and you're doing it here with one less block than the code above it. Be careful with this last method. The pick function only allows true and false, not none. See either for more details. In addition, it should be noted that the any function used earlier didn't really require the if at all. It could have been written as: ``` all [ time > 10:20 age > 20 find users "bob" print "that's true" ] ``` ''A Common Error'' A common error is to use if and add an "else" block without using the either function. The extra block gets ignored: ``` n: 0 if 1 > 2 [n: 1] [n: 2] print n 0 ``` The second block is ignored in this case and not evaluated. The code should have used the either function: ``` n: 0 either 1 > 2 [n: 1] [n: 2] print n 2 ``` ''The /Else refinement is obsolete'' The `/Else` refinement is obsolete and will be removed in future versions. Avoid it.
``` image? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[to-image|Functions: to-image]] ''Description'' Returns true if the value is an image! datatype. This function is often used after the load function to verify that the data is in fact an image. For example: ``` img: load %test-image.png if not image? img [alert "Not an image file!"] ```
``` import module /version ver /check sum /isolate /only Imports a module; locate, load, make, and setup its bindings. Arguments: module [word! file! url! module! block!] Refinements: /version ver [tuple!] - Module must be this version or greater /check sum [binary!] - Module checksum as (checksum/secure of mold/flat) /isolate - Force module to create and use its own non-shared global namespace /only - Load and return module, but don't export to system ``` See also: [[do|Functions: do]] [[load|Functions: load]] ''Contents'' * Description * Return value * Useful refinements * When to use IMPORT ''Description'' The import function is used to import modules into your runtime environment. For a full description see the modules: loading modules section of this documentation. For example, you can write: ``` import 'mysql ``` and the system will search for the mysql module. You can also use a filename or URL for the module identifier: ``` import %mysql.r import http://www.rebol.com/mods/mysql.r ``` ''Return value'' When successful, the import function returns a module! datatype as its result. This allows you to write: ``` mysql: import 'mysql ``` Now, the mysql variable can be used to refer to values within the mysql module. For example the module value is used here to reference a function: ``` mysql/open-db %my-database.sql ``` See below for more. ''Useful refinements'' Like the header needs field, the import function also lets you specify a version and a checksum. These are all supported: ``` import/version mysql 1.2.3 import/check mysql #{A94A8FE5CCB19BA61C4C0873D391E987982FBBD3} import/version/check mysql 1.2.3 #{A94A8FE5CCB19BA61C4C0873D391E987982FBBD3} ``` ''When to use IMPORT'' The benefit of using the import function compared to the needs header field is that the arguments can be variables. A basic example is: ``` mod: 'mysql import mod ``` Or, something like: ``` mod-list: [ mysql 1.2.3 db-gui 2.4.5 http-server 1.0.1 ] foreach [id ver] mod-list [ import/version id ver ] ```
``` in object word Returns the word or block in the object's context. Arguments: object [any-object! block!] word [any-word! block! paren!] ``` See also: [[set|Functions: set]] [[get|Functions: get]] ''Description'' Return the word from within another context. This function is normally used with [[set|Functions: set]] and [[get|Functions: get]]. ``` set-console: func ['word value] [ set in system/console word value ] set-console prompt "==>" set-console result "-->" ``` This is a useful function for accessing the words and values of an object. The `in` function will obtain a word from an object's context. For example, if you create an object: ``` example: make object! [ name: "fred" age: 24 ] ``` You can access the object's name and age fields with: ``` print example/name print example/age 24 ``` But you can also access them with: ``` print get in example 'name print get in example 'age 24 ``` The `in` function returns the name and age words as they are within the example object. If you type: ``` print in example 'name name ``` The result will be the word name, but with a value as it exists in the example object. The get function then fetches their values. This is the best way to obtain a value from an object, regardless of its datatype (such as in the case of a function). A set can also be used: ``` print set in example 'name "Bob" Bob ``` Using in, here is a way to print the values of all the fields of an object: ``` foreach word words-of example [ probe get in example word ] 24 ``` Here is another example that sets all the values of an object to none: ``` foreach word words-of example [ set in example word none ] ``` The `in` function can also be used to quickly check for the existence of a word within an object: ``` if in example 'name [print example/name] none if in example 'address [print example/address] ``` This is useful for objects that have optional variables. ''Advanced binding uses'' In R3, in can also be used for binding a block to an object to support this useful idiom: `do in example [age + 1] 25` Identically, a [[paren!|Datatypes: Paren!]] can be used as the rebound block: ``` do in example second [(age + 1) (age + 20)] 44 ```
``` in-dir dir block Evaluate a block while in a directory. Arguments: dir [file!] - Directory to change to (changed back after) block [block!] - Block to evaluate ``` ''Description'' This is useful if you need to temporarily switch to a different directory to do something, and then switch back without manually doing so. Example: ``` in-dir %tmp-dir/ [tmp-files: read %.] ```
``` index? series /xy Returns the index number of the current position in the series. Arguments: series [series! gob! port!] Refinements: /xy - Returns index as an XY pair offset ``` See also: [[length?|Functions: length?]] [[offset?|Functions: offset?]] [[head|Functions: head]] [[head?|Functions: head?]] [[tail|Functions: tail]] [[tail?|Functions: tail?]] [[pick|Functions: pick]] [[skip|Functions: skip]] ''Description'' The index function returns the position within a series. For example, the first value in a series is an index of one, the second is an index of two, etc. ``` str: "with all things considered" print index? str 1 print index? find str "things" 10 blk: [264 "Rebol Dr." "Calpella" CA 95418] print index? find blk 95418 5 ``` Use the OFFSET? function when you need the index difference between two positions in a series.
``` info? target Returns an info object about a file or url. Arguments: target [file! url!] ``` See also: [[exists?|Functions: exists?]] [[dir?|Functions: dir?]] [[modified?|Functions: modified?]] [[size?|Functions: size?]] ''Description'' The information is returned within an object that has SIZE, DATE, and TYPE words. These can be accessed in the same manner as other objects. ``` info: info? %file.txt print info/size print info/date ```
``` input Inputs a string from the console. New-line character is removed. ``` See also: [[ask|Functions: ask]] [[confirm|Functions: confirm]] ''Description'' Returns a string from the standard input device (normally the keyboard, but can also be a file or an interactive shell). The string does not include the new-line character used to terminate it. The `/HIDE` refinement hides input with "*" characters. ``` prin "Enter a name: " name: input print [name "is" length? name "characters long"] Luke is 4 characters long ```
``` insert series value /part length /only /dup count Inserts into a series and returns the series after the insert. (Modifies) Arguments: series [series! port! map! gob! object! bitset! port!] - Series at point to insert value [any-type!] - The value to insert Refinements: /part - Limits to a given length or position length [number! series! pair!] /only - Only insert a block as a single value (not the contents of the block) /dup - Duplicates the insert a specified number of times count [number! pair!] ``` See also: [[append|Functions: append]] [[change|Functions: change]] [[clear|Functions: clear]] [[remove|Functions: remove]] [[join|Functions: join]] ''Description'' If the value is a series compatible with the first (block or string-based datatype), then all of its values will be inserted. The series position just past the insert is returned, allowing multiple inserts to be cascaded together. ''Refinements'' `/part` allows you to specify how many elements you want to insert. `/only` will force a block to be insert, rather than its individual elements. (Is only done if first argument is a block datatype.) `/dup` will cause the inserted series to be repeated a given number of times. (Positive integer or zero) The series will be modified. ``` str: copy "here this" insert str "now " print str now here this insert tail str " message" print str now here this message insert tail str reduce [tab now] print str now here this message 12-Feb-2009/17:47:52-8:00 insert insert str "Tom, " "Tina, " print str Tom, Tina, now here this message 12-Feb-2009/17:47:52-8:00 insert/dup str "." 7 print str .......Tom, Tina, now here this message 12-Feb-2009/17:47:52-8:00 insert/part tail str next "!?$" 1 print str .......Tom, Tina, now here this message 12-Feb-2009/17:47:52-8:00? blk: copy ["hello"] insert blk 'print probe blk [print "hello"] insert tail blk http://www.rebol.com probe blk [print "hello" http://www.rebol.com] insert/only blk [separate block] probe blk [[separate block] print "hello" http://www.rebol.com] ```
<<< Editor note: This function is not implemented for REBOL 3 <<< ''Description'' Set-up file associations, default icons, and path to executable.
``` integer? value ``` Returns TRUE if it is this type. ``` Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. ``` print integer? -1234 true ``` ``` print integer? "string" false ```
``` intersect set1 set2 /case /skip size Returns the intersection of two data sets. Arguments: set1 [block! string! binary! bitset! typeset!] - first set set2 [block! string! binary! bitset! typeset!] - second set Refinements: /case - Uses case-sensitive comparison /skip - Treat the series as records of fixed size size [integer!] ``` See also: [[difference|Functions: difference]] [[union|Functions: union]] [[exclude|Functions: exclude]] [[unique|Functions: unique]] ''Description'' Returns all elements within two blocks or series that exist in both. ``` lunch: [ham cheese bread carrot] dinner: [ham salad carrot rice] probe intersect lunch dinner [ham carrot] probe intersect [1 3 2 4] [3 5 4 6] [3 4] string1: "CBAD" ; A B C D scrambled string2: "EDCF" ; C D E F scrambled probe intersect string1 string2 "CD" items: [1 1 2 3 2 4 5 1 2] probe intersect items items ; get unique set [1 2 3 4 5] str: "abcacbaabcca" probe intersect str str "abc" ``` To obtain a unique set (to remove duplicate values) you can use UNIQUE. <<< Note that performing this function over very large data sets can be CPU intensive. <<<
``` issue? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. ``` print issue? #1234-5678-9012 true print issue? #467-8000 true print issue? $12.56 false ```
``` join value rest Concatenates values. Arguments: value - Base value rest - Value or block of values ``` See also: [[ajoin|Functions: ajoin]] [[rejoin|Functions: rejoin]] [[form|Functions: form]] [[reform|Functions: reform]] [[append|Functions: append]] [[repend|Functions: repend]] [[mold|Functions: mold]] [[remold|Functions: remold]] ''Description'' Returns a new series that joins together a value with another value or block of values. ``` join "super" "duper" "superduper" join %file ".txt" %file.txt ``` This differs from append and repend because a new value is created, and the first argument is not modified in any way. The first argument determines the datatype of the returned value. When the first argument is a type of series, the return value will be that type of series (d:string, [[file!|Datatypes: File!]], [[url!|Datatypes: Url!]], [[block!|Datatypes: Block!]], etc.) When the first argument is a scalar value (such as [[integer!|Datatypes: Integer!]], [[date!|Datatypes: Date!]], [[time!|Datatypes: Time!]], and others), the return will always be a [[string!|Datatypes: String!]]. When the second argument is a [[block!|Datatypes: Block!]], it will be evaluated and all of its values joined to the return value. ``` join http:// ["www.rebol.com/" %index.html] http://www.rebol.com/index.html join "t" ["e" "s" "t"] "test" join 11:11 "PM" "11:11PM" ``` Note that it also works for [[block!|Datatypes: Block!]] series, but returns a block, not a string: ``` join [1] ["two" 3 "four"] [1 "two" 3 "four"] ``` And, this case is important to note: ``` join <a> "test" <atest> ``` (See [[rejoin|Functions: rejoin]] for more detail on this case.) If you want the result here to be a [[string!|Datatypes: String!]], use the [[ajoin|Functions: ajoin]] function instead.
``` last value Returns the last value of a series. Arguments: value [series! tuple! gob!] ``` ''Description'' LAST returns the last value of a series. If the series is empty, LAST will cause an error. ``` print last "abcde" e print last [1 2 3 4 5] 5 print last %file e probe last 'system/options options ``` If you do not want an error when the series is empty, use the PICK function instead: ``` string: "" print pick back tail string 1 none ```
``` latin1? value Returns TRUE if value or string is in Latin-1 character range (below 256). Arguments: value [any-string! char! integer!] ``` ''Description'' No description provided.
``` launch script /args arg Runs a script as a separate process; return immediately. Arguments: script [file! string! none!] - The name of the script Refinements: /args arg [string! block! none!] - Arguments to the script ``` See also: [[call|Functions: call]] [[do|Functions: do]] <<< Note this special requirement: Security In order to use launch, you must have secure call enabled. <<< ''Description'' The LAUNCH function is used to run REBOL scripts as a separate process. When LAUNCH is called, a new process is created and passed the script file name or URL to be processed. The process is created as a subprocess of the main REBOL process. Launch has certain restrictions depending on the REBOL system used. Also, within Unix/Linux systems, launch will use the same shell standard files as the main REBOL process, and output will be merged. ``` launch %calculator.r launch http://www.rebol.com/scripts/news.r ```
''Description'' Editor note: This section is new or has has recently changed and is still under construction.
``` length? series Returns the length of the series from the current position. Arguments: series [series! port! map! tuple! bitset! object! gob! struct! any-word!] ``` See also: [[head|Functions: head]] [[tail?|Functions: tail?]] [[offset?|Functions: offset?]] ''Description'' The length? function returns the number of values from the current position of a series to the tail of the series. For example: ``` print length? "REBOL" 5 ``` but, in the case of an offset position from [[skip|Functions: skip]] : ``` print length? skip "REBOL" 2 3 ``` or from [[find|Functions: find]] : ``` print length? find "REBOL" "L" 1 ``` Other examples: ``` print length? [1 2 3 4 5] 5 print length? [1 2 3 [4 5]] 4 print length? read http://www.rebol.com 7216 obj: object [a: 10 b: 20] print length? obj 2 ```
``` lesser-or-equal? value1 value2 Returns TRUE if the first value is less than or equal to the second value. Arguments: value1 value2 ``` See also: [[<=|Functions: <=]] [[<|Functions: <]] [[>|Functions: >]] [[>=|Functions: >=]] [[=|Functions: =]] [[<>|Functions: <>]] [[min|Functions: min]] [[max|Functions: max]] ''Description'' Returns FALSE for all other values. For string-based datatypes, the sorting order is used for comparison with character casing ignored ([[uppercase = lowercase|Uppercase and Lowercase]]). ``` print lesser-or-equal? "abc" "abd" true print lesser-or-equal? 10-June-1999 12-june-1999 true print lesser-or-equal? 4.3.2.1 1.2.3.4 false print lesser-or-equal? 1:23 10:00 true ```
``` lesser? value1 value2 Returns TRUE if the first value is less than the second value. Arguments: value1 value2 ``` See also: [[<=|Functions: <=]] [[>|Functions: >]] [[>=|Functions: >=]] [[=|Functions: =]] [[<>|Functions: <>]] [[min|Functions: min]] [[max|Functions: max]] ''Description'' Returns FALSE for all other values. The values must be of the same datatype, or an error will occur. For string-based datatypes, the sorting order is used for comparison with character casing ignored ([[uppercase = lowercase|Uppercase and Lowercase]]). ``` print lesser? "abc" "abcd" true print lesser? 12-june-1999 10-june-1999 false print lesser? 1.2.3.4 4.3.2.1 true print lesser? 1:30 2:00 true ```
``` library? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns TRUE if the value is a LIBRARY datatype.
``` license Prints the REBOL/core license agreement. ``` See also: [[about|Functions: about]] ''Description'' Returns the REBOL end user license agreement for the currently running version of REBOL. ``` license ``` For SDK and other specially licensed versions of REBOL, the `license` function may return an empty string.
``` list-dir path /l /f /d /r /i indent Print contents of a directory (ls). Arguments: path [file! word! path! string! unset!] - Accepts %file, :variables, and just words (as dirs) Refinements: /l - Line of info format /f - Files only /d - Dirs only /r - Recursive /i indent ``` See also: [[change-dir|Functions: change-dir]] [[make-dir|Functions: make-dir]] [[what-dir|Functions: what-dir]] [[read|Functions: read]] ''Description'' Lists the files and directories of the specified path in a sorted multi-column output. If no path is specified, the directory specified in `system/script/path` is listed. Directory names are followed by a slash `/` in the output listing. ``` list-dir ``` To obtain a block of files for use by your program, use the LOAD function. The example below returns a block that contains the names of all files and directories in the local directory. ``` files: load %./ print length? files probe files [%autos.txt %build-docs.r %bulk-modify.r %cgi.r %convert-orig.r %CVS/ %emit-html.r %eval-examples.r %fix-args.r %fred/ %funcs.r %helloworld.txt %merge-funcs.r %newfile.txt %notes.txt %public/ %replace.r %scan-doc.r %scan-titles.r %strip-title.r %test-file.txt %trash.me] ```
``` list-env Returns a map of OS environment variables (for current process). ``` See also: [[get-env|Functions: get-env]] ''Description'' This function will return a map! of OS environment variables and their values. ``` probe list-env make map! [ "ALLUSERSPROFILE" "C:\Documents and Settings\All Users" "APPDATA" "C:\Documents and Settings\Carl\Application Data" "CLIENTNAME" "Console" "CommonProgramFiles" "C:\Program Files\Common Files" ```
``` lit-path? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns `true` if the value is a literal path datatype.
``` lit-word? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[set-word?|Functions: set-word?]] ''Description'' Returns FALSE for all other values. ``` probe lit-word? first ['foo bar] true ```
``` load source /header /next /all /unbound Loads a file, URL, or string. Arguments: source [file! url! string! binary! block!] - Source or block of sources Refinements: /header - Includes REBOL header object if present. Preempts /all. /next - Load the next value only. Return block with value and new position. /all - Load all values. Does not evaluate REBOL header. /unbound - Do not bind the block. ``` See also: [[save|Functions: save]] [[read|Functions: read]] [[do|Functions: do]] [[import|Functions: import]] [[bind|Functions: bind]] ''Description'' Reads and converts external data, including programs, data structures, images, and sounds into memory storage objects that can be directly accessed and manipulated by programs. The argument to LOAD can be a file, URL, string, or binary value. When a file name or URL is provided, the data is read from disk or network first, then it is loaded. In the case of a string or binary value, it is loaded directly from memory. Here are a few examples of using LOAD: ``` script: load %dict-notes.r image: load %image.png sound: load %whoosh.wav ;data: load http://www.rebol.com/example.r ;data: load ftp://ftp.rebol.com/example.r data: load "1 2 luke fred@example.com" code: load {loop 10 [print "hello"]} ``` LOAD is often called for a text file that contains REBOL code or data that needs to be brought into memory. The text is first searched for a REBOL header, and if a header is found, it is evaluated first. (However, unlike the DO function, LOAD does not require that there be a header.) If the load results in a single value, it will be returned. If it results in a block, the block will be returned. No evaluation of the block will be done; however, words in the block will be bound to the global context. If the header object is desired, use the `/HEADER` option to return it as the first element in the block. The `/ALL` refinement is used to load an entire script as a block. The header is not evaluated. The `/NEXT` refinement was removed - use `TRANSCODE/NEXT` instead
``` load-gui ``` Download current GUI module from web. (Temporary) ''Description'' No description provided.
``` log-10 value Returns the base-10 logarithm. Arguments: value [number!] ``` See also: [[exp|Functions: exp]] [[log-2|Functions: log-2]] [[log-e|Functions: log-e]] [[power|Functions: power]] ''Description'' The LOG-10 function returns the base-10 logarithm of the number provided. The argument must be a positive value, otherwise an error will occur (which can be trapped with the TRY function). ``` print log-10 100 2.0 print log-10 1000 3.0 print log-10 1234 3.091315159697223 ```
``` log-2 value Return the base-2 logarithm. Arguments: value [number!] ``` See also: [[exp|Functions: exp]] [[log-10|Functions: log-10]] [[log-e|Functions: log-e]] [[power|Functions: power]] ''Description'' The LOG-10 function returns the base-2 logarithm of the number provided. The argument must be a positive value, otherwise an error will occur (which can be trapped with the TRY function). ``` print log-2 2 1.0 print log-2 4 2.0 print log-2 256 8.0 print log-2 1234 10.26912667914941 ```
``` log-e value Returns the base-E (natural number) logarithm. Arguments: value [number!] ``` See also: [[exp|Functions: exp]] [[log-10|Functions: log-10]] [[log-2|Functions: log-2]] [[power|Functions: power]] ''Description'' The LOG-E function returns the natural logarithm of the number provided. The argument must be a positive value, otherwise an error will occur (which can be trapped with the TRY function). ``` print log-e 1234 7.118016204465333 print exp log-e 1234 1234.0 ```
``` logic? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. Note that all conditional functions will accept more than just a LOGIC value. A NONE will act as FALSE, and all other values other than logic will act as TRUE. ``` print logic? true true print logic? 123 false ```
``` loop count block Evaluates a block a specified number of times. Arguments: count [number!] - Number of repetitions block [block!] - Block to evaluate ``` See also: [[repeat|Functions: repeat]] [[for|Functions: for]] [[while|Functions: while]] [[until|Functions: until]] [[do|Functions: do]] [[break|Functions: break]] [[continue|Functions: continue]] ''Description'' The `loop` function is the simplest way to repeat the evaluation of a block. This function is very efficient and should be used if no loop counter is required. ``` loop 3 [print "hi"] hi hi hi ``` Here's an example that creates a block of 10 random integers: ``` block: make block! 10 loop 10 [append block random 100] probe block [31 25 53 20 40 2 30 79 47 79] ``` ''Returned Value'' When finished the `loop` function returns the final value the block: ``` num: 0 print loop 10 [num: num + 1] 10 ``` ''Other Notes'' * Negative or zero loop counts do not evaluate the block. * If a [[decimal!|Datatypes: Decimal!]] count is used, it will be truncated to a lower integer value. * The [[break|Functions: break]] function can be used to stop the loop at any time. The [[repeat|Functions: repeat]] function is similar to loop, except that it allows a variable to keep track of the current loop counter.
``` lowercase string /part length Converts string of characters to lowercase. (Modifies) Arguments: string [any-string! char!] Refinements: /part - Limits to a given length or position length [number! any-string!] ``` See also: [[uppercase|Functions: uppercase]] [[trim|Functions: trim]] ''Description'' The series passed to this function is modified as a result. ``` print lowercase "ABCDEF" abcdef print lowercase/part "ABCDEF" 3 abcDEF ```
``` ls path /l /f /d /r /i indent Print contents of a directory (ls). Arguments: path [file! word! path! string! unset!] - Accepts %file, :variables, and just words (as dirs) Refinements: /l - Line of info format /f - Files only /d - Dirs only /r - Recursive /i indent ``` See also: [[cd|Functions: cd]] [[change-dir|Functions: change-dir]] [[delete|Functions: delete]] [[list-dir|Functions: list-dir]] [[make-dir|Functions: make-dir]] [[mkdir|Functions: mkdir]] [[pwd|Functions: pwd]] [[rm|Functions: rm]] [[ what-dir|Functions: what-dir]] ''Description'' Note: Shell shortcut for [[list-dir|Functions: list-dir]].
``` make type spec Constructs a specified datatype. Arguments: type [any-type!] - The datatype or example value spec [any-type!] - The attributes of the new value ``` See also: [[copy|Functions: copy]] [[type?|Functions: type?]] ''Description'' The TYPE argument indicates the datatype to create. The form of the constructor is determined by the datatype. For most series datatypes, a number indicates the size of the initial allocation. ``` str: make string! 1000 blk: make block! 10 cash: make money! 1234.56 print cash $1234.560000000000000 time: make time! [10 30 40] print time 10:30:40 ``` NOTE: MAKE when used with OBJECTS will modify the context of the spec block (as if BIND was used on it). If you need to reuse the spec block use MAKE in combination with COPY/deep like this: ``` make object! copy/deep spec ```
``` make-dir path /deep Creates the specified directory. No error if already exists. Arguments: path [file! url!] Refinements: /deep - Create subdirectories too ``` See also: [[change-dir|Functions: change-dir]] [[what-dir|Functions: what-dir]] [[list-dir|Functions: list-dir]] [[delete|Functions: delete]] ''Description'' Creates a new directory at the specified location. This operation can be performed for files or FTP URLs. ``` make-dir %New-Dir/ delete %New-Dir/ ```
``` make-scheme def /with scheme Make a scheme from a specification and add it to the system. Arguments: def [block!] - Scheme specification Refinements: /with scheme - Scheme name to use as base ``` ''Description'' Description is needed.
``` map Temporary function to catch MAP usage changes. ``` ''Description'' Description is needed.
``` map-each word data body Evaluates a block for each value(s) in a series and returns them as a block. Arguments: word [word! block!] - Word or block of words to set each time (local) data [block! vector!] - The series to traverse body [block!] - Block to evaluate each time ``` ''Description'' No description provided.
``` map-event event ``` Returns event with inner-most graphical object and coordinate. ``` Arguments: event [event!] ``` ''Description'' No description provided.
``` map-gob-offset gob xy /reverse ``` Translates a gob and offset to the deepest gob and offset in it, returned as a block. ``` Arguments: gob [gob!] - Starting object xy [pair!] - Staring offset ``` ''Refinements'': `/reverse` - Translate from deeper gob to top gob. ''Description'' No description provided.
``` map? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' No description provided.
``` max value1 value2 Returns the greater of the two values. Arguments: value1 [scalar! date! series!] value2 [scalar! date! series!] ``` See also: [[min|Functions: min]] [[maximum-of|Functions: maximum-of]] [[< |Functions: <]] [[>|Functions: >]] [[maximum|Functions: maximum]] ''Description'' Returns the maximum of two values. ``` print max 0 100 100 print max 0 -100 0 print max 4.56 4.2 4.56 ``` The maximum value is computed by comparison, so MAX can also be used for non-numeric datatypes as well. ``` print max 1.2.3 1.2.8 1.2.8 print max "abc" "abd" abd print max 12:00 11:00 12:00 print max 1-Jan-1920 20-Feb-1952 20-Feb-1952 ``` Using MAX on xy pairs will return the maximum of each X and Y coordinate separately. ``` print max 100x10 200x20 200x20 ```
``` maximum value1 value2 Returns the greater of the two values. Arguments: value1 [scalar! date! series!] value2 [scalar! date! series!] ``` See also: [[max|Functions: max]] [[<|Functions: <]] [[>|Functions: >]] [[min|Functions: min]] ''Description'' See the MAX function for details.
``` maximum-of series /skip size Finds the largest value in a series Arguments: series [series!] - Series to search Refinements: /skip - Treat the series as records of fixed size size [integer!] ``` See also: [[min|Functions: min]] [[max|Functions: max]] ''Description'' Return the series at the position of its maximum value. ``` probe maximum-of [34 6 60 59 5] [60 59 5] probe maximum-of ["abc" "def" "xyz" "aaa" "efg"] ["xyz" "aaa" "efg"] ```
``` min value1 value2 Returns the lesser of the two values. Arguments: value1 [scalar! date! series!] value2 [scalar! date! series!] ``` See also: [[max|Functions: max]] [[<|Functions: <]] [[>|Functions: >]] [[minimum-of|Functions: minimum-of]] [[maximum-of |Functions: maximum-of]] ''Description'' Returns the minimum of two values. ``` print min 0 100 0 print min 0 -100 -100 print min 4.56 4.2 4.2 ``` The minimum value is computed by comparison, so MIN can also be used for non-numeric datatypes as well. ``` print min 1.2.3 1.2.8 1.2.3 print min "abc" "abd" abc print min 12:00 11:00 11:00 print min 1-Jan-1920 20-Feb-1952 1-Jan-1920 ``` Using `min` on xy pairs will return the minimum of each X and Y coordinate separately. ``` print min 100x10 200x20 100x10 ```
``` minimum value1 value2 Returns the lesser of the two values. Arguments: value1 [scalar! date! series!] value2 [scalar! date! series!] ``` See also: [[<|Functions: <]] [[>|Functions: >]] [[min|Functions: min]] [[max|Functions: max]] ''Description'' See the MIN function for details.
``` minimum-of series /skip size Finds the smallest value in a series Arguments: series [series!] - Series to search Refinements: /skip - Treat the series as records of fixed size size [integer!] ``` See also: [[min|Functions: min]] [[max|Functions: max]] ''Description'' Return the series at the position of its minimum value. ``` probe minimum-of [34 20 4 6 60] [4 6 60] probe minimum-of ["abc" "def" "xy" "aaaxy" "efg"] ["aaaxy" "efg"] ```
``` mkdir path /deep Creates the specified directory. No error if already exists. Arguments: path [file! url!] Refinements: /deep - Create subdirectories too ``` See also: [[cd|Functions: cd]] [[change-dir|Functions: change-dir]] [[delete|Functions: delete]] [[list-dir|Functions: list-dir]] [[ls|Functions: ls]] [[make-dir|Functions: make-dir]] [[pwd|Functions: pwd]] [[rm|Functions: rm]] [[what-dir|Functions: what-dir]] ''Description'' Note: Shell shortcut for [[make-dir|Functions: make-dir]].
``` mod a b Compute a nonnegative remainder of A divided by B. [catch] a [number! money! time!] b [number! money! time!] - Must be nonzero. ``` See also: [[modulo|Functions: modulo]] [[//|Functions: //]] [[remainder|Functions: remainder]] [[round|Functions: round]] ''Description'' Similar to REMAINDER, but the result is always non-negative.
``` modified? target Returns the last modified date of a file. Arguments: target [file! url!] See also: exists? ``` ''Description'' Returns NONE if the file does not exist. ``` print modified? %file.txt none ```
``` module spec body Creates a module. Arguments: spec [block!] - Name or spec block body [block!] - The body block of the module ``` ''Description'' Description is needed.
``` module? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' No description provided.
``` modulo a b Wrapper for MOD that handles errors like REMAINDER. Negligible values (compared to A and B) are rounded to zero. Arguments: a [number! money! time!] b [number! money! time!] - Absolute value will be used ``` See also: [[mod|Functions: mod]] [[//|Functions: //]] [[remainder|Functions: remainder]] [[round|Functions: round]] ''Description'' values (compared to A and B) are rounded to zero. See MOD for details.
``` mold value /only /all /flat Converts a value to a REBOL-readable string. Arguments: value [any-type!] - The value to mold Refinements: /only - For a block value, mold only its contents, no outer [] /all - Mold in serialized format /flat - No indentation ``` See also: [[form|Functions: form]] [[remold|Functions: remold]] [[join|Functions: join]] [[insert|Functions: insert]] [[reduce|Functions: reduce]] ''Description'' The `mold` function converts values to a source-code formatted string (REBOL-readable). ``` print mold 10:30 10:30 print mold %image.jpg %image.jpg print mold [1 2 3] [1 2 3] ``` The primary importance of mold is to produce strings that can be reloaded with load. ``` str: mold [1 + 2] probe load str [1 + 2] ``` The mold function is the cousin of form which produces a human-readable string (used by the print function.) For example a block will be shown with brackets `[ ]` and strings will be " " quoted or use braces `{ }` (if it is long or contains special characters). Also, remold first uses reduce then mold. The `/only` Refinement In some cases it is useful to not mold the outermost brackets of blocks. This is done with the `/only` refinement: `print mold/only [1 2 3] 1 2 3` This is commonly true for blocks of values that are saved to files: ``` write %example.r mold/only [1 2 3] ``` See the [[save|Functions: save]] function. ''The /all Refinement'' For some values mold produces an approximate string value, not a perfect representation. If you attempt to load such a string, its value may be different. For example: ``` mold 'true "true" mold true "true" ``` The first is the word true the second is the [[logic!|Datatypes: Logic!]] value true -- they are different but represented by the same word. If you load the resulting string, you will only obtain the word true not the logic value: ``` type? load mold true word! ``` The `/all` option provides a more accurate transformation from values to strings and back (using load.) ``` mold/all 'true "true" mold/all true "#[true]" ``` Using [[load|Functions: load]], you can see the difference: ``` type? load mold/all 'true word! type? load mold/all true logic! ``` Another difference occurs with strings that are indexed from their head positions. Sometimes this is desired, sometimes not. It can be seen here: ``` mold next "ABC" "BC" mold/all next "ABC" {#[string! "ABC" 2]} ``` ''Affected Datatypes'' The following datatypes are affected: [[unset!|Datatypes: Unset!]], [[none!|Datatypes: None!]], [[logic!|Datatypes: Logic!]], [[bitset!|Datatypes: Bitset!]], [[image!|Datatypes: Image!]], [[map!|Datatypes: Map!]],[[ datatype!|Datatypes: Datatype!]], [[typeset!|Datatypes: Typeset!]], [[native!|Datatypes: Native!]], [[action!|Datatypes: Action!]], [[op!|Datatypes: Op!]], [[closure!|Datatypes: Closure!]], [[function!|Datatypes: Function!]], [[object!|Datatypes: Object!]], [[module!|Datatypes: Module!]], [[error!|Datatypes: Error!]], [[task!|Datatypes: Task!]], [[port!|Datatypes: Port!]], [[gob!|Datatypes: Gob!]], [[event!|Datatypes: Event!]], [[handle!|Datatypes: Handle!]]. <<< Note on Restoring Semantics It should also be noted that some datatypes cannot be returned to a source form without losing semantic information. For example, functions cannot maintain the binding (scoping context) of their words. If such semantics reproduction is required it is recommended that your code output entire blocks that as a whole are evaluated to produce the correct semantic result. This is commonly done in REBOL code, including the common storage of mezzanine and module functions and other definitions. <<< ''Accuracy of Decimals'' The decimal! datatype is implemented as IEEE 754 binary floating point type. When molding decimal! values, mold/all will need to use the maximal precision 17 digits to allow for accurate transformation of Rebol decimals to string and back, as opposed to just mold, which uses a default precision 15 decimal digits. ''The /flat Refinement'' The `/flat` refinement is useful for minimizing the size of source strings. It properly removes leading indentation (from code lines, but not multi-line strings.) The /flat option is often used for data exchanged between systems or stored in files. Here is code often used for saving a script in minimal format (in R3): ``` write %output.r mold/only/flat code ``` For code larger than about 1K, you can also compress it: ``` write %output.rc compress mold/only/flat code ``` Such a file can be reloaded with: ``` load/all decompress read %output.rc ``` Note that if using R2, these lines must be modified to indicate binary format. ''Code Complexity Comparisons'' It should be noted that mold function is used for computing the relative complexity of code using the [[Load Mold Sizing method|http://www.rebol.com/docs/docs.html]].
``` money? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. ``` print money? $123 true print money? 123.45 false ```
``` more file Print file (shell shortcut function). Arguments: file [file! word! path! string!] - Accepts %file and also just words (as file names) ``` ''Description'' Description is needed.
``` move source offset /part length /skip size /to Move a value or span of values in a series. Arguments: source [series!] - Source series offset [integer!] - Offset to move by, or index to move to Refinements: /part - Move part of a series length [integer!] - The length of the part to move /skip - Treat the series as records of fixed size size [integer!] - Size of each record /to - Move to an index relative to the head of the series ``` ''Description'' Description is needed.
``` multiply value1 value2 ``` Returns the first value multiplied by the second. ``` Arguments: value1 [scalar!] value2 [scalar!] ``` See also: [[/|Functions: /]] [[//|Functions: //]] [[divide|Functions: divide]] Description The datatype of the second value may be restricted to INTEGER or DECIMAL, depending on the datatype of the first value (e.g. the first value is a time). ``` print multiply 123 10 1230 ``` ``` print multiply 3:20 3 10:00 ``` ``` print multiply 0:01 60 1:00 ```
Description This function is used during boot to create native built-in functions. It is [[unset|Functions: unset]] at the end of the bootstrap, and is not accessible to users. See [[extensions|Concepts: Extensions]] for methods of adding native functions.
``` native? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. When passing a function to NATIVE? to be checked, it must be denoted with ":". This is because the ":word" notation passes a word's reference, not the word's value. NATIVE? can only determine whether or not a function is a native if it is passed the function's reference. ``` probe native? :native? ; it's actually an ACTION! false probe native? "Vichy" false probe native? :if true ```
``` negate number ``` Changes the sign of a number. ``` Arguments: number [number! pair! money! time! bitset!] ``` See also: [[+|Functions: +]] [[-|Functions: -]] [[positive?|Functions: positive?]] [[negative?|Functions: negative?]] [[complement|Functions: complement]] [[not|Functions: not]] Description Returns the negative of the value provided. ``` print negate 123 -123 ``` ``` print negate -123 123 ``` ``` print negate 123.45 -123.45 ``` ``` print negate -123.45 123.45 ``` ``` print negate 10:30 -10:30 ``` ``` print negate 100x20 -100x-20 ``` ``` print negate 100x-20 -100x20 ```
``` negative? number Returns TRUE if the number is negative. Arguments: number [number! money! time! pair!] ``` See also: [[positive?|Functions: positive?]] ''Description'' Returns FALSE for all other values. ``` print negative? -50 true print negative? 50 false ```
``` new-line block value /all /skip size Sets or clears the new-line marker within a block. (Modifies) Arguments: block [block!] - Position in block to change marker value - Set TRUE for newline Refinements: /all - Set/clear marker to end of block /skip - Set/clear marker periodically to the end of the block size [integer!] ``` See also: [[new-line?|Functions: new-line?]] ''Description'' Where the NEW-LINE? function queries the status of the a block for markers, the NEW-LINE function inserts or removes them. You can use it to generate formatted blocks. Given a block at a specified offset, new-line? will return true if there is a marker at that position. ``` dent-block: func [ "Indent the contents of a block" block ][ head new-line tail new-line block on on ] b: [1 2 3 4 5 6] probe dent-block b [ 1 2 3 4 5 6 ] ``` If you want to put each item in a block on a new line, you can insert markers in bulk, using the `/all` refinement. ``` b: [1 2 3 4 5 6] probe new-line/all b on [ 1 2 3 4 5 6 ] ``` If you don't know whether a block contains markers, you may want to remove all markers before formatting the data. ``` b: [ 1 2 3 4 ] probe new-line/all b off [1 2 3 4] ``` Another common need is formatting blocks into lines of fixed size groups of items; that's what the `/skip` refinement is for. ``` b: [1 2 3 4 5 6] probe new-line/skip b on 2 [ 1 2 3 4 5 6 ] ```
``` new-line? block Returns the state of the new-line marker within a block. Arguments: block [block!] - Position in block to check marker ``` See also: [[new-line|Functions: new-line]] ''Description'' Given a block at a specified offset, `new-line?` will return `true` if there is a line marker at that position. ``` b: [1 2 3 4 5 6] forall b [if new-line? b [print index? b]] b: [ 1 2 3 4 5 6 ] forall b [if new-line? b [print index? b]] 5 ```
``` next series Returns the series at its next position. Arguments: series [series! gob! port!] ``` See also: [[back|Functions: back]] [[first|Functions: first]] [[head|Functions: head]] [[ tail|Functions: tail]] [[head?|Functions: head?]] [[tail?|Functions: tail?]] ''Description'' If the series is at its tail, it will remain at its tail. NEXT will not go past the tail, nor will it wrap to the head. ``` print next "ABCDE" BCDE print next next "ABCDE" CDE print next [1 2 3 4] 2 3 4 str: "REBOL" loop length? str [ print str str: next str ] L blk: [red green blue] loop length? blk [ probe blk blk: next blk ] [blue] ```
``` ninth value Returns the ninth value of a series. Arguments: value ``` See also: [[first|Functions: first]] [[second|Functions: second]] [[third|Functions: third]] [[pick|Functions: pick]] ''Description'' See the FIRST function for examples. An error will occur if no value is found. Use the PICK function to avoid this error.
``` none? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns FALSE for all other values. ``` print none? NONE true print none? pick "abc" 4 true print none? find "abc" "d" true ```
``` not value ``` Returns the logic complement. ``` Arguments: value - (Only FALSE and NONE return TRUE) ``` See also: [[complement|Functions: complement]] [[negate|Functions: negate]] [[and|Functions: and]] [[or|Functions: or]] [[xor|Functions: xor]] [[unless|Functions: unless]] ''Description'' The not function is a [[logic!|Datatypes: Logic!]] function that returns `true` if the value is `false` or `none`. It will return `false` for all other values. ``` not true false ``` ``` not none true ``` ``` not (10 = 1) true ``` ``` not 0 false ; take note of this ``` ``` not 1 false ``` To complement an [[integer!|Datatypes: Integer!]] use the [[complement|Functions: complement]] function or [[negate|Functions: negate]] function.
``` not-equal? value1 value2 Returns TRUE if the values are not equal. Arguments: value1 value2 ``` See also: [[<>|Functions: <>]] [[=|Functions: =]] [[==|Functions: ==]] [[equal?|Functions: equal?]] ''Description'' String-based datatypes are considered equal when they are identical or differ only by character casing (uppercase = lowercase). Use [[==|Functions: ==]] or `find/match/case` to compare strings by casing. ``` print not-equal? "abc" "abcd" true print not-equal? [1 2 4] [1 2 3] true print not-equal? 12-sep-98 10:30 true ```
``` now /year /month /day /time /zone /date /weekday /yearday /precise /utc Returns local date and time. Refinements: /year - Returns year only /month - Returns month only /day - Returns day of the month only /time - Returns time only /zone - Returns time zone offset from UCT (GMT) only /date - Returns date only /weekday - Returns day of the week as integer (Monday is day 1) /yearday - Returns day of the year (Julian) /precise - Higher precision /utc - Universal time (no zone) ``` See also: [[date?|Functions: date?]] ''Description'' For accuracy, first verify that the time, date and timezone are correctly set on the computer. ``` print now 12-Feb-2009/17:47:54-8:00 print now/date 12-Feb-2009 print now/time 17:47:54 print now/zone -8:00 print now/weekday 4 ```
``` number? value Return TRUE if value is a number (integer or decimal). Arguments: value [any-type!] ``` See also: [[integer?|Functions: integer?]] [[decimal?|Functions: decimal?]] ''Description'' Returns FALSE for all other values. ``` print number? 1234 true print number? 12.34 true print number? "1234" false ```
``` object blk Defines a unique object. Arguments: blk [block!] - Object words and values. ``` ''Description'' No description provided.
``` object? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. ``` print object? system true ```
``` odd? number Returns TRUE if the number is odd. Arguments: number [number! char! date! money! time! pair!] ``` See also: [[even?|Functions: even?]] ''Description'' Returns TRUE only if the argument is an odd integer value. If the argument is a decimal, only its integer portion is examined. ``` print odd? 3 true print odd? 100 false print odd? 0 false ```
''Description'' This function is provided to convert from an xy offset within a text face to a character index within a string. It is mainly used for text editing and text mapping operations such as for colored or hyperlinked text. Here is an interesting example. When you click your mouse on the upper text face, the string from that position forward will be shown in the lower text face. ``` view layout [ body 80x50 "This is an example string." feel [ engage: func [face act event] [ if act = 'down [ bx/text: copy offset-to-caret face event/offset show bx ] ] ] bx: body 80x50 white black ] ``` When the top face is clicked, the event/offset contains the xy offset that is converted to a string index position with offset-to-caret. The string from that point forward is copied and displayed in the lower text box (bx). Note that the string does not have to be displayed for this function to work. Also remember that when making changes to the contents of strings that are longer than 200 characters, you must set the text face line-list to NONE to force the recomputation of all line breaks.
``` offset? series1 series2 Returns the offset between two series positions. Arguments: series1 [series!] series2 [series!] ``` See also: [[index?|Functions: index?]] [[length?|Functions: length?]] [[head|Functions: head]] [[head?|Functions: head?]] [[tail|Functions: tail]] [[tail?|Functions: tail?]] [[pick|Functions: pick]] [[skip|Functions: skip]] ''Description'' Return the difference of the indexes for two positions within a series. ``` str: "abcd" p1: next str print offset? str p1 1 str: "abcd" p1: next str p2: find str "d" print offset? p1 p2 2 ```
``` op? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns FALSE for all other values. ``` print op? :and true print op? :+ true ```
``` open spec /new /read /write /seek /allow access Opens a port. Makes a new port from a specification, if necessary. Arguments: spec [port! file! url! block!] Refinements: /new - Create new file - if it exists, reset it (truncate) /read - Open for read access /write - Open for write access /seek - Optimize for random access /allow - Specifies protection attributes access [block!] ``` See also: [[close|Functions: close]] [[load|Functions: load]] [[do|Functions: do]] [[insert|Functions: insert]] [[remove|Functions: remove]] [[read|Functions: read]] [[write|Functions: write]] [[query|Functions: query]] ''Description'' Opens a port for I/O operations. The value returned from OPEN can be used to examine or modify the data associated with the port. The argument must be a fully-specified port specification, an abbreviated port specification such as a file path or URL, or a block which is executed to modify a copy of the default port specification. ``` autos: open/new %autos.txt insert autos "Ford" insert tail autos " Chevy" close autos print read %autos.txt ```
``` open? port Returns TRUE if port is open. Arguments: port [port!] ``` ''Description'' Description is needed.
``` or value1 value2 Returns the first value ORed with the second. Arguments: value1 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] value2 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] ``` See also: [[and|Functions: and]] [[not|Functions: not]] [[xor|Functions: xor]] ''Description'' An infix-operator. For LOGIC values, both must be FALSE to return FALSE; otherwise a TRUE is returned. For integers, each bit is separately affected. Because it is an infix operator, OR must be between the two values. ``` print true or false true print (10 > 20) or (20 < 100) true print 122 or 1 123 print 1.2.3.4 or 255.255.255.0 255.255.255.4 ```
``` or~ value1 value2 ``` Returns the first value ORed with the second. ``` Arguments: value1 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] value2 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] ``` See also: [[and~|Functions: and~]] [[xor~|Functions: xor~]] Description The trampoline action function for OR operator.
``` pair? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[to-pair|Functions: to-pair]] [[as-pair|Functions: as-pair]] ''Description'' Returns `true` if the value is an `xy` pair datatype. ``` print pair? 120x40 true ``` ``` print pair? 1234 false ``` See the [[PAIR!|Datatypes: Pair!]] word for more detail.
``` paren? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. A paren is identical to a block, but is immediately evaluated when found. ``` print paren? second [123 (456 + 7)] true ``` ``` print paren? [1 2 3] false ```
``` parse input rules /all /case Parses a string or block series according to grammar rules. Arguments: input [series!] - Input series to parse rules [block! string! char! none!] - Rules to parse by (none = ",;") Refinements: /all - For simple rules (not blocks) parse all chars including whitespace /case - Uses case-sensitive comparison ``` See also: [[trim|Functions: trim]] ''Contents'' * Description * General parse rules * List of keywords * Simple Parse ''Description'' The parse function is used to match patterns of values and perform specific actions upon such matches. A full summary can be found in parsing: summary of parse operations . Both string! and block! datatypes can be parsed. Parsing of strings matches specific characters or substrings. Parsing of blocks matches specific values, or specific datatypes, or sub-blocks. Whereas most languages provide a method of parsing strings, the parsing of blocks is an important feature of the REBOL language. The parse function takes two main arguments: an input to be parsed and the rules that are used to parse it. The rules are specified as a block of grammar productions that are to be matched. ''General parse rules'' Rules consist of these main elements: |Item |Description|h |keyword |a special word of the dialect, listed in the table below| |word |get or set a variable (see below) - cannot be a keyword| |path |get or set a variable via a path (see below)| |value |match the input to a value (accepted datatypes depend on input datatype)| |`"|"` |backtrack and match to next alternate rule (or)| |[block] |a block of sub-rules| |(paren) |evaluate an expression (a production)| ''List of keywords'' Within the parse dialect, these words are treated as keywords and cannot be used as variables. |Keyword |Description|h |and rule |match the rule, but do not advance the input (allows matching multiple rules to the same input)| |any rule |match the rule zero or more times; stop on failure or if input does not change.| |break |break out of a match loop (such as any, some, while), always indicating success.| |change rule only value |match the rule, and if true, change the input to the new value (can be different lengths)| |copy word |set the word to a copy of the input for matched rules| |do rule |evaluate the input as code, then attempt to match to the rule| |end |match end of input| |fail |force current rule to fail, backtrack| |if (expr) |evaluate the expression (in a paren) and if false or none, fail and backtrack| |insert only value |insert a value at the current input position (with optional ONLY for blocks by reference); input position is adjusted just past the insert| |into rule |match a series, then parse it with given rule; new series can be the same or different datatype.| |opt rule |match to the rule once or not at all (zero or one times)| |not rule |invert the result of the next rule| |quote arg |accept next argument exactly as is (exception: paren)| |reject |similar to break: break out of a match loop (such as any, some, while), but indicate failure.| |remove rule |match the rule, and if true, remove the matched input| |return rule |match the rule, and if true, immediately return the matched input as result of the PARSE function| |set word |set the word to the value of the input for matched rules| |skip |skip input (for the count range, if provided before it)| |some rule |match to the rule one or more times; stop on failure or if input does not change.| |then |regardless of failure or success of what follows, skip the next alternate rule (branch)| |thru rule |scan forward in input for matching rules, advance input to tail of the match| |to rule |scan forward in input for matching rules, advance input to head of the match| |while rule |like any, match to the rule zero or more times; stop on failure; does not care if input changes or not.| |?? |Debugging output. Prints the next parse rule value and shows the current input position (e.g. where you are in the string.)| In addition, none is a special value that can be used as a default match rule. It is often used at the end of alternate rules to catch all no-match cases. ''Simple Parse'' There is also a simple parse mode that does not require rules, but takes a string of characters to use for splitting up the input string. Parse also works in conjunction with bitsets (charset) to specify groups of special characters. The result returned from a simple parse is a block of values. For rule-based parses, it returns TRUE if the parse succeeded through the end of the input string. ``` print parse "divide on spaces" none divide on spaces print parse "Harry Haiku, 264 River Rd., Ukiah, 95482" "," Harry Haiku 264 River Rd. Ukiah 95482 page: read http://hq.rebol.net parse page [thru <title> copy title to </title>] print title Now is REBOL digits: charset "0123456789" area-code: ["(" 3 digits ")"] phone-num: [3 digits "-" 4 digits] print parse "(707)467-8000" [[area-code | none] phone-num] true ```
``` past? series Returns TRUE if a series index is past its tail. Arguments: series [series! gob! port!] ``` ''Description'' Description is needed.
``` path? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[make|Functions: make]] ''Description'' Returns FALSE for all other values. ``` print path? first [random/seed 10] true ```
``` percent? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' No description provided.
``` pick series index ``` Returns the value at the specified position in a series. ``` Arguments: series [series! map! gob! pair! date! time! tuple! bitset! port!] index - Index offset, symbol, or other value to use as index ``` See also: [[first|Functions: first]] [[second|Functions: second]] [[third|Functions: third]] [[fourth|Functions: fourth]] [[fifth|Functions: fifth]] [[find|Functions: find]] [[select|Functions: select]] ''Description'' The value is picked relative to the current position in the series (not necessarily the head of the series). The VALUE argument may be INTEGER or LOGIC. A positive integer positions forward, a negative positions backward. If the INTEGER is out of range, NONE is returned. If the value is LOGIC, then TRUE refers to the first position and FALSE to the second (same order as EITHER). An attempt to pick a value beyond the limits of the series will return NONE. ``` str: "REBOL" print pick str 2 E ``` ``` print pick 199.4.80.1 3 80 ``` ``` print pick ["this" "that"] now/time > 12:00 this ```
``` poke value index data ``` Returns value after changing its data at the given index. (Modifies) ``` Arguments: value [series! port! map! gob! bitset!] index - Index offset, symbol, or other value to use as index data - New value ``` See also: [[pick|Functions: pick]] [[change|Functions: change]] Description Similar to CHANGE, but also takes an index into the series. ``` str: "ABC" poke str 2 #"/" print str A/C ``` ``` print poke 1.2.3.4 2 10 10 ```
``` port? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. ``` file: open %newfile.txt print port? file close file true print port? "test" false ```
``` positive? number Returns TRUE if the value is positive. Arguments: number [number! money! time! pair!] ``` See also: [[negative?|Functions: negative?]] ''Description'' Returns FALSE for all other values. ``` print positive? 50 true print positive? -50 false ```
``` power number exponent ``` Returns the first number raised to the second number. ``` Arguments: number [number!] exponent [number!] ``` See also: [[exp|Functions: exp]] [[log-10|Functions: log-10]] [[log-2|Functions: log-2]] [[log-e|Functions: log-e]] Description ``` print power 12.3 5 281530.5684300001 ```
``` prin value Outputs a value with no line break. Arguments: value [any-type!] ``` See also: [[print|Functions: print]] [[input|Functions: input]] [[echo|Functions: echo]] ''Description'' No line termination is used, so the next value printed will appear on the same line. If the value is a block, each of its values will be evaluated first then printed. ``` prin "The value is " prin [1 + 2] prin ["The time is" now/time] ```
``` print value Outputs a value followed by a line break. Arguments: value [any-type!] - The value to print ``` See also: [[prin|Functions: prin]] [[probe|Functions: probe]] [[??|Functions: ??]] [[form|Functions: form]] [[reform|Functions: reform]] [[format|Functions: format]] [[mold|Functions: mold]] [[remold|Functions: remold]] [[ajoin|Functions: ajoin]] [[join|Functions: join]] [[rejoin|Functions: rejoin]] [[input|Functions: input]] [[echo|Functions: echo]] ''Description'' The `print` function outputs values in "human-friendly" format (without source code syntax.) ``` print 1234 1234 print "Example" Example print read %file.txt (file output) print read http://www.rebol.com (web page output) ``` If the value is a block, it will be processed by reduce to evaluate each of its values, which will then be output: ``` print ["The time is" now/time] The time is 17:47:54 print ["You are using REBOL" system/product system/version] You are using REBOL core 3.0.0.3.1 ``` ''Removing Spaces'' If you need to join strings and values together for output, use the ajoin, join, or rejoin functions. ``` print ajoin ["REBOL/" system/product " V" system/version/1]] REBOL/core V3 print ajoin ["The time is " 11:30 "AM"] The time is 11:30AM ``` ''Related Functions'' If a newline is not desired, use prin which does not terminate the output: ``` prin "T" print "est" Test ``` The `print` function is based on the reform function, which combines the reduce and form functions. Notice the difference between: ``` str: reform ["The time is" now/time] print str The time is 17:47:54 ``` and: ``` str: form ["The time is" now/time] print str The time is now/time ``` The alternative to form is mold which produces source code string output, and remold combines reduce with mold in the same way. ``` str: mold ["The time is" now/time] print str ["The time is" now/time] str: mold ["The time is" now/time] print str ["The time is" 17:47:54] ``` The probe function is similar to print but is defined as: ``` probe: func [value] [print mold :value :value] ``` The second use of value is to cause probe to return the value it was passed. If you want to copy print output to a file as well as the console, use the [[echo|Functions: echo]] function. ``` echo %output.txt print "Copying to file" ```
``` printf fmt val Formatted print. Arguments: fmt - Format val - Value or block of values ``` ''Description'' Description is needed.
``` probe value Debug print a molded value and returns that same value. Arguments: value [any-type!] ``` See also: [[??|Functions: ??]] [[mold|Functions: mold]] [[print|Functions: print]] [[trace|Functions: trace]] [[source|Functions: source]] [[help|Functions: help]] [[what|Functions: what]] ''Description'' The probe function will mold a value into reloadable source format and display it. ``` num: 1 probe [num + 2 "ABC"] [num + 2 "ABC"] ``` Compare with the print function which will reduce the block: ``` print [num + 2 "ABC"] 3 ABC ``` ''Return Value'' The probe function also returns its argument value as its result, making it easy to insert into code for debugging purposes. Examples: ``` n: probe 1 + 2 3 print n 3 print 2 * probe pi * probe sine 45 0.707106781186547 2.22144146907918 4.44288293815837 word: 'here if probe find [where here there] word [print "found"] [here there] found ``` See the [[print|Functions: print]] function for information about related functions.
``` protect value /deep /words /values /hide Protect a series or a variable from being modified. Arguments: value [word! series! bitset! map! object! module!] Refinements: /deep - Protect all sub-series/objects as well /words - Process list as words (and path words) /values - Process list of values (implied GET) /hide - Hide variables (avoid binding and lookup) ``` See also: [[unprotect|Functions: unprotect]] [[secure|Functions: secure]] [[set|Functions: set]] ''Contents'' * Description * Synopsis * Protecting series (strings and blocks) * Protecting objects and modules * Protecting variables (words) * Hiding variables (words) * Compatibility * Related articles ''Description'' The protect function provides the following features: * protects [[string!|Datatypes: String!]], [[block!|Datatypes: Block!]], and other series from modification (making them read-only.) * protects variables (words) from being set to new values. * protects [[object!|Datatypes: Object!]], [[module!|Datatypes: Module!]], and [[map!|Datatypes: Map!]] from modification (by protecting all its words.) * hide words within objects or modules - making them private - a method of read and write protection. ''Synopsis'' The protect argument and refinements provide these various protections: |Argument |Refinement Protection provided|h |word! or path!| |cannot set the word (variable)| |word! or path! |/hide |cannot bind to the word (variable)| |string!| |cannot modify the string| |block!| |cannot modify the block| |block! |/deep |cannot modify block or any series within it| |block! |/words |cannot set listed words or paths (variables)| |block! |/hide |cannot bind to listed words or paths| |object!| |cannot modify object or set its words (variables)| |object! |/deep |cannot modify object, set its words, or modify any of its series values| ''Protecting series (strings and blocks)'' For example to use protect to prevent modification to a string: ``` test: "text" protect test append test "a" ** Script error: protected value or series - cannot modify ``` The text string itself is now read-only. Any attempt to modify it will result in that error message. This also applies to other series: ``` test: [100 "example" 10:20] protect test append test 1.2 ** Script error: protected value or series - cannot modify ``` But notice: ``` print append test/2 "x" examplex ``` So, series within the block are still modifiable. To protect all series found within a block, use the /deep refinement: ``` test: [100 "example" 10:20] protect/deep test print append test/2 "x" ** Script error: protected value or series - cannot modify ``` ''Protecting objects and modules'' It can also be applied to objects and modules, where its meaning becomes: do not let the fields of the object be modified. However, the contents of those fields can still be modified. ``` person: make object! [ name: "Bob" age: 32 ] protect person person/name: "Ted" ** Script error: protected variable - cannot modify: name ``` However, you can still modify the contents of the name string: ``` append person/name "a" print person/name Boba ``` To prevent that, you call protect with the `/deep` refinement to protect all series within the object: ``` person: make object! [ name: "Bob" age: 32 ] protect/deep person append person/name "a" ** Script error: protected value or series - cannot modify ``` ''Protecting variables (words)'' Protect can also be used to prevent a variable word from being modified using a set operation. ``` test: "This word is protected!" protect 'test test: 123 ** Script error: protected variable - cannot modify: test ``` ''Hiding variables (words)'' To make a variable private, use the `/hide` refinement. In effect, this prevents any further bindings to the variable. It also blocks attempts at select, in, get, mold, and form, as well as reflect access. For example, here is an object that defines a password variable that is hidden. Once the object has been created, the pass variable is not accessible, except with the functions defined prior to the protect. ``` manager: object [ pass: none set-pass: func [pw][ print "setting password..." pass: pw exit ; return nothing ] get-pass: does [ checksum/secure to-binary pass ] protect/hide 'pass ] ``` The password can be accessed with the provided functions: ``` manager/set-pass "bingo" setting password... print manager/get-pass #{E410B808A7F76C6890C9ECACF2B564EC98204FDB} But any other access is not allowed: probe manager/pass ** Script error: cannot access pass in path manager/pass probe get in manager 'pass none probe select manager 'pass none probe words-of manager [set-pass get-pass] ``` For security reasons, once hidden, a variable cannot be unhidden. ''Compatibility'' <<< Non-compatibility with R2 When using a block with protect, the meaning is not to protect the words of the block, but to protect the block series itself. <<< If you need the behavior of R2, use the `/words` refinement. For example: ``` protect/words [test this] ``` Will protect the test and this variables. ''Related articles'' * [[Read-only strings, blocks, and objects|http://www.rebol.net/r3blogs/0186.html]] * [[Interesting insights from PROTECT|http://www.rebol.net/r3blogs/0187.html]] (From the A43 release.)
``` pwd Returns the current directory path. ``` See also: [[cd|Functions: cd]] [[change-dir|Functions: change-dir]] [[delete|Functions: delete]] [[list-dir|Functions: list-dir]] [[ls|Functions: ls]] [[make-dir|Functions: make-dir]] [[mkdir|Functions: mkdir]] [[rm|Functions: rm]] [[what-dir|Functions: what-dir]] ''Description'' Note: Shell shortcut for [[what-dir|Functions: what-dir]].
``` q /return value /now Stops evaluation and exits the interpreter. Refinements: /return - Returns a value (to prior script or command shell) value - Note: use integers for command shell /now - Quit immediately ``` See also: [[halt|Functions: halt]] [[exit|Functions: exit]] [[quit|Functions: quit]] ''Description'' Shortcut for [[quit|Functions: quit]]. See [[quit|Functions: quit]] for details.
``` query target /mode field Returns information about a port (also specified as file or URL). Arguments: target [port! file! url! block!] Refinements: /mode - Get mode information field [word! none!] - NONE will return valid modes for port type ``` See also: [[open|Functions: open]] [[update|Functions: update]] ''Description'' Its argument is an unopened port specification. The size, date and status fields in the port specification will be updated with the appropriate information if the query succeeds.
``` quit /return value /now Stops evaluation and exits the interpreter. Refinements: /return - Returns a value (to prior script or command shell) value - Note: use integers for command shell /now - Quit immediately ``` See also: [[halt|Functions: halt]] [[exit|Functions: exit]] [[q|Functions: q]] ''Description'' You can call `quit` to exit (terminate) your program at any point. ``` time: 10:00 if time > 12:00 [ print "time for lunch" quit ] ``` Without refinements, quit is a non-forceful exception (it will throw a quit exception.) This behavior allows a parent program to stop the termination. To force an immediate quit (no exception), use the /now refinement: ``` if bad-data [quit/now] ``` You can also return an integer! quit code to the operating system (shell) by using the return refinement: ``` quit/return 40 ``` Note that not all operating systems environments may support this quit code. <<< Rarely used Most programs do not require `quit`, and it can be problematic if your code is started by another REBOL program. Normally, when your program reaches the end, it will `quit` by itself. (If you want to prevent that behavior, use the `-h` command line option, or call halt at the end of your code.) <<<
``` random value /seed /secure /only Returns a random value of the datatype or shuffles series (modifies). Arguments: value - Maximum value of result Refinements: /seed - Restart or randomize /secure - Returns a cryptographically secure random number /only - Pick a random value from a series ``` See also: [[checksum|Functions: checksum]] [[now|Functions: now]] ''Description'' The value passed can be used to restrict the range of the random result. For integers random begins at one, not zero, and is inclusive of the value given. (This conforms to the indexing style used for all series datatypes, allowing random to be used directly with functions like PICK.) ``` loop 3 [print random 10] 1 5 3 lunch: ["Italian" "French" "Japanese" "American"] print pick lunch random 4 American ``` If the given argument is a logic value, the result is actually the same as the result of the expression ``` even? random 2 ``` ''Example'' ``` loop 4 [print random true] false false false true loop 2 [print random 1:00:00] 0:12:20 0:48:22 ``` For decimal value the function generates a uniformly distributed random number between zero (inclusive) and the given value (inclusive). ``` loop 3 [print random 1.0] 0.209417212061865 0.878424991742667 0.93627033045037 ``` Main properties: * the probability density in the interior points is the reciprocal of the given decimal VALUE argument * the probability density in the exterior points is 0.0 * as specified by IEEE754, the bounds represent "close" interior well as "close" exterior real numbers. Therefore, the frequency of every bound corresponds to the length of the segment containing adjacent interior real values (real numbers, that are IEEE 754 - rounded to the value of the bound) multiplied by the interior density equal to the reciprocal of the given VALUE RANDOM can also be used on all series datatypes: ``` print random "abcdef" dbcafe print random [1 2 3 4 5] 2 4 5 3 1 ``` In this case RANDOM randomly shuffles the given series "in place", yielding the original series with the same elements, just shuffled. To cut it down, you can use CLEAR: ``` key: random "abcdefghijklmnopqrstuv0123456789" clear skip key 6 print key anfruk ``` Here's an example password generator. Add more partial words to get more variations: ``` syls: ["ca" "ru" "lo" "ek" "-" "." "!"] print rejoin random syls .!ru-ekcalo ``` To initialize the random number generator, you can seed it with a value (to repeat the sequence) or the current time to start a unique seed. ``` random/seed 123 random/seed now ``` That last line is a good example to provide a fairly random starting value for the random number generator. The `/SECURE` variant uses SHA1() of a repeating pattern of the integer bytes (20 bytes total) and it produces cryptographically secure 64-bit random numbers. Cryptographical security means, that it is infeasible to compute the state of the generator from its output. If you don't need to make computing of the generator state infeasible (needed especially when you use the generator to generate passwords, challenges, etc. and want to comply to the FIPS security standards), it is more efficient to use the raw variant (without /SECURE refinement). Even in that case it is not feasible to compute the state, since the state of present generator consists of too many bits to be computable from the output. ''Algorithm'' The RANDOM function uses a random generator by Donald E. Knuth adjusted to generate 62-bit random integers. Thus, the maximal obtainable random number is 2 to the power of 62 = 4611686018427387904. If the RANDOM function obtains 0 as an argument, it yields 0. If the argument is a positive integer, the RANDOM function uses rejection, rejecting all "raw randoms" that exceed the largest obtainable multiple of the given VALUE argument. This way, the uniformity of the distribution is assured. In case the given VALUE exceeds the biggest obtainable "raw random", we would have to reject every "raw random" number, so in that case an overflow error is caused (It certainly is an error expecting a bigger random, than the "raw random" maximum). If the given VALUE is negative, then the generated random integers are in the interval VALUE <= R <= -1. Uniformly distributed random decimals are generated using the integer output of the Knuth's generator as follows: ``` tt62: to integer! 2 ** 62 4611686018427387904 random-dec: func [x [decimal!]] [(to decimal! (random tt62) - 1) / tt62 * x] random/seed 0 random 1.0 0.209417212061865 random/seed 0 random-dec 1.0 0.209417212061865 ``` In case the given decimal VALUE is positive, the generated random deviates are uniformly distributed in the interval 0.0 <= R <= VALUE, i.e. including bounds. In case the given decimal VALUE is negative, the random deviates are uniformly distributed in the interval VALUE <= R <= 0.0. Sometimes we need to obtain a uniformly distributed random number R, such that 0.0 < R < 1.0 (i.e. a uniformly distributed random number in the given interval, excluding the bounds). We can get such an R rejecting the bounds as follows: ``` random/seed 0 until [ r: random 1.0 all [ r !== 0.0 r !== 1.0 ] ] r 0.209417212061865 ```
``` read source /part length /seek index /string /lines Read from a file, URL, or other port. Arguments: source [port! file! url! block!] Refinements: /part - Partial read a given number of units (source relative) length [number!] /seek - Read from a specific position (source relative) index [number!] /string - Convert UTF and line terminators to standard text string /lines - Convert to block of strings (implies /string) ``` See also: [[write|Functions: write]] [[open|Functions: open]] [[close|Functions: close]] [[load|Functions: load]] [[save|Functions: save]] ''Description'' Using READ is the simplest way to get information from a file or URL. This is a higher level port operation that opens a port, reads some or all of the data, then closes the port and returns the data that was read. When used on a file, or URL, the contents of the file, or URL are returned as a string. The `/LINES` refinement returns read content as a series of lines. One line is created for each line terminator found in the read data. The `/PART` refinement reads the specified number of elements from the file, URL, or port. Reading a file or URL will read the specified number of characters. Used with /LINES, it reads a specified number of lines. See the User's Guide for more detailed explanation of using READ and its refinements. ``` write %rebol-test-file.r "text file" print read %rebol-test-file.r read write %rebol-test-file.r [ {A learned blockhead is a greater man than an ignorant blockhead. -- Rooseveldt Franklin} ] probe first read/lines %rebol-test-file.r write probe pick (read/lines %rebol-test-file.r) 3 probe read/part %rebol-test-file.r 9 probe read/with %rebol-test-file.r "blockhead" write/append %matrix.avi to-binary "abcdefg" ```
``` rebcode? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' No description provided.
``` recycle /off /on /ballast size /torture Recycles unused memory. Refinements: /off - Disable auto-recycling /on - Enable auto-recycling /ballast - Trigger for auto-recycle (memory used) size [integer!] /torture - Constant recycle (for internal debugging) ``` ''Description'' This function will force a garbage collection of unused words and values found in memory. This function is not required or recommened for most scripts because the system does it automatically as necessary. To disable garbage collection, you can specify `/off` refinement. ``` recycle/off ``` To enable it again, use `/on`: ``` recycle/on ``` Note that recently used values may not be immediately garbage collected, even though they are no longer being referenced by your program.
``` reduce value /no-set /only words /into out Evaluates expressions and returns multiple results. Arguments: value Refinements: /no-set - Keep set-words as-is. Do not set them. /only - Only evaluate words and paths, not functions words [block! none!] - Optional words that are not evaluated (keywords) /into - Output results into a block with no intermediate storage out [any-block!] ``` See also: [[compose|Functions: compose]] [[do |Functions: do]] [[foreach|Functions: foreach]] ''Description'' The reduce function evaluates multiple expressions and returns a block of results. This is one of the most useful functions in REBOL. ''For example'': ``` values: reduce [1 + 2 3 + 4] probe values [3 7] ``` Compare this with do, which only returns the result of the last expression: ``` values: do [1 + 2 3 + 4] probe values 7 ``` ''Part of other functions'' The reduce function is important because it enables you to create blocks of expressions that are evaluated and passed to other functions. Some functions, like print, use reduce as part of their operation, as shown in the following example: ``` print [1 + 2 3 + 4] 3 7 ``` The rejoin, repend, reform, remold functions also use reduce as part of their operation, as shown in the following examples: ``` rejoin ["example" 1 + 2] example3 str: copy "example" repend str [1 + 2] ; modifies (uses append) example3 reform ["example 1 + 2] example 3 remold ["example" 1 + 2] ["example" 3] Ignored reduction ``` For convenience, expressions that are fully evaluated simply pass-through the reduce function. ``` reduce 123 123 reduce "example" example ``` This makes it possible to use reduce in cases where other datatypes may be passed. For example, here is a common function for building HTML strings that relies on this behavior: ``` html: make string! 1000 emit: func [data] [repend html data] emit "test... " emit ["number is: " 10] print html test... number is: 10 ``` ''Blocks with set-words'' When you reduce blocks that contain set-words, those words will be set. For example: ``` a: 1 reduce [a: 2] print a 2 ``` There are times when you do not want this to occur. For example, if you're building a header for a file, you may want to leave the set-words alone. The `/no-set` refinement can be used to handle this case. ``` full-name: "Bob Smith" reduce/no-set [name: full-name time: now + 10] [name: "Bob Smith" time: 15-Aug-2010/16:10:50-7:00] ``` ''Memory usage for large blocks'' For most blocks you don't need to worry about memory because REBOL's automatic storage manager will efficiently handle it; however, when building large block series with reduce, you can manage memory even more carefully. For example, it is common to write: ``` repend series [a b c] ``` which is shorthand for: ``` append series reduce [a b c] ``` The evaluated results of a, b, and c are appended to the series. If this is done a lot, a large number of temporary series are generated, which take memory and also must be garbage collected later. The `/into` refinement helps optimize the situation: reduce/into [a b c] tail series It requires no intermediate storage. ''Common Problems'' Although reduce will create a new outer block, all other series (blocks, strings, etc.) are referenced, not copied. If you modify those values, they will change in all blocks that reference them. For example: ``` str: "name" probe result: reduce [str] ["name"] insert str "new-" probe result ["new-name"] ``` You can see that it's the same string. To change that behavior use the copy function: ``` result: reduce [copy str] ``` or, for blocks that contain multiple strings or other values: ``` result: copy/deep reduce [str] ```
``` refinement? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns FALSE for all other values. ``` print refinement? /any true print refinement? 'any false ```
``` reflect value field Returns definition-related details about a value. Arguments: value [any-type!] field [word!] - Such as: spec, body, words, values, title ``` See also: [[body-of|Functions: body-of]] [[spec-of|Functions: spec-of]] [[title-of|Functions: title-of]] [[types-of|Functions: types-of]] [[values-of|Functions: values-of]] [[words-of|Functions: words-of]] ''Description'' No description provided.
``` reform value Forms a reduced block and returns a string. Arguments: value - Value to reduce and form ``` See also: [[form|Functions: form]] [[mold|Functions: mold]] [[remold|Functions: remold]] [[join|Functions: join]] [[rejoin|Functions: rejoin]] ''Description'' Identical to FORM but reduces its argument first. Spaces are inserted between each value. ``` probe reform ["the time is:" now/time] "the time is: 17:47:54" probe form ["the time is:" now/time] "the time is: now/time" ```
``` rejoin block Reduces and joins a block of values. Arguments: block [block!] - Values to reduce and join ``` See also: [[join|Functions: join]] [[ajoin|Functions: ajoin]] [[form|Functions: form]] [[reform|Functions: reform]] ''Description'' Similar to join but accepts only one argument, the block (which will be reduced first). No spaces are inserted between values. ``` rejoin ["time=" now/time] time=17:47:54 ``` Notice this important case: ``` rejoin [<a> "test"] <atest> ``` This is fine for lines like: ``` rejoin [<a href=> "test.html"] <a href=test.html> ``` But you can see it creates a problem in this case: ``` rejoin [<a href=test.html> "test" </a>] <a href=test.htmltest</a>> ``` If you want the result to be a string!, use the ajoin function instead. ``` ajoin [<a href=test.html> "test" </a>] "<a href=test.html>test</a>" ```
``` remainder value1 value2 ``` Returns the remainder of first value divided by second. ``` Arguments: value1 [scalar!] value2 [scalar!] ``` See also: [[//|Functions: //]] [[/|Functions: /]] Description If the second number is zero, an error will occur. ``` print remainder 123 10 3 ``` ``` print remainder 10 10 0 ``` ``` print remainder 10.2 10 0.1999999999999993 ``` If the first value is positive, then the returned remainder is nonnegative. If the first value is negative, then the returned remainder is nonpositive.
``` remold value /only /all /flat Reduces and converts a value to a REBOL-readable string. Arguments: value - The value to reduce and mold Refinements: /only - For a block value, mold only its contents, no outer [] /all - Mold in serialized format /flat - No indentation ``` See also: [[mold|Functions: mold]] [[reduce|Functions: reduce]] [[reform|Functions: reform]] [[form|Functions: form]] ''Description'' Identical to MOLD, but reduces its argument first. Spaces are inserted between each values in a block. ``` print remold ["the time is:" now/time] ["the time is:" 17:47:54] ```
``` remove series /part length Removes value(s) from a series and returns after the remove. (Modifies) Arguments: series [series! gob! port! bitset! none!] Refinements: /part - Removes to a given length or position length [number! series! pair! char!] ``` See also: [[append|Functions: append]] [[ change|Functions: change]] [[clear|Functions: clear]] [[insert|Functions: insert]] [[sort|Functions: sort]] ''Description'' Removes a single value from the current position in any type of series. ``` str: copy "send it here" remove str print str end it here ``` Combine it with other functions to remove a value at a specific index: remove find str "it" print str end t here You can remove any number of values with the `/PART` refinement: ``` str: copy "send it here" remove/part str 3 print str d it here ``` The PART refinement also accepts an index of the series being removed form. It must be the same series. ``` remove/part str find str "here" print str here ``` An example using a [[block!|Datatypes: Block!]]: ``` blk: copy [red green blue] remove next blk probe blk [red blue] ```
``` remove-each word data body Removes values for each block that returns true. Returns remove count. (Modifies) Arguments: word [word! block!] - Word or block of words to set each time (local) data [series!] - The series to traverse body [block!] - Block to evaluate (return TRUE to remove) ``` See also: [[foreach|Functions: foreach]] [[remove|Functions: remove]] [[map-each|Functions: map-each]] ''Description'' The `remove-each` function is a high performance method of removing specific elements from a series. It is similar to foreach but will remove one or more values depending on the result of the evaluated block. In this example, remove-each is used to remove all strings from the block: ``` values: [12 "abc" test 5 "de" 10:30] remove-each value values [string? value] probe values [12 test 5 10:30] ``` Here, all integer values greater than 11 are removed: ``` values: [12 "abc" test 5 "de" 10:30] remove-each value values [all [integer? value value > 11]] probe values ["abc" test 5 "de" 10:30] ``` ''Multiple Elements'' The `remove-each` function can be used on multiple elements, just as foreach does. ``` movies: [ 8:30 "Contact" $4.95 10:15 "Ghostbusters" $3.25 12:45 "Matrix" $4.25 ] foreach [time title price] movies [ print [title "at" time "for" price] if price > $4.00 [print "removed" true] ] Contact at 8:30 for $4.95 removed Ghostbusters at 10:15 for $3.25 Matrix at 12:45 for $4.25 removed ``` This example also shows that the evaluated block may contain any other expressions as long as the last one returns true for removed values. Also, notice here the way if is used for its [[return|Functions: return]] value.
``` rename from to Rename a file. Arguments: from [port! file! url! block!] to [port! file! url! block!] ``` See also: [[delete|Functions: delete]] [[list-dir|Functions: list-dir]] [[what-dir|Functions: what-dir]] ''Description'' Renames a file within the same directory: ``` write %testfile now rename %testfile %remove.me probe read %remove.me delete %remove.me write ``` <<< This function cannot be used to move a file from one directory to another. <<<
``` repeat word value body Evaluates a block a number of times or over a series. Arguments: word [word!] - Word to set each time value [number! series! none!] - Maximum number or series to traverse body [block!] - Block to evaluate each time ``` See also: [[loop|Functions: loop]] [[foreach|Functions: foreach]] [[forall|Functions: forall]] [[forskip|Functions: forskip]] [[for|Functions: for]] [[while|Functions: while]] [[until|Functions: until]] ''Description'' The `repeat` function is an easy way to repeat the evaluation of a block with a loop counter. ``` repeat num 3 [print num] 1 2 3 ``` Here the num counter begins at one and continues up to and including the integer value given. ''Other Notes'' * Negative or zero loop counts do not evaluate the block. * If a decimal! count is used, it will be truncated to a lower integer value. * The break function can be used to stop the loop at any time. * The loop function is similar to repeat, except that it has no loop counter. If you don't need the counter, loop is more efficient. * The evaluated block is deep copied and rebound (see bind ) to a new context that holds the loop variable. For large nested repeat loops, you will want to consider this overhead. An alternative is to use while, until, or loop which do not require the copy and bind. ''In question...'' If the value is a series, then the loop will repeat for each element of the series. However, there's currently a difference between R2 and R3. In R2, if the value is a series, then the word holds the first value of each element of the series. In R3 it holds just the indexed series. <<< Editor note: Determine if this is intentional <<<
``` repend series value /part length /only /dup count Appends a reduced value to a series and returns the series head. Arguments: series [series! port! map! gob! object! bitset!] - Series at point to insert value - The value to insert Refinements: /part - Limits to a given length or position length [number! series! pair!] /only - Inserts a series as a series /dup - Duplicates the insert a specified number of times count [number! pair!] ``` See also: [[append|Functions: append]] [[insert|Functions: insert]] [[reduce|Functions: reduce]] [[ join|Functions: join]] ''Description'' REPEND stands for REDUCE APPEND. It performs the same operation as APPEND (inserting elements at the tail of a series) but Reduces the block of inserted elements first. Just like APPEND, REPEND returns the head of the series. For example, writing: ``` numbers: [1 2 3] probe repend numbers [2 + 2 2 + 3 3 + 3] [1 2 3 4 5 6] ``` is the same as writing: ``` numbers: [1 2 3] probe append numbers reduce [2 + 2 2 + 3 3 + 3] [1 2 3 4 5 6] ``` REPEND is very useful when you want to add to a series elements that need to be evaluated first. The example below creates a list of all the .r files in the current directory, along with their sizes and modification dates. ``` data: copy [] foreach file load %. [ if %.r = suffix? file [ repend data [file size? file modified? file] ] ] probe data [%build-docs.r 7915 13-Feb-2009/0:03:17.078 %bulk-modify.r 4210 7-Feb-2009/17:20:06.906 %cgi.r 5125 12-Feb-2009/20:54:51.578 %convert-orig.r 1112 7-Feb-2009/17:20:06.906 %emit-html.r 10587 13-Feb-2009/0:09:38.875 %eval-examples.r 2545 13-Feb-2009/1:46:59.765 %fix-args.r 416 13-Feb-2009/0:41:11.296 %funcs.r 1133 12-Feb-2009/18:54:32.875 %merge-funcs.r 1318 13-Feb-2009/0:42:03.718 %replace.r 197 7-Feb-2009/16:56:23 %scan-doc.r 3429 13-Feb-2009/0:05:33.062 %scan-titles.r 4402 12-Feb-2009/16:51:42.687 %strip-title.r 274 7-Feb-2009/17:20:06.953] ``` When used with strings, repend is a useful way to join values. The example below is a common method of generating HTML web page code: ``` html: copy "<html><body>" repend html [ "Date is: " now/date <P> "Time is: " now/time <P> "Zone is: " now/zone <P> </body></html> ] print html <html><body>Date is: 12-Feb-2009<P>Time is: 17:47:54<P>Zone is: -8:00<P></body></html> ```
``` replace target search replace /all /case /tail Replaces a search value with the replace value within the target series. Arguments: target [series!] - Series that is being modified search - Value to be replaced (converted if necessary) replace - Value to replace with (called each time if a function) Refinements: /all - Replace all occurrences /case - Case-sensitive replacement /tail - Return target after the last replacement position ``` See also: [[insert|Functions: insert]] [[remove|Functions: remove]] [[change|Functions: change]] ''Description'' Searches target block or series for specified data and replaces it with data from the replacement block or series. Block elements may be of any datatype. The `/ALL` refinement replaces all occurrences of the searched data in the target block or series. ``` str: "a time a spec a target" replace str "a " "on " print str on ime a spec a target replace/all str "a " "on " print str on ime on pec on arget fruit: ["apples" "lemons" "bananas"] replace fruit "lemons" "oranges" print fruit apples oranges bananas numbers: [1 2 3 4 5 6 7 8 9] replace numbers [4 5 6] ["four" "five" "six"] print numbers 1 2 3 four five six 7 8 9 ```
``` request-file /save /multi /file name /title text /filter list Asks user to select a file and returns full file path (or block of paths). Refinements: /save - File save mode /multi - Allows multiple file selection, returned as a block /file name [file!] - Default file name or directory /title text [string!] - Window title /filter list [block!] - Block of filters (filter-name filter) ``` See also: [[to-local-file|Functions: to-local-file]] [[to-rebol-file|Functions: to-rebol-file]] ''Contents'' * Description * Details * Normal usage for read or load * For saving or writing files * Specifying a default file or directory * Allowing multiple file selection * Filtering file views * Setting the window title ''Description'' Opens the standard operating system file requester to allow the user to select one or more files. ''Details'' ''Normal usage for read or load'' The line: ``` file: request-file ``` will open the file requester and return a single file name as a full file path. This is normally used to read or load files. If the user clicks CANCEL or closes the file requestor, a NONE is returned. ''For saving or writing files'' To open the file requester to save a file: ``` file: request-file/save ``` This will change the text of the window to indicate that a save (write) will be done. ''Specifying a default file or directory'' A default name can be provided for the file: ``` file: request-file/file %test.txt ``` This also works with the `/save` option, and a full path can be provided, in which case the requester will show the directory where the file will be found. In addition, just a directory can be used: ``` file: request-file/file %/c/data/files/ ``` Be sure to include the terminating slash to indicate a directory. Otherwise it will be treated as a file. ''Allowing multiple file selection'' To allow the selection of multiple files at the same time: ``` files: request-file/multi foreach file files [print file] ``` The result is returned as a block, and each file within the block is a full path. ''Filtering file views'' You can also provide file list filters to show only specific files. For example: ``` file: request-file/filter [ "REBOL Scripts" "*.r" "Text files" "*.txt" ] ``` ''Setting the window title'' The `/title` refinement lets you modify the window title for the file requester to help make it more clear to users. ``` file: request-file/save/title "Save your data file" either file [save file data] [print "data not saved"] Changes from R2 ``` This function contains minor changes and cleanup relative to R2. Note that the default operation (with no refinements) returns a single file, not a block. This is the most common form of operation, so it is made standard here. In addition, the `/multi` option returns a block of full file paths, not a directory path followed by relative files.
``` resolve target source /only from /all Copy context by setting values in the target from those in the source. Arguments: target [any-object!] source [any-object!] Refinements: /only from [block! integer!] - Only specific words (exports) or new words in target (index to tail) /all - Set all words, even those in the target that already have a value ``` ''Contents'' * Description * Basic Concept * Refinements ''Description'' The `resolve` function is used to merge values from one context into another but avoids replacing existing values. <<< It is used mainly to support runtime environments, where newly exported functions must be merged into an existing lib context. Because lib can become quite large, performance must be optimized, which is the reason why resolve is a native function. <<< ''Basic Concept'' This example will help to show the basic concept: ``` obj1: object [a: 10] obj2: object [b: 20] append obj1 'b resolve obj1 obj2 print obj1 a: 10 b: 20 ``` But notice: ``` obj1: object [a: 10] obj2: object [a: 30 b: 20] append obj1 'b resolve obj1 obj2 print obj1 a: 10 b: 20 ``` So, resolve has no affect on values that have already been set in the target context. Note that protected words will not be modified, they are ignored. No error occurs. ''Refinements'' * `/only` only affect word values that are provided in a block argument that follows this refinement. In addition, this refinement also supports a special optimization where you can indicate the index of the starting point for changes. That is useful with large contexts such as lib and others. * `/all` forces resolve to change all values, not just those that are unset. This is similar to append on an object! except that the source is an object, not a block. * `/extend` any words not found in the target context will be added. This eliminates the append step that was shown above (or a similar bind step). This refinement optimizes such operations.
``` return value /redo Returns a value from a function. Arguments: value [any-type!] Refinements: /redo - Upon return, re-evaluate the returned result. (Used for DO) ``` See also: [[break|Functions: break]] [[exit|Functions: exit]] [[catch|Functions: catch]] ''Description'' Exits the current function immediately, returning a value as the result of the function. To return no value, use the EXIT function. ``` fun: make function! [this-time] [ return either this-time >= 12:00 ["after noon"][ "before noon"] ] print fun 9:00 print fun 18:00 ```
``` reverse series /part length Reverses a series and similar types. (Modifies) Arguments: series [series! gob! tuple! pair!] Refinements: /part - Limits to a given length or position length [number! series!] ``` See also: [[insert|Functions: insert]] [[replace|Functions: replace]] [[sort|Functions: sort]] [[find|Functions: find]] ''Description'' Reverses the order of elements in a series or tuple. ``` blk: [1 2 3 4 5 6] reverse blk print blk 6 5 4 3 2 1 ``` The `/PART` refinement reverses the specified number of elements from the current index forward. If the number of elements specified exceeds the number of elements left in the series or tuple, the elements from the current index to the end will be reversed. ``` text: "It is possible to reverse one word in a sentence." reverse/part (find text "reverse") (length? "reverse") print text ``` It is possible to esrever one word in a sentence. Note that reverse returns the starting position it was given. (This change was made to newer versions.) ``` blk: [1 2 3 4 5 6] print reverse/part blk 4 4 3 2 1 5 6 ``` Reverse also works for pairs and tuples: ``` print reverse 10x20 print reverse 1.2.3 3.2.1 ``` For tuple values the current index cannot be moved so the current index is always the beginning of the tuple. ``` print reverse 1.2.3.4 4.3.2.1 print reverse/part 1.2.3.4 2 4.3.2.1 ```
``` reword source values /escape char /into output Substitutes values into a template string, returning a new string. Arguments: source [any-string!] - Template series (or string with escape sequences) values [map! object! block!] - Pairs of values and replacements (will be called if functions) Refinements: /escape - Choose your own escape char (no escape for block templates) char [char! any-string!] - Use this escape char (default $) /into - Insert into a buffer instead (returns position after insert) output [any-string!] - The buffer series (modified) ``` See also: [[compose|Functions: compose]] [[replace|Functions: replace]] ''Description'' This is a general substitution function useful for building web pages, form letters, and other documents. ''Work In Process'' The block substitution abilities are still pending but string substitution works well now.
``` rm port Send port a delete request. Arguments: port [port! file! url! block!] ``` See also: [[cd|Functions: cd]] [[change-dir|Functions: change-dir]] [[delete|Functions: delete]] [[list-dir|Functions: list-dir]] [[ls|Functions: ls]] [[make-dir|Functions: make-dir]] [[mkdir|Functions: mkdir]] [[pwd|Functions: pwd]] [[what-dir|Functions: what-dir]] ''Description'' Note: Shell shortcut for [[delete|Functions: delete]].
``` round n /to scale /even /down /half-down /floor /ceiling /half-ceiling Rounds a numeric value. Halves round up (away from zero) by default. Arguments: n [number! pair! money! time!] - The value to round Refinements: /to - Return the nearest multiple of the scale parameter scale [number! money! time!] - Must be a non-zero value /even - Halves round toward even results /down - Round toward zero, ignoring discarded digits. (truncate) /half-down - Halves round toward zero /floor - Round in negative direction /ceiling - Round in positive direction /half-ceiling - Halves round in positive direction ``` See also: [[mod|Functions: mod]] [[modulo|Functions: modulo]] [[//|Functions: //]] [[remainder|Functions: remainder]] ''Description'' <<< "Rounding is meant to loose precision in a controlled way." -- Volker Nitsch <<< The round function is quite flexible. With the various refinements and the scale option, you can easily round in various ways. Most of the refinements are mutually exclusive--that is, you should use only one of them--the /to refinement is an obvious exception; it can be combined with any other refinement. By default, round returns the nearest integer, with halves rounded up (away from zero). ``` probe round 1.4999 1 probe round 1.5 2 probe round -1.5 -2 ``` If the result of the rounding operation is a number! with no decimal component, and the SCALE value is not time! or money!, an integer will be returned. This makes it easy to use the result of ROUND directly with iterator functions such as LOOP and REPEAT. The `/TO` refinment controls the "precision" of the rounding. That is, the result will be a multiple of the SCALE parameter. In order to round to a given number of decimal places, you don't pass in the number of decimal places, but rather the "level of precision" they represent. For example, to round to two decimal places, often used for money values, you would do this: ``` probe round/to $1.333 .01 $0.5558830792256812207833088 ``` To round to the nearest 1/8, often used for interest rates, you would do this: ``` probe round/to 1.333 .125 1.375 ``` To round to the nearst 1K increment (e.g. 1024 bytes): ``` probe round/to 123'456 1024 123904 ``` If the `/TO` refinement is used, and SCALE is a time! or money! value, the result will be coerced to that type. If SCALE is not used, or is not a time! or money! value, the datatype of the result will be the same as the valued being rounded. The `/EVEN` refinement is designed to reduce bias when rounding large groups of values. It is sometimes called Banker's rounding, or statistical rounding. For cases where the final digit of a number is 5 (e.g. 1.5 or 15), the previous digit will be rounded to an even result (2, 4, etc.). ``` repeat i 10 [val: i + .5 print [val round/even val]] 10.5 10 repeat i 10 [val: i * 10 + 5 print [val round/even/to val 10]] 105 100 ``` The `/DOWN` refinement rounds toward zero, ignoring discarded digits. It is often called "truncate". ``` probe round/down 1.999 1 probe round/down -1.999 -1 probe round/down/to 1999 1000 1000 probe round/down/to 1999 500 1500 ``` The `/HALF-DOWN` refinement causes halves to round toward zero; by default they are rounded up. ``` probe round/half-down 1.5 1 probe round/half-down -1.5 -1 probe round/half-down 1.50000000001 2 probe round/half-down -1.50000000001 -2 ``` The `/HALF-CEILING` refinement causes halves to round in a positive direction; by default they are rounded up (away from zero). This works like the default behavior for positive values, but is not the same for negative values. ``` probe round -1.5 -2 probe round/half-ceiling -1.5 -1 ``` `/FLOOR` causes numbers with any decimal component to be rounded in a negative direction. It works like `/DOWN` for positive numbers, but not for negative numbers. ``` round/floor 1.999 round/floor -1.01 round/floor -1.00000000001 ``` `/CEILING` is the reverse of `/FLOOR`; numbers with any decimal component are rounded in a positive direction. ``` round/ceiling 1.01 round/ceiling 1.0000000001 round/ceiling -1.999 ``` If you are rounding extremely large numbers (e.g. 562'949'953'421'314), or using very high precision decimal values (e.g. 13 or more decimal places), you may run up against REBOL's native limits for values and its internal rounding rules. The ROUND function is a mezzanine and has no control over that behavior. Sometimes, it might appear that ROUND is doing something strange, so before submitting a bug to RAMBO, think about what you're actually asking it to do. For example, look at the results from this piece of code: ``` repeat i 10 [ scale: .9 + (i * .01) print [scale round/down/to 10.55 scale] ] 1.0 10.0 ``` The results approach 10.55 for values from 0.91 to 0.95, but then jump back when using values in the range 0.96 to 0.99. Those are the expected results, because you're truncating, that is, truncating to the nearest multiple of SCALE. The design and development of the ROUND function involved many members of the REBOL community. There was much debate about the interface (one function with refinement versus individual functions for each rounding type, what words to use for parameter names, behavior with regards to type coercion).
Description This function does not exist in REBOL 3. See [[library?|Functions: library?]]
Note this special requirement: <<< Security In order to use run, you must have secure call enabled. <<< ''Description'' Editor note: This section is new or has has recently changed and is still under construction.
``` same? value1 value2 Returns TRUE if the values are identical. Arguments: value1 value2 ``` See also: [[=?|Functions: =?]] [[equal?|Functions: equal?]] ''Description'' Returns TRUE if the values are identical objects, not just in value. For example, a TRUE would be returned if two strings are the same string (occupy the same location in memory). Returns FALSE for all other values. ``` a: "apple" b: a print same? a b true print same? a "apple" false ```
``` save where value /header header-data /all Saves a value or a block to a file, URL, or into a string. Arguments: where [file! url! binary! string! none!] - Where to save (suffix determines encoding) value - Value to save Refinements: /header - Save it with a header header-data [block! object! logic!] - Header block, object, or take object from value /all - Save in serialized format ``` See also: [[load|Functions: load]] [[mold|Functions: mold]] [[write|Functions: write]] ''Description'' The `save` function is used to save REBOL code and data to a file, upload it to a URL, or store it into a local string. When saving to a file or URL, the output of this function is always UTF-8 (an Unicode encoded format where ASCII is normal, but other characters are encoded.) The format of the resulting output depends on what you need. The `save` function is designed to allow simple values to be easily saved to be loaded with load later: ``` save %date.r now load %date.r 26-Feb-2009/13:06:15-8:00 ``` But, it also allows complex more complex data to be saved: ``` save %data.r reduce ["Data" 1234 %filename now/time] load %data.r ["Data" 1234 %filename 13:07:15] save %options.r system/options load %options.r make object! [ home: %/C/rebol/ script: none path: %/C/rebol/ boot: %/C/rebol/view.exe args: none ... ``` In general, save performs the appropriate conversion and formatting to preserve datatypes. For instance, if the value is a REBOL block, it will be saved as a REBOL script that, when loaded, will be identical. <<< Editor note: saving `/all` Editor note: saving with headers Note: Users must take care in how saved data is loaded. More on this below. <<<
``` scalar? value Return TRUE if value is any type of scalar. Arguments: value [any-type!] ``` ''Description'' Description is needed.
``` script? source Checks file, url, or string for a valid script header. Arguments: source [file! url! binary! string!] ``` ''Description'' If the header is found, the script string will be returned as of that point. If not found, then NONE is returned. ``` print either script? %file.txt ["found"]["not found"] ```
``` second value Returns the second value of a series. Arguments: value ``` See also: [[pick|Functions: pick]] [[first|Functions: first]] [[third|Functions: third]] [[fourth|Functions: fourth]] [[fifth|Functions: fifth]] ''Description'' An error will occur if no value is found. Use the PICK function to avoid this error. ``` print second "REBOL" E print second [11 22 33 44 55 66] 22 print second 12-jun-1999 6 print second 199.4.80.1 4 print second 12:34:56.78 34 ```
``` secure policy Set security policies (use SECURE help for more information). Arguments: policy [word! lit-word! block! unset!] - Set single or multiple policies (or HELP) ``` See also: [[protect|Functions: protect]] [[load|Functions: load]] [[import|Functions: import]] '' Contents'' * Description * What can be controlled * Usage * The main argument * Argument as a word * Argument as a block * Security policies * Access types * Querying security * Securing security * User confirmation * Controlling security at startup * Limiting evaluation (quota) * Limiting memory ''Description'' The `secure` function controls file, network, evaluation, and all other external access and related policies. The function uses a simple dialect to specify security sandboxes and other options that allow or deny access. You can set different security levels and multiple sandboxes for networking and specific files and directories. What can be controlled The secure function gives you control over policies for: |file |file read, write, and directory creation and listing| |net |read and write access to the network interfaces| |eval |limit the number of evaluation cycles allowed (always quits)| |memory |limit the amount of memory used (always quits)| |secure |control changes to security policies with secure| |protect |protecting and hiding values with protect| |debug |use of debug-related functions: trace and stack| |envr |getting OS/shell environment variables with get-env| |call |launching external programs with call| |browse |opening the web browser with browse| |extension |importing extensions (may contain native code)| A list of these for your current release can always be obtained with the line: ``` secure query ``` (Which will also show their current policy settings.) ''Usage'' <<< R3 ASK not available In current releases of R3, the ASK option is not available. Use either THROW or QUIT instead. <<< ''The main argument'' The argument to the secure function can be a word or a block. |word |a general, top-level action such as setting global security levels to allow or deny all access. It can also be used to query the current security policies.| |block |specify separate security policies for files, directories, networking, extensions, debugging, and other features.| ''Argument as a word'' If the argument is a word, it can be: |help |summarize what policies can be set| |query |show current policies| |allow |remove all policies (no security)| |none |the same as allow (no security)| |ask |require user permission on all policies| |throw |throw an error for all violations| |quit |exit the program for all violations| For example, developers often type: ``` secure none ``` to disable all security when developing new programs. However, use this with care. Do not run (or do) any programs other than those that you trust. Another example is: ``` secure quit ``` the program will quit immediately if any security violation occurs. Of course, this is a little extreme, and you won't get far. You'll want to specify a block for greater control. See the next section. ''Argument as a block'' To provide more detailed security, use a block: ``` secure [ net quit file ask %./ allow ] ``` This block will: ``` disable networking (force a quit if attempted) ask for user approval for all file access, except: allow access to the local directory ``` As you can see, the security dialect consists of a block of paired values. The first value in the pair specifies what is being secured (file or net), and the second value specifies the level of security (allow, ask, throw, quit). The second value can also be a block to further specify read and write security. ''Security policies'' The security policies are: |allow |removes all READ and/or WRITE restrictions.| |ask |restricts immediate READ and/or WRITE access and prompts the user for each access attempt, requiring approval before the operation may be completed.| |throw |denies READ and/or WRITE access, throwing an error when a restricted access attempt is made.| |quit |denies READ and/or WRITE access and quits the script when restricted access is attempted.| For example, to allow all network access, but to quit on any file access: ``` secure [ net allow ;allows any net access file quit ;any file access will cause the program to quit ] ``` If a block is used instead of a security level word, it can contain pairs of security levels and access types. This lets you specify a greater level of detail about the security you require. ''Access types'' The access types allowed are: |read |controls read access.| |write |controls write, delete, and rename access.| |execute |controls execute access.| |all |controls all access.| The pairs are processed in the order they appear, with later pairs modifying the effect of earlier pairs. This permits setting one type of access without explicitly setting all others. For example: ``` secure [ net allow file [ ask all allow read quit execute ] ] ``` The above sets the security level to ask for all operations except for reading (which is allowed). This technique can also be used for individual files and directories. For example: ``` secure [ net allow file quit %source/ [ask read] %object/ [allow all] ] ``` will prompt the user if an attempt is made to read the %source directory, but it will allow all operations on the `%object` directory. Otherwise, it uses the default (quit). If no security access level is specified for either network or file access, it defaults to ASK. The current settings will not be modified if an error occurs parsing the security block argument. ''Querying security'' The secure function returns the prior security settings before the new settings were made. This is a block with the global network and file settings followed by file or directory settings. The word query can also be used to obtain the current security settings without modifying them: ``` probe secure query [file allow net allow ...] ``` Using query, you can modify the current security level by querying the current settings, modifying them, then using the secure function to set the new values. ''Securing security'' Once you have your security policies set, it's a good idea to secure the secure function to prevent modifications. This is done in the same way as other policies. For example: ``` secure [secure quit] ``` will cause your program to immediately quit if any other code tries to modify the security policies. ''User confirmation'' Note that lowering the security level produces a change security settings requestor to the user. The exception is when the REBOL session is running in quiet mode which will, instead, terminate the REBOL session. No request is generated when security levels are raised. Note that the security request includes an option to allow all access for the remainder of the scripts processing. ''Controlling security at startup'' To disable all security on startup, you can start REBOL with: ``` rebol -s args... ``` This policy allows open access for everything. You can also use the `--secure` argument to specify any other default security level on startup. ''Limiting evaluation (quota)'' You can set secure to limit interpreter evaluation. This feature allows you to restrict server scripts (such as CGI) to a specific evaluation length to prevent runaway programs. This example sets the limit to 50000 cycles, after which the program will immediately `quit` (the default behavior): ``` >> secure [eval 50000] >> loop 100000 [next "test"] <quit> ``` Also, for debugging you can use the more detailed form of secure: ``` >> secure [eval [throw 50000]] >> loop 100000 [next "test"] ** Access error: security violation: eval ** Where: loop ** Near: loop 100000 [next "test"] ``` You can continue your debugging at the console, but secure will trap again on the next evaluation sample. To disable that behavior: ``` >> secure [eval allow] ``` When tuning your program, to determine how many cycles your code needs, you can use: ``` >> stats/evals == 50403 ``` However, add to that number a good margin of error for special conditions within your code. In many cases you will want to make it ten or twenty times larger, just to be sure. A few notes: * The maximum evaluation limit is 9e18. * The evaluation limit can be set only once and cannot be reset. However, for debugging after an eval THROW exception, you can use secure to disable the trap (use: [eval allow]). * The limit is approximate. It is sampled at regular intervals (to avoid slowing down evaluation.) The sampling period is 10000 cycles, so that is the resolution of the limit. For example, if you set the limit to 1, it won't trap an error until 10000. * If the program quits, the exit code is set to 101, the same as any security termination; however, we may want to use special codes to indicate the reason for the quit. * Some types of loops are not yet checked, but we will add them. For example, PARSE cycles are not yet counted. * Time limits are not yet supported, but may be added in the future. However, the cycle limit is better for most cases, because it is CPU speed independent. ''Limiting memory'' You can set secure to limit the amount of memory allocated by your program. This feature allows you to restrict server scripts (such as CGI) to a specific memory usage to prevent runaway programs. ``` >> secure [memory 2'000'000] >> strings: [] >> loop 100000 [append strings make string! 100'000] <quit> ``` This feature works the same way as the evaluation limit described above. Read that section for more details. To determine how much memory your program has currently used: ``` >> stats == 913616 ``` The number is shown in bytes. In addition, it should be noted that the memory limit applies to actual memory consumed. Due to automatic memory allocation (garbage collection) it is possible for a program to run a indefinite amount of time on a specific amount of memory. The memory limit can be set only once and cannot be reset. However, for debugging after an eval THROW exception, you can use secure to disable the trap: ``` secure [memory allow] ```
``` select series value /part length /only /case /any /with wild /skip size /last /reverse Finds a value in the series and returns the value or series after it. Arguments: series [series! port! map! object! none!] value [any-type!] Refinements: /part - Limits the search to a given length or position length [number! series! pair!] /only - Treats a series value as only a single value /case - Characters are case-sensitive /any - Enables the * and ? wildcards /with - Allows custom wildcards wild [string!] - Specifies alternates for * and ? /skip - Treat the series as records of fixed size size [integer!] /last - Backwards from end of series /reverse - Backwards from the current position ``` See also: [[find|Functions: find]] [[switch|Functions: switch]] ''Description'' Similar to the find function, but returns the next value in the series rather than the position of the match. Returns NONE if search failed. The `/only` refinement is evaluated for a block argument and is ignored if the argument is a string. ``` blk: [red 123 green 456 blue 789] print select blk 'red 123 weather: [ "Ukiah" [clear 78 wind west at 5 MPH] "Santa Rosa" [overcast 65 wind north at 10 MPH] "Eureka" [rain 62 wind north at 15 MPH] ] probe select weather "Eureka" [rain 62 wind north at 15 MPH] ```
``` series? value ``` Return TRUE if value is any type of series. Arguments: ``` value [any-type!] ``` See also: [[type?|Functions: type?]] [[string?|Functions: string?]] [[email?|Functions: email?]] [[file?|Functions: file?]] [[url?|Functions: url?]] [[issue?|Functions: issue?]] [[tuple?|Functions: tuple?]] [[block?|Functions: block?]] [[paren?|Functions: paren?]] Description Returns FALSE for all other values. ``` print series? "string" true ``` ``` print series? [1 2 3] true ``` ``` print series? 1234 false ```
``` set word value /any /pad Sets a word, path, block of words, or object to specified value(s). Arguments: word [any-word! any-path! block! object!] - Word, block of words, path, or object to be set value [any-type!] - Value or block of values Refinements: /any - Allows setting words to any value, including unset /pad - For objects, if block is too short, remaining words are set to NONE ``` See also: [[get|Functions: get]] [[in|Functions: in]] [[value?|Functions: value?]] [[unset|Functions: unset]] [[protect|Functions: protect]] [[unprotect|Functions: unprotect]] ''Description'' If the first argument is a block of words and the value is not a block, all of the words in the block will be set to the specified value. If the value is a block, then each of the words in the first block will be set to the respective values in the second block. If there are not enough values in the second block, the remaining words will be set to NONE The `/ANY` refinement allows words to be set any datatype including those such as UNSET! that are not normally allowed. This is useful in situations where all values must be handled. ``` set 'test 1234 print test 1234 set [a b] 123 print a 123 print b 123 set [d e] [1 2] print d 1 print e 2 ``` You can also use set-word! within the set function: ``` set [a: b:] [1 2] ``` This is useful if you use the funct function, which auto-detects local variables that use the [[set-word|Functions: set-word?]] notation.
``` set-path? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[make|Functions: make]] ''Description'' Returns FALSE for all other values. ``` if set-path? first [a/b/c: 10] [print "Path found"] Path found ```
``` set-word? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns FALSE for all other values. ``` if set-word? first [word: 10] [print "it will be set"] it will be set ```
``` seventh value Returns the seventh value of a series. Arguments: value ``` See also: [[first|Functions: first]] [[second|Functions: second]] [[third|Functions: third]] [[pick|Functions: pick]] ''Description'' See the FIRST function for examples. An error will occur if no value is found. Use the PICK function to avoid this error.
``` shift value bits /logical Shifts an integer left or right by a number of bits. Arguments: value [integer!] bits [integer!] - Positive for left shift, negative for right shift Refinements: /logical - Logical shift (sign bit ignored) ``` ''Description'' Supports right or left bits shifts on integers.
''Description'' This is a low-level View function that is used to display or update a face. The face being displayed must be part of a pane that is part of a window display. The SHOW function is called frequently to update the display of a face after changes have been made. If the face contains a pane of sub-faces, all of those faces will be redisplayed. If you attempt to show a face and nothing happens, make sure that the face is part of the display hierarchy. That is, the face must be present in the pane list of another face that is being displayed. For example, if you modify any of the attributes of a face, you call the SHOW function to display the change. The code below shows this: ``` view layout [ bx: box 100x24 black button "Red" [bx/color: red show bx] button "Green" [bx/color: green show bx] ] ``` The example below creates a layout face and then removes faces from its pane. The SHOW function is called each time to refresh the face and display what has happened. ``` out: layout [ h1 "Show Example" t1: text "Text 1" t2: text "Text 2" ] view/new out wait 1 remove find out/pane t2 show out wait 1 remove find out/pane t1 show out wait 1 append out/pane t2 show out wait 1 unview ```
``` sign? number Returns sign of number as 1, 0, or -1 (to use as multiplier). Arguments: number [number! money! time!] ``` See also: [[abs|Functions: abs]] [[negate|Functions: negate]] ''Description'' The SIGN? function returns a positive, zero, or negative integer based on the sign of its argument. ``` print sign? 1000 1 print sign? 0 0 print sign? -1000 -1 ``` The sign is returned as an integer to allow it to be used as a multiplication term within an expression: ``` val: -5 new: 2000 * sign? val print new -2000 size: 20 num: -30 if size > 10 [xy: 10x20 * sign? num] print xy -10x-20 ```
``` sine value /radians Returns the trigonometric sine. Arguments: value [number!] - In degrees by default Refinements: /radians - Value is specified in radians ``` See also: [[arccosine|Functions: arccosine]] [[arcsine|Functions: arcsine]] [[arctangent|Functions: arctangent]] [[cosine|Functions: arccosine]] [[tangent|Functions: arctangent]] ''Description'' Ratio between the length of the opposite side to the length of the hypotenuse of a right triangle. ``` print sine 90 1.0 print (sine 45) = (cosine 45) true print sine/radians pi 0.0 ```
``` sixth value Returns the sixth value of a series. Arguments: value ``` See also: [[first|Functions: first]] [[second|Functions: second]] [[third|Functions: third]] [[pick|Functions: pick]] ''Description'' See the FIRST function for examples. An error will occur if no value is found. Use the PICK function to avoid this error.
''Description'' Returns the xy size of face text. This function can be used to determine the size of text in advance, allowing code to make adjustments before displaying the text. Note that the face does not need to be shown for this function to work correctly. ``` f: make gob! [text: "Hello there"] size-text f ``` Note also the size of the text depends on the font used for the text.
``` size? target Returns the size of a file. Arguments: target [file! url!] ``` See also: [[modified?|Functions: modified?]] [[exists?|Functions: exists?]] ''Description'' If the file or URL is a directory, it returns the number of entries in the directory. ``` print size? %file.txt none ```
``` skip series offset Returns the series forward or backward from the current position. Arguments: series [series! gob! port!] offset [number! logic! pair!] ``` See also: [[at|Functions: at]] [[ index?|Functions: index?]] [[next|Functions: next]] [[back|Functions: back]] ''Description'' For example, SKIP series 1 is the same as NEXT. If skip attempts to move beyond the [[head|Functions: head]] or [[tail|Functions: tail]] it will be stopped at the [[head|Functions: head]] or [[tail|Functions: tail]]. ``` str: "REBOL" print skip str 3 OL blk: [11 22 33 44 55] print skip blk 3 44 55 ```
``` sort series /case /skip size /compare comparator /part length /all /reverse Sorts a series. (Modifies) Arguments: series [series!] Refinements: /case - Case sensitive sort /skip - Treat the series as records of fixed size size [integer!] - Size of each record /compare - Comparator offset, block or function comparator [integer! block! any-function!] /part - Sort only part of a series length [number! series!] - Length of series to sort /all - Compare all fields /reverse - Reverse sort order ``` See also: [[append|Functions: append]] [[change|Functions: change]] [[clear|Functions: clear]] [[insert|Functions: insert]] [[remove|Functions: remove]] ''Description'' Sorting will modify any type of series passed as the argument: ``` blk: [799 34 12 934 -24 0] sort blk print blk -24 0 12 34 799 934 print sort "dbeca" "abcde" ``` Normally sorting is not sensitive to character cases: ``` sort ["Fred" "fred" "FRED"] ["fred" "FRED" "Fred"] ``` But you can make it sensitive with the /CASE refinement: ``` sort/case ["Fred" "fred" "FRED"] ["FRED" "Fred" "fred"] ``` Editor note: Sort bug here causes camel-case strings to be sorted incorrectly. When using the `/SKIP` refinement, you can treat the series as a set of records of a fixed size. Here we sort by a "name" column, while "age" is skipped: ``` name-ages: [ "Larry" 45 "Curly" 50 "Mo" 42 ] print sort/skip name-ages 2 Curly 50 Larry 45 Mo 42 ``` A `/COMPARE` function can be specified to perform the comparison. This allows you to change the ordering of the SORT: ``` names: [ "Larry" "Curly" "Mo" ] print sort/compare names func [a b] [a < b] Curly Larry Mo ``` The `/ALL` refinement will force the entire record to be passed as a series to the compare function. This is useful if you need to compare one or more fields of a record while also doing a skip operation. Editor note: Need a good working example. This may not be possible until remaining SORT bugs are fixed. When sorting [[pair!|Datatypes: Pair!]] data (points and area sizes), the y coordinate is dominant. This is preferred to support the y sorting used by various graphics algorithms. ``` probe sort [1x2 2x1 0x0 1x0 0x1 1x1] [0x0 1x0 0x1 1x1 2x1 1x2] ```
``` source word Prints the source code for a word. Arguments: word [word! path!] ``` See also: [[what|Functions: what]] [[help|Functions: help]] [[?|Functions: ?]] [[??|Functions: ??]] [[trace|Functions: trace]] ''Description'' The `source` function displays the source code for REBOL defined functions. For example, type: ``` source join ``` The source to the [[join|Functions: join]] function will be returned: ``` join: make function! [[ "Concatenates values." value "Base value" rest "Value or block of values" ][ value: either series? :value [copy value] [form :value] repend value :rest ]] ``` REBOL defined functions include the mezzanine functions (built-in interpreted functions) and user defined functions. Native functions have no source to display.
``` spec-of value Returns a copy of the spec of a function or module Arguments: value ``` See also: [[body-of|Functions: body-of]] [[reflect|Functions: reflect]] [[title-of|Functions: title-of]] [[types-of|Functions: types-of]] [[values-of|Functions: values-of]] [[words-of|Functions: words-of]] ''Description'' Description is needed.
``` split series dlm /into ``` Split a series into pieces; fixed or variable size, fixed number, or at delimiters ``` Arguments: series [series!] - The series to split dlm [block! integer! char! bitset! any-string!] - Split size, delimiter(s), or rule(s). Refinements: /into - If dlm is an integer, split into n pieces, rather than pieces of length n. ``` See also: [[extract|Functions: extract]] [[parse|Functions: parse]] ''Contents'' * Description * Split into equal segments: * Split into N segments: * Split into uneven segments: * Simple delimiter splitting: ''Description'' The [[split|Functions: split]] function is used to divide a series into subcomponents. It provides several ways to specify how you want the split done. ''Split into equal segments:'' Given an integer as the dlm parameter, split will break the series up into pieces of that size. ``` probe split "1234567812345678" 4 ["1234" "5678" "1234" "5678"] ["1234" "5678" "1234" "5678"] ``` If the series can't be evenly split, the last value will be shorter. ``` probe split "1234567812345678" 3 ["123" "456" "781" "234" "567" "8"] ["123" "456" "781" "234" "567" "8"] ``` ``` probe split "1234567812345678" 5 ["12345" "67812" "34567" "8"] ["12345" "67812" "34567" "8"] ``` ''Split into N segments:'' Given an integer as dlm, and using the `/into` refinement, it breaks the series into n pieces, rather than pieces of length n. ``` probe split/into [1 2 3 4 5 6] 2 [[1 2 3] [4 5 6]] [[1 2 3] [4 5 6]] ``` ``` probe split/into "1234567812345678" 2 ["12345678" "12345678"] ["12345678" "12345678"] ``` If the series can't be evenly split, the last value will be longer. ``` probe split/into "1234567812345678" 3 ["12345" "67812" "345678"] ["12345" "67812" "345678"] ``` ``` probe split/into "1234567812345678" 5 ["123" "456" "781" "234" "5678"] ["123" "456" "781" "234" "5678"] ``` ''Split into uneven segments:'' If dlm is a block containing only integer values, those values determine the size of each piece returned. That is, each piece can be a different size. ``` probe split [1 2 3 4 5 6] [2 1 3] [[1 2] [3] [4 5 6]] [[1 2] [3] [4 5 6]] ``` ``` probe split "1234567812345678" [4 4 2 2 1 1 1 1] ["1234" "5678" "12" "34" "5" "6" "7" "8"] ["1234" "5678" "12" "34" "5" "6" "7" "8"] ``` ``` probe split first [(1 2 3 4 5 6 7 8 9)] 3 [[1 2 3] [4 5 6] [7 8 9]] [(1 2 3) (4 5 6) (7 8 9)] ``` ``` probe split #{0102030405060708090A} [4 3 1 2] [#{01020304} #{050607} #{08} #{090A}] [#{01020304} #{050607} #{08} #{090A}] ``` If the total of the dlm sizes is less than the length of the series, the extra data will be ignored. ``` probe split [1 2 3 4 5 6] [2 1] [[1 2] [3]] [[1 2] [3]] ``` If you have extra dlm sizes after the series data is exhausted, you will get empty values. ``` probe split [1 2 3 4 5 6] [2 1 3 5] [[1 2] [3] [4 5 6] []] [[1 2] [3] [4 5 6] []] ``` If the last dlm size would return more data than the series contains, it returns all the remaining series data, and no more. ``` probe split [1 2 3 4 5 6] [2 1 6] [[1 2] [3] [4 5 6]] [[1 2] [3] [4 5 6]] ``` Negative values can be used to skip in the series without returning that part: ``` probe split [1 2 3 4 5 6] [2 -2 2] [[1 2] [5 6]] [[1 2] [5 6]] ``` ''Simple delimiter splitting:'' Char or any-string values can be used for simple splitting, much as you would with `[bad-link:functions/parseall.txt]`, but with different behavior for strings that have embedded quotes. ``` probe split "abc,de,fghi,jk" #"," ["abc" "de" "fghi" "j"] ["abc" "de" "fghi" "jk"] ``` ``` probe split "abc<br>de<br>fghi<br>jk" <br> ["abc" "de" "fghi" "j"] ["abc" "de" "fghi" "jk"] ``` If you want to split at more than one character value, you can use a `[bad-link:functions/charsetbitset.txt]`. ``` probe split "abc|de/fghi:jk" charset "|/:" ["abc" "de" "fghi" "j"] ["abc" "de" "fghi" "jk"] ``` Note that for greater control, you can use simple parse rules: ``` probe split "abc de fghi jk" [some #" "] ["abc" "de" "fghi" "j"] ["abc" "de" "fghi" "jk"] ```
``` split-path target Splits and returns directory path and file as a block. Arguments: target [file! url! string!] ``` See also: [[clean-path|Functions: clean-path]] [[suffix?|Functions: suffix?]] ''Description'' Returns a block consisting of two elements, the path and the file. Can be used on URLs and files alike. ``` probe split-path %tests/math/add.r [%tests/math/ %add.r] set [path file] split-path http://www.rebol.com/graphics/logo.gif print path http://www.rebol.com/graphics/ print file logo.gif ```
``` square-root value Returns the square root of a number. Arguments: value [number!] ``` See also: [[exp|Functions: exp]] [[log-10|Functions: log-10]] [[log-2|Functions: log-2]] [[log-e|Functions: log-e]] [[power|Functions: power]] ''Description'' Returns the square-root of the number provided. If the number is negative, an error will occur (which you can trap with the TRY function). ``` print square-root 4 2.0 print square-root 2 1.414213562373095 ```
``` stack offset /block /word /func /args /size /depth /limit Returns stack backtrace or other values. Arguments: offset [integer!] - Relative backward offset Refinements: /block - Block evaluation position /word - Function or object name, if known /func - Function value /args - Block of args (may be modified) /size - Current stack size (in value units) /depth - Stack depth (frames) /limit - Stack bounds (auto expanding) ``` Note this special requirement: <<< Security In order to use stack, you must have secure debug enabled. <<< ''Description'' No description provided.
``` stats /show /profile /timer /evals Provides status and statistics information about the interpreter. Refinements: /show - Print formatted results to console /profile - Returns profiler object /timer - High resolution time difference from start /evals - Number of values evaluated by interpreter ``` See also: [[help|Functions: help]] [[trace|Functions: trace]] ''Description'' The STATS function returns a wide range of useful REBOL system statistics, including information about memory usage, interpreter cycles, and more. If no refinement is provide, STATS returns the amount of memory that it is using. This value must be computed from tables. The `/pools` refinement returns information about the memory pools that REBOL uses for managing its memory. The `/types` refinement provides a summary of the number of each datatype currently allocated by the system. ``` foreach [type num] stats/types [ print [type num] ] ``` The `/series` shows the number of series values, both string and block oriented, as free space, etc. The `/frames` provides the number of context frames used for objects and functions. The `/recycle` option summarizes garbage collection information. The `/evals` provides counters for the number of interpreter cycles, functions invoked, and blocks evaluated. The `/clear` refinement can be used with the `/evals` refinement to clear its counters. ``` stats/evals/clear loop 100 [print "hello"] print stats/evals ```
``` strict-equal? value1 value2 Returns TRUE if the values are strictly equal. Arguments: value1 value2 ``` See also: [[==|Functions: ==]] [[=|Functions: =]] [[<>|Functions: <>]] [[strict-not-equal?|Functions: strict-not-equal?]] ''Description'' Strict equality requires the values to not differ by datatype (so 1 would not be equal to 1.0) nor by character casing (so "abc" would not be equal to "ABC"). ``` print strict-equal? 123 123 true print strict-equal? "abc" "ABC" false ```
``` strict-not-equal? value1 value2 Returns TRUE if the values are not strictly equal. Arguments: value1 value2 ``` See also: [[!==|Functions: !==]] [[<>|Functions: <>]] [[=|Functions: =]] [[==|Functions: ==]] ''Description'' Returns FALSE if the values neither differ by datatype (so 1 would not be equal to 1.0) nor by character casing (so "abc" would not be equal to "ABC"). ``` print strict-not-equal? 124 123 true print strict-not-equal? 12-sep-98 10:30 true ```
``` string? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. ``` print string? "with all things considered" true print string? 123 false ```
``` struct? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns TRUE if the value is a STRUCT datatype.
``` subtract value1 value2 ``` Returns the second value subtracted from the first. ``` Arguments: value1 [scalar! date!] value2 [scalar! date!] ``` See also: [[-|Functions: -]] [[+|Functions: +]] [[add|Functions: add]] [[absolute|Functions: absolute]] Description Note: The [[+|Functions: +]] operator is a special infix form for this function. Many different datatypes support subtraction. Here are just a few: ``` print subtract 123 1 122 ``` ``` print subtract 1.2.3.4 1.0.3.0 0.2.0.4 ``` ``` print subtract 12:00 11:00 1:00 ``` ``` print subtract 1-Jan-2000 1 31-Dec-1999 ``` When subtracting values of different datatypes, the values must be compatible. Auto conversion of the values will occur into the datatype that has the most expansive representation. For example an integer subtracted from a decimal will produce a decimal.
``` suffix? path Return the file suffix of a filename or url. Else, NONE. Arguments: path [file! url! string!] ``` See also: [[find|Functions: find]] [[split-path|Functions: split-path]] ''Description'' The SUFFIX? function can be used to obtain the file extention (e.g. .exe, .txt, .jpg, etc.) that is part of a filename. ``` print suffix? %document.txt .txt print suffix? %program.exe .exe print suffix? %dir/path/doc.txt .txt print suffix? %file.type.r .r print suffix? http://www.rebol.com/doc.txt .txt ``` If there is no suffix, a NONE is returned: ``` print suffix? %filename none ``` The suffix function can be used with any string datatype, but always returns a FILE! datatype if the suffix was found. ``` print type? suffix? %file.txt file! print type? suffix? "file.txt" file! print type? suffix? http://www.rebol.com/file.txt file! ``` This was done to allow code such as: ``` url: http://www.rebol.com/docs.html if find [%.txt %.html %.htm %.doc] suffix? url [ print [url "is a document file."] ] http://www.rebol.com/docs.html is a document file. ```
``` swap series1 series2 Swaps elements of a series. (Modifies) Arguments: series1 [series! gob!] series2 [series! gob!] ``` ''Description'' Description is needed.
``` switch value cases /default case /all Selects a choice and evaluates the block that follows it. Arguments: value - Target value cases [block!] - Block of cases to check Refinements: /default case - Default case if no others found /all - Evaluate all matches (not just first one) ``` See also: [[case|Functions: case]] [[select|Functions: select]] [[find|Functions: find]] ''Description'' The switch function selects the block for a given choice and evaluates it. For example: ``` switch 22 [ 11 [print "here"] 22 [print "there"] ] there ``` This function is equivalent to writing a select like this: ``` do select [ 11 [print "here"] 22 [print "there"] ] 22 ``` ''Variety of Datatypes'' The selection choices can be of any datatype. Here are some examples: ``` file: %user.r switch file [ %user.r [print "here"] %rebol.r [print "everywhere"] %file.r [print "there"] ] here url: ftp://ftp.rebol.org switch url [ http://www.rebol.com [print "here"] http://www.cnet.com [print "there"] ftp://ftp.rebol.org [print "everywhere"] ] everywhere tag: <title> print switch html [ <pre> ["preformatted text"] <title> ["page title"] <li> ["bulleted list item"] ] page title ``` ''Cases Not Evaluated'' It's very important to note that the choices are not evaluated (think of them as constants.) This allows the choices to be words, as shown below. If you need evaluation of the case values, use the case function instead. ``` person: 'mom switch person [ dad [print "here"] mom [print "there"] kid [print "everywhere"] ] there ``` This most often becomes important when you want to switch based on a datatype value. You must be sure to use type? with a /word refinement: ``` val: 123 switch type?/word [ integer! [print "it's integer"] decimal! [print "it's decimal"] date! [print "it's a date"] ] it's integer ``` Here the type? function returns the word (name) of the datatype!, not the datatype's type value. Another possible approach is to evaluate the block of cases. For the example above: ``` switch type? reduce [ integer! [print "it's integer"] decimal! [print "it's decimal"] date! [print "it's a date"] ] it's integer ``` This works because words like integer! are set to their actual datatype values. ''Default Case'' You can use the `/default` refinement to specify a default case. ``` time: 14:00 switch/default time [ 8:00 [send wendy@domain.dom "Hey, get up"] 12:30 [send cindy@dom.dom "Join me for lunch."] 16:00 [send group@every.dom "Dinner anyone?"] ][ print ["Nothing done at" time] ] Nothing done at 14:00 ``` ''Return Value'' The `switch` function returns the value of the case block that it evaluated, or none otherwise. ``` car: pick [Ford Chevy Dodge] random 3 print switch car [ Ford [351 * 1.4] Chevy [454 * 5.3] Dodge [154 * 3.5] ] 491.4 ``` ''Common Problems'' The most common problem is to assume that switch evaluates your case values. It does not. This kind of code does not work: ``` item1: 100 item2: 200 n: 100 switch n [ item1 [...] item2 [...] ] ``` However, you can reduce the case block to its actual values: ``` switch n reduce [ item1 [...] item2 [...] ] ```
``` tag? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' Returns FALSE for all other values. ``` print tag? <title> true print tag? "title" false ```
``` tail series Returns the series at the position after the last value. Arguments: series [series! gob! port!] ``` See also: [[tail?|Functions: tail?]] [[head|Functions: head]] [[head?|Functions: head?]] ''Description'' Access to the `tail` allows insertion at the end of a series (because insertion always occurs before the specified element). ``` blk: copy [11 22 33] insert tail blk [44 55 66] print blk 11 22 33 44 55 66 ```
``` tail? series Returns TRUE if empty, or for series, if index is at or beyond its tail. Arguments: series [series! gob! port! bitset! map!] ``` See also: [[empty?|Functions: empty?]] [[tail|Functions: tail]] [[head|Functions: head]] [[head?|Functions: head?]] ''Description'' This function is the best way to detect the end of a series while moving through it. ``` print tail? "string" false print tail? tail "string" true str: "Ok" print tail? tail str true print tail? next next str true items: [oven sink stove blender] while [not tail? items] [ print first items items: next items ] blender blk: [1 2] print tail? tail blk true print tail? next next blk true ```
``` take value /part length /deep /last Copies and removes from series. (Modifies) Arguments: value [series! port! gob! none!] Refinements: /part - Limits to a given length or position length [number! series! pair!] /deep - Also copies series values within the block /last - Take it from the tail end ``` ''Description'' The `take` function removes a value from a series and returns it as the result. It's a useful combination of pick with remove. For example, used on blocks: ``` data: [a b c d] take data a probe data [b c d] Used on strings: str: "abcd" take str #"a" probe str "bcd" ``` ''For Queues and Stacks'' The take function is quite useful for making queues and stacks. An example queue is implemented as first in first out (FIFO) block. New values are added with append and removed with take. ``` data: make block! 10 append data 1 append data 2 append data 3 take data 1 take data 2 ``` An example stack is implemented as last in first out (LIFO). The difference is to use the `/last` refinement with take. ``` data: make block! 10 append data 1 append data 2 append data 3 take/last data 3 take/last data 2 ``` The data queued and stacked above can be any REBOL values, including string, functions, objects or whatever.
``` tangent value /radians Returns the trigonometric tangent. Arguments: value [number!] - In degrees by default Refinements: /radians - Value is specified in radians ``` See also: [[arccosine|Functions: arccosine]] [[arcsine|Functions: arcsine]] [[arctangent|Functions: arctangent]] [[cosine|Functions: cosine]] [[tangent|Functions: tangent]] ''Description'' Ratio between the length of the opposite side to the length of the adjacent side of a right triangle. ``` print tangent 30 0.5773502691896257 print tangent/radians 2 * pi 0.0 ```
``` task spec body Creates a task. Arguments: spec [block!] - Name or spec block body [block!] - The body block of the task ``` ''Description'' Description is needed.
task? value Returns TRUE if it is this type. Arguments: value [any-type!] Description No description provided.
``` tenth value Returns the tenth value of a series. Arguments: value ``` See also: [[first|Functions: first]] [[second|Functions: second]] [[third|Functions: third]] [[pick|Functions: pick]] ''Description'' See the FIRST function for examples. An error will occur if no value is found. Use the PICK function to avoid this error.
``` third value Returns the third value of a series. Arguments: value ``` See also: [[first|Functions: first]] [[second|Functions: second]] [[fourth|Functions: fourth]] [[fifth|Functions: fifth]] [[pick|Functions: pick]] ''Description'' An error will occur if no value is found. Use the PICK function to avoid this error. ``` print third "REBOL" B print third [11 22 33 44 55 66] 33 print third 12-jun-1999 12 print third 199.4.80.1 80 print third 12:34:56.78 56.78 ```
``` throw value /name word Throws control back to a previous catch. Arguments: value [any-type!] - Value returned from catch Refinements: /name - Throws to a named catch word [word!] ``` See also: [[catch|Functions: catch]] [[return|Functions: return]] [[exit|Functions: exit]] ''Description'' CATCH and THROW go together. They provide a method of exiting from a block without evaluating the rest of the block. To use it, provide CATCH with a block to evaluate. If within that block a THROW is evaluated, the script will return from the CATCH at that point. The result of the CATCH will be the value that was passed as the argument to the THROW. When using multiple CATCH functions, provide them with a name to identify which one will CATCH which THROW. ``` print catch [ if exists? %file.txt [throw "Doc file!"] ] none ```
``` time? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type? |Functions: type?]] ''Description'' Returns FALSE for all other values. ``` print time? 12:00 true print time? 123 false ```
``` title-of value Returns a copy of the title of a function Arguments: value ``` See also: [[body-of|Functions: body-of]] [[reflect|Functions: reflect]] [[spec-of|Functions: spec-of]] [[types-of|Functions: types-of]] [[values-of|Functions: values-of]] [[words-of|Functions: words-of]] ''Description'' No description provided.
``` to type spec Converts to a specified datatype. Arguments: type [any-type!] - The datatype or example value spec [any-type!] - The attributes of the new value ``` See also: [[make |Functions: make]] ''Description'' Every datatype provides a TO method to allow conversions from other datatypes. The [[to-binary|Functions: to-binary]], [[to-block|Functions: to-block]], and all other to- functions are mezzanine functions that are based on this TO function. Here are a few examples: ``` probe to file! "test.r" %test.r probe to path! [a b c] a/b/c ``` The TO function lets the target datatype be specified as an argument, allowing you to write code such as: ``` flag: true value: to either flag [integer!][decimal!] "123" print value 123 ``` The conversions that are allowed depend on the specific datatype. Some datatypes allow special conversions, such as: ``` print to integer! false 0 print to integer! true 1 print to logic! 1 true print to time! 600 ; # of seconds 0:10 ```
``` to-action value Converts to action! value. Arguments: value ``` ''Description'' No description provided.
``` to-binary value Converts to binary! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[binary!|Datatypes: Binary!]] value made from the given value. ``` probe to-binary "123456" #{313233343536} ``` Notice, that the binary returned is not how the "actual storage" in computer memory looks. Instead, the bits are in "network order", which is, by convention, big endian: ``` to-binary 1 #{0000000000000001} ```
``` to-bitset value Converts to bitset! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[bitset!|Datatypes: Bitset!]] value made from the given value. ``` probe to-bitset [#"a" - #"z" #"A" - #"Z"] make bitset! #{00000000000000007FFFFFE07FFFFFE0} ```
``` to-block value ``` Converts to [[block!|Datatypes: Block!]] value. ``` Arguments: value ``` See also: [[to |Functions: to]] ''Description'' Returns a [[block!|Datatypes: Block!]] value made from the given value. ``` print to-block "123 10:30" 123 10:30 ```
``` to-char value Converts to char! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[char!|Datatypes: Char!]] value made from the given value. ``` print to-char "a" a print to-char 65 A ```
``` to-closure value Converts to closure! value. Arguments: value ``` ''Description'' No description provided.
``` to-datatype value Converts to datatype! value. Arguments: value ``` See also: [[make|Functions: make]] [[to|Functions: to]] ''Description'' Returns a [[datatype!|Datatypes: Datatype!]] value made from the given value. ``` probe to-datatype "REBOL" ```
``` to-date value Converts to date! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[date!|Datatypes: Date!]] value made from the given value. ``` print to-date "12-April-1999" 12-Apr-1999 ```
``` to-decimal value Converts to decimal! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[decimal!|Datatypes: Decimal!]] value made from the given value. ``` print to-decimal 12.3 12.3 ```
``` to-email value Converts to email! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns an [[email!|Datatypes: Email!]] value made from the given value. ``` print to-email [luke rebol.com] lukerebol.com ```
``` to-end value Converts to end! value. Arguments: value ``` ''Description'' No description provided.
``` to-error value Converts to error! value. Arguments: value ``` See also: [[make|Functions: make]] [[to|Functions: to]] ''Description'' Returns an [[error!|Datatypes: Error!]] value made from the given value. ``` probe disarm try [to-error "Oops! My error."] make object! [ code: 308 type: 'Script id: 'cannot-use arg1: 'to arg2: unset! arg3: none near: [to error! :value] where: [to to-error try do attempt if emit parse foreach catch if either if do begin do] ] ``` <<< Note that this differs from TO and MAKE in that you have to wrap the call in a TRY block to catch the error it makes. <<<
``` to-event value Converts to event! value. Arguments: value ``` ''Description'' No description provided.
``` to-file value Converts to file! value. Arguments: value ``` See also: [[to|Functions: to]] Description Returns a [[file!|Datatypes: File!]] value made from the given value. ``` print to-file ask "What file would you like to create? " test ```
``` to-frame value Converts to frame! value. Arguments: value ``` ''Description'' No description provided.
``` to-function value Converts to function! value. Arguments: value ``` ''Description'' No description provided.
``` to-get-path value Converts to get-path! value. Arguments: value ``` ''Description'' No description provided.
``` to-get-word value Converts to get-word! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[get-word!|Datatypes: Get-word!]] value made from the given value. ``` probe to-get-word "test" :test ```
``` to-gob value Converts to gob! value. Arguments: value ``` ''Description'' No description provided.
``` to-handle value Converts to handle! value. Arguments: value ``` ''Description'' No description provided.
``` to-hex value /size len Converts a numeric value to a hex issue! datatype (with leading #). Arguments: value [integer! tuple!] - Value to be converted Refinements: /size - Specify number of hex digits in result len [integer!] ``` See also: [[to-integer |Functions: to-integer]] ''Description'' The TO-HEX function provides an easy way to convert an integer to a hexidecimal value. ``` print to-hex 123 000000000000007B ``` The value returned is a string of the ISSUE datatype (not the BINARY datatype). This allows you to convert hex values back to integers: ``` print to-integer #7B 123 ``` Note: To convert HTML hex color values (like #80FF80) to REBOL color values, it is easier to do the conversion to binary and then use a base 16 encoding: ``` to-html-color: func [color [tuple!]] [ to-issue enbase/base to-binary color 16 ] print to-html-color 255.155.50 FF9B32 ``` The TO-ISSUE function is just used to add the # to it. To convert from an HTML color back to a REBOL color tuple, you can use this: ``` to-rebol-color: func [color [issue!]] [ to-tuple debase/base color 16 ] to-rebol-color #FF9B32 ``` If the HTML color value is a string, convert it to an issue first. The function below will work for strings and issues: ``` to-rebol-color2: func [color [string! issue!]] [ if string? color [ if find/match color "#" [color: next color] color: to-issue color ] to-tuple debase/base color 16 ] to-rebol-color2 "#FF9B32" ```
``` to-image value Converts to image! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' This is a special conversion function that is used for converting a FACE object (such as those created by the layout function) into an image bitmap in memory. For example, the code below converts the OUT layout to a bitmap image, then writes it out as a PNG file: ``` out: layout [ h2 "Title" field button "Done" ] image: to-image out save/png %test-image.png image ``` This function provides a useful way to save REBOL generated images for use in other programs or web pages (which also allows you to print the images). For example, you can display the image above in a web browser with this code: ``` write %test-page.html trim/auto { <html><body> <h2>Image:</h2> <img src="test-image.png"> </body></html> } browse %test-page.html write ```
``` to-integer value Converts to integer! value. Arguments: value ``` See also: [[to|Functions: to]] [[to-hex|Functions: to-hex]] ''Description'' Returns an [[integer!|Datatypes: Integer!]] value made from the given value. ``` print to-integer "123" 123 print to-integer 123.9 123 print to-integer #"A" ; convert to the character value 65 print to-integer #102030 ; convert hex value (see to-hex for info) 1056816 ```
``` to-issue value ``` Converts to [[issue!|Datatypes: Issue!]] value. ``` Arguments: value ``` See also: [[to|Functions: to]] [[to-hex|Functions: to-hex]] ''Description'' Returns an issue! value made from the given value. ``` print to-issue "1234-56-7890" 1234-56-7890 ``` To convert HTML RGB color values (that look like #000000), see the [[to-hex|Functions: to-hex]] function.
``` to-library value Converts to library! value. Arguments: value ``` See also: [[make|Functions: make]] [[to|Functions: to]] [[load|Functions: load]] ''Description'' Returns a [[library|Datatypes: Library!]] value made from the given value. ``` probe to-library %kernel32.dll none ```
``` to-lit-path value Converts to lit-path! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[lit-path!|Datatypes: Lit-path!]] value made from the given value. ``` probe to-lit-path [a b c] 'a/b/c ```
``` to-lit-word value Converts to lit-word! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[Datatypes: Lit-word!]] value made from the given value. ``` probe to-lit-word "test" test ```
``` to-local-file path /full Converts a REBOL file path to the local system file path. Arguments: path [file! string!] Refinements: /full - Prepends current dir for full path (for relative paths only) ``` See also: [[to-rebol-file|Functions: to-rebol-file]] ''Description'' This function provides a way to convert standard, system independent REBOL file formats into the file format used by the local operating system. ``` probe to-local-file %/c/temp "c:\temp" probe to-local-file what-dir "C:\REBOL\3.0\docs\scripts\" ``` <<< Note that the format of the file path depends on your local system. Be careful how you use this function across systems. <<<
``` to-logic value Converts to logic! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a logic! value made from the given value. ``` print to-logic 1 print to-logic 0 false ```
``` to-map value Converts to map! value. Arguments: value ``` ''Description'' No description provided.
``` to-module value Converts to module! value. Arguments: value ``` ''Description'' No description provided.
``` to-money value Converts to money! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[money!|Datatypes: Money!]] value made from the given value. ``` print to-money 123.4 $123.4000000000000000 print to-money [AUS 123.4] ```
``` to-native value Converts to native! value. Arguments: value ``` ''Description'' No description provided.
``` to-none value Converts to none! value. Arguments: value ``` See also: [[make|Functions: make]] [[to|Functions: to]] ''Description'' Returns a [[none!|Datatypes: None!]] value made from the given value. ``` probe to-none "REBOL" none ``` This function is not of significant use. It is automatically generated by the system for reasons of completion.
``` to-object value Converts to object! value. Arguments: value ``` ''Description'' No description provided.
``` to-op value Converts to op! value. Arguments: value ``` ''Description'' No description provided.
``` to-pair value Converts to pair! value. Arguments: value ``` See also: [[to|Functions: to]] [[as-pair|Functions: as-pair]] [[pair?|Functions: pair?]] ''Description'' Returns a [[pair?|Functions: pair?]] value made from the given value. ``` print to-pair [120 50] x: 100 y: 80 print to-pair reduce [x y] ``` This last line is done so often that the AS-PAIR function was created. See the PAIR! word for more detail.
``` to-paren value Converts to paren! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[paren!|Datatypes: Paren!]] value made from the given value. ``` print to-paren "123 456" 123 456 ```
``` to-path value Converts to path! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[path!|Datatypes: Path!]] value made from the given value. ``` colors: make object! [reds: ["maroon" "brick" "sunset"]] p-reds: to-path [colors reds] print form :p-reds colors/reds print p-reds colors/reds insert tail p-reds "bright" print colors/reds maroon brick sunset print p-reds colors/reds/"bright" ```
``` to-percent value Converts to percent! value. Arguments: value ``` ''Description'' No description provided.
``` to-port value Converts to port! value. Arguments: value ``` See also: [[make|Functions: make]] [[to|Functions: to]] ''Description'' Returns a [[port!|Datatypes: Port!]] value made from the given value. ``` probe to-port [scheme: 'checksum] ```
``` to-rebcode value Converts to rebcode! value. Arguments: value ``` ''Description'' No description provided.
``` to-rebol-file path Converts a local system file path to a REBOL file path. Arguments: path [file! string!] ``` See also: [[to-local-file|Functions: to-local-file]] ''Description'' This function provides a standard way to convert local operating system files into REBOL's standard machine independent format. ``` probe to-rebol-file "c:\temp" %/c/temp probe to-rebol-file "e:\program files\rebol" %/e/program%20files/rebol ``` <<< Note that the format of the file path depends on your local system. Be careful how you use this function across systems. <<<
``` to-refinement value Converts to refinement! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[refinement!|Datatypes: Refinement!]] value made from the given value. ``` probe to-refinement 'REBOL /REBOL ```
``` to-relative-file file /no-copy /as-rebol /as-local Returns the relative portion of a file if in a subdirectory, or the original if not. Arguments: file [file! string!] - File to check (local if string!) Refinements: /no-copy - Don't copy, just reference /as-rebol - Convert to REBOL-style filename if not /as-local - Convert to local-style filename if not ``` ''Description'' No description provided.
''Description'' Does not exist in REBOL 3. See [[to-library|Functions: to-library]].
``` to-set-path value Converts to set-path! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[set-path!|Datatypes: Set-path!]] value made from the given value. ``` colors: make object! [blues: ["sky" "sea" "midnight"]] ps-blues: to-set-path [colors blues] print form :ps-blues colors/blues: print ps-blues colors/blues: ps-blues compose [(ps-blues) "light"] print colors/blues sky sea midnight print ps-blues colors/blues: ```
``` to-set-word value Converts to set-word! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[set-word!|Datatypes: Set-word!]] value made from the given value. ``` probe to-set-word "test" test: ```
``` to-string value Converts to string! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[string!|Datatypes: String!]] value made from the given value. ``` print to-string [123 456] 123456 ```
``` to-struct value Converts to struct! value. Arguments: value ``` ''Description'' No description provided.
``` to-tag value Converts to tag! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[tag!|Datatypes: Tag!]] value made from the given value. ``` print to-tag ";comment:" <;comment:> ```
``` to-task value Converts to task! value. Arguments: value ``` ''Description'' No description provided.
``` to-time value Converts to time! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[time!|Datatypes: Time!]] value made from the given value. ``` print to-time 75 0:01:15 ``` Integer values are interpreted as a number of seconds. A block may contain up to three values. The first two must be integers, and correspond to the hour and minute values. The third value can be an integer or decimal value, and corresponds to the number of seconds.
``` to-tuple value Converts to tuple! value. Arguments: value ``` See also: [[to|Functions: to]] [[to-hex|Functions: to-hex]] ''Description'' Returns a [[tuple!|Datatypes: Tuple!]] value made from the given value. ``` print to-tuple [12 34 56] 12.34.56 ``` To convert REBOL RGB color tuples to HTML hex color values, see the [[to-hex|Functions: to-hex]] function. Tuples can have up to 10 segments.
``` to-typeset value Converts to typeset! value. Arguments: value ``` ''Description'' No description provided.
``` to-unset value Converts to unset! value. Arguments: value ``` ''Description'' No description provided.
``` to-url value Converts to url! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[url!|Datatypes: Url!]] value made from the given value. ``` print to-url "info@rebol.com" info@rebol.com ```
``` to-utype value Converts to utype! value. Arguments: value ``` ''Description'' No description provided.
``` to-vector value Converts to vector! value. Arguments: value ``` ''Description'' No description provided.
``` to-word value Converts to word! value. Arguments: value ``` See also: [[to|Functions: to]] ''Description'' Returns a [[word!|Datatypes: Word!]] value made from the given value. ``` print to-word "test" test ```
``` trace mode /back /function Enables and disables evaluation tracing and backtrace. Arguments: mode [integer! logic!] Refinements: /back - Set mode ON to enable or integer for lines to display /function - Traces functions only (less output) ``` See also: [[echo|Functions: echo]] [[probe|Functions: probe]] [[stack|Functions: stack]] Note this special requirement: <<< Security In order to use trace, you must have secure debug properly set. You can use any of these methods to do so: * Run REBOL with -s option. * Type secure [debug allow] or put it in your rebol.r file. * Type secure none (but don't put it in your rebol.r file.) <<< ''Contents'' * Description * Understanding the format * Simple example * Larger example * Minimizing the output * Setting trace depth * Locating trace within your code * Tracing functions only * Backtrace * Example backtrace * Important notes ''Description'' The `trace` lets you watch the evaluation of your script, expression by expression. The three most common arguments to trace are shown here: ``` trace on ; turn on trace trace off ; turn off trace trace 5 ; turn on, but trace only 5 levels deep ``` Once enabled, when you evaluate an expression, you will see each step as a single line: ``` >> print 123 1: print : native! [value] 2: 123 --> print 123 <-- print == unset! ``` Understanding the format The trace format uses these formatting notations to indicate what your code is doing: |Notation |Meaning|h |(indent) |The indentation for each line indicates the depth of the code.| ``` N: ``` The index number of the value in the code block (that is to be evaluated.) ``` --> ``` Entry into a function, followed by its formal argument list. ``` <-- ``` Return from a function, followed by the value it returned `==`. ''Simple example'' To [[help|Functions: help]] understand the format, here's a description for each line in the earlier example: |Code |Meaning|h |>> |print 123| Typed into the console to evaluate. ``` 1: print : native! [value] ``` The value at block index 1 is the word print. It's value is looked up and found to be a native! function that takes value as an argument. ``` 2: 123 ``` The value at block index 2 is the integer 123. ``` --> print ``` The argument is valid and the print function is entered. The --> means "enter into the function." ``` 123 ``` Output is printed. ``` <-- print == unset! ``` The print function returns, but it has no return value (it is unset.) The <-- means "return from the function." ''Larger example'' Here is a user defined function to compute the average of a block of numbers. ``` ave: func [nums [block!] /local val][ val: 0 foreach num nums [val: val + num] val / length? nums ] ``` Tracing the evaluation, you will see how each new level is indented and begins a new sequence of index numbers. Notice also the foreach loop. ``` >> ave [1 2 3] 1: ave : function! [nums /local val] 2: [1 2 3] --> ave 1: val: 2: 0 3: foreach : native! ['word data body] 5: nums : [1 2 3] 6: [val: val + num] --> foreach 1: val: 2: val : 0 3: + : op! [value1 value2] 4: num : 1 --> + <-- + == 1 1: val: 2: val : 1 3: + : op! [value1 value2] 4: num : 2 --> + <-- + == 3 1: val: 2: val : 3 3: + : op! [value1 value2] 4: num : 3 --> + <-- + == 6 <-- foreach == 6 7: val : 6 8: / : op! [value1 value2] 9: length? : action! [series] 10: nums : [1 2 3] --> length? <-- length? == 3 --> / <-- / == 2 <-- ave == 2 == 2 ``` ''Minimizing the output'' At times the trace output will be a lot more than you want. The trick becomes how to cut it down without losing the information you need.. There are three methods: * Specify a trace depth. * Locate the trace on and off lines deeper within your code. * Trace only functions, not all values. * Use the backtrace option. (see more below) ''Setting trace depth'' Using the example above, set the trace depth to 2, and run it again. You will see: ``` >> trace 2 >> ave [1 2 3] 1: ave : function! [nums /local val] 2: [1 2 3] --> ave 1: val: 2: 0 3: foreach : native! ['word data body] 5: nums : [1 2 3] 6: [val: val + num] --> foreach <-- foreach == 6 7: val : 6 8: / : op! [value1 value2] 9: length? : action! [series] 10: nums : [1 2 3] --> length? <-- length? == 3 --> / <-- / == 2 <-- ave == 2 == 2 ``` The output has been reduced. You no longer see the foreach loop operate. ''Locating trace within your code'' Most of the time you don't need to trace your entire program, just part of it. So, it is useful just to put trace in your code where you need it. Using the same example as above: ``` ave: func [nums [block!] /local val][ val: 0 trace on foreach num nums [val: val + num] trace off val / length? nums ] ``` You will now see: ``` >> ave [1 2 3] <-- trace == unset! 5: foreach : native! ['word data body] 7: nums : [1 2 3] 8: [val: val + num] --> foreach 1: val: 2: val : 0 3: + : op! [value1 value2] 4: num : 1 --> + <-- + == 1 1: val: 2: val : 1 3: + : op! [value1 value2] 4: num : 2 --> + <-- + == 3 1: val: 2: val : 3 3: + : op! [value1 value2] 4: num : 3 --> + <-- + == 6 <-- foreach == 6 9: trace : native! [mode /back] 10: off : false --> trace == 2 ``` ''Tracing functions only'' With the `/function` refinement you can trace just function calls and their returns. The evaluation of each code block value is not shown, saving a few lines. ``` >> trace/function on >> ave [1 2 3] --> ave [1 2 3] . . --> foreach num [1 2 3] [val: val + num] --> + 0 1 <-- + == 1 --> + 1 2 <-- + == 3 --> + 3 3 <-- + == 6 <-- foreach == 6 --> length? [1 2 3] <-- length? == 3 --> / 6 3 <-- / == 2 <-- ave == 2 ``` In this mode, the function call lines will show the arguments passed to the functions. (A dot is used to show NONE value slots, such as those for unused refinements or local variables.) ''Backtrace'' At times it is important to know what your code was doing immediately before a crash. In such cases, you don't want to see trace output until after the crash. That is the purpose of the /back refinement: to tell trace to redirect its output to an internal buffer that you can examine later. To enable backtrace: ``` >> trace/back on ``` Then, run your code. When your crash occurs, type: ``` >> trace/back 20 ``` to see the last 20 lines (or however many lines you want to see.) You can also modify your trace depth as you would normally. For example: ``` >> trace/back on >> trace 5 ``` will only trace down five levels of code. When you are done with the backtrace, you can disable it with: ``` >> trace/back off ``` and that will also free memory used by the backtrace buffer. To use backtrace with the `/function` refinement: ``` >> trace/back/function on ``` This will also speed-up trace evaluation. ''Example backtrace'' Here is an example session: ``` >> trace/back on >> test: func [a] [if integer? a [loop a [bug]]] >> test 10 ** Script error: bug has no value ** Where: loop if test ** Near: loop a [bug] >> trace/back 10 --> if 1: loop : native! [count block] 2: a : 10 3: [bug] --> loop 1: bug : unset! **: error : Script no-value 1: trace/back 2: 20 --> trace ``` So, it's not hard to see what was going on when the script crashed. Backtrace can be quite handy when you need it. ''Important notes'' * Tracing is disabled automatically when you display the backtrace. (This prevents additional accumulation of trace information, allowing you to redisplay the buffer without interference from additional console lines.) * Backtrace will slow down your program by a factor of 20 (because for each value that is evaluated, it must store a log record). * The internal backtrace buffer is 100KB. On average, the most it will hold is 100 pages of backtrace. * Enabling normal trace will disable backtrace and delete the backtrace buffer. * Backtrace may interfere with some kinds of tracing, especially if the bug is related to a defect within the REBOL interpreter itself. * The stack function can also be used to show stack related backtrace information.
``` transcode source /next /only /error Translates UTF-8 binary source to values. Returns [value binary]. Arguments: source [binary!] - Must be Unicode UTF-8 encoded Refinements: /next - Translate next complete value (blocks as single value) /only - Translate only a single value (blocks dissected) /error - Do not throw errors - return error object as value ``` See also: [[to-block|Functions: to-block]] ''Contents'' * Description * Input * Refinements * Output ''Description'' The `transcode` function translates source code and data into the block value memory format that can be interpreted by REBOL. Input The source input to transcode must be Unicode UTF-8. This is a binary! encoded format, and should not be confused with a string!, which is a decoded in-memory indexable string. If you need to transcode a string, you must convert it to a UTF-8 binary first. This can be done with to-binary. ``` data: transcode to-binary string ``` ''Reduced efficiency'' In general, conversions to and from UTF-8 require extra time to for the Unicode conversion process. Therefore, is not a good idea to write REBOL code like TCL or PERL where computations are done on strings. Don't write code such as: ``` do append "1 +" n ``` Because you can just as easily write: ``` do append [1 +] n ``` in REBOL. ''Refinements'' Without refinements, transcode will convert the entire input string. Refinements are provided for partial translation: |`/next` |Translate the next full value. If it is a block, translate the entire block.| |`/only` |Translate the next singular value. If it is a block, translate only the first element of the block, and return it within a block.| |`/error` |Convert syntax errors to error objects and output them rather than throwing them as an error.| These refinements can be used in various ways to parse REBOL source a value at a time. ''Output'' The output from transcode is a [[block!|Datatypes: Block!]] containing two values: * The translated value, block of values, or [[error!|Datatypes: Error!]] object. * The [[binary!|Datatypes: Binary!]] source at the point where the translation ended. For example: ``` a: to-binary "a b c" #{6120622063} transcode/only a [a #{20622063}] ```
``` trim series /head /tail /auto /lines /all /with str Removes space from a string or NONE from a block or object. Arguments: series [series! object! error! module!] Refinements: /head - Removes only from the head /tail - Removes only from the tail /auto - Auto indents lines relative to first line /lines - Removes all line breaks and extra spaces /all - Removes all whitespace /with str [char! string! binary! integer!] - Same as /all, but removes characters in 'str' ``` See also: [[parse|Functions: parse]] [[remove|Functions: remove]] [[clear|Functions: clear]] ''Contents'' * Description * Details on trimming strings * TRIM on blocks * TRIM on objects ''Description'' Trim removes unwanted values, normally it trims whitespace from a [[string!|Datatypes: String!]] or [[none!|Datatypes: None!]] values from a [[block!|Datatypes: Block!]] or [[object!|Datatypes: Object!]]. Here is an example of a string: ``` str: " string " probe trim str "string" ``` Note that the str is modified. To avoid that, use copy: ``` new-str: trim copy str ``` For a [[block!|Datatypes: Block!]] : ``` trim reduce [none 'a none 'b none] [a b] ``` It removes the none! values from the block. (And it will also remove unset! values as well.) Note that the block is modified. But, in this example, reduce creates a unique copy, so the original is not effected. And for an object! : ``` trim system/options make object! [ home: %/C/Program%20Files/ path: %/C/rebol/r3/ boot: %/C/rebol/r3/view.exe binary-base: 16 decimal-digits: 15 ] ``` Because object fields cannot be removed (due to binding) the result of trim of an object is always to return a new shallow object. (The values of the object are not deep-copied or rebound.) The new object only shows fields that have actual value (not none or unset.) ''Details on trimming strings'' The default for TRIM is to remove whitespace characters (tabs and spaces) from the heads and tails of every line of a string. Empty leading and trailing lines are also trimmed. When a string includes multiple lines, the head and tail whitespace will be trimmed from each line (but not within the line): ``` str: { Now is the winter of our discontent made glorious summer by this sun of York. } probe trim str {Now is the winter of our discontent made glorious summer by this sun of York. } ``` The line terminator of the final line is preserved. As mentioned above, empty leading and trailing lines are also trimmed: ``` probe trim { Non-empty line. Non-empty line. Non-empty line. } {Non-empty line. Non-empty line. Non-empty line. } ``` Note that TRIM modifies the string in the process. ``` str: " string " trim str probe str "string" ``` TRIM does not copy the string. If that's what you want, then use TRIM with COPY to copy the string before trimming it. Several refinements to TRIM are available. To trim just the head `and/or` tail of a string you can use the `/HEAD` or `/TAIL` refinements. ``` probe trim/head " string " "string " probe trim/tail " string " " string" probe trim/head/tail " string " "string" ``` When using `/HEAD` or `/TAIL`, multiple lines are not affected: ``` probe trim/head { line 1 line 2 line 3 } {line 1 line 2 line 3 } ``` To trim just the head and tail of a multiline string, but none of its internal spacing: ``` str: { line 1 line 2 line 3 line 4 line 5 } probe trim/head/tail str {line 1 line 2 line 3 line 4 line 5} ``` If you use `TRIM/LINES` then all lines and extra spaces will be removed from the text. This is useful for word wrapping and web page kinds of applications. ``` str: { Now is the winter } probe trim/lines str "Now is^/the^/winter" ``` You can also remove /ALL space: ``` probe trim/all " Now is the winter " "Nowisthewinter" str: { Now is the winter } probe trim/all str "Nowisthewinter" ``` One of the most useful TRIM refinements is `/AUTO` which will do a "smart" trim of the indentation of text lines. This mode detects the indentation from the first line and preserves indentation for the lines to follow: ``` probe trim/auto { line 1 line 2 line 3 line 4 line 5 } {line 1 line 2 line 3 line 4 line 5 } ``` This is useful for sections of text that are embedded within code and indented to the level of the code. To trim other characters, the `/WITH` refinement is provided. It takes an additional string that specifies what characters to be removed. ``` str: {This- is- a- line.} probe trim/with str "-" "This is a line." str: {This- is- a- line.} probe trim/with str "- ." "Thisisaline" ``` ''TRIM on blocks'' When trim is used on a block!, it strips all none! values from the block: ``` trim reduce [1 2 none] [1 2] ``` Note that trim modifies the argument block. ''TRIM on objects'' When trim is used on an [[object!|Datatypes: Object!]], it will return a new object that has all [[none!|Datatypes: None!]] values removed: ``` obj: make object [arg1: 10 arg2: none] trim obj make object! [ arg1: 10 ] ```
``` true? val Returns true if an expression can be used as true. Arguments: val ``` ''Description'' No description provided.
``` try block /except code Tries to DO a block and returns its value or an error. Arguments: block [block!] Refinements: /except - On exception, evaluate this code block code [block! any-function!] ``` See also: [[attempt|Functions: attempt]] [[error?|Functions: error?]] [[do|Functions: do]] ''Description'' The `try` function evaluates a block and will capture any errors that occur during that evaluation. The purpose of try is to give your own code the opportunity to handle errors, rather than causing your program to terminate with an error message. For example, in this line: ``` try [delete %afile.txt] ``` if the file does not exist, then the error will not cause your program to terminate. ''Return Value'' The try function returns an error value if an error happened, otherwise it returns the normal result of the block. Taking the above example, we can do something special if an error happened: ``` if error? try [delete %afile.txt] [print "delete failed"] ``` or, even use the error value itself: ``` if error? err: try [delete %afile.txt] [print ["delete failed:" mold err]] ``` Sometimes you'll want to use the value that was returned: ``` either error? val: try [1 + "x"] [print "nope"] [print val] nope either error? val: try [1 + 2] [print "nope"] [print val] 3 ``` ''Exception Handling'' The `try` function is for error handling, but there are times when you may be returning error objects as values, and you cannot distinguish between an error occurring and the error value itself. This is case rare, but it does happen. For this situation the `/except` refinement is provided. If an error occurs, it will evaluate a exception handling function (or just a block). This indicates that an error exception happened (not just an error value being passed.) The example below will catch the [bad-link:errors/zero-divide.txt] error within a function. The error is passed as the argument to the exception function, and a value (zero in this case) is returned from the try function: ``` try/except [1 / 0] func [value] [?? value 0] value: make error! [ code: 400 type: 'Math id: 'zero-divide arg1: none arg2: none arg3: none near: [/ 0] where: [/ try] ] 0 ``` ''Shortcut'' The [[attempt|Functions: attempt]] function is shortcut for the common pattern where you don't care about the specific error, and mainly just want the non-error result. `data: attempt [load %data.r]` The data will be either the data or none, if it failed to load.
``` tuple? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. ``` print tuple? 1.2.3.4 true version: 0.1.0 if tuple? version [print version] 0.1.0 ```
``` type? value /word Returns a value's datatype. Arguments: value [any-type!] Refinements: /word - Returns the datatype as a word ``` See also: [[make|Functions: make]] [[none?|Functions: none?]] [[logic?|Functions: logic?]] [[integer?|Functions: integer?]] [[decimal?|Functions: decimal?]] [[money?|Functions: money?]] [[tuple?|Functions: tuple?]] [[time? |Functions: time?]] [[date?|Functions: date?]] [[string?|Functions: string?]] [[email?|Functions: email?]] [[file?|Functions: file?]] [[url?|Functions: url?]] [[issue?|Functions: issue?]] [[word?|Functions: word?]] [[block?|Functions: block?]] [[paren?|Functions: paren?]] [[path?|Functions: path?]] [[native?|Functions: native?]] [[function?|Functions: function?]] [[object?|Functions: object?]] [[port?|Functions: port?]] ''Description'' To check for a single datatype, use its datatype test function (e.g. string?, time?) The `/WORD` refinement returns the type as a word so you can use if for FIND, SELECT, SWITCH, and other functions. ``` print type? 10 integer! print type? :type? native! value: 10:30 print switch type?/word value [ integer! [value + 10] decimal! [to-integer value] time! [value/hour] date! [first value/time] ] 10 ```
``` types-of value Returns a copy of the types of a function Arguments: value ``` See also: [[body-of|Functions: body-of]] [[reflect|Functions: reflect]] [[spec-of|Functions: spec-of]] [[title-of|Functions: title-of]] [[values-of|Functions: values-of]] [[words-of |Functions: words-of]] ''Description'' No description provided.
``` typeset? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' No description provided.
''Description'' No description provided.
``` union set1 set2 /case /skip size Returns the union of two data sets. Arguments: set1 [block! string! binary! bitset! typeset!] - first set set2 [block! string! binary! bitset! typeset!] - second set Refinements: /case - Use case-sensitive comparison /skip - Treat the series as records of fixed size size [integer!] ``` See also: [[difference|Functions: difference]] [[intersect|Functions: intersect]] [[exclude|Functions: exclude]] [[unique|Functions: unique]] ''Description'' Returns all elements present within two blocks or strings ignoring the duplicates. ``` lunch: [ham cheese bread carrot] dinner: [ham salad carrot rice] probe union lunch dinner [ham cheese bread carrot salad rice] probe sort union [1 3 2 4] [3 5 4 6] [1 2 3 4 5 6] string1: "CBDA" ; A B C D scrambled string2: "EDCF" ; C D E F scrambled probe sort union string1 string2 "ABCDEF" items: [1 1 2 3 2 4 5 1 2] probe union items items ; get unique set [1 2 3 4 5] str: "abcacbaabcca" probe union str str "abc" ``` To obtain a unique set (to remove duplicate values) you can use UNIQUE. <<< Note that performing this function over very large data sets can be CPU intensive. <<<
``` unique set1 /case /skip size Returns the data set with duplicates removed. Arguments: set1 [block! string! binary! bitset! typeset!] Refinements: /case - Use case-sensitive comparison (except bitsets) /skip - Treat the series as records of fixed size size [integer!] ``` See also: [[intersect|Functions: intersect]] [[union|Functions: union]] [[difference|Functions: difference]] [[exclude|Functions: exclude]] ''Description'' Removes all duplicate values from a set or series: ``` lunch: [ham cheese bread carrot ham ham carrot] probe unique lunch [ham cheese bread carrot] probe unique [1 3 2 4 3 5 4 6] [1 3 2 4 5 6] string: "CBADEDCF" probe unique string "CBADEF" ``` <<< Note that performing this function over very large data sets can be CPU intensive. <<<
``` unless condition block Evaluates the block if condition is not TRUE. Arguments: condition block [block!] ``` See also: [[if|Functions: if]] [[not|Functions: not]] [[either|Functions: either]] ''Description'' The `unless` function is the equivalent of writing `if not` of a condition. ``` unless now/time > 12:00 [print "It's still morning"] ``` See the [[if|Functions: if]] function for a lot more information. ''Why?'' This function can take some getting used to. It has been provided to make PERL programmers happier, and it's marginally simpler and faster than writing an `if not` expression.
``` unprotect value /deep /words /values Unprotect a series or a variable (it can again be modified). Arguments: value [word! series! bitset! map! object! module!] Refinements: /deep - Protect all sub-series as well /words - Block is a list of words /values - Process list of values (implied GET) ``` See also: [[protect|Functions: protect]] ''Description'' Unprotects a series, variable, or object that was protected earlier with protect. For example: ``` test: "text" protect test append test "a" ** Script error: protected value or series - cannot modify unprotect test append test "a" probe texta "texta" ``` To unprotect all series found within a block, use the `/deep` refinement: ``` test: [100 "example" 10:20] protect/deep test print append "example" "x" ** Script error: protected value or series - cannot modify unprotect/deep test print append "example" "x" examplex ``` See protect for other usage and information.
``` unset word Unsets the value of a word. Arguments: word [word! block!] - Word or block of words ``` See also: [[set|Functions: set]] ''Description'' Using UNSET, the word's current value will be lost. If a block is specified, all the words within the block will be unset. ``` test: "a value" unset 'test print value? 'test false ```
``` unset? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[value?|Functions: value?]] ''Description'' Returns TRUE if a value is UNSET. Normally you should use VALUE? to test if a word has a value. ``` if unset? do [print "test"] [print "Nothing was returned"] test ```
``` until block Evaluates a block until it is TRUE. Arguments: block [block!] ``` See also: [[while|Functions: while]] [[repeat|Functions: repeat]] [[loop|Functions: loop]] [[foreach|Functions: foreach]] [[for|Functions: for]] ''Description'' The `until` function evaluates a block until the block returns true. It is different from while because it only requires a single block, which also serves as the condition. However, the block is always evaluated at least once. The general form is: ``` while [cond] [body] ``` For example: ``` num: 0 until[ print num num: num + 1 num >= 2 ] 0 1 2 ``` Another example: ``` str: "test" until [ print str tail? str: next str ] test est st t ``` ''Return Value'' The last value of the block is returned from the until function. Because this is also the termination condition, it will always be non-none non-false, but that can be useful at times. ''Other Notes'' * A [[break|Functions: break]] can be used to escape from the loop at any time. * A common mistake is to forget that block must return the test condition for the loop, which could result in an infinite loop.
The UNVIEW function is used to close a window previously opened with the VIEW function. By default, the last window that has been opened will be closed. To close a specific window, use the `/only` refinement and specify the window's face (that which was returned from a layout, for example). All windows can be closed with the /all refinement. The example below opens a window that displays a Close button. Clicking on the button will evaluate the UNVIEW function and the window will be closed. ``` view layout [button "Close" [unview]] ``` Note that the VIEW function will not return until all windows have been closed. (Use `VIEW/new` to return immediately after the window is opened.) The next example will open two windows, then use `UNVIEW/only` to close each one separately. ``` out1: layout [button "Close 2" [unview out2]] out2: layout [button "Close 1" [unview out1]] view/new out1 view/new out2 do-events ``` You could have closed both windows with the line: ``` unview/all ```
``` update port Updates the port's external state to match internal state (normally after read/write). Arguments: port [port!] ``` See also: [[read|Functions: read]] [[write|Functions: write]] [[insert|Functions: insert]] [[remove|Functions: remove]] [[query|Functions: query]] ''Description'' Updates the input or output of a port. If input is expected, the port is checked for more input. If output is pending then that output is written. ``` out: open/new %trash.me insert out "this is a test" update out insert out "this is just a test" close out ```
``` upgrade Check for newer versions (update REBOL). ``` See also: [[about|Functions: about]] [[license|Functions: license]] ''Description'' Checks your version of REBOL against the latest released version (requires a network connection) and prompts you to download the latest version if your current version is outdated. If your current version of REBOL is up to date, this is indicated. ``` upgrade ```
``` uppercase string /part length Converts string of characters to uppercase. (Modifies) Arguments: string [any-string! char!] Refinements: /part - Limits to a given length or position length [number! any-string!] ``` See also: [[lowercase|Functions: lowercase]] [[trim|Functions: trim]] ''Description'' The series passed to this function is modified as a result. ``` print uppercase "abcdef" ABCDEF print uppercase/part "abcdef" 1 Abcdef ```
``` url? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. ``` print url? http://www.REBOL.com true print url? "test" false ```
``` usage Prints command-line arguments. ``` See also: [[help|Functions: help]] [[?|Functions: ?]] ''Description'' Displays REBOL command line arguments, including options and examples. ``` usage ``` SDK and special versions of REBOL may not include usage information.
``` use vars body Defines words local to a block. Arguments: vars [block! word!] - Local word(s) to the block body [block!] - Block to evaluate ``` ''Description'' The first block contains a list of words which will be local to the second block. The second block will be evaluated and its results returned from the USE. ``` total: 1234 nums: [123 321 456] use [total] [ total: 0 foreach n nums [total: total + n] print total ] 900 print total 1234 ``` Note: The USE function modifies the context (bindings) of the code block (as if BIND was used on it). This can lead to problems for recursive functions. To use the USE function recusively, you will need to `COPY/deep` the code block first: ``` words: [a] body: [print a * b] use words copy/deep body ```
``` utf? data Returns UTF BOM (byte order marker) encoding: positive for BE, negative for LE. Arguments: data [binary!] ``` ''Description'' No description provided.
``` utype? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` ''Description'' No description provided.
``` value? value Returns TRUE if the word has been set. Arguments: value ``` See also: [[default|Functions: default]] [[unset?|Functions: unset?]] [[equal?|Functions: equal?]] [[strict-equal?|Functions: strict-equal?]] [[same?|Functions: same?]] ''Description'' The value? function returns true if the specified word! has a value. It returns false if not. ``` test: 1234 value? 'test true value? 'not-defined false ``` The word can be passed as a literal or as the result of other operations. ``` value? first [test this] true value? second [test this] false ```
``` values-of value Returns a copy of the values of a object or module Arguments: value ``` See also: [[body-of|Functions: body-of]] [[reflect|Functions: reflect]] [[spec-of|Functions: spec-of]] [[title-of|Functions: title-of]] [[types-of|Functions: types-of]] [[words-of |Functions: words-of]] ''Description'' No description provided.
``` vector? value ``` Returns TRUE if it is this type. ``` Arguments: value [any-type!] ``` ''Description'' No description provided.
''Description'' The view function creates and updates windows. It takes a face as its argument. The contents of the window is determined from a face that holds a block of the graphical objects. The window face is normally created with the LAYOUT function, but faces can be constructed directly from face objects and displayed as well. The example below opens a window and displays some text and a button. ``` view layout [ h2 "The time is currently:" h3 form now button "Close" [unview] ] ``` The position and size of the window is determined from the face to be displayed. In the example above, the size of the window is automatically computed by the LAYOUT function. The window is shown in the default position in the upper left area of the screen. The window's caption will be default be the title of the script that is being run. To provide a different caption, use the /title refinement and a string. ``` view/title layout [h1 "Window"] "A Window" ``` The first use of view within an application is special. It displays the window and initializes the graphical interface system. Subsequent calls to VIEW update the window, they do not create new windows unless the /new refinement is provided. ``` view layout [ button "Change" [ view layout [button "Stop" [unview]] ] ] ``` The first call to the VIEW function will not return immediately. At that point your code becomes event driven, calling the functions associated with various faces. While the first call to VIEW remains active, any other calls to VIEW will return immediately. The first call will return only after all windows have been closed. Additionally, calls to view can specify options, such as whether the window has borders and is resizable. Single options are provided as a word and multiple options are specified in a block. ``` out: layout [vh1 "This is a window."] view/options out [resize no-title] ```
``` wait value /all Waits for a duration, port, or both. Arguments: value [number! time! port! block! none!] Refinements: /all - Returns all in a block ``` ''Description'' If the value is a [[time!|Datatypes: Time!]], delay for that period. If the value is an integer! or decimal!, wait that number of seconds. If the value is a [[port!|Datatypes: Port!]], wait for an event from that port. If a [[block!|Datatypes: Block!]] is specified, wait for any of the times or ports to occur. Return the port that caused the wait to complete or return none if the timeout occurred. ``` print now/time 17:48:19 wait 1 print now/time 17:48:22 wait 0:00:01 print now/time 17:48:23 ```
``` wake-up port event ``` Awake and update a port with event. ``` Arguments: port [port!] event [event!] ``` ''Description'' No description provided.
``` what name /args Prints a list of known functions. Arguments: name [word! lit-word! unset!] - Optional module name Refinements: /args - Show arguments not titles ``` See also: [[help|Online help]] [[?|Functions: ?]] ''Description'' The `what` function lists globally exported functions and their titles or arguments. For example: ``` >> what ... about Information about REBOL abs Returns the absolute value. absolute Returns the absolute value. action Creates datatype action (for internal usage only). action? Returns TRUE if it is this type. add Returns the result of adding two values. ajoin Reduces and joins a block of values into a new string. alias Creates an alternate spelling for a word. ... ``` To see function arguments use: ``` >> what/args ... about [] abs [value] absolute [value] action? [value] add [value1 value2] ajoin [block] ... ``` Also see the help function which allows searching for functions. ''Module Export Lists'' To see a list of functions for a specific module, provide the module name: ``` what module-name ```
``` what-dir Returns the current directory path. ``` See also: [[change-dir|Functions: change-dir]] [[make-dir|Functions: make-dir]] [[list-dir|Functions: list-dir]] ''Description'' Returns the value of `system/script/path`, the default directory for file operations. ``` print what-dir /C/REBOL/3.0/docs/scripts/ ```
``` while cond-block body-block While a condition block is TRUE, evaluates another block. Arguments: cond-block [block!] body-block [block!] ``` See also: [[until|While and until]] [[loop|Functions: loop]] [[repeat|Functions: repeat]] [[for|Functions: for]] ''Description'' The `while` function repeats the evaluation of its two block arguments while the first block returns true. The first block is the condition block, the second block is the evaluation block. When the condition block returns `false` or [[none!|Datatypes: None!]], the expression block will no longer be evaluated and the loop terminates. The general form is: ``` while [cond] [body] ``` For example: ``` num: 0 while [num < 3] [ print num num: num + 1 ] 0 1 2 ``` Another example, using while to traverse a series (like [[foreach|Functions: foreach]] ): ``` color: [red green blue] while [not tail? color] [ print first color color: next color ] red green blue ``` Here is an example using a string series: ``` str: "abc" while [not tail? str: next str] [ print ["length of" str "is" length? str] ] length of abc is 3 length of bc is 2 length of c is 1 ``` ''Condition Block'' The condition block can contain any number of expressions, so long as the last expression returns the condition. To illustrate this, the next example adds a print to the condition block. This will print the index value of the color. It will then check for the tail of the color block, which is the condition used for the loop. ``` color: [red green blue] while [ print index? color not tail? color ][ print first color color: next color ] 1 red 2 green 3 blue 4 ``` ''Return Value'' The last value of the block is returned from the `while` function. ''Other Notes'' A break can be used to escape from the loop at any time. The most common mistake is to forget to provide a block for the first argument (the condition).
``` why? err Explain the last error in more detail. Arguments: err [word! path! error! none! unset!] - Optional error value ``` ''Description'' This function opens your web browser to the page in this R3 document database that explains the error message in more detail. After an error, you can type why? (with no arguments) to see info about that specific error. For example: ``` >> test ** Script error: test has no value ** Note: use WHY? for more about this error >> why? Opening web browser... ``` and, this page, no-value, would be displayed. You can also use `why?` with an argument, such as an error object. This line opens the same web page as above: ``` if err: try [test] [why? err] Internals ``` So, how does the `why?` function know the last error? Use source on it to see the answer.
``` word? value Returns TRUE if it is this type. Arguments: value [any-type!] ``` See also: [[type?|Functions: type?]] ''Description'' Returns FALSE for all other values. To test for "word:", ":word", or "'word", use the SET?, GET?, and LITERAL? functions. ``` print word? second [1 two "3"] true ```
``` words-of value Returns a copy of the words of a function, object, or module Arguments: value ``` See also: [[body-of|Functions: body-of]] [[reflect|Functions: reflect]] [[spec-of|Functions: spec-of]] [[title-of|Functions: title-of]] [[types-of|Functions: types-of]] [[values-of|Functions: values-of]] ''Description'' No description provided.
``` write destination data /part length /seek index /append /allow access /lines Writes to a file, URL, or other port - auto-converts text strings. Arguments: destination [port! file! url! block!] data [binary! string! block!] - Data to write (non-binary converts to UTF-8) Refinements: /part - Partial write a given number of units length [number!] /seek - Write at a specific position index [number!] /append - Write data at end of file /allow - Specifies protection attributes access [block!] /lines - Write each value in a block as a separate line ``` See also: [[read|Functions: read]] [[open|Functions: open]] [[close|Functions: close]] [[load|Functions: load]] [[save|Functions: save]] [[form|Functions: form]] ''Description'' WRITE is typically used to write a file to disk, but many other operations, such as writing data to URLs and ports, are possible. Normally a string or binary value is provided to this function, but other types of data such as a number or a time can be written. They will be converted to text. The `/BINARY` refinement will write out data as its exact representation. This is good for writing image, sound and other binary data. The `/STRING` refinement translates line terminators to the operating system's line terminator. This behavior is default. The `/APPEND` refinement is useful logging purposes, as it won't overwrite existing data. The /LINES refinement can take a block of values and will write each value to a line. By default, WRITE will write the block of values as a concatonated string of formed values. The /`PART` refinement will read the specified number of elements from the data being written. The `/WITH` refinement converts characters, or strings, specified into line terminators. See the User's Guide for more detailed explanation of using READ and its refinements. ``` write %junkme.txt "This is a junk file." write write %datetime.txt now write write/binary %data compress "this is compressed data" write %rebol-test-file.r "some text" print read %rebol-test-file.r read write/append %rebol-test-file.r "some more text" print read %rebol-test-file.r write %rebol-test-file.r reduce ["the time is:" form now/time] print read %rebol-test-file.r read write/lines %rebol-test-file.r reduce ["time is:" form now/time] print read %rebol-test-file.r write/part %rebol-test-file.r "this is the day!" 7 print read %rebol-test-file.r ```
``` xor value1 value2 Returns the first value exclusive ORed with the second. Arguments: value1 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] value2 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] ``` See also: [[and|Functions: and]] [[or|Functions: or]] [[not|Functions: not]] ''Description'' For integers, each bit is exclusively-or'd. For logic values, this is the same as the [[not-equal|Functions: not-equal?]] function. ``` print 122 xor 1 123 print true xor false true print false xor false false print 1.2.3.4 xor 1.0.0.0 0.2.3.4 ```
``` xor~ value1 value2 ``` Returns the first value exclusive ORed with the second. ``` Arguments: value1 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] value2 [logic! integer! char! tuple! binary! bitset! typeset! datatype!] ``` See also: [[and~|Functions: and~]] [[or~|Functions: or~]] Description The trampoline action function for XOR operator.
``` zero? value Returns TRUE if the value is zero (for its datatype). Arguments: value ``` See also: [[positive?|Functions: positive?]] [[negative?|Functions: negative?]] ''Description'' Check the value of a word is zero. ``` print zero? 50 false print zero? 0 true ```
The general pattern in most scripts is: ``` REBOL [ Title: "This is the header" Date: 10-Feb-2009 ] ;-- Data definitions: name: "Bud" ... ;-- Function definitions: do-it: func [data] [print data] ... ;-- Main code: do-it name ``` Of course, this will vary, depending on the purpose of the script.
Rules consist of these main elements: |''Item'' |''Description''|h |keyword |a special word of the dialect, listed in the table below| |word |get or set a variable (see below) - cannot be a keyword| |path |get or set a variable via a path (see below)| |value |match the input to a value (accepted datatypes depend on input datatype)| |`"|"` |backtrack and match to next alternate rule (or)| |[block] |a block of sub-rules| |(paren) |evaluate an expression (a production)|
Function arguments can also specify that a word's value be fetched but not evaluated. This is similar to the literal arguments described above, but rather than passing the word, the value of the word is passed without being evaluated. To specify that an argument be fetched but not evaluated, precede the argument name with a colon. For example, the following function accepts functions as arguments: ``` print-body: func [:fun] [probe second :fun] ``` The sample function prints the body of a function that is passed to it. The argument is preceded by a colon, which indicates that the value of the word should be obtained, but not further evaluated. ``` print-body reform [form reduce value] ``` ``` print-body rejoin [ if empty? block: reduce block [return block] append either series? first block [copy first block] [ form first block] next block ] ```
To get the value of a word that was previously defined, place a colon `:` at the front of the word. A word prefixed with a colon obtains the value of the word, but does not evaluate it further if it is a function. For example, the following line: ``` drucken: :print ``` defines a new word, drucken (which is German for print), to refer to the same function [[print|Functions: print]] does. This is possible because the get-word `:` returns the function for print, but does not evaluate it. Now, `drucken` performs the same function as print : ``` drucken "test" test ``` Both [[print|Functions: print]] and `drucken` are set to the same value, which is the function that does printing. This can also be accomplished with the [[get|Functions: get]] function. When given a literal word, [[get|Functions: get]] returns its value, but does not evaluate it: ``` stampa: get 'print stampa "test" test ``` The ability to get the value of a word is also important if you want to determine what the value is without evaluating it. For example, you can determine if a word is a native function using the following line: ``` print native? :if true ``` Here the get returns the function for [[if|Functions: if]]. The if function is not evaluated, but rather it is passed to the [[native?|Functions: native?]] function which checks [[if|Functions: if]] it is a native datatype. Without the colon, the if function would be evaluated, and, because it has no arguments, an error would occur.
!!!! ''Making GOBs'' New GOBs are created with make and a specification block. ``` gob1: make gob! [text: "Example" size: 400x40] gob2: make gob! [offset: 10x20 image: logo-image] gob3: make gob! [ offset: 100x200 size: 400x400 draw: [pen yellow line-width 5 circle 200x200 150] ] ``` <<< Note that the specification block is not reduced and only valid field names are allowed (see list below.) <<< You can also create a GOB from another GOB, inheriting its settings: ``` gob4: make gob1 [text: "Another example"] ``` !!!! ''Content Types'' Each GOB is of a content type that determines the format of its data and how it will be rendered on the display. Complex displays are created by combining layers of GOBs of these various types. For example, you can create a display that has colored text on top of an image on top of a draw-rendered gradient on top of a colored background. |''Type'' |''Description''|h |''color'' |An RGBA color to fill the specified area.| |''image'' |An RGBA image. The size of the GOB is determined by the size of the image.| |''draw'' |A block of scalar vector graphic (SVG) commands, such as line, box, and circle.| |''effect'' |A block of special effect commands, such as blur or colorize, etc.| |''text'' |A block of rich-text commands including special modes such as bold, italic, color, etc.| In addition a GOB may have no content type and just be used as a pane that holds a list of GOBs that will be composited together. For example a window or a panel used for an input form may be used just for "organizational" purposes. !!!! ''Access Fields'' A GOB datatype allows access to the following fields: |''Field'' |''Datatype'' |''Descriptio''n|h |''offset'' |pair! |the x-y coordinate relative to parent| |''size'' |pair! |width and height of gob canvas or coordinate space| |''pane'' |block! |a block of child gobs (see below)| |''parent'' |gob! |the parent gob (in its pane)| |''data'' |object! block! string! binary! integer! none! |normally used to reference data related to the gob, such as the VID face object| |''flags'' |block! |special flags, see section below| |''alpha'' |integer! |alpha transparency for the gob overall| |''owner'' |gob! |a temporary field used for popup windows to specify the owning parent window| For example: ``` agob/offset: 100x100 print agob/size bgob: agob/parent ``` In addition, these fields are used to access the content of a GOB, depending on its type: |''Field'' |''Datatype'' |''Description''|h |''color'' |tuple! |the color of the gob| |''image'' |image! |an image within the gob| |''draw'' |block! |a DRAW dialect block| |''effect'' |block! |an EFFECT dialect block| |''text'' |block! string! |a richtext dialect block| Examples: ``` agob/color: blue agob/image: load %photo.jpg agob/draw: [ pen edge-color line-width 1.5 box 1x1 300x40 3 ] ``` Note that you can only specify one content field per GOB. If you attempt to set a second field, it overwrites the earlier one. !!!! ''Offset and Size'' Spatial information about the GOB can be accessed with: |''Name'' |''Description''|h |''offset'' |The x-y offset of the GOB relative to its parent. Either value (or both) can be negative and clipping will occur.| |''size'' |The width and height of GOB content area. Any graphics that extends outside this area will be clipped.| For example: ``` gob/offset: 100x20 print gob/offset gob/size: 150x50 ``` !!!! ''Data Reference'' The primary purpose of the data field is to provide a way to reference an object, block, or other `data` related to your rendering, subsystem, or application. Although the `data` field is under the control of the programmer and is not accessed by the GOB system itself, it is used by subsystems like the GUI. For example, in the GUI the data field might point to the [[face|http://www.rebol.com/r3/docs/gui/faces.html]] object that stores run-time information such as event handling to quickly locate the face. <<< ''Internally, the `data` field is pointer-sized (32 bits as of writing this page) for optimization reasons''. It is not a fully-qualified value field, so can only hold the specific values mentioned above, and any series references contain no indexed offsets. If you need to store general values, use a block or object. <<<
The screen and its windows are controlled with GOBs. New windows are opened by adding a window GOB to the screen GOB pane. Windows are closed by removing the window GOB from the pane. !!!! ''The Screen GOB'' The `screen-gob` is a field in `system/view` object. The size field of the GOB is the size of the screen: ``` print system/view/screen-gob/size 1440x900 ``` Each GOB within the screen-gob/pane is a window. Creating a Window Note: See [[View - Windowing System]] for more information about windows. Normally, windows are created by the view function. Internally, it creates a new GOB for the window. The offset provides the position of the window, and the size provides its width and height. If text is provided, it will become the window caption. (Window GOBs do not allow color, image, draw, or effect content types, only text for the caption.) For example, if you create a GOB: ``` win: make gob! [text: "Test Window" offset: 100x100 size: 300x200] ``` You can use that for a window by calling view this way: ``` view/as-is win ; use the argument as the window itself ``` Or, you could open the window on screen with this: ``` append system/view/screen-gob win show win ``` However, this method should be avoided. You should use the [[view|Functions: view]] function, which handles many other features. !!!! ''Window Flags'' Window GOBs accept these special flags: |''Flag'' |''Description''|h |''dropable'' |allow drag and drop of files| |''hidden'' |window is hidden| |''modal'' |modal event handling (for requestors)| |''no-border'' |do not draw window borders (or title)| |''no-title'' |do not show window title| |''on-top'' |keep window on top| |''popup'' |a popup window (has owning parent window)| |''resize'' |allow the window to be resized| |''transparent'' |let the window be transparent| These flags can be set like this: ``` win/flags: [resize dropable] ``` or during the MAKE with: ``` win: make gob! [size: 100x200 flags: [resize]] ``` You can obtain the flags block with: ``` probe win/flags ``` !!!! ''Event Handling'' Window events such as mouse moves and button clicks are mapped by the native system to an offset within a specific window gob. The higher level event system is responsible for locating the specific sub-gob target of the click, if that action is desired. Typically, a GOB that requires interactivity, such as processing of button events will be part of a higher level face object, and the processing of the specific events will be done by functions of that face. For more information see [[View - Event Handling|http://www.rebol.com/r3/docs/view/events.html]] and [[View - Windowing System]] sections.
''About the GUI'': * The primary objectives of the R3 GUI have been clearly stated in prior documents. However, to be sure we're all in sync: ''the GUI is designed to make simple apps simple, and sophisticated apps possible''. That is, you really can write a useful app in just a few lines of GUI dialect, and a full scale app may require just a few dozen pages. * You can use the GUI in programs without knowing the details about how it works. That's fine; however, if you want to create new styles or features, it is critical that you undertand the desgin. * We have begun writing the official R3 GUI documentation, as you see below. We seek the best ways to explain how the GUI works and provide you with a solid conceptual model. ''User's Guide'' This is a whole new guide that's being started for new users it goes step-by-step. (Currently, this part is lower priority compared to developer docs.) [[GUI Guide|GUI - User's Guide]] Getting started with the GUI. In development. ''Developer's Guide'' This section is for developers to understand the language of the GUI. Here are the primary terms you need to know, with each linked to its documentation: |[[Style|http://www.rebol.com/r3/docs/gui/styles.html]] |Defines the look and feel of a GUI element. A GUI class.| |[[Face|http://www.rebol.com/r3/docs/gui/faces.html]] |An instance of a style, with specific attributes and options. A GUI object.| |[[Panel|http://www.rebol.com/r3/docs/gui/panels.html]] |An organized collection of related faces. A GUI layout.| |[[Actor|http://www.rebol.com/r3/docs/gui/actors.html]] |A style-defined function that acts on face instances. A GUI method.| |[[Reactor|http://www.rebol.com/r3/docs/gui/reactors.html]] |A top level "result" from user input or other events. GUI results.| |[[Dialect|http://www.rebol.com/r3/docs/gui/dialect.html]] |Specifies the styles, faces, and layout within a GUI panel. The GUI language.| ''Lower-level Graphics'' |[[Window|http://www.rebol.com/r3/docs/view/windows.html]] |An area of the screen managed by the operating system.| |[[Event|http://www.rebol.com/r3/docs/view/events.html]] |A datatype that indicates user input or other activities.| |[[Gob|http://www.rebol.com/r3/docs/view/gobs.html]] |A lower level graphical object, optimized for size and performance.| |[[Draw|http://www.rebol.com/r3/docs/view/draw.html]] |A block of graphical rendering commands.| |[?Effect?] |[[A block of graphical effect commands.|http://www.rebol.com/cgi-bin/wip3.cgi?edit=effect.txt]]| |[?Richtext?] |[[A block of text and formatting commands.|http://www.rebol.com/cgi-bin/wip3.cgi?edit=richtext.txt]]|
Often it is necessary to sort a data set that has more than one value per record. The `/skip` refinement supports this for sorting records that have a fixed length. The refinement takes one additional argument: an integer specifying length of each record. Here is an example that sorts a block that contains first name, last name, ages, and emails. The block is sorted by its first column, first-name. ``` names: [ "Evie" "Jordan" 43 eve@jordan.dom "Matt" "Harrison" 87 matt@harrison.dom "Luke" "Skywader" 32 luke@skywader.dom "Beth" "Landwalker" 104 beth@landwalker.dom "Adam" "Beachcomber" 29 adam@bc.dom ] sort/skip names 4 foreach [first-name last-name age email] names [ print [first-name last-name age email] ] Adam Beachcomber 29 adam@bc.dom Beth Landwalker 104 beth@landwalker.dom Evie Jordan 43 eve@jordan.dom Luke Skywader 32 luke@skywader.dom Matt Harrison 87 matt@harrison.dom ```
''Contents'' * Introduction * Hello World in a Window ** Don't Forget... ** What's Going On? * Simple Forms ** Basic Form ** A Real Form ** Survey Form ** What's Missing * Other Input Styles * More to come... ''Introduction'' This page introduces the main concepts of the REBOL 3 graphical user interface, the GUI. In the sections below, I will show you how to quickly get started making your own windows with text, buttons, fields, panels, and many other types of GUI object. Although this document is intended for beginners, experienced REBOL programmers may find it a useful introduction as well. Although the general principles of this GUI are similar to those of REBOL 2, it's been through a major redesign to incorporate all of what we've learned over the years in writing code the REBOL way. Specifically, we designed a GUI that is: |''Powerful'' |Can create a wide range of GUIs for our REBOL applications.| |''Clean'' |Easier to read with less clutter that other languages or methods.| |''Simpler'' |Much less complex both for apps and for the system itself.| |''Fast'' |Quick to build and/or modify user interfaces.| |''Pretty'' |Updated display method with anti-aliased scalar vector graphics (SVG).| ''Hello World in a Window'' These lines will open a new window, display some text, and provide a close button: ``` view [ title "Hello World" button "Close" close ] ``` When you run it, it looks like this: ... Hello world window (alpha skin) Clicking the button will close the window. <<< Note that the bright background color indicates this is the alpha test version of the GUI. This ''will not be'' the final release default colors. <<< !!!!! ''Don't Forget...'' In order to run the above example, be sure to add these lines to the top: ``` REBOL [] load-gui ``` The [[load-gui|Functions: load-gui]] function will download the current under-development GUI system. Later, this line will not be needed. !!!!! ''What's Going On?'' In this example, the [[view|Functions: view]] function opens [[window|View - Windowing System]] and displays a [[panel|GUI Panels and Layouts]]. The panel was created from a layout block that includes two [[styles|GUI Styles]] and their options: |''Style'' |''Description''|h |''title'' |A style that displays a title in a large bold font at the top of the panel. It also sets the window title to the same string.| |''button'' |A style that when clicked will do some kind of action. Here it close the window, and because no other GUI windows are open, REBOL will quit too.| In this example, the options for those styles are the strings that follow them, and for the button, the the word close is a special kind of [[reactor|GUI Reactors]] option. <<< Notice that we call graphic elements [[styles|GUI Styles]], not controls, widgets, or gadgets. That's because they aren't hard coded functions as found in most GUI systems; they are more like the style sheets, a bit like CSS used for web pages. <<< ''Simple Forms'' To show how quickly you can build user interfaces, I'll start by making a few input forms. !!!!! ''Basic Form'' Let's expand on the example above by making it into a small input form. This window: <img src="http://www.rebol.com/r3/docs/graphics/gui-simple-form-1.jpg"/> is created from this code: ``` view [ title "Simple Form" panel 2 [ label "Name:" field label "Message:" area ] button "Cancel" close ] ``` And, I've introduced a few new styles: |''Style'' |''Description''|h |''panel'' |Creates sub-panel with two columns (from the integer that follows it).| |''label'' |Text labels for name and message.| |''field'' |A single-line text input field.| |''area'' |A multiple-line text input field.| !!!!! ''A Real Form'' The above form, although it looks good, doesn't do anything useful. So, let's add a couple more buttons to make the form do something. I will add two more buttons: one for ''submit'' and the other for ''help'': <img src="http://www.rebol.com/r3/docs/graphics/gui-simple-form-2.jpg"/> This window comes from the code: ``` view [ title "Simple Form" panel 2 [ label "Name:" name: field label "Message:" message: area ] group [ button "Submit" submit http://www.rebol.com/cgi-bin/gui-form.r button "Help" browse http://www.rebol.com/r3/docs/gui/gui.html button "Close" close ] ] ``` Notice the `group` style. It's similar to a panel but has no borders and places items horizontally. It turn out that these two styles are related. One is defined from the other, but I'll talk more about that later. The `submit` button will automatically submit all the input fields to the given URL. I will be talking about this more later. On submit, the data of the fields are formatted like an object, with names and values. That's why I've put set-word names in front of the field and area styles. The `help` button will open the default web browser to the given URL. Easy. !!!!! ''Survey Form'' Next, I'm adding more to the above form to make an opinion survey out of it: <img src="http://www.rebol.com/r3/docs/graphics/gui-opinion-form.png"/> You can see I've added a few more styles here: ``` view [ title "Opinion Survey" text "Do you want programs to be easy to build?" panel 2 [ label "Answer:" group [ radio "Agree" radio "Disagree" radio "Not sure" ] pad check "I'm a programmer." pad check "I am also a REBOL expert." label "Name:" field label "Comment:" area pad ; temporary, for bug ] group [ button "Submit" submit http://www.rebol.net/cgi/submit.r button "Reset" reset button "Cancel" close ] ] ``` The new styles in this example are: |''Style'' |''Description''|h |''text'' |Displays simple text lines| |''radio'' |Mutually exclusive choice buttons (classic radio buttons).| |''pad'' |A filler for an empty position in the panel.| |''check'' |A check box button and text.| In addition, the second button performs a `reset` action on the form, resetting all contents to its initial values. Also, you may be wondering why there are no set-word names for the various input fields. Yes, that's accepted, and I'll talk more about that when I cover how `submit` works. !!!!! ''What's Missing'' Something's missing in the above forms. Did you notice? They end with the user submitting data to a URL, but then what? Shouldn't we see a response from the server, some kind of confirmation or perhaps even the current results of the survey? Yes, indeed we need that, and I'll be showing that in the sections ahead. ''Other Input Styles'' Here's a fun one to try. This window will show a few other input styles and the top two bars will change based on changes you make to the other bars or buttons that you click. <img src="http://www.rebol.com/r3/docs/graphics/gui-sliders.png"/> The check boxes as the bottom will determine the width of the scroll bar knob. It all comes from this code: ``` view [ title "Progress, Scrollers, and Sliders" text "These will change:" panel [ prog: progress sbar: scroller attach 'prog ] text "Change the above, variable amounts::" panel 80.200.180.80 [ slider attach 'sbar scroller attach 'sbar ] text "Change the above, predefined amounts:" group 3 [ button "Set 0%" set 'sbar 0% button "Set 10%" set 'sbar 10% button "Set 50%" set 'sbar 50% button "Set 90%" set 'sbar 90% button "Set 100%" set 'sbar 100% button "Set 150%" set 'sbar 150% ] text "How wide to make them (their deltas):" panel 3 200.100.80.80 [ radio "Delta 10%" on set 'sbar 'delta 10% radio "Delta 50%" set 'sbar 'delta 50% radio "Delta 100%" set 'sbar 'delta 100% ] ] ``` These new styles are being used: |''Style'' |''Description''|h |''progress'' |Displays a progress bar.| |''scroller'' |A sliding scroll bar with arrow buttons.| |''slider'' |A sliding control bar.| In addition, these two [[reactors|GUI Reactors]] make it all work: |''Reactor'' |''Description''|h |''attach'' |Attach one GUI element to another. It's value will automatically set the other value.| |''set'' |Set the value of a GUI element and update its display.| This is a good time to mention that in R3 a GUI element is called a [[face|GUI Faces]] (as in interface or surface.) A face is an instance of a [[style|GUI Styles]]. It's the actual object created in the panel that holds the attributes and values related to the style. ''More to come...'' This is just a start. I'll be adding more very soon. -Carl March 2010
''Contents'' http://www.rebol.com/r3/docs/gui/actors.html * Concept * Defining Actors * Actor Arguments * Inherited Actors * Accessing Facets * Standard Actor Names * Default Actors * Calling an Actor * Actors for Initialization * on-make * on-init * on-attach * Actors for Events * on-click * on-drag * on-drag-over * on-drop * on-focus * on-key * on-move * on-over * on-resize * on-scroll * on-scroll-event * Actors for Value Control * on-get * on-set * on-clear * on-reset * Other Actors * on-draw Concept An actor implements a style function. If you think of a style as an object class, its actors are like the methods, and they operate on the instance of that class, the face object. Essentially, they are functions that are reused for each instance of a style, each face. We call them actors because they are are not true methods and are similar to the actor functions used in [?schemes?]. This document is is for advanced users who plan to implement their own styles and need to provide new functions for rendering, input, or other control. Casual GUI users do not need to know about actors. Defining Actors GUI styles define actors to provide functions that handle events, process input, modify attributes, and setup graphics rendering. Within a style an actor block holds the actor definitions. The block is a collection of actors names followed by their function body blocks. No function creators or argument specifications are needed, the make-style function will create those. The naming convention for actors begins with on- followed by a verb or verb-noun that best describes the action. Examples are: on-draw or on-view. Although not strictly required, using this convention helps make GUI code more clear. Here's an example actors block as it would look within a style definintion: actors: [ on-make: [ ... ] on-update: [ ... ] on-resize: [ ... ] on-scroll: [ ... ] on-over: [ ... ] ] Here is a complete style definition of clicker, the base-style that implements buttons. clicker: [ about: "Single-action button without text. Basis of other styles." facets: [ size: 28x28 area-color: 60.70.150 edge-color: 96.96.96 ] options: [ size: [pair!] area-color: [tuple!] ] faced: [ area-size: ; set by resize pen-color: ; set by on-draw area-fill: ; set by on-draw ] draw: [ pen pen-color line-width 1.5 grad-pen cubic 1x1 0 40 area-fill box 1x1 area-size 3 ] actors: [ on-draw: [ face/facets/area-fill: make-fill face/facets/area-color face/state/mode color: get-facet face 'edge-color if face/state/mode = 'over [color: color / 2] face/facets/pen-color: color arg ; return draw block ] on-click: [ ; arg: event face/state/mode: arg/type draw-face face if arg/type = 'up [do-face face] none ] ] ] Actor Arguments Actor arguments are fixed and standardized. The arguments are: face The face upon which the actor acts. args A single value or block of multiple values. When an actor is called, those values are passed to the body block. Normally, local variables are not required because the face object, or subobjects within it, hold most values. However, should a temporary be required, they can be created with use, foreach, or other such context creating functions. Q: Should the FUNCT method of set-word locals be used? Inherited Actors When a style is derived from another style its actors are inherited. It should be the derived actors are not bound to any particular style, but are simple functions. This allows actors to be efficiently reused in all instances of a face object. For example, button uses the clicker actors here: button: clicker [ about: "Single action button with text." facets: [ size: 100x28 max-size: 200x28 min-size: 50x24 text-body: "Button" text-style: 'button ] options: [ text-body: [string! block!] area-color: [tuple!] size: [pair!] wide: [percent!] ] ] Notice, no actor definitions are needed. Accessing Facets For any given style a facet value may be stored in either the style object itself, or within the face instance. The location depends on whether the facet is static for all face instances, or changes for each instance. Because you don't know and shouldn't care where it is stored, the get-facet function is provided to get the value and the set-facet function to set it. For example, if the on-resize actor needs to know the size facet, it would use: size: get-facet face 'size If the size is found in the face/facets object, that will be used. Otherwise, the style/facets object will be used. Standard Actor Names A number of actor names are predefined for standard actions, and we recommend that you use these for their equivalent actors within your GUI styles: Actor Description on-make when face is first created to initialize special values on-click when mouse button clicked on face on-drag when dragging inside a face on-drag-over when dragging and are over a target face on-drop when drag has stopped or when a file is dropped on-focus when we have been given or are losing focus on-get to fetch state values on-set when state values are set on-clear when the state values are cleared on-key when key has been pressed (for our focus) on-move when mouse has moved on-over when mouse passes over or away on-reset when reset is needed on-resize when size values have changed on-draw when system starts to draw the face (create DRAW block) on-scroll when scrolling is needed on-scroll-event when the mouse wheel is used on-init when face and its parent pane are ready (including initial sizing) on-attach when a face is attached to another face Default Actors A small number of actors are defined by default to work for all styles. They are: Style Description on-resize Recompute the area-size facet. on-over Force redraw on state change. on-get Return the face/state of a given name. locate A special actor to map an event to an offset position. Style definitions are allowed to override these actors with their own definition specific to their operation. Calling an Actor There will be times when one actor function will call another. This is done with the do-style function. Actors are always called this way, never directly. For example: do-style face 'on-click true It should be noted that the call will be ignored if the face has no on-click actor. Actors for Initialization on-make The on-make actor is called when the face is created within the layout engine. args none return none This actor can be used to setup face facet values such as blocks of data, colors, face orientation, etc. and anything else unique to the face. If you are defining a compound style, this is a good actor to set-up any sub-faces. It is not necessary to compute the face size within on-make because on-resize will be called later to do that. Example that sets colors unique to the new face: on-make: [ face/facets/colors: copy [255.255.255 128.128.128] ] on-init The on-init actor is called when a new panel is created. args none return none When a new panel is created, the on-init actor will be called for each face within the panel. At this point the face objects exist and the panel has been initialized, including any special bindings. It is also called for any trigger faces (special faces that act on when panel events.) Resetting the face on initialization: on-init: [ do-style face 'on-reset ] on-attach The on-attach actor is called when this face gets attached to another face. args the face requesting attachment return non For example, the on-init actor for a scroll bar will call the on-attach for a scrollable face that was defined earlier. Here's how a scroller uses it: on-attach: [ ; arg: scroller ; Called when scroll bar auto attaches: extend-face face 'attached arg update-scrollers face sub-gob? face ] For the scroller, the code to attach adds a scroll reactor to the target style through its on-init: on-init: [ ; Find a prior face to attach the scroll bar to: if target: find-face-actor/reverse face 'on-scroll [ append-face-act face reduce ['scroll target] do-style target 'on-attach face ] ] Actors for Events on-click The on-click is called each time a mouse button press or release occurs. args the event object for the mouse click. return on down, can be none or the drag object. On up, none. This example prints the button event that occurred: on-click: [ probe arg/type ] on-click is also the precursor to dragging (holding down a mouse button, while moving the mouse), so you can create a drag object in on-click using the init-drag function. If you return the drag object the on-drag actor will be invoked. on-click: [ if arg/type = 'down [ return init-drag face arg/offset ] none ; return value ] on-drag The on-drag actor is called when the drag object is created or when the mouse is moving inside its target face. args drag object (created earlier) return none on-drag usually comes after on-click and ceases to be used when the drag object is destroyed, which happens right after on-drop. Note that when a drag object exists, the on-move and on-over actors are not called. Here is an example used by a slider that changes a value constantly during drag, updates its graphics, and calls its reactors (if any). on-drag: [ do-style face 'on-offset arg/delta + arg/base draw-face face do-face face ] on-drag-over The on-drag-over actor is called when the mouse is moving over a foreign face (not the target of the drag.) args Block of values related to the drag (!! define) return none Examples on-drag-over: [ ; write this example ] on-drop The on-drop actor is called when the drag operation is released. args the drag object created earlier. return none At the end of a drag operation, when one of the mouse buttons is released, the on-click action is called with the event, then on-drop is called. After on-drop, the drag object is automatically destroyed. The on-drop actor is caleld regardless of whether the drag operation was started over this face or a different face. The on-drop actor is also called if a file is dragged and dropped from the system desktop over the face. This is a special case. Example: on-drop: [ ; write an example here ] on-focus The on-focus actor is called every time the face gains focus using the focus or next-focus function or loses focus with the unfocus function. args true for focus and none for unfocus. return none Nothing is called after on-focus, so if the face is changing appearance, a show-later should be called within the actor. This example makes the background color yello (selection variation of yellow) when the face is focused and makes it white, when the face is unfocused: on-focus: [ face/facets/back-color: pick reduce [yello white] arg show-later face ] on-key The on-key actor is called when a face has focus and a key is pressed. args the input event return the same event The on-key actor has a default value for all faces, to return the event argument. Simple keyboard navigation in a street map face: on-key: [ dx: dy: 0 switch arg/key [ right [dx: 1] left [dx: -1] up [dy: 1] down [dy: -1] ] if find arg/flags 'shift [ dx: dx * 3 dy: dy * 3 ] move-map as-pair dx dy arg ; return same event ] on-move The on-move actor is called every time the mouse moves. args the event value (with face-relative positions) return none Important notes: Not required for most styles. Will be called often, so don't define it unless you need it. The on-over actor will be called after this actor. Not be called during a drag operation. on-over The on-over actor is called every time the mouse moves over or away from the face. args the face relative position or none return none If the face has the all-over value specified as true, this actor will be run continuously as long as the mouse is over the face. If all-over is not true, it does not report continuously, only on enter and exit. The on-over actor has a default for all styles. It will set the face/state/mode to over or up and then redraw the face. The default on-over actor code is: on-over: [ face/state/mode: pick [over up] face/state/over not not arg draw-face none ] on-resize The on-resize actor is called every time the layout is resized. args new size (pair! value) return none Normally, you use this actor to modify the size fields of the draw block and any GOBs used within it. If your style is a compound style, the faces inside may also need to be resized, and can often be done with the resize-panel function. Resizing a single face: on-resize: [ face/gob/size: arg set-facet face 'size arg set-facet face 'area-size arg - 2 ] Resizing a compound face with scrollers: on-resize: [ resize-panel face arg update-scrollers face face/gob ] on-scroll The on-scroll actor is called from one face to scroll another face. args the face object of the scroller return true if the attach was successful When a scroll-bar is moved it will call this function to tell its target face to scroll. This is how a scroll-bar informs the other face that it's time to update. So, this actor must be defined for styles that are scrollable. When a face is scrolled, this actor can be called directly by the scroll reactor or by a prior attachment that occurs when a scrollable face is defined before a scrolling style. Do not confuse this with on-scroll-event which takes an event to perform. Scroll a text area face: on-scroll: [ ; arg: scroller gob: sub-gob? face ; subtract view area size from total text size: size: negate max 0x0 gob/size - face/gob/size ; multiply by scroll amount: offset: size * arg/state/value ; change only the axis axis: face-axis? arg xy: gob/offset xy/:axis: offset/:axis gob/offset: xy show-later face true ; we got it ] on-scroll-event The on-scroll-event actor is called when a scroll event occurs. args the event args then same event Scroll events can be caused by the mouse-wheel or other such devices. Do not confuse this actor with on-scroll which is used to scroll a face from another face, such as a scroller style. Here's an example: on-scroll-event: [ dy: none switch arg/type [ scroll-line [dy: arg/offset/y / -30] scroll-page [dy: negate arg/offset/y] ] if dy [bump-scroll face dy] none ] Note that bump-scroll is a function specific to this style. Actors for Value Control on-get The on-get actor returns values stored in the face object and is normally called by get-face. Normally, the default actor is all you need. args the name of the variable to fetch (default is value) return The value fetched. The default definition of on-get is: on-get: [ ; arg: the field to get select face/state arg ] on-set The on-set actor is called by set-face for setting the state value of a face or any other value in the face. args A block containing the name and its value. return none The default name is value, which means set the primary value of the face. Here's an example of on-set used by a clock style to set its time: on-set: [ if arg/1 = 'value [ if date? time: arg/2 [time: time/time] face/state/value: time face/facets/clock/set-clock time show-later face ] ] on-clear The on-clear actor is called when a face needs to be cleared. args none return none This actor is called by the clear reactor. It is also called when a panel that contains input fields is cleared with the clear-panel function. on-clear: [ clear face/facets/text-edit show-later face ] on-reset The on-reset actor is called when the face needs to be reset to a predefined initial value. args none return none This actor is mainly used for the reset reactor. on-reset: [ do-style face 'on-set 0 ] Other Actors on-draw The on-draw actor allows you modify a draw block immediately before it is rendered. args the current draw block for the face return the modified draw block This function may be called often, every time a draw-face is needed. You should make this actor as efficient as possible. If it is possible for computations can be performed in other actors, such as on-click, that should be done. Here is an example of the on-draw used by buttons (from the clicker style): on-draw: [ face/facets/area-fill: make-fill face/facets/area-color face/state/mode color: get-facet face 'edge-color if face/state/mode = 'over [color: color / 2] face/facets/pen-color: color arg ; return draw block ]
''Concepts'' PENDING: This document will describe the GUI sub-language.
''Contents'' * Concepts * Using Faces * Primary Functions * Advanced Functions * Face Names * Face Values * Face Object * Style Field * Facets Field * State Field * GOB Field * Options Field * Name Field * Reactors Field * Debugging Techniques * Examining Faces * Face Debug * Red-line Mode * Style Debug * Runtime Debug ''Concepts'' A face is an instance of a [[style|GUI Styles]]. A style holds the default attributes, variables, and functions of a GUI element, but a face object stores the specific values for that instance of the style. For example, a button style may specify a default size, but its actual size as displayed on screen is stored in its face object. Its current position as well as its "clicked" state are also stored in its face object. Panels are collections of related faces used for a specific part of the user interface. The faces within a panel are created during the layout stage of processing where the GUI language (a dialect) is interpreted and its styles create actual faces. A panel is itself a face, and a GUI is created from one or more layers of panels, each of which holds faces of its own. This method of design helps minimize memory requirements. The static variables of a graphical element are kept in its style object to be shared by many instances of that style. Only the dynamic variables of the style need be stored in a face object. The style object also stores the code related to the face, which is reused for every face. ''Using Faces'' Faces are created during the layout of panel. The GUI dialect specifies the styles and attributes required for the GUI, and those are used to construct the faces of the panel. For example, the GUI dialect code below uses the view function to layout a single panel that is displayed in a window. ``` view [ title "Example GUI" field button "Submit" submit ] ``` The title, field, and button styles are specified, and the result will be a panel containing three faces, each associated with those style. Faces can also be created with the make-face function. This function takes a style and an attribute block as its arguments, and returns a new face object. This provides a functional method of creating GUIs (but, it's rarely used, because the GUI dialect is more concise.) ``` b-face: make-face 'button [text: "Submit"] ``` In order to be useful, this new face must be inserted into a panel to be displayed. See the R3 GUI Panels and Layouts section for details. ''Primary Functions'' These functions are the most common for faces: |''Function'' |''Description''|h |view |Create a panel from a dialect block, and display it in a window.| |unview |Close a window opened with view.| |layout |Layout a panel of faces. The panel can be displayed later.| |make-face |Creates a new face object based on a given style with the given attributes.| |get-face |Get the primary value of the face, or a specific state variable of the face.| |set-face |Set the primary value of the face, or a specific state variable of the face, then redraw the face.| ''Advanced Functions'' These functions are used mainly for style implementation or to create special results within a GUI. |''Function'' |''Description''|h |get-facet |Get a named facet of a face. If not present in the face, get the value from the style of the face. Multiple values can be fetch at the same time in a block.| |set-facet |Set a named facet of a face. If not defined, create it.| |do-face |Evaluate the reactor functions for a face. This is provided to allow reactor code from one face to relay actions to another face.| |draw-face |Generate the rendering block for a face, and refresh the face on screen.| |extend-face |Add a new field to the face. This is used by special styles during face creation.| |do-style |Call a style actor function for the face. Used to decouple the face, style, and actor.| |has-actor? |Return true if the face's style supports the given actor.| |do-related |If there are related faces within the same parent panel, call their related actors. This is how faces inter-connect.| |find-face-actor |Find the next (or prior) face that responds to a given actor. This is also used to inter-connect faces by nearness.| ''Face Names'' Each face can have a name. Within a panel, it is useful to refer to a face by its name. For example, a panel that requests a user name and email address might need to refer to those faces within its code. ``` name: field email: field button "Submit" do [ unless verify get-face name [warn "invalid name"] unless verify get-face email [warn "invalid email address"] ] ``` The name and email words are panel-local variables that refer to their respective face objects. Here's another example that attaches a slider to a progress bar. The prog name is used by the slider to refer to the progress bar face and change it as necessary: ``` text "Drag slider to see progress bar change:" slider attach 'prog prog: progress ``` The more about face names is provided below and in the R3 GUI Panels and Layouts page. ''Face Values'' Faces can have one or more values. In the example above, both the slider and the progress faces hold a percentage as their value. The get-face and set-face functions get and set the values of faces. Because the majority of faces have only a single primary value of interest, get-face and set-face refer to the value by default. For example, you can write: ``` slid: slider button "Show" do [print get-face slid] button "Full" do [set-face slid 100%] button "Empty" do [set-face slid 0%] ``` However, it should be noted that there is an even easier way to set the slider that does not require the set-face function: ``` button "Full" set 'slid 100% button "Empty" set 'slid 0% ``` These face reactors are shorthand for the set-face function. ''Face Object'' Users don't need to know much about the structure of the face object just to create GUI's. However, if you plan to implement your own styles, you'll need to know a few things about faces and how they store information related to the style. Some styles may require more storage than others; therefore, face objects are extensible (vary in size.) This minimizes the memory required for faces that do not require extra fields. Every face must have these standard fields: |''Function'' |''Datatype''|''Description''|h |style |word! |The name of the style for this face.| |facets |object! |Attributes that are unique to this face (from style/faced).| |state |object! |Storage for state-related variables (not attributes).| |gob |gob! |The graphical object used to display this face.| |options |object! |Optional attributes specified for this instance.| Depending on how the face was defined, these fields may also be present: |''Function'' |''Datatype''|''Description''|h |name |word! |A name used to refer to this specific face. (For example, to get or set its value.)| |reactors |block! |A block of user actions for this face.| Some styles may add other fields. For example, a panel adds these fields: |''Function'' |''Datatype''|''Description''|h |grid |object! |A table of panel layout parameters and limits.| |faces |block! |A list of sub-faces of the panel.| |triggers |block! |Triggers needed for the panel.| The next few sections are detailed descriptions of the fields above. ''Style Field'' The style field just holds the name of the style, not a direct reference to the style object itself. It's done this way (as a word) to avoid long listings during debugging. ''Facets Field'' The facets object stores attributes that are unique to the instance of the face. That is, it only holds attribute values that are different from the style itself or that may change based on variations in the state of the object (for example a change to a color when the mouse is hovering over a button.) For example, a button might have these face facets: ``` area-size: 24x100 ; set by resize pen-color: 100.50.50 ; set by on-draw area-fill: 200.200.200 ; set by on-draw ``` Note that the face/facets field is merged with the style/facets field during the processing of the DRAW dialect. The face/facets always take precedence over the style/facets. ''State Field'' The state object provides storage for the non-attribute values of a style. For example, a button might keep track of its over and selected states. For a scroll-bar, the scroll value and delta percentages must be stored. An example of the state object for a scroll-bar: ``` value: 0% ; scroller offset delta: 10% ; page size increment ``` Note that the state object is normally small, but can be extended as necessary for specific styles that require extra fields. If you need to store your own internal, non-attribute variables for a face, it's best to store them in this location. ''GOB Field'' The gob field refers to the lower level graphical object that implements face rendering. It is normally a GOB of the draw type; however, for special text sections, it can be a text GOB (richtext). Note that within a face gob the gob/data field is a reference back to the face object itself. This allows the display and event sub-systems to process gobs efficiently. Some faces will use a face/gob/pane to holds sub-gobs to implement various parts of their display. For example, a scroll bar contains several such sub-gobs for its various components. These sub-gobs may or may not be actual faces, depending on how the style is implemented. It should be noted that the gob/offset and gob/size fields are only approximations of the actual graphic image area. This is due to the anti-aliased graphics engine which requires that the gob be large enough to include pixels that are part of the anti-aliased edges of the face.(The same reason why the facet/size and facet/area-size have slightly different values.) ''Options Field'' The options field holds the optional attributes that were provided to the face within the GUI dialect when the face was defined. For example, in the line: ``` button "Submit" ``` The submit string is an option, and it will be stored in the face/options object: ``` text-body: "Submit" ``` What gets stored in the options object is determined by the options field of the style. It is permitted for the face/options object to be used to reset a face back to its initial value. For example, when resetting the fields of a form. If a style requires this ability, it should always copy its option series values in order to be able to restore them later. Note that face actions (reactors) are not stored in this options object. ''Name Field'' When a face is named, the name field holds that name (as a word). Such names can later be used to reference the face object from other faces and functions. The name field comes from the set-word used in the dialect. For example, the area face created in this line: ``` summary: area ``` will have the name summary. The name can now be used to reset or clear the area: ``` button "Reset" reset 'summary button "Clear" clear 'summary ``` For user coding convenience, the face name spans more than just the panel where it was defined. For example, this code works as you would expect, even though the buttons are part of a sub-panel, not the panel in which the field name was defined: ``` panel [ user: field group [ button "Reset" reset 'user button "Clear" clear 'user ] ] ``` In cases where it is necessary to open a new name-space, for example in unrelated sub-panels, this can be done with the style/facet/names field. See the panels document for more information. ''Reactors Field'' The reactors field is a block of names and values for special actions on a face, called reactors. For example, the line below specifies a reset reactor with an argument of summary: ``` button "Reset" reset 'summary ``` This information is stored in the reactors block of the face. Multiple reactors may be specified. Whenever specific events occur, the block is processed to perform various actions. For example, to evaluate code when a button is clicked. ''Debugging Techniques'' There will be times when you create a GUI but do not understand why it displays or acts a certain way. You can experiment around and try different methods, and often you'll find a good solution. At other times, it may get frustrating, and you're not sure what's going on. Sometimes, you really want to know more about what's going on "under the hood". Fortunately, because the R3 GUI system is relatively simple. You can display more information about the GUI and gain an understanding what that information means. ''Examining Faces'' If you plan to write your own styles, you need to understand face objects fairly well. One easy way to learn about faces is to use the make-face function with different styles and options. For example, here's the face that is created for a text style: ``` >> probe make-face 'text [text-body: "test"] make object! [ style: 'text facets: make object! [ area-size: 0x0 text-body: "test" text-color: none size: 200x20 ] state: make object! [ mode: 'up over: false value: none ] gob: make gob! [offset: 0x0 size: 100x100 alpha: 0] options: make object! [ text-body: "test" ] ] ``` ''Face Debug'' If you want to dump (display to the console) a face object created during a layout, just add the word debug on the line. The GUI code: ``` button "Test" debug do [test: true] will dump debug information to the console: -- debug-face[button:make]: make object! [ style: 'button facets: make object! [ area-size: none size: 100x28 area-color: 60.70.150 pen-color: none area-fill: none text-body: "test" wide: none ] state: make object! [ mode: 'up over: false value: none ] gob: make gob! [offset: 0x0 size: 100x100 alpha: 0] options: make object! [ text-body: "test" ] debug: [make] ] ``` Now you can review it and determine all of the facets and other variables are set as you would expect. Keep in mind that this dump occurs just after the face has been made and before any panel-related resizing occurs. ''Red-line Mode'' For face styles that render graphics (contain a DRAW), the face debug method above will also show up as a red box at the edges of the face's clip area (the GOB). Example: ``` Missing image: /-code Missing image: /-code view [button "Test" debug do [test: true]] ``` Notes: This is the true edge of the gob, so for most faces, the red box will be slightly outside the area-size borders of the face. That's because the area-size leaves extra space for anti-aliasing of the face border. If your face draws or fills the entire GOB clip area, the red line will not be seen. (It is underneath the draw graphics.) Styles that dynamically modify their draw blocks using on-draw should be aware that the face debug mode will copy and modify the draw block each time it is rendered (in order to add the red box). ''Style Debug'' When defining new styles you can examine the object that is created in the processby adding a debug field to the style definition: ``` stylize [ thing: [ facets: [ size: 100x100 area-color: blue ] draw: [ circle ] debug: [style] ] ] ``` When the "thing" style is defined, you will see: ``` -- debug-style [thing]: make object! [ name: 'thing facets: make object! [ size: 100x100 area-color: 0.0.255 ] draw: [ circle ] actors: make map! [ locate: make function! [[face arg /local][ arg/offset ]] on-resize: make function! [[face arg /local][ face/gob/size: arg face/facets/area-size: arg - 2x2 ]] on-over: make function! [[face arg /local][ face/state/mode: pick [over up] face/state/over: not not arg draw-face face none ]] on-get: make function! [[face arg /local][face/state/value]] ] options: make object! [ ] parent: none state: none content: none faced: make object! [ area-size: 0x0 ] about: "Not documented." debug: [style] ] ``` Note that you can also use this same method to output the face object each time it is used in a panel. To do so change the debug line to: ``` debug: [style make] ``` ''Runtime Debug'' You can globally enable debugging throughout the GUI system for monitoring various functions and events. The GUI module object includes a debug field that can be set to a block of debug flag words. They are: |Flag |Description|h |make-style |when stylize creates a new style| |do-style |when a style actor is invoked| |draw |when a draw block is reduced| |events |to monitor events as they occur| |dialect |to watch panel GUI dialect| These can always be found simply by scanning source modules for "debug-gui" calls. For example, the line: ``` guie/debug: [events draw] ``` will show all events and draws. Output will look like this: ``` -- draw tight -- draw text-list -- draw scroller -- draw scroller -- draw code-area -- draw text-box -- draw scroller ... -- events move 380x113 -- draw text-box -- events move 336x102 -- events move 320x93 -- events move 301x85 -- events move 285x83 -- events move 268x83 ==Debug Functions== ``` Two internal debug functions can be called from your code: |Function |Description|h |dump-face |print information about a face| |dump-panel |print information about a panel| An example of dump-face is: ``` view [ example: button "Test" do [dump-face face] ] ``` When you click on the button, you will see: ``` button: 10x10 size: 100x28 example "Test" ``` This shows the button style location, size, name, and data. An example of dump-panel is: ``` view [ pan: panel [ button "Dump" do [dump-panel pan] button "Quit" quit ] ] ``` and it will output: ``` panel: 10x10 size: 120x81 pan "*" button: 10x10 size: 100x28 * "Dump" button: 10x43 size: 100x28 * "Quit" ``` It shows the panel face and all of its sub-faces, even if they are sub-panels. The asterisk means that the field has not been set.
''Contents'' http://www.rebol.com/r3/docs/gui/panels.html * Concepts * Using Panels * Panel Functions * Panel Object is a Face * Panels for Layout * Panel Variations * Multiple Columns * Horizontal Only * Combining Panels * Input Form Panel * Panel Spacing * Margins and Spacers * Extra Pad Spacing * Panel Sizing * Size, Min-size, Max-size * Size Computation * Examples * Linking Related Faces * Named Relations * Proximity Relations * Transition Effects * Other Predefined Panels * Defining Panel Styles Concepts A panel is a layout of faces. Panels are collections of related faces used for specific parts of a user interface. The faces within a panel are created during the layout stage of processing where the GUI language (a dialect) is interpreted and its styles create actual faces. The GUI system has been designed to make panels very easy to create, debug, and maintain. One of the main goals was for simple GUI definitions to be able to create a wide range of simple, predictable results, but also to allow more sophisticated and elaborate results to be produced using the same set of basic rules. Basically, panels provide a way to: Group a number of faces together, Arrange faces into a desired layout, Display a 2D layer, with background or other effects, Update and resize those faces when events occur. Every window of the GUI display is a panel, and each contains a number of sub-panels to further divide its area into sections. And, a panel is itself a face, and a GUI is created from one or more layers of panels, each of which holds faces of its own. The faces that compose a panel are defined using the GUI language, a special dialect of REBOL. This approach saves time and effort compared to function-based or tag-based languages. Using Panels Panels are fundamental to the GUI. When you open a new window like the one defined below, you are creating a panel. Missing image: /-code Missing image: /-code view [ text "Example window." button "Close" close ] Here the view function internally calls the make-panel function that takes the GUI dialect block and builds a panel object as a result. The panel contains two faces: one of the text style and one of the button style. Panels are often used to divide other panels with subpanels: Missing image: /-code Missing image: /-code view [ panel [ text "Show website" button "Show" browse http://www.rebol.com ] panel [ text "Example window." button "Close" close ] ] This window panel contains two subpanels. New panels can also be created directly with make-panel, and then dynamically added to other panels and displayed. b-panel-gui: [ text "Example window." button "Close" close ] b-panel: make-panel 'group b-panel-gui none switch b-panel a-panel 'fly-up This code creates a new panel then switches to display it with the fly-up transition. Panel Functions The GUI functions that deal with panels are: Function Description view Create a panel and display it in a window. set-panel Set panel input face values from a block of values. get-panel Get panel input face values as a block. clear-panel Clear panel input face values. parse-panel Parses the panel dialect and returns a block of faces/commands. layout-panel Layout a panel by setting faces sizes and offsets. resize-panel Resize a panel face, layout its subfaces, render it. effect-panel Display a panel transition effect. switch-panel Switch the contents of a panel, using the effect if specified. get-parent-panel Get panel input faces for the contextual parent panel. get-panel-var Get the value of a top level panel/names local variable. Panel Object is a Face Panels just use the face object, with a few extra fields added: Field Datatype Description grid object! Layout parameters and limits, mainly for sizing. faces block! A list of the faces within the panel. triggers block! Triggers used for the panel. These fields are used mainly by the GUI system, not by end-user code. Also, additional fields may be appended by special panel styles. Panels for Layout Panels provide an efficient and elegant mechanism for laying out the elements of a GUI. A panel is defined as a collection of faces. When specified within the GUI dialect, the order of the style names determines their positions within the panel area. For example, using the code below, you'll see the buttons positioned in that same order vertically: Missing image: /-code Missing image: /-code panel [ button "First" button "Second" button "Third" ] Panel Variations As you can see above, the default layout direction is vertical. Faces are positioned from top to bottom. However, several variations in layout are possible, and a few predefined styles are available that can be used in various combinations to create a wide variety of layouts. Style Description panel Provides a backdrop with a border around it and arranges its contents vertically by default. group Does not include a backdrop, and its contents are arranged horizontally by default, and, a group has no margin. tight Is a group that has both margin and spacer set to zero. The examples below show the main differences between the panel and group styles. Here's a panel layout. It's default orientation is vertical and it has a border: Missing image: /-code Missing image: /-code view [ panel [ button "First" button "Second" ] ] And, here's a group layout. It's default orientation is horizontal, and it has no border: Missing image: /-code Missing image: /-code view [ group [ button "First" button "Second" ] ] And this is a tight layout. It's also horizontal by default, but with minimal spacing between elements: Missing image: /-code Missing image: /-code view [ tight [ button "First" button "Second" ] ] This table summarizes the main differences between these panel styles: Style Direction Backdrop Border Spacing panel vertical yes yes normal group horizontal no no normal tight horizontal no no none Multiple Columns You can specify the number of columns for a panel or group styles. This is convenient for many layouts, such as input forms that contain multiple labels and input fields. Here's an example two column panel: Missing image: /-code Missing image: /-code view [ panel 2 [ button "First" button "Second" button "Third" button "Fourth" button "Fifth" button "Sixth" ] ] The buttons are laid out in columns first, then rows. The number of rows is simply determined by dividing the total number of faces by the number of columns. Note that columns work for group panels too: Missing image: /-code Missing image: /-code view [ group 2 [ button "First" button "Second" button "Third" button "Fourth" button "Fifth" button "Sixth" ] ] Continuing on, here is a three column panel layout: Missing image: /-code Missing image: /-code view [ panel 3 [ button "First" button "Second" button "Third" button "Fourth" button "Fifth" button "Sixth" ] ] And if we show four columns, note that we don't have enough buttons. In such cases, the remaining cells are padded with blanks. Missing image: /-code Missing image: /-code view [ panel 4 [ button "First" button "Second" button "Third" button "Fourth" button "Fifth" button "Sixth" ] ] Horizontal Only If you need a strictly horizontal layout a special value of zero is used. This is a similar layout to a group panel, but includes the border and background. view [ panel 0 [ button "First" button "Second" button "Third" button "Fourth" button "Fifth" button "Sixth" ] ] <img src="http://www.rebol.com/r3/docs/graphics/gui-panels-horiz.png"/> The zero indicates a single row using as many columns as necessary. Note that you don't need this for group panels, because horizontal layout is their default. Combining Panels To create a wide variety of layouts, you can combine panel and group styles in various ways. For example, here's a group of panels of buttons: Missing image: /-code Missing image: /-code view [ group [ panel [ button "First" button "Second" ] panel [ button "Third" button "Fourth" ] panel [ button "Fifth" button "Sixth" ] ] ] But, here they are stacked in a different order: Missing image: /-code Missing image: /-code view [ group 1 [ panel 2 [ button "First" button "Second" ] panel 2 [ button "Third" button "Fourth" ] panel 2 [ button "Fifth" button "Sixth" ] ] ] The example below shows how different numbers of elements can be grouped on separate rows: Missing image: /-code Missing image: /-code view [ group [ button "First" button "Second" ] group [ button "Third" button "Fourth" button "Fifth" ] group [ button "Sixth" button "Seventh" button "Eighth" button "Nineth" ] ] Input Form Panel Of course, the above layouts are just for illustration. A real panel might look more like: <img src="http://www.rebol.com/r3/docs/graphics/gui-opinion-form.png"/> Opinion survey form (alpha skin) Opinion survey form (alpha skin) And, it's code is: view [ title "Opinion Survey" text "Do you want programs to be easy to build?" panel 2 [ label "Answer:" group [ radio "Agree" radio "Disagree" radio "Not sure" ] pad check "I'm a programmer." pad check "I am also a REBOL expert." label "Name:" field label "Comment:" area pad ; temporary, for bug ] group [ button "Submit" submit http://www.rebol.net/cgi/submit.r button "Reset" reset button "Cancel" close ] ] For more examples, see R3 GUI - User's Guide. Panel Spacing The panel style defines the spacing for its layout. The spacing consists of a margin at the panel's edges and the spacer size between each face that it contains. Missing image: /get Missing image: /get Margins and Spacers The margin and spacer are style options and can be specified in the options block. Both values are pairs, so they can define both horizontal and vertical spacing in pixels. Here are a few panels with specified options: Missing image: /-code Missing image: /-code view [ panel [ button "1" button "2" button "3" ] panel [ button "1" button "2" button "3" ] options [margin: 30x30] panel [ button "1" button "2" button "3" ] options [ margin: 30x30 spacer: 20x20 ] ] Also, keep in mind that a group style defines its margin as 0x0 and a tight style defines both its margin and its spacer as 0x0. Extra Pad Spacing From time to time you may need additional spacing between faces in a panel. The pad style has been defined to help with this. The pad style can be used with or without optional size information. When used alone, it expands space automatically. Or, you can give it an exact size. Here are a few examples: Missing image: /-code Missing image: /-code view [ panel [ button "1" button "2" button "3" ] panel [ button "1" pad button "2" button "3" ] panel [ button "1" pad 10x20 button "2" button "3" ] ] Note that a pad spacer is an actual face, so when used with columns, it will count as the element of a cell. Missing image: /-code Missing image: /-code view [ panel 2 [ button "1" button "2" pad button "3" ] ] Panel Sizing The size of a panel is determined by its elements and by the size available for it (for example, by the size of the screen or window). And, within a panel, the rows and columns that make up its layout may be of different widths and heights. In general the rules are: The widest element of a column will set the column width. The tallest element of a row will set the row height. Columns and rows can be smaller or larger than these values, depending on the availability of space for expansion. Size, Min-size, Max-size More specifically, the sizes of elements are determined by their sizes, as set by their styles or by their face instance. Each style, hence each face, can specify three sizes: Facet Description size called the natural size of the face, this is the size it "wants to be" min-size the smallest size allowed max-size the largest size allowed These sizes are all pair! values, so the include both the x (width) and y (height) values. For example, a text field can normally be 300x24, but be allowed to shrink to 100x24 or expand to 500x24. Such a style definition would look like this: my-field: field [ facets [ size: 300x24 min-size: 100x24 max-size: 500x24 ] ] Size Computation The size of a panel is determined by the combined sizes of its elements (faces within it) or by a size specified for it (from its options). Before any panel sizing can be done, the system must determine for each column and each row: the largest size the largest min-size (e.g. smallest width allowed) the largest max-size (e.g. limit of column growth) Now the system can compute, as sums of the above: the panel's natural size the panel's min-size the panel's max-size The resizing algorithm then works like this: If panel size is unknown, use the natural panel size computed above and locate each face according to the natural sizes of all the columns. Add margins and spacing. If panel size is specified, then compute width percentages of each column. This is a bit tricky because we must examine if faces allow min-size and max-sizes. If so, then those values must be used rather than their natural size. In this way, faces can shrink or expand as necessary. When a face is expanded, the rate of its expansion is determined by its max-size. A larger max-size will expand the face at a greater rate within the same row or column, as compared to faces of smaller max-sizes. Panels can be resized by the user, such as when a window size is changed, or by the program itself. When a panel is resized, the layout is recomputed according to the same rules as above. All of the faces within it will be resized as necessary, including all sub-panels and groups. Examples This code provides a good comparison for how GUI faces are resized according to their max-size option. The window shows five groups, each that contains three colored boxes. Each box is the same style, but changes its max-size option to a different value. Resize the window to see the resizing of each box: stylize [ boxa: box [ facets: [size: 32x32] draw: [ pen 0.0.0 line-width 1.2 fill-pen area-color box 1x1 area-size 3 ] ] pada: pad [ facets: [max-size: 10x10] ] ] view [ group [ boxa red boxa green boxa blue ] group [ boxa red options [max-size: 100x32] boxa green options [max-size: 200x32] boxa blue options [max-size: 400x32] ] group [ boxa red options [max-size: 100x32] boxa green options [max-size: 2000x32] boxa blue options [max-size: 4000x32] ] group [ boxa red options [max-size: 100x32] pad boxa green options [max-size: 2000x32] pad boxa blue options [max-size: 4000x32] ] group [ boxa red options [max-size: 100x32] pada boxa green options [max-size: 2000x32] pada boxa blue options [max-size: 4000x32] ] ] Here's how the window is first opened: <img src="http://www.rebol.com/r3/docs/graphics/gui-panels-sizing-1.png"/> And if it's resized to 600 pixels wide, it will look like: <img src="http://www.rebol.com/r3/docs/graphics/gui-panels-sizing-2.png"/> Here are some features to observe: The first group of boxes all expand by an equal amount. The second group expands the green box at twice the amount of the red box, and the blue box at four times that amount. Also note that if you expand the window large enough, each of the boxes will stop expanding at their max-size values. (You will not see that effect if the window is too small.) The third group shows a more extreme example, where the green and blue boxes are expanded by a lot more than the red box. The red box has only expanded by a small amount (if at all). The fourth group adds some pad faces between the boxes. Notice that by default, the pads add substantial space. The fifth group uses the pada style which limits the max-size. Notice that the pad spaces are much smaller. Linking Related Faces Within a GUI there are times when you need to link or attach one face to another. Change to one of the faces affects the other. For example, a scroll bar may cause a text panel to scroll its contents. There are two methods of relating faces: named relations and proximity relations. They are explained below. Named Relations You can give a name to a face and that name can be used from other faces to perform specific actions. For example: prog: progress slider attach 'prog Here attach is a reactor that "connects" the slider value to the progress bar. The prog face name is used to do that, and be sure to note that the name must be a literal word where it is referenced. It should be noted that all names are scoped to their primary panel, so you can refer to a name from other panels within the primary panel. For example, this still works, even though the prog name is used from a different panel: prog: progress panel [ text "Move this slider:" slider attach 'prog ] Note: the names facet of a parent controls the scope of names. Proximity Relations Some faces can automatically attach themselves to other faces that are nearby. For example, a scroller will attach itself automatically to any prior face that includes an on-scroll actor. This feature makes it easy to attach scroll bars to text areas and panels without requiring names. Here is an example: group [ text-area (read-string %file.txt) scroller ] This works the same way as if you wrote: group [ ta: text-area (read-string %file.txt) scroller attach 'ta ] Transition Effects Animated transition effects can be used to switch from one panel to another. The effects are specified as an argument to the switch-panel function. Currently, these effects are defined: Effect Description fly-right fly on from left to right fly-left fly on from right to left fly-up fly on from bottom to top fly-down fly on from top to bottom Other Predefined Panels add table Defining Panel Styles docs needed
''Contents'' http://www.rebol.com/r3/docs/gui/reactors.html * Concept * Using Reactors * Standard Reactors * Multiple Reactors * Creating Custom Reactors * Calling Reactors * Examples Concept Events on GUI faces trigger reactors. When a user pushes a button, something happens. The GUI reacts to user input. The result may be a common action such as opening or closing a window, or it may be a very specific action. A reactor is just a type of shortcut for a common action. They make the GUI easier to use by eliminating the need to write detailed code. Reactors are attached to faces and are invoked by the actors of its style. A reactor can include a single argument value. If more than one argument is needed, they must be enclosed in a block. Multiple reactors can be attached to the same face. Each reactor is processed in the order that it appears, so the consequences of a reactor's actions must be considered; it can impact the reactors that follow. Using Reactors Reactors are specified in the GUI dialect that is used to create a panels. For example, here's a panel that opens a window and displays three buttons, each of which that specifies a reactor: view [ button "REBOL" browse http://www.rebol.com button "Alert" alert "This is an alert." button "Close" close ] The obvious actions occur when each button is pressed. The browse reactor opens a web browser, the alert opens a pop-up alert panel, and close will close the current window. Standard Reactors These reactor functions are provided as a standard part of the GUI: Reactor Description alert open an alert message box window attach set a target value to our value back return to prior panel (on panel stack) browse open web browser to given URL call run a shell script on local OS clear clear face value (empty it) close close the window debug trace face operation do evaluate a REBOL block, file, or URL download opens download progress panel, starts download dump probe the contents of the related face object edit opens editor for specified content halt halt the interpreter link fetch reb content and evaluate it launch run file or URL in a new instance of REBOL open open a file using local OS methods quit exit the application play plays a sound print print output reset reset face to original value scroll scroll a target face send sends a message to a target set set the state of another face submit submit face (or panel) to service or website undo undo last change upload opens upload progress panel, starts upload view view a new "page" Here are a few examples: button "Alert" alert "This is an alert." button "Browse" browse http://www.rebol.com button "Close" close button "Do" do [alert "It worked!"] button "Dump" dump button "Halt" halt button "Launch" launch %test.r button "Print" print "print to console" button "Quit" quit button "Run" run %explorer.exe button "View" view [button "Close" close] f1: field "Field 1" button "Focus on 1" focus 'f1 Multiple Reactors A face can have more than one reactor. Each reactor is processed in the order that it appears. The example below shows how two fields are reset using a single reset button: user: field pass: field button "Reset" reset 'user reset 'pass Reactors are processed from left to right, so be sure to consider that. For example, this line works: button "Submit" submit cgi-url clear 'user But, in this line the field is cleared, so the submitted text is empty: button "Submit" clear 'user submit cgi-url So, that's not useful. Creating Custom Reactors The make-reactor function can be called to create custom reactors for your GUI. One or more new reactors can be defined. The format of a reactor definition is similar to that of a function, except the function creator such as func is not used. Here's an example reactor definition: make-reactor [ my-browse: ["Open web browser." arg [url! file!]] [browse arg] ] Calling Reactors When implmenting a style actor, when a final result is known, it may be necessary to call one or more face reactors. The do-face function calls reactors. This line calls all reactors: do-face face To call a specific reactor, you can write: do-face/only face 'reactor where reactor is its name. Examples Here's an example panel that uses a few different reactors: view [ panel 2 [ button "Do" do [request "Got it!" "It worked."] button "Browse" browse http://www.rebol.com button "Run" run %explorer button "Alert" alert "This is an alert." ] panel 2 [ f1: field "Field 1" f2: field "Field 2" button "Focus on 1" focus 'f1 button "Focus on 2" focus 'f2 ] panel 2 [ button "Close" close button "Halt" halt button "Quit" quit button "Print" print "print this message" button "Dump" dump ] ]
''Contents'' http://www.rebol.com/r3/docs/gui/styles.html * Concepts * Using Styles * With a Layout * With Make-Face * Predefined Styles * Defining Styles * Style Functions * Definition Format * Style Object * Standard Facet Names * Example Definitions * Simple Variation * New Style * Facet Attributes * Options * Local Attributes and Actors * View All Styles * Advanced Examples * Progress Bar * Slider bar (numeric value input) Concepts Styles define GUI elements. A GUI is built from a collection of styles, such as button, field, text, and image. In essence a style defines a class of user interface object, specifying the attributes, variables, and functions that are used to create and operate that object. An instance of a style is a face, one or more of which are displayed in a panel. Every style has a name that refers to the style during the construction of a GUI, within documentation, or later for debugging purposes. For example, button is the name for a style that looks and acts like a push-button. Styles can be collected into a style-sheet that provides all of the definitions for the desired look and feel of a GUI. Style-sheets can be global across an entire application, or local to a specific section of the application. The GUI system supplies a default style-sheet that includes a standard set of useful styles. Using Styles GUI styles are used in two main ways: To create face objects to be displayed in the GUI. Styles create faces from a layout block (with the GUI dialect) provided to the view function and panel panels, or by calling the make-face function directly. To create new styles from existing styles. The new styles can be simple graphical changes or deeper modifications to the behavior of the style. For example, a cancel-button style might be defined from a plain button, but with a different color, shape, or default action. With a Layout Here's an example of styles used within a layout block. view [ text "Enter your name:" field button "Submit" ] The words text, field, and button are the names of styles. They are used here to create faces that will be shown in the GUI when the window is created. With Make-Face You can also create a face from a style by calling the make-face function directly and providing the style's name and specification block: btn-face: make-face 'button [text: "Submit"] For more examples, see the R3 GUI Faces section. With regard to the creation of new styles from existing styles, that is the subject covered in detail below. Predefined Styles The system defines a standard set of styles that implement the basic set of graphical elements (the widgets) of a GUI. !add full list of styles, this is just a start Style Description area text input area button expandable button draw scalar vector graphic field text input field image bitmap image h1 heading of level 1 h2 heading of level 2 scroller scrollbar slider sliding controller text section of text toggle toggle button Defining Styles Styles are normally defined form existing styles. This approach saves time because you only need to define the additional attributes required by the new style. When it comes to defining new styles, there are three common patterns, depending on how close existing styles are to what you need: Minor variations of another style. Often for commonly reused element of your GUI. These make simple changes to the color, size, or other basic attributes. Derived from another style. Starts with a basic foundation from another style, but makes substantial additions to its attributes, rendering, or actor functions. Entirely new style. When no other styles have what you need, you must build one from scratch. This will require greater knowledge of the system. Style Functions New styles are created by providing a definition block to the stylize or make-style functions: Function Description stylize Define one more more new styles from a block of names and definitions. The specification of the style is provided in a block format, similar to that used by objects. make-style Define a new style of a given name. A parent style can be specified. The specification of the style is provided in a block format, similar to that used by objects. Note that various other functions related to styles can be found on the R3 GUI Faces page. Definition Format In order to make style definitions easier to create and maintain, the stylize function accepts a special declaration format of the general syntax: new-style: parent-style [specifications] The specifications block consists of field names followed followed by their settings, attributes, or functions. The field names are those used by the style object, described in the next section. Here's an example of the actual style definition for button: button: clicker [ about: "Single action button with text." facets: [ size: 100x28 max-size: 200x28 min-size: 50x24 text-body: "Button" text-style: 'button ] options: [ text-body: [string! block!] area-color: [tuple!] size: [pair!] wide: [percent!] ] ] This simple style is based on the clicker style which defines the main actor functions, as reused for buttons. It adds a new about string, a few new facets, and some options. Many examples will be shown below. Style Object A style object includes at least these fields: Field Datatype Description name word! Identifies a style for construction or debugging purposes. The system finds styles by their unique names. Example names: button and text. about string! A short summary of the style for display by help and documentation functions. parent word! The name of the parent style. For example, the parent of button is a clicker. facets object! Holds named attributes that are referenced within other parts of the style. For example the size or area-color of the style. options object! Optional attributes that are used inline within the GUI definition as shortcuts. For example, a pair value may specify the size of an object. actors map! Functions that are called by the GUI system at specific times for specific purposes. For example, on-click and on-resize. draw block! A block of draw commands and their arguments that are used to render the style into a displayed image. faced object! Face defined fields. These are special variables used by the style within the face object. state block! Holds the prototype definition for the face instance variables used by a style. content block! The panel layout for composite styles. Standard Facet Names Although you can add any facet name you want, many functions of the GUI depend on standard names. For example, the area-color is used for creating the gradient backgrounds of most graphical elements. Some of the common names are: Name Description size define area-size define area-color define pen-color define area-fill define edge-color define add complete list! Example Definitions Here are some examples of the most common style creation methods. Simple Variation Here is a very simple variation on a style. It's called red-box, and it is based on the box style. It makes only one change, to define a new facet for the area-color. The rest of the style is inherited from the box style which is a base-style of the GUI system. Missing image: /-code Missing image: /-code stylize [ red-box: box [ facets: [area-color: maroon] ] ] view [red-box] It should be noted that to make a new style from an existing style, you must know the names the facets and how they are being used. In the code above, we know that area-color controls the background color of the box. When you are not sure of what facets are used, you can review the definition of the parent style. Here's another example of stylize that creates a new button style of a different color and default text label: Missing image: /-code Missing image: /-code stylize [ stop-button: button [ about: "Implements a red stop button" facets: [ area-color: 200.0.0 text-body: "Stop" ] ] ] view [stop-button] New Style Here's an example of a completely new style called circle that draws a circle of a fixed size and color: Missing image: /-code Missing image: /-code stylize [ circle: [ about: "A circle style" facets: [ size: 100x100 ] draw: [ pen black line-width 2.7 fill-pen maroon circle 50x50 40 ] ] ] view [circle] The facets block provides the size for the face and the draw block provides the drawing instructions. Of course, this is just a static circle style with no variations, so let's add a few. Facet Attributes Taking the above circle style, we want to parameterize its size and color. This allows its attributes to be specified later, when it is used within a GUI. Running this code and resizing the window, we see: Missing image: /-code Missing image: /-code stylize [ circle: [ about: "A resizable circle style" facets: [ size: 100x100 max-size: 1000x1000 area-color: maroon edge-color: black ] draw: [ pen edge-color line-width 2.7 fill-pen area-color circle (area-size / 2) ((min area-size/y area-size/x) - 3 / 2) ] ] ] view [circle] Several fields have been added to the facets, and you can see how they are used in the draw block. Notice the max-size field; it allows the face to resize automatically. The draw block includes a bit of math to help compute the new values. Note that in the draw block, you can obtain the inner size of the face using area-size, which is a standard facet for all styles and thus not displayed in the facets block above. When displayed, if a size is not provided, it will use its default size. However, it can be resized. If you enter this example, drag the window corner to see the circle resize automatically. Options An option is an attribute that can be specified directly within the GUI layout code. For example, let's allow the circle color to be provided as an option. In addition, let's expand the code to use that color to make a gradient within the circle. Missing image: /-code Missing image: /-code stylize [ circle: [ about: "A colorable resizable circle style" facets: [ size: 100x100 max-size: 1000x1000 area-color: maroon edge-color: black ] options: [ area-color: [tuple!] ] draw: [ pen edge-color line-width 2.7 grad-pen radial (area-size / 2) 0 ((min area-size/y area-size/x) - 3 / 2) (span-colors area-color [2.0 .2]) circle (area-size / 2) ((min area-size/y area-size/x) - 3 / 2) ] ] ] view [ circle red circle green circle blue ] Resize the window, and you will see all three automatically resize. Local Attributes and Actors You will notice that the above example recomputes a few values in the draw block every time the object is redrawn. Normally, this is not a problem, but if those computations were more complex, they may add a lot of extra time to the redraw, slowing down the GUI. Instead, you can move some of those computed values out of the draw block, and make them attributes of the face. Then, you add some code to compute the values only when necessary. Here's an example: stylize [ circle: [ about: "Draws a resizable circle." facets: [ size: 100x100 max-size: 1000x1000 edge-color: black area-color: maroon ] options: [ area-color: [tuple!] ] faced: [ area-fill: none diameter: 50 ] draw: [ pen edge-color line-width 2.7 grad-pen radial (area-size / 2) 0 diameter area-fill circle (area-size / 2) diameter ] actors: [ on-make: [ face/facets/area-fill: span-colors get-facet face 'area-color [2.0 .2] ] on-resize: [ ; arg is the size face/gob/size: arg face/facets/area-size: arg - 2 face/facets/diameter: (min arg/y arg/x) - 5 / 2 ] ] ] ] view [ circle red circle green circle blue ] The faced block is similar to facets block, but makes them local to each instance of the face. Now, they can be modified without effecting any other faces that are of the same circle style. The actors block defines a few actor functions that are called from the GUI as needed. The first computes the area-fill when the face is created. The second handles resizing, recomputing the size of the face and the diameter of the circle. Notice that within the actor functions, the face variables must be referenced via the face object itself. The faced variables of the style are stored in the facet object of the face. You should note the use of get-facet for obtaining the area-color. This allows the area color to be obtained from the style facets or from the face facets, depending on if it was changed in the options line. This is the general method for obtaining the attributes of a style. On the other hand, when you set an attribute, it must be part of the face facets. You are not allowed to directly modify the facets of the style itself, or you would change all faces of that style, affecting the entire GUI! View All Styles Here's an example that's a little bit extreme. It creates a three column window that shows all predefined viewable styles: all-styles: find extract to-block guie/styles 2 'clicker view repend [group 3] [all-styles] We'll let you run it for yourself to see the results (because the window is too large to show in this document.) Here's a more elaborate example that creates a list of the predefined styles, then let's you view each one separately. Missing image: /-code Missing image: /-code all-styles: find extract to-block guie/styles 2 'clicker last-view: none view/options [ title "Pick a style:" text-list all-styles do [ if last-view [unview last-view] style-name: pick all-styles value last-view: view/options reduce [ 'title reform ["Example of a" style-name "style:"] style-name ][offset: 'center] ] ][offset: 50x50 size: 200x400] The last-view variable provides a way to close the prior windows, otherwise you'd end up with a many windows on top of each other. Advanced Examples A number of other example styles can be found in the source code to the GUI system. They range from simple styles of just a few lines (e.g. a button) to advanced styles that may require one or two pages (e.g. a scroller). Progress Bar A progress bar is just an output display bar that can be set from your program or from other GUI objects. Here's an example using the predefined progress style: Missing image: /-code Missing image: /-code view [ prog: progress button "Set 50%" set 'prog 50% ] Normally, you won't need to create your own progress bar style, but if you did here's an example of what it might look like: stylize [ my-progress: [ about: "Progress bar." facets: [ size: 200x22 max-size: 1000x22 edge-color: 96.96.96 area-color: 80.80.80.128 area-fill: span-colors area-color [.3 .5 1] ] options: [ bar-color: [tuple!] size: [pair!] ] faced: [ bar-color: teal bar-size: 1x1 ; modified by the progress % value bar-fill: ; generated from bar-color option ] draw: [ pen edge-color line-width 1.5 grad-pen 1x1 0 20 90 area-fill box 1x1 area-size 3 grad-pen 1x1 0 20 90 bar-fill box 1x1 bar-size 3 ] actors: [ on-make: [ face/facets/bar-fill: span-colors get-facet face 'bar-color [1.0 1.5 .6] ] on-set: [ ; arg: event ; Update the bar size from the face value. face/state/value: arg/2 v: clip-face-val face size: get-facet face 'area-size face/facets/bar-size: as-pair v * size/x size/y ] ] ] ] view [ prog: my-progress button "Set 50%" set 'prog 50% ] Slider bar (numeric value input) Here's a much more advanced example that shows how the slider style was defined. A slider bar is an input device that for setting a value between 0% and 100%. Here's an example using the predefined slider style: Missing image: /-code Missing image: /-code view [ slider attach 'prog prog: progress ] Normally, you won't need to create your own slider style, but if you did here's an example of what it might look like: stylize [ my-slider: [ about: "Slide-bar for numeric input (0% - 100%)" facets: [ size: 200x22 max-size: 1000x22 edge-color: 96.96.96 area-color: 80.80.80 area-fill: span-colors area-color [0.5 2.0] ] options: [ size: [pair!] knob-color: [tuple!] ] faced: [ area-size: none knob-color: red knob-xy: bias-xy: 6x0 ; pointer adjustment at ends ] draw: [ pen edge-color line-width .4 grad-pen 1x1 0 4 90 area-fill box 1x1 area-size 3 line-width 1.5 fill-pen knob-color translate knob-xy triangle -6x16 0x2 6x16 ] actors: [ on-resize: [ ; arg: size face/gob/size: arg face/facets/area-size: arg - 2 * 1x0 + 0x6 do-style face 'on-update none ] on-update: [ ; Compute the knob offset from face/value: val: clip-face-val face bias: face/facets/bias-xy size: face/facets/area-size - bias - bias face/facets/knob-xy: val * size * 1x0 + bias ] on-offset: [ ; arg: offset ; Compute face/value from knob offset: bias: face/facets/bias-xy arg: max 0x0 arg - bias size: face/facets/area-size - bias - bias axis: face-axis? face face/state/value: val: min 100% max 0% to-percent arg/:axis / size/:axis face/facets/knob-xy: val * size * 1x0 + bias ] on-click: [ ; arg: event if arg/type = 'down [drag: init-drag face arg/offset] do-style face 'on-offset arg/offset if arg/type = 'down [ draw-face face return drag ] do-face face ; Click UP: compute percentage value from xy offset none ; handled event ] on-drag: [ ; arg: drag do-style face 'on-offset arg/delta + arg/base draw-face face do-face face ] on-set: [ ; arg: [field value] if all [ 'value = first arg number? second arg ][face/state/value: second arg] do-style face 'on-update none ; will clip value range ] ] ] ] view [ my-slider attach 'prog prog: progress ] For details about the actor functions above, see the R3 GUI Actors section. Here is a quick summary of the ones used above: Actor Description on-resize changes the gob and area sizes, then calls update to recompute the knob location. on-update is a general update function that recomputes the knob location. on-offset is used during mouse input to convert the mouse position to the actual state value, which is a percentage between 0% and 100%. It also updates the knob location, just to save time. on-click handles the mouse button when it is clicked in the bar. First, the knob is moved to where the click occurred. Then, if the user starts to drag, the drag operation begins. on-drag takes care of the drag operation, updating the value as needed, depending on the location of the mouse. on-set handles setting the slider from another GUI object or from the program. It's main job is to make sure the value is valid, then update the slider. Descriptions of various other functions can be found in the R3 GUI Faces section.
Note We're still testing out R3. If you're going to try it, please be sure to read the introductory docs found on ''DocBase''. This page will change as R3 moves toward final release. Please read the ''R3 Alpha page''. Pay attention to the warnings. !!! ''Contents'' * [[Quick download]] * [[Try it on your system]] * [[Important notes!]] !!! ''Quick download'' {{Quick download}} !!! ''Try it on your system'' {{Try it on your system}} !!! ''Important notes!'' {{Important notes!}}
Usually, you can setup your favorite programming text editor to make code development go much quicker. Each text editor does this differently. For instance, in some editors, you will use the language compiler options. Specify the REBOL program rather than a compiler. Then you can press a single key that saves the script and evaluates it.
!!! ''Contents'' * [[In general]] * [[Online help]] ** [[Help on help]] ** [[Help about a function]] ** [[Help search]] ** [[Help on objects]] ** [[Help on errors]] * [[Community chat]] * [[Listing built-in functions]] * [[Viewing source code]] * [[More detailed help with errors]] !!! ''In general'' {{In general}} !!! ''Online help'' {{Online help}} !!! ''Community chat'' {{Community chat}} !!! ''Listing built-in functions'' {{Listing built-in functions}} !!! ''Viewing source code'' {{Viewing source code}} !!! ''More detailed help with errors'' {{More detailed help with errors}}
!!! ''In this section'': * Get the program and try it: [[Download and test|Guide: Basics: Download and test]] * Run scripts with: [[Running scripts (programs)|Guide: Basics: Running scripts (programs)]] * How to edit scripts: [[Editing scripts|Guide: Basics: Editing scripts]] * Learn where to get help: [[Getting help and advice|Guide: Basics: Getting help and advice]]
There are several ways to run a script. !!! ''Contents'' * [[Run from an icon]] * [[Run from a command shell (CLI)]] * [[Run from the console]] * [[Run from an editor]] * [[Run from embedded files]] * [[Run from a web server as a CGI script]] * [[Scripts need a header]] !!! ''Run from an icon'' {{Run from an icon}} !!! ''Run from a command shell (CLI)'' {{Run from a command shell (CLI)}} !!! ''Run from the console'' {{Run from the console}} !!! ''Run from an editor'' {{Run from an editor}} !!! ''Run from embedded files'' {{Run from embedded files}} !!! ''Run from a web server as a CGI script'' {{Run from a web server as a CGI script}} !!! ''Scripts need a header'' {{Scripts need a header}}
To create REBOL scripts, you need to understand its basic syntax. !!! ''Contents'' * [[What makes a language?]] * [[Elements of the language]] * [[Special characters]] * [[Words]] * [[Values]] * [[Blocks]] * [[Comments]] !!! ''What makes a language?'' {{What makes a language?}} !!! ''Elements of the language'' {{Elements of the language}} !!! ''Special characters'' {{Special characters}} !!! ''Words'' {{Words}} !!! ''Values'' {{Values}} !!! ''Blocks'' {{Blocks}} !!! ''Comments'' {{Comments}}
This section describes conditional evaluation. Be sure you know the basics of evaluation from the prior section: [[Code: How code is evaluated|Guide: Code: How code is evaluated]]. !!! ''Contents'' * [[What is true?]] * [[If then]] * [[Either or]] * [[A common mistake]] * [[Any and all]] * [[Case of many]] * [[Switch on value]] * [[Conditional loops|Guide: Code: Conditional evaluation: Conditional loops]] !!! ''What is true?'' {{What is true?}} !!! ''If then'' {{If then}} !!! ''Either or'' {{Either or}} !!! ''A common mistake'' {{A common mistake}} !!! ''Any and all'' {{Any and all}} !!! ''Case of many'' {{Case of many}} !!! ''Switch on value'' {{Switch on value}} !!! ''Conditional loops'' {{Guide: Code: Conditional evaluation: Conditional loops}}
Conditional loops, such as while and until, are covered in the [[Code: Repeated evaluation (loops)|Guide: Code: Repeated evaluation (loops)]] section that follows.
Scripts don't always work the way you want. This section helps you to figure out why, and understand some common problems that can occur. !!! ''Contents'' * [[Common debugging methods]] ** [[Print]] ** [[The ?? function]] ** [[Probing code and data]] ** [[Trace]] * [[Understanding error messages]] * [[Common mistakes]] ** [[Missing brackets or quotes]] ** [[Missing arguments]] ** [[Extra arguments ignored]] ** [[Conditional values other than TRUE and FALSE]] !!! ''Common debugging methods'' {{Common debugging methods}} !!! ''Understanding error messages'' {{Understanding error messages}} !!! ''Common mistakes'' {{Common mistakes}}
The purpose of this section is to give you a quick summary of how new functions are created. If you want to read more about functions in general, see [[Functions|Concepts: Functions]]. !!! ''Contents'' * [[Defining functions]] ** [[General form|Defining functions: General form]] ** [[Other methods]] * [[Restricting arguments]] * [[Embedded documentation]] * [[Function refinements]] * [[Optional arguments]] ** [[Values of optional arguments]] * [[/local refinement]] !!! ''Defining functions'' {{Defining functions}} !!! ''Restricting arguments'' {{Restricting arguments}} !!! ''Embedded documentation'' {{Embedded documentation}} !!! ''Function refinements'' {{Function refinements}} !!! ''Optional arguments'' {{Optional arguments}} !!! ''/local refinement'' {{/local refinement}}
Code is data, grouped in blocks, then evaluated. !!! ''Contents'' * [[Evaluation, not execution]] * [[Code is held in blocks]] * [[Blocks return results]] * [[Blocks aren't always evaluated]] * [[Code is data and data can be code]] !!! ''Evaluation, not execution'' {{Evaluation, not execution}} !!! ''Code is held in blocks'' {{Code is held in blocks}} !!! ''Blocks return results'' {{Blocks return results}} !!! ''Blocks aren't always evaluated'' {{Blocks aren't always evaluated}} !!! ''Code is data and data can be code'' {{Code is data and data can be code}}
Left to right and right to left. !!! ''Contents'' * [[Evaluation sequence]] * [[Multiple expressions]] * [[Multiple results]] * [[Operator precedence]] * [[Parentheses]] !!! ''Evaluation sequence'' {{Evaluation sequence}} !!! ''Multiple expressions'' {{Multiple expressions}} !!! ''Multiple results'' {{Multiple results}} !!! ''Operator precedence'' {{Operator precedence}} !!! ''Parentheses'' {{Parentheses}}
The purpose of this section is to provide a summary of how loops are created. !!! ''Contents'' * [[Loop]] * [[Repeat]] * [[For]] * [[Foreach]] * [[Forall and Forskip]] * [[Forever]] * [[While and until]] * [[Break]] * [[Continue]] !!! ''Loop'' {{Loop}} !!! ''Repeat'' {{Repeat}} !!! ''For'' {{For}} !!! ''Foreach'' {{Foreach}} !!! ''Forall and Forskip'' {{Forall and Forskip}} !!! ''Forever'' {{Forever}} !!! ''While and until'' {{While and until}} !!! ''Break'' {{Break}} !!! ''Continue'' {{Continue}}
Words are the key to REBOL. !!! ''Contents'' * [[Meaning of words]] * [[Special notations for words]] * [[Words as symbols]] * [[Words as variables]] * [[Words for refinements]] * [[Context provides meaning]] * [[Usage changes the meaning]] !!! ''Meaning of words'' {{Meaning of words}} !!! ''Special notations for words'' {{Special notations for words}} !!! ''Words as symbols'' {{Words as symbols}} !!! ''Words as variables'' {{Words as variables}} !!! ''Words for refinements'' {{Words for refinements}} !!! ''Context provides meaning'' {{Context provides meaning}} !!! ''Usage changes the meaning'' {{Usage changes the meaning}}
In order to write code, you need to understand the basic principles. <<< Please note If you already know other programming languages, then you know some of these concepts, but watch out: REBOL is different in many ways. So, it may be good just to scan these over. <<< !!! ''In this section'': * Learn the [[Basic syntax|Guide: Code: Basic syntax]] of the language. It's different in important ways. * Please read [[Evaluating blocks|Guide: Code: Evaluating blocks]], because code is data, and data can be code. * It is essential to understand the [[Words and variables|Guide: Code: Words and variables]]. * The key to code is to know [[How code is evaluated|Guide: Code: How code is evaluated]] including operator precedence. * Learn about [[Conditional evaluation|Guide: Code: Conditional evaluation]] used for functions like if, either, case, switch, and select. * For iteration, read [[Repeated evaluation (loops)|Guide: Code: Repeated evaluation (loops)]] about loop, repeat, for, foreach, forall, while, and until. * And finally, you'll need [[Defining functions|Guide: Code: Defining functions]] to build any serious programs. Of course, there's quite a lot more to on this topic, which you can find in the [[Expressions|Concepts: Expressions]] section.
REBOL Expressions are based on this concept: you combine `values` and `words` into `blocks`. In scripts, a block is normally enclosed with square brackets `[ ]`. Everything within the square brackets is part of the block. The block contents can span any number of lines, and its format is completely freeform. The following examples show various ways of formatting block content: ``` [white red green blue yellow orange black] ["Spielberg" "Back to the Future" 1:56:20 MCA] [ "Bill" billg@ms.dom #315-555-1234 "Steve" jobs@apl.dom #408-555-4321 "Ted" ted@gw2.dom #213-555-1010 ] sites: [ http://www.rebol.com [save %reb.html data] http://www.cnn.com [print data] ftp://www.amiga.com [send cs@org.foo data] ] ``` Some blocks do not require square brackets, because they are implied. For example, in a REBOL script, there are no brackets around the entire script, however, the script content is a block. The square brackets of an `outer-block` of the script are implied. The same is true for expressions typed at the command prompt or for REBOL messages sent between computers--each is an implied block. Another important aspect of blocks is that they imply additional information. Blocks group a set of values in a particular order. That is, a block can be used as a data set as well as a sequence. This will be described in more detail in the [[series|Concepts: Series]] Chapter. =!
Every REBOL value is of a particular `datatype`. The datatype of a value defines: # The range of possible values for the datatype. For example, the logic datatype can only be true or false. # The operations that can be performed. For example, you can add two integers, but you cannot add two logical values. # The way in which the values are stored in memory. Some datatypes can be stored directly (such as numbers), while others are stored indirectly (such as strings). By convention, REBOL datatype words are followed by an exclamation point (!) to help make them stand out. For example: ``` integer! char! word! string! ``` For a complete list of datatypes, see the ''[bad-link:concepts/datatypes.txt]'' Chapter. <<< ''Editor note: This section is new or has has recently changed and is still under construction.'' <<<
<<< ''Editor note: This section is new or has has recently changed and is still under construction. datatypes'' <<< blocks - nested, create, store, copy, find, foreach strings - copy find objects saving and loading maps (dictionary) databases
The most common ways to modify strings. <<< ''Editor note: This section is new or has has recently changed and is still under construction.'' <<<
<<< ''Editor note: This section is new or has has recently changed and is still under construction.'' <<<
<<< ''Editor note: This section is new or has has recently changed and is still under construction.'' <<<
reading foreach file filtering info? exists? modified? size?
!!! ''Contents'' * [[Loading data from files]] * [[Saving data to files]] * [[Loading from the Internet]] * [[Saving to the Internet]] * [[Loading headers also]] !!! ''Loading data from files'' {{Loading data from files}} !!! ''Saving data to files'' {{Saving data to files}} !!! ''Loading from the Internet'' {{Loading from the Internet}} !!! ''Saving to the Internet'' {{Saving to the Internet}} !!! ''Loading headers also'' {{Loading headers also}}
For binary data and strings, you can use read and write to transfer data to and from files. For other types of data, it's easier to use load and save, as described in the [[Files: Loading and saving files|Guide: Files: Loading and saving files]] section. !!! ''Contents'' * [[Reading binary data]] * [[Writing a binary file]] * [[Reading string data]] * [[Writing string data]] * [[Reading a block of lines]] * [[Writing a block of lines]] !!! ''Reading binary data'' {{Reading binary data}} !!! ''Writing a binary file'' {{Writing a binary file}} !!! ''Reading string data'' {{Reading string data}} !!! ''Writing string data'' {{Writing string data}} !!! ''Reading a block of lines'' {{Reading a block of lines}} !!! ''Writing a block of lines'' {{Writing a block of lines}}
Files provide the fundamental method of performing input and output. !!! ''Summary'' The main concepts of files are: * Files are their own datatype in REBOL (it does not use "quoted strings") * Files use a special source code notation (begin with `%` char.) * You can read and write files to both your local system and remote servers. * Data can be loaded and saved to your local system and remote servers. * You can request directory information about files !!! ''File names and paths'' File names are writen in REBOL with the `%` character: ``` %file.txt %dir/code.r %dir/dir2/image.jpg ``` Do not use "quotes" for file names. Those represent strings in REBOL. In this section: * Find out about [[Reading and writing files|Guide: Files: Reading and writing files]] * For data, learn about [[Loading and saving files|Guide: Files: Loading and saving files]] * To access directories, [[Directories and file information|Guide: Files: Directories and file information]]
!!! ''HTTP (web)'' <<< ''Editor note: This section is new or has has recently changed and is still under construction.'' <<< !!! ''Others?'' R2 had about ten other protocols. We'll add more to R3. <<< ''Editor note: This section is new or has has recently changed and is still under construction.'' <<<
If you provide a function word as an argument, help prints all of the information that was provided about the function. For instance, if you type: ``` >> help insert ``` you will see: ``` USAGE: INSERT series value /part range /only /dup count DESCRIPTION: Inserts into a series and returns the series after the insert. (Modifies) INSERT is an action value. ARGUMENTS: series -- Series at point to insert (series! port! map! gob! object! bitset! port!) value -- The value to insert (any-type!) REFINEMENTS: /part -- Limits to a given length or position. length (number! series! pair!) /only -- Only inserts a block as a single value (not the contents of the block) /dup -- Duplicates the insert a specified number of times. count (number! pair!) ```
There is a special mechanism for getting help on errors. When you get an error message at the console, you can type [[why?|Functions: why?]] to see info about that specific error. For example: ``` >> test ** Script error: test has no value >> why? Opening web browser... ``` and, this page, `no-value`, would be displayed. See [[why?|Functions: why?]] for more about this function.
Type `help` or `?` at the console prompt `>>` to view a summary of [[help|Functions: help]]: ``` >> help To use HELP, supply a word or value as an argument: help insert Also, the ? is a shortcut for help: ? insert ? system ? system/options To search all internal help strings and values: help "insert" help to- ; (a partial word) To see detailed online web docs for a function: help/doc forall For all on-line web documentation, just type: docs To see words with values of a specific datatype: help native! help function! help datatype! Other debug functions: ? self - show words and values (in context) ?? - display a variable and its value probe - print a value (molded) source func - show source code of func trace - trace evaluation steps what - show a list of known functions why? - explain more about last error (via web) Other information: chat - open DevBase developer forum/BBS docs - open DocBase document wiki website bugs - open CureCore bug database website demo - run demo launcher (from rebol.com) about - see general product info upgrade - check for newer versions changes - show changes for recent version install - install (when applicable) license - show user license usage - view program options ```
If you use [[help|Functions: help]] on an object, it will list a summary of the object's fields. ``` >> ? system SYSTEM is an object of value: product word! core version tuple! 2.100.90.3.1 build date! 14-Oct-2009/22:40:04 license string! {Alpha prototype version. For testing only. U... catalog object! [datatypes actions natives errors reflectors ... contexts object! [root system exports user] state object! [note last-error] intrinsic object! [do make-module make-port parse-url begin] modules block! length: 3 codecs object! [bmp gif png jpeg] dialects object! [secure draw effect text rebcode] schemes object! [system console file dir event dns tcp clipbo... ports object! [wait-list input output echo system] locale object! [language language* locale locale* months day... options object! [boot home path flags script args do-arg impo... script object! [title header parent path args] standard object! [error script header scheme port port-spec-he... view object! [screen-gob handler event-port metrics event-... ```
The [[help|Functions: help]] function also finds words that contain a specified string. For instance, to find all of the words that include the string [[path!|Datatypes: Path!]], type: ``` >> ? "path" ``` and the result will be: ``` Found these related words: ?? function! Debug print a word, path, or block of such, f... any-path! typeset! [path! set-path! get-path! lit-path!] any-path? function! Return TRUE if value is any type of path. assert native! Assert that condition is true, else throw an ... cd function! Change directory (shell shortcut function). change-dir native! Changes the current directory path. clean-path function! Returns new directory path with //, . and .. ... dirize function! Returns a copy of the path turned into a dire... file! datatype! file name or path get native! Gets the value of a word, path, or values of ... get-path! datatype! the value of a path get-path? action! Returns TRUE if it is this type. import function! Imports a module; locate, load, make, and set... list-dir function! Print contents of a directory (ls). lit-path! datatype! literal path value lit-path? action! Returns TRUE if it is this type. ls function! Print contents of a directory (ls). make-dir function! Creates the specified directory. No error if ... mkdir function! Creates the specified directory. No error if ... more function! Print file (shell shortcut function). path! datatype! refinements to functions, objects, files path? action! Returns TRUE if it is this type. pwd native! Returns the current directory path. reduce native! Evaluates expressions and returns multiple re... request-file native! Asks user to select a file and returns full f... set native! Sets a word, path, block of words, or object ... set-path! datatype! definition of a path's value set-path? action! Returns TRUE if it is this type. source function! Prints the source code for a word. split-path function! Splits and returns directory path and file as... suffix? function! Return the file suffix of a filename or url. ... to-get-path function! Converts to get-path! value. to-lit-path function! Converts to lit-path! value. to-local-file native! Converts a REBOL file path to the local syste... to-path function! Converts to path! value. to-rebol-file native! Converts a local system file path to a REBOL ... to-set-path function! Converts to set-path! value. undirize function! Returns a copy of the path with any trailing ... what-dir native! Returns the current directory path. why? function! Explain the last error in more detail. ``` You can also search for all globally defined words that are of a given datatype. For example, to list all words that are function! datatypes, type: ``` >> ? function! ``` and the result would be: ``` Found these related words: ? function! Prints information about words and values. ?? function! Debug print a word, path, or block of such, f... about function! Information about REBOL alter function! If a value is not found in a series, append i... any-block? function! Return TRUE if value is any type of block. any-function? function! Return TRUE if value is any type of function. any-object? function! Return TRUE if value is any type of object. any-path? function! Return TRUE if value is any type of path. any-string? function! Return TRUE if value is any type of string. any-word? function! Return TRUE if value is any type of word. array function! Makes and initializes a series of a given siz... as-pair function! Combine X and Y values into a pair. ask function! Ask the user for input. ... ``` To obtain a list of all REBOL datatypes, type: ``` >> ? datatype! Found these related words: action! datatype! datatype native function (standard polymorphic) binary! datatype! string series of bytes bitset! datatype! set of bit flags block! datatype! series of values char! datatype! 8bit and 16bit character ... ```
Although it is not required, if your operating system sets the HOME environment variable, REBOL will use it to locate its startup files. On many operating systems such as UNIX or Linux, the HOME variable may be set by default already. (So you do not need to set it yourself).
As shown above, a extension is a dynamically loaded library (DLL). When the extension is loaded by REBOL, it expects to find one or more pre-defined function names. |''RX_Init'' |called when the extension has been loaded. The purpose is to provide any special option flags as well as a pointer to the extension library (RL_LIB).| |''RX_Quit'' |called when the extension is no longer needed. This is optional.| |''RX_Call'' |dispatches the native command functions defined by the extension. This function is passed the command number and an array that holds the command's arguments (called the command frame.)| After the DLL has been loaded, its RX_Init function will be called. If the RX_Init function cannot be found in the DLL, REBOL will throw an error that the extension is not valid. The `RX_Init` function will perform these actions: # set the RL variable to be used to access library functions. # verify that the lib version number is what you expect. If it is not, then your code should not attempt to continue. # return a pointer to a string (ASCII or UFT-8) that provides the extension module identification and initialization code. If an error occurred, a zero is returned. (Later we may allow an error string here). The init string is REBOL source similar to that used to define [[modules|Concepts: Modules]]. It can define functions (both internal and exported), variables, strings, or other data used by your extension. In the code example above, the init_block holds this source: ``` REBOL [ Title: {Example Extension Module} Name: example Type: module Exports: [add-mul] ] add-mul: command [{Add and multiply integers.} a b c] ``` Although we use the quote mechanism of C to embed it, you can use any technique you want, as long as what is returned is a valid ASCII or UTF-8 string.
The following example shows how to use the HTTP protocol to read a web page: ``` page: read http://www.rebol.com ``` The next example fetches an image from a web page and writes it to a local file: ``` image: read/binary http://www.page.dom/image.jpg write/binary %image.jpg image ```
The [[if|Functions: if]] function evaluates an expression, and if it is `true`, evaluates the block that follows. ``` n: 14 if n > 10 [print "greater than 10"] greater than 10 ``` Any expression that returns `false` or `none` will not evaluate the block. All others will. Therefore, you can use expressions that return other values. Here's a common one: ``` string: "let's talk about REBOL" if find string "talk" [print "found"] found ``` If the find function succeeds, it returns a string. That's considered a true expression. If [[find|Functions: find]] fails, it returns `none`, a `false` expression. Because [[if|Functions: if]] is a function it returns a value. For a `true` condition it returns the result of the block evaluation, or none when false: ``` n: 10 print if n > 3 ["greater"] greater ``` ``` n: 1 print if n > 3 ["greater"] none ``` Also, notice that you can pass variables for block arguments: ``` then-block: [print "greater than 10"] n: 14 if n > 10 then-block greater than 10 ``` In fact the block also be the result of some other expression, that returns a block. More on that later.
Please read the ''R3 Alpha page''. Pay attention to the warnings. Here are a few other notes: |''Network settings'' |R3 does not require network settings. This means that in order to use R3, you need direct access to the Internet. No proxy access is supported at this time. (R3 does plan to support it in the beta release.)| |''Demos to try'' |From the console, type demo to download and see the current demos. Note that graphics demos will not be run from non-graphics (server) versions of R3.| |''Version updates'' |Check for updates often using the upgrade function.| |''About the console'' |The console is a bit crude. It's just the Microsoft command shell. On other systems, the console is whatever default shell for that system. Later, we may add back a special console if there's user interest in doing so.|
You can also import modules directly using the import function. This function follows the same rules as the needs field of a program header, as explained above. For example, you can write: ``` import 'mysql ``` and the system will search for the mysql module, using the method described above. You can also use a filename or URL for the module identifier: ``` import %mysql.r import http://www.rebol.com/mods/mysql.r ``` And, you can import from a block of modules (which is in fact a valid needs block): ``` import [mysql db-gui http-server] ``` !!!!! ''Return value'' When successful, the import function returns a module! datatype as its result. This allows you to write: ``` mysql: import 'mysql ``` Now, the mysql variable can be used to refer to values within the mysql module. For example the module value is used here to reference a function: ``` mysql/open-db %my-database.sql ``` See below for more. !!!!! ''Useful refinements'' Like the header needs field, the [[import|Functions: import]] function also lets you specify a version and a checksum. These are all supported: ``` import/version mysql 1.2.3 import/check mysql #{A94A8FE5CCB19BA61C4C0873D391E987982FBBD3} import/version/check mysql 1.2.3 #{A94A8FE5CCB19BA61C4C0873D391E987982FBBD3} ``` !!!!! ''When to use IMPORT'' The benefit of using the [[import|Functions: import]] function compared to the needs header field is that the arguments can be variables. A basic example is: ``` mod: 'mysql import mod ``` Or, something like: ``` mod-list: [ mysql 1.2.3 db-gui 2.4.5 http-server 1.0.1 ] import mod-list ``` !!!!! ''Doing modules'' Another method of importing modules is supported. If you use do on a module file, it will also be imported. This is provided as a convenience, because do has been used in REBOL for years as a way to load and initialize additional functions and values. For example, writing: ``` do %mysql.r do http://www.rebol.com/mods/mysql.r ``` is equivalent to: ``` import %mysql.r import http://www.rebol.com/mods/mysql.r ``` But note that: ``` import 'mysql ``` is not the same as: ``` do 'mysql ``` because do of a word simply returns the value word. Note also that do does not support the version and checksum refinements found in the [[import|Functions: import]] function.
If you need help: REBOL itself has help built-in (see below). It's very useful, so keep it in mind. There's a community of users that you can talk with. Use chat to connect. You can get a list of built-in functions with the what function. View the source code of mezzanine functions with the source function. For help with errors, they why? function will take you to an error explanation page. Other online sources of information are available. See the [[community|http://www.rebol.com/community.html]] page for links.
|''Function'' |''Description''|h |[[head?|Functions: head?]] |Returns true if at the head of the series.| |[[tail?|Functions: tail?]] |Returns true if at the tail of the series.| |[[index?|Functions: index?]] |Returns the offset from the head of the series.| |[[length?|Functions: length?]] |Returns the length of a series from the current position.| |[[offset?|Functions: offset?]] |Returns the distance between two series positions.| |[[empty?|Functions: empty?]] |Returns true if the series is empty from this position.|
When initializing a string or block series, use copy on the value to make is a unique series: ``` str: copy "" blk: copy [] ``` Using [[copy|Functions: copy]] assures that a new series is created for the word every time the word is initialized. Here is an example of why this is important. ``` print-it: func [/local str] [ str: "" insert str "ha" print str ] print-it ha ``` ``` print-it haha ``` ``` print-it hahaha ``` In this example, because copy wasn't used, the empty string series is modified with every call of `print-it`. The string series `ha` is inserted into `str` each time `print-it` is called. Examining the source of the function as it now exists exposes the root of the problem: ``` source print-it print-it: func [/local str] [ str: "hahaha" insert str "ha" print str ] ``` Although `str` is a local variable, its string value is global. To avoid this problem, the function should copy the empty string or use make on the string. ``` print-it: func [/local str] [ str: copy "" insert str "ha" print str ] print-it ha ``` ``` print-it ha ``` ``` print-it ha ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< REBOL networking is built-in. To create scripts that use the network protocols you do not need any special include files or libraries. The only requirement is that you provide the basic information necessary to enable protocols to connect to servers or through firewalls and proxies. For instance, to send an email, the SMTP protocol needs an SMTP server name and a reply email address. ''Contents'' * [[Basic Network Settings]] * [[Proxy Settings]] * [[Other Settings]] * [[Access to Settings]] !!! ''Basic Network Settings'' {{Basic Network Settings}} !!! ''Proxy Settings'' {{Proxy Settings}} !!! ''Other Settings'' {{Other Settings}} !!! ''Access to Settings'' {{Access to Settings}}
Three types of input can be provided to the parse function: |''any-string!'' |strings of any type (unicode)| |''any-block!'' |blocks of any type| |''binary!'' |sequence of bytes (not characters)|
The [[parse|Functions: parse]] function is about matching the input stream with given rules. In some cases, a rule may succeed, but the input position did not change. For example: ``` parse str [some [to "abc"]] parse str [some ["a" | "b" | none]] ``` To avoid infinite looping, a special internal rule is triggered based on the fact that the rule did not change the input position. However, this shows a problem with this rule: ``` parse str [some [to "a" remove thru "b"]] ``` Here the input did not appear to advance, but something useful happened. In such cases, the some word should not be used, and the `while` word is better: `parse str [while [to "a" remove thru "b"]]`
You can insert one or more new values into any part of a series using the insert function. When you insert a value at a position in a series, space is made by shifting its prior values toward the tail of the series. For instance, the block: ``` colors: [red green] ``` would be shown as: To insert a new value at the head of the block where the `colors` variable is now positioned: ``` insert colors 'blue ``` The `red` and `green` words are shifted over and the blue word (which is prefixed with a tick because it is a word and should not be evaluated) is inserted at the head of the list. Note that the `colors` variable remains positioned at the head of the list. ``` probe colors [blue red green] ``` Also note that the return from the [[insert|Functions: insert]] function was not used because it was not set to a variable or passed along to another function. If the return had been used to set the value of the `colors` variable with the line: ``` colors: insert colors 'blue ``` the effect on the block would have been the same, but the position of the `colors` variable would have changed as a result of setting the return value. The position returned from [[insert|Functions: insert]] is immediately following the insertion point. An insertion can be made anywhere in the series. The position of the insert can be specified, and it can include the tail. Inserting at the tail has the effect of appending to the series. ``` colors: tail colors insert colors 'gold probe colors [blue red green gold] ``` Before the insertion: After the insertion: The word `gold` has been inserted at the tail of the series. Another way to insert at the tail of a series is with the [[append|Functions: append]] function. The append function works in the same way as insert, but always [[insert|Functions: insert]] at the tail. The previous example would become: ``` append colors 'gold ``` The result is the same as the previous example. The [[insert|Functions: insert]] and [[append|Functions: append]] function also accept a block of arguments to insert. As an example: ``` colors: [red green] insert colors [blue yellow orange] probe colors [blue yellow orange red green] ``` If you want to insert the new values between the `red` and `green` words: ``` colors: [red green] insert next colors [blue yellow orange] probe colors [red blue yellow orange green] ``` The [[insert|Functions: insert]] and [[append|Functions: append]] functions have other capabilities that are covered in more detail in a later section.
The first block of a function definition is called its ''interface specification''. This block includes a description of the function, its arguments, the datatypes allowed for arguments, descriptions of the arguments, and other items. The interface specification is a dialect of REBOL (because it has different evaluation rules than normal code). The specification block has the format: ``` [ "function description" [optional-attributes] argument-1 [optional-type] "argument description" argument-2 [optional-type] "argument description" ... /refinement "refinement description" refinement-argument-1 [optional-type] "refinement argument description" ... ] ``` The fields of the specification block are: |''Description'' |A short description of the function. This is a string that can be accessed by other functions such as help to output descriptions of functions.| |''Attributes'' |A block that describes special properties of the function, such as its behavior on errors. It may be expanded in the future to include flags for optimizations.| |''Argument'' |A variable that is used to access an argument from within the body of the function.| |''Arg Type'' |A block that identifies the datatypes that are accepted by the function. If a datatype not identified in this block is passed to the function, an error will occur.| |''Arg Description'' |A short description of the argument. Like the function description, this can be accessed by other functions such as help.| |''Refinement'' |A refinement word that indicates special behavior is required of the function.| |''Refinement Description'' |A short description of the refinement.| |''Refinement Argument'' |A variable that is used by the refinement.| |''Refinement Argument Type'' |A block that identifies the datatypes that are accepted by the refinement.| |''Refinement Argument Description'' |A short description of the refinement argument.| All of these fields are optional. As an example, the argument block of the sum function (defined in a previous example) is expanded to restrict the type of arguments accepted. It also includes a description of the function and its expected arguments. ``` sum: func [ "Return the sum of two numbers." arg1 [number!] "first number" arg2 [number!] "second number" ][ arg1 + arg2 ] ``` Now, the datatype of the arguments is automatically checked, catching errors like: ``` print sum 1 "test" ** Script Error: sum expected arg2 argument of type: number. ** Where: print sum 1 "test" ``` To allow additional argument datatypes, more than one can be given: ``` sum: func [ "Return the sum of two numbers." arg1 [number! tuple! money!] "first number" arg2 [number! tuple! money!] "second number" ][ arg1 + arg2 ] print sum 1.2.3 3.2.1 4.4.4 ``` ``` print sum $1234 100 $1334.00 ``` Now the sum function accepts a number, tuple, or monetary value as arguments. If within the function you need to distinguish what datatype was passed, you can use the datatype test functions: ``` if tuple? arg1 [print arg1] if money? arg2 [print arg2] ``` Because the [[sum|Functions: checksum]] function provided description strings, the [[help|Functions: help]] function now supplies useful information about it: ``` help sum USAGE: SUM arg1 arg2 DESCRIPTION: Return the sum of two numbers. SUM is a function value. ARGUMENTS: arg1 -- first number (Type: number tuple money) arg2 -- second number (Type: number tuple money) ```
The [[dehex|Functions: dehex]] function converts Internet URL and CGI style hexadecimal encoded characters to strings. Hexadecimal ASCII representations appear in a URL or CGI string as `%xx`, where `xx` is the hexadecimal value. ``` str: "there%20seem%20to%20be%20no%20spaces" print dehex str there seem to be no spaces ``` ``` print dehex "%68%65%6C%6C%6F" hello ```
A script can be interrupted by pressing the ESCAPE key, which returns immediately to the command prompt. During some types of operating system or network activity there may be a delay in responding to the ESCAPE interrupt.
The [[intersect|Functions: intersect]] function takes two series and returns a series that contains the values that are present in both series. Examples: ``` probe intersect [Bill Bob Bart] [Bob Ted Fred] [Bob] ``` ``` lunch: [ham cheese bread carrot] dinner: [ham salad carrot rice] probe intersect lunch dinner [ham carrot] ``` ``` print intersect [1 3 2 4] [3 5 4 6] 3 4 ``` ``` string1: "CBAD" ; A B C D scrambled string2: "EDCF" ; C D E F scrambled print sort intersect string1 string2 CD ``` The intersection can be found between bitsets: ``` all-chars: "ABCDEFGHI" charset1: charset "ABCDEF" charset2: charset "DEFGHI" charset3: intersect charset1 charset2 print find charset3 "E" true ``` ``` print find charset3 "B" false ``` The `/case` refinement allows case-sensitive intersection: ``` probe intersect/case [Bill bill Bob bob] [Bart bill Bob] [bill Bob] ```
REBOL does not support an IDE at this time (although we want to add one in the future.) You can use existing IDEs, such as Visual Studio, XCode, Eclipse, KDevelop and others.
Issues are identification numbers, such as telephone numbers, model numbers, credit card numbers. For example: ``` #707-467-8000 #0000-1234-5678-9999 #MFG-932-741-A ```
The [[join|Functions: join]] function takes two arguments and concatenates them into a single series. The datatype of series returned is based on the value of the first argument. When the first argument is a series value, that series type is returned. ``` str: "abc" file: %file url: http://www.rebol.com/ probe join str [1 2 3] abc123 ``` ``` probe join file ".txt" %file.txt ``` ``` probe join url %index.html http://www.rebol.com/index.html ``` When the first argument is not a series, the [[join|Functions: join]] converts it to a string first, then performs the append: ``` print join $11 " dollars" $11.00 dollars ``` ``` print join 9:11:01 " elapsed" 9:11:01 elapsed ``` ``` print join now/date " -- today" 30-Jun-2000 -- today ``` ``` print join 255.255.255.0 " netmask" 255.255.255.0 netmask ``` ``` print join 412.452 " light-years away" 412.452 light-years away ``` When the second argument to [[join|Functions: join]] is a block, the values of that block are evaluated and appended to the series returned. ``` print join "a" ["b" "c" 1 2] abc12 ``` ``` print join %/ [%dir1/ %sub-dir/ %filename ".txt"] %/dir1/sub-dir/filename.txt ``` ``` print join 11:09:11 ["AM" " on " now/date] 11:09:11AM on 30-Jun-2000 ``` ``` print join 312.423 [123 987 234] 312.423123987234 ```
A single-line comment is made with a semicolon. Everything following the semicolon to the end of the line is part of the comment: ``` zertplex: 10 ; set to the highest quality ```
The REBOL end-user license agreement that you agreed to when you downloaded or installed REBOL can be viewed at any time from the REBOL console by typing license at the REBOL prompt.
The [[open|Functions: open]] function allows ports to be opened for line access. In line mode, the [[first|Functions: first]] function will return a line of text, rather than a character. The example below reads a file one line at a time: ``` fp: open/lines %file.txt print first fp I wanted the gold, and I got it -- ``` ``` print third fp Yet somehow life's not what I thought it, ``` The `/lines` refinement is also useful for Internet protocols that are line oriented. ``` tp: open/lines tcp://server:8000 print first tp ```
A long list of [[REBOL editors|http://www.rebol.com/editors.html]] is available, but here are a few of the most common: * [[TextMate with REBOL Bundle|http://www.rebol.com/editors.html]] * [[Programmer's Notepad|http://www.pnotepad.org]] * [[Crimson editor|http://www.crimsoneditor.com]] * [[Emerald editor|http://www.emeraldeditor.com]] * [[Emacs|https://en.wikipedia.org/wiki/Emacs]] * [[VIM or VI|http://www.vim.org]] * Windows notepad, etc. You can even use web-based text-area editors, although beware that they do not handle tab spaces very well.
Within the parse dialect, these words are treated as keywords and cannot be used as variables. |''Keyword'' |''Description''|h |`and` rule |match to the rule, but do not advance the input (allows matching multiple rules to the same input)| |`any` rule |match to the rule zero or more times; stop on failure or if input does not change.| |`break` |break out of a match loop (such as any, some, while), always indicating success.| |`change` rule only value |match the rule, and if true, change the input to the new value (can be different lengths)| |`copy` word |set the word to a copy of the input for matched rules| |`do` rule |evaluate the input as code, then attempt to match to the rule| |`end` |match end of input| |`fail` |force current rule to fail, backtrack| |`if` (expr) |evaluate the expression (in a paren) and if false or none, fail and backtrack| |`insert` only value |insert a value at the current input position (with optional ONLY for blocks by reference); input position is adjusted just past the insert| |`into` rule |match a series, then parse it with given rule; new series can be the same or different datatype.| |`opt` rule |match to the rule once or not at all (zero or one times)| |`not` rule |invert the result of the next rule| |`quote` arg |accept next argument exactly as is (exception: paren)| |`reject` |similar to break: break out of a match loop (such as any, some, while), but indicate failure.| |`remove` rule |match the rule, and if true, remove the matched input| |`return` value |match the rule, and if true, immediately return the matched input as result of the PARSE function| |`set` word |set the word to the value of the input for matched rules| |`skip` |skip input (for the count range, if provided before it)| |`some` rule |match to the rule one or more times; stop on failure or if input does not change.| |`then` |regardless of failure or success of what follows, skip the next alternate rule (branch)| |`thru` rule |scan forward in input for matching rules, advance input to tail of the match| |`to` rule |scan forward in input for matching rules, advance input to head of the match| |`while` rule |like any, match to the rule zero or more times; stop on failure; does not care if input changes or not.| |`??` |Debugging output. Prints the next parse rule value and shows the current input position (e.g. where you are in the string.)| In addition, `none` is a special value that can be used as a default match rule. It is often used at the end of alternate rules to catch all no-match cases.
To see a list of all built-in functions, use the what function: <<< This list may be large. If you are unable to scroll in the console to your desired function, use the echo command as a means to capture that list into a file which you can later look through. <<< ``` >> what ... about Information about REBOL abs Returns the absolute value. absolute Returns the absolute value. action Creates datatype action (for internal usage only). action? Returns TRUE if it is this type. add Returns the result of adding two values. ajoin Reduces and joins a block of values into a new string. alias Creates an alternate spelling for a word. ... ```
To list the contents of the current directory, use: ``` list-dir ``` The number of columns used to show the directory is dependent on the console window size and the maximum file name length.
As described earlier, the interpreter evaluates the arguments of functions and passes them to the function body. However, there are times when you do not want function arguments evaluated. For instance, if you need to pass a word and access it from the function body, you do not want it evaluated as an argument. The help function, which expects a word, is a good example: ``` help print ``` To prevent print from being evaluated, the help function must specify that its argument should not be evaluated. To specify that an argument not be evaluated, precede the argument name with a single quote (indicates a literal word). For example: ``` zap: func [`var] [set var 0] test: 10 zap test print test 10 ``` The var argument is preceded with a single quote, which instructs the interpreter to obtain the argument without evaluating it first. The argument is passed as the word. For example: ``` say: func [`var] [probe var] say test test ``` The example prints the word that is passed as an argument. Another example is a function that increments a variable by one and returns its result (similar to the `++` increment function in C): ``` ++: func ['word] [set word 1 + get word] count: 0 ++ count print count 1 ``` ``` print ++ count 2 ```
The ability to deal with a word as a literal is useful. Both [[set|Functions: set]] and [[get|Functions: get]], as well as other functions like [[value?|Functions: value?]], [[unset!|Datatypes: Unset!]], [[protect|Functions: protect]], and [[unprotect|Functions: unprotect]], expect a literal value. Literal words can be written in one of two ways: by prefixing the word with a single quotation mark, also known as a tick, `'` or by placing the word in a block. You can use a tick in front of a word that is evaluated: ``` word: 'this ``` In the above example, the [[word!|Datatypes: Word!]] variable is set to the literal word `this`, not to the value of `this`. The [[word!|Datatypes: Word!]] variable just uses the name symbolically. The example below shows that if you print the value of the word, you will see the this word: ``` print word this ``` You can also obtain literal words from an unevaluated block. In the following example, the [[first|Functions: first]] function fetches the first word from the block. This word is then set to the word variable. ``` word: first [this and that] ``` Any word can be used as a literal. It may or may not refer to a value. For example, in the example below the word here has no value. The word [[print|Functions: print]] does have a value, but it can still be used as a literal because literal words are not evaluated. ``` word: 'here print word here ``` ``` word: 'print print word print ``` The next example illustrates the importance of literal values: ``` video: [ title "Independence Day" length 2:25:24 date 4/july/1996 ] print select video 'title Independence Day ``` In this example, the word `title` is searched for in a block. If the tick was missing from `title`, then its natural value would be used. If `title` has no natural value, an error is displayed. See the `[bad-link:concepts/words.txt]` Section in the `[bad-link:concepts/values.txt]` Appendix for more information about word literals.
The [[load|Functions: load]] function reads raw binary data and converts it to useful datatypes. For example, you can load REBOL text files, both code and data, with a line like: ``` data: load %data.r ``` If `data.r` contains multiple values, the result of [[load|Functions: load]] will be a block. For example, take a file that contains the text: ``` test 1234 4:25 <test> "test" ``` If you [[load|Functions: load]] it and [[probe|Functions: probe]] the results: ``` probe load %example.r [test 1234 4:25 <test> "test"] ``` The data is not evaluated, it's just data that you can now use in your code: ``` data: load %example.r foreach item data [ probe item ] test 1234 4:25 <test> "test" ``` Note that if the file only contains a single value like an integer or date, the result will be that value. You also use [[load|Functions: load]] for other datatypes, such as images: ``` image: load %photo.jpg ``` Here the `photo.jpg` file is [[read|Functions: read]] and converted from an encoded JPEG [[image|Datatypes: Image!]] (a [[binary!|Datatypes: Binary!]] format) into the standard RGBA [[image|Datatypes: Image!]] format used by REBOL. The [[load|Functions: load]] function contains many other options. (Click on its name to see the details.)
In addition to loading local files, you can also [[load|Functions: load]] files from a web server (or from any other network protocol that allows it.) This makes it easy to obtain shared data that may be posted to various web sites. Here's an example: ``` data: load http://www.rebol.com/index.r probe data [ title "REBOL Central Folder" summary "The portal to REBOL sites, demos, tests, and more." folder "Demos" %view/demos/index.r info "Demos of REBOL/View" ... ```
All REBOL programs require a header block. The header provides the title, version, author, and other useful meta-data about the program. To [[load|Functions: load]] the header, use the `/header` refinement. An example for a local file is: ``` prog: load/header %script.r ``` or, for a remote file on a web server: ``` prog: load/header http://www.rebol.com/speed.r ``` The first value in prog is the header [[object!|Datatypes: Object!]]. For example, let's look at the header of a program: ``` prog: load/header http://www.rebol.com/speed.r print first prog Title: "REBOL Quick and Dirty Speed Test" Name: 'speed-test Type: none Version: 1.2.0 ``` For more information about headers, see the [[Scripts: Headers|Concepts: Scripts: Headers]] section.
A local variable is a word whose value is defined within the scope of a function. Changes to a local variable only affect the function in which the variable is defined. If the same word is used outside of the function, it will not be affected by the changes to the local variable of the same name. Argument variables and refinements are local variables. Their values are defined within the scope of the function. By convention, additional local variables can be specified with the `/local` refinement. The `/local` refinement is followed by a list of words that are used as local variables within the function. ``` average: func [ block "Block of numbers" /local total length ][ total: 0 length: length? block foreach num block [total: total + num] either length > 0 [total / length][0] ] ``` Here the `total` and `length` words are local to the function. Another method of creating local words is to use the [[function!|Datatypes: Function!]] function, which is identical to [[func|Functions: func]], but accepts a separate block that contains the local words: ``` average: function [ block "Block of numbers" ][ total length ][ total: 0 length: length? block foreach num block [total: total + num] either length > 0 [total / length][0] ] ``` In this example, notice that the `/local` refinement is not used with the [[function!|Datatypes: Function!]] function. The [[function!|Datatypes: Function!]] function creates the refinements for you. If a local variable is used before its value has been set within the body of its function, it will have a [[none!|Datatypes: None!]] value.
Local variables that hold series need to be copied if the series is used multiple times. For example, if you want the `stars` string to be the same each time you call the `start-name` function, you should write: ``` star-name: func [name] [ stars: copy "**" insert next stars name stars ] ``` Otherwise, if you write: ``` star-name: func [name] [ stars: "**" insert next stars name stars ] ``` you will be using the same string each time and each time the function is used the pervious name will appear within the result. ``` print star-name "test" *test* ``` ``` print star-name "this" *thistest* ``` <<< This is Important The concept described above is important to remember. If you forget it, you will observe odd results in your programs. <<<
The [[loop|Functions: loop]] function is the simplest way to evaluate a block a given number of times. ``` loop 3 [print "Hello world"] Hello world Hello world Hello world ``` The [[loop|Functions: loop]] function returns the value of the final evaluation of the block: ``` i: 0 print loop 40 [i: i + 10] 400 ```
The [[make-dir|Functions: make-dir]] makes a new directory. The new name for the directory can be relative to either the current directory or an absolute path. ``` make-dir %new-dir make-dir %local-dir/ make-dir %/work/docs/old-docs/ ``` The trailing slash is optional for this function. Internally, the [[make-dir|Functions: make-dir]] function calls open with the `/new` refinement. The line: ``` close open/new %local-dir/ ``` also creates a new directory. The trailing slash is important in this example, indicating that a directory is to be created rather than a file. If you use the [[make-dir|Functions: make-dir]] function to create a directory that already exists, an error will occur. The error can be caught with the [[try|Functions: try]] function. The directory can be checked in advance with the [[exists?|Functions: exists?]] function.
New series are created with the [[make|Functions: make]] and [[copy|Functions: copy]] functions. Use the [[make|Functions: make]] function to create a new series from a series datatype and an initial size. The size is an estimate of the size needed for the series. If the initial size is too small, the series will automatically expand, but at a slight performance cost. ``` block: make block! 50 string: make string! 10000 list: make list! 128 file: make file! 64 ```
Modules can be dynamically created by using the [[make|Functions: make]] constructor, in the general form: ``` mod: make module! [spec body] ``` where the spec and body are both blocks, as noted above, and `mod` is the new module. The [[module|Functions: module]] shortcut function is also provided. (This function is similar to [[func|Functions: func]] or [[function|Functions: function]] helper functions.) The format is: ``` mod: module spec body ``` Now, the earlier stock-trade example can be written: ``` stocks: module [ Title: "Stock Trading Module" Name: stock-trade Version: 1.2.0 Type: module Exports: [buy sell] ][ buy: func [stock price] [...] sell: func [stock price] [...] ] ``` Note that modules created in this way are not automatically imported into the system. In other words, to call `sell`, you would need to write: ``` stocks/sell "acme" $20.00 ``` To import the module, simply [[import|Functions: import]] the module, and then you can use its exported functions directly: ``` import stocks sell "acme" $20.00 ``` Modules created dynamically don't process the needs block.
The copy action makes a copy of the substring that it finds, but that is not always desirable. In some cases, it is better to save the current position of the input stream in a variable. NOTE: The [[copy|Functions: copy]] word as used in parse is different from the copy function used in REBOL expressions. Parse uses a dialect of REBOL, and copy has a different meaning within that dialect. In the following example, the `begin` variable holds a reference to the `page` input string just after `<title>`. The ending refers to the page string just before `>/title<`. These variables can be used in the same way as they would be used with any other series. ``` parse page [ thru <title> begin: to </title> ending: (change/part begin "Word Reference Guide" ending) ] ``` You can see the above parse expression actually changed the contents of the title: parse page [thru <title> copy text to </title>] print text Word Reference Guide Here is another example that marks the position of every table tag in an HTML file: ``` page: read http://www.rebol.com/index.html tables: make block! 20 parse page [ any [to "<table" mark: thru ">" (append tables index? mark) ] ] ``` The `tables` block now contains the position of every tag: ``` foreach table tables [ print ["table found at index:" table] ] table found at index: 836 table found at index: 2076 table found at index: 3747 table found at index: 3815 table found at index: 4027 table found at index: 4415 table found at index: 6050 table found at index: 6556 table found at index: 7229 table found at index: 8268 ``` NOTE: The current position in the input string can also be modified. The next section explains how this is done.
Input can be compared with various values "match" rules: |''Rule Type'' |''Description''|h |literal |Most of the literal values can be used as matches. The primary exceptions are integer! (used for repeat counts), and words (used as variables, unless you make them literal words), blocks and parens .| |quote |Any value that follows the word quote is used literally, with the exception of parens (which are evaluated and their results are used for matching). For example, this is how you can match an integer value, even though integers are normally used for counters.| |block |Hold collections of sub-rules for matching.| |variable |A variable can be used to hold a literal and has the same effect as described above.|
The `/match` refinement modifies the behavior of [[find|Functions: find]] to perform pattern matching on the current position of a series. This refinement allows parsing operations to be performed by matching the next part of a series with expected patterns. See the chapter on [[parsing|Concepts: Parsing]] for another way to match series. A simple example of matching is as follows: ``` blk: [1342 "Franklin Pike Circle"] probe find/match blk integer! ["Franklin Pike Circle"] ``` ``` probe find/match blk 1432 ["Franklin Pike Circle"] ``` ``` probe find/match blk "test" none ``` ``` str: "Keep things simple." probe find/match str "keep" " things simple." ``` ``` print find/match str "things" none ``` Notice in the example that a search is not performed. The beginning of the series either matches or it does not. If it does match, the series is advanced the position immediately following the match point, allowing you to match the next sequence. Here is a simple parser written with `find/match`: ``` grammar: [ ["keep" "make" "trust"] ["things" "life" "ideas"] ["simple" "smart" "happy"] ] parse-it: func [str /local new] [ foreach words grammar [ foreach word words [ if new: find/match str word [break] ] if none? new [return false] str: next new ;skip space ] true ] print parse-it "Keep things simple" true ``` ``` print parse-it "Make things smart" true ``` ``` print parse-it "Trust life well" false ``` Matching can be made case-sensitive with the `/case` refinement. The capability of `/match` can be greatly extended with the addition of the `/any` refinement as discussed below.
You can match a value of any datatype by specifying the data type word. See Datatype Matches below. |''Datatype Word'' |''Description''|h |[[string!|Datatypes: String!]] |matches any quoted string| |[[time!|Datatypes: Time!]] |matches any time| |[[date!|Datatypes: Date!]] |matches any date| |[[tuple!|Datatypes: Tuple!]] |matches any tuple| NOTE: Don't forget the `!` that is part of the name or an error will be generated.
When parsing a block, to match against a word specify the word as a literal: ``` 'name 'when 'empty ```
!!!!! ''Fibonacci and factorial'' This extension provides two functions to compute the Fibonacci number and the factorial. The REBOL extension module definition: ``` REBOL [ Title: {Math functions} Type: module Exports: [fibonacci factorial] ] fibonacci: command [n [integer!]] factorial: command [n [integer!]] ``` The C code: ``` RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { switch (cmd) { case 0: // fibonacci { i64 n, a, b, c, i; n = RXA_INT64(frm, 1); for (a = b = 1, i = 3; i <= n; i++) { c = b; b += a; a = c; } RXA_INT64(frm, 1) = b; RXA_TYPE(frm, 1) = RXT_INTEGER; // not strictly necessary break; } case 1: // factorial { i64 n, i, f = 1; n = RXA_INT64(frm, 1); for (i = 2; i <= n; i++) f *= i; RXA_INT64(frm, 1) = f; RXA_TYPE(frm, 1) = RXT_INTEGER; // not strictly necessary break; } default: return RXR_NO_COMMAND; } return RXR_VALUE; } ``` The test code: ``` print fibonacci 80 23416728348467685 ``` ``` print factorial 20 2432902008176640000 ``` If you time these functions, you will find that they are about 25 times faster than interpreted code.
Words are commonly used in both code and data. In code, words can be ''variables'' that holds values (including functions), but they can also be just symbols. For example, here we use the word join three different ways: ``` join a b actions: [split join copy] get 'join ``` The first is using join as a function value, but the second and third are using join as a symbol. Basically, the meaning of a word is defined by its: |''Symbol'' |the name itself. So, obviously, join is not the same as ajoin. Different name.| |''Notation'' |special markup on the word. Above 'join is a symbol, not a function variable.| |''Context'' |how the word is associated with a value. The word may have a global or local meaning, or could be part of another context such as a module or object.| |''Usage'' |how the word is used in the code or data. Above, the word join in the actions block written as a symbol. Later it may be used to obtain the join function, but we do not know from this line, nor does it matter here.| Each of these will be explained below.
In large scripts and where possible, avoid using global variables that carry their internal state from one module or function to another. For short scripts, this isn't always practical. But recognize that short scripts may become longer scripts over time. If you have a collection of global variables that are closely related, consider using an object to keep track of them: ``` user: make object! [ name: "Fred Dref" age: 94 phone: 707-555-1234 email: dref@fred.dom ] ```
Don't forget to provide all required arguments to each function. For example, [[either|Functions: either]] takes three arguments as shown with here: ``` ? either USAGE: EITHER condition true-block false-block ``` The code below forgets to provide the third argument, and you see an error: ``` either a > 10 [a: 1] print "done" ** Script error: either does not allow unset! for its false-block argument ``` This error occurs because [[print |Functions: print]]returns [[unset!|Datatypes: Unset!]], which is then passed to [[either|Functions: either]] as its second block. That's not valid, and the error occurs. If you're not sure about the number of arguments, use [[help|Functions: help]] to check. You can also use this technique: enclose the problematic expression in a do block. For example, this will better show an error: ``` do [ either cond [a: 1] ] ** Script error: either is missing its false-block argument ```
If you miss a beginning or ending bracket, parenthesis, or quote, when you load the code, you'll see an error message. For example, if the test.r file is missing its final bracket, you will see this error message: ``` Evaluating: test.r ** Syntax error: missing "]" at "end-of-script" ** Where: to unless either if load either either do begin do ** Near: (line 3) loop 3 [ ``` The system will attempt to tell you where the problem started, or the matching position for the missing item. However, they can be difficult to find. If this is a common problem for you, we suggest that you use a code editor that includes a feature for finding matching brackets, braces, and parentheses. For example the VI(M) editor on Linux or XCode on OSX.
There are two basic modes of network operation: ''atomic'' and ''port-based''. <<< Atomic network operations are those that are accomplished in a single function. For instance, you can read an entire Web page with a single call to the read function. There is no need to separately open a connection or set up the read. All of that is done automatically as part of the read. For example, you can type: ``` print read http://www.rebol.com ``` <<< The host is found and opened, its Web page transferred, and the connection closed. The `port-based` mode of operation is one that uses a more traditional programming approach. It involves opening a port and performing various series operations on the port. For instance, if you want to read your email from a POP server one message at a time, you would use this method. Here is an example that reads and displays all of your email: ``` pop: open pop://user:pass@mail.example.com forall pop [print first pop] close pop ``` The atomic method of operation is easier, but it is also more limited. The port-based method allows more types of operations, but also requires a greater understanding of networking.
|''Function'' |''Description''|h |[[insert|Functions: insert]] |Inserts values into a series.| |[[append|Functions: append]] |Appends values to the tail of a series.| |[[remove|Functions: remove]] |Removes values from a series.| |[[clear|Functions: clear]] |Clears values to the tail of a series.| |[[change|Functions: change]] |Changes values in a series.| |[[poke|Functions: poke]] |Changes values at a position in a series.|
The input series can be modified during the parse using these commands: |''remove'' |removes the matched input| |''insert'' |inserts into the series at current input (resumes past the insertion)| |''change'' |changes the matched input to a given value (resumes past the change)| All of these will handle the input pointer appropriately. However, for `remove`, it is possible that the input does not advance (because it was removed.) If you are using it with a some or any loop, read the next section.
Now that you know how to obtain the position of the input series, you also can use other series functions on it, including [[insert|Functions: insert]], [[remove|Functions: remove]], and [[change|Functions: change]]. To write a script that replaces all question marks `?` with exclamation marks `!`, write: ``` str: "Where is the turkey? Have you seen the turkey?" parse str [some [to "?" mark: (change mark "!") skip]] print str Where is the turkey! Have you seen the turkey! ``` The skip at the tail advances the input over the new character, which is not necessary in this case, but it is a good practice. As another example, to insert the current time everywhere the word [[time!|Datatypes: Time!]] appears in some text, write: ``` str: "at this time, I'd like to see the time change" parse str [ some [to "time" mark: (remove/part mark 4 mark: insert mark now/time) :mark ] ] print str at this 14:42:12, I'd like to see the 14:42:12 change ``` Notice the :mark word used above. It sets the input to a new position. The insert function returns the new position just past the insert of the current time. The set-word :mark is used to set the input to that position.
Modules can be stored in three locations: * On a website, accessible via HTTP. * On your local filesystem, in one of a few directories. * Within other programs (as dynamic modules). You can change where the system looks for modules by modifying the `system/options/module-paths` block. For example, to search first in a directory that you've created: ``` insert system/options/module-paths %/c/reb-mods/ ``` Or, use append to search there last (after searching all other paths). Add that line to your rebol.r file if you want to do it each time you run REBOL. Standard modules for a variety of useful functions will be available on REBOL.com, REBOL.net, and other sites. They can be accessed and updated using DevBase. <<< Editor note: This section is new or has has recently changed and is still under construction. <<<
Important notes.
Here is an example module showing the spec (header) and the body of the module. ``` REBOL [ Title: "Stock Trading Module" Name: stock-trade Version: 1.2.0 Type: module Exports: [buy sell] ] buy: func [stock price] [...] sell: func [stock price] [...] ``` This is the most common way to define a module. However, it is also possible to define a module directly within a program. (More below.) !!!!! ''The specification header'' The specification block (called the "spec") is written as a standard header, just like that used for programs. It is prototype is defined by `system/standard/header`. The most important spec fields used for modules are: |''Field'' |''Datatype'' |''Description''|h |type |[[word!|Datatypes: Word!]] |Indicates that the file is a module. This field must be set to the word module or the file will be processed by do as normal program code, not as a module.| |title |[[string!|Datatypes: String!]] |The title of your module. This field can be used for directories, libraries, browsing, and user messages.| |name |[[word!|Datatypes: Word!]] |The name of the module. Identifies the module within the system, such as the argument for import. This field is important because it helps prevent a module from being reloaded if it's already been loaded earlier.| |version |[[tuple!|Datatypes: Tuple!]] |The version of the module. Multiple versions are allowed to be loaded at the same time, and the import function can be used to request that a specific version or greater be used.| |needs |[[block!|Datatypes: Block!]] |A list of other modules that your module needs to work. These other modules will be imported first, before the code in your module runs. Only used by module scripts, not dynamic modules.| |exports |[[block!|Datatypes: Block!]] |Provides a list of words that are exported by the module to the system's standard export list (if your module is named). (Do not confuse export with `public/private` properties. More below.)| When a module is created, the specification is converted to an object and the fields of the object are used to control the behavior of the module. The example above shows an example with a few fields, but depending on your requirements other fields can be provided. Also, you are free to add your own fields, as needed. !!!!! ''The body block'' The body block is identical to an object initialization block. It defines the functions and data of the module. Normally, the body block is evaluated when the module is created. In the example above, the `buy` and `sell` functions are defined in the body block, and exported via the exports block of the spec.
The [[mold|Functions: mold]] function converts a value to a string that is usable by REBOL. Strings created with [[mold|Functions: mold]] can be converted back to values with the [[load|Functions: load]] function. ``` blk: [[11 * 4] ($15 - $3.89) "eleven dollars"] probe blk [[11 * 4] ($15.00 - $3.89) "eleven dollars"] ``` ``` molded-blk: mold blk probe molded-blk {[[11 * 4] ($15.00 - $3.89) "eleven dollars"]} ``` ``` print type? blk block ``` ``` print type? molded-blk string ``` ``` probe first blk [11 * 4] ``` ``` <A name=pgfId-539552>probe first molded-blk #"[" ``` The strings returned from [[mold|Functions: mold]] can be loaded by REBOL: ``` new-blk: load molded-blk probe new-blk [[11 * 4] ($15.00 - $3.89) "eleven dollars"] ``` ``` print type? new-blk block ``` ``` probe first new-blk [11 * 4] ``` The [[mold|Functions: mold]] function does not evaluate the values of a block. ``` money: $11.11 sub-blk: [inside another block mold this is unevaluated] probe mold [$22.22 money "-- unevaluated block:" sub-blk] {[$22.22 money "-- unevaluated block:" sub-blk]} ``` ``` probe mold [a block of undefined words] [a block of undefined words] ```
Money is written as an optional international three-letter currency symbol followed by a numeric amount. For example: ``` $12.34 USD$12.34 CAD$123.45 DEM$1234,56 ```
For debugging purposes, you can monitor the actions of any handler. Each handler has its own debugging output to indicate what operations are being performed. To enable network debugging, turn network tracing on with the line: ``` trace/net on ``` To turn network debugging off, use: ``` trace/net off ``` Here is an example: ``` read pop://carl:poof@zen.example.com URL Parse: carl poof zen.example.com none none none Net-log: ["Opening tcp for" POP] connecting to: zen.example.com Net-log: [none "+OK"] Net-log: {+OK QPOP (version 2.53) at zen.example.com starting.} Net-log: [["USER" port/user] "+OK"] Net-log: "+OK Password required for carl." Net-log: [["PASS" port/pass] "+OK"] ** User Error: Server error: tcp -ERR Password supplied for "carl" is incorrect. ** Where: read pop://carl:poof@zen.example.com ```
Error messages can sometimes be confusing, especially to new users. When an error occurs in your script, you'll see an error message. You can use the why? function to open a web page to get a more detailed explanation about the error. See the [[Code: Debugging tips|Guide: Code: Debugging tips]] section for more about errors.
If you begin a block on the command line and don't end it, the block is extended to the next line. This is indicated by a prompt that begins with a bracket and is followed by indentation. The line will be indented four spaces for each open block. For example: ``` loop 10 [ [ print "example" [ if odd? random 10 [ [ print "here" [ ] [ ] ``` This is also true for multilined strings enclosed in braces. ``` Print {This is a long { string that has more { than one line.} ``` Brackets and braces that appear within quoted strings are ignored. You can escape from input at any time by pressing the ESCAPE key.
Multiple expressions are written in the same way. You don't need separators, but we often will put new expressions on a separate line to make them more readable. Here are three separate expressions: ``` print "reading web page..." data: read http://www.rebol.com print length? data ``` You could have written all these on one line, but the results would be the same. How do you know where each expression begins and ends? It is determined by the arity (the number of arguments) required by each function. For example, print only takes one argument. Once it has that argument, evaluation advances to the next expression. If you are not sure how many arguments a function requires, use help on it. However, for the most common functions, it won't take long for you to memorize them.
As mentioned in [[Code: Evaluating blocks|Guide: Code: Evaluating blocks]] a block returns a result. However, there are times when we want multiple results from a block. Consider what happens when you write: ``` print ["results:" 1 + 2 3 * 4] results: 3 12 ``` Here the block passed to print is returning more than just one value. As you can see below, the block result is no longer the same thing as: ``` do ["results:" 1 + 2 3 * 4] 12 ``` When you need multiple results, rather than do, use reduce instead: ``` reduce ["results:" 1 + 2 3 * 4] ["results:" 3 12] ``` Notice that the substitution method of evaluating your results remains the same, but you keep all results in a block. ''This is a very important concept in REBOL. It allows you to to pass, store, and return multiple values in a similar way to how you would handle a single value''.
|''Function'' |''Description''|h |[[next|Functions: next]] |Returns the next position in a series.| |[[back|Functions: back]] |Returns the previous position in a series.| |[[head|Functions: head]] |Returns the head position of a series.| |[[tail|Functions: tail]] |Returns the tail position of a series.| |[[skip|Functions: skip]] |Returns the position plus or minus an integer.| |[[at|Functions: at]] |Returns the position plus or minus an integer, but uses the same indexing as [[pick|Functions: pick]].|
As network connections are initiated, a message appears on the console. For instance, typing: ``` >> read http://www.rebol.com connecting to: www.rebol.com ``` If necessary, you can disable this output by setting the quiet flag. See the `[bad-link:concepts/console.txt]` Appendix for more information.
The first time you start REBOL, it prompts you for network information. This information is optional. Some protocols, such as email or FTP, require an email address or an email server name. In addition, if you are behind a firewall or use a proxy server, you need to provide specific information to access the Internet. To set up your network: # Type your email address. For example, name@example.com. # Type the name of your email server. For example: `mail.example.com`. Use the name of the email server you normally use. If you are not sure of the name of the server, contact your network administrator or Internet service provider for the name of your SMTP (email) server. # Specify whether you use a proxy server. If you are directly connected to the Internet with a modem or ethernet, type N (no). If you use a proxy or firewall, provide the required information as described in `[bad-link:concepts/proxy.txt]` and Firewall Settings below. Once the startup questions are answered, REBOL creates a `user.r` file and places your network settings in it. You can change these settings at any time by editing the `user.r` file.
The following example fetches news with the network news transfer protocol (NNTP), reading all of the news in a particular news group: ``` messages: read nntp://news.server.dom/comp.lang.rebol ``` The next example reads a list of all news group and prints them: ``` news-groups: read nntp://news.some-isp.net foreach group news-groups [print group] ```
<<< Editor note: pending <<< <<< Editor note: mention make-host-ext tool for building the body of the module <<< dealing with handles Pending features: codecs, devices Output a DLL. equivalent to: ``` make command! [specs extension-handle func-num] ``` More information about this will be available in the advanced section. # The method of using a single `RX_Call` entry point for all command functions was decided because it gives you a central location to setup your code's "environment" variables as well as a place to put debugging breakpoints or your own trace output. # We use this name to differentiate it from [[function!|Datatypes: Function!]], [[native!|Datatypes: Native!]], [[action!|Datatypes: Action!]], and other REBOL function-oriented datatypes.
To be sent as text, binary strings must be converted to hexadecimal or base64 encoding. This is often done for email and newsgroup content. The [[enbase|Functions: enbase]] function will encode a binary string: ``` line: "No! There's a land!" print enbase line Tm8hIFRoZXJlJ3MgYSBsYW5kIQ== ``` Encoded strings can be decoded with the [[debase|Functions: debase]] function. Note that the result is a binary value. To convert it back to a string, use the [[to-string|Functions: to-string]] function. ``` b-line: debase e-line print type? b-line binary ``` ``` probe b-line #{4E6F2120546865726527732061206C616E6421} ``` ``` print to-string b-line No! There's a land! ``` The `/base` refinement may be used with [[enbase|Functions: enbase]] and debase to specify a base2 (binary), base16 (hexadecimal), or base64 encoding. Here are some examples using base2: ``` e2-str: enbase/base str 2 print e2-str 01100001 ``` ``` b2-str: debase/base e2-str 2 print type? b2-str binary ``` ``` probe b2-str #{61} ``` ``` print to-string b2-str a ``` Here are some examples using base16: ``` e16-line: enbase/base line 16 print e16-line 4E6F2120546865726527732061206C616E6421 ``` ``` b16-line: debase/base e16-line 16 print type? b16-line binary ``` ``` probe b16-line #{4E6F2120546865726527732061206C616E6421} ``` ``` print to-string b16-line No! There's a land! ```
Numbers are written as integers, decimals, or scientific notation. For example: ``` 1234 -432 3.1415 1.23E12 ``` And can also be written in European format: ``` 123,4 0,01 1,2E12 ```
Both beginners and experts find the online help useful. !!!! ''Help on help'' {{Help on help}} !!!! ''Help about a function'' {{Help about a function}} !!!! ''Help search'' {{Help search}} !!!! ''Help on objects'' {{Help on objects}} !!!! ''Help on errors'' {{Help on objects}}
The `/only` refinement changes or inserts a block as a block, rather than its individual values. Examples: ``` blk: [1 2 3 4 5 6] ``` You can replace the 2 in `blk` with the block [a b c] and insert the block [$1 $2 $3] at the position of the 5. ``` change/only (find blk 2) [a b c] probe blk [1 [a b c] 3 4 5 6] ``` ``` insert/only (find blk 5) [$1 $2 $3] probe blk [1 [a b c] 3 4 [$1.00 $2.00 $3.00] 5 6] ```
To make mathematical expressions easier to read, the language supports infix operators like plus, minus, multiply, divide, and a few others. Operators are an exception to the above rule. Take the expression: ``` print 1 + 2 ``` This is evaluated as: ``` print (1 + 2) ``` not as: ``` (print 1) + 2 ``` Operators take precedence over normal functions. However, note that ''all operators have the same precedence''. Operators are applied from left to right. Take this example: ``` print 1 + 2 * 3 + 4 * 5 65 ``` It evaluates left to right, using the substitution method: ``` print 3 * 3 + 4 * 5 print 9 + 4 * 5 print 13 * 5 print 65 ``` Changing the order of the values changes the result: ``` print 2 * 3 + 1 + 4 * 5 55 ``` So, it's just left-to-right, and operators take precedence over functions. Looking at: ``` print 10 * sine 30 + 60 ``` It evaluates to: ``` print 10 * sine 90 print 10 * 1.0 print 10.0 ``` <<< Linear precedence If you program in other languages, you will need to remember this difference. We've found that for most expressions, linear precedence works as well or better than multilevel precedence, and you don't have to memorize all the precedence rules (which once you add comparisons and logic can become quite complex and few people remember them.) <<<
Refinements are also used to provide optional arguments. Let's say you want to provide an optional argument for rounding the result. You can do this by adding a refinement followed by its optional argument: ``` sum2: func [ "Adds two numbers and returns the result." a [number!] "The first number" b [number!] "The second number" /rounded "Return a rounded result" precision [decimal!] "The rounding precision" ] [ a: a + b if rounded [a: round/to a precision] a ] ``` Trying it out: ``` sum2 1.23 3.94 5.17 ``` ``` sum2/rounded 1.23 3.94 .1 5.2 ``` Notice that the optional argument is added to the end of the argument line. !!!! ''Values of optional arguments'' {{Values of optional arguments}}
Rules can be optional or repeated a number of ways: |''Word or value'' |''Description''|h |`opt` rule |match rule or not (zero or one time)| |`some` rule |repeat rule one or more times| |`any` rule |repeat rule zero or more times| |3 rule |repeat rule 3 times| |0 3 rule |repeat rule 0 to 3 times| |1 3 rule |repeat rule 1 to 3 times| Keywords that accept a repeat count are: ``` skip to thru quote into end ``` See the section below about repeat loop termination due to non-advancing input matching.
|''Function'' |''Description''|h |[[sort|Functions: sort]] |Sorts the values in a series into an order.| |[[reverse|Functions: reverse]] |Reverse the order of values in a series|
Above, [[func|Functions: funct]] is actually a function itself that is used to create a new function. This happens at run-time, so new functions can be defined at any time. There are also other functions for creating functions: |''funct'' |assumes variables are local by default| |''does'' |shortcut when no specification is needed| |''has'' |shortcut when only local variables are used| |''make'' |the low-level function constructor| See [[Functions|Concepts: Functions]] section for more on those.
In addition to proxy settings, you can set network timeout values for all of the schemes (in the default) or for specific schemes. For instance, to increase the timeout for all schemes, you can write: ``` system/schemes/default/timeout: 0:05 ``` This sets the network timeout for 5 minutes. If you want to increase the timeout just for SMTP, you would write: ``` system/schemes/smtp/timeout: 0:10 ``` Some schemes have custom fields. For instance, the FTP scheme allows you to set passive mode for all transfers: ``` system/schemes/ftp/passive: on ``` FTP passive mode is useful because FTP servers that are set to passive mode do not attempt to connect back through your firewall. When making HTTP accesses to Web sites, you may want to use a different user-agent field in the HTTP request to get better results on a few sites that detect the browser type: ``` system/schemes/http/user-agent: "Mozilla/4.0" ```
''An extension is a type of module''. Extensions easy to create. They can contain both C and REBOL code, and in less than one page of C you can create a useful extension. Before you can use an extension, you must [[import|Functions: import]] it. That loads the module's code and data, including both REBOL or C. There are four main concepts that you need to know to write your own extensions: |''DLL functions'' |three standard functions for initializing the extension, dispatching functions, and cleanup.| |''init block'' |a text string that defines the extension and its options, variables, exports, and initialization.| |''commands'' |the native functions provided by your extension.| |''reb-lib'' |a function API for accessing REBOL datatypes, structures, and services.| Each of these will be explained in detail below.
Pairs are used to indicate spatial coordinates, such as positions on a display. They are used to indicate both positions and sizes. Coordinates are separated by an `x`. For example: ``` 100x50 1024x800 -50x200 ```
The `pane` field provides the tree structure (the hierarchy) for a GOB display. Each pane begins a new relative-coordinate system with sub-GOBs located within it. Each GOB can include a content and a pane. In such cases, the content is layered behind any GOBs of the pane. The GOBs of the pane are also clipped according to the size of the parent GOB. <<< ''The order of layering for GOBs in a pane is last-on-top''. That is, they are rendered in the order they appear in the pane, with each successive GOB on top of the others. <<< Reuse restriction: When a GOB can only be in one pane at a time. If you attempt to insert a GOB into more than one pane, it will be removed form it prior pane. This is a necessary requirement of the linked list used to manage panes and state internal variables required for rendering. !!!! ''Adding GOBS to Panes'' To add one or more GOBs to a pane, use the [[append|Functions: append]] or insert functions. For example, given these gobs: ``` gob1: make gob! [size: 200x200 color: white] gob2: make gob! [offset: 20x20 size: 40x30 color: red] gob3: make gob! [offset: 120x80 size: 50x40 color: blue] ``` this line will add gob2 to the gob1 pane: ``` append gob1 gob2 view gob1 ``` Or, you can add several GOBs at the same time: ``` append gob1 [gob2 gob3] view gob1 ``` Note that the block of words is not reduced, but words will be looked up. !!!! ''Other Useful Actions'' You can use other series-like functions, such as getting the length: ``` length? gob1 2 ``` Or clearing the pane, or specific parts of the pane: ``` clear gob1 clear at gob1 2 ``` You can also [[remove|Functions: remove]] from the pane: ``` remove find gob1 gob2 ``` As well as use indexing refinements: ``` gob1/1: gob4 gob1/2/image: new-image ``` !!!! ''All Valid Actions'' Here's a full list of all the [[action|Datatypes: Action!]] functions that operate on the GOB datatype: |''Action'' |''Description''|h |''append'' |Inserts a value at tail of series and returns the series at head. (Modifies)| |''at'' |Returns the series at the specified index.| |''back'' |Returns the series at its previous position.| |''clear'' |Removes all values. For series, removes from current index to tail and returns tail. (Modifies)| |''find'' |Finds a value in a series and returns the series at the start of it.| |''head'' |Returns the series at its head.| |''head?'' |Returns TRUE if a series is at its head.| |''index?'' |Returns the index number of the current position in the series.| |''insert'' |Inserts into a series and returns the series after the insert. (Modifies)| |''length?'' |Returns the length of the series from the current position.| |''next'' |Returns the series at its next position.| |''past?'' |Returns TRUE if a series index is past its tail.| |''pick'' |Returns the value at the specified position in a series.| |''poke'' |Returns value after changing its data at the given index. (Modifies)| |''remove'' |Removes value(s) from a series and returns after the remove. (Modifies)| |''reverse'' |Reverses a series and similar types. (Modifies)| |''skip'' |Returns the series forward or backward from the current position.| |''tail'' |Returns the series at the position after the last value.| |''tail?'' |Returns TRUE if empty, or for series, if index is at or beyond its tail.| |''take'' |Copies and removes from series. (Typically, removes last GOB.)| !!!! ''Coordinate Mapping'' Each GOB pane provides it's own coordinate system. That is, all of it's sub-gobs are located relative to the origin of their parent. Often you will need to take a position at the top level and map it to a position within a sub-gob, or within even deeper sub-gobs. There are two functions to help perform this mapping: |''Function'' |''Description''|h |[[map-gob-offset|Functions: map-gob-offset]] |Translates a gob and offset to the deepest gob and offset in it, returned as a block: the gob and offset. Also supports the reverse operation: given a GOB and offset, provide the GOB and offset within its top-most GOB.| |[[map-event|Functions: map-event]] |Within an event datatype that has a GOB and offset position, modify the event by mapping to its terminal (lowest) GOB and offset.|
Parentheses can be used to control the order of evaluation: ``` (2 + 3) * (10 - 5) 25 ``` That is the same as: ``` 2 + 3 * (10 - 5) ``` When using length?, this is a common case: ``` if (length? "a string of chars") > 10 [print "ok"] ok ``` Of course, you can reorder that line as: ``` if 10 <= length? "a string of chars" [print "ok"] ``` But, maybe that does not read as well, so another alternative is to use the greater? function instead of the operator: ``` if greater? length? "a string of chars" 10 [print "ok"] ```
When parsing a block, if a sub-block is found, it is treated as a single value that is of the [[block!|Datatypes: Block!]] datatype. However, to parse a sub-block, you must invoke the parser recursively on the sub-block. The `into` word provides this capability. It expects that the next value in the input block is a sub-block to be parsed. This is as if a [[block!|Datatypes: Block!]] datatype had been provided. If the next value is not a block! datatype, the match fails and into looks for alternates or exits the rule. If the next value is a block, the parser rule that follows the into word is used to begin parsing the sub-block. It is processed in the same way as a sub-rule. ``` rule: [date! into [string! time!]] data: [10-Jan-2000 ["Ukiah" 10:30]] print parse data rule ``` All of the normal parser operations can be applied to into. ``` rule: [ set date date! set info into [string! time!]] ] data: [10-Jan-2000 ["Ukiah" 10:30]] print parse data rule print info rule: [date! copy items 2 into [string! time!]] data: [10-Jan-2000 ["Ukiah" 10:30] ["Rome" 2:45]] print parse data rule probe items ```
The `/part` refinement accepts a count or a position in the series and uses it to limit the effect of the function. For example, using the following series: ``` str: "abcdef" blk: [1 2 3 4 5 6] ``` you can change part of `str` and `blk` using `change/part`: ``` change/part str [1 2 3 4] 3 probe str 1234def ``` ``` change/part blk "abcd" 3 probe blk ["abcd" 4 5 6] ``` ``` You can insert part of a series into the tail of `str` and `blk` using insert/part. ``` ``` insert/part tail str "-ghijkl" 4 probe str 1234def-ghi ``` ``` insert/part tail blk ["--" 7 8 9 10 11 12] 4 probe blk ["abcd" 4 5 6 "--" 7 8 9] ``` To remove part of the `str` and `blk` series, use `remove/part`. Note how [[find|Functions: find]] is used to obtain the series position: ``` remove/part (find str "d") (find str "-") probe str 1234-ghi ``` ``` remove/part (find blk 4) (find blk "--") probe blk ["abcd" "--" 7 8 9] ```
The [[copy|Functions: copy]] function `/part` refinement takes a single argument, which is either an integer specifying the number of items to copy or a position within the series indicating the last position to copy. ``` str: "Message in a bottle" print str Message in a bottle ``` ``` print copy/part str find str " " Message ``` ``` new-str: copy/part (find str "in") (find str "bottle") print new-str in a ``` ``` blk: [ages [10 12 32] sizes [100 20 30]] new-blk: copy/part blk 2 probe new-blk [ages [10 12 32]] ```
The `/part` refinement allows a search to be confined to a specific portion of a series. For instance, you may want to restrict a search to a given line or section of text. Similar to `insert/part` and `remove/part`, `find/part` takes either a count or an ending position. The following example uses a count and restricts the search to the first three items: ``` colors: [red green blue yellow blue orange gold] probe find/part colors 'blue [blue yellow blue orange gold] ``` The next search is restricted to the first 15 characters: ``` text: "Keep things as simple as you can." print find/part text "as" 15 as simple as you can. ``` The next example uses an ending position. The search is restricted to a single line of text: ``` text: { This is line one. This is line two. } start: find text "this" end: find start newline item: find/part start "line" end print item line one. ```
File paths are written with a percent sign `%` followed by a sequence of directory names that are each separated by a forward slash `/`. ``` %dir/file.txt %/file.txt %dir/ %/dir/ %/dir/subdir/ %../dir/file.txt ``` The standard character for separating directories is the forward slash `/`, not the backslash `\`. If backslashes are found they are converted to forward slashes: ``` probe %\some\cool\movie.mpg %/some/cool/movie.mpg ``` REBOL provides a standard, operating system independent method for specifying directory paths. Paths can be relative to the current directory or absolute from the top-level file structure of the operating system. File paths that do not begin with a forward slash (/) are relative paths. ``` %docs/intro.txt %docs/new/notes.txt %"new mail/inbox.mbx ``` The standard convention of using double dots `..` to indicate a parent directory or a single dot `.` to refer to the current directory is also supported. For example: %. %./ %./file.txt %.. %../ %../script.r %../../plans/schedule.r File paths use the standard Internet convention of beginning absolute paths with a forward slash `/`. The forward slash indicates to start at the top level of the file system. (Generally, absolute paths should be avoided to ensure machine-independent scripts.) The example: ``` %/home/file.txt ``` would refer to a disk volume or partition named home. Other examples are: ``` %/ram/temp/test.r %/cd0/scripts/test/files.r ``` To refer to the C volume that is often used by Windows, the notation is: ``` %/C/docs/file.txt %"/c/program files/qualcomm/eudora mail/out.mbx ``` Notice in the above lines that the disk volume, C, is not written as: ``` %c:/docs/file.txt ``` The above example is not a machine independent format and causes an error. If the first directory name is absent, and the path begins with double forward slashes `//`, then the file path is relative to the current volume: ``` %//docs/notes ```
The following example fetches email with the post office protocol (POP) and prints all of the current messages but leaves them on the server: ``` foreach message read pop://user:pass@mail.dom [ print message ] ```
The [[secure|Functions: secure]] function provides flexibility in setting and controlling the security features of REBOL. The current security settings are returned as a result of calling the secure function. Security settings use a REBOL dialect, that is, a language within a language. The normal dialect consists of a block of paired values. The [[first|Functions: first]] value in the pair specifies what is being secured: |''file'' |specifies file security.| |''net''| specifies network security.| A file name or directory path allows you to specify security levels for a specific file or directory. The second value in the pair specifies the level of security. This can be either a security level word or a block of words. The security level words are: |''allow'' |allow access with no restrictions.| |''ask'' |ask permission if any restricted access occurs.| |''throw'' |throw an error if any restricted access occurs.| |''quit'' |quit this REBOL session if any restricted access occurs.| For example, to allow all network access, but to quit on any file access: ``` secure [ net allow ;allows any net access file quit ;any file access will cause the program to quit ] ``` If a block is used instead of a security level word, it can contain pairs of security levels and access types. This lets you specify a greater level of detail about the security you require. The access types allowed are: |''read'' |controls read access.| |''write'' |controls write, delete and rename access.| |''all'' |controls all access.| The pairs are processed in the order they appear, with later pairs modifying the effect of earlier pairs. This permits setting one type of access without explicitly setting all others. For example: ``` secure [ net allow file [ ask all allow read ] ] ``` The above sets the security level to [[ask|Functions: ask]] for all operations except for reading which is to be allowed. This technique can also be used for individual files and directories. For example: ``` secure [ net allow file quit %source/ [ask read] ] ``` asks if an attempt is made to read the `%source` directory. Otherwise, it uses the default `'quit`. There is a special case in which the secure function takes a single word argument that must be one of the security access levels. In that case, the security level for all network and file access is set to that level. ``` secure quit ``` The secure function also accepts [[none!|Datatypes: None!]], allowing access with no restrictions (same as allow). ``` secure none ``` The default security level is now: ``` secure [ net allow file [ ask all allow read ] ] ``` If no security access level is specified for either network or file access, it defaults to [[ask|Functions: ask]]. The current settings will [[not|Functions: not]] be modified if an error occurs parsing the security block argument. `[bad-link:concepts/.txt]`
Quite often, you can simply insert a [[print|Functions: print]] to see what your code is doing: ``` data: copy "test" loop 3 [print append data random 10] test3 test38 test382 ```
The [[secure|Functions: secure]] function now returns the prior security settings before the new settings were made. This is a block with the global network and file settings followed by file or directory settings. The [[query|Functions: query]] word can be used to obtain the settings without modifying them. ``` current-security: secure query ``` You can modify the current security level by querying the current settings, modifying them, then using the secure function to set the new values. Lowering the security level produces a change security settings request. The exception is when the REBOL session is running in `quiet` mode which will, instead, terminate the REBOL session. No query is generated when security levels are raised. Note that the security request now includes an option to allow all access for the remainder of the scripts processing. When running REBOL from the shell, the -s argument is equivalent to: ``` secure allow ``` and the `+s` arguments is equivalent to: ``` secure quit ``` You can now follow the `--secure` argument with one of the security access levels for both network and file access: ``` rebol --secure throw ```
The [[probe|Functions: probe]] function will [[mold|Functions: mold]] a value into source format and display it. It also returns the value as a result. ``` word: 'here if probe find [where here there] word [] [here there] ``` Unlike [[print|Functions: print]], [[probe|Functions: probe]] does not evaluate the contents of blocks. ``` probe [1 + 2] [1 + 2] ``` ``` print [2 + 2] 3 ```
There are a number of arguments that can be specified in a shell command line, in a batch script, or in the properties of an icon. To view the arguments and options available for any version of the REBOL language, type [[usage|Functions: usage]] at the console prompt. ``` The command line usage is: REBOL <options> <script> <arguments> All fields are optional. Supported options are: --cgi (-c) Check for CGI input --do expr Evaluate expression --help (-?) Display this usage information --nowindow (-w) Do not open a window --noinstall (-i) Do not install (View) --quiet (-q) Don't print banners --reinstall (+i) Force an install (View) --script file Explicitly specify script --secure level Set security level: (allow ask throw quit) --trace (-t) Enable trace mode --uninstall (-u) Uninstall REBOL (View) Other command line options: +q Force not quiet (View) -s No security +s Full security -- args Provide args without script Examples: REBOL script.r REBOL script.r 10:30 test@domain.dom REBOL script.r --do "verbose: true" REBOL --cgi -s REBOL --cgi --secure throw --script cgi.r "debug: true" REBOL --secure none ``` Again, the format of the command line is: ``` REBOL options script arguments ``` Where: |''options'' |one or more of the program options. See `[bad-link:concepts/specifying.txt]` Options below for more details.| |''script'' |the file name of the script you want to run. If the file name contains spaces, it should be typed in quotes.| |''arguments'' |the arguments passed to the script as a string. These arguments can be accessed from within the script.| All of the above arguments are optional, and any combination is permitted. <<< Shortcut Icons In some operating systems, like Windows or AmigaOS, you can create icons that supply any of the above options as part of the icon. Using this technique, you can create icons that directly execute REBOL scripts with the correct options. <<<
You can prevent a word from being set with the [[protect|Functions: protect]] function: ``` protect 'word ``` An attempt to redefine a protected word causes an error: ``` word: "here" ** Script Error: Word word is protected, cannot modify. ** Where: word: "here" ``` A word can be unprotected as well using [[unprotect|Functions: unprotect]] : ``` unprotect 'word word: "here" ``` The protect and [[unprotect|Functions: unprotect]] functions also accept a block of words: ``` protect [this that other] ``` Important function and system words can be protected using the [bad-link:functions/protect-system.txt] function. Protecting function and system words is especially useful for beginners who might accidentally set important words. If `[bad-link:functions/protect-system.txt]` is placed in your user.r file, then all predefined words are protected.
Frequently, organizations use a firewall or proxy server to protect access to and from the Internet. Before REBOL can access the Internet through these systems, you need to provide some additional information. To provide proxy server information: # When REBOL asks if you use a proxy server, answer by typing Y (yes). # Type the name of your proxy host. This is the computer or firewall on your network serving as a proxy. # Type the port number used by the proxy host for proxy requests. Typically, this is port 1080, but this can vary. If you don't know the port number, check your Web browser settings or ask your network administrator. REBOL defaults to using a SOCKS proxy protocol. You can specify some other type of proxy by editing the `user.r` file and supplying the `[bad-link:functions/set-net.txt]` function with the appropriate identification for the type of proxy being used. The following settings are supported: ``` socks - use the latest SOCKS version (5) socks5 - use socks5 proxy socks4 - use socks4 proxy generic - use generic CERN proxy none - use no proxy ``` These settings are provided as the sixth argument to the `[bad-link:functions/set-net.txt]` function called in the `user.r` file. For more information about modifying the proxy settings in the user.r file, refer to the [bad-link:concepts/network.txt] Protocols Chapter.
If you use a proxy or firewall, you can provide the set-net function with your proxy settings. This can include the proxy server name or address, a proxy port number to access the server, and an optional proxy type. For example: ``` set-net [ email@addr mail.example.com pop.example.com proxy.example.com 1080 socks ] ``` This example would use a proxy called `proxy.example.com` on its TCP port 1080 with the socks proxy method. To use a `socks4` proxy server, use the word `socks4` rather than `socks`. To use the generic CERN server, use the word `generic`. You can also set the proxy to be different machines for different schemes (protocols). Each protocol has its own proxy object where you can set the proxy values for just that scheme. Here is an example of setting a proxy for FTP: ``` system/schemes/ftp/proxy/host: "proxy2.example.com" system/schemes/ftp/proxy/port-id: 1080 system/schemes/ftp/proxy/type: 'socks ``` In this case, only FTP uses a special proxy server. Notice that the machine name must be a string and the proxy type must be a literal word. Here are two more examples. The first example sets the proxy for HTTP to be the generic (CERN) proxy method: ``` system/schemes/http/proxy/host: "wp.example.com" system/schemes/http/proxy/port-id: 8080 system/schemes/http/proxy/type: 'generic ``` In the above example, all HTTP requests go through a generic proxy on wp.example.com using TCP port 8080. If you want to disable the proxy settings for a particular scheme, you can set the proxy fields to false. ``` system/schemes/smtp/proxy/host: false system/schemes/smtp/proxy/port-id: false system/schemes/smtp/proxy/type: false ``` In the above example, all outgoing email does not go through a proxy. The false value prevents even the default proxy from being used. If you set these fields to none!, then the default proxy is used if it is configured. If you want to bypass the proxy settings for particular machines, such as those on your local network, you can provide a bypass list. Here is a bypass list for the default proxy: ``` system/schemes/default/proxy/bypass: ["host.example.net" "*.example.com"] ``` Note that the asterisk ('') and question mark (?) characters can be used for pattern matching. The asterisk ('') as used in the example above bypasses any machine that ends with example.com. To set a bypass list for only the HTTP scheme, type: ``` system/schemes/http/proxy/bypass: ["host.example.net" "*.example.com"] ```
Series datatypes are grouped into a few pseudo-types that make function argument and type testing easier: |''Pseudo-type'' |''Description''|h |`[bad-link:datatypes/series.txt]` |A series datatype| |`[bad-link:datatypes/any-block.txt]` |Any of the block datatypes| |`[bad-link:datatypes/any-string.txt]` |Any of the string datatypes|
We like to keep REBOL really easy to run, so... # The [[R3 Download|http://www.rebol.com/r3/downloads.html]] is small (about 550 KB.) # You don't need anything else. No other DLLs or other files are needed. You don't need SQL or .NET. # You can just run it. It does not require installation. (We'll give you the option later to install in order to make icons and file types work.)
You can find a small package that contains source files for getting started at: [[example REBOL extension source code and binary|http://www.rebol.com/r3/example/ext-a77.zip]] It's a 12K zip. To try it: run REBOL R3 with the `test-ext.r` script and ext-test.dll file in the same directory. A few notes to be aware of at this time: * ''It's a first draft''. It works, but more to do. * ''It's useful already''. Try a few of your own favorite math natives. They will fly. * ''Do not post bugs on CureCode, yet''. Just like the GUI, I don't want to generate alpha noise. Post your notes in Chat group 5045. * ''Don't hack beyond the isolation interface''. Any first year student can do it, but if you break the isolation, future updates will break you. That is a promise. * ''By default, SECURE will block extensions''. You can easily guess why. * ''The included MSVC project files are old school''. But, the build is trivial, whatever compiler you like should be easy. If you want to post instructions for other compilers... send them to me or put them in the docs.
We are considering changing the suffix for R3, in order to make it easy for an OS to identify the correct interpreter for the file.
You can use the `/read` refinement to open a port as read only: ``` fp: open/read %file.txt ``` Changes made to the port's buffer, are not written back to the file. To open for write only, use the `/write` refinement: ``` fp: open/write %file.txt ``` File ports opened with the `/write` refinement will not read the current data upon opening the port. Closing, or updating a write only file port will cause existing data in the file to be overwritten: ``` insert fp "This is the law of the Yukon..." close fp print read %file.txt This is the law of the Yukon... ```
Another option is to read a file as a block of strings. Each line is a separate string within the block. This format is handy at times for processing files on a line-by-line basis. ``` doc: read/lines %data.txt foreach line doc [print line] ``` Note that each line is a string and does not contain the line terminator.
Directories are read in the same manner as files. The [[read|Functions: read]] function returns a block of file names rather than text or binary data. To read all the file names from the current directory, use the following line of code: ``` read %. ``` The above example reads the entire directory and returns a block of file names. To print the names of all files in a directory, use the following line of code: ``` print read %intro/ CVS/ history.t intro.t overview.t quick.t ``` Within the returned block, names of directories are indicated with a trailing forward slash. To print each file name on a separate line, use: ``` foreach file read %intro/ [print file] CVS/ history.t intro.t overview.t quick.t ``` Here is an easy way to print just the directories that were found: ``` foreach file read %intro/ [ if #"/" = last file [print file] ] CVS/ ``` If you want to read a directory from the network, be sure to include a forward slash at the end of the URL to indicate to the protocol that you are referring to a directory: ``` print read ftp://ftp.rebol.com/ ```
There are several ways to read a file. For small files, you can simply read them directly with a line like: ``` data: read %image.jpg ``` This works for files up to a few megabytes. Beyond that, it's better to break the read up into sections (using open). More on that later. The data above is the [[binary!|Datatypes: Binary!]] contents of the file. No conversions are made to the data. Thus, any kind of file can be read this way, including images, programs, sounds, encoded text, etc. <<< Note change from R2: Please note that files in R3 are read as binary! as the default. This was done to prevent corruption to files for data such as images, when read accidentally as read as text. In addition, because of Unicode, even text files are now assumed to be encoded (even if they are ASCII.) <<<
To read a binary file such as an image, a program, or a sound, use `read/binary`: ``` data: read/binary %file.bin ``` The `read/binary` function returns a binary series that holds the entire contents of the file. In the above example, the variable data refers to the binary series. No conversion of any type is done to the file. To read a binary file a piece at a time, use the open function as described in the [[ports|Concepts: Ports]] Chapter.
Files can be read from a network. For example, to view a text file from a network using the HTTP protocol: ``` print read http://www.rebol.com/test.txt Hellotherenewuser! ``` The file could be written locally with the line: ``` write %test.txt read http:/www.rebol.com/test.txt ``` In the write process the file will have its line termination converted to that which is used by your operating system. To read and save a binary file, such as an image, use the following line: ``` write %image.jpg read/binary http:/www.rebol.com/image.jpg ``` Refer to the chapter on `[bad-link:concepts/network.txt]` Protocols for more information and examples of accessing files across networks.
If you want to read a file as string, you can use the `/string` refinement to indicate that you want the necessary Unicode (UTF-8) and line conversions. For example: ``` notes: read/string %notes.txt ``` Line terminators will be converted to the standard format used within REBOL strings (a single LF character at the end of each line.)
To read a local text file, use the read function: ``` text: read %file.txt ``` The [[read|Functions: read]] function returns a string that holds the entire text of the file. In the above example, the variable text refers to that string. Within the string returned by read, line terminators are converted to newline characters, regardless of what style of line termination is used on your operating system. This allows you to write scripts that search for `newline` without concern for what particular character or characters constitute a line termination. ``` next-line: next find text newline ``` A file can also be read as separate lines that are stored in a block: ``` lines: read/lines %file.txt ``` See the `[bad-link:concepts/line.txt]` Conversion section for more information about newline and reading lines. To read a file a piece at a time, use the [[open|Functions: open]] function as described in the [[ports|Concepts: Ports]] Chapter. To view the contents of a text file, you can read it using [[read|Functions: read]] and print it using `print`: ``` print read %service.txt I wanted the gold, and I sought it,I scrabbled and mucked like a slave. ```
<<< Pending Revision This document was written for R2 and has yet to be revised for R3. <<< ''Contents'' * [[Modes of Operation]] * [[Specifying Network Resources]] * [[Schemes, Handlers, and Protocols]] * [[Monitoring Handlers]] !!! ''Modes of Operation'' {{Modes of Operation}} !!! ''Specifying Network Resources'' {{Specifying Network Resources}} !!! ''Schemes, Handlers, and Protocols'' {{Schemes, Handlers, and Protocols}} !!! ''Monitoring Handlers'' {{Monitoring Handlers}}
When you evaluate a block with do, only the value of its last expression is returned as a result. However, there are times when you want the values of all the expressions in a block to be returned. To return the results of all of the expressions in a block, use the [[reduce|Functions: reduce]] function. In the following example, reduce is used to return the results of both expressions in the block: ``` reduce [ 1 + 2 3 + 4 ] [3 7] ``` In the above example, the block was ''reduced'' to its evaluation results. The reduce function returns results in a block. The [[reduce|Functions: reduce]] function is important because it enables you to create blocks of expressions that are evaluated and passed to other functions. reduce evaluates each expression in a block and puts the result of that expression into a new block. That new block is returned as the result of [[reduce|Functions: reduce]]. Some functions, like [[print|Functions: print]], use reduce as part of their operation, as shown in the following example: ``` print [1 + 2 3 + 4] 3 7 ``` The [[rejoin|Functions: rejoin]], [[reform|Functions: reform]], and [[remold|Functions: remold]] functions also use [[reduce|Functions: reduce]] as part of their operation, as shown in the following examples: ``` print rejoin [1 + 2 3 + 4] 37 ``` ``` print reform [1 + 2 3 + 4] 3 7 ``` ``` print remold [1 + 2 3 + 4] [3 7] ``` The [[rejoin|Functions: rejoin]], [[reform|Functions: reform]], and [[remold|Functions: remold]] functions are based on the [[join|Functions: join]], [[form|Functions: form]], and [[mold|Functions: mold]] functions, but reduce their blocks first.
<<< Out of date This section is out of date and needs revision. <<< Within extensions it can be quite useful to access words as symbols. For example, if you are writing an extension that has it's own special control dialect, you will want to easily handle the words that are part of it. (If you were familiar with AREXX in AmigaOS, then you know what can be done with just little programming effort.) There are generally two ways to use a [[word!|Datatypes: Word!]] type: |''symbols'' |words that represent themselves (the word itself is the meaning)| |''variables'' |words used to represent storage| In the R3 1.0 extension interface, words are supported as symbols only. When you specify your extension, within its module initialization, define a block of words. Later within your code, the word will be indicated by its index within that block. For example, if within your init block you define: ``` words: [jpeg mpeg gif tiff] resize-image: command [img [image!] 'action [word!]] ``` then you can use this C code to determine which word was passed: ``` switch (RXA_WORD(frm, 2)) { case 1: // jpeg ... case 2: // mpeg ... case 3: // gif ... case 4: // tiff ... } ``` This same technique can be used for words found in blocks. (See block value access below.) Now, writing: ``` resize-image data 'gif ``` will enter the case 3 code above. (Of course, this can also be done using `[bad-link:datatypes/refinements.txt]`, see earlier notes.)
Find has many refinements that support a wide variety of search parameters: |''Refinement'' |''Description''|h |`/part` |Limits a search on a series to a given length or ending position.| |`/only` |Treats a series value as a single value.| |`/case` |Uses case-sensitive string comparison.| |`/any` |Allows the use of pattern wildcards that allow matches to be made with any character. An asterisk `()` in the pattern matches any string, and a question mark `?` in the pattern matches any character.| |`/with` |Allows pattern wildcards with different characters other than asterisk () and (?). This allows a pattern to contain asterisks and question marks.| |`/match` |Matches a pattern beginning at the current series position, rather than finding the first occurrence of a value or string. Returns the tail position if the match is found.| |`/tail` |Return the tail position of a match on a successful search, rather than returning the point at which the match was found.| |`/last` |Searches backwards for the match, starting at the tail of the series.| |`/reverse` |Searches backwards for the match, starting at the current position.|
A refinement specifies a variation in the normal evaluation of a function. Refinements also allow optional arguments to be provided. Refinements are available for both native and user-defined functions. Refinements are specified by following the function name with a forward slash `/` and a refinement name. For instance: ``` copy/part (copy just part of a string) find/tail (return the tail of the match) load/markup (return XML/HTML tags and strings) ``` Functions can also include multiple refinements: ``` find/case/tail (match case and return tail) insert/only/dup (insert entire block multiple times) ``` You have seen the [[copy|Functions: copy]] function used to make a copy of a string. By default, copy returns a copy of its argument: ``` string: "no time like the present" print copy string no time like the present ``` Using the `/part` refinement, copy returns part of the string: ``` print copy/part string 7 no time ``` ``` In the previous example, the /part refinement specifies that only seven characters of the string are copied. ``` To review what refinements are allowed on a function such as copy, use online help: ``` help copy USAGE: COPY value /part range /deep DESCRIPTION: Returns a copy of a value. COPY is an action value. ARGUMENTS: value -- Usually a series (Type: series port bitset) REFINEMENTS: /part -- Limits to a given length or position. range -- (Type: number series port) /deep -- Also copies series values within the block. ``` Notice that the `/part` refinement requires an additional argument. Not all refinements require additional arguments. For example, the `/deep` refinement specifies that copy make copies of all its sub-blocks. No other arguments are required. When multiple refinements are used with a function, the order of the extra arguments is determined by the order in which the refinements are specified. For example: ``` str: "test" insert/dup/part str "this one" 4 5 print str this this this this test ``` Reversing the order of the `/dup` and `/part` refinement changes the order of the arguments. You can see the difference: ``` str: "test" insert/part/dup str "this one" 4 5 print str thisthisthisthisthistest ``` The refinements indicate the order of the arguments.
The [[reform|Functions: reform]] function is like [[form|Functions: form]], except that blocks are reduced before being converted. ``` str1: "Today's date is:" str2: "The time is now:" print reform [str1 now/date newline str2 now/time] Today's date is: 30-Jun-2000 The time is now: 14:41:44 ``` The [[print|Functions: print]] function is based on the [[reform|Functions: reform]] function.
The [[rejoin|Functions: rejoin]] function is identical to [[join|Functions: join]], except that it takes one argument, a block. ``` print rejoin ["try" 1 2 3] try123 ``` ``` print rejoin ["h" 'e #"l" (to-char 108) "o"] hello ```
The [[remold|Functions: remold]] function works just like [[mold|Functions: mold]], except that blocks are reduced before being converted. ``` str1: "Today's date is:" probe remold [str1 now/date] {["Today's date is:" 30-Jun-2000]} ```
You can remove one or more values from any part of a series by using the remove function. For instance, starting with the block: ``` colors: [red green blue gold] ``` As shown here: You can remove the first value from the block with the line: ``` remove colors ``` The block becomes: It can be printed with: ``` probe colors [green blue gold] ``` The [[remove|Functions: remove]] function removes values relative to the position of the `colors` variable. You can remove values from anywhere in the series by setting the position. ``` remove next colors ``` The block is now: Multiple values can be removed by supplying the `/part` refinement. ``` remove/part colors 2 ``` This removes the remaining values, leaving an empty block: Similar to `insert/part`, the argument to `remove/part` can also be a position within the block. Removing all of the remaining values is a common operation. The [[clear|Functions: clear]] function is provided to make this more direct. [[clear|Functions: clear]] removes all values from the current position to the tail. For example: ``` Colors: [blue red green gold] ``` As shown here: Everything after blue can be removed with: ``` clear next colors ``` The block becomes: You can easily clear the entire block with: ``` clear colors ```
To rename a file, use the rename function: ``` rename %old-file %new-file ``` The old file name may include a complete path to the file, but the new file name must not include a path. This is because the [[rename|Functions: rename]] function is not intended to move files between directories (various operating systems do not provide this function). ``` rename %../docs/intro.txt %conclusion.txt ``` If the old file name is a directory (indicated by a trailing slash), the [[rename|Functions: rename]] function renames the directory: ``` rename %../docs/ %manual/ ``` If the file cannot be renamed, an error will occur. The error can be caught with the [[try|Functions: try]] function.
Graphics is rendered with the [[show|Functions: show]] function. This same function is used for both initial rendering as well as updates (refresh). The target GOB to render is specified as the argument. The line: ``` show gob1 ``` Render gob1 as well as all sub-gobs in its pane, if it has one. If the GOB is already being displayed, it's display would be refreshed. This same function is true for window GOBs: ``` show win ``` renders all of the graphics in the window and redisplays it. The [[show|Functions: show]] function also allows a block of GOBs: ``` show [gob1 gob2 gob3] ``` As you can see, if the gobs are words, their values will be used. Here are a few important notes about rendering: * ''Rendering order is first to last'' For GOB panes, each GOB is rendered in the order it appears in the pane, with each successive GOB on top of the others, with the last GOB on top. * ''Background refresh'' When a GOB offset is moved relative to its parent GOB, or when it changes size, any background behind the GOB is re-rendered. (Internally a GOB stores its old-offset and old-size information for use in this process.) * ''Optimized show'' If a gob appears more than once within a [[show|Functions: show]] block (and the panes of gobs in that block) the second case of the GOB will be ignored (an optimization). * ''Delayed show'' If you are changing several GOBs during a single event, it is more efficient to keep a list of changes then render all the changes together with a single call to [[show|Functions: show]]. In the R3 GUI, this is done by defining a `show-later` that queues the requests to a block, then calls `show-now` to refresh the display.
The [[repeat|Functions: repeat]] function extends [[loop|Functions: loop]] by allowing you to refer to the loop counter variable. The [[repeat|Functions: repeat]] function's first argument is a word that will be used to hold the count value: ``` repeat count 3 [print ["count:" count]] count: 1 count: 2 count: 3 ``` Notice that [[repeat|Functions: repeat]] is one-based. The counter begins at one, not zero. The final block value is also returned: ``` i: 0 print repeat count 10 [i: i + count] 55 ``` Important to know: In the above loop, and many that follow, the `count` word only has its counting value within the block. We say that `count` is ''local to the block''. (A special context exists while the block is evaluated. See [[bind|Functions: bind]] for details.) Any value that `count` had before the loop, it will still have after the loop. The loop does not effect it. For example: ``` count: "test" ``` ``` repeat count 3 [print ["count:" count]] count: 1 count: 2 count: 3 print count test ```
You can easily repeat the [[find|Functions: find]] function to search for multiple occurrences of a value or string. Here is an example that would print all the strings found in a block: ``` blk: load %script.r while [blk: find blk string!] [ print first blk blk: next blk ] ``` The next example counts the number of new lines in a script. It uses the `/tail` refinement to prevent an infinite loop and returns the position immediately following the match. ``` text: read %script.r count: 0 while [text: find/tail text newline] [count: count + 1] ``` To perform a repeated search in reverse, use the `/reverse` refinement. The following example prints all of the index positions in reverse order for the text of a script. ``` while [text: find/reverse tail text newline] [ print index? text ] ```
The `sum2` example above did not require arguments of any specific type. That means you can provide any type of data as arguments: ``` print sum2 10:00 2:30 12:30 ``` ``` print sum2 1-Jan-2009 10 11-Jan-2009 ``` However, if you need to restrict argument types, you can do that within the specification block. Here we restrict a and b to be [[integer!|Datatypes: Integer!]] only: ``` sum2: func [a [integer!] b [integer!]] [a + b] ``` Multiple types are also allowed. Here we've added [[decimal!|Datatypes: Decimal!]] as well: ``` sum2: func [ a [integer! decimal!] b [integer! decimal!] ] [ a + b ] ``` Now, if you provide two times as arguments, you'll get an error: ``` print sum2 10:10 2:30 ** Script error: sum2 does not allow time! for its a argument ``` In addition to datatype names, you can also use [[typeset!|Datatypes: Typeset!]], which are groups of datatypes. (To see a list of predefined typesets, type `? typeset!` at the console.) For example, `number!` is defined as a typeset that includes [[integer!|Datatypes: Integer!]], [[decimal!|Datatypes: Decimal!]], and [[percent!|Datatypes: Percent!]]. ``` sum2: func [ a [number!] b [number!] ] [ a + b ] ```
The examples in previous chapters showed how to parse strings, but no results were produced. This is only done to verify that a string has the specified grammar; the value returned from parse indicates its success. The following examples show this: ``` probe parse "a b c" ["a" "b" "c"] true ``` ``` probe parse "a b" ["a" "c"] false ``` The [[parse|Functions: parse]] function returns `true` only if it reaches the end of the input string. An unsuccessful match stops the parse of the series. If [[parse|Functions: parse]] runs out of values to search for before reaching the end of the series, it does not traverse the series and returns `false`: ``` probe parse "a b c d" ["a" "b" "c"] false ``` ``` probe parse "a b c d" [to "b" thru "d"] true ``` ``` probe parse "a b c d" [to "b" to end] true ```
As you know from the `[bad-link:concepts/expressions.txt]` Chapter, blocks return their last value when they return from evaluation: ``` do [1 + 3 5 + 7] 12 ``` This is also true for functions. The last value is returned as the value of the function: ``` sum: func [a b] [ print a print b a + b ] print sum 123 321 123 321 444 ``` In addition, the [[return|Functions: return]] function can be used to stop the evaluation of a function at any point and return a value: ``` find-value: func [series value] [ forall series [ if (first series) = value [ return series ] ] none ] probe find-value [1 2 3 4] 3 [3 4] ``` In the example, if the value is found, the function returns the series at the position of the match. Otherwise, the function returns [[none!|Datatypes: None!]]. To stop a function evaluation without returning a value, use the [[exit|Functions: exit]] function: ``` source: func [ "Print the source code for a word" 'word [word!] ][ prin join word ": " if not value? word [print "undefined" exit] either any [ native? get word op? get word action? get word ][ print ["native" mold third get word] ][print mold get word] ] ```
Here is an example that shows how to return a few different values. The REBOL module code is: ``` REBOL [ Title: {Example} Type: module Exports: [t-unset t-none t-true t-false t-value t-block] ] t-unset: command [] t-none: command [] t-true: command [] t-false: command [] t-value: command [v] t-block: command [a b c] ``` The relevant C code is: ``` RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { switch (cmd) { case 0: return RXR_UNSET; case 1: return RXR_NONE; case 2: return RXR_TRUE; case 3: return RXR_FALSE; case 4: return RXR_VALUE; // return first arg case 5: return RXR_BLOCK; // 3 args become a block } } ```
To return more than one value from a function, use a block. You can do this easily by returning a block that has been reduced. For example: ``` find-value: func [series value /local count] [ forall series [ if (first series) = value [ reduce [series index? series] ] ] none ] ``` The function returns a block that holds the series and the index value where the value was found. ``` probe find-value [1 2 3 4] 3 [[3 4] 3] ``` The [[reduce|Functions: reduce]] is necessary to create a block of values from the block of words that it is given. Do not return the local variables themselves. That is not a supported mode of operation (currently). To easily set variables to the return value of the function, use `set`: ``` set [block index] find-value [1 2 3 4] 3 print block 3 4 ``` ``` print index 3 ```
|''Function:'' |int RL_Callback(RXICBI cbi)| |''Summary:'' |Evaluate a REBOL callback function, either synchronous or asynchronous.| |''Returns:'' |Sync callback: type of the result; async callback: true if queued| |''Arguments:'' |cbi - callback information including special option flags, object pointer (where function is located), function name as global word identifier (within above object), argument list passed to callback (see notes below), and result value.| |''Notes: ''|The flag value will determine the type of callback. It can be either synchronous, where the code will re-enter the interpreter environment and call the specified function, or asynchronous where an EVT_CALLBACK event is queued, and the callback will be evaluated later when events are processed within the interpreter's environment. For asynchronous callbacks, the cbi and the args array must be managed because the data isn't processed until the callback event is handled. Therefore, these cannot be allocated locally on the C stack; they should be dynamic (or global if so desired.) See [[extensions: callback functions|Concepts: Extensions: Callback Functions]]|
|''Function:'' |int RL_Do_Binary(REBYTE bin, REBINT length, REBCNT flags, REBCNT key, RXIARG result)| |''Summary:'' |Evaluate an encoded binary script such as compressed text.| |''Returns:'' |The datatype of the result or zero if error in the encoding.| |''Arguments:'' |''bin'' - by default, a REBOL compressed UTF-8 (or ASCII) script. ''length'' - the length of the data. ''flags'' - special flags (set to zero at this time). ''key'' - encoding, encryption, or signature key. ''result'' - value returned from evaluation.| |''Notes: ''|As of A104, only compressed scripts are supported, however, rebin, cloaked, signed, and encrypted formats will be supported.|
|''Function:'' |int RL_Do_Block(REBSER blk, REBCNT flags, RXIARG result)| |''Summary:'' |Evaluate a block. (not implemented)| |''Returns:'' |The datatype of the result or zero if error in the encoding.| |''Arguments:'' |''blk'' - A pointer to the block series. ''flags'' - set to zero for now. ''result'' - value returned from evaluation| |''Notes: ''|Not implemented. Contact Carl on R3 Chat if you think you could use it for something.|
|''Function:'' |void RL_Do_Commands(REBSER blk, REBCNT flags, REBCEC context)| |''Summary:'' |Evaluate a block of extension commands at high speed.| |''Returns:'' |Nothing| |''Arguments:'' |''blk'' - a pointer to the block series. ''flags'' - set to zero for now. ''context'' - command evaluation context struct or zero if not used.| |''Notes: ''|For command blocks only, not for other blocks. The context allows passing to each command a struct that is used for back-referencing your environment data or for tracking the evaluation block and its index.|
|''Function:'' |int RL_Do_String(REBYTE text, REBCNT flags, RXIARG result)| |''Summary:'' |Load a string and evaluate the resulting block.| |''Returns:'' |The datatype of the result.| |''Arguments:'' |''text'' - A null terminated UTF-8 (or ASCII) string to transcode into a block and evaluate. ''flags'' - set to zero for now. ''result'' - value returned from evaluation.|
|''Function:'' |void RL_Escape(REBINT reserved)| |''Summary:'' |Signal that code ecaluation needs to be interrupted.| |''Returns:'' |nothing| |''Arguments:'' |reserved - must be set to zero.| |''Notes: ''|This function set's a signal that is checked during evaluation and will cause the interpreter to begin processing an escape trap. Note that control must be passed back to REBOL for the signal to be recognized and handled.|
|''Function:'' |int RL_Event(REBEVT evt)| |''Summary:'' |Appends an application event (e.g. GUI) to the event port.| |''Returns:'' |Returns TRUE if queued, or FALSE if event queue is full.| |''Arguments:'' |evt - A properly initialized event structure. The contents of this structure are copied as part of the function, allowing use of locals.| |''Notes: ''| Sets a signal to get REBOL attention for WAIT and awake. To avoid environment problems, this function only appends to the event queue (no auto-expand). So if the queue is full|
|''Function:'' |void RL_Extend(REBYTE source, RXICAL call)| |''Summary:'' | Appends embedded extension to system/catalog/boot-exts.| |''Returns:'' |A pointer to the REBOL library (see reb-lib.h).| |''Arguments:'' |''source'' - A pointer to a UTF-8 (or ASCII) string that provides extension module header, function definitions, and other related functions and data. ''call'' - A pointer to the extension's command dispatcher.| |''Notes: ''|This function simply adds the embedded extension to the boot-exts list. All other processing and initialization happens later during startup. Each embedded extension is queried and init using LOAD-EXTENSION system native. See [[extensions: embedded extensions|Concepts: Extensions: Embedded Extensions]]|
|''Function:'' |u32 RL_Find_Word(u32 words, u32 word)| |''Summary:'' |Given an array of word ids, return the index of the given word.| |''Returns:'' |The index of the given word or zero.| |''Arguments:'' |''words'' - a word array like that returned from MAP_WORDS (first element is size) ''word'' - a word id| |''Notes: ''|The first element of the word array is the length of the array.|
|''Function:'' |int RL_Get_Char(REBSER series, u32 index)| |''Summary:'' |Get a character from byte or unicode string.| |''Returns:'' |A Unicode character point from string. If index is at or past the tail, a -1 is returned.| |''Arguments:'' |''series'' - string series pointer. ''index'' - zero based index of character| |''Notes: ''|This function works for byte and unicoded strings. The maximum size of a Unicode char is determined by R3 build options. The default is 16 bits.|
|''Function:'' |int RL_Get_Field(REBSER obj, u32 word, RXIARG result)| |''Summary:'' |Get a field value (context variable) of an object.| |''Returns:'' |Datatype of value or zero if word is not found in the object.| |''Arguments:'' |''obj'' - object pointer (e.g. from RXA_OBJECT) ''word'' - global word identifier (integer) ''result'' - gets set to the value of the field|
|''Function:'' |int RL_Get_String(REBSER series, u32 index, void str)| |''Summary:'' |Obtain a pointer into a string (bytes or unicode).| |''Returns:'' |The length and type of string. When len > 0, string is unicode. When len < 0, string is bytes.| |''Arguments:'' |''series'' - string series pointer. ''index'' - index from beginning (zero-based) ''str'' - pointer to first character| |''Notes: ''|If the len is less than zero, then the string is optimized to codepoints (chars) 255 or less for ASCII and LATIN-1 charsets. Strings are allowed to move in memory. Therefore, you will want to make a copy of the string if needed.|
|''Function:'' |int RL_Get_Value(REBSER series, u32 index, RXIARG result)| |''Summary:'' |Get a value from a block.| |''Returns:'' |Datatype of value or zero if index is past tail.| |''Arguments:'' |''series'' - block series pointer. ''index'' - global word identifier (integer) ''result'' - set to the value of the field|
|''Function:'' |int RL_Init(REBARGS rargs, void lib)| |''Summary:'' |Initialize the REBOL interpreter.| |''Returns:'' | Zero on success, otherwise an error indicating that the host library is not compatible with this release.| |''Arguments:'' |''rargs'' - REBOL command line args and options structure. See the host-args.c module for details. ''lib'' - the host lib (OS_ functions) to be used by REBOL. See host-lib.c for details.| |''Notes: ''|This function will allocate and initialize all memory structures used by the REBOL interpreter. This is an extensive process that takes time.|
|''Function:'' |void RL_Make_Block(u32 size)| |''Summary:'' |Allocate a new block.| |''Returns:'' |A pointer to a block series.| |''Arguments:'' | size - the length of the block. The system will add one extra for the end-of-block marker.| |''Notes: ''|Blocks are allocated with REBOL's internal memory manager. Internal structures may change, so NO assumptions should be made! Blocks are automatically garbage collected if there are no references to them from REBOL code (C code does nothing.) However, you can lock blocks to prevent deallocation. (?? default)|
|''Function:'' |void RL_Make_Image(u32 width, u32 height)| |''Summary:'' |Allocate a new image of the given size.| |''Returns:'' |A pointer to an image series.| |''Arguments:'' |''width'' - the width of the image in pixels. ''height'' - the height of the image in lines| |''Notes: ''|Images are allocated with REBOL's internal memory manager. Image are automatically garbage collected if there are no references to them from REBOL code (C code does nothing.)|
|''Function:'' |void RL_Make_String(u32 size, int unicode)| |''Summary:'' |Allocate a new string.| |''Returns:'' |A pointer to a string series.| |''Arguments:'' |''size'' - the length of the string. The system will add one extra for a null terminator (not strictly required, but good for C.) ''unicode'' - set FALSE for ASCII/Latin1 strings, set TRUE for Unicode.| |''Notes: ''|Strings can be REBYTE or REBCHR sized (depends on R3 config.) Strings are allocated with REBOL's internal memory manager. Internal structures may change, so NO assumptions should be made! Strings are automatically garbage collected if there are no references to them from REBOL code (C code does nothing.) However, you can lock strings to prevent deallocation. (?? default)|
|''Function:'' |u32 RL_Map_Word(REBYTE string)| |''Summary:'' |Given a block of word values, return an array of word ids.| |''Returns:'' |An array of global word identifiers (integers). The [0] value is the size.| |''Arguments:'' |series - block of words as values (from REBOL blocks, not strings.)| |''Notes: ''|Word identifiers are persistent, and you can use them anytime. The block can include any kind of word, including set-words, lit-words, etc. If the input block contains non-words, they will be skipped. The array is allocated with OS_MAKE and you can OS_FREE it any time.|
|''Function:'' |u32 RL_Map_Words(REBSER series)| |''Summary:'' |Given a block of word values, return an array of word ids.| |''Returns:'' |An array of global word identifiers (integers). The [0] value is the size.| |''Arguments:'' |series - block of words as values (from REBOL blocks, not strings.)| |''Notes: ''| Word identifiers are persistent, and you can use them anytime. The block can include any kind of word, including set-words, lit-words, etc. If the input block contains non-words, they will be skipped. The array is allocated with OS_MAKE and you can OS_FREE it any time.|
|''Function:'' |void RL_Print(REBYTE fmt, ...)| |''Summary:'' |Low level print of formatted data to the console.| |''Returns:'' | nothing| |''Arguments:'' |fmt - A format string similar but not identical to printf. Special options are available. ... - Values to be formatted.| |''Notes: ''|This function is low level and handles only a few C datatypes at this time.|
|''Function:'' |void RL_Print_TOS(REBCNT flags, REBYTE marker)| |''Summary:'' |Print top REBOL stack value to the console. (pending changes)| |''Returns:'' |Nothing| |''Arguments:'' |''flags'' - special flags (set to zero at this time). ''marker'' - placed at beginning of line to indicate output.| |''Notes: ''|This function is used for the main console evaluation input loop to print the results of evaluation from stack. The REBOL data stack is an abstract structure that can change between releases. This function allows the host to print the result of processed functions. Note that what is printed is actually TOS+1. Marker is usually "==" to show output. The system/options/result-types determine which values are automatically printed.|
|''Function:'' |void RL_Protect_GC(REBSER series, u32 flags)| |''Summary:'' |Protect memory from garbage collection.| |''Returns:'' |nothing| |''Arguments:'' |''series'' - a series to protect (block, string, image, ...) ''flags'' - set to 1 to protect, 0 to unprotect| |''Notes: ''|You should only use this function when absolutely necessary, because it bypasses garbage collection for the specified series. Meaning: if you protect a series, it will never be freed. Also, you only need this function if you allocate several series such as strings, blocks, images, etc. within the same command and you don't store those references somewhere where the GC can find them, such as in an existing block or object (variable).|
|''Function:'' |void RL_Reset()| |''Summary:'' |Reset REBOL (not implemented)| |''Returns:'' |nothing| |''Arguments:'' |none| |''Notes: ''|Intended to reset the REBOL interpreter.|
|''Function:'' |int RL_Series(REBSER series, REBCNT what)| |''Summary:'' |Get series information.| |''Returns:'' |Returns information related to a series.| |''Arguments:'' |''series'' - any series pointer (string or block) ''what'' - indicates what information to return (see RXI_SER enum)| |''Notes: ''|Invalid what arg nums will return zero.|
|''Function:'' |u32 RL_Set_Char(REBSER series, u32 index, u32 chr)| |''Summary:'' |Set a character into a byte or unicode string.| |''Returns:'' |The index passed as an argument.| |''Arguments:'' |''series'' - string series pointer. ''index'' - where to store the character. If past the tail, the string will be auto-expanded by one and the char will be appended.|
|''Function:'' |int RL_Set_Field(REBSER obj, u32 word, RXIARG val, int type)| |''Summary:'' |Set a field (context variable) of an object.| |''Returns:'' |The type arg, or zero if word not found in object or if field is protected.| |''Arguments:'' |''obj'' - object pointer (e.g. from RXA_OBJECT) ''word'' - global word identifier (integer) ''val'' - new value for field. ''type'' - datatype of value|
|''Function:'' |int RL_Set_Value(REBSER series, u32 index, RXIARG val, int type)| |''Summary:'' |Set a value in a block.| |''Returns:'' |TRUE if index past end and value was appended to tail of block.| |''Arguments:'' |''series'' - block series pointer. ''index'' - global word identifier (integer) ''val'' - new value for field. ''type'' - datatype of value|
|''Function:'' |int RL_Start(int reserved)| |''Summary:'' |Evaluate the default boot function.| |''Returns:'' |Zero on success, otherwise indicates an error occurred.| |''Arguments:'' |reserved - must be set to zero| |''Notes: ''|This function should be called after the host has added any custom code or extensions. Note that before this function is called, security and startup options have not been initialized. The primary content of the boot is in mezz-intrinsics.r in system/intrinsic/begin function.|
|''Function:'' |void RL_Version(REBYTE vers[])| |''Summary:'' |Obtain current REBOL interpreter version information.| |''Returns:'' |A byte array containing version, revision, update, and more.| |''Arguments:'' |vers - a byte array to hold the version info. First byte is length, followed by version, revision, update, system, variation.| |''Notes: ''|This function can be called before any other initialization to determine version compatiblity with the caller.|
|''Function:'' |REBYTE RL_Word_String(u32 word)| |''Summary:'' |Return a string related to a given global word identifier.| |''Returns:'' |A copy of the word string, null terminated.| |''Arguments:'' |word - a global word identifier| |''Notes: ''|The result is a null terminated copy of the name for your own use. The string is always UTF-8 encoded (chars > 127 are encoded.) In this API, word identifiers are always canonical. Therefore, the returned string may have different spelling/casing than expected. The string is allocated with OS_MAKE and you can OS_FREE it any time.|
|''Function:'' |u32 RL_Words_Of_Object(REBSER obj)| |''Summary:'' |Returns information about the object.| |''Returns:'' |Returns an array of words used as fields of the object.| |''Arguments:'' |obj - object pointer (e.g. from RXA_OBJECT)| |''Notes: ''|Returns a word array similar to MAP_WORDS(). The array is allocated with OS_MAKE. You can OS_FREE it any time.|
From a shell prompt, go to the directory that contains the REBOL executable file and type: ``` ./rebol ``` or, on Windows command console, just: ``` rebol ``` You can include a script file name: ``` rebol build-web.r ``` And special [[Scripts: program options|Concepts: Scripts: Program Options]] can be provided: ``` rebol -u ``` Some operating systems such as UNIX let you create alias shell commands that are able to run REBOL with a set of arguments and files.
The above technique is also useful for CGI scripts used on web servers. Here's an example CGI script: ``` #!/path/to/rebol -cs REBOL [Title: "Example CGI script"] print "Content-Type: text/html^/" print [<html><body><pre> system/options </pre></body></html>] ``` The -cs indicates CGI and disable security (allow file access outside the sandbox). When the web server runs this script, it will launch REBOL and provide the code that follows it as the script. Be sure to save the script with a file suffix (extension) that is supported by your web browser. (It may not support .r so you may need to use a .cgi suffix.) Also note that you can run this file directly from REBOL, because it ignores all lines prior to the REBOL header.
Usually, you can setup your favorite programming text editor to make code development go much quicker. Each text editor does this differently. For instance, in some editors, you will use the language compiler options. Specify the REBOL program rather than a compiler. Then you can press a single key that saves the script and evaluates it. See [[Guide: Basics: Editing scripts]] for more.
On systems that support it (like Windows): * Double-click the REBOL program icon, or * Drag a file (the script) onto the program icon. * Associate the file with the REBOL program. (Can be done by installing REBOL.) * Create a shortcut or alias icon with both the program and script file info. They also allow special scripts: [[Program options|Concepts: Scripts: Program Options]] to be specified.
In Linux, BSD, and similar systems, you can embed REBOL scripts in other types of script files. For example, if you created file list.r with these lines: ``` #!/path/to/rebol -s REBOL [Title: "Example script"] foreach file read %./ [print [file size? file]] ``` This works because REBOL ignores all text prior to its header object. Now, from your OS shell (but not in MS Windows default shell), make test.r executable: ``` chmod +x test.r ``` and you can run it with: ``` ./test.r ```
In the REBOL console, use do to run another script. For example: ``` do %build-site.r ``` Once that script has finished, it will return to the expression that follows it. If the script is in a different directory, REBOL will change to that directory while that script is run, and change back when done (if no errors occurred.)
Quite often you will use the save function to save values to a file that you will [[load|Functions: load]] and use later. To save some data: ``` data: [test 1234 4:25 <test> "test"] save %data.r data ``` The `data.r` file will be created, or if it exists, it will be overwritten. If you examine the file, you will find: ``` test 1234 4:25 <test> "test" ``` Which of course can be reloaded with [[load|Functions: load]] (as shown above): ``` data2: load %data.r probe data2 [test 1234 4:25 <test> "test"] ``` The [[save|Functions: save]] function contains many other options. (Click on its name to see the details.)
You can also save data to a web server, if it provides a method for accepting the data (such as a web CGI script). Here's an example: ``` data: [test 1234 4:25 <test> "test"] save http://www.rebol.com/cgi-bin/save-data.r data ``` The data is sent to the server. If you try this, you will notice that save returned a result. It is the response from the server. Because it's also in REBOL format, you can view it easily with the load function: ``` load save http://www.rebol.com/cgi-bin/save-data.r data [ok 28 bytes] ``` The `save-data.r` script on the server is confirming that it received 28 bytes of data. (The server does nothing else with the data.)
REBOL networking operates by using schemes to identify `handlers` that communicate with `protocols`. In REBOL a scheme is used to identify the method of accessing a resource. That method uses a code object that is called a handler. Each of the URL schemes that are supported by REBOL (such as HTTP, FTP) has a handler. The list of schemes can be obtained with: ``` probe next first system/schemes [default Finger Whois Daytime SMTP POP HTTP FTP NNTP] ``` In addition, there are lower level scheme names that are not shown here. For instance, the TCP and UDP schemes are used for direct, lower level communication. New schemes can be added to this list. For instance, you can define your own scheme, called FTP2, that provides special features for FTP access, such as automatically supplying your username and password so it does not need to be included in every FTP URL. Most handlers are used to provide an interface to a network protocol. A protocol is used to communicate between various devices, including clients and servers. Although each protocol is quite different in how it communicates, it does have some things in common with other protocols. For instance, most protocols require a network connection to be opened, read, written, and closed. These common operations are performed by a default handler in REBOL. This handler makes protocols like finger, whois, and daytime almost trivial to implement. Scheme handlers are written as objects. The default handler serves as the root object for all the other handlers. When a handler requires a particular field, such as a timeout value to use for reading data, if the value is not defined in the specific handler, it will be provided by the default handler. Hence, handlers overlay one another with their fields and value. You can also create handlers that use other handlers for default values. For instance, you can create an FTP2 handler that looks for missing fields first in the FTP handler, then in the default handler. When a port is used to access network resources, it is linked to a specific handler. The handler and the port together form the unit that is used to provide the data, code, and state information to process all protocols. The source code to handlers can be obtained from the system/scheme object. This can be useful if you want to modify the behavior of a handler or build your own handler. For instance, to view the code for the whois handler, type: ``` probe get in system/schemes 'whois ``` Note that what you are seeing is a composite of the default handler with the whois handler. The actual source code that is used to create the whois handler is only a few lines: ``` make Root-Protocol [ open-check: [[any [port/user ""]] none] net-utils/net-install Whois make self [] 43 ] ```
Everything on the command line that follows the script file name is passed to the script as its argument. This allows you to write scripts that accept arguments directly from the command line. For example, if you start REBOL with the line: ``` REBOL script.r 10:30 test@domain.dom ``` There are two ways to obtain the command line arguments. The first method returns the arguments as a block of REBOL values: ``` probe system/options/args ["10:30" "test@domain.dom"] ``` The second method returns the arguments as a string: ``` probe system/script/args "10:30 test@domain.dom" ``` <<< Version dependent note: Earlier versions of REBOL returned the block of values for the script/args field (similar to options/args). It is advised that you verify that your script receives the correct args datatype as shown above. <<<
Typically, you run REBOL with the file name of the script that you want it to evaluate. Only one script file is allowed. For example: ``` REBOL script.r ``` If the file name contains spaces, it must be provided in double quotes.
As we noted above, scripts are free form. However, to evaluate a script with do does require a REBOL header. !!! ''General form'' {{General form}} !!! ''An example script'' {{An example scriptcs: Editing scripts}}
The best way to name a file is to think about how you can best find that file in a few months. Short and clear names are often enough. Plurals should be avoided, unless meaningful. In addition, when naming a script, consider how the name will sort in a directory. For instance, keep related files together by starting them with a common word. ``` %net-start.r %net-stop.r %net-run.r ```
You can write REBOL code and data in just about any form you want. Here are some basics: |''Spacing'' |spacing is used to separate values and words, just like in English and other natural languages. You will need to keep this in mind. For example, a - b is not the same as a-b.| |''Indentation'' |can be whatever you want, but we suggest tab size of 4 spaces, or set your editor so actual tabs are 4 spaces.| |''Line-length'' |lines can be any length, but remember that not everyone has a wide screen. Good idea to keep them less than 100 chars wide.| |''Line-termination'' |any terminators will work (LF, CR, CR-LF) and REBOL can easily convert termination if you need it to do so. However, once loaded into memory, REBOL strings normally use just LF. That's our standard.| |''Brackets'' |are used for blocks (collections or lists of words and values). Normally, bracket's begin on the same line with their associated expression and end brackets line up with the beginning of that same expression.| |''Braces'' |are used for multiline strings. If you use braces, keep in mind that they include any indentation on the lines that follow. (See trim for an easy way to adjust them.)| Example of the above: ``` if now/time < 12:00 [ print "Good morning!" ] ``` Notice the spaces around the greater-than symbol, the "[" on the same line, and the 4 space indentation of the next line. Then the "]" appears on a separate line, indented to the same level as the if that it belongs to. For more, see the large example at the end of this page. We also recommend that you take a look at the style guide found in [[Scripts: Style guide section|Concepts: Scripts: Style Guide]].
The advantage of using headers is clear. Headers give users a summary of a script and allow other scripts to process the information (like a cataloging script). A minimum header provides a title, date, file name and purpose. Other fields can also be provided such as author, notes, usage, and needs. ``` REBOL [ Title: "Local Area Defringer" Date: 1-Jun-1957 File: %defringe.r Purpose: { Stabilize the wide area ignition transcriber using a double ganged defringing algorithm. } ] ```
In most cases REBOL requires that the script includes a REBOL header. This is a simple text signature at the top of the file that identifies the data as being REBOL code. The line above is an example header: ``` REBOL [Title: "Example script"] ``` The error message will be: ``` ** Syntax error: Script is missing a REBOL header. ``` See [[Scripts: headers|Concepts: Scripts: Headers]] for more information.
It appears that the above Quick Edit change also enables the scroll wheel. Of course, your results for the MS console may vary, depending on release, country, time of day, prior RAM contents, temperature of CPU, etc.
To replace values throughout a series, you can use the [[replace|Functions: replace]] function. This function searches for a specific value in a series, then replaces it with a new value. The [[replace|Functions: replace]] function takes three arguments: the series to search, value to replace, and the new value. ``` str: "hello world hello" probe replace str "hello" "aloha" "aloha world hello" ``` ``` data: [1 2 8 4 5] probe replace data 8 3 [1 2 3 4 5] ``` ``` probe replace data 4 `four [1 2 3 four 5] ``` ``` probe replace data integer! 0 [0 2 3 four 5] ``` Use the `/all` refinement to replace all occurrences of the value from the current position to the tail. ``` probe replace/all data integer! 0 [0 0 0 four 0] ``` ``` code: [print "hello" print "world"] replace/all code 'print 'probe probe code [probe "hello" probe "world"] ``` ``` do code helloworld ``` ``` str: "hello world hello" probe replace/all str "hello" "aloha" "aloha world aloha" ```
|''Function'' |''Description''|h |[[find|Functions: find]] |Finds a value in a series.| |[[select|Functions: select]] |Finds an associated value in a series.| |[[replace|Functions: replace]] |Searches and replaces values in a series.| |[[parse|Functions: parse]] |Parses values in a series.|
By default, security is set to prevent scripts from modifying any of your files or directories. * [[Port Security]] * [[Prior Security Settings]]
A useful variation of the [[find|Functions: find]] function is the [[select|Functions: select]] function, which returns the value following the one found. The [[select|Functions: select]] function is often used to lookup a value in tagged blocks of data. The [[select|Functions: select]] function takes the same arguments as `find`: the series to search and the value [[find|Functions: find]]. However, unlike find, which returns a series position, the [[select|Functions: select]] function returns the value that follows the match. ``` colors: [red green blue yellow orange] print select colors 'green blue ``` Given a simple database, the [[select|Functions: select]] function can be used to access its values: ``` email-book: [ "George" harrison@guru.org "Paul" lefty@bass.edu "Ringo" richard@starkey.dom "Robert" service@yukon.dom ] ``` The following code locates a specific email address: print select email-book "Paul" lefty@bass.edu Use the [[select|Functions: select]] function to find a block of expressions to evaluate. For example, given the following data: ``` cases: [ 10 [print "ten"] 20 [print "twenty"] 30 [print "thirty"] ] ``` a block can be evaluated based on a selector: ``` do select cases 10 ten ``` ``` do select cases 30 thirty ```
A word followed by a colon `: `is used to define or set its value: ``` age: 42 lunch-time: 12:32 birthday: 20-March-1990 town: "Dodge City" test: %stuff.r ``` You can set a word to be any type of value. In the previous examples, words are defined to be integer, time, date, string, and file values. You can also set words to be more complex types of values. For example, the following words are set to block and function values: ``` towns: ["Ukiah" "Willits" "Mendocino"] code: [if age > 32 [print town]] say: func [item] [print item] ``` <<< Why Words Are Set This Way In many langages words are set with an equal sign, such as: ``` age = 42 ``` In REBOL words are set with a colon. The reason for this is important. It makes the set operation on words into a single lexical value. The representation for the set operation is ''atomic''. The difference between the two approaches can be seen in this example. ``` print length? [age: 42] 2 ``` ``` print length? [age = 42] 3 ``` REBOL is a reflective language, it is able to manipulate its own code. This method of setting values allows you to write code that easily manipulates [[set-word!|Datatypes: Set-word!]] operations as a single unit. Of couse, the other reason is that the equal sign `=` is used as a comparision operator. <<< Multiple words can be set at one time by cascading the word definitions. For example, each of the following words are set to 42: ``` age: number: size: 42 ``` Words can also be set with the set function: ``` set 'time 10:30 ``` In this example, the line sets the word time! to 10:30. The word [[time!|Datatypes: Time!]] is written as a literal (using a single quote) so that it will not be evaluated. The set function can also set multiple words: ``` set [number num ten] 10 print [number num ten] 10 10 10 ``` In the above example, notice that the words do not need to be quoted because they are within a block, which is not evaluated. The [[print|Functions: print]] function shows that each word is set to the integer 10. If set is provided a block of values, each of the individual values are set to the words. In this example, one, two, and three are set to 1, 2, and 3: ``` set [one two three] [1 2 3] print three 3 ``` ``` print [one two three] 1 2 3 ``` See the `[bad-link:concepts/words.txt]` Section in the `[bad-link:concepts/.txt]` Values Appendix for more about setting words.
The simplest and most common use of [[find|Functions: find]] is to search a block or string for a value. In this case, [[find|Functions: find]] requires only two arguments: the series to search and the value to find. An example of using find on a block is: ``` colors: [red green blue yellow orange] where: find colors 'blue probe where [blue yellow orange] ``` ``` print first where blue ``` The [[find|Functions: find]] function can also search for values by datatype. This can be quite useful. ``` items: [10:30 20-Feb-2000 Cindy "United"] where: find items date! print first where 20-Feb-2000 ``` ``` where: find items string! print first where United ``` An example of using [[find|Functions: find]] on a string is: ``` colors: "red green blue yellow orange" where: find colors "blue" print where blue yellow orange ``` When a search fails, [[none!|Datatypes: None!]] is returned. ``` colors: [red green blue yellow orange] probe find colors 'indigo none ```
The simplest examples of [[sort|Functions: sort]] are: ``` names: [Eve Luke Zaphod Adam Matt Betty] probe sort names [Adam Betty Eve Luke Matt Zaphod] ``` ``` print sort [321.3 78 321 42 321.8 12 98] 12 42 78 98 321 321.3 321.8 ``` ``` print sort "plosabelm" abellmops ``` Notice that [[sort|Functions: sort]] is destructive to its argument series. It reorders the original data. To prevent this, use [[copy|Functions: copy]], as in the following example: ``` probe sort copy names ``` By default, sorting is case insensitive: ``` print sort ["Fred" "fred" "FRED"] Fred fred FRED ``` ``` print sort "G4C28f9I15Ed3bA076h" 0123456789AbCdEfGhI ``` Providing the `/case` refinement makes sorting case sensitive: ``` print sort/case "gCcAHfiEGeBIdbFaDh" ABCDEFGHIabcdefghi ``` ``` print sort/case ["Fred" "fred" "FRED"] FRED Fred fred ``` ``` print sort/case "g4Dc2BI8fCF9i15eAd3bGaE07H6h" 0123456789ABCDEFGHIabcdefghi ``` Many other datatypes can be sorted: ``` print sort [1.3.3.4 1.2.3.5 2.2.3.4 1.2.3.4] 1.2.3.4 1.2.3.5 1.3.3.4 2.2.3.4 ``` ``` print sort [$4.23 $23.45 $62.03 $23.23 $4.22] $4.22 $4.23 $23.23 $23.45 $62.03 ``` ``` print sort [11:11:43 4:12:53 4:14:53 11:11:42] 4:12:53 4:14:53 11:11:42 11:11:43 ``` ``` print sort [11-11-1999 10-11-9999 11-4-1999 11-11-1998] 11-Nov-1998 11-Apr-1999 11-Nov-1999 10-Nov-9999 ``` ``` print sort [john@doe.dom jane@doe.dom jack@jill.dom] jack@jill.dom jane@doe.dom john@doe.dom ``` ``` print sort [%user.r %rebol.r %history.r %notes.html] history.r notes.html rebol.r user.r ```
The previous examples move through the series one item at a time. However, there are times when you want to skip past multiple items using the [[skip|Functions: skip]] function. Assume that the colors variable is positioned at the head of a series: You can skip forward two items using: ``` colors: skip colors 2 ``` The [[skip|Functions: skip]] function is similar to [[next|Functions: next]] in that back returns the series at the new position. The following code confirms the new position: ``` print index? colors 3 ``` ``` print first colors blue ``` To move backward, use [[skip|Functions: skip]] with negative values: ``` colors: skip colors -1 ``` This is similar to [[back|Functions: back]]. In the above example, a skip of -1 moves back one item. ``` print first colors green ``` Note that you cannot skip past the tail or the head of a series. If you attempt to do so, [[skip|Functions: skip]] only goes as far as it can. It will not generate an error. If you skip too far forward, [[skip|Functions: skip]] returns the tail of the series: colors: skip colors 20 print tail? colors true If you skip too far back, [[skip|Functions: skip]] returns the head of the series: ``` colors: skip colors -100 print head? colors true ``` To skip directly to the head of the series, use the [[head|Functions: head]] function: ``` colors: head colors print head? colors true ``` ``` print first colors red ``` You can return to the tail with the [[tail|Functions: tail]] function: ``` colors: tail colors print tail? colors true ```
There are two ways to skip data that exists in a port. First, you can open the port with the `/skip `refinement. This [[open|Functions: open]] function will automatically skip to a point in the port. For example: ``` fp: open/direct/skip %file.big 1000000 fp: open/skip http://www.example.com/bigfile.dat 100000 ``` You can also use the [[skip|Functions: skip]] function on the port. For files that are opened with `/direct` and `/binary` the skip operation is identical to a file system seek operation. Data is not read into memory. This is not possible in `/string` mode because the line breaks interfere with the skip size. ``` fp: open/direct/binary %file.dat fp: skip fp 100000 ```
You can advance the input stream without an immediate match in these ways: |''skip'' |skip a value (or multiple if repeat given)| |''to'' |scan for a value or datatype, advance to the head of the value| |''thru'' |scan for a value or datatype, advance to the tail of the value| For ease-of-use, the to and thru actions also allow simple alternate match values. (However, this capability is not intended as a substitute for defining proper parse rules for more complex parse cases.)
The following example sends email with the simple mail transfer protocol (SMTP): ``` send luke@rebol.com "Use the force." ``` The next example sends the text of a file as an email: ``` send luke@rebol.com read %plan.txt ```
White-space is used in general for delimiting (for separating values). This is especially important because words may contain characters such as + and -. For example, this line is an expression consisting of 5 words: ``` a + b - c ``` , while this line is actually a single word a+b-c ``` a+b-c ``` Other special characters are |[ ] |mark the start and end of a block| |( ) |mark the start and end of a paren| |/ |used to "glue together" paths| |{ } |mark the start and end of a string| |" " |mark the start and end of a short string fitting into one line of text| |; |mark the start of a comment to the end of line|
For developers, there are a few special "Unix-like" functions that may be of help. |''ls'' |to list files. Also, ls dir works, and you can do ls/l, ls/f, ls/r, and combinations like ls/r/f, etc. HELP ls for info.| |''cd'' |to change current dir (or show the current dir if no arg)| |''pwd'' |to see current dir (or use CD with no args)| |''more'' |to view a file| |''rm'' |to delete a file|
!!!!! ''Allocation and GC'' REBOL uses automatic memory management, so REBOL and C code cannot be directly merged or referenced. In addition, if the C code allocates REBOL series such as a string, image, or block, that memory is "volatile" because without proper referencing, it can be targeted for garbage collection. !!!!! ''Struct Passing'' C structs and REBOL are not directly compatible. Therefore, it is the responsibility of the C extension code to deal with the conversion of values between the two domains. For example, a callback may need to return multiple values to REBOL. This can be done with a REBOL block or with an object. The allocation of the block or object can be passed in from REBOL, done in advance by the C command, or done dynamically within the callback, assuming that it has access to the R3 Extension Lib API. <<< Editor note: Add some notes about event handling... when it happens, etc. <<< !!!!!! ''Clips pending'' Some things to keep in mind: # Garbage collection can occur when evaluating the callback. If you created invalidating any REBOL series that may have been created exclusively in the C domain and not otherwise referenced from REBOL. It should be noted that good coding practices can prevent most of these problems. The arguments to the function are passed in a standard REBOL extension format, and the result is returned in that same format. Simple immediate values and series values with offsets can be passed and returned. More complex datatypes cannot be passed, and when required, must be handled with context references. The disadvantage of this method is that a programmer must be careful not to evaluate code that may conflict with the callback function.
A word can be written in several ways. Special notations can be used. We want to introduce these now, so you can start to recognize them in the examples that follow throughout this document. In essence, these notations modify the action or meaning related to the word. |''Notation'' |''Definition'' |''Notes''|h |`word` |Get the natural value of the word. |If the value is a function, evaluate it, otherwise return it.| |`word:` |Set the word to a value. |We do not use = for assignment!| |`:word` |Get the value of a word without evaluating it. |Useful for getting the value of a function.| |`'word` |Use the word as a symbol. |We treat it as is and do not evaluate it.| |`/word` |Use the word as a refinement symbol. |For functions, objects, file-paths, special fields.| Most of the time, you will use the first two, the natural notation and the set-word notation. But, the other notations are useful too, and you need to know them.
If your program requires one or more modules, you can specify them in your program's header block using the needs field. For example: ``` REBOL [ Title: "Super Web Site" Author: "John Adams" Needs: [mysql http-server] ] db: open-db %my-database.sql ... ``` When this file is loaded, the header is examined, the `mysql` and `http-server` modules are imported, then the main body of the program is evaluated. Once a module has been imported, all of it's exported functions and other values are available to be used by your code. In the example above, the `open-db` function is defined by the mysql module. !!!!! ''Types of module identifiers'' A few types of module identifiers are allowed, and are summarized in this table: |''Datatype'' |''What'' |''Action''|h |[[word!|Datatypes: Word!]] |module by name |search multiple locations for the module| |[[file!|Datatypes: File!]] |local file path of module |must be found at that location| |[[url!|Datatypes: Url!]] |Internet location of module |must be found at that location| !!!!! ''Searching for modules'' When the module name is a word, REBOL will search for the module in a few locations. Here's what happens: * The name is used to check the `system/modules` list to see if the module has already been loaded. If so, it will not be loaded again. * The module name is converted to a file name (with a .r suffix is added). * Local directories and Internet addresses are searched for the module. The order of the search is determined by the `system/options/module-paths` block. !!!!! ''Example'' Here is an example that uses all three types of module identifiers: ``` Needs: [ mysql %mods/database.r http://www.rebol.com/mods/http-server.r ] ``` In this example: * The `mysql` module can be found locally or remotely. * The `database.r` file must exist locally in the mods directory. * The `http-server.r` module must be at that web address. !!!!! ''Specifying a module version'' If your program requires specific module versions, they can be specified as well: ``` Needs: [ mysql 2.3.0 http-server 1.0.1 ] ``` For the `mysql` module a version of 2.3.0 or greater is required. For `http-server` the version must be 1.0.1 or greater. <<< Versions are tuples Version numbers are always [[tuple!|Datatypes: Tuple!]] datatypes so be sure to provide at least three parts of the version number, otherwise it's not a tuple, it's a [[decimal!|Datatypes: Decimal!]] number. <<< Also note that if a version number appears before any module name, it is assumed to be the REBOL system version. So: ``` Needs: [3.0.2 mysql 2.3.0 http-server 1.0.1] ``` indicates that the script needs REBOL 3.0.2. If the REBOL version is less, an error message will be displayed. !!!!! ''Validating modules with a hash checksum'' In addition to specifying a module name and version, you can also specify that modules be validated using a hash checksum. This is a type of integrity check. It is done to verify that the module contents have not been modified in any way (but, read the note below, because it's not perfect.) ``` Needs: [ mysql 1.2.3 #{A94A8FE5CCB19BA61C4C0873D391E987982FBBD3} http-server 1.0.1 #{8E67416A43298507CC22135E28233F4B9C27E75D} ] ``` Here the two modules will be located and read in to memory. The hash checksums will be computed for their source code (not including the header) and compared to the header. If they are the same, the load continues. If not, an error is displayed. <<< Super-secure applications REBOL uses the more secure SHA-1 hashing method rather than MD5. However, it must be noted that SHA-1 is not perfect. For applications that require maximal module integrity (nuclear submarines, power plants, automated cat food dispensers), you should download the modules files, manually validate them, then load them as local file modules, not from the Internet. See [[SHA Hashing|https://en.wikipedia.org/wiki/Secure_Hash_Algorithms]] for more information. <<<
REBOL provides two approaches for specifying network resources: URLs and port specifications. <<< Uniform Resource Locators (URL) are used on the Internet to identify a network resource, such as a Web page, FTP site, email address, file, or other resource or service. URLs are integral to the operation of REBOL, and they can be expressed directly in the language. <<< The standard notation for URLs consists of a scheme followed by a specification: ``` scheme:specification ``` The scheme is often the name of a protocol, such as HTTP, FTP, SMTP, and POP; however, that is not a requirement. A scheme can be any name that identifies the method used to access a resource. The format of a scheme's specification depends on the scheme; however, most schemes share a common format for identifying network hosts, user names, passwords, port numbers, and file paths. Here are a few commonly used formats: ``` scheme://host scheme://host:port scheme://user@host scheme://user:pass@host scheme://user:pass@host:port scheme://host/path scheme://host:port/path scheme://user@host/path scheme://user:pass@host/path scheme://user:pass@host:port/path ``` `[bad-link:concepts/network.txt]` Resource Specification lists the fields used in the above formats. |''scheme'' |The name used to identify the type of resource, often the same as the protocol. For example, HTTP, FTP, and POP.| |''host'' |The network name or address for a machine. For example, www.rebol.com, cnn.com, accounting.| |''port'' |Port number on the host machine for the scheme being used. Normally there is a default for this, so it is not required most of the time. Examples: 21, 23, 80, 8000.| |''user'' |A user name to access the resource.| |''pass'' |A password to verify the user name.| |''path'' |A file path or some other method for referencing the resource. This is scheme dependent. Some schemes include patterns and script arguments (such as CGI).| Another way to identify a resource is with a REBOL [[port!|Datatypes: Port!]] specification. In fact, when a URL is used, it is automatically converted into a port specification. A port specification can accept many more arguments than a URL, but it requires multiple lines to express. A port specification is written as an object block definition that provides each of the parameters necessary to access the network resource. For instance, the URL to access a Web site is: ``` read http://www.rebol.com/developer.html ``` but, it can also be written as: ``` read [ scheme: 'HTTP host: "www.rebol.com" target: %/developer.html ] ``` The URL for an FTP read can be: ``` read ftp://bill:vbs@ftp.example.com:8000/file.txt ``` but, it can also be written as: ``` read [ scheme: 'FTP host: "ftp.example.com" port-id: 8000 target: %/file.txt user: "bill" pass: "vbs" ] ``` In addition, there are many other port fields that can be specified, such as timeout, type of access, and security.
Program options are identifed with a plus `+` or minus `- `before a character or by a double dash `-- `before a word. This is a standard practice for specifying program options on most operating systems. Here are several examples of how options are used. To run a script with an option, such as the -s option, which evaluates the script with security turned off, type: ``` REBOL -s script.r ``` To obtain usage information about REBOL, type: ``` REBOL -? REBOL --help ``` To run REBOL without opening a new window (this is done when you need to redirect output to a file or server), type: ``` REBOL -w REBOL --nowindow ``` To prevent the printout of startup information which is useful if you are redirecting the output to a file or server, type: ``` REBOL -q REBOL --quiet ``` To evaluate a REBOL expression from the command line, type: ``` REBOL --do "print 1 + 2" REBOL --do "verbose: true" script.r ``` This lets you evaluate a remote script with a line such as: ``` REBOL --do "do http://www.rebol.com/speed.r" ``` To change the security level of REBOL, type: ``` REBOL -s script.r REBOL --secure none script.r ``` To use REBOL scripts for CGI (see the `[bad-link:concepts/cgi.txt]` - Common Gateway Interface Section of the `[bad-link:concepts/network.txt]` Protocols Chapter for more information), type: ``` REBOL -c cgi-script.r REBOL --cgi ``` Multiple options are also allowed. Multiple single character options can be included together. Multiple full word options must be separated with spaces. ``` REBOL -cs cgi-script.r REBOL --cgi --secure none cgi-script.r ``` The above example runs in CGI mode, with security turned off. The shorthand method is required for various web servers that restrict the number of arguments allowed on the command line (such as the Apache server on Linux).
When REBOL starts, it attempts to load the r`ebol.r` and `user.r` boot files. These files are optional, but when found, they can be used to set up networking, define common functions, and initialize data used by scripts. The rebol.r script file holds special functions or extensions to REBOL that are provided as part of the standard distribution. It is suggested that you do not edit this file as it is overwritten with each new release of REBOL. The `user.r` script file holds user preferences. You can edit this file and add whatever definitions or data you require. On multi-user systems, there can be a different `user.r` for every user. While the user.r file is not part of the distribution, it is automatically generated if it does not exist. When REBOL starts, it looks for the `rebol.r` and `user.r` files first in the home directory and, if not found there, then in the current directory. To set a HOME directory, you can set an environment variable in the appropriate login or startup script for your system. Note that some systems, such as UNIX or Linux may already do this, so you do not need to. For example, on Windows NT to set HOME you can add: ``` set HOME=C:\REBOL ``` to your environment by following these steps: # Choose `Settings` Control Panel in the Windows `Start` Menu, # Double-click the `System` icon, and select the `Environment` tab. # Type HOME in the variable field and `[bad-link:concepts/\rebol.txt]` (or the path to where you put the REBOL program) in the value field. On Unix systems, you can set the path to REBOL by adding a line like the following in your login shell script or profile: ``` set HOME=/usr/bin/rebol ``` For some versions of REBOL, the path is stored in a .rebol file that is located in your home directory.
As input is parsed, you can store parts of it into variables for use later within your productions: |''set'' |set the next value to a variable| |''copy'' |copy the next matched sequence to a variable|
!!!!! ''Checksum of characters'' Here's an extension that provides a function to compute a 64 bit checksum on a string chars. It works for both types of strings (Latin-1 and Unicode). The REBOL extension module definition: ``` REBOL [ Title: {String 64 bit checksum} Type: module Exports: [sum-chars] ] sum-chars: command [str [string!]] ``` The C code: ``` RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { switch (cmd) { case 0: { i32 idx, tail; i64 sum = 0; REBSER *ser; ser = RXA_SERIES(frm, 1); idx = RXA_INDEX(frm, 1); tail = RXI_SERIES_INFO(ser, RXI_INFO_TAIL); for (; idx < tail; idx++) { sum += RXI_GET_CHAR(ser, idx); } RXA_INT64(frm, 1) = sum; RXA_TYPE(frm, 1) = RXT_INTEGER; break; } // ...other command cases... default: return RXR_NO_COMMAND; } return RXR_VALUE; } ``` Test code: ``` probe sum-chars "testing" 766 ``` ``` probe sum-chars to-string read http://www.rebol.com 751827 ``` !!!!! ''Reverse a string'' Although REBOL provides the [[reverse|Functions: reverse]] function, here's a simple example that helps show how strings can be modified. The REBOL extension module definition: ``` REBOL [ Title: {String example} Type: module Exports: [reverse-str] ] reverse-str: command [str [string!]] ``` The C code: ``` RXIEXT int RX_Call(int cmd, RXIFRM *frm, REBCEC *ctx) { switch (cmd) { case 0: { u32 idx, tail, chr; REBSER *ser; ser = RXA_SERIES(frm, 1); idx = RXA_INDEX(frm, 1); tail = RXI_SERIES_INFO(ser, RXI_INFO_TAIL); if (tail > 0) tail--; for (; idx < tail; idx++, tail--) { chr = RXI_GET_CHAR(ser, idx); RXI_SET_CHAR(ser, idx, RXI_GET_CHAR(ser, tail)); RXI_SET_CHAR(ser, tail, chr); } break; // returns same string } default: return RXR_NO_COMMAND; } return RXR_VALUE; } ``` Test code: ``` probe reverse-str "" "" ``` ``` probe reverse-str "ab" "ba" ``` ``` probe reverse-str "abc" "cba" ``` ``` probe reverse-str "abcd" "dcba" ``` ``` probe head reverse-str next "ab" "ab" ``` ``` probe head reverse-str next "abc" "acb" ``` ``` probe head reverse-str next "abcd" "adcb" ```
!!!!! ''Trim'' The [[trim|Functions: trim]] function removes extra spaces from a string. The default operation of trim is to remove extra spaces from the head and tail of a string: ``` str: " line of text with spaces around it " print trim str line of text with spaces around it ``` Note that the string is modified in the process: ``` print str line of text with spaces around it ``` To trim a copy of the string, write: ``` print trim copy str line of text with spaces around it ``` Trim includes a number of refinements to specify where space is to be removed from a string: |`/head` |removes space from the head of the string| |`/tail` |removes space from the tail of the string| |`/auto` |removes space from each line, relative to the first line| |`/lines` |removes newlines, replacing them with spaces| |`/all` -- removes all whitespace :`/with` |removes all specified characters| Use the `/head` and `/tail` refinements to trim from either end of a string: ``` probe trim/head copy str line of text with spaces around it ``` ``` probe trim/tail copy str line of text with spaces around it ``` Use the `/auto` refinement to trim leading spaces from multiple lines leaving indented spaces intact: ``` str: { indent text indent text indent text indent text indent text } print str indent text indent text indent text indent text indent text ``` ``` probe trim/auto copy str {indent text indent text indent text indent text indent text } ``` Use `/lines` to trim the head and tail and also convert newlines into spaces: ``` probe trim/lines copy str ``` {indent text indent text indent text indent text indent text} Use `/all` to remove all whitespace: ``` probe trim/all copy str ``` indenttextindenttextindenttextindenttextindenttext The `/with` refinement will remove all characters that you specify. In the following example, spaces, line breaks and the characters e and t are removed: ``` probe trim/with copy str " ^/et" indnxindnxindnxindnxindnx ``` !!!!! ''Detab and Entab'' The [[detab|Functions: detab]] and [[entab|Functions: entab]] will convert tabs to spaces and spaces to tabs. ``` str: {^(tab)line one ^(tab)^(tab)line two ^(tab)^(tab)^(tab)line three ^(tab)line^(tab)full^(tab)of^(tab)tabs} ``` ``` print str line one line two line three line full of tabs ``` By default, the [[detab|Functions: detab]] function converts tabs to four spaces (the REBOL standard spacing). All tabs in the string will be converted to spaces, regardless of where they are located. ``` probe detab str { line one line two line three line full of tabs} ``` Note that the [[detab|Functions: detab]] and [[entab|Functions: entab]] functions affect the string that is provided as an argument. To change a copy of the source string, use the copy function. The [[entab|Functions: entab]] function converts spaces to tabs. Every four spaces will be converted to a single tab. Only spaces at the beginning of a line will be converted to tabs. ``` probe entab str {^-line one ^-^-line two ^-^-^-line three ^-line^-full^-of^-tabs} ``` You can use the `/size` refinement to specify the size of tabs. For instance, if you want to convert each tab to eight spaces, or convert every eight spaces to a tab, you can use this example: ``` probe detab/size str 8 { line one line two line three line full of tabs} ``` ``` probe entab/size str 8 {^-line one ^-^-line two ^-^-^-line three ^-line^-full^-of^-tabs} ```
|''String Type'' |''Description''|h |[[string!|Datatypes: String!]] |Character strings| |[[binary!|Datatypes: Binary!]] |Byte strings| |[[tag!|Datatypes: Tag!]] |HTML and XML tags| |[[file!|Datatypes: File!]] |File names| |[[url!|Datatypes: Url!]] |Internet uniform resource locators| |[[email!|Datatypes: Email!]] |Email names| |[[image!|Datatypes: Image!]] |Image data| |[[issue!|Datatypes: Issue!]] |Sequence codes|
Strings are written in a single-line format or a multiline format. Single-line format strings are enclosed in quotes. Multiline format strings are enclosed in braces. Strings that include quotes, tabs, or line breaks must be enclosed in braces using the multiline format. For example: ``` "Here is a single-line string" {Here is a multiline string that contains a "quoted" string.} ``` Special characters (escapes) within strings are indicated with the caret character `^`. `[bad-link:concepts/see.txt]` the string section in the Values Chapter for the table of escape sequences.
There are a few ways to load modules: |`needs` |is a block that you can put in your program header to specify the modules your program wants loaded to run.| |[[import|Functions: import]] |called in your code to load a module from a file, URL, or name.| |[[do|Functions: do]] |called in your code with a module file or URL.| |[[module|Functions: module]] |directly creates modules from blocks that contain a module definition.| |[[make|Functions: make]] |lower level module creation function. Takes a block that contains a module definition.|
|''RX_'' |the main functions of the DLL itself (not the API)| |''RL_'' |functions in the reb-lib (REBOL library)| |''RXT_'' |type (datatype) identifiers for command arguments| |''RXA_'' |command argument access macros| |''RXR_'' |command return codes|
These [[datatype actions|Datatypes: Action!]] are defined for the [[bitset!|Datatypes: Bitset!]] datatype: |''Action'' |''Description''|h |[[make|Functions: make]] |creates and returns a new bitset| |[[copy|Functions: copy]] |returns a copy of a bitset| |[[complement|Functions: complement]] |inverts each bit; returns a new bitset| |[[find|Functions: find]] |test that value is set| |[[append|Functions: append]] |add new bits to the set (set them to true)| |[[poke|Functions: poke]] |set one or more bits true or false| |[[remove|Functions: remove]] |remove specific bits from the bitset (requires /part refinement)| |[[clear|Functions: clear]] |clear entire bitset| |[[length?|Functions: length?]] |returns the number of bits used| |[[and|Functions: and]] |bitwise and of two bitsets; returns new bitset| |[[or|Functions: or]] |bitwise or of two bitsets; returns new bitset| |[[xor|Functions: xor]] |bitwise xor of two bitsets; returns new bitset| In addition, these actions are identical: |''Action'' |''Same as''|h |[[to|Functions: to]] |[[make|Functions: make]]| |[[insert|Functions: insert]] |[[append|Functions: append]]| |[[pick|Functions: pick]] |[[find|Functions: find]]| |[[negate|Functions: negate]] |[[complement|Functions: complement]]| These comparisons are supported: |''Action'' |''Description''|h |[[equal?|Functions: equal?]] |the bitsets are equal| |[[not-equal?|Functions: not-equal?]] |the bitsets are not equal| |[[same?|Functions: same?]] |the bitsets use the same memory storage| |[[tail?|Functions: tail?]] |provided to allow empty? to work for bitsets| |[[zero?|Functions: zero?]] |always returns false (because bitsets are not scalar values)|
The [[switch|Functions: switch]] function finds a matching value and evaluates its related block. The matched value can be of any datatype. Simple integers for example: ``` n: 22 switch n [ 11 [print "here"] 22 [print "there"] 33 [print "everywhere"] ] there ``` You can also tell [[switch|Functions: switch]] to evaluate a default block, if no values are matched: ``` n: 123 switch/default n [ 11 [print "here"] 22 [print "there"] 33 [print "everywhere"] ][ print "nowhere" ] nowhere ``` There are many uses for [[switch|Functions: switch]] as shown here: ``` name: "Sam" switch n [ "Bob" [print "here"] "Sam" [print "there"] "Ted" [print "everywhere"] ] there ``` ``` html-tag: <title> print switch html-tag [ <pre> ["preformatted text"] <title> ["page title"] <li> ["bulleted list item"] ] page title ``` ``` time: 12:30 switch time [ 8:00 [send wendy@domain.dom "Hey, get up"] 12:30 [send cindy@dom.dom "Join me for lunch."] 16:00 [send group@every.dom "Dinner anyone?"] ] ``` Note that the switch block is ''not evaluated'' so if it contains expressions, you will need to use reduce first: ``` n: 22 switch n reduce [ 11 [print "here"] 11 * 2 [print "there"] 11 * 3 [print "everywhere"] ] there ``` If you want to use [[switch|Functions: switch]] on datatypes, use this method: ``` n: 22 switch type?/word n [ integer! [print "integer"] decimal! [print "decimal"] time! [print "time" ] ``` See the [[type?|Functions: type?]] function for details. Also, like other functions, [[switch|Functions: switch]] returns the value of the block it has evaluated.
|''Value'' |''Summary'' |''Example''|h |[[integer!|Datatypes: Integer!]] |64 bit integers |`1234` `-432`| |[[decimal!|Datatypes: Decimal!]] |64 bit floating point |`3.1415` `1.23E12` `0,01 1,2E12`| |[[percent!|Datatypes: Percent!]] |64 bit decimal percent |`1%` `100%` `12.34%` `1234%`| |[[money! |Datatypes: Money!]]|arbitrary precision math |`$12.34` `USD$12.34` `CAD$123.45` `DEM$1234,56`| |[[time!|Datatypes: Time!]] |absolute and relative time |`12:34` `20:05:32` `-0:25.34`| |[[date!|Datatypes: Date!]] |date, time, zone |`20-Apr-1998` `20-4-1998` `20-Apr-1998/12:32 ; date and time` `20-Apr-1998/12:32-8:00 ; with timezone`| |[[tuple!|Datatypes: Tuple!]] |versions, colors, IP addresses |`3.1.5 ; version numbers` `255.255.0.100 ; RGBA colors` `199.4.80.7 ; Internet addresses`| |[[pair!|Datatypes: Pair!]] |coordinate pairs |`5x10` `100x100` `-50x-25`| |[[string!|Datatypes: String!]] |ASCII and Unicode strings |`"Here is a string"` `{Here is another way to write a string that spans many lines and contains "quoted" strings.}`| |[[binary!|Datatypes: Binary!]] |Encoded strings of bytes |`#{0A6B14728C4DBEF5} ; hex encoded` `64#{45kLKJOIU8439LKJklj} ; base-64 encoded`| |[[tag!|Datatypes: Tag!]] |General markup tags (HTML, XML, etc.) |`<title> </body> <font size="2" color="blue">`| |[[email!|Datatypes: Email!]] |email addresses |`info@rebol.com` `bill-smity@example.com`| |[[file!|Datatypes: File!]] |File names and directory paths| `%data.txt %images/photo.jpg` `%../scripts/*.r`| |[[url!|Datatypes: Url!]] |Uniform resource locators |`http://www.rebol.com` `ftp://ftp.rebol.com/sendmail.r` `mailto:info@rebol.com`| |[[issue!|Datatypes: Issue!]] |Identification and serial strings |`#707-467-8000 ; a phone number` `#0000-1234-5678-9999 ; a credit card number` `#MFG-932-741-A ; a model number`|
\define toc-heading(caption,body) <$reveal type="nomatch" state=<<qualify "$:/state/toc/$caption$">> text="show"> <$button set=<<qualify "$:/state/toc/$caption$">> setTo="show" class="tc-btn-invisible">{{$:/core/images/right-arrow}} $caption$ </$button> </$reveal> <$reveal type="match" state=<<qualify "$:/state/toc/$caption$">> text="show"> <$button set=<<qualify "$:/state/toc/$caption$">> setTo="hide" class="tc-btn-invisible">{{$:/core/images/down-arrow}} $caption$ </$button> </$reveal> <$reveal type="match" state=<<qualify "$:/state/toc/$caption$">> text="show" retain="yes" animate="yes"> $body$ </$reveal> \end <div class="tc-table-of-contents"> #<<toc-heading "guide" " ##[[Getting started|Guide: Basics: Getting started]] ###[[Download and test|Guide: Basics: Download and test]] ###[[Running scripts (programs)|Guide: Basics: Running scripts (programs)]] ###[[Editing scripts|Guide: Basics: Editing scripts]] ###[[Getting help and advice|Guide: Basics: Getting help and advice]] ##[[Writing code|Guide: Code: Writing code]] ###[[Basic syntax|Guide: Code: Basic syntax]] ###[[Evaluating blocks|Guide: Code: Evaluating blocks]] ###[[Words and variables|Guide: Code: Words and variables]] ###[[How code is evaluated|Guide: Code: How code is evaluated]] ###[[Conditional evaluation|Guide: Code: Conditional evaluation]] ###[[Repeated evaluation (loops)|Guide: Code: Repeated evaluation (loops)]] ###[[Defining functions|Guide: Code: Defining functions]] ###[[Debugging tips|Guide: Code: Debugging tips]] ##[[Handling data (section pending)|Guide: Data: Handling data (section pending)]] ###[[Datatypes|Guide: Data: Datatypes]] ###[[Blocks of data|Guide: Data: Blocks of data]] ###[[Manipulating strings|Guide: Data: Manipulating strings]] ###[[Objects provide context|Guide: Data: Objects provide context]] ###[[Saving and loading data|Guide: Data: Saving and loading data]] ##[[Using files|Guide: Files: Using files]] ###[[Reading and writing files|Guide: Files: Reading and writing files]] ###[[Loading and saving files|Guide: Files: Loading and saving files]] ###[[Directories and file information|Guide: Files: Directories and file information]] ##[[Network protocols|Guide: Network: Network protocols]] ">> #<<toc-heading "concepts" " ##[[Scripts|Concepts: Scripts]] ###[[File Suffix|Concepts: Scripts: File Suffix]] ###[[Structure|Concepts: Scripts: Structure]] ###[[Headers|Concepts: Scripts: Headers]] ###[[Script Arguments|Concepts: Scripts: Script Arguments]] ###[[Program Options|Concepts: Scripts: Program Options]] ###[[Running Scripts|Concepts: Scripts: Running Scripts]] ###[[Loading Scripts|Concepts: Scripts: Loading Scripts]] ###[[Saving Scripts|Concepts: Scripts: Saving Scripts]] ###[[Storing Data|Concepts: Scripts: Storing Data]] ###[[Comments|Concepts: Scripts: Comments]] ###[[Script Cleanup|Concepts: Scripts: Script Cleanup]] ###[[Style Guide|Concepts: Scripts: Style Guide]] ###[[Embedding Scripts|Concepts: Scripts: Embedding Scripts]] ##[[Expressions|Concepts: Expressions]] ###[[Blocks|Concepts: Expressions: Blocks]] ###[[Values|Concepts: Expressions: Values]] ###[[Evaluation|Concepts: Expressions: Evaluation]] ###[[Words|Concepts: Expressions: Words]] ###[[Conditionals|Concepts: Expressions: Conditional]] ###[[Loops|Concepts: Expressions: Loop]] ###[[Selection|Concepts: Expressions: Selection]] ###[[Stopping Evaluation|Concepts: Expressions: Stopping Evaluation]] ###[[Trying Blocks|Concepts: Expressions: Trying Blocks]] ##[[Series|Concepts: Series]] ###[[Traversing|Concepts: Series: Traversing]] ###[[Series Functions|Concepts: Series: Series Functions]] ###[[Series Datatypes|Concepts: Series: Series Datatypes]] ###[[Series Information|Concepts: Series: Series Information]] ###[[Making and Copying Series|Concepts: Series: Making and Copying Series]] ###[[Series Iteration|Concepts: Series: Series Iteration]] ###[[Searching Series|Concepts: Series: Searching Series]] ###[[Sorting Series|Concepts: Series: Sorting Series]] ###[[Series as Data Sets|Concepts: Series: Series as Data Sets]] ###[[Multiple Series Variables|Concepts: Series: Multiple Series Variables]] ###[[Modification Refinements|Concepts: Series: Modification Refinements]] ##[[Blocks|Concepts: Blocks]] ###[[Blocks of Blocks|Concepts: Blocks: Blocks of Blocks]] ###[[Paths for Nested Blocks|Concepts: Blocks: Paths for Nested Blocks]] ###[[Arrays|Concepts: Blocks: Arrays]] ###[[Composing Blocks|Concepts: Blocks: Composing Blocks]] ###[[String Functions|Concepts: Blocks: String Functions]] ###[[Converting Values to Strings|Concepts: Blocks: Converting Values to Strings]] ##[[Files|Concepts: Files]] ###[[Names and Paths|Concepts: Files: Names and Paths]] ###[[Reading Files|Concepts: Files: Reading Files]] ###[[Writing Files|Concepts: Files: Writing Files]] ###[[Line Conversion|Concepts: Files: Line Conversion]] ###[[Blocks of Lines|Concepts: Files: Blocks of Lines]] ###[[File and Directory Information|Concepts: Files: File and Directory Information]] ###[[Directories|Concepts: Files: Directories]] ##[[Functions|Concepts: Functions]] ###[[Evaluating Functions|Concepts: Functions: Evaluating Functions]] ###[[Defining Functions|Concepts: Functions: Defining Functions]] ###[[Nested Functions|Concepts: Functions: Nested Functions]] ###[[Unnamed Functions|Concepts: Functions: Unnamed Functions]] ###[[Conditional Functions|Concepts: Functions: Conditional Functions]] ###[[Function Attributes|Concepts: Functions: Function Attributes]] ###[[Forward References|Concepts: Functions: Forward References]] ###[[Scope of Variables|Concepts: Functions: Scope of Variables]] ###[[Online Function Help|Concepts: Functions: Online Function Help]] ###[[Reflective Properties|Concepts: Functions: Reflective Properties]] ###[[Viewing Source Code|Concepts: Functions: Viewing Source Code]] ##[[Math|Concepts: Math]] ###[[Scalar DataTypes|Concepts: Math: Scalar DataTypes]] ###[[Evaluation Order|Concepts: Math: Evaluation Order]] ###[[Standard Functions and Operators|Concepts: Math: Standard Functions and Operators]] ###[[Type Conversion|Concepts: Math: Type Conversion]] ###[[Comparison Functions|Concepts: Math: Comparison Functions]] ###[[Logarithmic Functions|Concepts: Math: Logarithmic Functions]] ###[[Trigonometric Functions|Concepts: Math: Trigonometric Functions]] ###[[Logic Functions|Concepts: Math: Logic Function]] ###[[Errors|Concepts: Math: Errors]] ##[[Objects|Concepts: Objects]] ###[[Making Objects|Concepts: Objects: Making Objects]] ###[[Cloning Objects|Concepts: Objects: Cloning Objects]] ###[[Accessing Objects|Concepts: Objects: Accessing Objects]] ###[[Object Functions|Concepts: Objects: Object Functions]] ###[[Prototype Objects|Concepts: Objects: Prototype Objects]] ###[[Referring to Self|Concepts: Objects: Referring to Self]] ###[[Encapsulation|Concepts: Objects: Encapsulation]] ###[[Reflective Properties|Concepts: Objects: Reflective Properties]] ##[[Modules|Concepts: Modules]] ###[[Loading Modules|Concepts: Modules: Loading Modules]] ###[[Defining Modules|Concepts: Modules: Defining Modules]] ###[[Special Notes|Concepts: Modules: Special Notes]] ##[[Extensions|Concepts: Extensions]] ###[[Using Extensions|Concepts: Extensions: Using Extensions]] ###[[Making Extensions|Concepts: Extensions: Making Extensions]] ###[[Host/Extension API|Concepts: Extensions: Host/Extension API]] ###[[Example extensions|Concepts: Extensions: Example extensions]] ###[[Embedded Extensions|Concepts: Extensions: Embedded Extensions]] ###[[Callback Functions|Concepts: Extensions: Callback Functions]] ##[[Graphics|Concepts: Graphics]] ##[[Graphical User Interface (GUI)|Concepts: Graphical User Interface (GUI)]] ###[[Main concepts and terms|Concepts: Gui: Main concepts and terms]] ##[[Ports|Concepts: Ports]] ###[[Opening a Port|Concepts: Ports: Opening a Port]] ###[[Closing a Port|Concepts: Ports: Closing a Port]] ###[[Reading from a Port|Concepts: Ports: Reading from a Port]] ###[[Writing to a Port|Concepts: Ports: Writing to a Port]] ###[[Updating a Port|Concepts: Ports: Updating a Port]] ###[[Waiting for a Port|Concepts: Ports: Waiting for a Port]] ###[[Other Port Modes|Concepts: Ports: Other Port Modes]] ###[[File Permissions|Concepts: Ports: File Permissions]] ###[[Directory Ports|Concepts: Ports: Directory Ports]] ##[[Protocols|Concepts: Protocols]] ###[[REBOL Networking Basics]] ###[[Initial Setup]] ##[[Parsing|Concepts: Parsing]] ###[[Parsing Blocks and Dialects|Concepts: Parsing: Parsing Blocks and Dialects]] ###[[Evaluation|Concepts: Parsing: Evaluation]] ###[[Match Types|Concepts: Parsing: Match Types]] ###[[Recursive Rules|Concepts: Parsing: Recursive Rules]] ###[[Grammar Rules|Concepts: Parsing: Grammar Rules]] ###[[Simple Splitting|Concepts: Parsing: Simple Splitting]] ###[[Skipping Input|Concepts: Parsing: Skipping Input]] ###[[Dealing with Spaces|Concepts: Parsing: Dealing with Spaces]] ###[[Summary of Parse Operations|Concepts: Parsing: Summary of Parse Operations]] ##[[Errors|Concepts: Errors]] ###[[Error Categories|Concepts: Errors: Error Categories]] ###[[Catching Errors|Concepts: Errors: Catching Errors]] ###[[Error Object|Concepts: Errors: Error Object]] ###[[Generating Errors|Concepts: Errors: Generating Errors]] ##[[Tour (older version)|Concepts: Tour (older version)]] ###[[Blocks|Concepts: Tour: Blocks]] ###[[Evaluation|Concepts: Tour: Evaluation]] ###[[Files|Concepts: Tour: Files]] ###[[Functions|Concepts: Tour: Functions]] ###[[Networking|Concepts: Tour: Networking]] ###[[Objects|Concepts: Tour: Objects]] ###[[Paths|Concepts: Tour: Paths]] ###[[Scripts|Concepts: Tour: Scripts]] ###[[Values|Concepts: Tour: Values]] ###[[Variables|Concepts: Tour: Variables]] ###[[Words|Concepts: Tour: Words]] ">> #<<toc-heading "datatypes" " ##[[action!|Datatypes: Action!]] ##[[binary!|Datatypes: Binary!]] ##[[bitset!|Datatypes: Bitset!]] ##[[block!|Datatypes: Block!]] ##[[char!|Datatypes: Char!]] ##[[closure!|Datatypes: Closure!]] ##[[command!|Datatypes: Command!]] ##[[datatype!|Datatypes: Datatype!]] ##[[date!|Datatypes: Date!]] ##[[decimal!|Datatypes: Decimal!]] ##[[email!|Datatypes: Email!]] ##[[end!|Datatypes: End!]] ##[[error!|Datatypes: Error!]] ##[[event!|Datatypes: Event!]] ##[[file!|Datatypes: File!]] ##[[frame!|Datatypes: Frame!]] ##[[function!|Datatypes: Function!]] ##[[get-path!|Datatypes: Get-path!]] ##[[get-word!|Datatypes: Get-word!]] ##[[gob!|Datatypes: Gob!]] ##[[handle!|Datatypes: Handle!]] ##[[hash!|Datatypes: Hash!]] ##[[image!|Datatypes: Image!]] ##[[integer!|Datatypes: Integer!]] ##[[issue!|Datatypes: Issue!]] ##[[library!|Datatypes: Library!]] ##[[list!|Datatypes: List!]] ##[[lit-path!|Datatypes: Lit-path!]] ##[[lit-word!|Datatypes: Lit-word!]] ##[[logic!|Datatypes: Logic!]] ##[[map!|Datatypes: Map!]] ##[[module!|Datatypes: Module!]] ##[[money!|Datatypes: Money!]] ##[[native!|Datatypes: Native!]] ##[[none!|Datatypes: None!]] ##[[object!|Datatypes: Object!]] ##[[op!|Datatypes: Op!]] ##[[pair!|Datatypes: Pair!]] ##[[paren!|Datatypes: Paren!]] ##[[path!|Datatypes: Path!]] ##[[percent!|Datatypes: Percent!]] ##[[port!|Datatypes: Port!]] ##[[rebcode!|Datatypes: Rebcode!]] ##[[refinement!|Datatypes: Refinement!]] ##[[routine!|Datatypes: Routine!]] ##[[set-path!|Datatypes: Set-path!]] ##[[set-word!|Datatypes: Set-word!]] ##[[string!|Datatypes: String!]] ##[[struct!|Datatypes: Struct!]] ##[[tag!|Datatypes: Tag!]] ##[[task!|Datatypes: Task!]] ##[[time!|Datatypes: Time!]] ##[[tuple!|Datatypes: Tuple!]] ##[[typeset!|Datatypes: Typeset!]] ##[[unset!|Datatypes: Unset!]] ##[[url!|Datatypes: Url!]] ##[[utype!|Datatypes: Utype!]] ##[[vector!|Datatypes: Vector!]] ##[[word!|Datatypes: Word!]] ">> #<<toc-heading "functions" " ##[[about|Functions: about]] ##[[abs|Functions: abs]] ##[[absolute|Functions: absolute]] ##[[action?|Functions: action?]] ##[[add|Functions: add]] ##[[ajoin|Functions: ajoin]] ##[[alias|Functions: alias]] ##[[all|Functions: all]] ##[[also|Functions: also]] ##[[alter|Functions: alter]] ##[[and|Functions: and]] ##[[and~|Functions: and~]] ##[[any-block?|Functions: any-block?]] ##[[any-function?|Functions: any-function?]] ##[[any-path?|Functions: any-path?]] ##[[any-string?|Functions: any-string?]] ##[[any-word?|Functions: any-word?]] ##[[any|Functions: any]] ##[[append|Functions: append]] ##[[apply|Functions: apply]] ##[[arccosine|Functions: arccosine]] ##[[arcsine|Functions: arcsine]] ##[[arctangent|Functions: arctangent]] ##[[array|Functions: array]] ##[[as-binary|Functions: as-binary]] ##[[as-pair|Functions: as-pair]] ##[[as-string|Functions: as-string]] ##[[ascii?|Functions: ascii?]] ##[[ask|Functions: ask]] ##[[assert|Functions: assert]] ##[[at|Functions: at]] ##[[attempt|Functions: attempt]] ##[[back|Functions: back]] ##[[binary?|Functions: binary?]] ##[[bind?|Functions: bind?]] ##[[bind|Functions: bind]] ##[[bitset?|Functions: bitset?]] ##[[block?|Functions: block?]] ##[[body-of|Functions: body-of]] ##[[break|Functions: break]] ##[[browse|Functions: browse]] ##[[bugs|Functions: bugs]] ##[[call|Functions: call]] ##[[caret-to-offset|Functions: caret-to-offset]] ##[[case|Functions: case]] ##[[catch|Functions: catch]] ##[[cause-error|Functions: cause-error]] ##[[cd|Functions: cd]] ##[[change-dir|Functions: change-dir]] ##[[change|Functions: change]] ##[[char?|Functions: char?]] ##[[charset|Functions: charset]] ##[[chat|Functions: chat]] ##[[checksum|Functions: checksum]] ##[[clean-path|Functions: clean-path]] ##[[clear|Functions: clear]] ##[[close|Functions: close]] ##[[closure?|Functions: closure?]] ##[[closure|Functions: closure]] ##[[collect|Functions: collect]] ##[[comment|Functions: comment]] ##[[complement|Functions: complement]] ##[[compose|Functions: compose]] ##[[compress|Functions: compress]] ##[[confirm|Functions: confirm]] ##[[construct|Functions: construct]] ##[[context|Functions: context]] ##[[continue|Functions: continue]] ##[[copy|Functions: copy]] ##[[cosine|Functions: cosine]] ##[[create|Functions: create]] ##[[cursor|Functions: cursor]] ##[[datatype?|Functions: datatype?]] ##[[date?|Functions: date?]] ##[[debase|Functions: debase]] ##[[decimal?|Functions: decimal?]] ##[[decloak|Functions: decloak]] ##[[decode-url|Functions: decode-url]] ##[[decode|Functions: decode]] ##[[decompress|Functions: decompress]] ##[[default|Functions: default]] ##[[dehex|Functions: dehex]] ##[[delect|Functions: delect]] ##[[delete|Functions: delete]] ##[[deline|Functions: deline]] ##[[delta-profile|Functions: delta-profile]] ##[[delta-time|Functions: delta-time]] ##[[demo|Functions: demo]] ##[[detab|Functions: detab]] ##[[difference|Functions: difference]] ##[[dir?|Functions: dir?]] ##[[dirize|Functions: dirize]] ##[[disarm|Functions: disarm]] ##[[divide|Functions: divide]] ##[[do-codec|Functions: do-codec]] ##[[do-commands|Functions: do-commands]] ##[[do-events|Functions: do-events]] ##[[do|Functions: do]] ##[[docs|Functions: docs]] ##[[does|Functions: does]] ##[[dp|Functions: dp]] ##[[draw|Functions: draw]] ##[[dt|Functions: dt]] ##[[dump-obj|Functions: dump-obj]] ##[[dump|Functions: dump]] ##[[echo|Functions: echo]] ##[[effect|Functions: effect]] ##[[eighth|Functions: eighth]] ##[[either|Functions: either]] ##[[else|Functions: else]] ##[[email?|Functions: email?]] ##[[empty?|Functions: empty?]] ##[[enbase|Functions: enbase]] ##[[encloak|Functions: encloak]] ##[[encode|Functions: encode]] ##[[enline|Functions: enline]] ##[[entab|Functions: entab]] ##[[equal?|Functions: equal?]] ##[[error?|Functions: error?]] ##[[eval|Functions: eval]] ##[[even?|Functions: even?]] ##[[event?|Functions: event?]] ##[[evoke|Functions: evoke]] ##[[exclude|Functions: exclude]] ##[[exists?|Functions: exists?]] ##[[exit|Functions: exit]] ##[[exp|Functions: exp]] ##[[extend|Functions: extend]] ##[[extract|Functions: extract]] ##[[fifth|Functions: fifth]] ##[[file?|Functions: file?]] ##[[find-module|Functions: find-module]] ##[[find-script|Functions: find-script]] ##[[find|Functions: find]] ##[[first+|Functions: first+]] ##[[first|Functions: first]] ##[[for|Functions: for]] ##[[forall|Functions: forall]] ##[[foreach|Functions: foreach]] ##[[forever|Functions: forever]] ##[[form|Functions: form]] ##[[format|Functions: format]] ##[[forskip|Functions: forskip]] ##[[found?|Functions: found?]] ##[[fourth|Functions: fourth]] ##[[frame?|Functions: frame?]] ##[[func|Functions: func]] ##[[funco|Functions: funco]] ##[[funct|Functions: funct]] ##[[function?|Functions: function?]] ##[[function|Functions: function]] ##[[functor|Functions: functor]] ##[[get-env|Functions: get-env]] ##[[get-path?|Functions: get-path?]] ##[[get-word?|Functions: get-word?]] ##[[get|Functions: get]] ##[[gob?|Functions: gob?]] ##[[greater-or-equal?|Functions: greater-or-equal?]] ##[[greater?|Functions: greater?]] ##[[halt|Functions: halt]] ##[[handle-events|Functions: handle-events]] ##[[handle?|Functions: handle?]] ##[[has|Functions: has]] ##[[head?|Functions: head?]] ##[[head|Functions: head]] ##[[help|Functions: help]] ##[[if|Functions: if]] ##[[image?|Functions: image?]] ##[[import|Functions: import]] ##[[in-dir|Functions: in-dir]] ##[[in|Functions: in]] ##[[index?|Functions: index?]] ##[[info?|Functions: info?]] ##[[input|Functions: input]] ##[[insert|Functions: insert]] ##[[install|Functions: install]] ##[[integer?|Functions: integer?]] ##[[intersect|Functions: intersect]] ##[[issue?|Functions: issue?]] ##[[join|Functions: join]] ##[[last|Functions: last]] ##[[latin1?|Functions: latin1?]] ##[[launch|Functions: launch]] ##[[layout|Functions: layout]] ##[[length?|Functions: length?]] ##[[lesser-or-equal?|Functions: lesser-or-equal?]] ##[[lesser?|Functions: lesser?]] ##[[library?|Functions: library?]] ##[[license|Functions: license]] ##[[list-dir|Functions: list-dir]] ##[[list-env|Functions: list-env]] ##[[lit-path?|Functions: lit-path?]] ##[[lit-word?|Functions: lit-word?]] ##[[load-gui|Functions: load-gui]] ##[[load|Functions: load]] ##[[log-10|Functions: log-10]] ##[[log-2|Functions: log-2]] ##[[log-e|Functions: log-e]] ##[[logic?|Functions: logic?]] ##[[loop|Functions: loop]] ##[[lowercase|Functions: lowercase]] ##[[ls|Functions: ls]] ##[[make-dir|Functions: make-dir]] ##[[make-scheme|Functions: make-scheme]] ##[[make|Functions: make]] ##[[map-each|Functions: map-each]] ##[[map-event|Functions: map-event]] ##[[map-gob-offset|Functions: map-gob-offset]] ##[[map?|Functions: map?]] ##[[map|Functions: map]] ##[[max|Functions: max]] ##[[maximum-of|Functions: maximum-of]] ##[[maximum|Functions: maximum]] ##[[min|Functions: min]] ##[[minimum-of|Functions: minimum-of]] ##[[minimum|Functions: minimum]] ##[[mkdir|Functions: mkdir]] ##[[mod|Functions: mod]] ##[[modified?|Functions: modified?]] ##[[module?|Functions: module?]] ##[[module|Functions: module]] ##[[modulo|Functions: modulo]] ##[[mold|Functions: mold]] ##[[money?|Functions: money?]] ##[[more|Functions: more]] ##[[move|Functions: move]] ##[[multiply|Functions: multiply]] ##[[native?|Functions: native?]] ##[[native|Functions: native]] ##[[negate|Functions: negate]] ##[[negative?|Functions: negative?]] ##[[new-line?|Functions: new-line?]] ##[[new-line|Functions: new-line]] ##[[next|Functions: next]] ##[[ninth|Functions: ninth]] ##[[none?|Functions: none?]] ##[[not-equal?|Functions: not-equal?]] ##[[not|Functions: not]] ##[[now|Functions: now]] ##[[number?|Functions: number?]] ##[[object?|Functions: object?]] ##[[object|Functions: object]] ##[[odd?|Functions: odd?]] ##[[offset?|Functions: offset?]] ##[[offset-to-caret|Functions: offset-to-caret]] ##[[op?|Functions: op?]] ##[[open?|Functions: open?]] ##[[open|Functions: open]] ##[[or|Functions: or]] ##[[or~|Functions: or~]] ##[[pair?|Functions: pair?]] ##[[paren?|Functions: paren?]] ##[[parse|Functions: parse]] ##[[past?|Functions: past?]] ##[[path?|Functions: path?]] ##[[percent?|Functions: percent?]] ##[[pick|Functions: pick]] ##[[poke|Functions: poke]] ##[[port?|Functions: port?]] ##[[positive?|Functions: positive?]] ##[[power|Functions: power]] ##[[prin|Functions: prin]] ##[[print|Functions: print]] ##[[printf|Functions: printf]] ##[[probe|Functions: probe]] ##[[protect|Functions: protect]] ##[[pwd|Functions: pwd]] ##[[q|Functions: q]] ##[[query|Functions: query]] ##[[quit|Functions: quit]] ##[[random|Functions: random]] ##[[read|Functions: read]] ##[[rebcode?|Functions: rebcode?]] ##[[recycle|Functions: recycle]] ##[[reduce|Functions: reduce]] ##[[refinement?|Functions: refinement?]] ##[[reflect|Functions: reflect]] ##[[reform|Functions: reform]] ##[[rejoin|Functions: rejoin]] ##[[remainder|Functions: remainder]] ##[[remold|Functions: remold]] ##[[remove-each|Functions: remove-each]] ##[[remove|Functions: remove]] ##[[rename|Functions: rename]] ##[[repeat|Functions: repeat]] ##[[repend|Functions: repend]] ##[[replace|Functions: replace]] ##[[request-file|Functions: request-file]] ##[[resolve|Functions: resolve]] ##[[return|Functions: return]] ##[[reverse|Functions: reverse]] ##[[reword|Functions: reword]] ##[[rm|Functions: rm]] ##[[round|Functions: round]] ##[[routine?|Functions: routine?]] ##[[run|Functions: run]] ##[[same?|Functions: same?]] ##[[save|Functions: save]] ##[[scalar?|Functions: scalar?]] ##[[script?|Functions: script?]] ##[[second|Functions: second]] ##[[secure|Functions: secure]] ##[[select|Functions: select]] ##[[series?|Functions: series?]] ##[[set-path?|Functions: set-path?]] ##[[set-word?|Functions: set-word?]] ##[[set|Functions: set]] ##[[seventh|Functions: seventh]] ##[[shift|Functions: shift]] ##[[show|Functions: show]] ##[[sign?|Functions: sign?]] ##[[sine|Functions: sine]] ##[[sixth|Functions: sixth]] ##[[size?|Functions: size?]] ##[[size-text|Functions: size-text]] ##[[skip|Functions: skip]] ##[[sort|Functions: sort]] ##[[source|Functions: source]] ##[[spec-of|Functions: spec-of]] ##[[split-path|Functions: split-path]] ##[[split|Functions: split]] ##[[square-root|Functions: square-root]] ##[[stack|Functions: stack]] ##[[stats|Functions: stats]] ##[[strict-equal?|Functions: strict-equal?]] ##[[strict-not-equal?|Functions: strict-not-equal?]] ##[[string?|Functions: string?]] ##[[struct?|Functions: struct?]] ##[[subtract|Functions: subtract]] ##[[suffix?|Functions: suffix?]] ##[[swap|Functions: swap]] ##[[switch|Functions: switch]] ##[[tag?|Functions: tag?]] ##[[tail?|Functions: tail?]] ##[[tail|Functions: tail]] ##[[take|Functions: take]] ##[[tangent|Functions: tangent]] ##[[task?|Functions: task?]] ##[[task|Functions: task]] ##[[tenth|Functions: tenth]] ##[[third|Functions: third]] ##[[throw|Functions: throw]] ##[[time?|Functions: time?]] ##[[title-of|Functions: title-of]] ##[[to-action|Functions: to-action]] ##[[to-binary|Functions: to-binary]] ##[[to-bitset|Functions: to-bitset]] ##[[to-block|Functions: to-block]] ##[[to-char|Functions: to-char]] ##[[to-closure|Functions: to-closure]] ##[[to-datatype|Functions: to-datatype]] ##[[to-date|Functions: to-date]] ##[[to-decimal|Functions: to-decimal]] ##[[to-email|Functions: to-email]] ##[[to-end|Functions: to-end]] ##[[to-error|Functions: to-error]] ##[[to-event|Functions: to-event]] ##[[to-file|Functions: to-file]] ##[[to-frame|Functions: to-frame]] ##[[to-function|Functions: to-function]] ##[[to-get-path|Functions: to-get-path]] ##[[to-get-word|Functions: to-get-word]] ##[[to-gob|Functions: to-gob]] ##[[to-handle|Functions: to-handle]] ##[[to-hex|Functions: to-hex]] ##[[to-image|Functions: to-image]] ##[[to-integer|Functions: to-integer]] ##[[to-issue|Functions: to-issue]] ##[[to-library|Functions: to-library]] ##[[to-lit-path|Functions: to-lit-path]] ##[[to-lit-word|Functions: to-lit-word]] ##[[to-local-file|Functions: to-local-file]] ##[[to-logic|Functions: to-logic]] ##[[to-map|Functions: to-map]] ##[[to-module|Functions: to-module]] ##[[to-money|Functions: to-money]] ##[[to-native|Functions: to-native]] ##[[to-none|Functions: to-none]] ##[[to-object|Functions: to-object]] ##[[to-op|Functions: to-op]] ##[[to-pair|Functions: to-pair]] ##[[to-paren|Functions: to-paren]] ##[[to-path|Functions: to-path]] ##[[to-percent|Functions: to-percent]] ##[[to-port|Functions: to-port]] ##[[to-rebcode|Functions: to-rebcode]] ##[[to-rebol-file|Functions: to-rebol-file]] ##[[to-refinement|Functions: to-refinement]] ##[[to-relative-file|Functions: to-relative-file]] ##[[to-routine|Functions: to-routine]] ##[[to-set-path|Functions: to-set-path]] ##[[to-set-word|Functions: to-set-word]] ##[[to-string|Functions: to-string]] ##[[to-struct|Functions: to-struct]] ##[[to-tag|Functions: to-tag]] ##[[to-task|Functions: to-task]] ##[[to-time|Functions: to-time]] ##[[to-tuple|Functions: to-tuple]] ##[[to-typeset|Functions: to-typeset]] ##[[to-unset|Functions: to-unset]] ##[[to-url|Functions: to-url]] ##[[to-utype|Functions: to-utype]] ##[[to-vector|Functions: to-vector]] ##[[to-word|Functions: to-word]] ##[[to|Functions: to]] ##[[trace|Functions: trace]] ##[[transcode|Functions: transcode]] ##[[trim|Functions: trim]] ##[[true?|Functions: true?]] ##[[try|Functions: try]] ##[[tuple?|Functions: tuple?]] ##[[type?|Functions: type?]] ##[[types-of|Functions: types-of]] ##[[typeset?|Functions: typeset?]] ##[[unhandle-events|Functions: unhandle-events]] ##[[union|Functions: union]] ##[[unique|Functions: unique]] ##[[unless|Functions: unless]] ##[[unprotect|Functions: unprotect]] ##[[unset?|Functions: unset?]] ##[[unset|Functions: unset]] ##[[until|Functions: until]] ##[[unview|Functions: unview]] ##[[update|Functions: update]] ##[[upgrade|Functions: upgrade]] ##[[uppercase|Functions: uppercase]] ##[[url?|Functions: url?]] ##[[usage|Functions: usage]] ##[[use|Functions: use]] ##[[utf?|Functions: utf?]] ##[[utype?|Functions: utype?]] ##[[value?|Functions: value?]] ##[[values-of|Functions: values-of]] ##[[vector?|Functions: vector?]] ##[[view|Functions: view]] ##[[wait|Functions: wait]] ##[[wake-up|Functions: wake-up]] ##[[what-dir|Functions: what-dir]] ##[[what|Functions: what]] ##[[while|Functions: while]] ##[[why?|Functions: why?]] ##[[word?|Functions: word?]] ##[[words-of|Functions: words-of]] ##[[write|Functions: write]] ##[[xor|Functions: xor]] ##[[xor~|Functions: xor~]] ##[[--|Functions: --]] ##[[-|Functions: -]] ##[[//|Functions: //]] ##[[/|Functions: /]] ##[[==|Functions: ==]] ##[[=?|Functions: =?]] ##[[=|Functions: =]] ##[[!==|Functions: !==]] ##[[!=|Functions: !=]] ##[[!|Functions: !]] ##[[<=|Functions: <=]] ##[[<>|Functions: <>]] ##[[<|Functions: <]] ##[[>=|Functions: >=]] ##[[>|Functions: >]] ##[[**|Functions: **]] ##[[*|Functions: *]] ##[[++|Functions: ++]] ##[[+|Functions: +]] ##[[??|Functions: ??]] ##[[?|Functions: ?]] ##[[zero?|Functions: zero?]] ">> #<<toc-heading "errors" " ##[[syntax errors|Errors: Syntax errors]] ###[[bad-char|Errors: bad-char]] ###[[header|Errors: header]] ###[[invalid|Errors: invalid]] ###[[malconstruct|Errors: malconstruct]] ###[[missing|Errors: missing]] ###[[needs|Errors: syntax-needs]] ###[[no-header|Errors: no-header]] ##[[note|Errors: Note]] ###[[deprecated (undoc)|Errors: deprecated (undoc)]] ###[[else-gone (undoc)|Errors: else-gone (undoc)]] ###[[exited (undoc)|Errors: exited (undoc)]] ###[[no-load (undoc)|Errors: no-load (undoc)]] ##[[script errors|Errors: Script errors]] ###[[already-used|Errors: already-used]] ###[[assert-failed|Errors: assert-failed]] ###[[bad-bad|Errors: bad-bad]] ###[[bad-command (undoc)|Errors: bad-command (undoc)]] ###[[bad-decode (undoc)|Errors: bad-decode (undoc)]] ###[[bad-field-set (undoc)|Errors: bad-field-set (undoc)]] ###[[bad-func-arg (undoc)|Errors: bad-func-arg (undoc)]] ###[[bad-func-def (undoc)|Errors: bad-func-def (undoc)]] ###[[bad-make-arg (undoc)|Errors: bad-make-arg (undoc)]] ###[[bad-path-set (undoc)|Errors: bad-path-set (undoc)]] ###[[bad-path-type (undoc)|Errors: bad-path-type (undoc)]] ###[[bad-port-action|Errors: bad-port-action]] ###[[bad-press|Errors: bad-press]] ###[[bad-refine (undoc)|Errors: bad-refine (undoc)]] ###[[bad-refines (undoc)|Errors: bad-refines (undoc)]] ###[[block-lines (undoc)|Errors: block-lines (undoc)]] ###[[cannot-use|Errors: cannot-use]] ###[[dialect (undoc)|Errors: dialect (undoc)]] ###[[dup-vars|Errors: dup-vars]] ###[[expect-arg|Errors: expect-arg]] ###[[expect-set|Errors: expect-set]] ###[[expect-type (undoc)|Errors: expect-type (undoc)]] ###[[expect-val (undoc)|Errors: expect-val (undoc)]] ###[[hidden (undoc)|Errors: hidden (undoc)]] ###[[invalid-arg|Errors: invalid-arg]] ###[[invalid-chars (undoc)|Errors: invalid-chars (undoc)]] ###[[invalid-compare (undoc)|Errors: invalid-compare (undoc)]] ###[[invalid-data (undoc)|Errors: invalid-data (undoc)]] ###[[invalid-op|Errors: invalid-op]] ###[[invalid-part (undoc)|Errors: invalid-part (undoc)]] ###[[invalid-path|Errors: script-invalid-path]] ###[[invalid-type (undoc)|Errors: invalid-type (undoc)]] ###[[locked-word|Errors: locked-word]] ###[[missing-arg (undoc)|Errors: missing-arg (undoc)]] ###[[need-value|Errors: need-value]] ###[[needs|Errors: script-needs]] ###[[no-arg|Errors: no-arg]] ###[[no-memory|Errors: no-memory]] ###[[no-op-arg|Errors: no-op-arg]] ###[[no-refine|Errors: no-refine]] ###[[no-return|Errors: no-return]] ###[[no-value|Errors: no-value]] ###[[not-defined|Errors: not-defined]] ###[[not-in-context (undoc)|Errors: not-in-context (undoc)]] ###[[not-related (undoc)|Errors: not-related (undoc)]] ###[[not-same-type (undoc)|Errors: not-same-type (undoc)]] ###[[out-of-range|Errors: out-of-range]] ###[[parse-command (undoc)|Errors: parse-command (undoc)]] ###[[parse-end (undoc)|Errors: parse-end (undoc)]] ###[[parse-rule (undoc)|Errors: parse-rule (undoc)]] ###[[parse-series (undoc)|Errors: parse-series (undoc)]] ###[[parse-variable (undoc)|Errors: parse-variable (undoc)]] ###[[past-end|Errors: past-end]] ###[[protected (undoc)|Errors: protected (undoc)]] ###[[set-self (undoc)|Errors: set-self (undoc)]] ###[[size-limit (undoc)|Errors: size-limit (undoc)]] ###[[too-long (undoc)|Errors: too-long (undoc)]] ###[[too-short (undoc)|Errors: too-short (undoc)]] ###[[type-limit (undoc)|Errors: type-limit (undoc)]] ###[[type (undoc)|Errors: script-type (undoc)]] ###[[wrong-denom|Errors: wrong-denom]] ###[[wrong-type (undoc)|Errors: wrong-type (undoc)]] ###[[overflow (undoc)|Errors: overflow (undoc)]] ###[[positive (undoc)|Errors: positive (undoc)]] ###[[type (undoc)|Errors: math-type (undoc)]] ###[[zero-divide (undoc)|Errors: zero-divide (undoc)]] ###[[already-closed|Errors: already-closed]] ###[[already-open|Errors: already-open]] ###[[bad-extension (undoc)|Errors: bad-extension (undoc)]] ###[[bad-file-mode (undoc)|Errors: bad-file-mode (undoc)]] ###[[bad-file-path (undoc)|Errors: bad-file-path (undoc)]] ###[[bad-media (undoc)|Errors: bad-media (undoc)]] ###[[call-fail (undoc)|Errors: call-fail (undoc)]] ###[[cannot-open|Errors: cannot-open]] ###[[extension-init (undoc)|Errors: extension-init (undoc)]] ###[[invalid-actor (undoc)|Errors: invalid-actor (undoc)]] ###[[invalid-check (undoc)|Errors: invalid-check (undoc)]] ###[[invalid-path|Errors: access-invalid-path]] ###[[invalid-port (undoc)|Errors: invalid-port (undoc)]] ###[[invalid-spec|Errors: invalid-spec]] ###[[new-level|Errors: new-level]] ###[[no-buffer (undoc)|Errors: no-buffer (undoc)]] ###[[no-codec (undoc)|Errors: no-codec (undoc)]] ###[[no-connect|Errors: no-connect]] ###[[no-create (undoc)|Errors: no-create (undoc)]] ###[[no-delete|Errors: no-delete]] ###[[no-extension (undoc)|Errors: no-extension (undoc)]] ###[[no-make-dir|Errors: no-make-dir]] ###[[no-port-action (undoc)|Errors: no-port-action (undoc)]] ###[[no-rename|Errors: no-rename]] ###[[no-scheme-name (undoc)|Errors: no-scheme-name (undoc)]] ###[[no-scheme (undoc)|Errors: no-scheme (undoc)]] ###[[not-connected (undoc)|Errors: not-connected (undoc)]] ###[[not-open|Errors: not-open]] ###[[protocol (undoc)|Errors: protocol (undoc)]] ###[[read-error (undoc)|Errors: read-error (undoc)]] ###[[read-only (undoc)|Errors: read-only (undoc)]] ###[[security-error (undoc)|Errors: security-error (undoc)]] ###[[security-level (undoc)|Errors: security-level (undoc)]] ###[[security|Errors: security]] ###[[socket-open|Errors: socket-open]] ###[[timeout|Errors: timeout]] ###[[type (undoc)|Errors: access-type (undoc)]] ###[[write-error (undoc)|Errors: write-error (undoc)]] ###[[bad-intrinsic (undoc)|Errors: bad-intrinsic (undoc)]] ###[[bad-path|Errors: bad-path]] ###[[bad-series (undoc)|Errors: bad-series (undoc)]] ###[[feature-na (undoc)|Errors: feature-na (undoc)]] ###[[globals-full|Errors: globals-full]] ###[[limit-hit (undoc)|Errors: limit-hit (undoc)]] ###[[max-natives (undoc)|Errors: max-natives (undoc)]] ###[[no-memory (undoc)|Errors: no-memory (undoc)]] ###[[not-done (undoc)|Errors: not-done (undoc)]] ###[[not-here|Errors: not-here]] ###[[stack-overflow|Errors: stack-overflow]] ###[[type (undoc)|Errors: internal-type (undoc)]] ">> #<<toc-heading "usage" " ##[[using rebol|Usage: Using REBOL]] ###[[installing rebol|Usage: Installing REBOL]] ###[[starting rebol|Usage: Starting REBOL]] ###[[quitting rebol|Usage: Quitting REBOL]] ###[[getting help|Usage: Getting help]] ###[[upgrading|Usage: Upgrading]] ###[[using the console|Usage: Using the console]] ###[[errors|Usage: Errors]] ##[[the command console|Usage: The command console]] ###[[advanced console operations|Usage: Advanced Console Operations]] ###[[busy indicator|Usage: Busy Indicator]] ###[[history recall|Usage: History Recall]] ###[[command prompt|Usage: Command Prompt]] ###[[result indicator|Usage: Result Indicator]] ">> </div> * http://www.rebol.com/r3/docs/toc.html * http://www.rebol.com/docs/docs.html * http://www.rebol.com/r3/docs/concepts/host-kit.html * http://www.rebol.net * http://rebol.org * http://ru.rebol.wikia.com/wiki/REBOLution_in_RUSSIA
Tags are useful for markup languages such as XML and HTML. Tags are enclosed in angle brackets For example: ``` <title> </body> <font size="2" color="blue"> ```
The [[find|Functions: find]] function returns the position in the series where an item was found. The `/tail` refinement returns the position immediately following the item that was found. Here's an example: ``` filename: %script.txt print find filename "." .txt ``` ``` print find/tail filename "." txt ``` ``` clear change find/tail filename "." "r" print filename script.r ``` In this example, clear is necessary to remove `xt`, which follows `t`.
Direct connections with TCP/IP are also possible in REBOL. The following example is a simple, but useful, server that waits for connections on a port, then executes whatever has been sent: ``` server-port: open/lines tcp://:9999 forever [ connection-port: first server-port until [ wait connection-port error? try [do first connection-port] ] close connection-port ] ```
If a script is to be followed by other text unrelated to the script itself, the script must be enclosed with square brackets `[ ]`: ``` Here is some text before the script. [ REBOL [ Title: "Embedded Example" Date: 8-Nov-1997 ] print "done" ] Here is some text after the script. ``` Only white space is permitted between the initial bracket and the word REBOL.
Script text does not need to begin with a header. Scripts can begin with any text, allowing them to be inserted into email messages, web pages, and other files. The header marks the beginning of the script, and the text that follows is the body of the script. Text that appears before the header is called the preface and is ignored during evaluation. ``` The text that appears before the header is ignored by REBOL and can be used for comments, email headers, HTML tags, etc. REBOL [ Title: "Preface Example" Date: 8-Jul-1999 ] print "This file has a preface before the header" ```
The ?? function will print the variable name, followed by its value. ``` a: 10 ?? a a: 10 ``` In addition, it also returns the result, so it can be inserted inline with code: ``` b: 20 c: a + ?? b b: 20 ``` If a block is provided as the argument, then each variable and value will be shown: ``` ?? [a b] a: 10 b: 20 ```
Any of the loops can be stopped at any time by evaluating the break function from within the evaluation block. See the `[bad-link:concepts/expressions.txt]` Chapter for more information about the [[break|Functions: break]] function.
We typically append a .r suffix to script file names: ``` filter.r user-actions.r data-file.r ``` However, this convention is not mandatory. Any file suffix is valid: ``` add-files.txt user-data.rdb build-site.xyz ``` As mentioned earlier a script can refer to: * sources stored as REBOL files * sources embedded in other types of files (like web pages) * sources passed in messages between systems * fragments of source text, such as examples in a document So the REBOL interpreter will read any file and will scan its contents for a valid REBOL [[scripts: headers|Concepts: Scripts: Headers]]. If found, then the code (or data) that follows it will be processed as REBOL source.
Time is written in hours and minutes with optional seconds, each separated by colons. For example: ``` 12:34 20:05:32 0:25.345 0:25,345 ``` Seconds can include a decimal sub-second. Times can also include AM and PM appended without intervening spaces: ``` 12:35PM 9:15AM ```
If you really need to know what's going on, you can use [[trace|Functions: trace]]. <<< Use secure [debug allow] to allow security for debug (used in trace), or type secure help for more information. <<< You can specify a number of levels to trace ``` trace 3 ; only trace top three levels ``` or you can trace everything: ``` trace on ``` To disable trace ``` trace off ``` The output of trace is very detailed. Tracing: ``` print 123 1: print : native! [value] 2: 123 --> print 123 <-- print => unset! ``` The ==> indicates entry into a function, and <== is the return, with the return value following it.
GOBs support two levels of transparency. # Images or colors may specify transparency. For example, an image with transparent rounded edges. # The transparency of a GOB can be controlled with /alpha. This setting affects the entire GOB (and all subGOBs within it). The range is 0 to 255. An example of setting the transparency of a GOB: ``` gob/alpha: 200 ``` <<< Note on speed optimization: if an image or color is found not to be transparent, and the `/alpha` field fully opaque, the compositing system will optimize the action (using a non-transparent blit). The speed difference is significantly faster, but should only matter in special cases, such as when moving or updating large areas of a window (e.g. playing a large animation or video, where alpha is not so important.) <<<
Since a series is an ordered set of values, you can traverse it from one position to another. As an example, take a series of three colors defined by the following block: ``` colors: [red green blue] ``` There is nothing special about this block. It is a series containing three words. It has a set of values: red, green, and blue. The values are organized into a specific order: red is first, green is second, and blue is third. The first position of the block is called its head. This is the position occupied by the word red. The last position of the block is called its tail. This is the position immediately after the last word in the block. If you were to draw a diagram of the block, it would look like this: Notice that the tail is just past the end of the block. The importance of this will become more clear shortly. The variable `colors` is used to refer to the block. It is currently set to the head of the block: ``` print head? colors true ``` The `colors` variable is at the first index position of the block. ``` print index? colors 1 ``` The block has a length of three: ``` print length? colors 3 ``` The first item in the block is: ``` print first colors red ``` The second item in the block is: ``` print second colors green ``` You can reposition the `colors` variable in the block using various functions. To move the `colors` variable to the next position in the colors block, use the next function: ``` colors: next colors ``` The next function moves forward one value in the block and returns that position as a result. The colors variable is now set to that new position: The position of the colors variable has changed. Now the variable is no longer at the head of the block: ``` print head? colors false ``` It is at the second position in the block: ``` print index? colors 2 ``` However, if you obtain the first item of colors, you get: ``` print first colors green ``` The position of the value that is returned by the [[first|Functions: first]] function is relative to the position that `colors` has in the block. The returned value is not the first color in the block, but the first color immediately following the current position of the block. Similarly, if you ask for the length or the second color, you find that these are relative as well: ``` print length? Colors 2 ``` ``` print second colors blue ``` You could move to the next position, and get a similar set of results: ``` colors: next colors print index? colors 3 ``` ``` print first colors blue ``` ``` print length? colors 1 ``` The block diagram now looks like this: The colors variable is now at the last color in the block, but it is not yet to the tail position. ``` print tail? colors false ``` To reach the tail, it has to be moved to the next position: colors: next colors Now the `colors` variable is resting at the tail of the block. It is no longer positioned at a valid color. It is past the end of the block. If you try your code, you will get: ``` print tail? colors true ``` ``` print index? colors 4 ``` ``` print length? Colors 0 ``` ``` print first colors ** Script Error: Out of range or past end. ** Where: print first colors ``` You receive an error in this last case because there is no valid first item when you are past the end of the block. It is also possible to move backwards in the block. If you write: ``` colors: back colors ``` you will move the `colors` variable back one position in the series: All of the same code will work as before: ``` print index? colors 3 ``` ``` print first colors blue ```
Once you've downloaded the program, check that it works on your system: |''On Windows'': |Double click on the icon you just downloaded. The REBOL console will open.| |''On others'': |Run the program from the shell prompt. (Many systems require` ./name` syntax for local files.)| If the REBOL program does not run, make sure that your OS is supported. If it is a commonly used OS, and the program does not run, please contact us via the Feedback.
Tuples are used for version numbers, RGB color values, and network addresses. They are written as integers that range from 0 to 255 and are separated by dots. For example: ``` 2.3.0.3.1 255.255.0 199.4.80.7 ``` At least two dots are required (otherwise the number will be interpreted as a decimal value, not a tuple). Example: ``` 2.3.0 ; tuple 2.3. ; tuple 2.3 ; decimal ```
Block type tests: ``` Block? Paren? Path? List? Hash? ``` String type tests: ``` String? Binary? Tag? File? URL? Email? Image? Issue? ``` Other series type tests: ``` Series? Any-block? Any-string? ```
REBOL provides several types of comments: |''In headers'' |Every script begins with a scripts: headers which can provide general information about the script, including its title, purpose, author, and more.| |''In functions'' |Functions often include embedded title comment and argument comments. These are part of the function! specification, and are used for functions like help.| |''Embedded'' |Comments can be embedded within code, and will be kept with the code, even when it is loaded.| |''Lexical'' |Lexical comments only appear in the source code and get stripped out when the is loaded.|
Although we try to make error messages clear, new users may still find them to be frustrating until you understand REBOL at a deeper level. This example shows the general format of error messages: ``` either abc [this] [that] ** Script error: abc has no value ** Where: either catch case applier do ** Near: either abc [this] [that] ``` The first line tells you the general type of error (script error) and provides a few specifics (abc has no value, it is undefined.) The second line provides the back-trace of functions that were called before the error occurred. The first name is where the error happened. Some of these are functions in your code; others are system functions that called your code. The third line shows you the code where the error happened. This is an approximate location, because the error may span several values. More on the details of errors can be found in the [[Errors|Concepts: Errors]] section.
The [[union|Functions: union]] function takes two series and returns a series that contains all the values from both series, but no duplicates. Examples: ``` probe union [Bill Bob Bart] [Bob Ted Fred] [Bill Bob Bart Ted Fred] ``` ``` lunch: [ham cheese bread carrot] dinner: [ham salad carrot rice] probe union lunch dinner [ham cheese bread carrot salad rice] ``` ``` print union [1 3 2 4] [3 5 4 6] 1 3 2 4 5 6 ``` ``` string1: "CBDA" ; A B C D scrambled string2: "EDCF" ; C D E F scrambled print sort union string1 string2 ABCDEF ``` The [[union|Functions: union]] function can also be used on bitsets: ``` charset1: charset "ABCDEF" charset2: charset "DEFGHI" charset3: union charset1 charset2 print find charset3 "C" true ``` ``` print find charset3 "G" true ``` The `/case` refinement allows case-sensitive unions: ``` probe union/case [Bill bill Bob bob] [bill Bob] [Bill bill Bob bob] ```
The [[unique|Functions: unique]] function returns a unique set that contains no duplicate values. Examples: ``` data: [Bill Betty Bob Benny Bart Bob Bill Bob] probe unique data [Bill Betty Bob Benny Bart] ``` ``` print unique "abracadabra" abrcd ```
A word that has no value is [[unset!|Datatypes: Unset!]]. If an unset word is evaluated, an error will occur: ``` >> outlook ** Script Error: outlook has no value. ** Where: outlook ``` The error message in the previous example indicates that the word has not been set to a value. The word is unset. Do not confuse this with a word that has been set to [[none!|Datatypes: None!]], which is a valid value. A previously defined word can be unset at any time using [[unset!|Datatypes: Unset!]] : ``` unset 'word ``` When a word is unset, its value is lost. To determine if a word has been set, use the [[value?|Functions: value?]] function, which takes a literal word as its argument: ``` if not value? 'word [print "word is not set"] word is not set ``` Determining whether a word is set can be useful in scripts that call other scripts. For instance, a script may set a default parameter that was not previously set: ``` if not value? 'test-mode [test-mode: on] ```
There are two functions for changing character casing: [[uppercase|Functions: uppercase]] and [[lowercase|Functions: lowercase]]. The [[uppercase|Functions: uppercase]] function takes a string argument and converts its characters to uppercase: ``` print uppercase "SamPle TExT, tO test CASES" SAMPLE TEXT, TO TEST CASES ``` The [[lowercase|Functions: lowercase]] function converts characters to lowercase: ``` print lowercase "Sample TEXT, tO teST Cases" sample text, to test cases ``` To convert only a portion of a string, use the `/part` refinement: ``` print upppercase/part "ukiah" 1 Ukiah ```
Most types of Internet URLs are accepted directly by REBOL. They begin with a scheme name (HTTP for example) followed by a path. For example: ``` http://www.rebol.com ftp://ftp.rebol.com/sendmail.r ftp://freda:grid@da.site.dom/dir/files/ mailto:info@rebol.com ```
The meaning of words can also vary depending on how they are used. Like verbs and nouns, sometimes a verb can be a noun, and vice versa. For example, these lines all use the same word, print, but it's meaning is different for each. ``` print 123 probe [print] source print do get second [probe print] 456 parse [time to print 10:30] [thru 'print set time time!] database/print data ``` Each of these uses print in a different way.
The console provides "virtual terminal" capability that allows you to perform operations such as cursor movement, cursor addressing, line editing, screen clearing, control key input, and cursor position querying. The console control sequences follow the ANSI standard. These features provide you with the capability to write your own platform-independent terminal programs such as text editors, email clients, or telnet emulators. The console features apply to both input and output. On input, function keys will be converted to multiple-character escape sequences. On output, multiple-character escape sequences can be used to control the display of text in the console window. Both the input and output sequences begin with the ANSI escape character, 27 decimal (1B hex). The next character in the sequence indicates the control keys on input or the terminal control operation on output. * The ANSI control characters are case-sensitive and normally require an upper case character. ''Keyboard Input Sequences'' The input sequences for function keys are listed in the table below (on systems and shells that support them, such as Linux, BSD, etc.) To receive these sequences as a stream of unprocessed characters, disable the input port line handling mode: ``` set-modes system/ports/input [lines: false] ``` Now you can get input from the port (with COPY or READ-IO) or use a function like INPUT to get each character: ``` while [ code: input code <> 13 ; ENTER ][ probe code ] ``` Here are a few of the common ANSI input function codes: |''Function Key'' |''As Escape Code'' |''As REBOL Block''|h |F1 |ESC O P |[27 79 80]| |F2 |ESC O Q |[27 79 81]| |F3 |ESC O R |[27 79 82]| |F4 |ESC O S |[27 79 83]| |F5 |ESC [ 1 5 ~ |[27 91 49 53 126]| |F6 |ESC [ 1 7 ~ |[27 91 49 55 126]| |F7 |ESC [ 1 8 ~ |[27 91 49 56 126]| |F8 |ESC [ 1 9 ~ |[27 91 49 57 126]| |F9 |ESC [ 2 0 ~ |[27 91 50 48 126]| |F10 |ESC [ 2 1 ~ |[27 91 50 49 126]| |F11 |ESC [ 2 2 ~ |[27 91 50 50 126]| |F12 |ESC [ 2 3 ~ |[27 91 50 51 126]| |Home |ESC [ 1 ~ |[27 91 49 126]| |End |ESC [ 4 ~ |[27 91 52 126]| |Page-up |ESC [ 5 ~ |[27 91 53 126]| |Page-down |ESC [ 6 ~ |[27 91 54 126]| |Insert |ESC [ 2 ~ |[27 91 50 126]| |Up |ESC [ A |[27 91 65]| |Down |ESC [ B |[27 91 66]| |Left |ESC [ D |[27 91 68]| |Right |ESC [ C |[27 91 67]| ''Terminal Output Sequences'' There are several variations in the terminal control output character sequences. Some command codes are preceded by a number (sent in ASCII) indicating that the operation is to be performed the specified number of times. For example the cursor motion command may be preceded by two numbers separated by a semicolon to indicate the row and column position to move to. The cursor command characters (upper case required) are included in the following table: |''Output Sequence'' |''Description''|h |(1B) |Use this escape code prior to the following codes| |D |Moves cursor one space left| |C |Moves cursor one space right| |A |Moves cursor one space up| |B |Moves cursor one space down| |n D |Moves cursor n spaces left| |n C |Moves cursor n spaces right| |n A |Moves cursor n spaces up| |n B |Moves cursor n spaces down| |r ; c H |Moves cursor to row r, column c| |H |Moves cursor to top left corner (home)| |P |Deletes one character to the right at current location| |n P |Deletes n characters to the right at current location| |@ |Inserts one blank space at current location| |n @ |Inserts n blank spaces at current location| |J |Clears screen and moves cursor to top left corner (home)| |K |Clears from current position to end of current line| |6n |Places the current cursor position in the input buffer| |7n |Places screen dimensions in the input buffer| The top left corner is defined as row 1, column 1 The following example moves the cursor to the right ten spaces: ``` print "^(1B)[10CHi!" Hi ``` This example moves the cursor to the left seven spaces and clears the remainder of the line: ``` cursor: func [parm [string!]][join "^(1B)[" parm] print ["How are you" cursor "7D" cursor "K"] How a ``` To find the current console window size, you can use this example: ``` cons: open/binary [scheme: 'console] print cursor "7n" screen-dimensions: next next to-string copy cons 33;105R ``` ``` close cons ``` The above example opens the console, sends a control character to the input buffer and copies the return value. It reads the value (screen dimensions) that is returned after the control character and closes the console. The return value is the height and width separated by a semicolon (;) and followed by an R. In the above example, the screen is 33 high by 105 wide. <<< Autoscroll Printing a character to the bottom-right corner of some terminals will cause a new line, which will scroll the screen. Others will not. This inconsistency between console terminal types must be considered when writing REBOL scripts intended to be cross-platform. <<<
When REBOL waits for a network operation to complete, a busy indicator appears on screen to indicate that something is happening. You can change the indicator with a line like: ``` system/console/busy: "123456789-" ``` Whe REBOL is running in quiet mode, te busy indicator will not be displayed.
The default command line prompt is `>>`. You can change the prompt with code such as: ``` system/console/prompt: "Input: " Input: ``` The prompt can be a block that is evaluated each time. This line prints the current time: ``` system/console/prompt: [reform [now/time " >> "]] 10:30 >> ```
''Error Messages'' There are several types of errors within REBOL. When an error occurs a message is displayed that tells you what the error was and approximately where it occurred. For instance if you type: ``` abc ** Script Error: abc has no value. ** Where: abc ``` The type of error is indicated by the first few words of the message. In the above example, the error is a Script Error. Script errors are the most common and occur when you use a function of the language in the wrong way or with improper arguments. Other types of errors are described in `[bad-link:concepts/error.txt]` Types. |''Error Type'' |''Description''|h |Syntax errors |Occur when the script contains an invalid value or a missing header, quote, bracket, or parenthesis.| |Math errors |Occur when dividing a number by zero or there was a math overflow or underflow.| |Access errors |Occur when a file, directory, or network operation cannot be accessed or access permissions are restricted.| |Throw errors |Occur when a break, exit, or throw is used in an improper manner.| |User errors |Defined by the user's script.| |Internal errors |Returned when a problem occurs within the REBOL system. If you encounter one of these types of errors, please report it to `[bad-link:concepts/feedback.txt]`.| Most types of errors can be trapped and processed by your script. See `[bad-link:concepts/trying.txt`] Blocks for a description of the try function. ''Redirecting Errors'' When errors are encountered in non-interactive sessions, such as when running in CGI mode (-c or --cgi ) or in no window mode (-w or --nowindow ), the session is automatically terminated. If a script terminates while running in non-interactive mode, you can use shell redirection to output the error to a file: ``` REBOL -cs my_script.r >> my_script.log ``` This appends the output to the file in most operating systems.
moved this page [[Guide: Basics: Getting help and advice]]
Each line typed into REBOL at the prompt is stored in a history block, and it can be recalled later using the up and down arrow keys. For instance, pressing the up arrow once recalls the prior input line. The history block containing all input lines is accessed from the system console object: ``` probe system/console/history ``` You can save the history block as a file: ``` save %history.r system/console/history ``` and it can be reloaded later with: ``` system/console/history: load %history.r ``` These lines can be put in the `user.r` file to save and reload your history between REBOL sessions.
REBOL installation takes only a few seconds and is very easy, non-intrusive, and non-disruptive. For `REBOL/Core` the only installation procedure is to uncompress the distribution files and store them in any directory on your system. For other REBOL products, installation may require you to provide additional information, such as where to store related files. Refer to the release notes that are included with the distribution files. ''Contents'' * [[Distribution Files]] * [[Home Environment Variable]] * [[Network Setup]] * [[Proxy and Firewall Settings]] * [[License Agreement]] !!! ''Distribution Files'' {{Distribution Files}} !!! ''Home Environment Variable'' {{Home Environment Variable}} !!! ''Network Setup'' {{Network Setup}} !!! ''Proxy and Firewall Settings'' {{Proxy and Firewall Settings}} !!! ''License Agreement'' {{License Agreement}}
To exit REBOL at any time, select quit from the `Console` [[file!|Datatypes: File!]] menu or by typing [[quit|Functions: quit]] or [[q|Functions: q]] at the prompt. You can also quit the program from within a script: ``` if now/time > 12:00 [quit] ``` The REBOL console may also quit if an error occurs during startup. <<< Exit Does Not Quit Do not use the word [[exit|Functions: exit]] to quit REBOL. This word is used for exiting functions and it will return an error if typed at the console. <<<
The default result indicator is `==` and can be modified with a line such as: ``` system/console/result: "Result: " ``` These settings can be placed in the `user.r` file to make them permanent.
''Contents'' * [[Security Issues]] ** [[Port Security]] ** [[Prior Security Settings]] * [[Program Arguments]] * [[Script File]] * [[Specifying Options]] * [[File Redirection]] * [[Script Arguments]] * [[Startup Files]] !!! ''Security Issues'' {{Security Issues}} !!!!! ''Port Security'' {{Port Security}} !!!!! ''Prior Security Settings'' {{Prior Security Settings}} !!! ''Program Arguments'' {{Program Arguments}} !!! ''Script File'' {{Script File}} !!! ''Specifying Options'' {{Specifying Options}} !!! ''File Redirection'' {{File Redirection}} !!! ''Script Arguments'' {{Script Arguments}} !!! ''Startup Files'' {{Startup Files}}
The R3 alpha uses the default Windows console. This is a temporary situation until the new console has been created. ''Contents'' * [[Copy and Paste]] * [[Scroll Wheel]] * [[Echo Mode]] * [[Special Commands]] * [[Cygwin console: rxvt]] !!! ''Copy and Paste'' {{Copy and Paste}} !!! ''Scroll Wheel'' {{Scroll Wheel}} !!! ''Echo Mode'' {{Echo Mode}} !!! ''Special Commands'' {{Special Commands}} !!! ''Cygwin console: rxvt'' {{Cygwin console: rxvt}}
On initialization, a banner is displayed that identifies the program version. Version numbers have the format: ``` version.revision.update.platform.variation ``` For example, the version number: ``` 2.3.0.3.1 ``` indicates that you are running version 2, revision 3, update 0, for Windows 95/98/NT (REBOL platform number 3.1). A complete list of all platform numbers is available from [[REBOL.com|http://www.rebol.com]]. This HTML file also contains a hidden REBOL database that can be used for determining the platform. You can obtain the version number from the REBOL prompt with: ``` print system/version ``` Only the latest release of REBOL is supported by REBOL Technologies. You can verify that you have the latest version and automatically update it if out of date. To do so, be sure that you are connected to the Internet, then from within REBOL type: ``` upgrade This copy of Windows 95/98/NT iX86 REBOL/core 2.3.0.3.1 is currently up to date. This copy of Windows 95/98/NT iX86 REBOL/core 2.1.2.3.1 is not up to date. Current version is: 2.3.0.3.1. Download current version? ``` To upgrade to the latest version, type Y (yes). Otherwise, type N (no).
This section will explain how to use REBOL. Editor note: This section is new or has has recently changed and is still under construction.
Whenever you run `REBOL/Core`, it opens a console to display output and accept input. If you provide a script argument to the program, the script is run, and you see the output from that script. If you do not provide a script file, the console prompts you for input. The input prompt looks like this: ``` >> == ``` For example: ``` >> 100 + 20 == 120 ``` ``` >> now - 7-Dec-1944 == 20341 ``` <<< Changing the Prompt The prompt characters can be changed. See the [bad-link:concepts/console.txt] Appendix for more information. <<< The console also becomes active if a script encounters an error or if the script calls the halt function. ''Contents'' * [[Mulitple Line Input]] * [[Interrupting a Script]] * [[History Recall|Using the console: History Recall]] * [[Word Completion]] * [[Busy Indicator|Using the console: Busy Indicator]] * [[Network Connections]] * [[Virtual Terminal]] !!! ''Mulitple Line Input'' {{Mulitple Line Input}} !!! ''Interrupting a Script'' {{Interrupting a Script}} !!! ''History Recall'' {{Using the console: History Recall}} !!! ''Word Completion'' {{Word Completion}} !!! ''Busy Indicator'' {{Using the console: Busy Indicator}} !!! ''Network Connections'' {{Network Connections}} !!! ''Virtual Terminal'' {{Virtual Terminal}}
When you use a bitset, you normally want to: * check if a single bit is set or not * check for if any one or more of several bits are set or not * check that all specified bits are set * find a character in a string specified by a bitset * parse a string for characters specified in a bitset !!!! ''Checking bits'' To check for one or more bits in a bitset most of the time you will use the find function. ``` find the-bitset some-bits ``` It's quite common for find to be part of a conditional expression, such as: ``` if find the-bitset some-bits [... do something ...] ``` Note that while less common, you can also use pick or a path selection in a similar way. !!!! ''Examples of character bitsets'' Examples of character-oriented: ``` alpha: make bitset! [#"A" - #"Z" #"a" - #"z"] if find alpha #"a" [...] if find alpha "abc" [...] if find alpha [#"a" - #"g"] [...] if find alpha [":;?" #"a" - #"g" 3 - 20] [...] ``` !!!! ''Examples using integer bitsets'' ``` bits: make bitset! [1 4 9 - 16 25 - 36] if find bits 42 [...] if find bits [20 - 29] [...] if find bits [#"A" - #"Z" ".,?" 20 - 29] [...] ``` !!!! ''Examples using path selection'' ``` if alpha/#"a" [...] if alpha/"abc" [...] if bits/12 [...] ``` !!!! ''Bitsets for character classes'' Bitsets are often used to create character classes (e.g. digits, alpha, alpha-numeric, punctuation) to search for multiple characters at the same time: ``` invalid-chars: charset [0 - #" " ",.;:?"] if find name invalid-chars [...] ``` Such character classes are also used in parse rules: ``` digits: charset "0123456789" alpha: charset [#"A" - #"Z" #"a" - #"z"] if parse name [some alpha any digits] [...] ``` See [[parse|Functions: parse]] section for details. !!!! ''Character casing'' ''Editor note: specification pending''
When parsing large grammar from a set of rules, variables are used to make the grammar more readable. However, the variables are global and may become confused with other variables that have the same name somewhere else in the program. The solution to this problem is to use an object to make all the rule words local to a context. For instance: ``` tag-parser: make object! [ tags: make block! 100 text: make string! 8000 html-code: [ copy tag ["<" thru ">"] (append tags tag) | copy txt to "<" (append text txt) ] parse-tags: func [site [url!]] [ clear tags clear text parse read site [to "<" some html-code] foreach tag tags [print tag] print text ] ] tag-parser/parse-tags http://www.rebol.com ```
When REBOL waits for a network operation to complete, a busy indicator appears to indicate that something is happening. You can change the indicator to your own character pattern. See the `[bad-link:concepts/console.txt]` Appendix for more information.
Each line that is typed into REBOL is stored for later recall. The up and down arrow keys are used to scroll through the list of previous lines. For instance, pressing the up arrow once recalls the prior input line. History lines can be written to a file by saving the history block. See the `[bad-link:concepts/console.txt]` Appendix for more information.
''Values'' are the raw data of REBOL. A wide variety of values can be written directly. No special constructor is required. You simply write the values as is. The language strives to use human-friendly forms for values. This makes scripts more readable. In addition, it accepts more than one format for some values to allow for international variations. Numeric data: ``` 1234 -432 5'678 ; integer 3.1415 1.23E12 0,01 1,2E12 ; decimal 1% 100% 12.34% 1234% ; percent $12.34 ; money (arbitrary precision) 3.1.5 ; version numbers 255.255.0.100 ; colors 199.4.80.7 ; network addresses 5x10 100x100 -50x-25 ; x/y coordinates/sizes ``` Times and dates: ``` 12:34 20:05:32 -0:25.34 20-Apr-2008 20-4-1998 20-Apr-1998/12:32 ; date and time 20-Apr-1998/12:32-8:00 ; with timezone ``` Strings and bytes: ``` "Here is a string" {Here is another way to write a string that spans many lines and contains "quoted" strings.} #{0A6B14728C4DBEF5} ; hex encoded 64#{45kLKJOIU8439LKJklj} ; base-64 encoded ``` Special strings, such as files, tags, URLs, and email forms: ``` %data.txt %images/photo.jpg %../scripts/*.r <title> </body> <font size="2" color="blue"> http://www.rebol.com ftp://ftp.rebol.com/sendmail.r info@rebol.com bill-smity@example.com ``` More details are found in [[Expressions: Values|Concepts: Expressions: Values]].
When the refinement is used, the optional arguments have to be provided. When the refinement isn't used, the optional arguments are set to `#[none]`.
''Contents'' * Concepts * Mechanism ** Basic Mechanism ** Detailed Mechanism * Event Handling Layers * System Port Awake * View Handlers ** Event Scheme ** Handler Objects ** Handler API ** Adding a Handler * Event Fields ** Event Types ** Keyboard Events ''Concepts'' An event is a signal that drives GUI actions. It is a method of notification that includes an event type along with a set of related attributes. User inputs such as moving the mouse, clicking a mouse button, or pressing a key cause events to occur that are handled by mechanisms implemented within the GUI system. For example, when a mouse button is pressed, you need to know which button was pressed, that it went down and also up, where the mouse was positioned, and other modifiers, such as the shift or control keys that were being held down at the time. An event handler is software that processes an event when it occurs and makes the necessary changes to the state of GUI objects. For example, if the mouse button is clicked while the mouse was over a button image, then the handler will cause the logic of the button to operate, including its end result, a [[reactor|GUI Reactors]]. See the [[lower level event system|http://www.rebol.net/wiki/Event_System]] description for more information. ''Mechanism'' For simple GUI scripts, you do not need to understand the event system. You can create panels with buttons and other styles, and they will work just fine. However, some developers may want to know the basics, and the easiest way to understand the event system is to look at a specific example. !!!!! ''Basic Mechanism'' Let's say the user has pressed down the left mouse button at position 100x100 within a specific window. Here's the basic sequence of events: # User presses a mouse button. # A sequence of event handlers is called to process the event. # The the GUI handler calls [[style actors|GUI Actors]] to update the display or take some other action. # The actors may trigger a [[reactor|GUI Reactors]] that produces an end-result, such as opening a new window or launching a web browser. This is the basic information you need to know to understand GUI events. However, if you need to do any special processing for events, such as write your own style actions, you may need to know more. See the next section. !!!!! ''Detailed Mechanism'' For developers who want to understand the complete GUI event mechanism, here are the full details of the above mouse button click sequence. # The user presses down the left mouse button. # The underlying OS detects the event. # The OS notifies the REBOL event device, low level C code functions. # The device decodes the mouse information including the down state of the button, the window GOB, the position at 100x100, and any other details. # An event! datatype is obtained (from a preallocated block). Its fields are set with the information above. For example, its type field is set to down. # The event is queued to the system port. This is an event concentrator (a funnel.) From the C code side, all events of all kinds are queued here. # Control returns to the REBOL interpreter. # The event wakes up the system port. # The system port redirects the event to the GUI event port. (''The system port is an event dispatcher. All REBOL side events originate from here''.) # The GUI event port examines the event and uses the window GOB to locate a GUI handler specific to that window. Most of the time, this is the general GUI system handler, but users can provide custom handlers as well (e.g. for high-performance code, games, etc.) # The GUI handler is called via its do-event function. # The handler dispatches a specific function associated with the down event. # The down event maps its location to a specific face, such as a button face that was displayed on screen earlier. # If a face is present, the `on-click` actor for its style is called. # The style actor then calls any reactor functions, such as setting a variable, evaluating a block of code, scrolling a panel, etc. All of this is done very efficiently with as few extra steps as possible in order to keep the GUI highly responsive to user interaction. For more information, see the Event System documentation or browse the GUI source code in the R3 DevBase archive. ''Event Handling Layers'' As you can see from the above discussion, there are various layers where events are handled. |''native level'' |The machine code native level written in C code. This is high-performance code and should only be modified by experts. (It's source is part of the R3 Host-kit.)| |''system port'' |Used to isolate and concentrate the native level from the interpreter level. All events, including GUI and networking events, pass through this code. It is also highly tuned code, and should only be modified by experts.| |''view handler'' |Handles events for the graphics system. REBOL provides two default handlers: a simple one for simple window event handling, such as done in GOB windows, and an advanced one for processing GUI events. Users can create their own window handlers.| |''style actors'' |Every style has actor functions that process events for faces, and they can be written by users familiar with GUI style and face operation.| |''face reactors'' |The highest level functions. These provide the end result for an event, such as opening a window, writing a file, evaluating code, etc.| Although code can be added or modified at any layer, it is advised that you only change the layers that you understand completely. Improper changes can cause intermittent problems, lost events, or event queue overflows. ''System Port Awake'' As mentioned above, the system port provides the main handler for REBOL. It's main purpose is to isolate native events from interpreter events, it decouples the two subsystems. This is necessary to prevent the host and the interpreter from intermixing their specific environments in a way that would cause problems for system resources, including heap and stack allocation. At the native host level, when host code is running, all events are appended to an event queue. Eventually, when control returns to the REBOL interpreter kernel, it examines the queue to determine what events have occurred. This process decouples the host from the interpreter. At the core of the system port is an event handler called `awake` that examines the event queue and dispatches events to specific port-based event handlers. This is done through a special [[wake-up|Functions: wake-up]] function. <<< Generally, you should not modify the system port awake handler unless ''you know what you're doing''. This code needs to be efficient. Even adding a few more lines to it will slow down all REBOL port I/O event handling. <<< However, if you have discovered an improvement or tweak that improves the code without serious side effects, please post it on R3 Chat (DevBase). The system port awake function as of publication of this document is: ``` awake: func [ sport "System port (State block holds events)" ports "Port list (Copy of block passed to WAIT)" /local event port waked ][ waked: sport/data ; The wake list (pending awakes) ; Process all events (even if no awake ports). ; Do only 8 events at a time (to prevent polling lockout). loop 8 [ unless event: take sport/state [break] port: event/port if wake-up port event [ ; Add port to wake list: ;print ["==System-waked:" port/spec/ref] unless find waked port [append waked port] ] ] ; No wake ports (just a timer), return now. unless block? ports [return none] ; Are any of the requested ports awake? forall ports [ if find waked first ports [return true] ] false ; keep waiting ] ``` It's archive location is in mezz-ports.r in the R3 Mezzanine section of DevBase. ''View Handlers'' The View graphics system provides the next layer of event handling. These types of events are related to user inputs that occur through windowing and related user input devices. !!!!! ''Event Scheme'' The event scheme provides a port definition that is used for view system events. It stores a list of handler objects that are dispatched by a central view-based event awake function. When an event occurs, its window field is examined for a handler. !!!!! ''Handler Objects'' The view system defines a standard handler object that consists of these fields: |''Field'' |''Datatype'' |''Description''|h |''name'' |word! |Identification of the handler. Used for debugging purposes, and it's useful to figure out what's going on when you have more than one handler running| |''about'' |string! |Short description of the handler. Used for help.| |''status'' |word! |The status of the handler.| |''priority''| integer! |The urgency of the handler. Controls where the handler is inserted into the handler list. A higher values is processed earlier.| |''do-event'' |function! |Main function to process events. Called whenever events occur.| The base event handler object is defined as: ``` base-handler: context [ do-event: func [event] [ ; at top for performance print "(Missing event handler)" event ] win-gob: none status: 'made name: 'no-name priority: 0 about: "Main template for VIEW event handlers." ] ``` !!!!! ''Handler API'' The functions for view handlers are: |''Function'' |''Description''|h |''handler-events'' |Adds a handler to the view event system.| |''unhandle-events'' |Removes a hander from the view event system.| |''handled-events?'' |Returns event handler object matching a given name.| |''do-events'' |Waits for window events. Returns when all windows are closed.| !!!!! ''Adding a Handler'' There are two ways to add a view-level handler: you can provide it as an option to the view function or install it with the handle-events function. The format of a handler is an object definition block of the form described above. Here's an example handler, notice it's just a block here: ``` my-handler: [ name: 'my-handler priority: 50 handler: func [event] [ print ["event:" event/type event/offset] if switch event/type [ close [true] key [event/key = escape] ] [ unhandle-events self unview event/window quit ] show event/window none ] ] ``` It can be provided to the [[view|Functions: view]] function at the same time the window GOB is provided: ``` view/options window [handler: my-handler] ``` Or, it can be installed with: ``` handle-events my-handler ``` Notice that this view handler will remove itself with unhandle-events when its window is closed. ''Event Fields'' An event value can decode these fields using refinements. Some fields may be meaningless for specific events. |''Field'' |''Datatype'' |''Description''|h |''type'' |word! |A word that indicates the type of event. See list below.| |''port'' |port! |The port for the event. For the GUI, this is the event port; however, for non-GUI ports, this field is overloaded and can contain other information.| |''gob'' |gob! |The GOB where the event occurred. By default, the window GOB.| |''window'' |gob! |Alias for above.| |''offset'' |pair! |The position (only valid for mouse and size events).| |''key'' |char! word! |Key char or word (only valid for keyboard events). See list below for word-based characters.| |''flags'' |block! none! |A block of possible modifiers: double control shift| |''code'' |integer! |The integer code for a key down event.| |''data'' |file! none! |For a drop-file event, provides the file name.| !!!!! ''Event Types'' Possible event types are defined in `system/view/event-types`. They are: ``` ignore interrupt device custom error init open close connect accept read write wrote lookup ready done time show hide offset resize active inactive minimize maximize restore move down up alt-down alt-up aux-down aux-up key key-up scroll-line scroll-page drop-file ``` !!!!! ''Keyboard Events'' Keyboard events can be character value or word value for virtual keys like `insert` and :home. Current virtual key words are defined in `system/view/event-keys`: ``` page-up page-down end home left up right down insert delete f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 ``` Of course, F10 may be a problem on most Windows systems.
''Contents'' [[Graphical User Interface (GUI)]] * ''Concept'' * [[GOB is a Datatype]] ** Making GOBs ** Content Types ** Access Fields ** Offset and Size ** Data Reference * [[Panes]] ** Adding GOBS to Panes ** Other Useful Actions ** All Valid Actions ** Coordinate Mapping * [[GOBs as Windows]] ** The Screen GOB ** Creating a Window ** Window Flags ** Event Handling * [[Rendering Graphics]] * [[Transparency]] * ''Examples'' ''Concept'' ''A GOB is a low-level graphical object''. GOBs are used for for constructing windows, panels, images, text, and drawings. They support two dimensional compositing with transparency (alpha channel), scalar vector graphics, image effects, and rich-text. A GOB is a highly optimized native datatype. It has been designed to provide the primary features required for graphics, but substantially reduce the memory footprint and processing overhead required. As a result, complex displays, such as animations, simulations, or video games can be created that are composed of thousands of individual GOB elements. <<< ''Users do not need this information just to use the GUI''. This information is provided for users who want to use the graphics system directly or to create new styles for the GUI. <<< ''Examples'' The example below creates a window with a background image and an image on top of that background. Note, that setting `gobb/image` to back-img automatically sets `gobb/size` to the image's size - or, to state it differently, for image GOBs the size is always equal to that of the image. ``` ;-- Load the images: back-img: load %img/ukiah.jpg tiny-img: load %img/dev.jpg ;-- Background image gobb: make gob! [offset: 0x0] gobb/image: back-img ;-- Top image: gobi: make gob! [offset: 10x10] gobi/image: tiny-img ;-- The window: win: make gob! [text: "Test Window"] win/size: gobb/size append win gobb append win gobi view win ```
''Contents'' * Concept ** Command Arguments ** Dialect Specification * Commands ** Setup, Attributes, Matrix ** Lines and Segments ** Curves and Arcs ** Custom Shapes * Error Processing ''Concept'' The draw dialect is a REBOL sub-language for describing scalar vector graphics (SVG). The dialect consists of a number of command keywords, as listed in this document below. Each command can be followed by its arguments, all of which are optional. Their names, datatypes, and descriptions are provided in the "argument" table for each command section below. !!!!! ''Command Arguments'' If an argument is not provided, it's default value will be used. In general, most commands will do something useful even if no arguments are provided. This is the "default simple" principle. In cases where a size is required, the approximate area size of the [[gob|View - Graphical Objects]] will be used. For example, if you draw a box and provide no arguments, the box will be made the size of the GOB. When command arguments are provided they are matched by datatype and then by position. For example, if a command accepts a string and two pair values, if only a pair value is provided, it will be assigned to the first pair argument. The string and the second pair will get their default values. This optional argument method also allows arguments of different datatypes to be written in a different order. In the example above, if the actual arguments were specified as a pair followed by a string, that would work as well. This relieves the programmer of needing to remember the precise order of all arguments. !!!!! ''Dialect Specification'' The draw dialect is currently implemented with the delect method of dialect definitions. The dialect is defined by the object found at `system/dialects/draw`. In this definition, the command words are set to blocks that specify their arguments. Words that are set to none are keyword arguments, not commands. It is not recommended for programs modify the `system/dialects/draw` object unless the modification is intended to affect all code (globally) that calls the draw dialect. ''Commands'' !!!!! ''Setup, Attributes, Matrix'' [[Draw - Setup and Attribute Commands|http://www.rebol.com/r3/docs/view/draw-setup.html]] describes draw commands related to special attributes, matrix setup and various transformations. * Anti-alias * Clip * Fill-pen * Fill-rule * Gamma * Grad-pen * Invert-matrix * Matrix * Pen * Push * Reset-matrix * Rotate * Scale * Skew * Transform * Translate !!!!! ''Lines and Segments'' [[Draw - Line Related Commands|http://www.rebol.com/r3/docs/view/draw-lines.html]] describes draw commands that are related to lines, line segments, vertices, polygons and basic shapes. * Arrow * Box * Line * Line-cap * Line-join * Line-pattern * Line-width * Polygon * Shape * Triangle !!!!! ''Curves and Arcs'' [[Draw - Curve Related Commands|http://www.rebol.com/r3/docs/view/draw-curves.html]] describes draw commands that are related to curves, arcs, circles, and ellipses. * Arc * Circle * Curve * Ellipse * Spline !!!!! ''Custom Shapes'' [[Draw - Shape Sub-Commands|http://www.rebol.com/r3/docs/view/draw-shapes.html]] Describes special commands optimized for describing shapes. All of these commands are used withing the shape argument block and should not be used separately. * Arc * Close * Curv * Curve * Hline * Line * Move * Qcurv * Qcurve * Vline ''Error Processing'' describe how errors are shown
''Contents'' * Concepts * Basic Functions * The VIEW Function ** Primary Argument ** Special Options * Implied Wait * Moving Windows * Window Metrics * Event Handlers ''Concepts'' The R3 View System handles windowing, events, popups, requestors, and modal operations. It is responsible for opening new windows on the screen and handling their events. The windowing part of the system is independent of the higher level graphical user interface (the GUI) and also of lower level graphical objects (GOBs); however, it can interact with both of those sub-systems. Normally the GUI provides the contents to the view system, but users are also allowed to build and display their own windows directly or even write their own custom graphics systems. ''Basic Functions'' The view system provides these basic top level functions: |''Function'' |''Description''|h |''view'' |open a window with contents based on a GUI panel or other graphical object.| |''unview'' |close one or more windows opened earlier.| |''do-events'' |process all events (switch to an event-driven mode of REBOL).| |''handle-events'' |add a global event handler.| |''unhandle-events'' |remove a global event handler.| ''The VIEW Function'' <<< Loading GUI During Alpha The R3 alpha release does not include the GUI code bundled into its executable. It must be downloaded. To do so, add this line near the top of your scripts: ``` load-gui ``` The view function opens new windows and is the main function of the view system. <<< The [[view|View - Graphical Objects]] function opens new windows and is the main function of the view system. ``` USAGE: VIEW spec /options opts /modal /no-wait /across /as-is DESCRIPTION: Displays a window view from a layout block, face (panel), or low level graphics object (gob). VIEW is a function value. ARGUMENTS: spec -- Layout block, face object, or gob type (block! object! gob!) REFINEMENTS: /options opts -- Optional features, in name: value format (block!) /modal -- Display a modal window (pop-up) /no-wait -- Return immediately - do not wait /across -- Use horizontal layout for top panel (rather than vertical) /as-is -- Use GOB exactly as passed - do not add a parent gob ``` !!!!! ''Primary Argument'' The view function accepts several different datatypes for its window argument, and each has a different meaning: |''Datatype'' |''Description''|H |''block!'' |A GUI panel layout description. Create the panel and open the window to display it.| |''object!'' |A face object created earlier, such as a panel that was created with make-panel. Open a window and display it.| |''gob!'' |A low level graphical object. Create a window gob and event handler for the passed gob and open it.| Examples: ``` view [text "Hello world!"] view make-face 'text [text: "Hello world!"] view make gob! [text: "Hello world!"] ``` The first and second examples are equivalent, but there will be times when you want to provide a panel face object rather than the GUI description itself. In the last example the gob is not the window itself, but the object to be displayed within the window. The view function will create a window to display that object with a title and other options. !!!!! ''Special Options'' Window options are specified in a block in name-value format. For example: ``` view/options window [title: "Example" modes: [resize]] ``` Valid fields of the block are: |''Name'' |''Description''|h |''across'' |build GUI as a horizontal panel by default| |''as-is'' |do not create a window, use the provided gob as a window| |''flags'' |special window flags (resize modal popup on-top no-title)| |''handler'' |provide a new event handler| |''modal'' |make it a modal (popup)| |''no-resize'' |do not allow resizing| |''no-wait'' |do not wait on VIEW| |''offset'' |window position (or 'center for centered)| |''owner'' |window owner| |''reactors'' |provide block of GUI reactors| |''title'' |window title| Examples: ``` view/options window [title: "My window title"] view/options window [flags: [resize dropable]] view/options window [no-wait: on] view/options window [offset: 100x100] view/options window [offset: 'center] view/options window [as-is: true] ; GOB is the window object ``` Some of these also have refinements as shortcuts: ``` view/modal window view/no-wait window ``` ''Implied Wait'' When the [[view|View - Graphical Objects]] function is called it does not return immediately. Instead, it waits and allows windows to process their events. That is, your code becomes event-driven at that point. This happens only once, when the first window is opened. Of course, if you call view more than once without closing, subsequent calls will not wait. The view function will return only when all windows have been closed. If you want view to return immediately, you can use: ``` view/no-wait win ``` Then, when you are ready, call the [[do-events|Functions: do-events]] function to start the event-driven mode of your code. Example: ``` view/no-wait win ...other stuff... do-events ``` ''Moving Windows'' This example shows how to dynamically relocate a window by changing its GOB offset and calling show again (in this case, show-later, see note below.) ``` view [ title "Click to move window" button "Move to 100x100" do [ win: window-face? face win/gob/offset: 100x100 show-later win ] ] ``` Notes: # The do reactor block uses its face (the button) with the `window-face?` function to find the top-level window face. # The GOB of the window has its offset changed to 100x100. # The `show-later` function will show the change when the GUI exits event handling (after processing the do reactor shown above.) This example moves a window other than the one that contains the move button. ``` wgob: view/no-wait [ title "This is the window" button "Quit" quit ] view/options [ title "Move other window" button "Move to 100x100" do [ wgob/offset: 100x100 show-later wgob ] ][offset: 200x200] do-events ``` Notes: # The first window uses `/no-wait` in order proceed (not wait) and allow the second window to appear. # The first [[view|View - Graphical Objects]] returns a gob, which we call wgob. # The second window is positioned at 200x200 to avoid it appearing on top of the first window. # The second window sets the `wgob` offset. # The `show-later` function will show the change when the GUI exits event handling (after processing the do reactor shown above.) # [[do-events|Functions: do-events]] is called to process the window events for both windows. ''Window Metrics'' Metrics about the graphics system are stored in: ``` system/view/metrics ``` They include the primary metrics supported on most OS implementations. We do not provide all possible window metrics, because they may not be available in all systems, and code would become non-portable. Here is an example of current metrics: ``` ? system/view/metrics SYSTEM/VIEW/METRICS is an object of value: screen-size pair! 1152x864 border-size pair! 4x4 border-fixed pair! 3x3 title-size pair! 0x26 work-origin pair! 0x0 work-size pair! 1060x864 ``` The work-origin and work-size provide the usable work-area of the screen (without task bar). ''Event Handlers'' When you call [[view|View - Graphical Objects]], normally the system event handlers will be provided; however, you can specify your own event handler if needed. Here is an example custom event handler: ``` view/options window [ handler: [ name: 'my-handler priority: 100 handler: func [event] [ if event/type = 'down [quit] ] ] ] ``` See the [[View - Event Handling]] section for more about event handlers.
The [[source|Functions: source]] function helps users learn more about specific functions by examining their source code. For example, type: ``` >> source join The source to the join function will be returned: join: make function! [[ "Concatenates values." value "Base value" rest "Value or block of values" ][ value: either series? :value [copy value] [form :value] repend value :rest ]] ``` REBOL defined functions include the mezzanine functions (built-in interpreted functions) and user defined functions.
The console provides `virtual` terminal capability that allows you to perform operations such as cursor movement, cursor addressing, line editing, screen clearing, control key input, and cursor position querying. The virtual terminal uses the standard ANSI character sequences. This allows you to write platform-independent terminal programs such as text editors, email clients, or telnet emulators. More information can be found in the `[bad-link:concepts/console.txt]` Appendix.
A conditional expression is one that evaluates to `true` or `false`. ``` 10 > 4 true ``` ``` empty? "" true ``` ``` empty? "test" false ``` However, in REBOL we allow a true condition to be more than just the value true - almost any other value is accepted as a true value. This allows us to simplify many expressions, but at the slight cost that you must keep the rule in mind. Here is the rule: ''any value that is not'' `false` ''and not'' `none` ''is true''. So, these are all considered true: ``` true "bob" 0 123 12:30 [a b c] %file ``` and, other such values. <<< C programmers: ''Note the zero case''! Any integer, even zero, is considered true! (The reason for this will become more clear as you learn more.) <<<
Languages are built on lexicon, grammar, and semantics. |''lexicon'' |are the written symbols of the language - its literal syntax. The lexicon is what defines that 123 is an integer and "ok" is a string.| |''grammar'' |provides rules that control the order of symbols used to form expressions. It is what makes a line like "print 1 + 2" have meaning as a sequence of symbols, just as sentences do in natural languages.| |''semantics'' |associates meaning to symbols and values, and in an interpreter such as REBOL, also performs computation.| REBOL's lexicon is advanced, because it allows many datatypes to be directly expressed. However, its basic grammar is very simple - mostly functions with arguments, but it does allow specialized grammars, dialects of the language. This gives the language some real power to build a wide range of expressions. And, REBOL's semantics are quite different - based on rules of context and association. That's enough about theory for now. Let's get into some details.
The [[until|Functions: until]] and [[while|Functions: while]] functions repeat the evaluation of a block until a condition is met. The [[until|Functions: until]] function repeats a block until the evaluation of the block returns `true` (that is, not `false` or `none`! ). The evaluation block is always evaluated at least once. The [[until|Functions: until]] function returns the value of its block. The example below will print each word in the color block. The block begins by printing the first word of the block. It then moves to the next color for each color in the block. The [[tail?|Functions: tail?]] function checks for the end of the block, and will return `true`, which will cause the [[until|Functions: until]] function to exit. ``` color: [red green blue] until [ print first color tail? color: next color ] red green blue ``` The [[break|Functions: break]] function can be used to escape from the [[until|Functions: until]] loop at any time. The [[while|Functions: while]] function repeats the evaluation of its two block arguments while the first block returns `true`. The first block is the condition block, the second block is the evaluation block. When the condition block returns `false` or [[none!|Datatypes: None!]], the expression block will no longer be evaluated and the loop terminates. Here is a similar example to that show above. The [[while|Functions: while]] loop will continue to print a color while there are still colors to print. ``` color: [red green blue] while [not tail? color] [ print first color color: next color ] red green blue ``` The condition block can contain any number of expressions, so long as the last expression returns the condition. To illustrate this, the next example adds a print to the condition block. This will print the index value of the color. It will then check for the tail of the color block, which is the condition used for the loop. ``` color: [red green blue] while [ print index? color not tail? color ][ print first color color: next color ] 1 red 2 green 3 blue 4 ``` The last value of the block is returned from the [[while|Functions: while]] function. A [[break|Functions: break]] can be used to escape from the loop at any time.
The most flexible approach is to use a [[while|Functions: while]] loop, which allows you to do just about anything to the series without problems. ``` colors: [red green blue yellow orange] while [not tail? colors] [ print first colors colors: next colors ] red green blue yellow orange ``` The method shown below allows you to [[insert|Functions: insert]] values without hitting a value twice: ``` colors: head colors while [not tail? colors] [ if colors/1 = 'yellow [ colors: insert colors 'blue ] colors: next colors ] ``` This example illustrates that the insert returns the position immediately following the insertion. To [[remove|Functions: remove]] a value without accidentally skipping a value, use the following code: ``` colors: head colors while [not tail? colors] [ either colors/1 = 'blue [ remove colors ][ colors: next colors ] ] ``` Notice that if a removal is done, the [[next|Functions: next]] function is not performed.
The following example finds out who is in charge of a domain using the whois protocol: ``` print read whois://rebol@rs.internic.net ```
The `/any` refinement enables wildcard pattern matching. The question mark `?` and asterisk `()` ''characters act as wildcards for matching any single character or any number of characters respectively''. The `/any` ''refinement can be used in conjunction with'' [[find|Functions: find]] ''with or without'' the `/match` ''refinement''. Examples: ``` str: "abcdefg" print find/any str "c*f" cdefg ``` ``` print find/any str "??d" bcdefg ``` ``` email-list: [ mack@rebol.dom judy@somesite.dom jack@rebol.dom biff@rebol.dom jenn@somesite.dom ] foreach email email-list [ if find/any email *@rebol.dom [print email] ] mack@rebol.dom jack@rebol.dombiff@rebol.dom ``` The next example uses the `/match` refinement to attempt to match the pattern to the next part of the series: ``` file-list: [ %rebol.exe %notes.html %setup.html %feedback.r %nntp.r %rebdoc.r %rebol.r %user.r ] foreach file file-list [ if find/match/any file %reb*.r [print file] ] rebdoc.rrebol.r ``` If either of the wildcard characters are part of what is to be matched, substitute wildcard characters can be provided using the `/with` refinement.
To help speed typing of long words and file names, the REBOL console has word and file name completion. After typing a few letters of a word, press the tab key. If the letters uniquely identify the word, the rest of the word is displayed. For example, typing: ``` >> sq ``` then pressing tab results in: ``` >> square-root ``` If the letters do not uniquely identify the word, you can press tab again to get a list of choices. For example, typing: ``` >> so ``` then pressing tab twice results in: ``` >> sort source ``` so and you can type the rest of the word or enough of it to be unique. Completion works for all words, including user-defined words. It also works for files when they are preceded by a percent sign. ``` >> print read %r ``` Pressing tab might produce: ``` >> print read %rebol.r ``` depending on your current directory.
Words are used in two ways: as ''symbols'' or as ''variables''. In the following block, words are used as symbols for colors. ``` [red green blue] ``` In the following line: ``` print second [red green blue] green ``` the words have no meaning other than their use as names for colors. All words used within blocks serve as symbols until they are evaluated. When a word is evaluated, it is used as a variable. In the previous example, the words [[print|Functions: print]] and [[second|Functions: second]] are variables that hold native functions which perform the required processing. A word can be written in four ways to indicate how it is to be treated, as shown in `[bad-link:concepts/word.txt]` Formats. |''Notation'' |''Definition'' |''Notes''|h |`word` |Get the natural value of the word. |If the value is a function, evaluate it, otherwise return it.| |`word:` |Set the word to a value. |We do not use = for assignment!| |`:word` |Get the value of a word without evaluating it. |Useful for getting the value of a function.| |`'word` |Use the word as a symbol. |We treat it as is and do not evaluate it.| |`/word` |Use the word as a refinement symbol. |For functions, objects, file-paths, special fields.|
Words are used for symbols and variable names. They are formed from a non-numeric character followed by alphabetic characters: ``` print show next image on off true false one none good1 ``` They can include hyphens and other special characters: ``` + - ` * ! ~ & ? | ``` So, you can make words like: ``` number? time? date! image-files l'image ++ -- == +- ***** *new-line* ``` Words are not case sensitive, but casing is preserved: ``` state = State = STATE ``` The end of a word is marked by a white-space character, end of text or one of the characters: ``` ] ) / ``` More on words can be found in the next section, [[Code: Words and variables|Guide: Code: Words and variables]].
If a word is not a keyword (listed above), and it is not a literal word or refinement word, then it is assumed to be a variable. This is also true for paths, such as object fields, uses as variables. Variables can hold: * Repeat range integers (min and max counts) * Match values (strings, blocks, and other values) * Input series index positions * Paren evaluation blocks (productions) Words are not allowed to hold keywords. Within the parse dialect, word notation has a different meaning. Here is a summary: |''Usage'' |''Description''|h |word|look-up the value of a word| |word:|set the variable to the current input position| |:word|set the current input series position from the variable|
REBOL is a symbolic language. You need to think of words as symbols of their own right, not just as variables, keywords, commands, or functions. Above we wrote the line: ``` actions: [split join copy] ``` This block is not evaluated, so the words split, join, and copy are symbols. We might use it in code like: ``` action: 'join ... if find actions action [do something] ``` A lot more will be said about words as symbols, because they are widely used in REBOL for creating dialects (domain specific languages).
Variables are words with values associated within a specific context, such as in an object, module, or a function. To set the value of a variable, this notation is used: ``` size: 12 ``` You can now write this line to get the value of the variable: ``` print size 12 ``` A lot more needs to be explained about variables, and it will be discussed later in this guide as we explain [[Code: Defining functions|Guide: Code: Defining functions]] and [[Data: Objects provide context|Guide: Data: Objects provide context]]. <<< Why a colon? We use colon for setting variables, not an equal `=` operator because it allows the language to easily recognize and manipulate variable definitions. This is very important to the language, and the reasons will become clear as you learn more. <<<
Words are also used for ''refinements''. A refinement! specifies a variation, option, or clarification in meaning. It is an abstraction that applies to functions, objects, indexing, file paths, and other data types. For example, the copy function normally copies it's entire input: ``` print copy "example string" ``` But, when the /part refinement is provided, a partial copy is made: ``` print copy/part "example string" 7 ``` In this way, we don't need another function for partial copies. We can have a single copy function with a number of refinements. This makes it easier to remember. Examples of refinements for objects are similar. They are used to select fields of an object. You will be seeing this a lot. ``` print system/options/home %/users/carl ``` That example finds the home field in the options object of the system object. <<< Why slash and not dot? In REBOL, we write: ``` system/options/home ``` not: ``` system.options.home ``` We will admit that this was a difficult design decision. We did not make it lightly. On the surface, the slash `/` was used for refinements because they are similar to file directory paths. ``` file-dir: %user/data names: load file-dir/names.r ``` Also, slash refinements do a lot more than dot (selectors) in other languages, as can be seen in this line: ``` load/header/only system/options/home/database.r ``` Here, the load is being refined, and an object path is both accessed and filename appended. As you can see, we also did not use dot because we didn't want to lose the ability to specify file names as refinements (with suffixes that use dot, like that shown above). <<< Of course, this is a good time to remind you that ''all words and values in REBOL must be separated by spaces''. So, divide is: ``` m: n / 2 ``` but: ``` m: n/2 ``` is an indexing refinement to `n` (assuming it is a series).
To write a [[binary!|Datatypes: Binary!]] file, use the write function. This line will write the data read in the above section to a new file, or it will overwrite the file if it already exists: ``` write %new-image.jpg data ``` The data must be [[binary!|Datatypes: Binary!]] to be written as binary. So, to copy an image file, you can simply write: ``` write %new-image.jpg read %image.jpg ``` Of course, keep in mind that for large files, a different technique should be used to reduce memory requirements.
To write a block where each value of the block is placed on a separate line: ``` write/lines %data.txt doc ``` If you use the read function shown above with the `/lines` refinement, then each string is written as a line. However, if the block contains other values, the form function will be used to convert them to a string first. Here's a simple example that removes all blank lines from a file: ``` data: read/lines %data.txt remove-each line data [empty? line] write/lines %data-small.txt data ``` Note that if a line contains only spaces (or tabs) it is not empty, and will not be removed.
To write a binary file such as an image, a program, a sound, use `write/binary`: ``` write/binary %file.bin data ``` The `write/binary` function creates the file if it does not exist or overwrites the file if it already exists. No conversion of any type is done to the file. To write a binary file a piece at a time, use the open function as described in the [[ports|Concepts: Ports]] Chapter.
Files can also be written to a network. For example, to write a text file to a network using FTP, use: ``` write ftp://ftp.domain.com/file.txt "save this text" ``` The file can be read locally and written to the net with a line such as: ``` write ftp://ftp.domain.com/file.txt read %file.txt ``` In the process, the file has its line termination converted to the standard CRLF format. To write a binary file, such as an image, to the network, use the following lines of code: ``` write/binary ftp://ftp.domain.com/file.txt/image.jpg read/binary %image.jpg ``` Refer to the chapter on `[bad-link:concepts/network.txt]` Protocols for more information and examples of accessing files from networks.
When writing strings, the [[write|Functions: write]] function automatically detects that they are strings, and preforms the necessary conversion to UTF-8 format. No `/string` refinement is needed. So, to write the above notes string: ``` write %notes2.txt notes ``` The line terminators will also be converted to the local format. On PCs, it will be CRLF, but on Linux and other systems it will be LF. So, you can easily use REBOL to convert a text file from one line termination format to the format used on your local system: ``` write %notes-local.txt read/string %notes.txt ``` Note that this is slightly different from REBOL 2, because of the change that makes file reads binary by default. The `/string` refinement must be used here.
To write a local text file, use the following line of code: ``` write %file.txt "sample text here" ``` This writes the entire text to the file. If a file contains `newline` characters, they will be converted to those used by your local file system. This allows you to deal with files in a consistent `manner`, but write them out using the convention that is standard to your file system. For instance, the following line converts any text file from one line termination format (UNIX, Macintosh, PC, Amiga) to that which is used by your local system: ``` write %newfile.txt read %file.txt ``` The above line reads the entire file while converting its line termination to the REBOL standard, then writes the file converting it to the local operating system format. To append to the end of a file, use the `/append` refinement: ``` write/append %file.txt "more text" ``` A file can also be written from separate lines that are stored in a block. ``` write/lines %file.txt lines ``` To write a file a piece at a time, use the [[open|Functions: open]] function as described in the [[ports|Concepts: Ports]] Chapter.