mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-26 18:10:27 +00:00
Merge branch 'master' of https://github.com/Jermolene/TiddlyWiki5 into zh
This commit is contained in:
commit
3a70ddb235
@ -1547,6 +1547,9 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
|||||||
case "basename":
|
case "basename":
|
||||||
value = path.basename(filename,path.extname(filename));
|
value = path.basename(filename,path.extname(filename));
|
||||||
break;
|
break;
|
||||||
|
case "basename-uri-decoded":
|
||||||
|
value = decodeURIComponent(path.basename(filename,path.extname(filename)));
|
||||||
|
break;
|
||||||
case "extname":
|
case "extname":
|
||||||
value = path.extname(filename);
|
value = path.extname(filename);
|
||||||
break;
|
break;
|
||||||
@ -1931,6 +1934,7 @@ $tw.boot.startup = function(options) {
|
|||||||
$tw.utils.registerFileType("application/enex+xml","utf8",".enex");
|
$tw.utils.registerFileType("application/enex+xml","utf8",".enex");
|
||||||
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","base64",".xlsx");
|
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","base64",".xlsx");
|
||||||
$tw.utils.registerFileType("application/x-bibtex","utf8",".bib");
|
$tw.utils.registerFileType("application/x-bibtex","utf8",".bib");
|
||||||
|
$tw.utils.registerFileType("application/epub+zip","base64",".epub");
|
||||||
// Create the wiki store for the app
|
// Create the wiki store for the app
|
||||||
$tw.wiki = new $tw.Wiki();
|
$tw.wiki = new $tw.Wiki();
|
||||||
// Install built in tiddler fields modules
|
// Install built in tiddler fields modules
|
||||||
|
@ -24,6 +24,7 @@ Each field can be specified as either a ''string'' or ''array'' value to be assi
|
|||||||
* ''source'' - (optional) a string specifying the source value for the field. If not specified, the existing value is used
|
* ''source'' - (optional) a string specifying the source value for the field. If not specified, the existing value is used
|
||||||
** //filename// the filename of the file containing the tiddler
|
** //filename// the filename of the file containing the tiddler
|
||||||
** //basename// the filename of the file containing the tiddler without any extension
|
** //basename// the filename of the file containing the tiddler without any extension
|
||||||
|
** //basename-uri-decoded// the filename of the file containing the tiddler without any extension, with [[URI decoding|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent]] applied
|
||||||
** //extname// the extension of the filename of the file containing the tiddler
|
** //extname// the extension of the filename of the file containing the tiddler
|
||||||
** //created// the creation date/time of the file containing the tiddler
|
** //created// the creation date/time of the file containing the tiddler
|
||||||
** //modified// the modification date/time of the file containing the tiddler
|
** //modified// the modification date/time of the file containing the tiddler
|
||||||
@ -61,13 +62,14 @@ There are also several examples of `tiddlywiki.files` files in the main [[Tiddly
|
|||||||
|
|
||||||
!! Importing a folder of PDFs
|
!! Importing a folder of PDFs
|
||||||
|
|
||||||
This example retrieves all the files with the extension `.pdf` from a folder specified by a relative path. Each tiddler is given the following fields:
|
This example retrieves all the files with the extension `.pdf` from a folder specified by a relative path. Each tiddler is set up for LazyLoading with the following fields:
|
||||||
|
|
||||||
* ''title'' - set to the filename of the PDF file
|
* ''title'' - set to the URI decoded base filename of the PDF file. [[URI decoding|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent]] allows characters like "/" to be included in titles by URI encoding them as "%2F"
|
||||||
* ''created'' - set to the creation date/time of the PDF file
|
* ''created'' - set to the creation date/time of the PDF file
|
||||||
* ''modified'' - set to the modification date/time of the PDF file
|
* ''modified'' - set to the modification date/time of the PDF file
|
||||||
* ''type'' - set to `application/pdf`
|
* ''type'' - set to `application/pdf`
|
||||||
* ''tags'' - set to `$:/tags/AttachedFile`
|
* ''tags'' - set to `$:/tags/AttachedFile`
|
||||||
|
* ''text'' - set to an empty string
|
||||||
* ''_canonical_uri'' - set to the string "pdfs/" concatenated with the filename
|
* ''_canonical_uri'' - set to the string "pdfs/" concatenated with the filename
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -78,16 +80,15 @@ This example retrieves all the files with the extension `.pdf` from a folder spe
|
|||||||
"filesRegExp": "^.*\\.pdf$",
|
"filesRegExp": "^.*\\.pdf$",
|
||||||
"isTiddlerFile": false,
|
"isTiddlerFile": false,
|
||||||
"fields": {
|
"fields": {
|
||||||
"title": {"source": "filename"},
|
"title": {"source": "basename-uri-decoded"},
|
||||||
"created": {"source": "created"},
|
"created": {"source": "created"},
|
||||||
"modified": {"source": "modified"},
|
"modified": {"source": "modified"},
|
||||||
"type": "application/pdf",
|
"type": "application/pdf",
|
||||||
"tags": ["$:/tags/AttachedFile"],
|
"tags": ["$:/tags/AttachedFile"],
|
||||||
|
"text": "",
|
||||||
"_canonical_uri": {"source": "filename", "prefix": "pdfs/"}
|
"_canonical_uri": {"source": "filename", "prefix": "pdfs/"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The approach of re-using the filename of the PDF as the
|
|
@ -130,6 +130,8 @@ suffixed
|
|||||||
<$reveal state="""$(field)$!!import-field-source""" type="match" text="constant" default="column" tag="span">
|
<$reveal state="""$(field)$!!import-field-source""" type="match" text="constant" default="column" tag="span">
|
||||||
<$edit-text tiddler=<<field>> field="import-field-value" tag="input" placeholder="constant" default=""/>
|
<$edit-text tiddler=<<field>> field="import-field-value" tag="input" placeholder="constant" default=""/>
|
||||||
</$reveal>
|
</$reveal>
|
||||||
|
<$checkbox tiddler=<<field>> field="import-field-skip-tiddler-if-blank" checked="yes" unchecked="no" default="no">
|
||||||
|
Skip this tiddler when field blank
|
||||||
<br/>
|
<br/>
|
||||||
Title:
|
Title:
|
||||||
<$tiddler tiddler=<<field>>>
|
<$tiddler tiddler=<<field>>>
|
||||||
@ -192,6 +194,13 @@ Title:
|
|||||||
</$tiddler>
|
</$tiddler>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
Row type:
|
||||||
|
<$select tiddler=<<row>> field="import-row-type" default="by-field">
|
||||||
|
<option value="by-field">By field</option>
|
||||||
|
<option value="by-column">By column</option>
|
||||||
|
</$select>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
<$button class="tc-btn-invisible">
|
<$button class="tc-btn-invisible">
|
||||||
<$action-createtiddler $basetitle="$:/_ExcelImporter/ImportSpecifiers/Field" $savetitle="$:/temp/newtiddler" import-spec-role="field" import-field-name="fieldname" import-field-type="string" import-field-source="column" import-field-column="Column Name" />
|
<$action-createtiddler $basetitle="$:/_ExcelImporter/ImportSpecifiers/Field" $savetitle="$:/temp/newtiddler" import-spec-role="field" import-field-name="fieldname" import-field-type="string" import-field-source="column" import-field-column="Column Name" />
|
||||||
<$action-listops $tiddler=<<row>> $subfilter="[{$:/temp/newtiddler}] +[putfirst[]]"/>
|
<$action-listops $tiddler=<<row>> $subfilter="[{$:/temp/newtiddler}] +[putfirst[]]"/>
|
||||||
|
@ -23,7 +23,7 @@ exports["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] = f
|
|||||||
text: text
|
text: text
|
||||||
});
|
});
|
||||||
// Return the output tiddlers
|
// Return the output tiddlers
|
||||||
return importer.importTiddlers();
|
return importer.getResults();
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -21,103 +21,155 @@ var XLSXImporter = function(options) {
|
|||||||
this.filename = options.filename;
|
this.filename = options.filename;
|
||||||
this.text = options.text;
|
this.text = options.text;
|
||||||
this.importSpec = options.importSpec || $tw.wiki.getTiddlerText(DEFAULT_IMPORT_SPEC_TITLE);
|
this.importSpec = options.importSpec || $tw.wiki.getTiddlerText(DEFAULT_IMPORT_SPEC_TITLE);
|
||||||
|
this.logger = new $tw.utils.Logger("xlsx-utils");
|
||||||
|
this.results = [];
|
||||||
|
if(JSZip) {
|
||||||
|
this.processWorkbook();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
XLSXImporter.prototype.importTiddlers = function() {
|
XLSXImporter.prototype.getResults = function() {
|
||||||
var self = this,
|
return this.results;
|
||||||
results = [],
|
};
|
||||||
workbook;
|
|
||||||
// Check for the JSZIP plugin
|
XLSXImporter.prototype.processWorkbook = function() {
|
||||||
if(!JSZip) {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
// Read the workbook
|
// Read the workbook
|
||||||
if(this.filename) {
|
if(this.filename) {
|
||||||
workbook = XLSX.readFile(this.filename);
|
this.workbook = XLSX.readFile(this.filename);
|
||||||
} else if(this.text) {
|
} else if(this.text) {
|
||||||
workbook = XLSX.read(this.text,{type:"base64"});
|
this.workbook = XLSX.read(this.text,{type:"base64"});
|
||||||
}
|
}
|
||||||
// Read the root import specification
|
// Read the root import specification
|
||||||
var rootImportSpec = $tw.wiki.getTiddler(this.importSpec);
|
this.rootImportSpec = $tw.wiki.getTiddler(this.importSpec);
|
||||||
if(rootImportSpec) {
|
if(this.rootImportSpec) {
|
||||||
// Iterate through the sheets specified in the list field
|
// Iterate through the sheets specified in the list field
|
||||||
$tw.utils.each(rootImportSpec.fields.list || [],function(sheetImportSpecTitle) {
|
$tw.utils.each(this.rootImportSpec.fields.list || [],this.processSheet.bind(this));
|
||||||
// Get the sheet import specifier
|
|
||||||
var sheetImportSpec = $tw.wiki.getTiddler(sheetImportSpecTitle);
|
|
||||||
if(sheetImportSpec) {
|
|
||||||
var sheetName = sheetImportSpec.fields["import-sheet-name"],
|
|
||||||
sheet = workbook.Sheets[sheetName];
|
|
||||||
// Get the size of the sheet
|
|
||||||
var sheetSize = self.measureSheet(sheet);
|
|
||||||
// Read the column names from the first row
|
|
||||||
var columnsByName = self.findColumns(sheet,sheetSize);
|
|
||||||
// Iterate through the rows
|
|
||||||
for(var row=sheetSize.startRow+1; row<=sheetSize.endRow; row++) {
|
|
||||||
// Iterate through the row import specifiers
|
|
||||||
$tw.utils.each(sheetImportSpec.fields.list || [],function(rowImportSpecTitle) {
|
|
||||||
var rowImportSpec = $tw.wiki.getTiddler(rowImportSpecTitle);
|
|
||||||
if(rowImportSpec) {
|
|
||||||
var tiddlerFields = {};
|
|
||||||
// Iterate through the fields for the row
|
|
||||||
$tw.utils.each(rowImportSpec.fields.list || [],function(fieldImportSpecTitle) {
|
|
||||||
var fieldImportSpec = $tw.wiki.getTiddler(fieldImportSpecTitle);
|
|
||||||
if(fieldImportSpec) {
|
|
||||||
var fieldName = fieldImportSpec.fields["import-field-name"],
|
|
||||||
value;
|
|
||||||
switch(fieldImportSpec.fields["import-field-source"]) {
|
|
||||||
case "column":
|
|
||||||
var columnName = fieldImportSpec.fields["import-field-column"],
|
|
||||||
cell = sheet[XLSX.utils.encode_cell({c: columnsByName[columnName], r: row})];
|
|
||||||
if(cell) {
|
|
||||||
switch(fieldImportSpec.fields["import-field-type"] || "string") {
|
|
||||||
case "date":
|
|
||||||
if(cell.t === "n") {
|
|
||||||
value = $tw.utils.stringifyDate(new Date((cell.v - (25567 + 2)) * 86400 * 1000));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "string":
|
|
||||||
// Intentional fall-through
|
|
||||||
default:
|
|
||||||
value = cell.w;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "constant":
|
|
||||||
value = fieldImportSpec.fields["import-field-value"]
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(fieldImportSpec.fields["import-field-prefix"]) {
|
|
||||||
value = fieldImportSpec.fields["import-field-prefix"] + value;
|
|
||||||
}
|
|
||||||
if(fieldImportSpec.fields["import-field-suffix"]) {
|
|
||||||
value = value + fieldImportSpec.fields["import-field-suffix"];
|
|
||||||
}
|
|
||||||
if(fieldImportSpec.fields["import-field-replace-blank"] && (value || "").trim() === "") {
|
|
||||||
value = fieldImportSpec.fields["import-field-replace-blank"];
|
|
||||||
}
|
|
||||||
switch(fieldImportSpec.fields["import-field-list-op"] || "none") {
|
|
||||||
case "none":
|
|
||||||
tiddlerFields[fieldName] = value;
|
|
||||||
break;
|
|
||||||
case "append":
|
|
||||||
var list = $tw.utils.parseStringArray(tiddlerFields[fieldName] || "");
|
|
||||||
$tw.utils.pushTop(list,value)
|
|
||||||
tiddlerFields[fieldName] = list;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
results.push(tiddlerFields);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return results;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
XLSXImporter.prototype.processSheet = function(sheetImportSpecTitle) {
|
||||||
|
// Get the sheet import specifier
|
||||||
|
this.sheetImportSpec = $tw.wiki.getTiddler(sheetImportSpecTitle);
|
||||||
|
if(this.sheetImportSpec) {
|
||||||
|
this.sheetName = this.sheetImportSpec.fields["import-sheet-name"];
|
||||||
|
this.sheet = this.workbook.Sheets[this.sheetName];
|
||||||
|
if(!this.sheet) {
|
||||||
|
this.logger.alert("Missing sheet '" + this.sheetName + "'");
|
||||||
|
} else {
|
||||||
|
// Get the size of the sheet
|
||||||
|
this.sheetSize = this.measureSheet(this.sheet);
|
||||||
|
// Read the column names from the first row
|
||||||
|
this.columnsByName = this.findColumns(this.sheet,this.sheetSize);
|
||||||
|
// Iterate through the rows
|
||||||
|
for(this.row=this.sheetSize.startRow+1; this.row<=this.sheetSize.endRow; this.row++) {
|
||||||
|
// Iterate through the row import specifiers
|
||||||
|
$tw.utils.each(this.sheetImportSpec.fields.list || [],this.processRow.bind(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
XLSXImporter.prototype.processRow = function(rowImportSpecTitle) {
|
||||||
|
this.rowImportSpec = $tw.wiki.getTiddler(rowImportSpecTitle);
|
||||||
|
if(this.rowImportSpec) {
|
||||||
|
this.tiddlerFields = {};
|
||||||
|
this.skipTiddler = false;
|
||||||
|
// Determine the type of row
|
||||||
|
this.rowType = this.rowImportSpec.fields["import-row-type"] || "by-field";
|
||||||
|
switch(this.rowType) {
|
||||||
|
case "by-column":
|
||||||
|
this.processRowByColumn();
|
||||||
|
break;
|
||||||
|
case "by-field":
|
||||||
|
this.processRowByField();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Save the tiddler if not skipped
|
||||||
|
if(!this.skipTiddler) {
|
||||||
|
if(!this.tiddlerFields.title) {
|
||||||
|
this.logger.alert("Missing title field for " + JSON.stringify(this.tiddlerFields));
|
||||||
|
}
|
||||||
|
this.results.push(this.tiddlerFields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
XLSXImporter.prototype.processRowByColumn = function() {
|
||||||
|
var self = this;
|
||||||
|
// Iterate through the columns for the row
|
||||||
|
$tw.utils.each(this.columnsByName,function(index,name) {
|
||||||
|
var cell = self.sheet[XLSX.utils.encode_cell({c: self.columnsByName[name], r: self.row})];
|
||||||
|
name = name.toLowerCase();
|
||||||
|
if(cell && cell.w && $tw.utils.isValidFieldName(name)) {
|
||||||
|
self.tiddlerFields[name] = cell.w;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Skip the tiddler entirely if it doesn't have a title
|
||||||
|
if(!this.tiddlerFields.title) {
|
||||||
|
this.skipTiddler = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
XLSXImporter.prototype.processRowByField = function() {
|
||||||
|
// Iterate through the fields for the row
|
||||||
|
$tw.utils.each(this.rowImportSpec.fields.list || [],this.processField.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
XLSXImporter.prototype.processField = function(fieldImportSpecTitle) {
|
||||||
|
var fieldImportSpec = $tw.wiki.getTiddler(fieldImportSpecTitle);
|
||||||
|
if(fieldImportSpec) {
|
||||||
|
var fieldName = fieldImportSpec.fields["import-field-name"],
|
||||||
|
value;
|
||||||
|
switch(fieldImportSpec.fields["import-field-source"]) {
|
||||||
|
case "column":
|
||||||
|
var columnName = fieldImportSpec.fields["import-field-column"],
|
||||||
|
cell = this.sheet[XLSX.utils.encode_cell({c: this.columnsByName[columnName], r: this.row})];
|
||||||
|
if(cell) {
|
||||||
|
switch(fieldImportSpec.fields["import-field-type"] || "string") {
|
||||||
|
case "date":
|
||||||
|
if(cell.t === "n") {
|
||||||
|
value = $tw.utils.stringifyDate(new Date((cell.v - (25567 + 2)) * 86400 * 1000));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "string":
|
||||||
|
// Intentional fall-through
|
||||||
|
default:
|
||||||
|
value = cell.w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "constant":
|
||||||
|
value = fieldImportSpec.fields["import-field-value"]
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if((value || "").trim() === "") {
|
||||||
|
if((fieldImportSpec.fields["import-field-skip-tiddler-if-blank"] || "").trim().toLowerCase() === "yes") {
|
||||||
|
this.skipTiddler = true;
|
||||||
|
}
|
||||||
|
if(fieldImportSpec.fields["import-field-replace-blank"]) {
|
||||||
|
value = fieldImportSpec.fields["import-field-replace-blank"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(fieldImportSpec.fields["import-field-prefix"]) {
|
||||||
|
value = fieldImportSpec.fields["import-field-prefix"] + value;
|
||||||
|
}
|
||||||
|
if(fieldImportSpec.fields["import-field-suffix"]) {
|
||||||
|
value = value + fieldImportSpec.fields["import-field-suffix"];
|
||||||
|
}
|
||||||
|
switch(fieldImportSpec.fields["import-field-list-op"] || "none") {
|
||||||
|
case "none":
|
||||||
|
this.tiddlerFields[fieldName] = value;
|
||||||
|
break;
|
||||||
|
case "append":
|
||||||
|
var list = $tw.utils.parseStringArray(this.tiddlerFields[fieldName] || "");
|
||||||
|
$tw.utils.pushTop(list,value)
|
||||||
|
this.tiddlerFields[fieldName] = list;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
XLSXImporter.prototype.measureSheet = function(sheet) {
|
XLSXImporter.prototype.measureSheet = function(sheet) {
|
||||||
var sheetRange = XLSX.utils.decode_range(sheet["!ref"]);
|
var sheetRange = XLSX.utils.decode_range(sheet["!ref"]);
|
||||||
return {
|
return {
|
||||||
|
@ -36,7 +36,7 @@ Command.prototype.execute = function() {
|
|||||||
filename: filename,
|
filename: filename,
|
||||||
importSpec: importSpec
|
importSpec: importSpec
|
||||||
});
|
});
|
||||||
$tw.wiki.addTiddlers(importer.importTiddlers());
|
$tw.wiki.addTiddlers(importer.getResults());
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,11 +25,11 @@ html body .tc-site-title,
|
|||||||
html body .tc-titlebar,
|
html body .tc-titlebar,
|
||||||
html body .tc-subtitle,
|
html body .tc-subtitle,
|
||||||
html body .tc-tiddler-missing .tc-title,
|
html body .tc-tiddler-missing .tc-title,
|
||||||
html body .tc-tab-buttons button {
|
html body .tc-tab-buttons button,
|
||||||
|
html body .tc-tiddler-frame .tc-tiddler-body {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
html body .tc-view-field-name,
|
html body .tc-view-field-name {
|
||||||
html body .tc-tiddler-frame .tc-tiddler-body {
|
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user