1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-07-06 20:14:22 +00:00
TiddlyWiki5/plugins/tiddlywiki/text-slicer/slicer.js

234 lines
7.1 KiB
JavaScript
Raw Normal View History

/*\
title: $:/plugins/tiddlywiki/text-slicer/slicer.js
type: application/javascript
module-type: startup
Setup the root widget event handlers
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "slicer";
exports.platforms = ["browser"];
exports.after = ["startup"];
exports.synchronous = true;
var SLICER_OUTPUT_TITLE = "$:/TextSlicer";
// Install the root widget event handlers
exports.startup = function() {
$tw.rootWidget.addEventListener("tm-slice-tiddler",function(event) {
var slicer = new Slicer($tw.wiki,event.param);
// slicer.sliceTiddler();
// slicer.outputTiddlers();
// Slice up and output the tiddler
slicer.outputTiddlers(slicer.sliceTiddler(event.param),event.param,event.param);
slicer.destroy();
});
};
function Slicer(wiki,sourceTitle) {
this.wiki = wiki;
this.sourceTitle = sourceTitle;
this.currentId = 0;
this.iframe = null; // Reference to iframe used for HTML parsing
}
Slicer.prototype.destroy = function() {
// Remove the iframe from the DOM
if(this.iframe && this.iframe.parentNode) {
this.iframe.parentNode.removeChild(this.iframe);
}
};
Slicer.prototype.nextId = function() {
return ++this.currentId;
};
Slicer.prototype.getSourceHtmlDocument = function(tiddler) {
this.iframe = document.createElement("iframe");
document.body.appendChild(this.iframe);
this.iframe.contentWindow.document.open();
this.iframe.contentWindow.document.write(tiddler.fields.text);
this.iframe.contentWindow.document.close();
return this.iframe.contentWindow.document;
};
Slicer.prototype.getSourceWikiDocument = function(tiddler) {
var widgetNode = this.wiki.makeTranscludeWidget(this.sourceTitle,{document: $tw.fakeDocument, parseAsInline: false}),
container = $tw.fakeDocument.createElement("div");
widgetNode.render(container,null);
return container;
};
Slicer.prototype.getSourceDocument = function() {
var tiddler = $tw.wiki.getTiddler(this.sourceTitle);
if(tiddler.fields.type === "text/html") {
return this.getSourceHtmlDocument(tiddler);
} else {
return this.getSourceWikiDocument(tiddler);
}
};
// Slice a tiddler into individual tiddlers
Slicer.prototype.sliceTiddler = function(title) {
var self = this,
tiddlers = {},
domNode = this.getSourceDocument(),
parentStack = [],
addTiddler = function(fields) {
if(fields.title) {
tiddlers[fields.title] = $tw.utils.extend({},tiddlers[fields.title],fields);
return fields.title;
} else {
return null;
}
},
addToList = function(parent,child) {
var parentTiddler = tiddlers[parent] || {},
parentList = parentTiddler.list || [];
parentList.push(child);
addTiddler($tw.utils.extend({title: parent},parentTiddler,{list: parentList}));
},
convertTypeToLevel = function(type) {
if(type.charAt(0) === "h") {
return parseInt(type.charAt(1),10);
} else {
return null;
}
},
popParentStackUntil = function(type) {
// Pop the stack to remove any entries at the same or lower level
var newLevel = convertTypeToLevel(type),
topIndex = parentStack.length - 1;
do {
var topLevel = convertTypeToLevel(parentStack[parentStack.length - 1].type);
if(topLevel !== null && topLevel < newLevel ) {
break;
}
parentStack.length--;
} while(true);
return parentStack[parentStack.length - 1].title;
},
isBlank = function(s) {
return (/^[\s\xA0]*$/mg).test(s);
},
processNodeList = function(domNodeList) {
$tw.utils.each(domNodeList,function(domNode) {
var parentTitle,
text = domNode.textContent,
nodeType = domNode.nodeType;
if(nodeType === 1) {
var tagName = domNode.tagName.toLowerCase();
if(tagName === "p" && (domNode.getAttribute("style") || "").indexOf("mso-list:") !== -1) {
tagName = "li";
}
if(tagName === "h1" || tagName === "h2" || tagName === "h3" || tagName === "h4") {
if(!isBlank(text)) {
parentTitle = popParentStackUntil(tagName);
addToList(parentTitle,text);
parentStack.push({type: tagName, title: addTiddler({
title: text,
text: "<<display-heading-tiddler level:'" + tagName + "'>>",
list: [],
tags: [parentTitle]
})});
}
} else if(tagName === "ul" || tagName === "ol") {
var listTitle = title + "-list-" + self.nextId();
parentTitle = parentStack[parentStack.length - 1].title;
addToList(parentTitle,listTitle);
parentStack.push({type: tagName, title: addTiddler({
title: listTitle,
text: "<<display-list-tiddler type:'" + tagName + "'>>",
list: [],
tags: [parentTitle]
})});
processNodeList(domNode.childNodes);
parentStack.pop();
} else if(tagName === "li") {
if(!isBlank(text)) {
var listItemTitle = title + "-listitem-" + self.nextId();
parentTitle = parentStack[parentStack.length - 1].title;
addToList(parentTitle,listItemTitle);
addTiddler({
title: listItemTitle,
text: text,
list: [],
tags: [parentTitle]
});
}
} else if(tagName === "p") {
if(!isBlank(text)) {
parentTitle = parentStack[parentStack.length - 1].title;
addToList(parentTitle,addTiddler({
title: title + "-para-" + self.nextId(),
text: text,
tags: [parentTitle]
}));
}
} else if(domNode.hasChildNodes()) {
processNodeList(domNode.childNodes);
}
}
});
};
parentStack.push({type: "h0", title: addTiddler({
title: "Sliced up " + title,
text: "{{||$:/plugins/tiddlywiki/text-slicer/templates/display-document}}",
list: []
})});
console.log(domNode);
processNodeList(domNode.childNodes);
return tiddlers;
};
// Output directly to the output tiddlers
Slicer.prototype.outputTiddlers = function(tiddlers,title,navigateFromTitle) {
$tw.utils.each(tiddlers,function(tiddlerFields) {
var title = tiddlerFields.title;
if(title) {
$tw.wiki.addTiddler(new $tw.Tiddler($tw.wiki.getCreationFields(),tiddlerFields,$tw.wiki.getModificationFields()));
}
});
// Navigate to output
var story = new $tw.Story({wiki: $tw.wiki});
story.navigateTiddler("Sliced up " + title,navigateFromTitle);
};
// Output via an import tiddler
Slicer.prototype.outputTiddlers_viaImportTiddler = function(tiddlers,navigateFromTitle) {
// Get the current slicer output tiddler
var slicerOutputTiddler = $tw.wiki.getTiddler(SLICER_OUTPUT_TITLE),
slicerOutputData = $tw.wiki.getTiddlerData(SLICER_OUTPUT_TITLE,{}),
newFields = new Object({
title: SLICER_OUTPUT_TITLE,
type: "application/json",
"plugin-type": "import",
"status": "pending"
});
// Process each tiddler
slicerOutputData.tiddlers = slicerOutputData.tiddlers || {};
$tw.utils.each(tiddlers,function(tiddlerFields) {
var title = tiddlerFields.title;
if(title) {
slicerOutputData.tiddlers[title] = tiddlerFields;
}
});
// Save the slicer output tiddler
newFields.text = JSON.stringify(slicerOutputData,null,$tw.config.preferences.jsonSpaces);
$tw.wiki.addTiddler(new $tw.Tiddler(slicerOutputTiddler,newFields));
// Navigate to output
var story = new $tw.Story({wiki: $tw.wiki});
story.navigateTiddler(SLICER_OUTPUT_TITLE,navigateFromTitle);
};
})();