Motivation: https://stackoverflow.com/questions/28120689/create-self-modifying-html-page-on-box
Bug: String escaping , formatting html
, js
generated by initial edited , saved html
, js
e.g.,
a) if open "saveFile.html" at local browser ;
b) type "abc" into textarea
;
c) click save file
button ;
d) click Save
at Save File
dialog ;
e) file-*[date according to universal time].html
saved to disk ;
f) open file-*[date according to universal time].html
in browser ;
g) type "def" into textarea
;
h) repeat d) , e) , f) ;
i) Bug: result at second file-*[date according to universal time].html
does display textarea
containing "abc def" text content ; button
not displayed at 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();};
generated at line 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>
Your replace function replaces until the /textarea>
that is in your clone
variable. It doesn't do it from the first file because there's a newline character after textarea in the html. One way to fix it would be to add a newline
character in the generated html. Like this:
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>"];
I'm not sure what is breaking the third-generation clone so that it results in the js info being output to the page, but it would probably be better to use an actual document object to clone/manipulate the original and output its contents as string for the Blob
object. For example, I tested using your base saveFile.html with the following changes:
//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"});
The only downsides I am seeing are:
This may be hard to expand into a more generic framework for generating a "live HTML file" of current state of loaded HTML page (though it shouldn't be more complicated than your example approach).
The string returned by
clone.documentElement.outerHTML
appears to drop the document type declaration to a simple element so that :
is not in the output string. You could probably use something like:
var clone_string = ["<!doctype html>" + clone.documentElement.outerHTML];
as a workaround. Or, for something more robust:
var doc_doctype = new XMLSerializer().serializeToString(document.doctype);
var clone_string = [doc_doctype + clone.documentElement.outerHTML];
来源:https://stackoverflow.com/questions/30563157/edit-save-self-modifying-html-document-format-generated-html-javascript