Browse Source

renamed template variables

Gildas 7 năm trước cách đây
mục cha
commit
7cada539e4
3 tập tin đã thay đổi với 86 bổ sung76 xóa
  1. 3 3
      extension/core/bg/config.js
  2. 23 24
      extension/ui/pages/help.html
  3. 60 49
      lib/single-file/single-file-core.js

+ 3 - 3
extension/core/bg/config.js

@@ -32,7 +32,7 @@ singlefile.config = (() => {
 		compressHTML: true,
 		compressCSS: true,
 		lazyLoadImages: true,
-		filenameTemplate: "{title} ({iso-date} {locale-time}).html",
+		filenameTemplate: "{page-title} ({date-iso} {time-locale}).html",
 		confirmFilename: false,
 		contextMenuEnabled: true,
 		shadowEnabled: true,
@@ -92,9 +92,9 @@ singlefile.config = (() => {
 		}
 		if (config.filenameTemplate === undefined) {
 			if (config.appendSaveDate || config.appendSaveDate === undefined) {
-				config.filenameTemplate = "{title} ({iso-date} {locale-time}).html";
+				config.filenameTemplate = "{page-title} ({date-iso} {time-locale}).html";
 			} else {
-				config.filenameTemplate = "{title}.html";
+				config.filenameTemplate = "{page-title}.html";
 			}
 			delete config.appendSaveDate;
 		}

+ 23 - 24
extension/ui/pages/help.html

@@ -122,25 +122,24 @@
 						<p>The template allows you to customize the file name of saved pages. You can use any valid character and "/" to
 							create sub-folders. You can also use the variables in the list below anywhere in the template.</p>
 						<ul>
-							<li><code>{title}</code>: the title of the page or the last segment if not found</li>
-							<li><code>{iso-datetime}</code>: the date and time in the ISO format (e.g. "2018-09-15T22_38_26_317Z")</li>
-							<li><code>{iso-date}</code>: the date in the ISO format (e.g. "2018-09-15")</li>
-							<li><code>{iso-time}</code>: the time in the ISO format (e.g. "22_38_26_317")</li>
-							<li><code>{utc-datetime}</code>: the date and time in UTC format (e.g. "Sat, 15 Sep 2018 22_38_26 GMT")</li>
-							<li><code>{utc-day}</code>: the day in UTC format (e.g. "15")</li>
-							<li><code>{utc-month}</code>: the the month in UTC format (e.g. "9")</li>
-							<li><code>{utc-year}</code>: the year in UTC format (e.g. "2018")</li>
-							<li><code>{locale-date}</code>: the localized value of the date (e.g. "16_09_2018")</li>
-							<li><code>{locale-time}</code>: the localized value of the time (e.g. "00_38_26")</li>
-							<li><code>{locale-day}</code>: the localized value of the day (e.g. "15")</li>
-							<li><code>{locale-month}</code>: the localized value of the month (e.g. "9")</li>
-							<li><code>{locale-year}</code>: the localized value of the year (e.g. "2018")</li>
-							<li><code>{locale-datetime}</code>: the localized value of the date and time (e.g. "9_16_2018, 12_54_31 AM")</li>
+							<li><code>{page-title}</code>: the title of the page or the last segment if not found</li>
+							<li><code>{datetime-iso}</code>: the save date and time in the ISO format (e.g. "2018-09-15T22_38_26_317Z")</li>
+							<li><code>{datetime-utc}</code>: the save date and time in UTC format (e.g. "Sat, 15 Sep 2018 22_38_26 GMT")</li>
+							<li><code>{datetime-locale}</code>: the localized value of the date and time (e.g. "9_16_2018, 12_54_31 AM")</li>
+							<li><code>{date-iso}</code>: the save date in the ISO format (e.g. "2018-09-15")</li>
+							<li><code>{date-locale}</code>: the localized value of the save date (e.g. "16_09_2018")</li>
+							<li><code>{time-iso}</code>: the save time in the ISO format (e.g. "22_38_26_317")</li>
+							<li><code>{time-locale}</code>: the localized value of the save time (e.g. "00_38_26")</li>
+							<li><code>{day-utc}</code>: the day of the save date in UTC format (e.g. "15")</li>
+							<li><code>{day-locale}</code>: the localized value of the day (e.g. "15")</li>
+							<li><code>{month-utc}</code>: the month of the save date in UTC format (e.g. "9")</li>
+							<li><code>{month-locale}</code>: the localized value of the month (e.g. "9")</li>
+							<li><code>{year-utc}</code>: the year of the save date in UTC format (e.g. "2018")</li>
+							<li><code>{year-locale}</code>: the localized value of the year (e.g. "2018")</li>
 							<li><code>{url-href}</code>: the URL of the page (e.g. "http_example.com")</li>
 							<li><code>{url-pathname}</code>: the path name of the URL (e.g. "category_index.html")</li>
 							<li><code>{url-last-segment}</code>: the last part of the pathname without the extension or the host if not
-								found
-								(e.g. "index")</li>
+								found (e.g. "index")</li>
 							<li><code>{url-protocol}</code>: the protocol of the URL (e.g. "https")</li>
 							<li><code>{url-host}</code>: the host name + the port of the URL (e.g. "example.com_8080")</li>
 							<li><code>{url-hostname}</code>: the host name of the URL (e.g. "example.com")</li>
@@ -160,14 +159,14 @@
 							&gt;, and control characters from 0 to 31 in the ASCII table.</p>
 						<p>Template Examples</p>
 						<ul>
-							<li><code>{title} ({iso-date} {locale-time}).html</code> will produce filenames like "Introduction to SingleFile
-								(2018-09-15
-								11_06_03 PM).html" for a page having "Introduction to SingleFile" as title.</li>
-							<li><code>{url-last-segment} - {iso-date}</code> will produce filenames like "welcome - " for a page hosted on
-								https://example.com/welcome.html.</li>
-							<li><code>archives/{locale-year}/{locale-month}/{locale-day}/{title}</code> will produce filenames like
-								"Introduction to SingleFile" stored into 3 sub-directories in the "archives" folder, one for each part of the
-								date.</li>
+							<li><code>{page-title} ({date-iso} {time-locale}).html</code> will produce filenames like "Introduction to
+								SingleFile (2018-09-15 11_06_03 PM).html" for a page having "Introduction to SingleFile" as title.</li>
+							<li><code>archives/{url-last-segment} - {date-iso}</code> will produce filenames like "welcome - 2018-09-15" for
+								a page hosted on https://example.com/welcome.html. The saved files will be saved in the sub-directory
+								"archives".</li>
+							<li><code>archives/{year-locale}/{month-locale}/{day-locale}/{page-title}.html</code> will produce filenames
+								like "Introduction to SingleFile.html" stored into 3 sub-directories in the "archives" folder, one for each
+								part of the save date (e.g. "2018/9/15/Introduction to SingleFile.html").</li>
 						</ul>
 					</li>
 					<li>

+ 60 - 49
lib/single-file/single-file-core.js

@@ -787,56 +787,37 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 			let filename = options.filenameTemplate;
 			const date = new Date();
 			const url = new URL(options.url);
-			filename = filename.replace(/{\s*title\s*}/g, options.title.replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*iso-datetime\s*}/g, date.toISOString().replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*iso-date\s*}/g, date.toISOString().split("T")[0].replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*iso-time\s*}/g, date.toISOString().split("T")[1].split("Z")[0].replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*locale-date\s*}/g, date.toLocaleDateString().replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*locale-time\s*}/g, date.toLocaleTimeString().replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*locale-day\s*}/g, String(date.getDate()).replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*locale-month\s*}/g, String(date.getMonth() + 1).replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*locale-year\s*}/g, String(date.getFullYear()).replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*locale-datetime\s*}/g, date.toLocaleString().replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*utc-datetime\s*}/g, date.toUTCString().replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*utc-day\s*}/g, String(date.getUTCDate()).replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*utc-month\s*}/g, String(date.getUTCMonth() + 1).replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*utc-year\s*}/g, String(date.getUTCFullYear()).replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*url-hash\s*}/g, url.hash.substring(1).replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*url-host\s*}/g, url.host.replace(/\/+/g, "_").replace(/\/$/, ""));
-			filename = filename.replace(/{\s*url-hostname\s*}/g, url.hostname.replace(/\/+/g, "_").replace(/\/$/, ""));
-			filename = filename.replace(/{\s*url-href\s*}/g, url.href.replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*url-password\s*}/g, url.password.replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*url-pathname\s*}/g, url.pathname.replace(/\/+/g, "_").replace(/\/$/, "").replace(/^\//, ""));
-			filename = filename.replace(/{\s*url-port\s*}/g, url.port.replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*url-protocol\s*}/g, url.protocol.replace(/\/+/g, "_").replace(/\/$/, ""));
-			filename = filename.replace(/{\s*url-search\s*}/g, url.search.substring(1).replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*url-username\s*}/g, url.username.replace(/\/+/g, "_"));
-			filename = filename.replace(/{\s*tab-id\s*}/g, String(options.tabId || "unknown"));
-			let lastSegmentMatch = url.pathname.match(/\/([^/]+)$/);
-			let lastSegment = lastSegmentMatch && lastSegmentMatch[0];
-			if (!lastSegment) {
-				lastSegmentMatch = url.href.match(/([^/]+)\/?$/);
-				lastSegment = lastSegmentMatch && lastSegmentMatch[0];
-			}
-			if (!lastSegment) {
-				lastSegmentMatch = lastSegment.match(/(.*)<\.[^.]+$/);
-				lastSegment = lastSegmentMatch && lastSegmentMatch[0];
-			}
-			if (!lastSegment) {
-				lastSegment = url.hostname.replace(/\/+/g, "_").replace(/\/$/, "");
-			}
-			filename = filename.replace(/{\s*url-last-segment\s*}/g, lastSegment.replace(/\/+/g, "").replace(/\/$/, "").replace(/^\//, ""));
-			if (filename.match(/{\s*digest-sha-256\s*}/g)) {
-				filename = filename.replace(/{\s*digest-sha-256\s*}/g, await DOM.digest("SHA-256", content));
-			}
-			if (filename.match(/{\s*digest-sha-384\s*}/g)) {
-				filename = filename.replace(/{\s*digest-sha-384\s*}/g, await DOM.digest("SHA-384", content));
-			}
-			if (filename.match(/{\s*digest-sha-512\s*}/g)) {
-				filename = filename.replace(/{\s*digest-sha-512\s*}/g, await DOM.digest("SHA-512", content));
-			}
+			filename = await DomUtil.evalTemplateVariable(filename, "page-title", () => options.title);
+			filename = await DomUtil.evalTemplateVariable(filename, "datetime-iso", () => date.toISOString());
+			filename = await DomUtil.evalTemplateVariable(filename, "date-iso", () => date.toISOString().split("T")[0]);
+			filename = await DomUtil.evalTemplateVariable(filename, "time-iso", () => date.toISOString().split("T")[1].split("Z")[0]);
+			filename = await DomUtil.evalTemplateVariable(filename, "date-locale", () => date.toLocaleDateString());
+			filename = await DomUtil.evalTemplateVariable(filename, "time-locale", () => date.toLocaleTimeString());
+			filename = await DomUtil.evalTemplateVariable(filename, "day-locale", () => String(date.getDate()));
+			filename = await DomUtil.evalTemplateVariable(filename, "month-locale", () => String(date.getMonth()));
+			filename = await DomUtil.evalTemplateVariable(filename, "year-locale", () => String(date.getFullYear()));
+			filename = await DomUtil.evalTemplateVariable(filename, "datetime-locale", () => date.toLocaleString());
+			filename = await DomUtil.evalTemplateVariable(filename, "datetime-utc", () => date.toUTCString());
+			filename = await DomUtil.evalTemplateVariable(filename, "day-utc", () => String(date.getUTCDate()));
+			filename = await DomUtil.evalTemplateVariable(filename, "month-utc", () => String(date.getUTCMonth()));
+			filename = await DomUtil.evalTemplateVariable(filename, "year-utc", () => String(date.getUTCFullYear()));
+			filename = await DomUtil.evalTemplateVariable(filename, "url-hash", () => url.hash.substring(1));
+			filename = await DomUtil.evalTemplateVariable(filename, "url-host", () => url.host.replace(/\/$/, ""));
+			filename = await DomUtil.evalTemplateVariable(filename, "url-hostname", () => url.hostname.replace(/\/$/, ""));
+			filename = await DomUtil.evalTemplateVariable(filename, "url-href", () => url.href);
+			filename = await DomUtil.evalTemplateVariable(filename, "url-password", () => url.password);
+			filename = await DomUtil.evalTemplateVariable(filename, "url-pathname", () => url.pathname.replace(/^\//, "").replace(/\/$/, ""), true);
+			filename = await DomUtil.evalTemplateVariable(filename, "url-port", () => url.port);
+			filename = await DomUtil.evalTemplateVariable(filename, "url-protocol", () => url.protocol);
+			filename = await DomUtil.evalTemplateVariable(filename, "url-search", () => url.search.substring(1));
+			filename = await DomUtil.evalTemplateVariable(filename, "url-username", () => url.username);
+			filename = await DomUtil.evalTemplateVariable(filename, "tab-id", () => String(options.tabId || ""));
+			filename = await DomUtil.evalTemplateVariable(filename, "url-last-segment", () => DomUtil.getLastSegment(url));
+			filename = await DomUtil.evalTemplateVariable(filename, "digest-sha-256", async () => DOM.digest("SHA-256", content));
+			filename = await DomUtil.evalTemplateVariable(filename, "digest-sha-384", async () => DOM.digest("SHA-384", content));
+			filename = await DomUtil.evalTemplateVariable(filename, "digest-sha-512", async () => DOM.digest("SHA-512", content));
 			filename = filename.replace(/[~\\?%*:|"<>\x00-\x1f\x7F]+/g, "_"); // eslint-disable-line no-control-regex
-			filename = filename.replace(/\.\.\/?/g, "").replace(/^\/+/, "");
+			filename = filename.replace(/\.\.\//g, "").replace(/^\/+/, "");
 			if (filename.length > 192) {
 				const extensionMatch = filename.match(/(\.[^.]{3,4})$/);
 				const extension = extensionMatch && extensionMatch[0] && extensionMatch[0].length > 1 ? extensionMatch[0] : "";
@@ -1077,6 +1058,36 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 			}
 		}
 
+		static async evalTemplateVariable(template, variableName, valueGetter, dontReplaceSlash) {
+			const replaceRegExp = new RegExp("{\\s*" + variableName + "\\s*}", "g");
+			if (template.match(replaceRegExp)) {
+				let value = await valueGetter();
+				if (!dontReplaceSlash) {
+					value = value.replace(/\/+/g, "_");
+				}
+				return template.replace(replaceRegExp, value);
+			}
+			return template;
+		}
+
+		static getLastSegment(url) {
+			let lastSegmentMatch = url.pathname.match(/\/([^/]+)$/);
+			let lastSegment = lastSegmentMatch && lastSegmentMatch[0];
+			if (!lastSegment) {
+				lastSegmentMatch = url.href.match(/([^/]+)\/?$/);
+				lastSegment = lastSegmentMatch && lastSegmentMatch[0];
+			}
+			if (!lastSegment) {
+				lastSegmentMatch = lastSegment.match(/(.*)<\.[^.]+$/);
+				lastSegment = lastSegmentMatch && lastSegmentMatch[0];
+			}
+			if (!lastSegment) {
+				lastSegment = url.hostname.replace(/\/+/g, "_").replace(/\/$/, "");
+			}
+			lastSegment.replace(/\/$/, "").replace(/^\//, "");
+			return lastSegment;
+		}
+
 		static getRegExp(string) {
 			return new RegExp(string.replace(REGEXP_ESCAPE, "\\$1"), "gi");
 		}