2013-11-28 40 views
0

我正在创建一个firefox扩展,让操作员执行修改HTML文档内容的各种操作。操作员不编辑HTML,他们采取其他操作,我的扩展通过插入元素,添加属性等来修改文档。可以firefox扩展修改HTML文档的DOM然后保存为HTML吗?

当操作员完成后,他们需要能够将HTML文档保存为文件(或者让我的扩展名将其发送到Internet目标,但这不是必需的,因为他们可以通过电子邮件发送保存的文件)。

我想也许我的扩展中的JavaScript代码所做的更改会反映在HTML文档中,但是当我在修改后让Firefox浏览器“查看源代码”时,它会显示原始HTML文本。

我的问题是:

#1:什么是运营商节省我的分机已进行的所有更改HTML文档的最简单的方法?

#2:什么是我的扩展中的JavaScript代码处理HTML文档内容并写入本地磁盘上的HTML文件的最简单方法?

#3:任何有效的HTML内容无法在保存的文件中进行准确表示吗?

#4:TreeWalker是解决方案的一部分(见下文)?


从我的研究,到目前为止,一对夫妇的意见:

我读过有关的TreeWalker对象,这似乎提供了相当便捷方式,延期通过一切(或几乎一切走? )在HTML文件中。但它是否暴露了一切,所以原始(和我的修改)中的所有内容都可以保存而不会丢失任何重要的东西?

TreeWalker是否以“正确的顺序” - 我的扩展程序生成原始和/或修改的HTML文档所需的顺序遍历HTML文档?

对这些问题有什么隐晦或棘手的问题?

回答

0

看起来我可以回答我自己的问题,这要感谢mozilla #extdev IRC中的某个人。

我完全被“查看源”伪造。当我在“查看源代码”显示的窗口中看不到我的修改时,我认为浏览器不会提供这些信息。

但是,猜猜看是什么?当我“文件”=== >>“将页面另存为...”时,然后使用纯文本编辑器检查页面内容......当然,这包含我的Firefox扩展所做的修改!惊喜!

1

好,所以我假设你有访问页面的DOM。你需要做的事情主要是修改dom,然后获取所有dom代码并将其保存为文件。这里是你如何下载页面的html代码。这将创建一个a标签,用户需要点击该标签才能下载该文件。

var a = document.createElement('a'), code = document.querySelectorAll('html')[0].innerHTML; 
a.setAttribute('download', 'filename.html'); 
a.setAttribute('href', 'data:text/html,' + code); 

现在,您可以在DOM中的任何位置插入此标记,并且该文件将在用户单击它时下载。

注意:这是一种黑客攻击,它会在a标签中注入整个html文件,理论上应该在任何up to date browser(除了惊喜,IE)工作。有更稳定和不太可靠的方法来完成它,比如将其存储在文件系统API文件中,然后下载该文件。

编辑:document.querySelectorAll行访问页面DOM。对于它的工作document必须是可访问的。你说你正在修改DOM,所以应该已经在那里了。确保你在页面上添加了代码,而不是你的扩展代码。此代码与您的DOM修改代码位于相同的位置,而不是您无法访问DOM的扩展页面。

至于a标签,它将被插入到页面中。我忽略了这些步骤,因为我假定您已经知道如何操作DOM,也因为我不知道您想在哪里添加链接。你也可以跳过点击链接的用户动作,但这是一种黑客行为,只适用于现代浏览器。您可以在原始页面的某处插入a标记,用户在该页面中不会看到它,然后调用a.click()函数来模拟链接上的单击事件。但这不是一种合法的方式,我个人只在我的实践项目中使用它来调用click事件监听器。

我只能在chrome上测试这个,而不是在FF上,但试试这个代码,这不需要你甚至添加一个链接到DOM。您需要将其添加到DOM操作代码旁边。如果运气在你身边,这将起作用:)

var a = document.createElement('a'), code = document.querySelectorAll('html')[0].innerHTML; 
a.setAttribute('download', 'filename.html'); 
a.setAttribute('href', 'data:text/html,' + code); 
a.click(); 
+0

您的代码似乎将DOM文档中的单个元素保存到磁盘文件。我需要做的是将整个HTML文档保存到磁盘文件。你知道当你从浏览器菜单中选择“查看页面源代码”时你看到了什么吗?那么,这就是我需要保存的 - HTML文本格式的整个HTML文档。但是,在我的扩展对DOM做了很多更改之后(例如,插入几十个具有新属性的新元素),执行“查看页面源代码”时看到的是加载到浏览器中的原始HTML。我需要保存包含所有更改的HTML文本。 – honestann

+0

