mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-08-07 03:18:53 +00:00
Merge branch 'master' into dynamic-macro-calls
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
boot/** -linguist-generated
|
||||
**/tiddlywiki.files linguist-language=JSON
|
||||
**/tiddlywiki.info linguist-language=JSON
|
||||
**/plugin.info linguist-language=JSON
|
||||
@@ -1,6 +1,7 @@
|
||||
name: Bug report
|
||||
description: Create a report to help us improve TiddlyWiki 5
|
||||
title: "[BUG] "
|
||||
type: bug
|
||||
body:
|
||||
- type: textarea
|
||||
id: Describe
|
||||
|
||||
@@ -4,6 +4,7 @@ about: Suggest an idea for TiddlyWiki 5
|
||||
title: "[IDEA]"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
type: feature
|
||||
|
||||
---
|
||||
|
||||
|
||||
+25
-57
@@ -8,6 +8,8 @@ On the server this file is executed directly to boot TiddlyWiki. In the browser,
|
||||
|
||||
\*/
|
||||
|
||||
/* eslint-disable @stylistic/indent */
|
||||
|
||||
var _boot = (function($tw) {
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
@@ -44,12 +46,8 @@ $tw.utils.hop = function(object,property) {
|
||||
return object ? Object.prototype.hasOwnProperty.call(object,property) : false;
|
||||
};
|
||||
|
||||
/*
|
||||
Determine if a value is an array
|
||||
*/
|
||||
$tw.utils.isArray = function(value) {
|
||||
return Object.prototype.toString.call(value) == "[object Array]";
|
||||
};
|
||||
/** @deprecated Use Array.isArray instead */
|
||||
$tw.utils.isArray = value => Array.isArray(value);
|
||||
|
||||
/*
|
||||
Check if an array is equal by value and by reference.
|
||||
@@ -128,35 +126,22 @@ $tw.utils.pushTop = function(array,value) {
|
||||
return array;
|
||||
};
|
||||
|
||||
/*
|
||||
Determine if a value is a date
|
||||
*/
|
||||
$tw.utils.isDate = function(value) {
|
||||
return Object.prototype.toString.call(value) === "[object Date]";
|
||||
};
|
||||
/** @deprecated Use instanceof Date instead */
|
||||
$tw.utils.isDate = value => value instanceof Date;
|
||||
|
||||
/*
|
||||
Iterate through all the own properties of an object or array. Callback is invoked with (element,title,object)
|
||||
*/
|
||||
/** @deprecated Use array iterative methods instead */
|
||||
$tw.utils.each = function(object,callback) {
|
||||
var next,f,length;
|
||||
if(object) {
|
||||
if(Object.prototype.toString.call(object) == "[object Array]") {
|
||||
for(f=0, length=object.length; f<length; f++) {
|
||||
next = callback(object[f],f,object);
|
||||
if(next === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(Array.isArray(object)) {
|
||||
object.every((element,index,array) => {
|
||||
const next = callback(element,index,array);
|
||||
return next !== false;
|
||||
});
|
||||
} else {
|
||||
var keys = Object.keys(object);
|
||||
for(f=0, length=keys.length; f<length; f++) {
|
||||
var key = keys[f];
|
||||
next = callback(object[key],key,object);
|
||||
if(next === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Object.entries(object).every(entry => {
|
||||
const next = callback(entry[1], entry[0], object);
|
||||
return next !== false;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -331,32 +316,13 @@ $tw.utils.htmlDecode = function(s) {
|
||||
return s.toString().replace(/</mg,"<").replace(/ /mg,"\xA0").replace(/>/mg,">").replace(/"/mg,"\"").replace(/&/mg,"&");
|
||||
};
|
||||
|
||||
/*
|
||||
Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)
|
||||
*/
|
||||
$tw.utils.getLocationHash = function() {
|
||||
var href = window.location.href;
|
||||
var idx = href.indexOf('#');
|
||||
if(idx === -1) {
|
||||
return "#";
|
||||
} else if(href.substr(idx + 1,1) === "#" || href.substr(idx + 1,3) === "%23") {
|
||||
// Special case: ignore location hash if it itself starts with a #
|
||||
return "#";
|
||||
} else {
|
||||
return href.substring(idx);
|
||||
}
|
||||
};
|
||||
/** @deprecated Use window.location.hash instead. */
|
||||
$tw.utils.getLocationHash = () => window.location.hash;
|
||||
|
||||
/*
|
||||
Pad a string to a given length with "0"s. Length defaults to 2
|
||||
*/
|
||||
$tw.utils.pad = function(value,length) {
|
||||
length = length || 2;
|
||||
var s = value.toString();
|
||||
if(s.length < length) {
|
||||
s = "000000000000000000000000000".substr(0,length - s.length) + s;
|
||||
}
|
||||
return s;
|
||||
/** @deprecated Pad a string to a given length with "0"s. Length defaults to 2 */
|
||||
$tw.utils.pad = function(value,length = 2) {
|
||||
const s = value.toString();
|
||||
return s.padStart(length, "0");
|
||||
};
|
||||
|
||||
// Convert a date into UTC YYYYMMDDHHMMSSmmm format
|
||||
@@ -630,7 +596,7 @@ $tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
|
||||
// Compile the code into a function
|
||||
var fn;
|
||||
if($tw.browser) {
|
||||
fn = window["eval"](code + "\n\n//# sourceURL=" + filename);
|
||||
fn = window["eval"](code + "\n\n//# sourceURL=" + filename); // eslint-disable-line no-eval -- See https://github.com/TiddlyWiki/TiddlyWiki5/issues/6839
|
||||
} else {
|
||||
if(sandbox){
|
||||
fn = vm.runInContext(code,sandbox,filename)
|
||||
@@ -2801,6 +2767,8 @@ return $tw;
|
||||
|
||||
});
|
||||
|
||||
/* eslint-enable @stylistic/indent */
|
||||
|
||||
if(typeof(exports) !== "undefined") {
|
||||
exports.TiddlyWiki = _boot;
|
||||
} else {
|
||||
|
||||
@@ -12,6 +12,8 @@ See Boot.js for further details of the boot process.
|
||||
|
||||
\*/
|
||||
|
||||
/* eslint-disable @stylistic/indent */
|
||||
|
||||
var _bootprefix = (function($tw) {
|
||||
|
||||
"use strict";
|
||||
@@ -114,6 +116,8 @@ return $tw;
|
||||
|
||||
});
|
||||
|
||||
/* eslint-enable @stylistic/indent */
|
||||
|
||||
if(typeof(exports) === "undefined") {
|
||||
// Set up $tw global for the browser
|
||||
window.$tw = _bootprefix(window.$tw);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
title: @Christian_Byron
|
||||
tags: Community/Person
|
||||
fullname: Christian Byron
|
||||
talk.tiddlywiki.org: Christian_Byron
|
||||
github: ceebeetree
|
||||
linkedin: www.linkedin.com/in/christian-byron-b84a594/
|
||||
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAuAAEBAAMBAAAAAAAAAAAAAAAHBgEDBQQBAAMBAAAAAAAAAAAAAAAAAAABAwX/2gAMAwEAAhADEAAAADv2xtJlY03sqePW3ARS1RSydIhcH//EACcQAAICAgIBAgYDAAAAAAAAAAECAwQFEQASMRMhBhBBk8HRIzJx/9oACAEBAAE/AMFQxs+NExqJLMCwYE+SOT4bF3qr+hAIpRsDQ6lWH0Yco4S/eVniRVQHXZzrZ5dwGQpQtNII2RfJVvHMRl5cbKxC94n/ALp+RxfiKpNcgMMUqPIwjcnWip/I5XtUowaL3Ujir/xt79Glb6/4OZ7MV5oEpUzuIa7MPB14A5jpoYLsEsydo1bbLre+CWEEEYab7Uf74ZYSSThpvtR/vmRmhnuzywp1jZtquta+VPM49qlcy24lf017At7g8uZnHrUsGK3Ez+m3UBvcnXy//8QAHhEAAgEFAAMAAAAAAAAAAAAAAQIDAAQRIkEyUaH/2gAIAQIBAT8AmiuVlZkLEeQOflJPcvMAF0z65V+h0YIW52rBDuxUrztf/8QAIxEBAAEDAwMFAAAAAAAAAAAAAgEAAxEEBSMSQcEiMVJxof/aAAgBAwEBPwC/Z1ZvNBOYz1Gc/lDUat3ySPRM/H2P3W4hcbIldpxnxW3BcjQk9oznzX//2Q==
|
||||
|
||||
Hello ~TiddlyWikiers - I have been a long time fan, recent contributor to the TW community.
|
||||
Recently I have volunteered to run the [[TiddlyWiki Newsletter|https://tiddlywiki.substack.com/]] to spread the great news about TW.
|
||||
|
||||
I have been in the IT industry for about thirty years, mostly as a consultant and technical arcitect.
|
||||
More recently I went back to study a masters in IT focussing on AI and data science.
|
||||
Now my partner and I have started our own business ([[Sphere Innovations|https://sphere-innovations.com.au]]) - in consulting and building web applications for small to medium size businesses here in Australia.
|
||||
@@ -2,5 +2,6 @@ title: Newsletter Team
|
||||
tags: Community/Team
|
||||
modified: 20250909171928024
|
||||
created: 20250909171928024
|
||||
leader: @Christian_Byron
|
||||
|
||||
The Newsletter Team is responsible for producing the TiddlyWiki Newsletter, a monthly email newsletter that highlights news, updates, and community contributions related to TiddlyWiki.
|
||||
@@ -156,8 +156,8 @@ Fix the height of textarea to fit content
|
||||
FramedEngine.prototype.fixHeight = function() {
|
||||
// Make sure styles are updated
|
||||
this.copyStyles();
|
||||
// Adjust height
|
||||
if(this.widget.editTag === "textarea") {
|
||||
// If .editRows is initialised, it takes precedence
|
||||
if(this.widget.editTag === "textarea" && !this.widget.editRows) {
|
||||
if(this.widget.editAutoHeight) {
|
||||
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
|
||||
var newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
|
||||
|
||||
@@ -100,7 +100,8 @@ SimpleEngine.prototype.getText = function() {
|
||||
Fix the height of textarea to fit content
|
||||
*/
|
||||
SimpleEngine.prototype.fixHeight = function() {
|
||||
if(this.widget.editTag === "textarea") {
|
||||
// If .editRows is initialised, it takes precedence
|
||||
if((this.widget.editTag === "textarea") && !this.widget.editRows) {
|
||||
if(this.widget.editAutoHeight) {
|
||||
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
|
||||
$tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
|
||||
|
||||
+21
-16
@@ -88,8 +88,8 @@ function parseFilterOperation(operators,filterString,p) {
|
||||
rexMatch = rex.exec(filterString.substring(p));
|
||||
if(rexMatch) {
|
||||
operator.regexp = new RegExp(rexMatch[1], rexMatch[2]);
|
||||
// DEPRECATION WARNING
|
||||
console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp);
|
||||
// DEPRECATION WARNING
|
||||
console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp);
|
||||
nextBracketPos = p + rex.lastIndex - 1;
|
||||
}
|
||||
else {
|
||||
@@ -232,7 +232,12 @@ exports.getFilterRunPrefixes = function() {
|
||||
|
||||
exports.filterTiddlers = function(filterString,widget,source) {
|
||||
var fn = this.compileFilter(filterString);
|
||||
return fn.call(this,source,widget);
|
||||
try {
|
||||
const fnResult = fn.call(this,source,widget);
|
||||
return fnResult;
|
||||
} catch(e) {
|
||||
return [`${$tw.language.getString("Error/Filter")}: ${e}`];
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -314,19 +319,19 @@ exports.compileFilter = function(filterString) {
|
||||
|
||||
// Invoke the appropriate filteroperator module
|
||||
results = operatorFunction(accumulator,{
|
||||
operator: operator.operator,
|
||||
operand: operands.length > 0 ? operands[0] : undefined,
|
||||
operands: operands,
|
||||
multiValueOperands: multiValueOperands,
|
||||
isMultiValueOperand: isMultiValueOperand,
|
||||
prefix: operator.prefix,
|
||||
suffix: operator.suffix,
|
||||
suffixes: operator.suffixes,
|
||||
regexp: operator.regexp
|
||||
},{
|
||||
wiki: self,
|
||||
widget: widget
|
||||
});
|
||||
operator: operator.operator,
|
||||
operand: operands.length > 0 ? operands[0] : undefined,
|
||||
operands: operands,
|
||||
multiValueOperands: multiValueOperands,
|
||||
isMultiValueOperand: isMultiValueOperand,
|
||||
prefix: operator.prefix,
|
||||
suffix: operator.suffix,
|
||||
suffixes: operator.suffixes,
|
||||
regexp: operator.regexp
|
||||
},{
|
||||
wiki: self,
|
||||
widget: widget
|
||||
});
|
||||
if($tw.utils.isArray(results)) {
|
||||
accumulator = self.makeTiddlerIterator(results);
|
||||
} else {
|
||||
|
||||
@@ -18,6 +18,7 @@ exports.synchronous = true;
|
||||
// Default story and history lists
|
||||
var PAGE_TITLE_TITLE = "$:/core/wiki/title";
|
||||
var PAGE_STYLESHEET_TITLE = "$:/core/ui/PageStylesheet";
|
||||
var ROOT_STYLESHEET_TITLE = "$:/core/ui/RootStylesheet";
|
||||
var PAGE_TEMPLATE_TITLE = "$:/core/ui/RootTemplate";
|
||||
|
||||
// Time (in ms) that we defer refreshing changes to draft tiddlers
|
||||
@@ -44,22 +45,13 @@ exports.startup = function() {
|
||||
publishTitle();
|
||||
}
|
||||
});
|
||||
// Set up the styles
|
||||
$tw.styleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_STYLESHEET_TITLE,{document: $tw.fakeDocument});
|
||||
$tw.styleContainer = $tw.fakeDocument.createElement("style");
|
||||
$tw.styleWidgetNode.render($tw.styleContainer,null);
|
||||
$tw.styleWidgetNode.assignedStyles = $tw.styleContainer.textContent;
|
||||
$tw.styleElement = document.createElement("style");
|
||||
$tw.styleElement.innerHTML = $tw.styleWidgetNode.assignedStyles;
|
||||
document.head.insertBefore($tw.styleElement,document.head.firstChild);
|
||||
|
||||
var styleParser = $tw.wiki.parseTiddler(ROOT_STYLESHEET_TITLE,{parseAsInline: true}),
|
||||
styleWidgetNode = $tw.wiki.makeWidget(styleParser,{document: document});
|
||||
styleWidgetNode.render(document.head,null);
|
||||
|
||||
$tw.wiki.addEventListener("change",$tw.perf.report("styleRefresh",function(changes) {
|
||||
if($tw.styleWidgetNode.refresh(changes,$tw.styleContainer,null)) {
|
||||
var newStyles = $tw.styleContainer.textContent;
|
||||
if(newStyles !== $tw.styleWidgetNode.assignedStyles) {
|
||||
$tw.styleWidgetNode.assignedStyles = newStyles;
|
||||
$tw.styleElement.innerHTML = $tw.styleWidgetNode.assignedStyles;
|
||||
}
|
||||
}
|
||||
styleWidgetNode.refresh(changes,document.head,null);
|
||||
}));
|
||||
// Display the $:/core/ui/PageTemplate tiddler to kick off the display
|
||||
$tw.perf.report("mainRender",function() {
|
||||
@@ -68,7 +60,7 @@ exports.startup = function() {
|
||||
$tw.utils.addClass($tw.pageContainer,"tc-page-container-wrapper");
|
||||
document.body.insertBefore($tw.pageContainer,document.body.firstChild);
|
||||
$tw.pageWidgetNode.render($tw.pageContainer,null);
|
||||
$tw.hooks.invokeHook("th-page-refreshed");
|
||||
$tw.hooks.invokeHook("th-page-refreshed");
|
||||
})();
|
||||
// Remove any splash screen elements
|
||||
var removeList = document.querySelectorAll(".tc-remove-when-wiki-loaded");
|
||||
|
||||
@@ -63,24 +63,16 @@ exports.startup = function() {
|
||||
$tw.eventBus.emit("window:closed",{windowID});
|
||||
},false);
|
||||
// Set up the styles
|
||||
var styleWidgetNode = $tw.wiki.makeTranscludeWidget("$:/core/ui/PageStylesheet",{
|
||||
document: $tw.fakeDocument,
|
||||
variables: variables,
|
||||
importPageMacros: true}),
|
||||
styleContainer = $tw.fakeDocument.createElement("style");
|
||||
styleWidgetNode.render(styleContainer,null);
|
||||
var styleElement = srcDocument.createElement("style");
|
||||
styleElement.innerHTML = styleContainer.textContent;
|
||||
srcDocument.head.insertBefore(styleElement,srcDocument.head.firstChild);
|
||||
var styleParser = $tw.wiki.parseTiddler("$:/core/ui/RootStylesheet",{parseAsInline: true}),
|
||||
styleWidgetNode = $tw.wiki.makeWidget(styleParser,{document: srcDocument});
|
||||
styleWidgetNode.render(srcDocument.head,null);
|
||||
// Render the text of the tiddler
|
||||
var parser = $tw.wiki.parseTiddler(template),
|
||||
widgetNode = $tw.wiki.makeWidget(parser,{document: srcDocument, parentWidget: $tw.rootWidget, variables: variables});
|
||||
widgetNode.render(srcDocument.body,srcDocument.body.firstChild);
|
||||
// Function to handle refreshes
|
||||
refreshHandler = function(changes) {
|
||||
if(styleWidgetNode.refresh(changes,styleContainer,null)) {
|
||||
styleElement.innerHTML = styleContainer.textContent;
|
||||
}
|
||||
styleWidgetNode.refresh(changes);
|
||||
widgetNode.refresh(changes);
|
||||
};
|
||||
$tw.wiki.addEventListener("change",refreshHandler);
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*\
|
||||
title: $:/core/modules/utils/deprecated.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
|
||||
Deprecated util functions
|
||||
|
||||
\*/
|
||||
|
||||
exports.logTable = data => console.table(data);
|
||||
|
||||
exports.repeat = (str,count) => str.repeat(count);
|
||||
|
||||
exports.startsWith = (str,search) => str.startsWith(search);
|
||||
|
||||
exports.endsWith = (str,search) => str.endsWith(search);
|
||||
|
||||
exports.trim = function(str) {
|
||||
if(typeof str === "string") {
|
||||
return str.trim();
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
exports.hopArray = (object,array) => array.some(element => $tw.utils.hop(object,element));
|
||||
|
||||
exports.sign = Math.sign;
|
||||
|
||||
exports.strEndsWith = (str,ending,position) => str.endsWith(ending,position);
|
||||
|
||||
exports.stringifyNumber = num => num.toString();
|
||||
|
||||
exports.tagToCssSelector = function(tagName) {
|
||||
return "tc-tagged-" + encodeURIComponent(tagName).replace(/[!"#$%&'()*+,\-./:;<=>?@[\\\]^`{\|}~,]/mg,function(c) {
|
||||
return "\\" + c;
|
||||
});
|
||||
};
|
||||
|
||||
exports.domContains = (a,b) => a.compareDocumentPosition(b) & 16;
|
||||
|
||||
exports.domMatchesSelector = (node,selector) => node.matches(selector);
|
||||
|
||||
exports.hasClass = (el,className) => el.classList && el.classList.contains(className);
|
||||
|
||||
exports.addClass = function(el,className) {
|
||||
el.classList && el.classList.add(className);
|
||||
};
|
||||
|
||||
exports.removeClass = function(el,className) {
|
||||
el.classList && el.classList.remove(className);
|
||||
};
|
||||
|
||||
exports.toggleClass = function(el,className,status) {
|
||||
el.classList && el.classList.toggle(className, status);
|
||||
};
|
||||
|
||||
exports.getLocationPath = () => window.location.origin + window.location.pathname;
|
||||
@@ -11,19 +11,6 @@ Various static DOM-related utility functions.
|
||||
|
||||
var Popup = require("$:/core/modules/utils/dom/popup.js");
|
||||
|
||||
/*
|
||||
Determines whether element 'a' contains element 'b'
|
||||
Code thanks to John Resig, http://ejohn.org/blog/comparing-document-position/
|
||||
*/
|
||||
exports.domContains = function(a,b) {
|
||||
return a.contains ?
|
||||
a !== b && a.contains(b) :
|
||||
!!(a.compareDocumentPosition(b) & 16);
|
||||
};
|
||||
|
||||
exports.domMatchesSelector = function(node,selector) {
|
||||
return node.matches ? node.matches(selector) : node.msMatchesSelector(selector);
|
||||
};
|
||||
|
||||
/*
|
||||
Select text in a an input or textarea (setSelectionRange crashes on certain input types)
|
||||
@@ -49,38 +36,6 @@ exports.removeChildren = function(node) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.hasClass = function(el,className) {
|
||||
return el && el.hasAttribute && el.hasAttribute("class") && el.getAttribute("class").split(" ").indexOf(className) !== -1;
|
||||
};
|
||||
|
||||
exports.addClass = function(el,className) {
|
||||
var c = (el.getAttribute("class") || "").split(" ");
|
||||
if(c.indexOf(className) === -1) {
|
||||
c.push(className);
|
||||
el.setAttribute("class",c.join(" "));
|
||||
}
|
||||
};
|
||||
|
||||
exports.removeClass = function(el,className) {
|
||||
var c = (el.getAttribute("class") || "").split(" "),
|
||||
p = c.indexOf(className);
|
||||
if(p !== -1) {
|
||||
c.splice(p,1);
|
||||
el.setAttribute("class",c.join(" "));
|
||||
}
|
||||
};
|
||||
|
||||
exports.toggleClass = function(el,className,status) {
|
||||
if(status === undefined) {
|
||||
status = !exports.hasClass(el,className);
|
||||
}
|
||||
if(status) {
|
||||
exports.addClass(el,className);
|
||||
} else {
|
||||
exports.removeClass(el,className);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Get the first parent element that has scrollbars or use the body as fallback.
|
||||
*/
|
||||
@@ -297,10 +252,6 @@ exports.copyToClipboard = function(text,options) {
|
||||
document.body.removeChild(textArea);
|
||||
};
|
||||
|
||||
exports.getLocationPath = function() {
|
||||
return window.location.toString().split("#")[0];
|
||||
};
|
||||
|
||||
/*
|
||||
Collect DOM variables
|
||||
*/
|
||||
|
||||
@@ -48,31 +48,6 @@ exports.warning = function(text) {
|
||||
exports.log(text,"brown/orange");
|
||||
};
|
||||
|
||||
/*
|
||||
Log a table of name: value or name: [values...] pairs
|
||||
*/
|
||||
exports.logTable = function(data) {
|
||||
var hasArrays = false;
|
||||
$tw.utils.each(data,function(value,name) {
|
||||
if($tw.utils.isArray(value)) {
|
||||
hasArrays = true;
|
||||
}
|
||||
});
|
||||
if(console.table && !hasArrays) {
|
||||
console.table(data);
|
||||
} else {
|
||||
$tw.utils.each(data,function(value,name) {
|
||||
if($tw.utils.isArray(value)) {
|
||||
for(var t=0; t<value.length; t++) {
|
||||
console.log(`${name}[${t}]: ${value[t]}`);
|
||||
}
|
||||
} else {
|
||||
console.log(`${name}: ${value}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Return the integer represented by the str (string).
|
||||
Return the dflt (default) parameter if str is not a base-10 number.
|
||||
@@ -91,43 +66,6 @@ exports.replaceString = function(text,search,replace) {
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
Repeats a string
|
||||
*/
|
||||
exports.repeat = function(str,count) {
|
||||
var result = "";
|
||||
for(var t=0;t<count;t++) {
|
||||
result += str;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/*
|
||||
Check if a string starts with another string
|
||||
*/
|
||||
exports.startsWith = function(str,search) {
|
||||
return str.substring(0, search.length) === search;
|
||||
};
|
||||
|
||||
/*
|
||||
Check if a string ends with another string
|
||||
*/
|
||||
exports.endsWith = function(str,search) {
|
||||
return str.substring(str.length - search.length) === search;
|
||||
};
|
||||
|
||||
/*
|
||||
Trim whitespace from the start and end of a string
|
||||
Thanks to Steven Levithan, http://blog.stevenlevithan.com/archives/faster-trim-javascript
|
||||
*/
|
||||
exports.trim = function(str) {
|
||||
if(typeof str === "string") {
|
||||
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
exports.trimPrefix = function(str,unwanted) {
|
||||
if(typeof str === "string" && typeof unwanted === "string") {
|
||||
if(unwanted === "") {
|
||||
@@ -212,18 +150,6 @@ exports.count = function(object) {
|
||||
return Object.keys(object || {}).length;
|
||||
};
|
||||
|
||||
/*
|
||||
Determine whether an array-item is an object-property
|
||||
*/
|
||||
exports.hopArray = function(object,array) {
|
||||
for(var i=0; i<array.length; i++) {
|
||||
if($tw.utils.hop(object,array[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/*
|
||||
Remove entries from an array
|
||||
array: array to modify
|
||||
@@ -952,44 +878,6 @@ exports.makeDataUri = function(text,type,_canonical_uri) {
|
||||
return parts.join("");
|
||||
};
|
||||
|
||||
/*
|
||||
Useful for finding out the fully escaped CSS selector equivalent to a given tag. For example:
|
||||
|
||||
$tw.utils.tagToCssSelector("$:/tags/Stylesheet") --> tc-tagged-\%24\%3A\%2Ftags\%2FStylesheet
|
||||
*/
|
||||
exports.tagToCssSelector = function(tagName) {
|
||||
return "tc-tagged-" + encodeURIComponent(tagName).replace(/[!"#$%&'()*+,\-./:;<=>?@[\\\]^`{\|}~,]/mg,function(c) {
|
||||
return "\\" + c;
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
IE does not have sign function
|
||||
*/
|
||||
exports.sign = Math.sign || function(x) {
|
||||
x = +x; // convert to a number
|
||||
if(x === 0 || isNaN(x)) {
|
||||
return x;
|
||||
}
|
||||
return x > 0 ? 1 : -1;
|
||||
};
|
||||
|
||||
/*
|
||||
IE does not have an endsWith function
|
||||
*/
|
||||
exports.strEndsWith = function(str,ending,position) {
|
||||
if(str.endsWith) {
|
||||
return str.endsWith(ending,position);
|
||||
} else {
|
||||
if(typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > str.length) {
|
||||
position = str.length;
|
||||
}
|
||||
position -= ending.length;
|
||||
var lastIndex = str.indexOf(ending, position);
|
||||
return lastIndex !== -1 && lastIndex === position;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Return system information useful for debugging
|
||||
*/
|
||||
@@ -1016,10 +904,6 @@ exports.parseInt = function(str) {
|
||||
return parseInt(str,10) || 0;
|
||||
};
|
||||
|
||||
exports.stringifyNumber = function(num) {
|
||||
return num + "";
|
||||
};
|
||||
|
||||
exports.makeCompareFunction = function(type,options) {
|
||||
options = options || {};
|
||||
// set isCaseSensitive to true if not defined in options
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
/*\
|
||||
title: $:/core/modules/widgets/action-log.js
|
||||
type: application/javascript
|
||||
@@ -32,7 +33,7 @@ LogWidget.prototype.execute = function(){
|
||||
this.message = this.getAttribute("$$message","debug");
|
||||
this.logAll = this.getAttribute("$$all","no") === "yes" ? true : false;
|
||||
this.filter = this.getAttribute("$$filter");
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Refresh the widget by ensuring our attributes are up to date
|
||||
@@ -69,10 +70,11 @@ LogWidget.prototype.log = function() {
|
||||
});
|
||||
// Collect values of all variables, using the source text for functions
|
||||
for(var v in this.variables) {
|
||||
var variableInfo = this.getVariableInfo(v);
|
||||
if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
|
||||
allVars[v] = variableInfo.text;
|
||||
var variable = this.parentWidget && this.parentWidget.variables[v];
|
||||
if(variable && variable.isFunctionDefinition) {
|
||||
allVars[v] = variable.value;
|
||||
} else {
|
||||
var variableInfo = this.getVariableInfo(v);
|
||||
allVars[v] = variableInfo.resultList.length > 1 ? variableInfo.resultList : variableInfo.text;
|
||||
}
|
||||
}
|
||||
@@ -94,6 +96,6 @@ LogWidget.prototype.log = function() {
|
||||
console.groupEnd();
|
||||
}
|
||||
console.groupEnd();
|
||||
}
|
||||
};
|
||||
|
||||
exports["action-log"] = LogWidget;
|
||||
|
||||
@@ -34,9 +34,10 @@ DiffTextWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
// Create the diff
|
||||
var dmpObject = new dmp.diff_match_patch(),
|
||||
diffs = dmpObject.diff_main(this.getAttribute("source",""),this.getAttribute("dest",""));
|
||||
// Create the diff object
|
||||
var dmpObject = new dmp.diff_match_patch();
|
||||
dmpObject.Diff_EditCost = $tw.utils.parseNumber(this.getAttribute("editcost","4"));
|
||||
var diffs = dmpObject.diff_main(this.getAttribute("source",""),this.getAttribute("dest",""));
|
||||
// Apply required cleanup
|
||||
switch(this.getAttribute("cleanup","semantic")) {
|
||||
case "none":
|
||||
@@ -132,7 +133,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
||||
*/
|
||||
DiffTextWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.source || changedAttributes.dest || changedAttributes.cleanup) {
|
||||
if(changedAttributes.source || changedAttributes.dest || changedAttributes.cleanup || changedAttributes.editcost) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -252,14 +252,14 @@ RevealWidget.prototype.updateState = function() {
|
||||
this.renderChildren(domNode,null);
|
||||
}
|
||||
// Animate our DOM node
|
||||
if(!domNode.isTiddlyWikiFakeDom && this.type === "popup" && this.isOpen) {
|
||||
this.positionPopup(domNode);
|
||||
$tw.utils.addClass(domNode,"tc-popup"); // Make sure that clicks don't dismiss popups within the revealed content
|
||||
|
||||
}
|
||||
if(this.isOpen) {
|
||||
domNode.removeAttribute("hidden");
|
||||
$tw.anim.perform(this.openAnimation,domNode);
|
||||
// Position popup after making it visible to ensure correct dimensions
|
||||
if(!domNode.isTiddlyWikiFakeDom && this.type === "popup") {
|
||||
this.positionPopup(domNode);
|
||||
$tw.utils.addClass(domNode,"tc-popup"); // Make sure that clicks don't dismiss popups within the revealed content
|
||||
}
|
||||
$tw.anim.perform(this.openAnimation,domNode);
|
||||
} else {
|
||||
$tw.anim.perform(this.closeAnimation,domNode,{callback: function() {
|
||||
//make sure that the state hasn't changed during the close animation
|
||||
|
||||
+357
-196
@@ -9,215 +9,376 @@ View widget
|
||||
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var ViewWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
const Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
==========================================
|
||||
ViewHandler Base Class
|
||||
==========================================
|
||||
Base class for all view format handlers.
|
||||
Provides common functionality and defines the interface for subclasses.
|
||||
*/
|
||||
ViewWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
ViewWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
if(this.text) {
|
||||
var textNode = this.document.createTextNode(this.text);
|
||||
parent.insertBefore(textNode,nextSibling);
|
||||
this.domNodes.push(textNode);
|
||||
} else {
|
||||
this.makeChildWidgets();
|
||||
this.renderChildren(parent,nextSibling);
|
||||
class ViewHandler {
|
||||
constructor(widget) {
|
||||
this.widget = widget;
|
||||
this.wiki = widget.wiki;
|
||||
this.document = widget.document;
|
||||
this.viewTitle = widget.viewTitle;
|
||||
this.viewField = widget.viewField;
|
||||
this.viewIndex = widget.viewIndex;
|
||||
this.viewSubtiddler = widget.viewSubtiddler;
|
||||
this.viewTemplate = widget.viewTemplate;
|
||||
this.viewMode = widget.viewMode;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
ViewWidget.prototype.execute = function() {
|
||||
// Get parameters from our attributes
|
||||
this.viewTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
|
||||
this.viewSubtiddler = this.getAttribute("subtiddler");
|
||||
this.viewField = this.getAttribute("field","text");
|
||||
this.viewIndex = this.getAttribute("index");
|
||||
this.viewFormat = this.getAttribute("format","text");
|
||||
this.viewTemplate = this.getAttribute("template","");
|
||||
this.viewMode = this.getAttribute("mode","block");
|
||||
switch(this.viewFormat) {
|
||||
case "htmlwikified":
|
||||
this.text = this.getValueAsHtmlWikified(this.viewMode);
|
||||
break;
|
||||
case "plainwikified":
|
||||
this.text = this.getValueAsPlainWikified(this.viewMode);
|
||||
break;
|
||||
case "htmlencodedplainwikified":
|
||||
this.text = this.getValueAsHtmlEncodedPlainWikified(this.viewMode);
|
||||
break;
|
||||
case "htmlencoded":
|
||||
this.text = this.getValueAsHtmlEncoded();
|
||||
break;
|
||||
case "htmltextencoded":
|
||||
this.text = this.getValueAsHtmlTextEncoded();
|
||||
break;
|
||||
case "urlencoded":
|
||||
this.text = this.getValueAsUrlEncoded();
|
||||
break;
|
||||
case "doubleurlencoded":
|
||||
this.text = this.getValueAsDoubleUrlEncoded();
|
||||
break;
|
||||
case "date":
|
||||
this.text = this.getValueAsDate(this.viewTemplate);
|
||||
break;
|
||||
case "relativedate":
|
||||
this.text = this.getValueAsRelativeDate();
|
||||
break;
|
||||
case "stripcomments":
|
||||
this.text = this.getValueAsStrippedComments();
|
||||
break;
|
||||
case "jsencoded":
|
||||
this.text = this.getValueAsJsEncoded();
|
||||
break;
|
||||
default: // "text"
|
||||
this.text = this.getValueAsText();
|
||||
break;
|
||||
render(parent, nextSibling) {
|
||||
this.text = this.getValue();
|
||||
this.createTextNode(parent, nextSibling);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
The various formatter functions are baked into this widget for the moment. Eventually they will be replaced by macro functions
|
||||
*/
|
||||
getValue() {
|
||||
return this.widget.getValueAsText();
|
||||
}
|
||||
|
||||
/*
|
||||
Retrieve the value of the widget. Options are:
|
||||
asString: Optionally return the value as a string
|
||||
*/
|
||||
ViewWidget.prototype.getValue = function(options) {
|
||||
options = options || {};
|
||||
var value = options.asString ? "" : undefined;
|
||||
if(this.viewIndex) {
|
||||
value = this.wiki.extractTiddlerDataItem(this.viewTitle,this.viewIndex);
|
||||
} else {
|
||||
var tiddler;
|
||||
if(this.viewSubtiddler) {
|
||||
tiddler = this.wiki.getSubTiddler(this.viewTitle,this.viewSubtiddler);
|
||||
createTextNode(parent, nextSibling) {
|
||||
if(this.text) {
|
||||
const textNode = this.document.createTextNode(this.text);
|
||||
parent.insertBefore(textNode, nextSibling);
|
||||
this.widget.domNodes.push(textNode);
|
||||
} else {
|
||||
tiddler = this.wiki.getTiddler(this.viewTitle);
|
||||
}
|
||||
if(tiddler) {
|
||||
if(this.viewField === "text" && !this.viewSubtiddler) {
|
||||
// Calling getTiddlerText() triggers lazy loading of skinny tiddlers
|
||||
value = this.wiki.getTiddlerText(this.viewTitle);
|
||||
} else {
|
||||
if($tw.utils.hop(tiddler.fields,this.viewField)) {
|
||||
if(options.asString) {
|
||||
value = tiddler.getFieldString(this.viewField);
|
||||
} else {
|
||||
value = tiddler.fields[this.viewField];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(this.viewField === "title") {
|
||||
value = this.viewTitle;
|
||||
}
|
||||
this.widget.makeChildWidgets();
|
||||
this.widget.renderChildren(parent, nextSibling);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsText = function() {
|
||||
return this.getValue({asString: true});
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsHtmlWikified = function(mode) {
|
||||
return this.wiki.renderText("text/html","text/vnd.tiddlywiki",this.getValueAsText(),{
|
||||
parseAsInline: mode !== "block",
|
||||
parentWidget: this
|
||||
});
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsPlainWikified = function(mode) {
|
||||
return this.wiki.renderText("text/plain","text/vnd.tiddlywiki",this.getValueAsText(),{
|
||||
parseAsInline: mode !== "block",
|
||||
parentWidget: this
|
||||
});
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsHtmlEncodedPlainWikified = function(mode) {
|
||||
return $tw.utils.htmlEncode(this.wiki.renderText("text/plain","text/vnd.tiddlywiki",this.getValueAsText(),{
|
||||
parseAsInline: mode !== "block",
|
||||
parentWidget: this
|
||||
}));
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsHtmlEncoded = function() {
|
||||
return $tw.utils.htmlEncode(this.getValueAsText());
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsHtmlTextEncoded = function() {
|
||||
return $tw.utils.htmlTextEncode(this.getValueAsText());
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsUrlEncoded = function() {
|
||||
return $tw.utils.encodeURIComponentExtended(this.getValueAsText());
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsDoubleUrlEncoded = function() {
|
||||
return $tw.utils.encodeURIComponentExtended($tw.utils.encodeURIComponentExtended(this.getValueAsText()));
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsDate = function(format) {
|
||||
format = format || "YYYY MM DD 0hh:0mm";
|
||||
var value = $tw.utils.parseDate(this.getValue());
|
||||
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
|
||||
return $tw.utils.formatDateString(value,format);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsRelativeDate = function(format) {
|
||||
var value = $tw.utils.parseDate(this.getValue());
|
||||
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
|
||||
return $tw.utils.getRelativeDate((new Date()) - (new Date(value))).description;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsStrippedComments = function() {
|
||||
var lines = this.getValueAsText().split("\n"),
|
||||
out = [];
|
||||
for(var line=0; line<lines.length; line++) {
|
||||
var text = lines[line];
|
||||
if(!/^\s*\/\/#/.test(text)) {
|
||||
out.push(text);
|
||||
}
|
||||
}
|
||||
return out.join("\n");
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsJsEncoded = function() {
|
||||
return $tw.utils.stringify(this.getValueAsText());
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
ViewWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.template || changedAttributes.format || changedTiddlers[this.viewTitle]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
refresh() {
|
||||
var self = this;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
Wikified View Handler Base
|
||||
==========================================
|
||||
Base class for wikified view handlers
|
||||
*/
|
||||
class WikifiedViewHandler extends ViewHandler {
|
||||
constructor(widget) {
|
||||
super(widget);
|
||||
this.fakeWidget = null;
|
||||
this.fakeNode = null;
|
||||
}
|
||||
|
||||
render(parent, nextSibling) {
|
||||
this.createFakeWidget();
|
||||
this.text = this.getValue();
|
||||
this.createWikifiedTextNode(parent, nextSibling);
|
||||
}
|
||||
|
||||
createFakeWidget() {
|
||||
this.fakeWidget = this.wiki.makeTranscludeWidget(this.viewTitle, {
|
||||
document: $tw.fakeDocument,
|
||||
field: this.viewField,
|
||||
index: this.viewIndex,
|
||||
parseAsInline: this.viewMode !== "block",
|
||||
mode: this.viewMode === "block" ? "block" : "inline",
|
||||
parentWidget: this.widget,
|
||||
subTiddler: this.viewSubtiddler
|
||||
});
|
||||
this.fakeNode = $tw.fakeDocument.createElement("div");
|
||||
this.fakeWidget.makeChildWidgets();
|
||||
this.fakeWidget.render(this.fakeNode, null);
|
||||
}
|
||||
|
||||
createWikifiedTextNode(parent, nextSibling) {
|
||||
const textNode = this.document.createTextNode(this.text || "");
|
||||
parent.insertBefore(textNode, nextSibling);
|
||||
this.widget.domNodes.push(textNode);
|
||||
}
|
||||
|
||||
refresh(changedTiddlers) {
|
||||
const refreshed = this.fakeWidget.refresh(changedTiddlers);
|
||||
if(refreshed) {
|
||||
const newText = this.getValue();
|
||||
if(newText !== this.text) {
|
||||
this.widget.domNodes[0].textContent = newText;
|
||||
this.text = newText;
|
||||
}
|
||||
}
|
||||
return refreshed;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
Text View Handler
|
||||
==========================================
|
||||
Default handler for plain text display
|
||||
*/
|
||||
class TextViewHandler extends ViewHandler {}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
HTML Wikified View Handler
|
||||
==========================================
|
||||
Handler for wikified HTML content
|
||||
*/
|
||||
class HTMLWikifiedViewHandler extends WikifiedViewHandler {
|
||||
getValue() {
|
||||
return this.fakeNode.innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
Plain Wikified View Handler
|
||||
==========================================
|
||||
Handler for wikified plain text content
|
||||
*/
|
||||
class PlainWikifiedViewHandler extends WikifiedViewHandler {
|
||||
getValue() {
|
||||
return this.fakeNode.textContent;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
HTML Encoded Plain Wikified View Handler
|
||||
==========================================
|
||||
Handler for HTML-encoded wikified plain text
|
||||
*/
|
||||
class HTMLEncodedPlainWikifiedViewHandler extends WikifiedViewHandler {
|
||||
getValue() {
|
||||
return $tw.utils.htmlEncode(this.fakeNode.textContent);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
HTML Encoded View Handler
|
||||
==========================================
|
||||
Handler for HTML-encoded text
|
||||
*/
|
||||
class HTMLEncodedViewHandler extends ViewHandler {
|
||||
getValue() {
|
||||
return $tw.utils.htmlEncode(this.widget.getValueAsText());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
HTML Text Encoded View Handler
|
||||
==========================================
|
||||
Handler for HTML text-encoded content
|
||||
*/
|
||||
class HTMLTextEncodedViewHandler extends ViewHandler {
|
||||
getValue() {
|
||||
return $tw.utils.htmlTextEncode(this.widget.getValueAsText());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
URL Encoded View Handler
|
||||
==========================================
|
||||
Handler for URL-encoded text
|
||||
*/
|
||||
class URLEncodedViewHandler extends ViewHandler {
|
||||
getValue() {
|
||||
return $tw.utils.encodeURIComponentExtended(this.widget.getValueAsText());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
Double URL Encoded View Handler
|
||||
==========================================
|
||||
Handler for double URL-encoded text
|
||||
*/
|
||||
class DoubleURLEncodedViewHandler extends ViewHandler {
|
||||
getValue() {
|
||||
const text = this.widget.getValueAsText();
|
||||
return $tw.utils.encodeURIComponentExtended($tw.utils.encodeURIComponentExtended(text));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
Date View Handler
|
||||
==========================================
|
||||
Handler for date formatting
|
||||
*/
|
||||
class DateViewHandler extends ViewHandler {
|
||||
getValue() {
|
||||
const format = this.viewTemplate || "YYYY MM DD 0hh:0mm";
|
||||
const rawValue = this.widget.getValueAsText();
|
||||
const value = $tw.utils.parseDate(rawValue);
|
||||
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
|
||||
return $tw.utils.formatDateString(value, format);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
Relative Date View Handler
|
||||
==========================================
|
||||
Handler for relative date display
|
||||
*/
|
||||
class RelativeDateViewHandler extends ViewHandler {
|
||||
getValue() {
|
||||
const rawValue = this.widget.getValueAsText();
|
||||
const value = $tw.utils.parseDate(rawValue);
|
||||
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
|
||||
return $tw.utils.getRelativeDate((new Date()) - (new Date(value))).description;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
Strip Comments View Handler
|
||||
==========================================
|
||||
Handler for stripping comments from text
|
||||
*/
|
||||
class StripCommentsViewHandler extends ViewHandler {
|
||||
getValue() {
|
||||
const lines = this.widget.getValueAsText().split("\n");
|
||||
const out = [];
|
||||
for(const text of lines) {
|
||||
if(!/^\s*\/\/#/.test(text)) {
|
||||
out.push(text);
|
||||
}
|
||||
}
|
||||
return out.join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
JS Encoded View Handler
|
||||
==========================================
|
||||
Handler for JavaScript string encoding
|
||||
*/
|
||||
class JSEncodedViewHandler extends ViewHandler {
|
||||
getValue() {
|
||||
return $tw.utils.stringify(this.widget.getValueAsText());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========================================
|
||||
ViewHandlerFactory
|
||||
==========================================
|
||||
Factory for creating appropriate view handlers based on format
|
||||
*/
|
||||
const ViewHandlerFactory = {
|
||||
handlers: {
|
||||
"text": TextViewHandler,
|
||||
"htmlwikified": HTMLWikifiedViewHandler,
|
||||
"plainwikified": PlainWikifiedViewHandler,
|
||||
"htmlencodedplainwikified": HTMLEncodedPlainWikifiedViewHandler,
|
||||
"htmlencoded": HTMLEncodedViewHandler,
|
||||
"htmltextencoded": HTMLTextEncodedViewHandler,
|
||||
"urlencoded": URLEncodedViewHandler,
|
||||
"doubleurlencoded": DoubleURLEncodedViewHandler,
|
||||
"date": DateViewHandler,
|
||||
"relativedate": RelativeDateViewHandler,
|
||||
"stripcomments": StripCommentsViewHandler,
|
||||
"jsencoded": JSEncodedViewHandler
|
||||
},
|
||||
|
||||
createHandler(format, widget) {
|
||||
const HandlerClass = this.handlers[format] || this.handlers["text"];
|
||||
return new HandlerClass(widget);
|
||||
},
|
||||
|
||||
registerHandler(format, handlerClass) {
|
||||
this.handlers[format] = handlerClass;
|
||||
}
|
||||
};
|
||||
|
||||
exports.view = ViewWidget;
|
||||
/*
|
||||
==========================================
|
||||
ViewWidget
|
||||
==========================================
|
||||
Main widget class that orchestrates view handlers
|
||||
*/
|
||||
class ViewWidget extends Widget {
|
||||
constructor(parseTreeNode, options) {
|
||||
super();
|
||||
this.initialise(parseTreeNode, options);
|
||||
}
|
||||
|
||||
render(parent, nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
this.viewHandler = ViewHandlerFactory.createHandler(this.viewFormat, this);
|
||||
this.viewHandler.render(parent, nextSibling);
|
||||
}
|
||||
|
||||
execute() {
|
||||
this.viewTitle = this.getAttribute("tiddler", this.getVariable("currentTiddler"));
|
||||
this.viewSubtiddler = this.getAttribute("subtiddler");
|
||||
this.viewField = this.getAttribute("field", "text");
|
||||
this.viewIndex = this.getAttribute("index");
|
||||
this.viewFormat = this.getAttribute("format", "text");
|
||||
this.viewTemplate = this.getAttribute("template", "");
|
||||
this.viewMode = this.getAttribute("mode", "block");
|
||||
}
|
||||
|
||||
getValue(options = {}) {
|
||||
let value = options.asString ? "" : undefined;
|
||||
if(this.viewIndex) {
|
||||
value = this.wiki.extractTiddlerDataItem(this.viewTitle, this.viewIndex);
|
||||
} else {
|
||||
let tiddler;
|
||||
if(this.viewSubtiddler) {
|
||||
tiddler = this.wiki.getSubTiddler(this.viewTitle, this.viewSubtiddler);
|
||||
} else {
|
||||
tiddler = this.wiki.getTiddler(this.viewTitle);
|
||||
}
|
||||
if(tiddler) {
|
||||
if(this.viewField === "text" && !this.viewSubtiddler) {
|
||||
value = this.wiki.getTiddlerText(this.viewTitle);
|
||||
} else {
|
||||
if($tw.utils.hop(tiddler.fields, this.viewField)) {
|
||||
if(options.asString) {
|
||||
value = tiddler.getFieldString(this.viewField);
|
||||
} else {
|
||||
value = tiddler.fields[this.viewField];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(this.viewField === "title") {
|
||||
value = this.viewTitle;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
getValueAsText() {
|
||||
return this.getValue({asString: true});
|
||||
}
|
||||
|
||||
refresh(changedTiddlers) {
|
||||
const changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index ||
|
||||
changedAttributes.template || changedAttributes.format || changedTiddlers[this.viewTitle]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
return this.viewHandler.refresh(changedTiddlers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.view = ViewWidget;
|
||||
+28
-27
@@ -200,7 +200,7 @@ exports.generateNewTitle = function(baseTitle,options) {
|
||||
c = (parseInt(options.startCount,10) > 0) ? parseInt(options.startCount,10) : 0,
|
||||
prefix = (typeof(options.prefix) === "string") ? options.prefix : " ";
|
||||
|
||||
if (template) {
|
||||
if(template) {
|
||||
// "count" is important to avoid an endless loop in while(...)!!
|
||||
template = (/\$count:?(\d+)?\$/i.test(template)) ? template : template + "$count$";
|
||||
// .formatTitleString() expects strings as input
|
||||
@@ -209,7 +209,7 @@ exports.generateNewTitle = function(baseTitle,options) {
|
||||
title = $tw.utils.formatTitleString(template,{"base":baseTitle,"separator":prefix,"counter":(++c)+""});
|
||||
}
|
||||
} else {
|
||||
if (c > 0) {
|
||||
if(c > 0) {
|
||||
title = baseTitle + prefix + c;
|
||||
}
|
||||
while(this.tiddlerExists(title) || this.isShadowTiddler(title) || this.findDraft(title)) {
|
||||
@@ -532,7 +532,7 @@ exports.getTiddlerLinks = function(title) {
|
||||
return self.extractLinks(parser.tree);
|
||||
}
|
||||
return [];
|
||||
});
|
||||
}).slice(0);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -551,8 +551,9 @@ exports.getTiddlerBacklinks = function(targetTitle) {
|
||||
backlinks.push(title);
|
||||
}
|
||||
});
|
||||
return backlinks;
|
||||
}
|
||||
return backlinks;
|
||||
return backlinks.slice(0);
|
||||
};
|
||||
|
||||
|
||||
@@ -578,7 +579,7 @@ exports.extractTranscludes = function(parseTreeRoot, title) {
|
||||
}
|
||||
}
|
||||
} else if(parseTreeNode.attributes.tiddler) {
|
||||
if (parseTreeNode.attributes.tiddler.type === "string") {
|
||||
if(parseTreeNode.attributes.tiddler.type === "string") {
|
||||
// Old transclude widget usage
|
||||
value = parseTreeNode.attributes.tiddler.value;
|
||||
}
|
||||
@@ -618,7 +619,7 @@ exports.getTiddlerTranscludes = function(title) {
|
||||
return self.extractTranscludes(parser.tree,title);
|
||||
}
|
||||
return [];
|
||||
});
|
||||
}).slice(0);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -630,9 +631,9 @@ exports.getTiddlerBacktranscludes = function(targetTitle) {
|
||||
backtranscludes = backIndexer && backIndexer.subIndexers.transclude.lookup(targetTitle);
|
||||
|
||||
if(!backtranscludes) {
|
||||
backtranscludes = [];
|
||||
return [];
|
||||
}
|
||||
return backtranscludes;
|
||||
return backtranscludes.slice(0);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -641,7 +642,7 @@ Return a hashmap of tiddler titles that are referenced but not defined. Each val
|
||||
exports.getMissingTitles = function() {
|
||||
var self = this,
|
||||
missing = [];
|
||||
// We should cache the missing tiddler list, even if we recreate it every time any tiddler is modified
|
||||
// We should cache the missing tiddler list, even if we recreate it every time any tiddler is modified
|
||||
this.forEachTiddler(function(title,tiddler) {
|
||||
var links = self.getTiddlerLinks(title);
|
||||
$tw.utils.each(links,function(link) {
|
||||
@@ -683,7 +684,7 @@ exports.getTiddlersWithTag = function(tag) {
|
||||
return self.sortByList(tagmap[tag],tag);
|
||||
});
|
||||
}
|
||||
return results;
|
||||
return results.slice(0);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -734,7 +735,7 @@ exports.findListingsOfTiddler = function(targetTitle,fieldName) {
|
||||
for(var i = 0; i < list.length; i++) {
|
||||
var listItem = list[i],
|
||||
listing = listings[listItem] || [];
|
||||
if (listing.indexOf(title) === -1) {
|
||||
if(listing.indexOf(title) === -1) {
|
||||
listing.push(title);
|
||||
}
|
||||
listings[listItem] = listing;
|
||||
@@ -743,7 +744,7 @@ exports.findListingsOfTiddler = function(targetTitle,fieldName) {
|
||||
});
|
||||
return listings;
|
||||
});
|
||||
return listings[targetTitle] || [];
|
||||
return (listings[targetTitle] || []).slice(0);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -782,7 +783,7 @@ exports.sortByList = function(array,listTitle) {
|
||||
}
|
||||
}
|
||||
// If a new position is specified, let's move it
|
||||
if (newPos !== -1) {
|
||||
if(newPos !== -1) {
|
||||
// get its current Pos, and make sure
|
||||
// sure that it's _actually_ in the list
|
||||
// and that it would _actually_ move
|
||||
@@ -1059,7 +1060,7 @@ Options include:
|
||||
exports.parseText = function(type,text,options) {
|
||||
text = text || "";
|
||||
options = options || {};
|
||||
var Parser = $tw.utils.getParser(type,options)
|
||||
var Parser = $tw.utils.getParser(type,options);
|
||||
// Return the parser instance
|
||||
return new Parser(type,text,{
|
||||
parseAsInline: options.parseAsInline,
|
||||
@@ -1078,11 +1079,11 @@ exports.parseTiddler = function(title,options) {
|
||||
tiddler = this.getTiddler(title),
|
||||
self = this;
|
||||
return tiddler ? this.getCacheForTiddler(title,cacheType,function() {
|
||||
if(tiddler.hasField("_canonical_uri")) {
|
||||
options._canonical_uri = tiddler.fields._canonical_uri;
|
||||
}
|
||||
return self.parseText(tiddler.fields.type,tiddler.fields.text,options);
|
||||
}) : null;
|
||||
if(tiddler.hasField("_canonical_uri")) {
|
||||
options._canonical_uri = tiddler.fields._canonical_uri;
|
||||
}
|
||||
return self.parseText(tiddler.fields.type,tiddler.fields.text,options);
|
||||
}) : null;
|
||||
};
|
||||
|
||||
exports.parseTextReference = function(title,field,index,options) {
|
||||
@@ -1138,7 +1139,7 @@ exports.getTextReferenceParserInfo = function(title,field,index,options) {
|
||||
parserInfo.parserType = null;
|
||||
}
|
||||
return parserInfo;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Parse a block of text of a specified MIME type
|
||||
@@ -1164,7 +1165,7 @@ exports.getSubstitutedText = function(text,widget,options) {
|
||||
});
|
||||
// Substitute any variable references with their values
|
||||
return output.replace(/\$\((.+?)\)\$/g, function(match,varname) {
|
||||
return widget.getVariable(varname,{defaultValue: ""})
|
||||
return widget.getVariable(varname,{defaultValue: ""});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1242,7 +1243,7 @@ exports.makeTranscludeWidget = function(title,options) {
|
||||
name: "recursionMarker",
|
||||
type: "string",
|
||||
value: options.recursionMarker || "yes"
|
||||
},
|
||||
},
|
||||
tiddler: {
|
||||
name: "tiddler",
|
||||
type: "string",
|
||||
@@ -1385,7 +1386,7 @@ exports.search = function(text,options) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Accumulate the array of fields to be searched or excluded from the search
|
||||
// Accumulate the array of fields to be searched or excluded from the search
|
||||
var fields = [];
|
||||
if(options.field) {
|
||||
if($tw.utils.isArray(options.field)) {
|
||||
@@ -1518,7 +1519,7 @@ exports.checkTiddlerText = function(title,targetText,options) {
|
||||
targetText = targetText.toLowerCase();
|
||||
}
|
||||
return text === targetText;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Execute an action string without an associated context widget
|
||||
@@ -1642,7 +1643,7 @@ exports.findDraft = function(targetTitle) {
|
||||
}
|
||||
});
|
||||
return draftTitle;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Check whether the specified draft tiddler has been modified.
|
||||
@@ -1669,7 +1670,7 @@ historyTitle: title of history tiddler (defaults to $:/HistoryList)
|
||||
exports.addToHistory = function(title,fromPageRect,historyTitle) {
|
||||
var story = new $tw.Story({wiki: this, historyTitle: historyTitle});
|
||||
story.addToHistory(title,fromPageRect);
|
||||
console.log("$tw.wiki.addToHistory() is deprecated since V5.1.23! Use the this.story.addToHistory() from the story-object!")
|
||||
console.log("$tw.wiki.addToHistory() is deprecated since V5.1.23! Use the this.story.addToHistory() from the story-object!");
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1682,7 +1683,7 @@ options: see story.js
|
||||
exports.addToStory = function(title,fromTitle,storyTitle,options) {
|
||||
var story = new $tw.Story({wiki: this, storyTitle: storyTitle});
|
||||
story.addToStory(title,fromTitle,options);
|
||||
console.log("$tw.wiki.addToStory() is deprecated since V5.1.23! Use the this.story.addToStory() from the story-object!")
|
||||
console.log("$tw.wiki.addToStory() is deprecated since V5.1.23! Use the this.story.addToStory() from the story-object!");
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -25,6 +25,7 @@ title: $:/core/templates/tiddlywiki5.html
|
||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}
|
||||
{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}
|
||||
{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||
<!--~~ Style section start ~~-->
|
||||
</head>
|
||||
<body class="tc-body">
|
||||
<!--~~ Raw markup for the top of the body section ~~-->
|
||||
|
||||
@@ -49,6 +49,27 @@ title: $:/core/ui/ImportListing
|
||||
\end
|
||||
|
||||
\whitespace trim
|
||||
<$let importJson={{{ [{$:/Import}] }}}>
|
||||
<$let importTitles={{{ [<importJson>jsonindexes[tiddlers]] }}}>
|
||||
<$let importTypes={{{ [(importTitles)] :map[<importJson>jsonget[tiddlers],<currentTiddler>,[type]] }}}>
|
||||
<$let anyMatch={{{ [all[shadows+tiddlers]tag[$:/tags/ImportOptions]get[condition]] :map[(importTypes)subfilter<currentTiddler>] +[!is[blank]limit[1]] }}}>
|
||||
<%if [<anyMatch>!is[blank]] %>
|
||||
<div class="tc-import-option">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ImportOptions]]" variable="importOption">
|
||||
<$let condition={{{ [<importOption>get[condition]] }}}>
|
||||
<$let hasMatch={{{ [(importTypes)subfilter<condition>limit[1]] }}}>
|
||||
<%if [<hasMatch>!is[blank]] %>
|
||||
<$transclude tiddler=<<importOption>>/>
|
||||
<%endif%>
|
||||
</$let>
|
||||
</$let>
|
||||
</$list>
|
||||
</div>
|
||||
<%endif%>
|
||||
</$let>
|
||||
</$let>
|
||||
</$let>
|
||||
</$let>
|
||||
<div class="tc-table-wrapper">
|
||||
<table class="tc-import-table">
|
||||
<tbody>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
title: $:/core/ui/RootStylesheet
|
||||
code-body: yes
|
||||
|
||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||
\whitespace trim
|
||||
<$let currentTiddler={{$:/language}} languageTitle={{!!name}}>
|
||||
<style type="text/css">
|
||||
<$view tiddler="$:/themes/tiddlywiki/vanilla/reset" format="text" mode="block"/>
|
||||
</style>
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Stylesheet]!is[draft]] -[[$:/themes/tiddlywiki/vanilla/reset]]">
|
||||
<style type="text/css">
|
||||
<$view format={{{ [<currentTiddler>tag[$:/tags/Stylesheet/Static]then[text]else[plainwikified]] }}} mode="block"/>
|
||||
</style>
|
||||
</$list>
|
||||
</$let>
|
||||
@@ -1,13 +1,12 @@
|
||||
created: 20240313100515958
|
||||
modified: 20241222104855231
|
||||
original-modified: 20240313103959789
|
||||
modified: 20251214111324789
|
||||
original-modified: 20251023154747366
|
||||
tags: Editions
|
||||
title: TiddlyWiki Docs PR Maker
|
||||
ja-title: TiddlyWikiドキュメントPRメーカー
|
||||
|
||||
[[@saqimtiaz|https://github.com/saqimtiaz/]]が作成した''~TiddlyWikiドキュメントPRメーカー''は、ドキュメントへの貢献と改善を支援するために設計された、tiddlywiki.comの特別エディションです。
|
||||
|
||||
https://saqimtiaz.github.io/tw5-docs-pr-maker/
|
||||
''~TiddlyWikiドキュメントPRメーカー''は、ドキュメントへの貢献と改善を支援するために設計された、tiddlywiki.comの特別エディションです。
|
||||
https://edit.tiddlywiki.com
|
||||
|
||||
ドキュメントに加えられたすべての変更は、GitHubに簡単に送信できます。 -- プルリクエストは自動的に作成されるため、エディションの名前は"PRメーカー"になります。
|
||||
|
||||
|
||||
+4
-2
@@ -1,8 +1,10 @@
|
||||
list: HelloThere [[Quick Start]] [[Find Out More]] [[TiddlyWiki on the Web]] [[Testimonials and Reviews]] GettingStarted Community
|
||||
tags: TableOfContents
|
||||
list-before:
|
||||
title: Welcome
|
||||
ja-title: ようこそ
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<list-links filter:"[tag<currentTiddler>]" >>
|
||||
<$transclude $tiddler="HelloThere"/>
|
||||
|
||||
''詳細については、トピックを選択してください:''
|
||||
<div class="tc-table-of-contents"><<toc-selective-expandable "Welcome">></div>
|
||||
@@ -1,6 +1,6 @@
|
||||
created: 20231005205623086
|
||||
modified: 20241226114558500
|
||||
original-modified: 20241115193649399
|
||||
modified: 20251208113045167
|
||||
original-modified: 20250807100434131
|
||||
tags: About
|
||||
title: TiddlyWiki Archive
|
||||
ja-title: TiddlyWikiアーカイブ
|
||||
@@ -10,7 +10,7 @@ ja-title: TiddlyWikiアーカイブ
|
||||
5.1.10 5.1.11 5.1.12 5.1.13 5.1.14 5.1.15 5.1.16 5.1.17 5.1.18 5.1.19
|
||||
5.1.20 5.1.21 5.1.22 5.1.23
|
||||
5.2.0 5.2.1 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7
|
||||
5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6
|
||||
5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.3.8
|
||||
\end
|
||||
|
||||
TiddlyWikiの古いバージョンは[[アーカイブ|https://github.com/TiddlyWiki/tiddlywiki.com-gh-pages/tree/master/archive]]で入手できます:
|
||||
|
||||
@@ -1,31 +1,13 @@
|
||||
created: 20150412191004348
|
||||
modified:
|
||||
original-modified: 20240925114810504
|
||||
modified: 20251208113458455
|
||||
original-modified: 20251022153208584
|
||||
tags: Community Reference
|
||||
title: Developers
|
||||
ja-title: 開発者
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
! [[GitHubの統計|https://github.com/TiddlyWiki/TiddlyWiki5/graphs/contributors]]
|
||||
|
||||
開発者がTiddlyWikiについて学び、開発について議論し、貢献するためのリソースがあります。
|
||||
|
||||
> [img[https://repobeats.axiom.co/api/embed/b92b1b363e2b5f26837ae573a60d39b4248b50a0.svg]]
|
||||
|
||||
* [[tiddlywiki.com/dev|https://tiddlywiki.com/dev]]は公式の開発者ドキュメントです
|
||||
|
||||
* [[GitHubでの開発|https://github.com/TiddlyWiki/TiddlyWiki5]]に参加する
|
||||
|
||||
* [[GitHubディスカッション|https://github.com/TiddlyWiki/TiddlyWiki5/discussions]]はQ&Aとオープンな形式のディスカッションです
|
||||
* [[GitHubイシュー|https://github.com/TiddlyWiki/TiddlyWiki5/issues]]は、バグレポートを作成し、具体的で実現可能な新しいアイデアを提案するためのものです
|
||||
|
||||
* 古い~TiddlyWikiDevGoogleグループは閉鎖され、[[TiddlyWikiトーク|https://talk.tiddlywiki.org/]]と[[GitHubディスカッション|https://github.com/TiddlyWiki/TiddlyWiki5/discussions]]に代わりました
|
||||
** 有用なアーカイブとして残っています: https://groups.google.com/group/TiddlyWikiDev
|
||||
*** 強化されたグループ検索機能は[[mail-archive.com|https://www.mail-archive.com/tiddlywikidev@googlegroups.com/]]で利用できます
|
||||
|
||||
* https://gitter.im/TiddlyWiki/public でチャットしてください(開発ルームは近日公開予定)
|
||||
|
||||
! Twitter
|
||||
|
||||
* 最新ニュースは[[Twitterで@TiddlyWiki|http://twitter.com/#!/TiddlyWiki]]をフォローしてください
|
||||
|
||||
* プロジェクトに貢献する方法についてのガイドラインについては、[[貢献|Contributing]]を参照してください
|
||||
|
||||
@@ -1,88 +1,14 @@
|
||||
created: 20140908114400000
|
||||
modified: 20241225112134741
|
||||
original-modified: 20241016125145988
|
||||
modified: 20251208115007037
|
||||
original-modified: 20251122174540932
|
||||
tags: About
|
||||
title: History of TiddlyWiki
|
||||
ja-title: TiddlyWikiの歴史
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
! ~TiddlyWikiの20年
|
||||
|
||||
~TiddlyWikiの20周年を祝うために、いくつかのライブストリームを開催しました。録画はここで視聴できます:
|
||||
|
||||
* 2024年9月19日 - https://youtube.com/live/z9slx92TyrU
|
||||
* 2024年9月20日 - https://youtube.com/live/puFdN-FgOjg
|
||||
* 2024年9月21日 - https://youtube.com/live/0SjsHvwjHGE
|
||||
* 2024年9月22日 - https://youtube.com/live/oD7Jtq2D4lg
|
||||
|
||||
GitHubでは、TiddlyWikiの貢献者に記念日の感想を[[聞いて|https://github.com/TiddlyWiki/TiddlyWiki5/discussions/7983]]お祝いしました。興味深く思慮深い回答がいくつか寄せられました。たとえば、[[@FND|https://github.com/FND]]からの回答は次の通りです:
|
||||
|
||||
> TiddlyWikiは、私のキャリアだけでなく、価値観にも計り知れないほどの永続的な影響を与えました。今日に至るまで、私はTiddlyWikiから学んだ[[基本的なコンセプト|https://prepitaph.org/articles/creative-privacy/]] - その多くは、他では忘れられたり無視されたりしています - を頻繁に参照しています。このバックグラウンドがあることで、技術的な複雑さを崇拝したり、テクノロジーの世界に人間が存在することを思い出したりする場合でも、この業界で仕事をする上で自分の方向性を保つことができます。
|
||||
|
||||
> TiddlyWikiとは、人々のことです。このコミュニティや、Jeremyがその周りに築いたグループと交流し、そこから学ぶことができたのは、私にとって計り知れない特権でした。また、この特権がまったくの偶然によって私に与えられたものだということを思い出すのにも役立ちます。この恩返しをしていきたいと思います。
|
||||
|
||||
~TiddlyWikiを特集した最近のポッドキャスト:
|
||||
|
||||
* 2016年のチェンジログ ポッドキャスト - https://changelog.com/podcast/196 ~TiddlyWikiの背景について議論しています
|
||||
* 2021年のFloss Weeklyの録画 - https://twit.tv/shows/floss-weekly/episodes/620
|
||||
|
||||
! TiddlyWikiの起源
|
||||
|
||||
遡ること1997年に、同僚が私に[[Ward Cunningham のオリジナル wiki|http://c2.com/cgi/wiki]]を紹介してくれました。これほど強力なものがわずか700行のPerlに収まることに感銘を受け、セキュリティとパーミッションの根本的な再考に魅了されました。他の多くの開発者と同様に、私もあらゆる機会を利用してさまざまなWikiを試し、仕事での使用法を模索しました
|
||||
|
||||
私にとってWikiの魅力は、印刷物中心のドキュメントやEメールの一般的なパラダイムを最終的に破壊する可能性があるという感覚でした
|
||||
|
||||
人々がWikiを使用する様子を数年間観察した結果、パワーユーザーは複数のブラウザタブで複数のWikiページを同時に開く機能を多用しており、ページの比較やレビュー、ページ間でのテキストのコピー、未読ページの一種のキューとして用いることが容易になっていることに気づきました
|
||||
|
||||
一度に複数のページを操作するこの機能がWikiをリファクタリングする機能の中心であると感じました。また、愛情を込めてリファクタリングされたWikiはより便利になる傾向があると一般に認められています。それでも、標準のWikiユーザーインターフェイスは常に、単一ページを一度に表示し操作すること専用にデザインされてきました
|
||||
|
||||
2004年4月にGMailを見たとき、すべての考えがまとまりました。GMailは、Ajaxを巧みに使用して個々のメールをスレッド化された会話に融合させました。
|
||||
|
||||
このアイデアをさらに探求するために、HTMLとJavaScriptを試し始めました。私にはどちらの経験もなく、以前の活動で、いくつかの静的ページと単純なASPサイトをまとめただけでした。これらのクライアント側テクノロジーについて理解するのは大変でした。他の皆さんと同じように、私もWebプログラミングの非互換性と矛盾がどれほど恐ろしいものであるかを知り、愕然としました
|
||||
|
||||
! TiddlyWikiのラウンチ
|
||||
|
||||
そうして、2004年9月に、私は原始的な[[TiddlyWikiの最初のバージョン|https://classic.tiddlywiki.com/firstversion.html]]をリリースしました。これは、アイデアを実証するための最小のもので、シンプルで自己完結型の静的な48KB HTMLファイルでした
|
||||
|
||||
TiddlyWikiの最初のバージョンをこの方法で作成することの欠点は、編集に使用するのが完全に非現実的になることでした。'変更を保存'をクリックすると、ファイルシステムにHTMLページを書き込むために、保存されるデータを示すウィンドウがポップアップ表示されるだけでした
|
||||
|
||||
初期のフィードバックの多くは、TiddlyWikiは優れているが、変更を適切に保存できればさらに便利になるというものでした。ブラウザで実行されているHTMLファイルがローカルファイルシステムに変更を保存することは不可能であることはわかっていると思っていたので、少しイライラしました
|
||||
|
||||
数か月以内に、TiddlyWikiがブラウザに変更を保存できるようにする実験的なFirefox拡張機能を目にしました。コードを調べてみると、ファイルシステムへの書き込みに使用されていたAPIは、`file://` URI経由でロードされている場合に限り、実際には通常のHTMLファイルで利用できることがわかりました
|
||||
|
||||
私はFirefoxコードをTiddlyWikiのコアに適合させ、すぐにInternet Explorerにも同様の機能を追加しました(MicrosoftがInternet Explorerとともに配布した古い[[ActiveX|https://en.wikipedia.org/wiki/ActiveX]]コントロールを利用しています)
|
||||
|
||||
! TiddlyWikiの成長
|
||||
|
||||
TiddlyWikiの成長における大きなマイルストーンは、Nathan Bowersによる"GTDTiddlyWiki"の作成でした。彼はバニラのTiddlyWiki製品を採用し、一般的なGetting Things Done方法論を使用してタスクをトラックするという特定のアプリケーションに適応させました。GTDTiddlyWikiはすぐに人気を博し、[[LifeHacker|https://lifehacker.com/]]などのWebサイトで熱狂的に歓迎されました
|
||||
|
||||
その後数年間にわたって、TiddlyWikiの人気は高まり続け、新しい機能や能力も獲得しました。1年以内に、私はTiddlyWikiでオーダーメイドの開発作業を行うことで自活できるようになり、特にWikiパイオニアである[[SocialText|https://en.wikipedia.org/wiki/Socialtext]]と協力して変更をオンラインサーバと同期する機能に取り組みました
|
||||
|
||||
! BTの獲得
|
||||
|
||||
2007年5月に、[[BT]]は私のコンサルティング会社である[[Osmosoft]]を買収しました。従業員が1人で、収益がほんの少ししかない会社を買収するというのは、異例の決断でした。[[Osmosoft]]は、コミュニティの将来を保証するために私がTiddlyWikiの知的財産をUnaMesaに譲渡したため、TiddlyWikiの知的財産さえ所有していませんでした
|
||||
|
||||
[[BT]]の動機は、コミュニティベースのエコシステムを理解することでした。私は"オープンソースイノベーション責任者"として組織に加わり、オープンソースガバナンスの責任を負い、オープンソースコミュニティへの参加方法に関するアドバイスと専門知識を提供しました
|
||||
|
||||
! [[Osmosoft]]とTiddlySpace
|
||||
|
||||
私はBTに[[Osmosoft]]という名前でチームを作りました。私たちの目的は、オープンソースのメリットを広め、他のチームが実際にそのメリットを実感できるよう支援することでした。また、Webの使用全般、特にWeb標準の使用を普及する必要があることもわかりました
|
||||
|
||||
私たちのアプローチは、話すことよりも見せることに重点を置くことでした。私たちはTiddlyWikiコミュニティと協力してエコシステムを拡張し、BT用の多数の内部システムを構築しました(TiddlyWikiに基づくものもあれば、そうでないものもあります)
|
||||
|
||||
TiddlyWikiコミュニティへの[[Osmosoft]]の主な貢献は、TiddlyWebとTiddlySpaceの作成でした。TiddlyWebは、Tiddlerのための堅牢なインターネット規模のサーバであり、TiddlerのTiddlyWikiビューを構成することもできました。TiddlySpaceは、TiddlyWebをより直接的に使用可能な形式にパッケージ化する試みでした
|
||||
|
||||
! BTを離れる
|
||||
|
||||
2011年の終わりまでに、私はBTという企業の枠外でTiddlyWikiの可能性を実現するのがより適切な立場にあると感じるようになりました。そうして、私は退職して独立した開発者として働き始め、主にTiddlyWiki5という形でTiddlyWikiを新しくリブートすることに取り組みました
|
||||
|
||||
! TiddlyWiki5の開発
|
||||
|
||||
私は2011年11月からTiddlyWikiの新しいリリースに取り組みました。プログラマーとして、すでに書いたものの"バージョン 2.0"に取り組むことは非常に魅力的な提案です。これは、要件が完全に理解され、目的の機能をサポートするために必要なアーキテクチャの進化に集中できることを意味します
|
||||
|
||||
! 将来
|
||||
|
||||
TiddlyWiki5がついに"ベータ"ステータスを脱した今、私の希望は、それが長く存続することです。HTML5とNode.jsの標準機能のみを使用しているため、今後何年にもわたって完全に動作しない理由はありません。私の目標は、少なくとも25年は続けることです
|
||||
|
||||
//Jeremy Ruston, 2014年9月20日//
|
||||
~TiddlyWikiの歴史をまとめています。このプロジェクトは現在進行中です。寄稿や思い出話など、ぜひお寄せください。
|
||||
|
||||
* [[TiddlyWiki物語|The Story of TiddlyWiki]] – [[@Jermolene]]によるTiddlyWikiの物語、その起源と進化に関する個人的な記録
|
||||
* https://github.com/TiddlyWiki/LaunchArchive – 2004年のTiddlyWiki立ち上げ時からのブログとツイート
|
||||
* [[TiddlyWiki記念日|TiddlyWiki Anniversaries]] – TiddlyWikiの主要な記念日のお祝いイベントの記録
|
||||
* [[フィルタシンタックスの歴史|Filter Syntax History]] – TiddlyWiki5におけるフィルタシンタックスの進化の簡単な歴史
|
||||
@@ -0,0 +1,71 @@
|
||||
title: The Story of TiddlyWiki
|
||||
ja-title: TiddlyWiki物語
|
||||
tags: [[History of TiddlyWiki]]
|
||||
modifier: Jeremy Ruston
|
||||
created: 20140908114400000
|
||||
modified: 20251215111120830
|
||||
original-modified: 20250730154331065
|
||||
|
||||
これは、2004年9月20日の最初のリリース以来のTiddlyWikiの起源と進化のストーリーについての個人的な記録です。
|
||||
|
||||
! TiddlyWikiの起源
|
||||
|
||||
遡ること1997年に、同僚が私に[[Ward Cunningham のオリジナル wiki|http://c2.com/cgi/wiki]]を紹介してくれました。これほど強力なものがわずか700行のPerlに収まることに感銘を受け、セキュリティとパーミッションの根本的な再考に魅了されました。他の多くの開発者と同様に、私もあらゆる機会を利用してさまざまなWikiを試し、仕事での使用法を模索しました
|
||||
|
||||
私にとってWikiの魅力は、印刷物中心のドキュメントやEメールの一般的なパラダイムを最終的に破壊する可能性があるという感覚でした
|
||||
|
||||
人々がWikiを使用する様子を数年間観察した結果、パワーユーザーは複数のブラウザタブで複数のWikiページを同時に開く機能を多用しており、ページの比較やレビュー、ページ間でのテキストのコピー、未読ページの一種のキューとして用いることが容易になっていることに気づきました
|
||||
|
||||
一度に複数のページを操作するこの機能がWikiをリファクタリングする機能の中心であると感じました。また、愛情を込めてリファクタリングされたWikiはより便利になる傾向があると一般に認められています。それでも、標準のWikiユーザーインターフェイスは常に、単一ページを一度に表示し操作すること専用にデザインされてきました
|
||||
|
||||
2004年4月にGMailを見たとき、すべての考えがまとまりました。GMailは、Ajaxを巧みに使用して個々のメールをスレッド化された会話に融合させました。
|
||||
|
||||
このアイデアをさらに探求するために、HTMLとJavaScriptを試し始めました。私にはどちらの経験もなく、以前の活動で、いくつかの静的ページと単純なASPサイトをまとめただけでした。これらのクライアント側テクノロジーについて理解するのは大変でした。他の皆さんと同じように、私もWebプログラミングの非互換性と矛盾がどれほど恐ろしいものであるかを知り、愕然としました
|
||||
|
||||
! TiddlyWikiのラウンチ
|
||||
|
||||
そうして、2004年9月に、私は原始的な[[TiddlyWikiの最初のバージョン|https://classic.tiddlywiki.com/firstversion.html]]をリリースしました。これは、アイデアを実証するための最小のもので、シンプルで自己完結型の静的な48KB HTMLファイルでした
|
||||
|
||||
TiddlyWikiの最初のバージョンをこの方法で作成することの欠点は、編集に使用するのが完全に非現実的になることでした。'変更を保存'をクリックすると、ファイルシステムにHTMLページを書き込むために、保存されるデータを示すウィンドウがポップアップ表示されるだけでした
|
||||
|
||||
初期のフィードバックの多くは、TiddlyWikiは優れているが、変更を適切に保存できればさらに便利になるというものでした。ブラウザで実行されているHTMLファイルがローカルファイルシステムに変更を保存することは不可能であることはわかっていると思っていたので、少しイライラしました
|
||||
|
||||
数か月以内に、TiddlyWikiがブラウザに変更を保存できるようにする実験的なFirefox拡張機能を目にしました。コードを調べてみると、ファイルシステムへの書き込みに使用されていたAPIは、`file://` URI経由でロードされている場合に限り、実際には通常のHTMLファイルで利用できることがわかりました
|
||||
|
||||
私はFirefoxコードをTiddlyWikiのコアに適合させ、すぐにInternet Explorerにも同様の機能を追加しました(MicrosoftがInternet Explorerとともに配布した古い[[ActiveX|https://en.wikipedia.org/wiki/ActiveX]]コントロールを利用しています)
|
||||
|
||||
! TiddlyWikiの成長
|
||||
|
||||
TiddlyWikiの成長における大きなマイルストーンは、Nathan Bowersによる"GTDTiddlyWiki"の作成でした。彼はバニラのTiddlyWiki製品を採用し、一般的なGetting Things Done方法論を使用してタスクをトラックするという特定のアプリケーションに適応させました。GTDTiddlyWikiはすぐに人気を博し、[[LifeHacker|https://lifehacker.com/]]などのWebサイトで熱狂的に歓迎されました
|
||||
|
||||
その後数年間にわたって、TiddlyWikiの人気は高まり続け、新しい機能や能力も獲得しました。1年以内に、私はTiddlyWikiでオーダーメイドの開発作業を行うことで自活できるようになり、特にWikiパイオニアである[[SocialText|https://en.wikipedia.org/wiki/Socialtext]]と協力して変更をオンラインサーバと同期する機能に取り組みました
|
||||
|
||||
! BTの獲得
|
||||
|
||||
2007年5月に、[[BT]]は私のコンサルティング会社である[[Osmosoft]]を買収しました。従業員が1人で、収益がほんの少ししかない会社を買収するというのは、異例の決断でした。[[Osmosoft]]は、コミュニティの将来を保証するために私がTiddlyWikiの知的財産をUnaMesaに譲渡したため、TiddlyWikiの知的財産さえ所有していませんでした
|
||||
|
||||
[[BT]]の動機は、コミュニティベースのエコシステムを理解することでした。私は"オープンソースイノベーション責任者"として組織に加わり、オープンソースガバナンスの責任を負い、オープンソースコミュニティへの参加方法に関するアドバイスと専門知識を提供しました
|
||||
|
||||
! [[Osmosoft]]とTiddlySpace
|
||||
|
||||
私はBTに[[Osmosoft]]という名前でチームを作りました。私たちの目的は、オープンソースのメリットを広め、他のチームが実際にそのメリットを実感できるよう支援することでした。また、Webの使用全般、特にWeb標準の使用を普及する必要があることもわかりました
|
||||
|
||||
私たちのアプローチは、話すことよりも見せることに重点を置くことでした。私たちはTiddlyWikiコミュニティと協力してエコシステムを拡張し、BT用の多数の内部システムを構築しました(TiddlyWikiに基づくものもあれば、そうでないものもあります)
|
||||
|
||||
TiddlyWikiコミュニティへの[[Osmosoft]]の主な貢献は、TiddlyWebとTiddlySpaceの作成でした。TiddlyWebは、Tiddlerのための堅牢なインターネット規模のサーバであり、TiddlerのTiddlyWikiビューを構成することもできました。TiddlySpaceは、TiddlyWebをより直接的に使用可能な形式にパッケージ化する試みでした
|
||||
|
||||
! BTを離れる
|
||||
|
||||
2011年の終わりまでに、私はBTという企業の枠外でTiddlyWikiの可能性を実現するのがより適切な立場にあると感じるようになりました。そうして、私は退職して独立した開発者として働き始め、主にTiddlyWiki5という形でTiddlyWikiを新しくリブートすることに取り組みました
|
||||
|
||||
! TiddlyWiki5の開発
|
||||
|
||||
私は2011年11月からTiddlyWikiの新しいリリースに取り組みました。プログラマーとして、すでに書いたものの"バージョン 2.0"に取り組むことは非常に魅力的な提案です。これは、要件が完全に理解され、目的の機能をサポートするために必要なアーキテクチャの進化に集中できることを意味します
|
||||
|
||||
! 将来
|
||||
|
||||
2014年、 TiddlyWiki5を初めてリリースした直後に、私は次のように書きました:
|
||||
|
||||
> TiddlyWiki5がついに"ベータ"ステータスを脱した今、私の希望は、それが長く存続することです。HTML5とNode.jsの標準機能のみを使用しているため、今後何年にもわたって完全に動作しない理由はありません。私の目標は、少なくとも25年は続けることです
|
||||
|
||||
これを書いている時点で、TiddlyWiki5は目標の44%を達成しています。コミュニティの皆様のご支援と熱意により、このプロジェクトは今後も発展し、進化していくと確信しています。
|
||||
@@ -0,0 +1,33 @@
|
||||
title: TiddlyWiki Anniversaries
|
||||
ja-title: TiddlyWiki記念日
|
||||
tags: [[History of TiddlyWiki]]
|
||||
created: 20250730154331065
|
||||
modified: 20251215105745893
|
||||
original-modified: 20250730154331065
|
||||
|
||||
! ~TiddlyWikiの20周年
|
||||
|
||||
~TiddlyWikiの20周年を祝うために、いくつかのライブストリームを開催しました。録画はここで視聴できます:
|
||||
|
||||
* 2024年9月19日 - https://youtube.com/live/z9slx92TyrU
|
||||
* 2024年9月20日 - https://youtube.com/live/puFdN-FgOjg
|
||||
* 2024年9月21日 - https://youtube.com/live/0SjsHvwjHGE
|
||||
* 2024年9月22日 - https://youtube.com/live/oD7Jtq2D4lg
|
||||
|
||||
GitHubでは、TiddlyWikiの貢献者に記念日の感想を[[聞いて|https://github.com/TiddlyWiki/TiddlyWiki5/discussions/7983]]お祝いしました。興味深く思慮深い回答がいくつか寄せられました。たとえば、[[@FND|https://github.com/FND]]からの回答は次の通りです:
|
||||
|
||||
> TiddlyWikiは、私のキャリアだけでなく、価値観にも計り知れないほどの永続的な影響を与えました。今日に至るまで、私はTiddlyWikiから学んだ[[基本的なコンセプト|https://prepitaph.org/articles/creative-privacy/]] - その多くは、他では忘れられたり無視されたりしています - を頻繁に参照しています。このバックグラウンドがあることで、技術的な複雑さを崇拝したり、テクノロジーの世界に人間が存在することを思い出したりする場合でも、この業界で仕事をする上で自分の方向性を保つことができます。
|
||||
|
||||
> TiddlyWikiとは、人々のことです。このコミュニティや、Jeremyがその周りに築いたグループと交流し、そこから学ぶことができたのは、私にとって計り知れない特権でした。また、この特権がまったくの偶然によって私に与えられたものだということを思い出すのにも役立ちます。この恩返しをしていきたいと思います。
|
||||
|
||||
~TiddlyWikiを特集した最近のポッドキャスト:
|
||||
|
||||
* 2016年のチェンジログ ポッドキャスト - https://changelog.com/podcast/196 ~TiddlyWikiの背景について議論しています
|
||||
* 2021年のFloss Weeklyの録画 - https://twit.tv/shows/floss-weekly/episodes/620
|
||||
|
||||
! ~TiddlyWikiの10周年
|
||||
|
||||
2014年9月20日に行われた、TiddlyWikiの10周年を祝うライブストリームはここで視聴できます:
|
||||
|
||||
https://www.youtube.com/watch?v=f_02ZV0J9NY
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
created: 20130909151600000
|
||||
modified: 20241002113817654
|
||||
original-modified: 20210322152237662
|
||||
modified: 20251210110939585
|
||||
original-modified: 20250909171928024
|
||||
tags: TableOfContents Welcome
|
||||
title: Community
|
||||
ja-title: コミュニティ
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.tip "最新の有益なリンクが[[コミュニティリンク収集|Community Links Aggregator]]に集められています。">>
|
||||
TiddlyWikiコミュニティは、TiddlyWikiをより良くするために協力し、お互いにベストを尽せるよう支援する熱心なユーザーと開発者のグループです。
|
||||
|
||||
すべての関連リンクがこれらのエントリに書かれると、メインのtiddlywiki.comサイトからは削除されます。
|
||||
|
||||
<<tabs "Forums Latest Tutorials [[Community Editions]] [[Community Plugins]] [[Community Themes]] [[Community Palettes]] [[Other Resources]] Examples Articles Meetups" "Latest">>
|
||||
<<tabs "[[TiddlyWiki Project]] [[TiddlyWiki People]] Forums" "TiddlyWiki Project">>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
color: #808
|
||||
created: 20241009150445080
|
||||
icon: $:/core/images/link
|
||||
list: TalkTiddlyWiki [[TiddlyWiki on YouTube]] [[TiddlyWiki on Reddit]] [[TiddlyWiki on Discord]] [[TiddlyWiki on GitHub]] [[TiddlyWiki on Mastodon]] [[TiddlyWiki on Twitter]] [[TiddlyWiki on Gitter]] [[TiddlyWiki on Open Collective]]
|
||||
modified: 20241010114936568
|
||||
original-modified: 20241009150453139
|
||||
list: TalkTiddlyWiki [[TiddlyWiki on YouTube]] [[TiddlyWiki on Reddit]] [[TiddlyWiki on Discord]] [[TiddlyWiki on GitHub]] [[TiddlyWiki on Mastodon]] [[TiddlyWiki on Open Collective]]
|
||||
modified: 20251210112417726
|
||||
original-modified: 20241115170824144
|
||||
tags: Welcome
|
||||
title: TiddlyWiki on the Web
|
||||
ja-title: ウェブ上のTiddlyWiki
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
created: 20140610213500000
|
||||
modified: 20241209112247651
|
||||
original-modified: 20241030132047048
|
||||
modified: 20251212111127961
|
||||
original-modified: 20250217154855572
|
||||
tags: Concepts Features
|
||||
title: ExternalImages
|
||||
ja-title: 外部画像
|
||||
@@ -25,22 +25,28 @@ TiddlyWikiの外部画像は、画像データすべてを埋め込むのでは
|
||||
参照される外部画像を含む''images''フォルダーを伴うWikiの静的HTMLファイルバージョンを作成するには、次の手順を使用します:
|
||||
|
||||
# 通常の方法でTiddlyWikiFoldersに画像Tiddlerを作成します
|
||||
# 画像を別ファイルとして保存します (慣例により、''images''という名前のサブフォルダに保存します)
|
||||
# 画像を別ファイルとして保存します (慣例により、''/images''という名前のサブフォルダに保存します)
|
||||
# ''_canonical_uri''フィールドを追加して画像Tiddlerを外部化します
|
||||
# メインのHTMLファイルを保存します
|
||||
|
||||
画像ファイルは外部化する前に保存する必要があることに注意してください。外部化すると、Wikiストアのメモリ内コピーの''text''フィールドが破壊され、保存の試みが失敗します。
|
||||
|
||||
たとえば、''tw5.com'' Wikiの''externalimages''ビルドターゲットを参照してください:
|
||||
!! 外部画像の構成
|
||||
|
||||
たとえば、''tiddlywiki.info''ファイル内に、''externalimages''ビルドターゲットを作成します:
|
||||
|
||||
```
|
||||
--save [is[image]] images
|
||||
--setfield [is[image]] _canonical_uri $:/core/templates/canonical-uri-external-image text/plain
|
||||
--setfield [is[image]] text "" text/plain
|
||||
--render $:/core/save/all externalimages.html text/plain
|
||||
"build": {
|
||||
"externalimages": [
|
||||
--save [is[image]] images
|
||||
--setfield [is[image]] _canonical_uri $:/core/templates/canonical-uri-external-image text/plain
|
||||
--setfield [is[image]] text "" text/plain
|
||||
--render $:/core/save/all externalimages.html text/plain
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
!! 個別の画像ファイルを保存する
|
||||
!! 画像Tiddlerの外部化
|
||||
|
||||
次の`--save`コマンド ([[Saveコマンド|SaveCommand]]を参照)を使用すると、Wikiの画像を''images''サブフォルダーに保存できます:
|
||||
|
||||
@@ -48,8 +54,6 @@ TiddlyWikiの外部画像は、画像データすべてを埋め込むのでは
|
||||
--save [is[image]] images
|
||||
```
|
||||
|
||||
!! 画像Tiddlerの外部化
|
||||
|
||||
2つの`--setfield`コマンドが使用されています: 最初のコマンドは、''_canonical_uri''フィールドをTiddlerのタイトルから派生したURIに設定し、2番目のコマンドはtextフィールドをクリアします。
|
||||
|
||||
```
|
||||
@@ -67,6 +71,20 @@ TiddlyWikiの外部画像は、画像データすべてを埋め込むのでは
|
||||
|
||||
これらの操作により、Wikiストア内のTiddlerが変更されるため、後続のコマンド操作に影響する可能性があることに注意してください。
|
||||
|
||||
!! 外部画像をビルドするためのNode.jsコマンド
|
||||
|
||||
次のコマンドは、`myWiki/output`フォルダー内に外部画像を作成します。
|
||||
|
||||
```
|
||||
tiddlywiki myWiki --build externalimages
|
||||
```
|
||||
|
||||
Windowsでは、次のコマンドを実行すると、[[tw5.comエディション|https://github.com/TiddlyWiki/TiddlyWiki5/blob/master/editions/tw5.com/tiddlywiki.info#L26]]の一部である外部画像が作成されます。ファイルは出力ディレクトリに作成されます。
|
||||
|
||||
```
|
||||
tiddlywiki .\editions\tw5.com --build index
|
||||
```
|
||||
|
||||
! 外部画像の使用について
|
||||
|
||||
URIフィールドを別の画像を指すように変更しない限り、ブラウザで外部画像を直接編集することはできません。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
created: 20150124182127000
|
||||
modified: 20250222110925130
|
||||
original-modified: 20230710074414361
|
||||
modified: 20251213102731461
|
||||
original-modified: 20250731101041336
|
||||
tags: [[Filter Run]]
|
||||
title: Filter Step
|
||||
ja-title: フィルタステップ
|
||||
@@ -13,10 +13,10 @@ type: text/vnd.tiddlywiki
|
||||
<$railroad text="""
|
||||
\start none
|
||||
\end none
|
||||
[:"!"]
|
||||
["!"]
|
||||
( / "省略の場合のデフォルト: title" /|:
|
||||
( - | :[[<"オペレータ">|"Filter Operators"]] )
|
||||
{ [:":" [[<"サフィックス">|"Filter Operators"]] ] } )
|
||||
( :[[<"オペレータ">|"Filter Operators"]] )
|
||||
[ {":" [: [[<"サフィックス">|"Filter Operators"]] ] }] )
|
||||
{ [[<"パラメータ">|"Filter Parameter"]] + "," }
|
||||
"""/>
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
color: #880
|
||||
created: 20241009150347613
|
||||
icon: $:/core/images/help
|
||||
modified: 20241010114029686
|
||||
original-modified: 20241009150430229
|
||||
modified: 20251213103718012
|
||||
original-modified: 20241115170824144
|
||||
tags: Welcome
|
||||
title: Find Out More
|
||||
ja-title: さらに詳しく
|
||||
|
||||
@@ -1,19 +1,41 @@
|
||||
created: 20130822170200000
|
||||
icon: $:/core/icon
|
||||
list: [[A Gentle Guide to TiddlyWiki]] [[Discover TiddlyWiki]] [[Some of the things you can do with TiddlyWiki]] [[Ten reasons to switch to TiddlyWiki]] Examples [[What happened to the original TiddlyWiki?]]
|
||||
modified: 20241010112232871
|
||||
original-modified: 20241009150333146
|
||||
modified: 20251213104120189
|
||||
original-modified: 20250807084952911
|
||||
tags: Welcome
|
||||
title: HelloThere
|
||||
ja-title: こんにちは
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
!!.tc-hero-heading ''TiddlyWikiへようこそ。 TiddlyWikiは複雑な情報を[[収集|Creating and editing tiddlers]]し、[[整理|Structuring TiddlyWiki]]し、[[共有|Sharing your tiddlers with others]]するためのユニークな[[非線形|Philosophy of Tiddlers]]ノートブックです。''
|
||||
<h2
|
||||
style="
|
||||
background: red;
|
||||
padding: 0.5em;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
border-radius: 0.5em;
|
||||
box-shadow: 0 1px 3px 0 #d4d4d5, 0 0 0 1px #d4d4d5;
|
||||
background-image: linear-gradient(90deg, rgb(34, 132, 224), rgb(95, 174, 248), rgb(34, 132, 224));
|
||||
">
|
||||
メモを有効活用する
|
||||
</h2>
|
||||
|
||||
<h2
|
||||
class="tc-hero-heading"
|
||||
style="
|
||||
text-align: center;
|
||||
">
|
||||
TiddlyWikiへようこそ。 TiddlyWikiは複雑な情報を[[収集|Creating and editing tiddlers]]し、[[整理|Structuring TiddlyWiki]]し、[[共有|Sharing your tiddlers with others]]するためのユニークな[[非線形|Philosophy of Tiddlers]]ノートブックです
|
||||
</h2>
|
||||
|
||||
[[ToDo リスト|TaskManagementExample]]を管理したり、[[エッセイや小説|"TiddlyWiki for Scholars" by Alberto Molina]]を練ったり、結婚式を準備したりするために使えます。頭をよぎるすべての考えを記録し、柔軟で応答性の高いWebサイトを構築できます。
|
||||
|
||||
* ~TiddlyWikiを使用すると、データの保存場所を選択でき、今日とったメモを今後数十年も[[使用できること|Future Proof]]が保証されます。
|
||||
* ~TiddlyWikiはデータとコードを単一のHTMLファイルに保存し、インストールや外部依存を必要とせず、Webブラウザのみで動作します
|
||||
|
||||
* ~TiddlyWikiは、新しい機能を追加する多くのプラグインにより、無限にカスタマイズ、拡張可能です。
|
||||
* ~TiddlyWikiを使用すると、データの保存場所を選択でき、今日とったメモを今後数十年も[[使用できること|Future Proof]]が保証されます
|
||||
|
||||
* ~TiddlyWikiは、大規模なユーザーコミュニティの一部である開発者集団の製品です。
|
||||
* ~TiddlyWikiは、新しい機能を追加する多くのプラグインにより、無限にカスタマイズ、拡張可能です
|
||||
|
||||
* ~TiddlyWikiは、大規模なユーザーコミュニティの一部である開発者集団の製品です
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
color: #088
|
||||
icon: $:/core/images/star-filled
|
||||
modified: 20241010114508408
|
||||
original-modified: 20241001141521924
|
||||
modified: 20251214104051278
|
||||
original-modified: 20241115170824144
|
||||
tags: Welcome
|
||||
title: Testimonials and Reviews
|
||||
ja-title: 利用者の声とレビュー
|
||||
|
||||
@@ -2,8 +2,8 @@ color: #cc9
|
||||
created: 20241009163451663
|
||||
icon: $:/core/images/tip
|
||||
list: GettingStarted [[Getting Started Video]] [[Find Out More]] [[TiddlyWiki on the Web]] [[Testimonials and Reviews]]
|
||||
modified: 20241010112536263
|
||||
original-modified: 20241009163521037
|
||||
modified: 20251214103541254
|
||||
original-modified: 20241115170824144
|
||||
tags: Welcome
|
||||
title: Quick Start
|
||||
ja-title: クイックスタート
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
created: 20240907042443909
|
||||
modified: 20241116104031988
|
||||
original-modified: 20240907042629405
|
||||
modified: 20251214104453831
|
||||
original-modified: 20241120225606237
|
||||
tags: [[Hidden Settings]]
|
||||
title: Hidden Setting: Default Tiddler Colour
|
||||
ja-title: 隠し設定: TIddlerのデフォルト色
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
デフォルトのTiddler色は、$:/config/DefaultTiddlerColourというTiddlerを作成し、CSSの色の値を含むことによって指定できます。
|
||||
デフォルトのtag-tiddler色は、$:/config/DefaultTiddlerColourというTiddlerを作成し、CSSの色の値を含むことによって指定できます。詳細については、[[Tiddlerカラーカスケード|Tiddler Colour Cascade]]を参照してください
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
created: 20201228143125000
|
||||
modified: 20241222103744408
|
||||
original-modified: 20201228143125000
|
||||
tags: OfficialPlugins
|
||||
modified: 20251214105341696
|
||||
original-modified: 20250302051857380
|
||||
tags: OfficialPlugins [[Plugin Editions]]
|
||||
title: Share Plugin
|
||||
ja-title: シェアプラグイン
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -11,4 +11,6 @@ type: text/vnd.tiddlywiki
|
||||
この実験的なプラグインは、URL経由でTiddlerを共有するためのツールを提供します。これには以下が含まれます:
|
||||
|
||||
* 起動時にブラウザのロケーションハッシュからTiddlerのグループをロードする機能
|
||||
* TiddlerのグループからURLを作成するためのウィザードとテンプレート
|
||||
* TiddlerのグループからURLを作成するためのウィザードとテンプレート
|
||||
|
||||
デモは[ext[https://tiddlywiki.com/share|share]]を参照してください
|
||||
@@ -1,12 +1,12 @@
|
||||
created: 20130825160900000
|
||||
modified: 20241110103519303
|
||||
original-modified: 20160610083350724
|
||||
modified: 20251214105948181
|
||||
original-modified: 20241106165307259
|
||||
tags: Features [[Working with TiddlyWiki]]
|
||||
title: Encryption
|
||||
ja-title: 暗号化
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
TiddlyWiki5を単一のHTMLファイルとして使用すると、[[Stanford JavaScript Crypto Library]]を使用してコンテンツを暗号化できます。
|
||||
TiddlyWiki5を単一のHTMLファイルとして使用すると、[[Stanford JavaScript Crypto Library]]を使用してCCMモードのAES 128ビット暗号化でコンテンツを暗号化できます。
|
||||
|
||||
# サイドバーの''ツール''タブに切り替えて、南京錠アイコンのボタンを探します
|
||||
# ボタンに<<.icon $:/core/images/unlocked-padlock>> ''パスワードの設定''と表示されている場合、現在のウィキは暗号化されていません。ボタンをクリックすると、以降の保存を暗号化するために使用されるパスワードの入力を求められます
|
||||
|
||||
@@ -4,7 +4,8 @@ created: 20160216191710789
|
||||
delivery: Protocol
|
||||
description: SharePointなどの製品で利用できる標準Webプロトコル
|
||||
method: save
|
||||
modified: 20220615155048712
|
||||
modified: 20251214110658333
|
||||
original-modified: 20220615155048712
|
||||
tags: Android Chrome Firefox [[Internet Explorer]] Linux Mac Opera PHP Safari Saving Windows iOS Edge
|
||||
title: Saving via WebDAV
|
||||
ja-title: WebDAV経由の保存
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
created: 20140908163900000
|
||||
modified: 20241016111248572
|
||||
original-modified: 20201228143412000
|
||||
modified: 20251214112408533
|
||||
original-modified: 20230803052125981
|
||||
tags: Learning
|
||||
title: Sharing your tiddlers with others
|
||||
ja-title: Tiddlerを他の人と共有する
|
||||
@@ -12,7 +12,7 @@ type: text/vnd.tiddlywiki
|
||||
* ~TiddlyWikiをオンラインで公開し、リンクを取得して他の人に送信、または、伝言できます:
|
||||
** ~TiddlyWikiファイル全体のWebアドレスへのリンク
|
||||
** 特定のTiddlerへの[[パーマリンク|PermaLinks]](<<.icon $:/core/images/permalink-button>>)
|
||||
** 現在開いているすべてのTiddlerの[[パーマビュー|PermaViews]](<<.icon $:/core/images/permaview-button>>)リンク
|
||||
** 現在開いているすべてのTiddlerの[[パーマビュー|PermaLinks]](<<.icon $:/core/images/permaview-button>>)リンク
|
||||
* [[TiddlyWikiへのDropboxリンクを共有|Sharing a TiddlyWiki on Dropbox]]できます
|
||||
* テキスト、静的HTML、カンマ区切り値(つまり、スプレッドシート互換)などのさまざまな形式で[[Tiddlerをエクスポート|How to export tiddlers]](<<.icon $:/core/images/export-button>>)できます
|
||||
* また、~TiddlyWikiを他の人がアクセスできるようにするだけで、例えば、オンラインで公開して、そこから[[Tiddlerをインポート|Importing Tiddlers]]できるようにするだけで、Tiddlerを共有できます
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
created: 20211117003509226
|
||||
modified: 20211117003657902
|
||||
modified: 20251119135921343
|
||||
tags: sampletag1 sampletag2 [[Widget Examples]]
|
||||
title: SampleTiddlerFirst
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
This is a test tiddler called SampleTiddlerFirst.
|
||||
This is a test tiddler called SampleTidlerFirst.
|
||||
@@ -0,0 +1,17 @@
|
||||
title: $:/changenotes/5.4.0/#8130
|
||||
created: 20251212171804335
|
||||
modified: 20251212171804335
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: performance
|
||||
change-category: internal
|
||||
description: Different Stylesheets are now included as single `<style>` tags in the Header
|
||||
release: 5.4.0
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/8130
|
||||
github-contributors: BurningTreeC
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Previously, all stylesheets were combined in a single `<style>` tag in the `<head>`.
|
||||
|
||||
Now, a separate `<style>` tag is created in the `<head>` for each stylesheet.
|
||||
|
||||
As part of these changes, the 'view widget' has also been updated. It can now respond dynamically to changes in the 'wikified' formats as well.
|
||||
@@ -0,0 +1,25 @@
|
||||
change-category: internal
|
||||
change-type: security
|
||||
created: 20251115012727571
|
||||
description: Set AES strength to 256 bit default
|
||||
github-contributors: pmario
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/8249
|
||||
modified: 20251115014704622
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#8249
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
This PR changes the default ''AES encryption'' setting ''from 128 bit to 256'' bit.
|
||||
|
||||
* Download [[emtpy.html v5.3.8 from the archve|https://tiddlywiki.com/archive/empty/Empty-TiddlyWiki-5.3.8]] which uses AES 128 bit
|
||||
* Create some content
|
||||
* Save encrypted as eg: ''aes-128.html''
|
||||
* Create aes-256.html with TW v5.4.x
|
||||
* Create some content
|
||||
* Save encrypted as: ''aes-256.html''
|
||||
|
||||
''Import decryption test''
|
||||
|
||||
* Import ''aes-256.html'' into ''aes-128.html'' -> Decryption and import works
|
||||
* Import ''aes-128.html'' into ''aes-256.html'' -> Decryption and import works
|
||||
@@ -0,0 +1,11 @@
|
||||
change-category: theme
|
||||
change-type: enhancement
|
||||
created: 20251115012539668
|
||||
description: Muted palette, minor adjustments
|
||||
github-contributors: pmario
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9015
|
||||
modified: 20251115012705865
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9015
|
||||
type: text/vnd.tiddlywiki
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
change-category: usability
|
||||
change-type: enhancement
|
||||
created: 20251115012214040
|
||||
description: list-links-draggable defaults to currentTiddler if tiddler parameter is missing
|
||||
github-contributors: pmario
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9254
|
||||
modified: 20251115012535958
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9254
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
* If macro `list-links-draggable` misses the tiddler parameter it points to `currentTiddler` variable by default now
|
||||
* Also discussed at [[Talk Tiddlywiki|https://talk.tiddlywiki.org/t/long-standing-bug-in-list-links-draggable-macro/8057]]
|
||||
@@ -0,0 +1,17 @@
|
||||
change-category: developer
|
||||
change-type: enhancement
|
||||
created: 20251115011206881
|
||||
description: Add th-debug-element hook to allow plugins to add additional info
|
||||
github-contributors: pmario
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9281
|
||||
modified: 20251115014302351
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9281
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
This PR adds:
|
||||
|
||||
* `th-dom-rendering-element` hook, that is called right before the DOM node is inserted into the DOM
|
||||
* It allows plugins to add debug info
|
||||
* An example using an experimental hook can be found at: [[#9222|https://github.com/TiddlyWiki/TiddlyWiki5/pull/9222]]
|
||||
@@ -0,0 +1,19 @@
|
||||
change-category: developer
|
||||
change-type: bugfix
|
||||
created: 20251115011834670
|
||||
description: Modules in draft tidders should not be executed
|
||||
github-contributors: pmario
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9293
|
||||
modified: 20251115012143765
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9293
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Modules in draft tiddlers should not be executed.
|
||||
|
||||
This PR:
|
||||
|
||||
* Checks for drafts in `$tw.Wiki.prototype.defineTiddlerModules`
|
||||
* It also reports and blocks draft modules that come from plugins
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
change-category: nodejs
|
||||
change-type: bugfix
|
||||
created: 20251115002825127
|
||||
description: Add output directory to eslint ignore configuration
|
||||
github-contributors: pmario
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9317
|
||||
modified: 20251115011145606
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9317
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
This PR adds the `**/output/**` directory to eslint ignore configuration
|
||||
@@ -0,0 +1,17 @@
|
||||
title: $:/changenotes/5.4.0/#9397
|
||||
description: Fix critical freelinks bugs: first character loss and false positive matches in v5.4.0
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: plugin
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9084 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9397
|
||||
github-contributors: s793016
|
||||
|
||||
This note addresses two major bugs introduced in the Freelinks plugin with the v5.4.0 release:
|
||||
|
||||
Fixes:
|
||||
* First Character Loss: The first character of a matched word would incorrectly disappear (e.g., "The" became "he"). This was fixed by correctly timing the filtering of the current tiddler's title during match validation, ensuring proper substring handling.
|
||||
* False Positive Matches: Unrelated words (like "it is" or "Choose") would incorrectly link to a tiddler title. This was resolved by fixing wrong output merging in the Aho-Corasick failure-link handling, eliminating spurious matches from intermediate nodes, and adding cycle detection.
|
||||
|
||||
Impact:
|
||||
* Significantly improved correctness and reliability of automatic linking for all users, especially in multilingual and large wikis.
|
||||
@@ -0,0 +1,9 @@
|
||||
title: $:/changenotes/5.4.0/#9452
|
||||
description: Add new editcost parameter to diff-text widget
|
||||
tags: $:/tags/ChangeNote
|
||||
release: 5.4.0
|
||||
change-type: feature
|
||||
change-category: widget
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9452
|
||||
github-contributors: pmario
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9454
|
||||
description: Ensure rows parameter of edit-text widget takes precedence
|
||||
tags: $:/tags/ChangeNote
|
||||
release: 5.4.0
|
||||
change-type: feature
|
||||
change-category: widget
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9454
|
||||
github-contributors: pmario
|
||||
|
||||
Edit-text widget rows parameter takes precedence
|
||||
@@ -0,0 +1,15 @@
|
||||
title: $:/changenotes/5.4.0/#9465
|
||||
description: Import UI now conditionally displays file-type-specific import options
|
||||
tags: $:/tags/ChangeNote
|
||||
release: 5.4.0
|
||||
change-type: enhancement
|
||||
change-category: hackability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9465
|
||||
github-contributors: linonetwo
|
||||
|
||||
The import UI now displays import options based on the file types being imported. Import options are only shown when relevant files are detected, an example is:
|
||||
|
||||
```tid
|
||||
tags: $:/tags/ImportOptions
|
||||
condition: [match[text/x-markdown]] :or[match[text/markdown]]
|
||||
```
|
||||
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9489
|
||||
description: Fix ActionLogWidget sluggishness
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: widget
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9489
|
||||
github-contributors: yaisog
|
||||
|
||||
PR #8972 introduced a change in the ActionLogWidget that could lead to a significant slowdown, which has been fixed.
|
||||
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9495
|
||||
description: Protect cached array data from external mutation
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9495
|
||||
github-contributors: yaisog
|
||||
|
||||
Functions returning cached tiddler lists now return shallow copies to prevent external code from inadvertently mutating the cache
|
||||
@@ -0,0 +1,8 @@
|
||||
title: $:/changenotes/5.4.0/#9251/impacts/deprecation
|
||||
changenote: $:/changenotes/5.4.0/#9251
|
||||
created: 20251129130610944
|
||||
modified: 20251129130610953
|
||||
tags: $:/tags/ImpactNote
|
||||
description: Some utility functions are deprecated and are discouraged to be used
|
||||
impact-type: deprecation
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9251
|
||||
description: Deprecate some utility functions
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: deprecation
|
||||
change-category: developer
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9251
|
||||
github-contributors: Leilei332
|
||||
|
||||
Deprecate some utility functions. Some of them are moved to [[$:/core/modules/utils/deprecated.js]].
|
||||
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9496
|
||||
description: Fix RSOE from decodebase64
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: filters
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9496
|
||||
github-contributors: Leilei332
|
||||
|
||||
[[decodebase64 Operator]] now outputs error to the filter operator result.
|
||||
@@ -0,0 +1,14 @@
|
||||
title: $:/changenotes/5.4.0/#9457
|
||||
description: Update eslint configuration
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: developer
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9457 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9474
|
||||
github-contributors: Leilei332
|
||||
|
||||
* Enforce tab indentation, semicolon
|
||||
* Switch off `max-classes-per-file`
|
||||
* Switch on `no-eval` rule and disable it in [[$:/boot/boot.js]] with one comment
|
||||
* Show warning for unused variables
|
||||
* Disable `@stylistic/indent` rule in [[$:/boot/boot.js]] and [[$:/boot/bootprefix.js]]
|
||||
@@ -1,6 +1,6 @@
|
||||
caption: diff-text
|
||||
created: 20180316162725329
|
||||
modified: 20180316162725329
|
||||
modified: 20251117054552220
|
||||
tags: Widgets
|
||||
title: DiffTextWidget
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -39,23 +39,31 @@ In other words, these three invocations are all equivalent:
|
||||
|!Attribute |!Description |
|
||||
|source |The source text |
|
||||
|dest |The destination text |
|
||||
|cleanup |See below |
|
||||
|cleanup |Defines a way to allow diffs to be human readable |
|
||||
|editcost |<<.from-version "5.4.0">> Only active if the cleanup flag is set to "efficient" |
|
||||
|
||||
|
||||
!!! Cleanup Flags
|
||||
|
||||
The ''cleanup'' attribute determines which optional post-processing should be applied to the diffs:
|
||||
|
||||
* ''none'': no cleanup is performed
|
||||
* ''semantic'' (default): rewrites the diffs for human readability
|
||||
* ''efficient'': rewrites the diffs to minimise the number of operations for subsequent processing
|
||||
* ''efficient'': rewrites the diffs to minimise the number of operations for subsequent processing
|
||||
** If efficient is defined, ''editcost'' defines how the cleanup algorithm for human readability works. See example slider
|
||||
|
||||
(Note that in many cases the results will be the same regardless of the cleanup option. See the [[docs|https://github.com/google/diff-match-patch/wiki/API]] of the underlying library for more details).
|
||||
<<.note """Note that in many cases the results will be the same regardless of the cleanup option. See the [[docs|https://github.com/google/diff-match-patch/wiki/API]] of the underlying library for more details""">>
|
||||
|
||||
! Examples
|
||||
|
||||
In this example we compare two texts:
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""<$edit-text tiddler="SampleTiddlerFirst"/>
|
||||
src="""|tc-max-width tc-edit-max-width|k
|
||||
|<$edit-text tiddler="SampleTiddlerFirst" rows="5"/>|<$edit-text tiddler="SampleTiddlerSecond" rows="5"/>|
|
||||
|
||||
<$edit-text tiddler="SampleTiddlerSecond"/>
|
||||
Edit cost: {{$:/temp/SampleTiddlerEditCost}} -- Drag to 7 and then to 33
|
||||
<$range tiddler="$:/temp/SampleTiddlerEditCost" min="1" max="200" default="4" class="tc-max-width"/>
|
||||
|
||||
<$diff-text source={{SampleTiddlerFirst}} dest={{SampleTiddlerSecond}}/>"""/>
|
||||
<$diff-text source={{SampleTiddlerFirst}} dest={{SampleTiddlerSecond}} cleanup=efficiency editcost={{$:/temp/SampleTiddlerEditCost}}/>
|
||||
"""/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
caption: edit-text
|
||||
created: 20131024141900000
|
||||
heading:
|
||||
modified: 20240627184331133
|
||||
modified: 20251118230450156
|
||||
tags: Widgets
|
||||
temp:
|
||||
title: EditTextWidget
|
||||
@@ -11,40 +11,40 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
The edit text widget provides a user interface in the browser for editing text tiddler fields. The editing element is dynamically bound to the underlying tiddler value: changes to the tiddler are instantly reflected, and any edits are instantly propagated.
|
||||
|
||||
By default, applying the EditTextWidget to the `text` field of a tiddler will generates an HTML `<textarea>` element, i.e. a multi-line editor. Applying the EditTextWidget to any other field generates an HTML `<input type="text">` element, a single-line editor. This behaviour can be overridden with the `tag` and `type` attributes.
|
||||
By default, applying the ~EditTextWidget to the `text` field of a tiddler will generates an HTML `<textarea>` element, i.e. a multi-line editor. Applying the ~EditTextWidget to any other field generates an HTML `<input type="text">` element, a single-line editor. This behaviour can be overridden with the `tag` and `type` attributes.
|
||||
|
||||
! Content and Attributes
|
||||
|
||||
The content of the `<$edit-text>` widget is ignored.
|
||||
|
||||
|!Attribute |!Description |
|
||||
|tiddler |The tiddler to edit (defaults to the [[current tiddler|Current Tiddler]]) |
|
||||
|field |The field to edit (defaults to `text`). Takes precedence over the `index` attribute |
|
||||
|tiddler |The tiddler to edit (''defaults'' to the [[current tiddler|Current Tiddler]]) |
|
||||
|field |The field to edit (''defaults'' to `text`). Takes precedence over the `index` attribute |
|
||||
|index |The index to edit |
|
||||
|default |The default text to be provided when the target tiddler doesn't exist |
|
||||
|class |A CSS class to be assigned to the generated HTML editing element |
|
||||
|placeholder |Placeholder text to be displayed when the edit field is empty |
|
||||
|focusPopup |Title of a state tiddler for a popup that is displayed when the editing element has focus |
|
||||
|focus |Set to "yes" or "true" to automatically focus the editor after creation |
|
||||
|focusSelectFromStart |<<.from-version 5.2.6>> If the `focus` attribute is enabled, determines the position of the start of the selection: `0` (default) places the start of the selection at the beginning of the text, `1` places the start of the selection after the first character, etc. |
|
||||
|focusSelectFromEnd |<<.from-version 5.2.6>> If the `focus` attribute is enabled, determines the position of the end of the selection: `0` (default) places the end of the selection at the end of the text, `1` places the start of the selection before the final character, etc. |
|
||||
|focusSelectFromStart |<<.from-version 5.2.6>> If the `focus` attribute is enabled, determines the position of the start of the selection: `0` (''default'') places the start of the selection at the beginning of the text, `1` places the start of the selection after the first character, etc. |
|
||||
|focusSelectFromEnd |<<.from-version 5.2.6>> If the `focus` attribute is enabled, determines the position of the end of the selection: `0` (''default'') places the end of the selection at the end of the text, `1` places the start of the selection before the final character, etc. |
|
||||
|tabindex |Sets the `tabindex` attribute of the input or textarea to the given value |
|
||||
|autocomplete |<<.from-version 5.1.23>> An optional string to provide a hint to the browser how to handle autocomplete for this input |
|
||||
|tag |Overrides the generated HTML editing element tag. For a multi-line editor use `tag=textarea`. For a single-line editor use `tag=input` |
|
||||
|type |Overrides the generated HTML editing element `type` attribute |
|
||||
|size |The size of the input field (in characters). This exact result depends on browser and font. Use the `class` attribute to style width for precise control |
|
||||
|autoHeight |Either "yes" or "no" to specify whether to automatically resize `textarea` editors to fit their content (defaults to "yes") |
|
||||
|minHeight |Minimum height for automatically resized `textarea` editors, specified in CSS length units such as "px", "em" or "%" |
|
||||
|rows|Sets the rows attribute of a generated textarea |
|
||||
|autoHeight |Either "yes" or "no" to specify whether to automatically resize `textarea` editors to fit their content (''defaults'' to "yes"). This setting can be changed globally with an editor toolbar button|
|
||||
|minHeight |Minimum height for automatically resized `textarea` editors, specified in CSS length units such as "px", "em" or "%". Has no effect if the [[CodeMirror Plugin]] is active |
|
||||
|rows|Sets the rows attribute of a generated textarea. `rows` ''takes precedence'' over `autoHeight`, so text areas can be defined individually |
|
||||
|cancelPopups |<<.from-version "5.1.23">> if set to "yes", cancels all popups when the input gets focus |
|
||||
|inputActions |<<.from-version 5.1.23>> Optional actions that are triggered every time an input event occurs within the input field or textarea.<br><<.from-version "5.2.1">> The variable `actionValue` is available to the `inputActions` and contains the value of the input field. |
|
||||
|refreshTitle |<<.from-version 5.1.23>> An optional tiddler title that makes the input field update whenever the specified tiddler changes |
|
||||
|disabled|<<.from-version "5.1.23">> Optional, disables the text input if set to "yes". Defaults to "no"|
|
||||
|fileDrop|<<.from-version "5.2.0">> Optional. When set to "yes" allows dropping or pasting images into the editor to import them. Defaults to "no"|
|
||||
|disabled|<<.from-version "5.1.23">> Optional, disables the text input if set to "yes". ''Defaults'' to "no"|
|
||||
|fileDrop|<<.from-version "5.2.0">> Optional. When set to "yes" allows dropping or pasting images into the editor to import them. ''Defaults'' to "no"|
|
||||
|
||||
! Examples
|
||||
|
||||
If you wanted to change the field //myconfig// of the tiddler //AppSettings//, you could use an EditTextWidget to edit the field, and then show the result anywhere else by using `{{AppSettings!!myconfig}}`. Note that this will create tiddler AppSettings if it doesn't already exist.
|
||||
If you wanted to change the field `myconfig` of the tiddler `AppSettings`, you could use an ~EditTextWidget to edit the field, and then show the result anywhere else by using `{{AppSettings!!myconfig}}`. Note that this will create tiddler AppSettings if it doesn't already exist.
|
||||
|
||||
<$macrocall $name=".example" n="1"
|
||||
eg="""<$edit-text tiddler="AppSettings" field="myconfig"/><p/>
|
||||
@@ -79,7 +79,6 @@ eg="""\procedure onInput()
|
||||
\end
|
||||
|
||||
Type a new tiddler name, starting with the system prefix `$:/`: <$edit-text inputActions=<<onInput>> field="temp" class="tc-edit-texteditor"/>
|
||||
|
||||
"""/>
|
||||
|
||||
|
||||
|
||||
+5
-5
@@ -100,7 +100,7 @@ js.configs.recommended,
|
||||
"id-length": "off",
|
||||
"id-match": "error",
|
||||
"@stylistic/implicit-arrow-linebreak": "error",
|
||||
"@stylistic/indent": "off",
|
||||
"@stylistic/indent": ["error", "tab"],
|
||||
"init-declarations": "off",
|
||||
"@stylistic/jsx-quotes": "error",
|
||||
"@stylistic/key-spacing": "off",
|
||||
@@ -121,7 +121,7 @@ js.configs.recommended,
|
||||
"@stylistic/lines-around-comment": "off",
|
||||
"@stylistic/lines-around-directive": "off",
|
||||
"@stylistic/lines-between-class-members": "error",
|
||||
"max-classes-per-file": "error",
|
||||
"max-classes-per-file": "off",
|
||||
"max-depth": "off",
|
||||
"@stylistic/max-len": "off",
|
||||
"max-lines": "off",
|
||||
@@ -152,7 +152,7 @@ js.configs.recommended,
|
||||
"no-else-return": "off",
|
||||
"no-empty-function": "off",
|
||||
"no-eq-null": "off",
|
||||
"no-eval": "off",
|
||||
"no-eval": "error",
|
||||
"no-extend-native": "off",
|
||||
"no-extra-bind": "off",
|
||||
"no-extra-label": "off",
|
||||
@@ -266,7 +266,7 @@ js.configs.recommended,
|
||||
"require-jsdoc": "off",
|
||||
"require-unicode-regexp": "off",
|
||||
"@stylistic/rest-spread-spacing": "error",
|
||||
"@stylistic/semi": "off",
|
||||
"@stylistic/semi": ["error", "always"],
|
||||
"@stylistic/semi-spacing": "off",
|
||||
"@stylistic/semi-style": "off",
|
||||
"sort-imports": "error",
|
||||
@@ -293,7 +293,7 @@ js.configs.recommended,
|
||||
yoda: "off",
|
||||
// temporary rules
|
||||
"no-useless-escape": "off",
|
||||
"no-unused-vars": "off",
|
||||
"no-unused-vars": "warn",
|
||||
"no-empty": "off",
|
||||
"@stylistic/no-extra-semi": "off",
|
||||
"no-redeclare": "off",
|
||||
|
||||
@@ -131,15 +131,14 @@ Saving/GitService/Gitea/Caption: Gitea Saver
|
||||
Saving/GitService/Gitea/Password: Token de acceso personal para API (a través de la interfaz web de Gitea: `Configuración | Aplicaciones | Generar token nuevo`)
|
||||
Saving/TiddlySpot/Advanced/Heading: Configuración Avanzada
|
||||
Saving/TiddlySpot/BackupDir: Directorio de copias de seguridad
|
||||
Saving/TiddlySpot/ControlPanel: ~TiddlySpot Control Panel
|
||||
Saving/TiddlySpot/ControlPanel: ~TiddlyHost Control Panel
|
||||
Saving/TiddlySpot/Backups: Copias de seguridad
|
||||
Saving/TiddlySpot/Caption: ~TiddlySpot Saver
|
||||
Saving/TiddlySpot/Description: Esta configuración sólo se usa para guardar el wiki en http://tiddlyspot.com o en otro servidor compatible
|
||||
Saving/TiddlySpot/Caption: ~TiddlyHost Saver
|
||||
Saving/TiddlySpot/Description: Esta configuración sólo se usa al guardar el wiki en [[TiddlyHost|https://tiddlyhost.com]] o en otro servidor compatible. [[Ver aquí|https://github.com/simonbaird/tiddlyhost/wiki/TiddlySpot-Saver-configuration-for-Tiddlyhost-and-Tiddlyspot]] para obtener información sobre cómo guardar en ~TiddlyHost
|
||||
Saving/TiddlySpot/Filename: Nombre del archivo
|
||||
Saving/TiddlySpot/Heading: ~TiddlySpot
|
||||
Saving/TiddlySpot/Hint: //La dirección (URL) por defecto de// TiddlySpot //es `http://<wikiname>.tiddlyspot.com/store.cgi` aunque puede cambiarse a voluntad para usar otro servidor//
|
||||
Saving/TiddlySpot/Heading: ~TiddlyHost
|
||||
Saving/TiddlySpot/Hint: //La dirección (URL) por defecto de// TiddlyHost //es `http://<wikiname>.tiddlyspot.com/` aunque puede cambiarse a voluntad para usar otro servidor//
|
||||
Saving/TiddlySpot/Password: Contraseña
|
||||
Saving/TiddlySpot/ReadOnly: Ten en cuenta que [[TiddlySpot|http://tiddlyspot.com]] ya no permite la creación de nuevos sitios. Para sitios nuevos, puede usa [[TiddlyHost|https://tiddlyhost.com]], un nuevo servicio de alojamiento que reemplaza a ~TiddlySpot.
|
||||
Saving/TiddlySpot/ServerURL: Dirección (URL) del servidor
|
||||
Saving/TiddlySpot/UploadDir: Directorio de almacenamiento
|
||||
Saving/TiddlySpot/UserName: Nombre del Wiki
|
||||
@@ -175,6 +174,8 @@ Settings/NavigationPermalinkviewMode/UpdateAddressBar/Description: Actualizar la
|
||||
Settings/PerformanceInstrumentation/Caption: //Estadísticas de rendimiento//
|
||||
Settings/PerformanceInstrumentation/Hint: Muestra estadísticas de las prestaciones de la página en la consola de desarrollo <br>Requiere recargar la página para que surta efecto
|
||||
Settings/PerformanceInstrumentation/Description: Activar //estadísticas de rendimiento//
|
||||
Settings/RecentLimit/Caption: Límite de Recientes
|
||||
Settings/RecentLimit/Hint: Número máximo de tiddlers que se mostrarán en la pestaña "Recientes" de la barra lateral
|
||||
Settings/ToolbarButtonStyle/Caption: Estilo de botón
|
||||
Settings/ToolbarButtonStyle/Hint: Selecciona el estilo de los botones de la barra de herramientas
|
||||
Settings/ToolbarButtonStyle/Styles/Borderless: Sin borde
|
||||
@@ -188,6 +189,8 @@ Settings/DefaultSidebarTab/Caption: Pestaña por defecto de la barra lateral
|
||||
Settings/DefaultSidebarTab/Hint: Indica qué pestaña de la barra lateral se muestra por defecto al inicio
|
||||
Settings/DefaultMoreSidebarTab/Caption: Pestaña predeterminada Más de la barra lateral
|
||||
Settings/DefaultMoreSidebarTab/Hint: Especifica qué pestaña de la barra lateral Más se muestra de forma predeterminada
|
||||
Settings/DefaultTiddlerInfoTab/Caption: Información de tiddler predeterminada
|
||||
Settings/DefaultTiddlerInfoTab/Hint: Especifica qué pestaña se muestra por defecto cuando se abre el panel de información de tiddler
|
||||
Settings/LinkToBehaviour/Caption: Comportamiento al abrir tiddlers...
|
||||
Settings/LinkToBehaviour/InsideRiver/Hint: ...dentro del Visor
|
||||
Settings/LinkToBehaviour/OutsideRiver/Hint: ...desde fuera del Visor
|
||||
@@ -204,10 +207,10 @@ Settings/MissingLinks/Hint: Elige si quieres vincular a tiddlers que aún no exi
|
||||
Settings/MissingLinks/Description: Habilitar enlaces a tiddlers inexistentes
|
||||
SocialCard/Caption: Tarjeta Red Social
|
||||
SocialCard/Domain/Prompt: Nombre de dominio que se mostrará para el enlace (por ejemplo, ''tiddlywiki.com'')
|
||||
SocialCard/Hint: Esta información es utilizada por los servicios de redes sociales y mensajería para mostrar una tarjeta de vista previa para los enlaces a este TiddlyWiki cuando se aloja en línea
|
||||
SocialCard/PreviewUrl/Prompt: URL completa para obtener una vista previa de la imagen de este TiddlyWiki
|
||||
SocialCard/Hint: Esta información es utilizada por los servicios de redes sociales y mensajería para mostrar una tarjeta de vista previa para los enlaces a este ~TiddlyWiki cuando se aloja en línea
|
||||
SocialCard/PreviewUrl/Prompt: URL completa para obtener una vista previa de la imagen de este ~TiddlyWiki
|
||||
SocialCard/PreviewUrl/Preview: Imagen de vista previa:
|
||||
SocialCard/Url/Prompt: URL completa de este TiddlyWiki
|
||||
SocialCard/Url/Prompt: URL completa de este ~TiddlyWiki
|
||||
StoryTiddler/Caption: Tiddler de Historia
|
||||
StoryTiddler/Hint: Esta cascada de reglas se usa para elegir dinámicamente la plantilla para mostrar un tiddler en el río de la historia.
|
||||
StoryView/Caption: Vista
|
||||
@@ -249,3 +252,6 @@ ViewTemplateSubtitle/Caption: Ver Subtítulo de Plantilla
|
||||
ViewTemplateSubtitle/Hint: La plantilla de vista predeterminada utiliza esta regla en cascada para elegir dinámicamente la plantilla para mostrar el subtítulo de un tiddler.
|
||||
ViewTemplateTags/Caption: Ver Etiquetas de Plantilla
|
||||
ViewTemplateTags/Hint: La plantilla de vista predeterminada utiliza esta regla en cascada para elegir dinámicamente la plantilla para mostrar el área de etiquetas de un tiddler.
|
||||
WikiInformation/Caption: Información del Wiki
|
||||
WikiInformation/Hint: Esta página resume información general sobre la configuración de este ~TiddlyWiki. Está diseñada para permitir a los usuarios compartir rápidamente aspectos relevantes de la configuración de su ~TiddlyWiki con otros, por ejemplo, al solicitar ayuda en alguno de los foros. No se incluye información privada o personal, y nada se comparte sin ser copiado y pegado explícitamente en otro lugar.
|
||||
WikiInformation/Drag/Caption: Arrastra este enlace para copiar esta herramienta a otro wiki
|
||||
|
||||
@@ -4,12 +4,12 @@ _canonical_uri: Dirección (URI) completa -absoluta o relativa- de un tiddler ex
|
||||
author: Nombre del autor de un plugin
|
||||
bag: Nombre de la bolsa de la que procede un tiddler
|
||||
caption: Texto que se muestra en una pestaña o botón, con independencia del título del tiddler que lo define
|
||||
class: La clase CSS que se aplica a un tiddler al renderizarlo (consulta [[Estilos personalizados por clase de usuario]]. También se utiliza para [[Modales]]
|
||||
class: La clase CSS que se aplica a un tiddler al renderizarlo. También se utiliza para [[Modales]]
|
||||
code-body: La plantilla de vista mostrará el tiddler como código si se establece en ''yes''
|
||||
color: Valor CSS del color de fondo asociado a un tiddler
|
||||
component: Nombre del componente responsable de un [[tiddler de alerta|AlertMechanism]]
|
||||
component: Nombre del componente responsable de un tiddler de alerta
|
||||
core-version: Para un plugin, indica con qué versión de TiddlyWiki es compatible
|
||||
current-tiddler: Usado para incluir el tiddler superior en una [[historia|HistoryMechanism]]
|
||||
current-tiddler: Usado para incluir el tiddler superior en una historia
|
||||
created: Fecha de creación del tiddler
|
||||
creator: Nombre del autor del tiddler
|
||||
dependents: En un complemento o extensión, lista de sus dependencias
|
||||
|
||||
@@ -96,4 +96,4 @@ TagManager/Info/Heading: Información
|
||||
TagManager/Tag/Heading: Etiqueta
|
||||
Tiddler/DateFormat: DD MMM YYYY a las hh:0mm
|
||||
UnsavedChangesWarning: Tienes cambios sin guardar en TiddlyWiki
|
||||
Yes: Yes
|
||||
Yes: Sí
|
||||
|
||||
@@ -632,6 +632,8 @@ Christian Byron, @CeeBeeTree, 2025/08/05
|
||||
|
||||
Frédéric Demers, @bepuzzled, 2025/08/17
|
||||
|
||||
@bombur51, 2025/09/28
|
||||
|
||||
Joseph Yi, @josephyi, 2025/10/14
|
||||
|
||||
Rishu kumar, @rishu-7549, 2025/10/25
|
||||
|
||||
@@ -122,7 +122,7 @@ function CodeMirrorEngine(options) {
|
||||
self.widget.invokeActionString(self.widget.editInputActions,this,event,{actionValue: this.getText()});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.cm.on("drop",function(cm,event) {
|
||||
if(!self.widget.isFileDropEnabled) {
|
||||
event.stopPropagation(); // Otherwise TW's dropzone widget sees the drop event
|
||||
@@ -257,7 +257,10 @@ CodeMirrorEngine.prototype.getText = function() {
|
||||
Fix the height of textarea to fit content
|
||||
*/
|
||||
CodeMirrorEngine.prototype.fixHeight = function() {
|
||||
if(this.widget.editAutoHeight) {
|
||||
// rows takes precedence
|
||||
if(this.widget.editRows) {
|
||||
this.cm.setSize(null,this.widget.editRows + "em");
|
||||
} else if(this.widget.editAutoHeight) {
|
||||
// Resize to fit
|
||||
this.cm.setSize(null,null);
|
||||
} else {
|
||||
|
||||
@@ -3,8 +3,7 @@ title: $:/core/modules/utils/aho-corasick.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
|
||||
Optimized Aho-Corasick string matching algorithm implementation with enhanced performance
|
||||
and error handling for TiddlyWiki freelinking functionality.
|
||||
Optimized Aho-Corasick string matching algorithm implementation with enhanced performance and error handling for TiddlyWiki freelinking functionality.
|
||||
|
||||
Useage:
|
||||
|
||||
@@ -39,7 +38,7 @@ Notes
|
||||
Word Boundary: Enabling useWordBoundary ensures more precise matches, ideal for link detection scenarios.
|
||||
Compatibility: Ensure compatibility with other TiddlyWiki modules (e.g., wikiparser.js) when processing WikiText.
|
||||
Debugging: Use getStats() to inspect the trie structure's size and ensure it does not overload browser memory.
|
||||
|
||||
|
||||
\*/
|
||||
|
||||
"use strict";
|
||||
@@ -111,14 +110,9 @@ AhoCorasick.prototype.buildFailureLinks = function() {
|
||||
var failureLink = (fail && fail[char]) ? fail[char] : root;
|
||||
this.failure[child] = failureLink;
|
||||
|
||||
var failureOutput = this.failure[child];
|
||||
if(failureOutput && failureOutput.$) {
|
||||
if(!child.$) {
|
||||
child.$ = [];
|
||||
}
|
||||
child.$.push.apply(child.$, failureOutput.$);
|
||||
}
|
||||
|
||||
// Do not merge outputs from failure links during build
|
||||
// Instead, collect matches dynamically by traversing failure links during search
|
||||
|
||||
queue.push(child);
|
||||
}
|
||||
}
|
||||
@@ -143,6 +137,7 @@ AhoCorasick.prototype.search = function(text, useWordBoundary) {
|
||||
var char = text[i];
|
||||
var transitionCount = 0;
|
||||
|
||||
// Follow failure links to find a valid transition
|
||||
while(node && !node[char] && node !== this.trie && transitionCount < this.maxFailureDepth) {
|
||||
node = this.failure[node] || this.trie;
|
||||
transitionCount++;
|
||||
@@ -157,9 +152,19 @@ AhoCorasick.prototype.search = function(text, useWordBoundary) {
|
||||
}
|
||||
}
|
||||
|
||||
// Traverse the current node and its failure link chain to gather all patterns
|
||||
var currentNode = node;
|
||||
var collectCount = 0;
|
||||
var visitedNodes = new Set();
|
||||
|
||||
while(currentNode && collectCount < 10) {
|
||||
// Prevent infinite loops
|
||||
if(visitedNodes.has(currentNode)) {
|
||||
break;
|
||||
}
|
||||
visitedNodes.add(currentNode);
|
||||
|
||||
// Only collect outputs from the current node (not merged ones)
|
||||
if(currentNode.$) {
|
||||
var outputs = currentNode.$;
|
||||
for(var j = 0; j < outputs.length && matches.length < maxMatches; j++) {
|
||||
@@ -167,6 +172,11 @@ AhoCorasick.prototype.search = function(text, useWordBoundary) {
|
||||
var matchStart = i - output.length + 1;
|
||||
var matchEnd = i + 1;
|
||||
|
||||
var matchedText = text.substring(matchStart, matchEnd);
|
||||
if(matchedText !== output.pattern) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(useWordBoundary && !this.isWordBoundaryMatch(text, matchStart, matchEnd)) {
|
||||
continue;
|
||||
}
|
||||
@@ -179,6 +189,7 @@ AhoCorasick.prototype.search = function(text, useWordBoundary) {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
currentNode = this.failure[currentNode];
|
||||
if(currentNode === this.trie) break;
|
||||
collectCount++;
|
||||
|
||||
@@ -84,7 +84,8 @@ TextNodeWidget.prototype.execute = function() {
|
||||
|
||||
if(this.tiddlerTitleInfo.titles.length > 0) {
|
||||
var newParseTree = this.processTextWithMatches(text, currentTiddlerTitle, ignoreCase, useWordBoundary);
|
||||
if(newParseTree.length > 1 || newParseTree[0].type !== "plain-text") {
|
||||
if(newParseTree && newParseTree.length > 0 &&
|
||||
(newParseTree.length > 1 || newParseTree[0].type !== "plain-text")) {
|
||||
childParseTree = newParseTree;
|
||||
}
|
||||
}
|
||||
@@ -94,6 +95,10 @@ TextNodeWidget.prototype.execute = function() {
|
||||
};
|
||||
|
||||
TextNodeWidget.prototype.processTextWithMatches = function(text, currentTiddlerTitle, ignoreCase, useWordBoundary) {
|
||||
if(!text || text.length === 0) {
|
||||
return [{type: "plain-text", text: text}];
|
||||
}
|
||||
|
||||
var searchText = ignoreCase ? text.toLowerCase() : text;
|
||||
var matches;
|
||||
|
||||
@@ -108,8 +113,10 @@ TextNodeWidget.prototype.processTextWithMatches = function(text, currentTiddlerT
|
||||
}
|
||||
|
||||
matches.sort(function(a, b) {
|
||||
var posDiff = a.index - b.index;
|
||||
return posDiff !== 0 ? posDiff : b.length - a.length;
|
||||
if(a.index !== b.index) {
|
||||
return a.index - b.index;
|
||||
}
|
||||
return b.length - a.length;
|
||||
});
|
||||
|
||||
var processedPositions = new FastPositionSet();
|
||||
@@ -120,6 +127,23 @@ TextNodeWidget.prototype.processTextWithMatches = function(text, currentTiddlerT
|
||||
var matchStart = match.index;
|
||||
var matchEnd = matchStart + match.length;
|
||||
|
||||
if(matchStart < 0 || matchEnd > text.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var matchedTitle = this.tiddlerTitleInfo.titles[match.titleIndex];
|
||||
|
||||
var titleToCompare = ignoreCase ?
|
||||
(currentTiddlerTitle ? currentTiddlerTitle.toLowerCase() : "") :
|
||||
currentTiddlerTitle;
|
||||
var matchedTitleToCompare = ignoreCase ?
|
||||
(matchedTitle ? matchedTitle.toLowerCase() : "") :
|
||||
matchedTitle;
|
||||
|
||||
if(titleToCompare && matchedTitleToCompare === titleToCompare) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var hasOverlap = false;
|
||||
for(var pos = matchStart; pos < matchEnd && !hasOverlap; pos++) {
|
||||
if(processedPositions.has(pos)) {
|
||||
@@ -148,39 +172,36 @@ TextNodeWidget.prototype.processTextWithMatches = function(text, currentTiddlerT
|
||||
var matchEnd = matchStart + match.length;
|
||||
|
||||
if(matchStart > currentPos) {
|
||||
var beforeText = text.substring(currentPos, matchStart);
|
||||
newParseTree.push({
|
||||
type: "plain-text",
|
||||
text: text.slice(currentPos, matchStart)
|
||||
text: beforeText
|
||||
});
|
||||
}
|
||||
|
||||
var matchedTitle = this.tiddlerTitleInfo.titles[match.titleIndex];
|
||||
var matchedText = text.substring(matchStart, matchEnd);
|
||||
|
||||
if(matchedTitle === currentTiddlerTitle) {
|
||||
newParseTree.push({
|
||||
newParseTree.push({
|
||||
type: "link",
|
||||
attributes: {
|
||||
to: {type: "string", value: matchedTitle},
|
||||
"class": {type: "string", value: "tc-freelink"}
|
||||
},
|
||||
children: [{
|
||||
type: "plain-text",
|
||||
text: text.slice(matchStart, matchEnd)
|
||||
});
|
||||
} else {
|
||||
newParseTree.push({
|
||||
type: "link",
|
||||
attributes: {
|
||||
to: {type: "string", value: matchedTitle},
|
||||
"class": {type: "string", value: "tc-freelink"}
|
||||
},
|
||||
children: [{
|
||||
type: "plain-text",
|
||||
text: text.slice(matchStart, matchEnd)
|
||||
}]
|
||||
});
|
||||
}
|
||||
text: matchedText
|
||||
}]
|
||||
});
|
||||
|
||||
currentPos = matchEnd;
|
||||
}
|
||||
|
||||
if(currentPos < text.length) {
|
||||
var remainingText = text.substring(currentPos);
|
||||
newParseTree.push({
|
||||
type: "plain-text",
|
||||
text: text.slice(currentPos)
|
||||
text: remainingText
|
||||
});
|
||||
}
|
||||
|
||||
@@ -203,7 +224,6 @@ function computeTiddlerTitleInfo(self, ignoreCase) {
|
||||
var validTitles = [];
|
||||
var ac = new AhoCorasick();
|
||||
|
||||
// Process titles in a single pass to avoid duplication
|
||||
for(var i = 0; i < titles.length; i++) {
|
||||
var title = titles[i];
|
||||
if(title && title.length > 0 && title.substring(0,3) !== "$:/") {
|
||||
@@ -214,17 +234,16 @@ function computeTiddlerTitleInfo(self, ignoreCase) {
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by length (descending) then alphabetically
|
||||
// Longer titles are prioritized to avoid partial matches (e.g., "JavaScript" before "Java")
|
||||
var sortedTitles = validTitles.sort(function(a,b) {
|
||||
var lenDiff = b.length - a.length;
|
||||
return lenDiff !== 0 ? lenDiff : (a < b ? -1 : a > b ? 1 : 0);
|
||||
if(lenDiff !== 0) return lenDiff;
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
});
|
||||
|
||||
// Build Aho-Corasick automaton
|
||||
for(var i = 0; i < sortedTitles.length; i++) {
|
||||
var title = sortedTitles[i];
|
||||
ac.addPattern(ignoreCase ? title.toLowerCase() : title, i);
|
||||
var pattern = ignoreCase ? title.toLowerCase() : title;
|
||||
ac.addPattern(pattern, i);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -2395,6 +2395,17 @@ html body.tc-body.tc-single-tiddler-window {
|
||||
** Import table
|
||||
*/
|
||||
|
||||
.tc-import-option {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
margin: 0.5em 0;
|
||||
padding: 0.5em;
|
||||
background: <<colour tiddler-editor-background>>;
|
||||
border: 1px solid <<colour tiddler-editor-border>>;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.tc-import-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user