├── README ├── core ├── TabAllTags.tiddler ├── TabTags.tiddler ├── MptwUpgradeURL.pub ├── HideWhenPlugin.js.meta ├── NewHerePlugin.js.meta ├── ToggleTagPlugin.js.meta ├── CloseOnCancelPlugin.js.meta ├── LessBackupsPlugin.js.meta ├── MptwCollapsePlugin.js.meta ├── MptwConfigPlugin.js.meta ├── NewMeansNewPlugin.js.meta ├── PrettyDatesPlugin.js.meta ├── QuickOpenTagPlugin.js.meta ├── RenameTagsPlugin.js.meta ├── SelectThemePlugin.js.meta ├── TagglyTaggingPlugin.js.meta ├── ExtendTagButtonPlugin.js.meta ├── InstantTimestampPlugin.js.meta ├── SaveCloseTiddlerPlugin.js.meta ├── TabMore.tiddler ├── MPTW.tiddler ├── NewHerePlugin.js ├── CloseOnCancelPlugin.js ├── ExtendTagButtonPlugin.js ├── MptwCollapsePlugin.js ├── SaveCloseTiddlerPlugin.js ├── PrettyDatesPlugin.js ├── MptwConfigPlugin.js ├── NewMeansNewPlugin.js ├── RenameTagsPlugin.js ├── InstantTimestampPlugin.js ├── LessBackupsPlugin.js ├── HideWhenPlugin.js ├── ToggleTagPlugin.js ├── SelectThemePlugin.js ├── QuickOpenTagPlugin.js └── TagglyTaggingPlugin.js ├── .gitignore ├── misc └── MptwUpgrade.pub ├── empties └── fetch.rb ├── themes ├── MptwStandardTheme.theme ├── MptwRoundTheme.theme ├── MptwTrimTheme.theme └── MptwTheme.theme ├── palettes ├── MptwBlack.palette ├── MptwBlue.palette ├── MptwGreen.palette ├── MptwRed.palette ├── MptwSmoke.palette └── MptwTeal.palette ├── sandbox ├── MGTDBlue.palette ├── MGTDRed.palette ├── MGTDGreen.palette ├── MGTDSmoke.palette ├── MGTDTeal.palette ├── SelectPalettePlugin.js └── RenameTagsPlugin.js ├── update_site.rb ├── noupgrade └── MptwUserConfigPlugin.js └── r4tw.rb /README: -------------------------------------------------------------------------------- 1 | See http://mptw.tiddlyspot.com/ 2 | -------------------------------------------------------------------------------- /core/TabAllTags.tiddler: -------------------------------------------------------------------------------- 1 | <> 2 | -------------------------------------------------------------------------------- /core/TabTags.tiddler: -------------------------------------------------------------------------------- 1 | <> 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | upload 2 | *.js.meta 3 | core/*.js.meta 4 | 5 | -------------------------------------------------------------------------------- /misc/MptwUpgrade.pub: -------------------------------------------------------------------------------- 1 | URL: http://mptw.tiddlyspot.com/empty_nolayout.html 2 | -------------------------------------------------------------------------------- /core/MptwUpgradeURL.pub: -------------------------------------------------------------------------------- 1 | For upgrading. See [[ImportTiddlers]]. 2 | URL: http://mptw.tiddlyspot.com/upgrade.html 3 | -------------------------------------------------------------------------------- /core/HideWhenPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271027 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/NewHerePlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271022 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/ToggleTagPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271026 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/CloseOnCancelPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271027 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/LessBackupsPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271027 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/MptwCollapsePlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271021 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/MptwConfigPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271022 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/NewMeansNewPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271023 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/PrettyDatesPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271024 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/QuickOpenTagPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271024 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/RenameTagsPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271025 2 | modified: 201306162220 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/SelectThemePlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271025 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/TagglyTaggingPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271026 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/ExtendTagButtonPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271027 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/InstantTimestampPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271019 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /core/SaveCloseTiddlerPlugin.js.meta: -------------------------------------------------------------------------------- 1 | created: 201106271025 2 | modified: 201106271033 3 | modifier: MPTW 4 | tags: systemConfig 5 | -------------------------------------------------------------------------------- /empties/fetch.rb: -------------------------------------------------------------------------------- 1 | 2 | require '../r4tw.rb' 3 | 4 | make_tw { 5 | source_file 'http://www.tiddlywiki.com/empty.html' 6 | to_file 'empty.html' 7 | } 8 | -------------------------------------------------------------------------------- /core/TabMore.tiddler: -------------------------------------------------------------------------------- 1 | <> 2 | -------------------------------------------------------------------------------- /themes/MptwStandardTheme.theme: -------------------------------------------------------------------------------- 1 | |Name|MptwStandard| 2 | |Description|Mptw Theme with the default TiddlyWiki PageLayout and Styles| 3 | |ViewTemplate|MptwTheme##ViewTemplate| 4 | |EditTemplate|MptwTheme##EditTemplate| 5 | -------------------------------------------------------------------------------- /core/MPTW.tiddler: -------------------------------------------------------------------------------- 1 | MPTW is a distribution or edition of TiddlyWiki that includes a standard TiddlyWiki core packaged with some plugins designed to improve usability and provide a better way to organise your information. For more information see http://mptw.tiddlyspot.com/. 2 | -------------------------------------------------------------------------------- /palettes/MptwBlack.palette: -------------------------------------------------------------------------------- 1 | Name: MptwBlack 2 | Background: #000 3 | Foreground: #fff 4 | PrimaryPale: #333 5 | PrimaryLight: #555 6 | PrimaryMid: #888 7 | PrimaryDark: #aaa 8 | SecondaryPale: #111 9 | SecondaryLight: #222 10 | SecondaryMid: #555 11 | SecondaryDark: #888 12 | TertiaryPale: #222 13 | TertiaryLight: #666 14 | TertiaryMid: #888 15 | TertiaryDark: #aaa 16 | Error: #300 17 | 18 | -------------------------------------------------------------------------------- /palettes/MptwBlue.palette: -------------------------------------------------------------------------------- 1 | Name: MptwBlue 2 | Background: #fff 3 | Foreground: #000 4 | PrimaryPale: #cdf 5 | PrimaryLight: #57c 6 | PrimaryMid: #114 7 | PrimaryDark: #012 8 | SecondaryPale: #ffc 9 | SecondaryLight: #fe8 10 | SecondaryMid: #db4 11 | SecondaryDark: #841 12 | TertiaryPale: #eee 13 | TertiaryLight: #ccc 14 | TertiaryMid: #999 15 | TertiaryDark: #666 16 | Error: #f88 17 | 18 | -------------------------------------------------------------------------------- /palettes/MptwGreen.palette: -------------------------------------------------------------------------------- 1 | Name: MptwGreen 2 | Background: #fff 3 | Foreground: #000 4 | PrimaryPale: #9b9 5 | PrimaryLight: #385 6 | PrimaryMid: #031 7 | PrimaryDark: #020 8 | SecondaryPale: #ffc 9 | SecondaryLight: #fe8 10 | SecondaryMid: #db4 11 | SecondaryDark: #841 12 | TertiaryPale: #eee 13 | TertiaryLight: #ccc 14 | TertiaryMid: #999 15 | TertiaryDark: #666 16 | Error: #f88 17 | 18 | -------------------------------------------------------------------------------- /palettes/MptwRed.palette: -------------------------------------------------------------------------------- 1 | Name: MptwRed 2 | Background: #fff 3 | Foreground: #000 4 | PrimaryPale: #eaa 5 | PrimaryLight: #c55 6 | PrimaryMid: #711 7 | PrimaryDark: #500 8 | SecondaryPale: #ffc 9 | SecondaryLight: #fe8 10 | SecondaryMid: #db4 11 | SecondaryDark: #841 12 | TertiaryPale: #eee 13 | TertiaryLight: #ccc 14 | TertiaryMid: #999 15 | TertiaryDark: #666 16 | Error: #f88 17 | 18 | -------------------------------------------------------------------------------- /palettes/MptwSmoke.palette: -------------------------------------------------------------------------------- 1 | Name: MptwSmoke 2 | Background: #fff 3 | Foreground: #000 4 | PrimaryPale: #aaa 5 | PrimaryLight: #777 6 | PrimaryMid: #111 7 | PrimaryDark: #000 8 | SecondaryPale: #ffc 9 | SecondaryLight: #fe8 10 | SecondaryMid: #db4 11 | SecondaryDark: #841 12 | TertiaryPale: #eee 13 | TertiaryLight: #ccc 14 | TertiaryMid: #999 15 | TertiaryDark: #666 16 | Error: #f88 17 | 18 | -------------------------------------------------------------------------------- /palettes/MptwTeal.palette: -------------------------------------------------------------------------------- 1 | Name: MptwTeal 2 | Background: #fff 3 | Foreground: #000 4 | PrimaryPale: #B5D1DF 5 | PrimaryLight: #618FA9 6 | PrimaryMid: #1a3844 7 | PrimaryDark: #000 8 | SecondaryPale: #ffc 9 | SecondaryLight: #fe8 10 | SecondaryMid: #db4 11 | SecondaryDark: #841 12 | TertiaryPale: #f8f8f8 13 | TertiaryLight: #bbb 14 | TertiaryMid: #999 15 | TertiaryDark: #888 16 | Error: #f88 17 | -------------------------------------------------------------------------------- /sandbox/MGTDBlue.palette: -------------------------------------------------------------------------------- 1 | Name: Blue 2 | Background: #fff 3 | Foreground: #000 4 | PrimaryPale: #cdf 5 | PrimaryLight: #57c 6 | PrimaryMid: #114 7 | PrimaryDark: #012 8 | SecondaryPale: #ffc 9 | SecondaryLight: #fe8 10 | SecondaryMid: #db4 11 | SecondaryDark: #841 12 | TertiaryPale: #eee 13 | TertiaryLight: #ccc 14 | TertiaryMid: #999 15 | TertiaryDark: #666 16 | Error: #f88 17 | 18 | -------------------------------------------------------------------------------- /sandbox/MGTDRed.palette: -------------------------------------------------------------------------------- 1 | Name: Red 2 | Background: #fff 3 | Foreground: #000 4 | PrimaryPale: #fdd 5 | PrimaryLight: #c55 6 | PrimaryMid: #711 7 | PrimaryDark: #500 8 | SecondaryPale: #ffc 9 | SecondaryLight: #fe8 10 | SecondaryMid: #db4 11 | SecondaryDark: #841 12 | TertiaryPale: #eee 13 | TertiaryLight: #ccc 14 | TertiaryMid: #999 15 | TertiaryDark: #666 16 | Error: #f88 17 | 18 | -------------------------------------------------------------------------------- /sandbox/MGTDGreen.palette: -------------------------------------------------------------------------------- 1 | Name: Green 2 | Background: #fff 3 | Foreground: #000 4 | PrimaryPale: #9b9 5 | PrimaryLight: #385 6 | PrimaryMid: #031 7 | PrimaryDark: #020 8 | SecondaryPale: #ffc 9 | SecondaryLight: #fe8 10 | SecondaryMid: #db4 11 | SecondaryDark: #841 12 | TertiaryPale: #eee 13 | TertiaryLight: #ccc 14 | TertiaryMid: #999 15 | TertiaryDark: #666 16 | Error: #f88 17 | 18 | -------------------------------------------------------------------------------- /sandbox/MGTDSmoke.palette: -------------------------------------------------------------------------------- 1 | Name: Smoke 2 | Background: #fff 3 | Foreground: #000 4 | PrimaryPale: #aaa 5 | PrimaryLight: #777 6 | PrimaryMid: #111 7 | PrimaryDark: #000 8 | SecondaryPale: #ffc 9 | SecondaryLight: #fe8 10 | SecondaryMid: #db4 11 | SecondaryDark: #841 12 | TertiaryPale: #eee 13 | TertiaryLight: #ccc 14 | TertiaryMid: #999 15 | TertiaryDark: #666 16 | Error: #f88 17 | 18 | -------------------------------------------------------------------------------- /sandbox/MGTDTeal.palette: -------------------------------------------------------------------------------- 1 | Name: Teal 2 | Background: #fff 3 | Foreground: #000 4 | PrimaryPale: #B5D1DF 5 | PrimaryLight: #618FA9 6 | PrimaryMid: #1a3844 7 | PrimaryDark: #000 8 | SecondaryPale: #ffc 9 | SecondaryLight: #fe8 10 | SecondaryMid: #db4 11 | SecondaryDark: #841 12 | TertiaryPale: #f8f8f8 13 | TertiaryLight: #bbb 14 | TertiaryMid: #999 15 | TertiaryDark: #888 16 | Error: #f88 17 | -------------------------------------------------------------------------------- /update_site.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'r4tw' 3 | 4 | require 'build' 5 | 6 | make_tw { 7 | puts "downloading..." 8 | source_file 'http://mptw.tiddlyspot.com/' 9 | puts "updating..." 10 | copy_all_tiddlers_from 'upload/upgrade.html' 11 | puts "setting modifier..." 12 | tiddlers.each { |t| t.fields['modifier'] = 'MPTW' } 13 | puts "writing..." 14 | to_file 'upload/index.html' 15 | puts "done." 16 | } 17 | 18 | -------------------------------------------------------------------------------- /themes/MptwRoundTheme.theme: -------------------------------------------------------------------------------- 1 | |Name|MptwRounded| 2 | |Description|Mptw Theme with some rounded corners (Firefox only)| 3 | |ViewTemplate|MptwTheme##ViewTemplate| 4 | |EditTemplate|MptwTheme##EditTemplate| 5 | |PageTemplate|MptwTheme##PageTemplate| 6 | |StyleSheet|##StyleSheet| 7 | 8 | !StyleSheet 9 | /*{{{*/ 10 | 11 | [[MptwTheme##StyleSheet]] 12 | 13 | .tiddler, 14 | .sliderPanel, 15 | .button, 16 | .tiddlyLink, 17 | .tabContents 18 | { -moz-border-radius: 1em; } 19 | 20 | .tab { 21 | -moz-border-radius-topleft: 0.5em; 22 | -moz-border-radius-topright: 0.5em; 23 | } 24 | #topMenu { 25 | -moz-border-radius-bottomleft: 2em; 26 | -moz-border-radius-bottomright: 2em; 27 | } 28 | 29 | /*}}}*/ 30 | 31 | -------------------------------------------------------------------------------- /core/NewHerePlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | |Name:|NewHerePlugin| 3 | |Description:|Creates the new here and new journal macros| 4 | |Version:|3.0a| 5 | |Date:|27-Jun-2011| 6 | |Source:|http://mptw.tiddlyspot.com/#NewHerePlugin| 7 | |Author:|Simon Baird | 8 | |License|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | ***/ 10 | //{{{ 11 | merge(config.macros, { 12 | newHere: { 13 | handler: function(place,macroName,params,wikifier,paramString,tiddler) { 14 | wikify("<>",place,null,tiddler); 15 | } 16 | }, 17 | newJournalHere: { 18 | handler: function(place,macroName,params,wikifier,paramString,tiddler) { 19 | wikify("<>",place,null,tiddler); 20 | } 21 | } 22 | }); 23 | 24 | //}}} 25 | -------------------------------------------------------------------------------- /core/CloseOnCancelPlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | |Name:|CloseOnCancelPlugin| 3 | |Description:|Closes the tiddler if you click new tiddler then cancel. Default behaviour is to leave it open| 4 | |Version:|3.0.1a| 5 | |Date:|27-Jun-2011| 6 | |Source:|http://mptw.tiddlyspot.com/#CloseOnCancelPlugin| 7 | |Author:|Simon Baird | 8 | |License:|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | ***/ 10 | //{{{ 11 | merge(config.commands.cancelTiddler,{ 12 | 13 | handler_mptw_orig_closeUnsaved: config.commands.cancelTiddler.handler, 14 | 15 | handler: function(event,src,title) { 16 | this.handler_mptw_orig_closeUnsaved(event,src,title); 17 | if (!story.isDirty(title) && !store.tiddlerExists(title) && !store.isShadowTiddler(title)) 18 | story.closeTiddler(title,true); 19 | return false; 20 | } 21 | 22 | }); 23 | 24 | //}}} 25 | -------------------------------------------------------------------------------- /core/ExtendTagButtonPlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | |Name:|ExtentTagButtonPlugin| 3 | |Description:|Adds a New tiddler button in the tag drop down| 4 | |Version:|3.2a| 5 | |Date:|27-Jun-2011| 6 | |Source:|http://mptw.tiddlyspot.com/#ExtendTagButtonPlugin| 7 | |Author:|Simon Baird | 8 | |License|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | ***/ 10 | //{{{ 11 | 12 | window.onClickTag_mptw_orig = window.onClickTag; 13 | window.onClickTag = function(e) { 14 | window.onClickTag_mptw_orig.apply(this,arguments); 15 | var tag = this.getAttribute("tag"); 16 | var title = this.getAttribute("tiddler"); 17 | // Thanks Saq, you're a genius :) 18 | var popup = Popup.stack[Popup.stack.length-1].popup; 19 | createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div"); 20 | wikify("<>",createTiddlyElement(popup,"li")); 21 | return false; 22 | } 23 | 24 | //}}} 25 | -------------------------------------------------------------------------------- /noupgrade/MptwUserConfigPlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | |Description:|A place to put your config tweaks so they aren't overwritten when you upgrade MPTW| 3 | See http://www.tiddlywiki.org/wiki/Configuration_Options for other options you can set. In some cases where there are clashes with other plugins it might help to rename this to zzMptwUserConfigPlugin so it gets executed last. 4 | ***/ 5 | //{{{ 6 | 7 | // example: set your preferred date format 8 | //config.mptwDateFormat = 'MM/0DD/YY'; 9 | //config.mptwJournalFormat = 'Journal MM/0DD/YY'; 10 | 11 | // example: set the theme you want to start with 12 | //config.options.txtTheme = 'MptwRoundTheme'; 13 | 14 | // example: switch off autosave, switch on backups and set a backup folder 15 | //config.options.chkSaveBackups = true; 16 | //config.options.chkAutoSave = false; 17 | //config.options.txtBackupFolder = 'backups'; 18 | 19 | // uncomment to disable 'new means new' functionality for the new journal macro 20 | //config.newMeansNewForJournalsToo = false; 21 | 22 | //}}} 23 | -------------------------------------------------------------------------------- /themes/MptwTrimTheme.theme: -------------------------------------------------------------------------------- 1 | |Name|MptwTrim| 2 | |Description|Mptw Theme with a reduced header to increase useful space| 3 | |ViewTemplate|MptwTheme##ViewTemplate| 4 | |EditTemplate|MptwTheme##EditTemplate| 5 | |StyleSheet|MptwTheme##StyleSheet| 6 | |PageTemplate|##PageTemplate| 7 | 8 | !PageTemplate 9 | 10 | 11 | 12 |
13 | : 14 | 15 |
16 | 23 |
24 |
25 |
26 |
27 | 28 | -------------------------------------------------------------------------------- /core/MptwCollapsePlugin.js: -------------------------------------------------------------------------------- 1 | //{{{ 2 | // Pretty sure this is incomplete and experimental 3 | // TODO: Fix it or remove it. 4 | 5 | (function($){ 6 | 7 | merge(config.macros,{ 8 | mptwCollapse: { 9 | handler: function(place,macroName,params) { 10 | createTiddlyButton(place, params[0] == '+' ? '\u25AD' : '\u25AC', 'collapse/uncollapse', function(){ 11 | $(story.findContainingTiddler(place)).toggleClass('collapsed'); 12 | }); 13 | } 14 | } 15 | }); 16 | 17 | /* this doesn't work unless you have a modified ViewTempate */ 18 | config.shadowTiddlers["MptwCollapsePluginStyles"] = "" 19 | +".collapsed .uncollapsedView { display:none; }" 20 | +".collapsedView { display:none; }" 21 | +".collapsed .collapsedView { display:block; }" 22 | +".tiddler.collapsed { padding-bottom:1em; }" 23 | +".tiddler.collapsed .title { font-size:100%; }" 24 | ; 25 | 26 | store.addNotification("MptwCollapsePluginStyles",refreshStyles); 27 | 28 | })(jQuery); 29 | 30 | //}}} 31 | -------------------------------------------------------------------------------- /core/SaveCloseTiddlerPlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | |Name:|SaveCloseTiddlerPlugin| 3 | |Description:|Provides two extra toolbar commands, saveCloseTiddler and cancelCloseTiddler| 4 | |Version:|3.0a| 5 | |Date:|27-Jun-2011| 6 | |Source:|http://mptw.tiddlyspot.com/#SaveCloseTiddlerPlugin| 7 | |Author:|Simon Baird | 8 | |License:|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | To use these add them to the commands in ToolbarCommands under EditToolbar, 10 | or in the MptwTheme tiddler under EditTemplate. 11 | ***/ 12 | //{{{ 13 | merge(config.commands,{ 14 | 15 | saveCloseTiddler: { 16 | text: 'done/close', 17 | tooltip: 'Save changes to this tiddler and close it', 18 | handler: function(ev,src,title) { 19 | var closeTitle = title; 20 | var newTitle = story.saveTiddler(title,ev.shiftKey); 21 | if (newTitle) 22 | closeTitle = newTitle; 23 | return config.commands.closeTiddler.handler(ev,src,closeTitle); 24 | } 25 | }, 26 | 27 | cancelCloseTiddler: { 28 | text: 'cancel/close', 29 | tooltip: 'Undo changes to this tiddler and close it', 30 | handler: function(ev,src,title) { 31 | // the same as closeTiddler now actually 32 | return config.commands.closeTiddler.handler(ev,src,title); 33 | } 34 | } 35 | 36 | }); 37 | 38 | //}}} 39 | -------------------------------------------------------------------------------- /core/PrettyDatesPlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | |Name:|PrettyDatesPlugin| 3 | |Description:|Provides a new date format ('pppp') that displays times such as '2 days ago'| 4 | |Version:|1.0a| 5 | |Date:|27-Jun-2011| 6 | |Source:|http://mptw.tiddlyspot.com/#PrettyDatesPlugin| 7 | |Author:|Simon Baird | 8 | |License:|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | !!Notes 10 | * If you want to you can rename this plugin. :) Some suggestions: LastUpdatedPlugin, RelativeDatesPlugin, SmartDatesPlugin, SexyDatesPlugin. 11 | * Inspired by http://ejohn.org/files/pretty.js 12 | ***/ 13 | //{{{ 14 | Date.prototype.prettyDate = function() { 15 | var diff = (((new Date()).getTime() - this.getTime()) / 1000); 16 | var day_diff = Math.floor(diff / 86400); 17 | 18 | if (isNaN(day_diff)) return ""; 19 | else if (diff < 0) return "in the future"; 20 | else if (diff < 60) return "just now"; 21 | else if (diff < 120) return "1 minute ago"; 22 | else if (diff < 3600) return Math.floor(diff/60) + " minutes ago"; 23 | else if (diff < 7200) return "1 hour ago"; 24 | else if (diff < 86400) return Math.floor(diff/3600) + " hours ago"; 25 | else if (day_diff == 1) return "Yesterday"; 26 | else if (day_diff < 7) return day_diff + " days ago"; 27 | else if (day_diff < 14) return "a week ago"; 28 | else if (day_diff < 31) return Math.ceil(day_diff/7) + " weeks ago"; 29 | else if (day_diff < 62) return "a month ago"; 30 | else if (day_diff < 365) return "about " + Math.ceil(day_diff/31) + " months ago"; 31 | else if (day_diff < 730) return "a year ago"; 32 | else return Math.ceil(day_diff/365) + " years ago"; 33 | } 34 | 35 | Date.prototype.formatString_orig_mptw = Date.prototype.formatString; 36 | 37 | Date.prototype.formatString = function(template) { 38 | return this.formatString_orig_mptw(template).replace(/pppp/,this.prettyDate()); 39 | } 40 | 41 | // for MPTW. otherwise edit your ViewTemplate as required. 42 | // config.mptwDateFormat = 'pppp (DD/MM/YY)'; 43 | config.mptwDateFormat = 'pppp'; 44 | 45 | //}}} 46 | -------------------------------------------------------------------------------- /core/MptwConfigPlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | |Name:|MptwConfigPlugin| 3 | |Description:|Miscellaneous tweaks used by MPTW| 4 | |Version:|1.0a| 5 | |Date:|27-Jun-2011| 6 | |Source:|http://mptw.tiddlyspot.com/#MptwConfigPlugin| 7 | |Author:|Simon Baird | 8 | |License:|http://mptw.tiddlyspot.com/#MptwConfigPlugin| 9 | !!Note: instead of editing this you should put overrides in MptwUserConfigPlugin 10 | ***/ 11 | //{{{ 12 | var originalReadOnly = readOnly; 13 | var originalShowBackstage = showBackstage; 14 | 15 | config.options.chkHttpReadOnly = false; // means web visitors can experiment with your site by clicking edit 16 | readOnly = false; // needed because the above doesn't work any more post 2.1 (??) 17 | showBackstage = true; // show backstage for same reason 18 | 19 | config.options.chkInsertTabs = true; // tab inserts a tab when editing a tiddler 20 | config.views.wikified.defaultText = ""; // don't need message when a tiddler doesn't exist 21 | config.views.editor.defaultText = ""; // don't need message when creating a new tiddler 22 | 23 | config.options.chkSaveBackups = true; // do save backups 24 | config.options.txtBackupFolder = 'twbackup'; // put backups in a backups folder 25 | 26 | config.options.chkAutoSave = (window.location.protocol == "file:"); // do autosave if we're in local file 27 | 28 | config.mptwVersion = "2.7.4"; 29 | 30 | config.macros.mptwVersion={handler:function(place){wikify(config.mptwVersion,place);}}; 31 | 32 | if (config.options.txtTheme == '') 33 | config.options.txtTheme = 'MptwTheme'; 34 | 35 | // add to default GettingStarted 36 | config.shadowTiddlers.GettingStarted += "\n\nSee also [[MPTW]]."; 37 | 38 | // add select theme and palette controls in default OptionsPanel 39 | config.shadowTiddlers.OptionsPanel = config.shadowTiddlers.OptionsPanel.replace(/(\n\-\-\-\-\nAlso see \[\[AdvancedOptions\]\])/, "{{select{<>\n<>}}}$1"); 40 | 41 | // these are used by ViewTemplate 42 | config.mptwDateFormat = 'DD/MM/YY'; 43 | config.mptwJournalFormat = 'Journal DD/MM/YY'; 44 | 45 | //}}} 46 | -------------------------------------------------------------------------------- /sandbox/SelectPalettePlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | | Name|SelectPalettePlugin| 3 | | Description|Lets you easily change colour palette| 4 | | Version|3.0 ($Rev: 1845 $)| 5 | | Date|$Date: 2007-03-16 15:19:22 +1000 (Fri, 16 Mar 2007) $| 6 | | Source|http://mptw.tiddlyspot.com/#SelectPalettePlugin| 7 | | Author|Simon Baird | 8 | | License|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | /*** 10 | !!Usage: 11 | {{{<<>}}} 12 | <> 13 | 14 | !!WARNING 15 | Will overwrite your ColorPalette tiddler. 16 | ***/ 17 | 18 | //{{{ 19 | 20 | merge(config.macros,{ 21 | 22 | setPalette: { 23 | 24 | handler: function(place,macroName,params,wikifier,paramString,tiddler) { 25 | var paletteName = params[0] ? params[0] : tiddler.title; 26 | createTiddlyButton(place,"apply","Apply this palette",function(e) { 27 | config.macros.selectPalette.updatePalette(tiddler.title); 28 | return false; 29 | }); 30 | } 31 | }, 32 | 33 | selectPalette: { 34 | 35 | handler: function(place,macroName,params,wikifier,paramString,tiddler) { 36 | createTiddlyDropDown(place,this.onPaletteChange,this.getPalettes()); 37 | }, 38 | 39 | getPalettes: function() { 40 | var result = [ 41 | {caption:"-palette-", name:""}, 42 | {caption:"(Default)", name:"(default)"} 43 | ]; 44 | var tagged = store.getTaggedTiddlers("palette","title"); 45 | for(var t=0; t| 8 | |License|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | !!Note: I think this should be in the core 10 | ***/ 11 | //{{{ 12 | 13 | // change this or set config.newMeansNewForJournalsToo it in MptwUuserConfigPlugin 14 | if (config.newMeansNewForJournalsToo == undefined) config.newMeansNewForJournalsToo = true; 15 | 16 | String.prototype.getNextFreeName = function() { 17 | numberRegExp = / \(([0-9]+)\)$/; 18 | var match = numberRegExp.exec(this); 19 | if (match) { 20 | var num = parseInt(match[1]) + 1; 21 | return this.replace(numberRegExp," ("+num+")"); 22 | } 23 | else { 24 | return this + " (1)"; 25 | } 26 | } 27 | 28 | config.macros.newTiddler.checkForUnsaved = function(newName) { 29 | var r = false; 30 | story.forEachTiddler(function(title,element) { 31 | if (title == newName) 32 | r = true; 33 | }); 34 | return r; 35 | } 36 | 37 | config.macros.newTiddler.getName = function(newName) { 38 | while (store.getTiddler(newName) || config.macros.newTiddler.checkForUnsaved(newName)) 39 | newName = newName.getNextFreeName(); 40 | return newName; 41 | } 42 | 43 | 44 | config.macros.newTiddler.onClickNewTiddler = function() 45 | { 46 | var title = this.getAttribute("newTitle"); 47 | if(this.getAttribute("isJournal") == "true") { 48 | title = new Date().formatString(title.trim()); 49 | } 50 | 51 | // ---- these three lines should be the only difference between this and the core onClickNewTiddler 52 | if (config.newMeansNewForJournalsToo || this.getAttribute("isJournal") != "true") 53 | title = config.macros.newTiddler.getName(title); 54 | 55 | var params = this.getAttribute("params"); 56 | var tags = params ? params.split("|") : []; 57 | var focus = this.getAttribute("newFocus"); 58 | var template = this.getAttribute("newTemplate"); 59 | var customFields = this.getAttribute("customFields"); 60 | if(!customFields && !store.isShadowTiddler(title)) 61 | customFields = String.encodeHashMap(config.defaultCustomFields); 62 | story.displayTiddler(null,title,template,false,null,null); 63 | var tiddlerElem = story.getTiddler(title); 64 | if(customFields) 65 | story.addCustomFields(tiddlerElem,customFields); 66 | var text = this.getAttribute("newText"); 67 | if(typeof text == "string") 68 | story.getTiddlerField(title,"text").value = text.format([title]); 69 | for(var t=0;t| 8 | |License|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | Rename a tag and you will be prompted to rename it in all its tagged tiddlers. 10 | ***/ 11 | //{{{ 12 | config.renameTags = { 13 | 14 | prompts: { 15 | rename: "Rename the tag '%0' to '%1' in %2 tiddler%3?", 16 | remove: "Remove the tag '%0' from %1 tiddler%2?" 17 | }, 18 | 19 | removeTag: function(tag,tiddlers) { 20 | store.suspendNotifications(); 21 | for (var i=0;i 0) { 48 | // then we are renaming a tag 49 | if (confirm(config.renameTags.prompts.rename.format([title,newTitle,tagged.length,tagged.length>1?"s":""]))) 50 | config.renameTags.renameTag(title,newTitle,tagged); 51 | 52 | if (!this.tiddlerExists(title) && newBody == "") 53 | // dont create unwanted tiddler 54 | return null; 55 | } 56 | } 57 | return this.saveTiddler_orig_renameTags(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created,creator); 58 | }, 59 | 60 | removeTiddler_orig_renameTags: TiddlyWiki.prototype.removeTiddler, 61 | 62 | removeTiddler: function(title) { 63 | var tagged = this.getTaggedTiddlers(title); 64 | if (tagged.length > 0) 65 | if (confirm(config.renameTags.prompts.remove.format([title,tagged.length,tagged.length>1?"s":""]))) 66 | config.renameTags.removeTag(title,tagged); 67 | return this.removeTiddler_orig_renameTags(title); 68 | } 69 | 70 | }, 71 | 72 | init: function() { 73 | merge(TiddlyWiki.prototype,this.storeMethods); 74 | } 75 | } 76 | 77 | config.renameTags.init(); 78 | 79 | //}}} 80 | -------------------------------------------------------------------------------- /core/InstantTimestampPlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | |Name:|InstantTimestampPlugin| 3 | |Description:|A handy way to insert timestamps in your tiddler content| 4 | |Version:|1.0.10a| 5 | |Date:|27-Jun-2011| 6 | |Source:|http://mptw.tiddlyspot.com/#InstantTimestampPlugin| 7 | |Author:|Simon Baird | 8 | |License:|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | !!Usage 10 | If you enter {ts} in your tiddler content (without the spaces) it will be replaced with a timestamp when you save the tiddler. Full list of formats: 11 | * {ts} or {t} -> timestamp 12 | * {ds} or {d} -> datestamp 13 | * !ts or !t at start of line -> !!timestamp 14 | * !ds or !d at start of line -> !!datestamp 15 | (I added the extra ! since that's how I like it. Remove it from translations below if required) 16 | !!Notes 17 | * Change the timeFormat and dateFormat below to suit your preference. 18 | * See also http://mptw2.tiddlyspot.com/#AutoCorrectPlugin 19 | * You could invent other translations and add them to the translations array below. 20 | ***/ 21 | //{{{ 22 | 23 | config.InstantTimestamp = { 24 | 25 | // adjust to suit 26 | timeFormat: 'DD/0MM/YY 0hh:0mm', 27 | dateFormat: 'DD/0MM/YY', 28 | 29 | translations: [ 30 | [/^!ts?$/img, "'!!{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"], 31 | [/^!ds?$/img, "'!!{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"], 32 | 33 | // thanks Adapted Cat 34 | [/\{ts?\}(?!\}\})/ig,"'{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"], 35 | [/\{ds?\}(?!\}\})/ig,"'{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"] 36 | 37 | ], 38 | 39 | excludeTags: [ 40 | "noAutoCorrect", 41 | "noTimestamp", 42 | "html", 43 | "CSS", 44 | "css", 45 | "systemConfig", 46 | "systemConfigDisabled", 47 | "zsystemConfig", 48 | "Plugins", 49 | "Plugin", 50 | "plugins", 51 | "plugin", 52 | "javascript", 53 | "code", 54 | "systemTheme", 55 | "systemPalette" 56 | ], 57 | 58 | excludeTiddlers: [ 59 | "StyleSheet", 60 | "StyleSheetLayout", 61 | "StyleSheetColors", 62 | "StyleSheetPrint" 63 | // more? 64 | ] 65 | 66 | }; 67 | 68 | TiddlyWiki.prototype.saveTiddler_mptw_instanttimestamp = TiddlyWiki.prototype.saveTiddler; 69 | TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) { 70 | 71 | tags = tags ? tags : []; // just in case tags is null 72 | tags = (typeof(tags) == "string") ? tags.readBracketedList() : tags; 73 | var conf = config.InstantTimestamp; 74 | 75 | if ( !tags.containsAny(conf.excludeTags) && !conf.excludeTiddlers.contains(newTitle) ) { 76 | 77 | var now = new Date(); 78 | var trans = conf.translations; 79 | for (var i=0;i expiry) 79 | return specialBackupPath; 80 | } 81 | } 82 | 83 | // hijack the core function 84 | window.getBackupPath_mptw_orig = window.getBackupPath; 85 | window.getBackupPath = function(localPath) { 86 | return getSpecialBackupPath(getBackupPath_mptw_orig(localPath)); 87 | } 88 | 89 | //}}} 90 | -------------------------------------------------------------------------------- /core/HideWhenPlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | |Name:|HideWhenPlugin| 3 | |Description:|Allows conditional inclusion/exclusion in templates| 4 | |Version:|3.2a| 5 | |Date:|27-Jun-2011| 6 | |Source:|http://mptw.tiddlyspot.com/#HideWhenPlugin| 7 | |Author:|Simon Baird | 8 | |License:|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | For use in ViewTemplate and EditTemplate. Example usage: 10 | {{{
[[TaskToolbar]]
}}} 11 | {{{
}}} 12 | 13 | Warning: the showWhen and hideWhen macros will blindly eval paramString. 14 | This could be used to execute harmful javascript from a tiddler. 15 | 16 | (TODO: Make some effort to sanitize paramString. Perhaps disallow the equals sign?) 17 | ***/ 18 | //{{{ 19 | 20 | window.hideWhenLastTest = false; 21 | 22 | window.removeElementWhen = function(test,place) { 23 | window.hideWhenLastTest = test; 24 | if (test) { 25 | jQuery(place).empty() 26 | place.parentNode.removeChild(place); 27 | } 28 | }; 29 | 30 | merge(config.macros,{ 31 | 32 | hideWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) { 33 | removeElementWhen( eval(paramString), place ); 34 | }}, 35 | 36 | showWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) { 37 | removeElementWhen( !eval(paramString), place ); 38 | }}, 39 | 40 | hideWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) { 41 | removeElementWhen( tiddler.tags.containsAll(params), place ); 42 | }}, 43 | 44 | showWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) { 45 | removeElementWhen( !tiddler.tags.containsAll(params), place ); 46 | }}, 47 | 48 | hideWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) { 49 | removeElementWhen( tiddler.tags.containsAny(params), place ); 50 | }}, 51 | 52 | showWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) { 53 | removeElementWhen( !tiddler.tags.containsAny(params), place ); 54 | }}, 55 | 56 | hideWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) { 57 | removeElementWhen( tiddler.tags.containsAll(params), place ); 58 | }}, 59 | 60 | showWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) { 61 | removeElementWhen( !tiddler.tags.containsAll(params), place ); 62 | }}, 63 | 64 | hideWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) { 65 | removeElementWhen( store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0]), place ); 66 | }}, 67 | 68 | showWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) { 69 | removeElementWhen( !(store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0])), place ); 70 | }}, 71 | 72 | hideWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) { 73 | removeElementWhen( tiddler.title == params[0], place ); 74 | }}, 75 | 76 | showWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) { 77 | removeElementWhen( tiddler.title != params[0], place ); 78 | }}, 79 | 80 | 'else': { handler: function(place,macroName,params,wikifier,paramString,tiddler) { 81 | removeElementWhen( !window.hideWhenLastTest, place ); 82 | }} 83 | 84 | }); 85 | 86 | //}}} 87 | -------------------------------------------------------------------------------- /core/ToggleTagPlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | |Name:|ToggleTagPlugin| 3 | |Description:|Makes a checkbox which toggles a tag in a tiddler| 4 | |Version:|3.1.0a| 5 | |Date:|27-Jun-2011| 6 | |Source:|http://mptw.tiddlyspot.com/#ToggleTagPlugin| 7 | |Author:|Simon Baird | 8 | |License:|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | !!Usage 10 | {{{<>}}} 11 | * TagName - the tag to be toggled, default value "checked" 12 | * TiddlerName - the tiddler to toggle the tag in, default value the current tiddler 13 | * LabelText - the text (gets wikified) to put next to the check box, default value is '{{{[[TagName]]}}}' or '{{{[[TagName]] [[TiddlerName]]}}}' 14 | (If a parameter is '.' then the default will be used) 15 | * TouchMod flag - if non empty then touch the tiddlers mod date. Note, can set config.toggleTagAlwaysTouchModDate to always touch mod date 16 | !!Examples 17 | |Code|Description|Example|h 18 | |{{{<>}}}|Toggles the default tag (checked) in this tiddler|<>| 19 | |{{{<>}}}|Toggles the TagName tag in this tiddler|<>| 20 | |{{{<>}}}|Toggles the TagName tag in the TiddlerName tiddler|<>| 21 | |{{{<>}}}|Same but with custom label|<>| 22 | |{{{<>}}}|dot means use default value|<>| 23 | !!Notes 24 | * If TiddlerName doesn't exist it will be silently created 25 | * Set label to '-' to specify no label 26 | * See also http://mgtd-alpha.tiddlyspot.com/#ToggleTag2 27 | !!Known issues 28 | * Doesn't smoothly handle the case where you toggle a tag in a tiddler that is current open for editing 29 | * Should convert to use named params 30 | ***/ 31 | //{{{ 32 | 33 | if (config.toggleTagAlwaysTouchModDate == undefined) config.toggleTagAlwaysTouchModDate = false; 34 | 35 | merge(config.macros,{ 36 | 37 | toggleTag: { 38 | 39 | createIfRequired: true, 40 | shortLabel: "[[%0]]", 41 | longLabel: "[[%0]] [[%1]]", 42 | 43 | handler: function(place,macroName,params,wikifier,paramString,tiddler) { 44 | var tiddlerTitle = tiddler ? tiddler.title : ''; 45 | var tag = (params[0] && params[0] != '.') ? params[0] : "checked"; 46 | var title = (params[1] && params[1] != '.') ? params[1] : tiddlerTitle; 47 | var defaultLabel = (title == tiddlerTitle ? this.shortLabel : this.longLabel); 48 | var label = (params[2] && params[2] != '.') ? params[2] : defaultLabel; 49 | var touchMod = (params[3] && params[3] != '.') ? params[3] : ""; 50 | label = (label == '-' ? '' : label); // dash means no label 51 | var theTiddler = (title == tiddlerTitle ? tiddler : store.getTiddler(title)); 52 | var cb = createTiddlyCheckbox(place, label.format([tag,title]), theTiddler && theTiddler.isTagged(tag), function(e) { 53 | if (!store.tiddlerExists(title)) { 54 | if (config.macros.toggleTag.createIfRequired) { 55 | var content = store.getTiddlerText(title); // just in case it's a shadow 56 | store.saveTiddler(title,title,content?content:"",config.options.txtUserName,new Date(),null); 57 | } 58 | else 59 | return false; 60 | } 61 | if ((touchMod != "" || config.toggleTagAlwaysTouchModDate) && theTiddler) 62 | theTiddler.modified = new Date(); 63 | store.setTiddlerTag(title,this.checked,tag); 64 | return true; 65 | }); 66 | } 67 | } 68 | }); 69 | 70 | //}}} 71 | 72 | -------------------------------------------------------------------------------- /sandbox/RenameTagsPlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | | Name:|RenameTagsPlugin| 3 | | Description:|Allows you to easily rename or delete tags across multiple tiddlers| 4 | | Version:|3.0 ($Rev: 1845 $)| 5 | | Date:|$Date: 2007-03-16 15:19:22 +1000 (Fri, 16 Mar 2007) $| 6 | | Source:|http://mptw.tiddlyspot.com/#RenameTagsPlugin| 7 | | Author:|Simon Baird | 8 | | License|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | Rename a tag and you will be prompted to rename it in all its tagged tiddlers. 10 | ***/ 11 | //{{{ 12 | config.renameTags = { 13 | 14 | prompts: { 15 | rename: "Rename the tag '%0' to '%1' in %2 tiddler%3?", 16 | remove: "Remove the tag '%0' from %1 tiddler%2?", 17 | update: "Rename links to '%0' to '%1' in %2 tiddler%3?" 18 | }, 19 | 20 | removeTag: function(tag,tiddlers) { 21 | store.suspendNotifications(); 22 | for (var i=0;i 0) { 66 | // renaming a tag 67 | if (confirm(config.renameTags.prompts.rename.format([title,newTitle,tagged.length,tagged.length>1?"s":""]))) { 68 | config.renameTags.renameTag(title,newTitle,tagged); 69 | } 70 | } 71 | 72 | if (refs.length > 0) { 73 | // renaming something that is referenced elsewhere 74 | if (confirm(config.renameTags.prompts.update.format([title,newTitle,refs.length,refs.length>1?"s":""]))) { 75 | config.renameTags.renameRefs(title,newTitle,refs); 76 | } 77 | } 78 | 79 | if (!this.tiddlerExists(title) && newBody == "") { 80 | // dont create unwanted tiddler 81 | return null; 82 | } 83 | 84 | } 85 | return this.saveTiddler_orig_renameTags(title,newTitle,newBody,modifier,modified,tags,fields); 86 | }, 87 | 88 | removeTiddler_orig_renameTags: TiddlyWiki.prototype.removeTiddler, 89 | 90 | removeTiddler: function(title) { 91 | var tagged = this.getTaggedTiddlers(title); 92 | if (tagged.length > 0) 93 | if (confirm(config.renameTags.prompts.remove.format([title,tagged.length,tagged.length>1?"s":""]))) 94 | config.renameTags.removeTag(title,tagged); 95 | return this.removeTiddler_orig_renameTags(title); 96 | } 97 | 98 | }, 99 | 100 | init: function() { 101 | merge(TiddlyWiki.prototype,this.storeMethods); 102 | } 103 | } 104 | 105 | config.renameTags.init(); 106 | 107 | //}}} 108 | 109 | -------------------------------------------------------------------------------- /core/SelectThemePlugin.js: -------------------------------------------------------------------------------- 1 | /*** 2 | |Name:|SelectThemePlugin| 3 | |Description:|Lets you easily switch theme and palette| 4 | |Version:|1.0.1a| 5 | |Date:|27-Jun-2011| 6 | |Source:|http://mptw.tiddlyspot.com/#SelectThemePlugin| 7 | |Author:|Simon Baird | 8 | |License:|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | !Notes 10 | * Borrows largely from ThemeSwitcherPlugin by Martin Budden http://www.martinswiki.com/#ThemeSwitcherPlugin 11 | * Theme is cookie based. But set a default by setting config.options.txtTheme in MptwConfigPlugin (for example) 12 | * Palette is not cookie based. It actually overwrites your ColorPalette tiddler when you select a palette, so beware. 13 | !Usage 14 | * {{{<>}}} makes a dropdown selector 15 | * {{{<>}}} makes a dropdown selector 16 | * {{{<>}}} applies the current tiddler as a theme 17 | * {{{<>}}} applies the current tiddler as a palette 18 | * {{{<>}}} applies TiddlerName as a theme 19 | * {{{<>}}} applies TiddlerName as a palette 20 | ***/ 21 | //{{{ 22 | 23 | config.macros.selectTheme = { 24 | label: { 25 | selectTheme:"select theme", 26 | selectPalette:"select palette" 27 | }, 28 | prompt: { 29 | selectTheme:"Select the current theme", 30 | selectPalette:"Select the current palette" 31 | }, 32 | tags: { 33 | selectTheme:'systemTheme', 34 | selectPalette:'systemPalette' 35 | } 36 | }; 37 | 38 | config.macros.selectTheme.handler = function(place,macroName) 39 | { 40 | var btn = createTiddlyButton(place,this.label[macroName],this.prompt[macroName],this.onClick); 41 | // want to handle palettes and themes with same code. use mode attribute to distinguish 42 | btn.setAttribute('mode',macroName); 43 | }; 44 | 45 | config.macros.selectTheme.onClick = function(ev) 46 | { 47 | var e = ev ? ev : window.event; 48 | var popup = Popup.create(this); 49 | var mode = this.getAttribute('mode'); 50 | var tiddlers = store.getTaggedTiddlers(config.macros.selectTheme.tags[mode]); 51 | // for default 52 | if (mode == "selectPalette") { 53 | var btn = createTiddlyButton(createTiddlyElement(popup,'li'),"(default)","default color palette",config.macros.selectTheme.onClickTheme); 54 | btn.setAttribute('theme',"(default)"); 55 | btn.setAttribute('mode',mode); 56 | } 57 | for(var i=0; i| 8 | |License:|http://mptw.tiddlyspot.com/#TheBSDLicense| 9 | ***/ 10 | //{{{ 11 | config.quickOpenTag = { 12 | 13 | dropdownChar: (document.all ? "\u25bc" : "\u25be"), // the little one doesn't work in IE? 14 | 15 | createTagButton: function(place,tag,excludeTiddler) { 16 | // little hack so we can do this: <> 17 | var splitTag = tag.split("|"); 18 | var pretty = tag; 19 | if (splitTag.length == 2) { 20 | tag = splitTag[1]; 21 | pretty = splitTag[0]; 22 | } 23 | 24 | var sp = createTiddlyElement(place,"span",null,"quickopentag"); 25 | createTiddlyText(createTiddlyLink(sp,tag,false),pretty); 26 | 27 | var theTag = createTiddlyButton(sp,config.quickOpenTag.dropdownChar, 28 | config.views.wikified.tag.tooltip.format([tag]),onClickTag); 29 | theTag.setAttribute("tag",tag); 30 | if (excludeTiddler) 31 | theTag.setAttribute("tiddler",excludeTiddler); 32 | return(theTag); 33 | }, 34 | 35 | miniTagHandler: function(place,macroName,params,wikifier,paramString,tiddler) { 36 | var tagged = store.getTaggedTiddlers(tiddler.title); 37 | if (tagged.length > 0) { 38 | var theTag = createTiddlyButton(place,config.quickOpenTag.dropdownChar, 39 | config.views.wikified.tag.tooltip.format([tiddler.title]),onClickTag); 40 | theTag.setAttribute("tag",tiddler.title); 41 | theTag.className = "miniTag"; 42 | } 43 | }, 44 | 45 | allTagsHandler: function(place,macroName,params) { 46 | var tags = store.getTags(params[0]); 47 | var filter = params[1]; // new feature 48 | var ul = createTiddlyElement(place,"ul"); 49 | if(tags.length == 0) 50 | createTiddlyElement(ul,"li",null,"listTitle",this.noTags); 51 | for(var t=0; t 12 |
13 |
14 |   15 | 16 |
17 |
18 |   19 | 20 |
21 |
22 | 23 |
24 | 25 | 26 | 30 |
31 |
32 |
33 |
34 | 35 | 36 | !ViewTemplate 37 | 38 |
39 | [[MptwTheme##ViewTemplateToolbar]] 40 | 41 |
42 | 43 |
44 | 45 | 46 |
47 | 48 |
49 | (updated 50 | by ) 51 | 55 |
56 | 57 |
58 |
59 |
60 |
61 |
62 |
63 | 64 |
65 |
66 |
67 | 68 | 69 | 70 | 71 | 72 |
73 | 74 | 75 | 76 | !ViewTemplateToolbar 77 | 78 |
79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
90 | 91 | 92 | !EditTemplate 93 | 94 |
95 |
96 |
Title
97 |
98 |
Content
99 |
Tags
100 |
101 | 102 | 103 | !StyleSheet 104 | /*{{{*/ 105 | 106 | /* a contrasting background so I can see where one tiddler ends and the other begins */ 107 | body { 108 | background: [[ColorPalette::TertiaryLight]]; 109 | } 110 | 111 | /* sexy colours and font for the header */ 112 | .headerForeground { 113 | color: [[ColorPalette::PrimaryPale]]; 114 | } 115 | .headerShadow, .headerShadow a { 116 | color: [[ColorPalette::PrimaryMid]]; 117 | } 118 | 119 | /* separate the top menu parts */ 120 | .headerForeground, .headerShadow { 121 | padding: 1em 1em 0; 122 | } 123 | 124 | .headerForeground, .headerShadow { 125 | font-family: 'Trebuchet MS', sans-serif; 126 | font-weight:bold; 127 | } 128 | .headerForeground .siteSubtitle { 129 | color: [[ColorPalette::PrimaryLight]]; 130 | } 131 | .headerShadow .siteSubtitle { 132 | color: [[ColorPalette::PrimaryMid]]; 133 | } 134 | 135 | /* make shadow go and down right instead of up and left */ 136 | .headerShadow { 137 | left: 1px; 138 | top: 1px; 139 | } 140 | 141 | /* prefer monospace for editing */ 142 | .editor textarea, .editor input { 143 | font-family: 'Consolas', monospace; 144 | background-color:[[ColorPalette::TertiaryPale]]; 145 | } 146 | 147 | 148 | /* sexy tiddler titles */ 149 | .title { 150 | font-size: 250%; 151 | color: [[ColorPalette::PrimaryLight]]; 152 | font-family: 'Trebuchet MS', sans-serif; 153 | } 154 | 155 | /* more subtle tiddler subtitle */ 156 | .subtitle { 157 | padding:0px; 158 | margin:0px; 159 | padding-left:1em; 160 | font-size: 90%; 161 | color: [[ColorPalette::TertiaryMid]]; 162 | } 163 | .subtitle .tiddlyLink { 164 | color: [[ColorPalette::TertiaryMid]]; 165 | } 166 | 167 | /* a little bit of extra whitespace */ 168 | .viewer { 169 | padding-bottom:3px; 170 | } 171 | 172 | /* don't want any background color for headings */ 173 | h1,h2,h3,h4,h5,h6 { 174 | background-color: transparent; 175 | color: [[ColorPalette::Foreground]]; 176 | } 177 | 178 | /* give tiddlers 3d style border and explicit background */ 179 | .tiddler { 180 | background: [[ColorPalette::Background]]; 181 | border-right: 2px [[ColorPalette::TertiaryMid]] solid; 182 | border-bottom: 2px [[ColorPalette::TertiaryMid]] solid; 183 | margin-bottom: 1em; 184 | padding:1em 2em 2em 1.5em; 185 | } 186 | 187 | /* make options slider look nicer */ 188 | #sidebarOptions .sliderPanel { 189 | border:solid 1px [[ColorPalette::PrimaryLight]]; 190 | } 191 | 192 | /* the borders look wrong with the body background */ 193 | #sidebar .button { 194 | border-style: none; 195 | } 196 | 197 | /* this means you can put line breaks in SidebarOptions for readability */ 198 | #sidebarOptions br { 199 | display:none; 200 | } 201 | /* undo the above in OptionsPanel */ 202 | #sidebarOptions .sliderPanel br { 203 | display:inline; 204 | } 205 | 206 | /* horizontal main menu stuff */ 207 | #displayArea { 208 | margin: 1em 15.7em 0em 1em; /* use the freed up space */ 209 | } 210 | #topMenu br { 211 | display: none; 212 | } 213 | #topMenu { 214 | background: [[ColorPalette::PrimaryMid]]; 215 | color:[[ColorPalette::PrimaryPale]]; 216 | } 217 | #topMenu { 218 | padding:2px; 219 | } 220 | #topMenu .button, #topMenu .tiddlyLink, #topMenu a { 221 | margin-left: 0.5em; 222 | margin-right: 0.5em; 223 | padding-left: 3px; 224 | padding-right: 3px; 225 | color: [[ColorPalette::PrimaryPale]]; 226 | font-size: 115%; 227 | } 228 | #topMenu .button:hover, #topMenu .tiddlyLink:hover { 229 | background: [[ColorPalette::PrimaryDark]]; 230 | } 231 | 232 | /* make 2.2 act like 2.1 with the invisible buttons */ 233 | .toolbar { 234 | visibility:hidden; 235 | } 236 | .selected .toolbar { 237 | visibility:visible; 238 | } 239 | 240 | /* experimental. this is a little borked in IE7 with the button 241 | * borders but worth it I think for the extra screen realestate */ 242 | .toolbar { float:right; } 243 | 244 | /* fix for TaggerPlugin. from sb56637. improved by FND */ 245 | .popup li .tagger a { 246 | display:inline; 247 | } 248 | 249 | /* makes theme selector look a little better */ 250 | #sidebarOptions .sliderPanel .select .button { 251 | padding:0.5em; 252 | display:block; 253 | } 254 | #sidebarOptions .sliderPanel .select br { 255 | display:none; 256 | } 257 | 258 | /* make it print a little cleaner */ 259 | @media print { 260 | #topMenu { 261 | display: none ! important; 262 | } 263 | /* not sure if we need all the importants */ 264 | .tiddler { 265 | border-style: none ! important; 266 | margin:0px ! important; 267 | padding:0px ! important; 268 | padding-bottom:2em ! important; 269 | } 270 | .tagglyTagging .button, .tagglyTagging .hidebutton { 271 | display: none ! important; 272 | } 273 | .headerShadow { 274 | visibility: hidden ! important; 275 | } 276 | .tagglyTagged .quickopentag, .tagged .quickopentag { 277 | border-style: none ! important; 278 | } 279 | .quickopentag a.button, .miniTag { 280 | display: none ! important; 281 | } 282 | } 283 | 284 | /* get user styles specified in StyleSheet */ 285 | [[StyleSheet]] 286 | 287 | /*}}}*/ 288 | 289 | -------------------------------------------------------------------------------- /r4tw.rb: -------------------------------------------------------------------------------- 1 | # 2 | # =r4tw 3 | # Author:: Simon Baird 4 | # URL:: http://simonbaird.com/r4tw 5 | # License:: http://en.wikipedia.org/wiki/MIT_license 6 | # r4tw is some ruby classes for manipuating TiddlyWikis and tiddlers. 7 | # It is similar to cook and ginsu but cooler. 8 | # 9 | # ===Known problems 10 | # from_remote_tw can be problematic if importing from a 2.1 TW into a 2.2 TW. 11 | # 12 | # Note: probably should rewrite this as a an extention to cook/slice. 13 | # 14 | # Note: should make this is gem or at least a submodule. It has it's 15 | # own repo, but this is just a copy and probably out of sync... 16 | # 17 | 18 | 19 | #--------------------------------------------------------------------- 20 | #-- General purpose utils 21 | 22 | require 'pathname' 23 | require 'open-uri' 24 | 25 | def read_file(file_name) #:nodoc: 26 | File.read(file_name) 27 | end 28 | 29 | def fetch_url(url) #:nodoc: 30 | open(url).read.to_s 31 | end 32 | 33 | def this_dir(this_file=$0) #:nodoc: 34 | Pathname.new(this_file).expand_path.dirname 35 | end 36 | 37 | class String 38 | def to_file(file_name) #:nodoc: 39 | File.open(file_name,"w") { |f| f << self } 40 | end 41 | end 42 | 43 | 44 | #--------------------------------------------------------------------- 45 | #-- TiddlyWiki related utils 46 | 47 | class String 48 | 49 | def escapeLineBreaks 50 | gsub(/\\/m,"\\s").gsub(/\n/m,"\\n").gsub(/\r/m,"") 51 | end 52 | 53 | def unescapeLineBreaks 54 | # not sure what \b is for 55 | gsub(/\\n/m,"\n").gsub(/\\b/m," ").gsub(/\\s/,"\\").gsub(/\r/m,"") 56 | end 57 | 58 | def encodeHTML 59 | gsub(/&/m,"&").gsub(//m,">").gsub(/\"/m,""") 60 | end 61 | 62 | def decodeHTML 63 | gsub(/&/m,"&").gsub(/</m,"<").gsub(/>/m,">").gsub(/"/m,"\"") 64 | end 65 | 66 | def readBrackettedList 67 | # scan is a beautiful thing 68 | scan(/\[\[([^\]]+)\]\]|(\S+)/).map {|m| m[0]||m[1]} 69 | end 70 | 71 | def toBrackettedList 72 | self 73 | end 74 | 75 | end 76 | 77 | class Array 78 | 79 | def toBrackettedList 80 | map{ |i| (i =~ /\s/) ? ("[["+i+"]]") : i }.join(" ") 81 | end 82 | 83 | end 84 | 85 | class Time 86 | 87 | def convertToLocalYYYYMMDDHHMM() 88 | self.localtime.strftime("%Y%m%d%H%M") 89 | end 90 | 91 | def convertToYYYYMMDDHHMM() 92 | self.utc.strftime("%Y%m%d%H%M") 93 | end 94 | 95 | def Time.convertFromYYYYMMDDHHMM(date_string) 96 | m = date_string.match(/(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/) 97 | Time.utc(m[1],m[2],m[3],m[4],m[5]) 98 | end 99 | 100 | end 101 | 102 | 103 | #--------------------------------------------------------------------- 104 | # Tiddler 105 | # 106 | 107 | # =Tiddler 108 | # For creating and manipulating tiddlers 109 | # ===Example 110 | # puts Tiddler.new({'tiddler'=>'Hello','text'=>'Hi there','tags'=>['tag1','tag2']}) 111 | 112 | class Tiddler 113 | 114 | @@main_fields = %w[tiddler modifier modified created tags] 115 | # and soon to be changecount? 116 | 117 | # text is not really a field in TiddlyWiki it makes 118 | # things easier to make it one here. It could possibly 119 | # clash with a real field called text. Ignore this fact for now... 120 | 121 | @@defaults = { 122 | 'tiddler' => 'New Tiddler', 123 | 'modified' => Time.now.convertToYYYYMMDDHHMM, 124 | 'created' => Time.now.convertToYYYYMMDDHHMM, 125 | 'modifier' => 'YourName', 126 | 'tags' => '', 127 | 'text' => '', 128 | } 129 | 130 | # used by from_file 131 | @@default_ext_tag_map = { 132 | '.js' => %[systemConfig], 133 | '.theme' => %[systemTheme], 134 | '.palette' => %[systemPalette], 135 | '.html' => %[html], 136 | '.css' => %[css], 137 | '.pub' => %[systemServer], 138 | } 139 | 140 | attr_accessor :fields 141 | 142 | # Depending on the arguments this can be used to create or import a tiddler in various ways. 143 | # 144 | # ===From scratch 145 | # If the argument is a Hash then it is used to specify a tiddler to be created from 146 | # scratch. 147 | # 148 | # Example: 149 | # t = Tiddler.new.from({ 150 | # 'tiddler'=>'HelloThere', 151 | # 'text'=>'And welcome', 152 | # }) 153 | # Other built-in fields are +modified+, +created+, +modifier+ and +tags+. Any other 154 | # fields you add will be created as tiddler extended fields. Text is the contents of 155 | # the tiddler. Tiddler is the title of the tiddler. 156 | # 157 | # 158 | # ===From a file 159 | # If the argument looks like a file name (ie a string that doesn't match the other 160 | # criteria then create a tiddler with the name being the file name and the 161 | # contents being the contents of the file. Does some guessing about tags based on 162 | # the file's extension. (This is customisable, see code for details). Also reads the 163 | # file modified date and uses it. 164 | # 165 | # Example: 166 | # t = Tiddler.new.from("myplugin.js") 167 | # 168 | # ===From a TiddlyWiki 169 | # If the argument is in the form file.html#TiddlerName or http://sitename.com/#TiddlerName 170 | # then import TiddlerName from the specified location 171 | # 172 | # Example: 173 | # t1 = Tiddler.new.from("myfile.html#SomeTiddler") 174 | # t2 = Tiddler.new.from("http://www.tiddlywiki.com/#HelloThere") 175 | # 176 | # 177 | # ===From a url 178 | # Creates a tiddler from a url. The entire contents of the page are the contents 179 | # of the tiddler. You should set the 'tiddler' field and other fields using a hash 180 | # as the second argument in the same format as creating a tiddler from scratch. 181 | # There is no automatic tagging for this one so you should add tags yourself as required 182 | # 183 | # Example: 184 | # t = Tiddler.new.from( 185 | # "http://svn.somewhere.org/Trunk/HelloWorld.js", 186 | # {'tiddler'=>'HelloWorld','tags'=>'systemConfig'} 187 | # ) 188 | # 189 | # 190 | # ===From a div string 191 | # If the argument is a string containing a tiddler div such 192 | # as would be found in a TiddlyWiki storeArea then the tiddler 193 | # is created from that div 194 | # 195 | def initialize(*args) 196 | @fields = {} 197 | 198 | case args[0] 199 | when Hash 200 | from_scratch(*args) 201 | 202 | when Tiddler 203 | from_tiddler(*args) 204 | 205 | when /^\s*
]+)>(.*?)<\/div>/m) 240 | field_str = match_data[1] 241 | text_str = match_data[2] 242 | 243 | field_str.scan(/ ([\w\.]+)="([^"]+)"/) do |field_name,field_value| 244 | if field_name == "title" 245 | field_name = "tiddler" 246 | end 247 | @fields[field_name] = field_value 248 | end 249 | 250 | text_str.sub!(/\n
/,'')
251 |     text_str.sub!(/<\/pre>\n/,'')
252 | 
253 |     #if (use_pre)
254 |       @fields['text'] = text_str.decodeHTML
255 |     #else
256 |     #  @fields['text'] = text_str.unescapeLineBreaks.decodeHTML
257 |     #end
258 | 
259 |     self
260 |   end
261 | 
262 |   def from_file(file_name, fields={}, ext_tag_map=@@default_ext_tag_map) #:nodoc:
263 |     ext = File.extname(file_name)
264 |     base = File.basename(file_name,ext)
265 |     @fields = @@defaults.merge(fields)
266 |     @fields['tiddler'] = base
267 |     @fields['text'] = read_file(file_name)
268 |     @fields['created'] = File.mtime(file_name).convertToYYYYMMDDHHMM
269 |     # @fields['modified'] = @fields['created']
270 |     @fields['tags'] = ext_tag_map[ext].toBrackettedList if ext_tag_map[ext]
271 |     self
272 |   end
273 | 
274 |   def from_url(url,fields={}) #:nodoc:
275 |     @fields = @@defaults.merge(fields)
276 |     @fields['text'] = fetch_url(url)
277 |     self
278 |   end
279 | 
280 |   def from_tw(tiddler_url) #:nodoc:
281 |     # this works if url is a local file, eg "somefile.html#TiddlerName"
282 |     # as well as if it's a remote file, eg "http://somewhere.com/#TiddlerName"
283 |     location,tiddler_name = tiddler_url.split("#")
284 |     TiddlyWiki.new.source_empty(location).get_tiddler(tiddler_name)
285 |   end
286 | 
287 |   alias from_remote_tw from_tw #:nodoc:
288 |   alias from_local_tw from_tw #:nodoc:
289 | 
290 |   # Returns a hash containing the tiddlers extended fields
291 |   # Probably would include changecount at this stage at least
292 |   def extended_fields
293 |     @fields.keys.reject{ |f| @@main_fields.include?(f) || f == 'text' }.sort
294 |   end
295 | 
296 |   # Converts to a div suitable for a TiddlyWiki store area
297 |   def to_s(use_pre=true)
298 | 
299 |     fields_string =
300 |       @@main_fields.
301 |         reject{ |f|
302 |           use_pre and (
303 |             # seems like we have to leave out modified if there is none
304 |             (f == 'modified' and !@fields[f]) or
305 |             (f == 'modifier' and !@fields[f]) or
306 |             # seems like we have to not print tags="" any more
307 |             (f == 'tags' and (!@fields[f] or @fields[f].length == 0))
308 |           )
309 |         }.
310 |         map { |f|
311 |           # support old style tiddler=""
312 |           # and new style title=""
313 |           if f == 'tiddler' and use_pre
314 |             field_name = 'title'
315 |           else
316 |             field_name = f
317 |           end
318 |           %{#{field_name}="#{@fields[f]}"}
319 |         } +
320 |       extended_fields.
321 |         map{ |f| %{#{f}="#{@fields[f]}"} }
322 | 
323 |     #if use_pre
324 |       "
\n
#{@fields['text'].encodeHTML}
\n
" 325 | #else 326 | # "
#{@fields['text'].escapeLineBreaks.encodeHTML}
" 327 | #end 328 | 329 | end 330 | 331 | # Build meta files as used by cook and slice 332 | # Does not do extended fields. TODO 333 | def to_cook_meta 334 | [ 335 | "created: #{self.created}", 336 | "modified: #{self.modified}", 337 | "modifier: #{self.modifier}", 338 | "tags: #{self.tags}", 339 | "", 340 | ].join("\n") 341 | end 342 | 343 | alias to_div to_s #:nodoc: 344 | 345 | # Lets you access fields like this: 346 | # tiddler.name 347 | # tiddler.created 348 | # etc 349 | # 350 | def method_missing(method,*args) 351 | 352 | method = method.to_s 353 | 354 | synonyms = { 355 | 'name' => 'tiddler', 356 | 'title' => 'tiddler', 357 | 'content' => 'text', 358 | 'body' => 'text', 359 | } 360 | 361 | method = synonyms[method] || method 362 | 363 | if @@main_fields.include? method or @fields[method] 364 | @fields[method] 365 | else 366 | raise "No such field or method #{method}" 367 | end 368 | 369 | end 370 | 371 | # Add some text to the end of a tiddler's content 372 | def append_content(new_content) 373 | @fields['text'] += new_content 374 | self 375 | end 376 | 377 | # Add some text to the beginning of a tiddler's content 378 | def prepend_content(new_content) 379 | @fields['text'] = new_content + @fields['text'] 380 | self 381 | end 382 | 383 | # Renames a tiddler 384 | def rename(new_name) 385 | @fields['tiddler'] = new_name 386 | self 387 | end 388 | 389 | # Makes a copy of this tiddler 390 | def copy 391 | Tiddler.new.from_div(self.to_div) 392 | end 393 | 394 | # Makes a copy of this tiddler with a new title 395 | def copy_to(new_title) 396 | copy.rename(new_title) 397 | end 398 | 399 | # Adds a tag 400 | def add_tag(new_tag) 401 | @fields['tags'] = @fields['tags']. 402 | readBrackettedList. 403 | push(new_tag). 404 | uniq. 405 | toBrackettedList 406 | 407 | self 408 | end 409 | 410 | # Adds a list of tags 411 | def add_tags(tags) 412 | tags.each { |tag| add_tag(tag) } 413 | end 414 | 415 | # Removes a single tag 416 | def remove_tag(old_tag) 417 | @fields['tags'] = @fields['tags']. 418 | readBrackettedList. 419 | reject { |tag| tag == old_tag }. 420 | toBrackettedList 421 | 422 | self 423 | end 424 | 425 | # Removes a list of tags 426 | def remove_tags(tags) 427 | tags.each { |tag| remove_tags(tag) } 428 | end 429 | 430 | # Returns true if a tiddler has a particular tag 431 | def has_tag(tag) 432 | fields['tags'] && fields['tags'].readBrackettedList.include?(tag) 433 | end 434 | 435 | # Returns a Hash containing all tiddler slices 436 | def get_slices 437 | if not @slices 438 | @slices = {} 439 | # look familiar? 440 | slice_re = /(?:[\'\/]*~?(\w+)[\'\/]*\:[\'\/]*\s*(.*?)\s*$)|(?:\|[\'\/]*~?(\w+)\:?[\'\/]*\|\s*(.*?)\s*\|)/m 441 | text.scan(slice_re).each do |l1,v1,l2,v2| 442 | @slices[l1||l2] = v1||v2; 443 | end 444 | end 445 | @slices 446 | end 447 | 448 | # Returns a tiddler slice 449 | def get_slice(slice) 450 | get_slices[slice] 451 | end 452 | 453 | # 454 | # Experimental. Provides access to plugin meta slices. 455 | # Returns one meta value or a hash of them if no argument is given 456 | # 457 | def plugin_meta(slice=nil) 458 | # see http://www.tiddlywiki.com/#ExamplePlugin 459 | if not @plugin_meta 460 | meta = %w[Name Description Version Date Source Author License CoreVersion Browser] 461 | @plugin_meta = get_slices.reject{|k,v| not meta.include?(k)} 462 | end 463 | if slice 464 | @plugin_meta[slice] 465 | else 466 | @plugin_meta 467 | end 468 | end 469 | 470 | end 471 | 472 | #--------------------------------------------------------------------- 473 | # =Tiddlywiki 474 | # Create and manipulate TiddlyWiki files 475 | # 476 | 477 | class TiddlyWiki 478 | 479 | attr_accessor :orig_tiddlers, :tiddlers, :raw 480 | 481 | # doesn't do much. probably should allow an empty file param 482 | def initialize(use_pre=true) 483 | @use_pre = use_pre 484 | @tiddlers = [] 485 | end 486 | 487 | # this should replace all the add_tiddler_from_blah methods 488 | # but actually they are still there below 489 | # testing required 490 | def method_missing(method_name,*args); 491 | case method_name.to_s 492 | when /^add_tiddler_(.*)$/ 493 | add_tiddler(Tiddler.new.send($1,*args)) 494 | end 495 | end 496 | 497 | # initialise a TiddlyWiki from a source file 498 | # will treat empty_file as a url if it looks like one 499 | # note that it doesn't have to be literally empty 500 | def source_empty(empty_file,&block) 501 | @empty_file = empty_file 502 | if empty_file =~ /^https?/ 503 | @raw = fetch_url(@empty_file) 504 | else 505 | @raw = read_file(@empty_file) 506 | end 507 | 508 | # stupid ctrl (\r) char 509 | #@raw.eat_ctrl_m! 510 | 511 | if @raw !~ /var version = \{title: "TiddlyWiki", major: 2, minor: [23456]/ # fix me 512 | @use_pre = false 513 | end 514 | 515 | @core_hacks = [] 516 | @orig_tiddlers = get_orig_tiddlers 517 | @tiddlers = @orig_tiddlers 518 | 519 | instance_eval(&block) if block 520 | 521 | self 522 | end 523 | 524 | # reads an empty from a file on disk 525 | def source_file(file_name="empty.html") 526 | source_empty(file_name) 527 | end 528 | 529 | # reads an empty file from a url 530 | def source_url(url="http://www.tiddlywiki.com/empty.html") 531 | source_empty(url) 532 | end 533 | 534 | # important regexp 535 | # if this doesn't work we are screwed 536 | @@store_regexp = /^(.*
\n?)(.*)(\n?<\/div>\r?\n