编辑、保存、自修改HTML个文档;生成的格式 HTML、JavaScript
Edit, save, self-modifying HTML document; format generated HTML, JavaScript
动机:
错误:字符串转义、格式化 html
、js
由初始编辑生成、保存 html
、js
例如,
a) 如果在本地浏览器中打开 "saveFile.html";
b) 在 textarea
中输入 "abc" ;
c) 点击save file
按钮;
d) 在 Save File
对话框点击 Save
;
e) file-*[date according to universal time].html
保存到磁盘;
f) 在浏览器中打开 file-*[date according to universal time].html
;
g) 在 textarea
中输入 "def" ;
h) 重复 d) , e) , f) ;
i) 错误:第二个 file-*[date according to universal time].html
的结果显示 textarea
包含 "abc def" 文本内容; button
不 显示在 html
:
// at rendered `html` from second `file-*[date according to universal time].html`
// `textarea` containing "abc def" displayed here ,
// `button` _not_ displayed ; following string displayed following `textarea`:
');"console.log(clone);var file = new Blob([clone], {'type':'text/html'});a.href = URL.createObjectURL(file);a.download = 'file-' + new Date().getTime() + '.html';a.click();};
在第 26 行生成,"saveFile.html"
+ "var clone = '<!doctype html>'+ document.documentElement.outerHTML.replace(/<textarea>.*<.+textarea>/, '<textarea>'+document.getElementsByTagName('textarea')[0].value+'<\/textarea>');"
"saveFile.html" v 1.0.0
html, js
<!doctype html>
<html>
<!-- saveFile.html 1.0.0 2015 guest271314 edit, save `html` document -->
<head>
</head>
<body>
<textarea>
</textarea>
<button>save file</button>
<script type="text/javascript">
var saveFile = document.getElementsByTagName("button")[0];
var input = document.getElementsByTagName("textarea")[0];
var a = document.createElement("a");
saveFile.onclick = function(e) {
var clone = ["<!doctype html><head></head><body><textarea>"
+ input.value
+ "</textarea>"
+ "<button>save file</button>"
+ "<script type='text/javascript'>"
+ "var saveFile = document.getElementsByTagName('button')[0];"
+ "var input = document.getElementsByTagName('textarea')[0];"
+ "var a = document.createElement('a');"
+ "saveFile.onclick = function(e) {"
+ "var clone = '<!doctype html>'+ document.documentElement.outerHTML.replace(/<textarea>.*<.+textarea>/, '<textarea>'+document.getElementsByTagName('textarea')[0].value+'<\/textarea>');"
+ "console.log(clone);"
+ "var file = new Blob([clone], {'type':'text/html'});"
+ "a.href = URL.createObjectURL(file);"
+ "a.download = 'file-' + new Date().getTime() + '.html';"
+ "a.click();"
+ "};"
+ "</scr"+"ipt>"
+ "</body>"
+ "</html>"];
var file = new Blob([clone], {"type":"text/html"});
a.href = URL.createObjectURL(file);
a.download = "file-" + new Date().getTime() + ".html";
a.click();
};
</script>
</body>
</html>
您的替换函数会一直替换到 clone
变量中的 /textarea>
。它不会从第一个文件开始执行,因为 html 中的 textarea 之后有一个换行符。修复它的一种方法是在生成的 html 中添加一个 newline
字符。像这样:
var clone = ["<!doctype html><head></head><body><textarea>"
+ input.value
// add newline here
+ "</textarea>\n"
+ "<button>save file</button>"
+ "<script type='text/javascript'>"
+ "var saveFile = document.getElementsByTagName('button')[0];"
+ "var input = document.getElementsByTagName('textarea')[0];"
+ "var a = document.createElement('a');"
+ "saveFile.onclick = function(e) {"
+ "var clone = '<!doctype html>'+ document.documentElement.outerHTML.replace(/<textarea>.*<.+textarea>/, '<textarea>'+document.getElementsByTagName('textarea')[0].value+'<\/textarea>');"
+ "console.log(clone);"
+ "var file = new Blob([clone], {'type':'text/html'});"
+ "a.href = URL.createObjectURL(file);"
+ "a.download = 'file-' + new Date().getTime() + '.html';"
+ "a.click();"
+ "};"
+ "</scr"+"ipt>"
+ "</body>"
+ "</html>"];
我不确定是什么破坏了第三代克隆,导致 js 信息被输出到页面,但使用实际的文档对象可能会更好 clone/manipulate原始并将其内容输出为 Blob
对象的字符串。例如,我使用您的基础 saveFile.html 进行了以下更改测试:
//remove original clone var and replace with:
var clone = document.cloneNode(true);
// grab textarea elements from both original document and clone:
var doc_input = document.getElementsByTagName("textarea")[0];
var clone_input = clone.getElementsByTagName("textarea")[0];
// set clone textarea's innerHTML to current textarea value:
clone_input.innerHTML = doc_input.value;
// use outerHTML of clone.documentElement to get string for Blob
var clone_string = [clone.documentElement.outerHTML];
var file = new Blob([clone_string], {"type":"text/html"});
我看到的唯一缺点是:
这可能很难扩展成一个更通用的框架来生成 "live HTML file" 当前加载状态的 HTML 页面(尽管它不应该比您的示例方法)。
clone.documentElement.outerHTML
返回的字符串似乎将文档类型声明放到一个简单的元素中,以便:
不在输出字符串中。你可能会使用类似的东西:
var clone_string = ["<!doctype html>" + clone.documentElement.outerHTML];
作为解决方法。或者,对于更强大的东西:
var doc_doctype = new XMLSerializer().serializeToString(document.doctype);
var clone_string = [doc_doctype + clone.documentElement.outerHTML];
动机:
错误:字符串转义、格式化 html
、js
由初始编辑生成、保存 html
、js
例如,
a) 如果在本地浏览器中打开 "saveFile.html";
b) 在 textarea
中输入 "abc" ;
c) 点击save file
按钮;
d) 在 Save File
对话框点击 Save
;
e) file-*[date according to universal time].html
保存到磁盘;
f) 在浏览器中打开 file-*[date according to universal time].html
;
g) 在 textarea
中输入 "def" ;
h) 重复 d) , e) , f) ;
i) 错误:第二个 file-*[date according to universal time].html
的结果显示 textarea
包含 "abc def" 文本内容; button
不 显示在 html
:
// at rendered `html` from second `file-*[date according to universal time].html`
// `textarea` containing "abc def" displayed here ,
// `button` _not_ displayed ; following string displayed following `textarea`:
');"console.log(clone);var file = new Blob([clone], {'type':'text/html'});a.href = URL.createObjectURL(file);a.download = 'file-' + new Date().getTime() + '.html';a.click();};
在第 26 行生成,"saveFile.html"
+ "var clone = '<!doctype html>'+ document.documentElement.outerHTML.replace(/<textarea>.*<.+textarea>/, '<textarea>'+document.getElementsByTagName('textarea')[0].value+'<\/textarea>');"
"saveFile.html" v 1.0.0
html, js
<!doctype html>
<html>
<!-- saveFile.html 1.0.0 2015 guest271314 edit, save `html` document -->
<head>
</head>
<body>
<textarea>
</textarea>
<button>save file</button>
<script type="text/javascript">
var saveFile = document.getElementsByTagName("button")[0];
var input = document.getElementsByTagName("textarea")[0];
var a = document.createElement("a");
saveFile.onclick = function(e) {
var clone = ["<!doctype html><head></head><body><textarea>"
+ input.value
+ "</textarea>"
+ "<button>save file</button>"
+ "<script type='text/javascript'>"
+ "var saveFile = document.getElementsByTagName('button')[0];"
+ "var input = document.getElementsByTagName('textarea')[0];"
+ "var a = document.createElement('a');"
+ "saveFile.onclick = function(e) {"
+ "var clone = '<!doctype html>'+ document.documentElement.outerHTML.replace(/<textarea>.*<.+textarea>/, '<textarea>'+document.getElementsByTagName('textarea')[0].value+'<\/textarea>');"
+ "console.log(clone);"
+ "var file = new Blob([clone], {'type':'text/html'});"
+ "a.href = URL.createObjectURL(file);"
+ "a.download = 'file-' + new Date().getTime() + '.html';"
+ "a.click();"
+ "};"
+ "</scr"+"ipt>"
+ "</body>"
+ "</html>"];
var file = new Blob([clone], {"type":"text/html"});
a.href = URL.createObjectURL(file);
a.download = "file-" + new Date().getTime() + ".html";
a.click();
};
</script>
</body>
</html>
您的替换函数会一直替换到 clone
变量中的 /textarea>
。它不会从第一个文件开始执行,因为 html 中的 textarea 之后有一个换行符。修复它的一种方法是在生成的 html 中添加一个 newline
字符。像这样:
var clone = ["<!doctype html><head></head><body><textarea>"
+ input.value
// add newline here
+ "</textarea>\n"
+ "<button>save file</button>"
+ "<script type='text/javascript'>"
+ "var saveFile = document.getElementsByTagName('button')[0];"
+ "var input = document.getElementsByTagName('textarea')[0];"
+ "var a = document.createElement('a');"
+ "saveFile.onclick = function(e) {"
+ "var clone = '<!doctype html>'+ document.documentElement.outerHTML.replace(/<textarea>.*<.+textarea>/, '<textarea>'+document.getElementsByTagName('textarea')[0].value+'<\/textarea>');"
+ "console.log(clone);"
+ "var file = new Blob([clone], {'type':'text/html'});"
+ "a.href = URL.createObjectURL(file);"
+ "a.download = 'file-' + new Date().getTime() + '.html';"
+ "a.click();"
+ "};"
+ "</scr"+"ipt>"
+ "</body>"
+ "</html>"];
我不确定是什么破坏了第三代克隆,导致 js 信息被输出到页面,但使用实际的文档对象可能会更好 clone/manipulate原始并将其内容输出为 Blob
对象的字符串。例如,我使用您的基础 saveFile.html 进行了以下更改测试:
//remove original clone var and replace with:
var clone = document.cloneNode(true);
// grab textarea elements from both original document and clone:
var doc_input = document.getElementsByTagName("textarea")[0];
var clone_input = clone.getElementsByTagName("textarea")[0];
// set clone textarea's innerHTML to current textarea value:
clone_input.innerHTML = doc_input.value;
// use outerHTML of clone.documentElement to get string for Blob
var clone_string = [clone.documentElement.outerHTML];
var file = new Blob([clone_string], {"type":"text/html"});
我看到的唯一缺点是:
这可能很难扩展成一个更通用的框架来生成 "live HTML file" 当前加载状态的 HTML 页面(尽管它不应该比您的示例方法)。
clone.documentElement.outerHTML
返回的字符串似乎将文档类型声明放到一个简单的元素中,以便:
不在输出字符串中。你可能会使用类似的东西:
var clone_string = ["<!doctype html>" + clone.documentElement.outerHTML];
作为解决方法。或者,对于更强大的东西:
var doc_doctype = new XMLSerializer().serializeToString(document.doctype);
var clone_string = [doc_doctype + clone.documentElement.outerHTML];