是的,这是html标签,它将是整个页面,不包括doctype和标签本身的任何属性,因为html标签始终包含页面的所有代码。所以这将是'view source'页面中的所有内容,我检查过,innerHTML确实反映了通过js对DOM所做的任何更改,所以您应该是黄金。 – Achshar

+0

这很酷,谢谢!你能解释每一步的作用吗?另外,有没有什么办法可以完全用我的扩展代码来完成同样的事情,所以操作员不必在浏览器中做任何事情(如查找和点击按钮)?我假设你上面显示的是我在扩展中插入的JavaScript,对吗?当你说“文件将下载”时,我假定你的意思是HTML文件将被写入运营商本地文件系统的“filename.html”中(可能在一些模糊的路径中)。我可以指定一个路径,特别是像我的扩展名所在的“chrome:// ...”吗? – honestann

-1

浏览器对本地文件系统没有直接的写访问权限。唯一的读访问是明确提供一个文件://URL(见下面注1)

在你的情况,我们明确谈论的JavaScript - 它可以读取和写入cookie和本地存储。它还可以将内容发送回服务器并检索它,例如,使用AJAX。

你放入本地存储/ cookies的东西实际上是其他程序(如电子邮件客户端)无法访问的东西。

可以创建非常长的mailto:URL(请参阅注2),但只处理电子邮件中的内嵌内容,并且您将遇到各种您尚未准备好处理的编码问题。

因此,我建议通过AJAX来追求存储服务器端 - 一旦你有这个排序/工作,看看本地存储。

注1:这不完全正确。可信,签名的javascript可以访问附加功能,其中可能包括包括直接文件访问。

注2:(极限取决于浏览器电子邮件客户端 - Lotus Notes的truncaets的内容,而很多)

+0

我建议你重新阅读这个问题:作者明确要求使用Firefox插件做这些事情,它与浏览器本身具有相同的功能,包括。直接文件读/写访问。你在谈论访问Web内容可能有或没有,这是完全不同的。 – nmaier

0

有没有简单的方法只与网络API要做到这一点,至少当你想要一个不会忽略doctype或注释之类的结果时。您仍然可以自己编写一个序列化程序,它通过document.childNodes并根据节点类型(Element.outerHTMLComment.data等)进行序列化。

幸运的是,您正在编写Firefox插件,因此您可以访问更多(功能强大)的内容。

尽管仍然不是100%完美,nsIDocumentEncoder实现将产生相当不错的结果,它应该仅在一些空白和明确的字符集声明(至多其他都是bug)方面有所不同。 这里是一个可以如何使用这个组件的例子:如果你正在写

function serializeDocument(document) { 
    const { 
     classes: Cc, 
     interfaces: Ci, 
     utils: Cu 
    } = Components; 
    let encoder = Cc['@mozilla.org/layout/documentEncoder;1?type=text/html'].createInstance(Ci.nsIDocumentEncoder); 
    encoder.init(document, 'text/html', Ci.nsIDocumentEncoder.OutputLFLineBreak | Ci.nsIDocumentEncoder.OutputRaw); 
    encoder.setCharset("utf-8"); 
    return encoder.encodeToString(); 
} 

的SDK插件,东东变得更加复杂的SDK抽象了一些重要的东西了。你需要通过chrome模块,并找出自己的活动窗口和标签。像Services.wm.getMostRecentWindow("navigator:browser").content.documentServices.jsm)应该做的伎俩。

在XUL重叠附加组件中,content.document应该足以获取当前活动选项卡的文档,并且您已有Components访问权限。

不过,你需要让用户选择一个文件目标,通常是通过nsIFilePicker,然后实际写入文件时,通过使用类似一个file stream或完全异步OS.File API。

+0

感谢您的想法和信息。我需要研究你的信息中的术语和功能,因为我不熟悉它们。我的扩展会做的事情是令人难以置信的,但所有的天才都在C共享库和相关文件中,而不是在这个简单的扩展中。正如我所说,我的扩展没有在浏览器中的GUI或菜单,但确实显示小的无边界窗口,让用户控制扩展。我需要的是指导者或承包商的帮助(一旦我解释我在做什么,我不能在公开场合做)。如果你想这个,请发邮件给honestann -at- ymail -dot- com。谢谢。 – honestann

+0

关于空白,HTML文档中可能无法顺序或自然地序列化的模糊字段以及文档的字符编码的一些小的注释。其中一种方法是保存并发送原始文档,以及修改文档的正文。这样,另一个应用程序可以将新主体插入原始文档。另外,由于我的应用程序的性质,即使原始文件不是UTF-8,我的扩展名也应该将文档保存为UTF-8。如有必要,我的应用程序只能在UTF-8文档上运行。 – honestann