1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-12-27 18:40:28 +00:00

Add slugify and duplicateslugs operators

Fixes #3379
This commit is contained in:
jeremy@jermolene.com 2020-05-09 15:54:44 +01:00
parent 33d973fb91
commit 4966f6ab62
6 changed files with 140 additions and 0 deletions

View File

@ -0,0 +1,36 @@
/*\
title: $:/core/modules/filters/duplicateslugs.js
type: application/javascript
module-type: filteroperator
Filter function for [duplicateslugs[]]
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.duplicateslugs = function(source,operator,options) {
var slugs = Object.create(null), // Hashmap by slug of title, replaced with "true" if the duplicate title has already been output
results = [];
source(function(tiddler,title) {
var slug = options.wiki.slugify(title);
if(slug in slugs) {
if(slugs[slug] !== true) {
results.push(slugs[slug]);
slugs[slug] = true;
}
results.push(title);
} else {
slugs[slug] = title;
}
});
return results;
};
})();

View File

@ -0,0 +1,23 @@
/*\
title: $:/plugins/tiddlywiki/static/filters/slugify.js
type: application/javascript
module-type: filteroperator
Filter operator for slugifying a tiddler title
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.slugify = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(options.wiki.slugify(title));
});
return results;
};
})();

View File

@ -1503,5 +1503,30 @@ exports.doesPluginInfoRequireReload = function(pluginInfo) {
}
};
exports.slugify = function(title,options) {
var tiddler = this.getTiddler(title),
slug;
if(tiddler && tiddler.fields.slug) {
slug = tiddler.fields.slug;
} else {
slug = $tw.utils.transliterate(title.toString().toLowerCase()) // Replace diacritics with basic lowercase ASCII
.replace(/\s+/g,"-") // Replace spaces with -
.replace(/[^\w\-\.]+/g,"") // Remove all non-word chars except dash and dot
.replace(/\-\-+/g,"-") // Replace multiple - with single -
.replace(/^-+/,"") // Trim - from start of text
.replace(/-+$/,""); // Trim - from end of text
}
// If the resulting slug is blank (eg because the title is just punctuation characters)
if(!slug) {
// ...then just use the character codes of the title
var result = [];
$tw.utils.each(title.split(""),function(char) {
result.push(char.charCodeAt(0).toString());
});
slug = result.join("-");
}
return slug;
};
})();

View File

@ -94,6 +94,7 @@ function setupWiki(wikiOptions) {
tags: ["one"],
cost: "123",
value: "120",
slug: "tiddler-one",
authors: "Joe Bloggs",
modifier: "JoeBloggs",
modified: "201304152222"});
@ -103,6 +104,7 @@ function setupWiki(wikiOptions) {
tags: ["two"],
cost: "42",
value: "190",
slug: "tiddler-two",
authors: "[[John Doe]]",
modifier: "John",
modified: "201304152211"});
@ -669,6 +671,14 @@ function runTests(wiki) {
expect(wiki.filterTiddlers("b a b c +[sortby[b a c b]]").join(",")).toBe("b,a,c");
});
it("should handle the slugify operator", function() {
expect(wiki.filterTiddlers("[[Joe Bloggs]slugify[]]").join(",")).toBe("joe-bloggs");
expect(wiki.filterTiddlers("[[Joe Bloggs2]slugify[]]").join(",")).toBe("joe-bloggs2");
expect(wiki.filterTiddlers("[[@£$%^&*((]slugify[]]").join(",")).toBe("64-163-36-37-94-38-42-40-40");
expect(wiki.filterTiddlers("One one ONE O!N!E +[slugify[]]").join(",")).toBe("one,one,one,one");
expect(wiki.filterTiddlers("TiddlerOne $:/TiddlerTwo +[slugify[]]").join(",")).toBe("tiddler-one,tiddler-two");
});
it("should handle the sortsub operator", function() {
var widget = require("$:/core/modules/widgets/widget.js");
var rootWidget = new widget.widget({ type:"widget", children:[ {type:"widget", children:[]} ] },

View File

@ -0,0 +1,22 @@
caption: duplicateslugs
created: 20200509141702846
modified: 20200509141702846
op-input: a [[selection of titles|Title Selection]]
op-output: the input titles transformed so that they only contain lower case letters, numbers, periods, dashes and underscores
op-purpose: returns each item in the list in a human-readable form for use in URLs or filenames
tags: [[Filter Operators]]
title: duplicateslugs Operator
type: text/vnd.tiddlywiki
<<.from-version "5.1.23">> The <<.olink slugify>> can be used to transform arbitrary tiddler titles into human readable strings suitable for use in URLs or filenames. However, itis possible for multiple different titles to slugify to the same string. The <<.olink duplicateslugs>> operator can be used to display a warning. For example:
<$macrocall $name='wikitext-example-without-html'
src='<$list filter="[!is[system]duplicateslugs[]limit[1]]" emptyMessage="There are no duplicate slugs">
The following tiddlers have duplicate slugs:
<ul>
<$list filter="[!is[system]duplicateslugs[]]">
<li><$link><$text text=<<currentTiddler>>/></$link></li>
</$list>
</ul>
</$list>'/>

View File

@ -0,0 +1,24 @@
caption: slugify
created: 20200509141702846
modified: 20200509141702846
op-input: a [[selection of titles|Title Selection]]
op-output: the input titles transformed so that they only contain lower case letters, numbers, periods, dashes and underscores
op-purpose: returns each item in the list in a human-readable form for use in URLs or filenames
tags: [[Filter Operators]]
title: slugify Operator
type: text/vnd.tiddlywiki
<<.from-version "5.1.23">> The transformation applied by the slugify operator follows these steps:
* If there is a tiddler with the same title that has a ''slug'' field, then return that field instead of running the following steps
* Replace uppercase letters with lowercase equivalents
* Transliterate diacritics to their basic lowercase ASCII equivalents (for example, "Æ" is transliterated to "AE")
* Replace spaces with dashes
* Remove all non-word characters except dashes and periods
* Replace multiple sequential dashes with a single dash
* Trim dashes from start and end
* If the result is the empty string then character codes are used instead (eg. "&£@" transforms to "38-163-64")
Note that it is possible for more than one title to slugify to the same string. The <<.olink duplicateslugs>> can be used to alert authors to any clashes.
<<.operator-examples "slugify">>