javascript - 使用 Javascript 确定 JSF 库资源
问题描述
我是 Primefaces Extensions 项目的开发人员,我使用核心 Primefaces JS 函数在 Javascript 中为 DocumentViewer 和 CKEditor 组件获取资源的位置。getFacesResource ()函数在 PrimeFaces core.js 中,看起来像这样..
/**
* Builds a resource URL for given parameters.
*
* @param {string} name The name of the resource. For example: primefaces.js
* @param {string} library The library of the resource. For example: primefaces
* @param {string} version The version of the library. For example: 5.1
* @returns {string} The resource URL.
*/
getFacesResource : function(name, library, version) {
// just get sure - name shoudln't start with a slash
if (name.indexOf('/') === 0)
{
name = name.substring(1, name.length);
}
var scriptURI = $('script[src*="/' + PrimeFaces.RESOURCE_IDENTIFIER + '/core.js"]').attr('src');
// portlet
if (!scriptURI) {
scriptURI = $('script[src*="' + PrimeFaces.RESOURCE_IDENTIFIER + '=core.js"]').attr('src');
}
scriptURI = scriptURI.replace('core.js', name);
它的作用是在 DOM 中找到“core.js”脚本,然后删除 core.js,以便为您构建的用于查找资源的新 URL 提供适当的位置。
为什么我们需要这样做?
CKEEditor 和 DocumentViewer 组件是加载大量插件、语言文件等的复杂组件。我们无法修改这些插件使用的核心 JS 文件,否则每次升级时我们都必须编辑它们的核心源。因此,对于 DocumentViewer 加载语言包,库值具有“documentviewer/locale/en-GB.locale.txt”来加载 DocumentViewer 使用的 PDF.js 的英语语言包。然而,这需要成为一个真正的资源,因此PrimeFaces.getFacesResource('documentviewer/locale/en-GB.locale.txt');
将 URL 转换为 PDF.JS 代码可以找到的适当资源,例如:
https://www.primefaces.org/showcase-ext/javax.faces.resource/documentviewer/locale/en-GB.locale.txt.jsf?ln=primefaces-extensions&v=6.2.5
它处理了解完整 URL、附加库版本以及了解当前服务器是否提供 .jsf 或 .xhtml 扩展名等。
问题:
我正在使用OmniFaces CombinedResourceHandler,它获取所有 JS 文件并从它找到的所有 JS 文件中创建 1 个脚本。所以 10 个不同的 JS 文件现在变成了 1 个资源来实现这样的性能......
/javax.faces.resource/XXX.js.xhtml?ln=omnifaces.combined&v=1532916484000
现在这会破坏核心 PrimeFaces 代码,因为它无法查找 core.js,因为 core.js 不再存在于页面上。
我尝试使用此开关将 core.js 排除在组合之外。
<context-param>
<param-name>org.omnifaces.COMBINED_RESOURCE_HANDLER_EXCLUDED_RESOURCES</param-name>
<param-value>primefaces:core.js</param-value>
</context-param>
这会在破坏整个页面的 omnifaces.combined.js 之后加载 PrimeFaces core.js。要确认输出是这样的...
<script src="/primeext-showcase/javax.faces.resource/XXX.js.jsf?ln=omnifaces.combined&v=1533319992000"></script>
<script src="/primeext-showcase/javax.faces.resource/core.js.jsf?ln=primefaces&v=6.2">
所以我的问题是如何使用纯 JavaScript 替换/修复 PrimeFaces.getFacesResource() JS 函数,无论 OmniFaces 是否组合了脚本?
解决方案
我能够重写该方法以不假设使用正则表达式在页面上找到 core.js。它现在在 PrimeFaces 处于正常模式时工作,并且在使用 OmniFaces CombinedResourceHandler 时工作。我将把它作为一个补丁提交给 PrimeFaces。
这是最终的工作方法:
/**
* Builds a resource URL for given parameters.
*
* @param {string}
* name The name of the resource. For example: primefaces.js
* @param {string}
* library The library of the resource. For example: primefaces
* @param {string}
* version The version of the library. For example: 5.1
* @returns {string} The resource URL.
*/
getFacesResource : function(name, library, version) {
// just get sure - name shoudln't start with a slash
if (name.indexOf('/') === 0) {
name = name.substring(1, name.length);
}
// find any JS served JSF resource
var scriptURI = $('script[src*="/' + PrimeFaces.RESOURCE_IDENTIFIER + '/"]').first().attr('src');
// portlet
if (!scriptURI) {
scriptURI = $('script[src*="' + PrimeFaces.RESOURCE_IDENTIFIER + '="]').first().attr('src');
}
// find script...normal is '/core.js' and portlets are '=core.js'
var scriptRegex = new RegExp('\\/' + PrimeFaces.RESOURCE_IDENTIFIER + '(\\/|=)(.*?)\\.js');
// find script to replace e.g. 'core.js'
var currentScriptName = scriptRegex.exec(scriptURI)[2] + '.js';
// replace core.js with our custom name
scriptURI = scriptURI.replace(currentScriptName, name);
// find the library like ln=primefaces
var libraryRegex = new RegExp('[?&]([^&=]*)ln=(.*?)(&|$)');
// find library to replace e.g. 'ln=primefaces'
var currentLibraryName = 'ln=' + libraryRegex.exec(scriptURI)[2];
// In a portlet environment, url parameters may be namespaced.
var namespace = '';
var urlParametersAreNamespaced = !(scriptURI.indexOf('?' + currentLibraryName) > -1 || scriptURI.indexOf('&'
+ currentLibraryName) > -1);
if (urlParametersAreNamespaced) {
namespace = new RegExp('[?&]([^&=]+)' + currentLibraryName + '($|&)').exec(scriptURI)[1];
}
// If the parameters are namespaced, the namespace must be included
// when replacing parameters.
scriptURI = scriptURI.replace(namespace + currentLibraryName, namespace + 'ln=' + library);
if (version) {
var extractedVersion = new RegExp('[?&]' + namespace + 'v=([^&]*)').exec(scriptURI)[1];
scriptURI = scriptURI.replace(namespace + 'v=' + extractedVersion, namespace + 'v=' + version);
}
var prefix = window.location.protocol + '//' + window.location.host;
return scriptURI.indexOf(prefix) >= 0 ? scriptURI : prefix + scriptURI;
},
推荐阅读
- java - 通过 XML 和注释启动缓存设置
- ruby-on-rails - Rails Heroku 部署问题
- python - 尝试将数据帧的特定列发送到新的 csv 文件,始终返回空数据帧
- json - Postgres如何嵌套多个json_agg子查询
- jquery - Ajax 无法调用控制器方法
- c - 解析具有不同类型的多个参数行并将它们保存在变量中
- json - 如何使复杂数据适合平面列表?
- asp.net - 将 Web 表单表示层迁移到 React
- javascript - 防止 `terser` 改变函数参数名称
- javascript - 使用新生成的图像自动更新/编辑嵌入消息 - Discord.js