Browse Source

增加网页编码设置功能

zxlie 7 years ago
parent
commit
0319098738
4 changed files with 197 additions and 3 deletions
  1. 1 0
      README.md
  2. 9 1
      apps/background/index.js
  3. 3 2
      apps/manifest.json
  4. 184 0
      apps/page-encoding/background.js

+ 1 - 0
README.md

@@ -43,6 +43,7 @@ https://chrome.google.com/webstore/detail/pkgccpejnmalmdinmhkkfafefagiiiad?hl=zh
 - 编码规范检测(HTML/CSS/JS规范检测)
 - 页面性能检测(页面响应时间、Header监测)
 - Ajax调试功能(需在控制台中使用)
+- 网页编码设置(UTF-8、GBK、日文、韩文等)
 
 ### 四、用户反馈渠道
 - https://www.baidufe.com/fehelper/feedback.html

+ 9 - 1
apps/background/index.js

@@ -280,6 +280,15 @@ var BgPageInstance = (function () {
             contexts: ['page', 'selection', 'editable', 'link', 'image'],
             documentUrlPatterns: ['http://*/*', 'https://*/*', 'file://*/*']
         });
+
+        // 网页编码设置的menu
+        PageEncoding.createMenu(feHelper.contextMenuId);
+
+        chrome.contextMenus.create({
+            type: 'separator',
+            contexts: ['all'],
+            parentId: feHelper.contextMenuId
+        });
         chrome.contextMenus.create({
             title: "▣  二维码生成",
             contexts: ['page', 'selection', 'editable', 'link', 'image'],
@@ -696,7 +705,6 @@ var BgPageInstance = (function () {
             }
             // ===========================以上为编码规范检测====end==================================
 
-
             return true;
         });
 

+ 3 - 2
apps/manifest.json

@@ -1,9 +1,9 @@
 {
   "name": "WEB前端助手(FeHelper)",
-  "version": "2018.10.2512",
+  "version": "2018.11.0116",
   "manifest_version": 2,
   "default_locale": "zh_CN",
-  "description": "FE助手:包括JSON格式化、二维码生成与解码、信息编解码、代码压缩、美化、页面取色、Markdown与HTML互转、网页滚动截屏、正则表达式、时间转换工具、编码规范检测、页面性能检测、Ajax接口调试、密码生成器、JSON比对工具",
+  "description": "FE助手:包括JSON格式化、二维码生成与解码、信息编解码、代码压缩、美化、页面取色、Markdown与HTML互转、网页滚动截屏、正则表达式、时间转换工具、编码规范检测、页面性能检测、Ajax接口调试、密码生成器、JSON比对工具、网页编码设置",
   "icons": {
     "16": "static/img/fe-16.png",
     "48": "static/img/fe-48.png",
@@ -19,6 +19,7 @@
     "scripts": [
       "background/detect.js",
       "static/vendor/require/require.js",
+      "page-encoding/background.js",
       "background/index.js"
     ]
   },

+ 184 - 0
apps/page-encoding/background.js

@@ -0,0 +1,184 @@
+/**
+ * 页面编码集
+ * @author zhaoxianlie
+ */
+"use strict";
+
+let PageEncoding = (() => {
+
+    // 某Tab的编码都暂存一下,这是prefix
+    const ENCODING_PREFIX = 'FE_ENCODING_PREFIX_';
+
+    // 系统支持的编码列表
+    let EncodingList = [
+        ['default', '默认'],
+        ['UTF-8', 'Unicode'],
+        ['GBK', '中文(简体全)'],
+        ['GB3212', '中文(简体)'],
+        ['GB18030', '中文(简体)'],
+        ['Big5', '中文(繁体)'],
+        ['UTF-16LE', 'Unicode'],
+        ['EUC-KR', '韩文'],
+        ['Shift_JIS', '日文'],
+        ['EUC-JP', '日文'],
+        ['ISO-2022-JP', '日文'],
+        ['Windows-874', '泰文'],
+        ['Windows-1254', '土耳其文'],
+        ['ISO-8859-7', '希腊文'],
+        ['Windows-1253', '希腊文'],
+        ['Windows-1252', '西文'],
+        ['ISO-8859-15', '西文'],
+        ['Macintosh', '西文'],
+        ['Windows-1258', '越南文'],
+        ['ISO-8859-2', '中欧文'],
+        ['Windows-1250', '中欧文']
+    ];
+
+
+    // 菜单列表
+    let menuMap = {};
+    // 监听是否已经加过了
+    let listenerAddedFlag = false;
+
+    /**
+     * 创建右键菜单
+     */
+    let createMenu = (parentMenuId) => {
+
+        let encodingMenu = chrome.contextMenus.create({
+            title: "♨  网页编码设置",
+            contexts: ["all"],
+            documentUrlPatterns: ['http://*/*', 'https://*/*', 'file://*/*'],
+            parentId: parentMenuId
+        });
+
+        EncodingList.forEach(item => {
+            menuMap[item[0].toUpperCase()] = chrome.contextMenus.create({
+                type: "radio",
+                contexts: ["all"],
+                title: item[0] === 'default' ? '默认' : `${item[1]}(${item[0]})`,
+                checked: item[0] === 'default',
+                parentId: encodingMenu,
+                onclick: (info, tab) => {
+                    if (!info.wasChecked) {
+                        if (item[0] === 'default') {
+                            localStorage.removeItem(ENCODING_PREFIX + tab.id);
+                        } else {
+                            localStorage.setItem(ENCODING_PREFIX + tab.id, item[0]);
+                        }
+                        if (!listenerAddedFlag) {
+                            addOnlineSiteEncodingListener((granted) => {
+                                if (granted) {
+                                    chrome.tabs.reload(tab.id, {
+                                        bypassCache: true
+                                    });
+                                }
+                            });
+                        } else {
+                            chrome.tabs.reload(tab.id, {
+                                bypassCache: true
+                            });
+                        }
+                    }
+                }
+            });
+        });
+    };
+
+    /**
+     * 更新菜单的选中状态
+     * @param tabId
+     */
+    let updateMenu = (tabId) => {
+        Object.keys(menuMap).forEach(menu => {
+            chrome.contextMenus.update(menuMap[menu], {
+                checked: false
+            });
+        });
+
+        // 选中它该选中的
+        let encoding = localStorage.getItem(ENCODING_PREFIX + tabId) || '';
+        let menuId = encoding ? menuMap[encoding.toUpperCase()] : menuMap['DEFAULT'];
+        chrome.contextMenus.update(menuId || menuMap['DEFAULT'], {
+            checked: true
+        });
+    };
+
+
+    /**
+     * web请求截获,重置response Headers
+     * @param callback
+     */
+    let addOnlineSiteEncodingListener = (callback) => {
+        // 请求权限
+        chrome.permissions.request({
+            permissions: ['webRequest', 'webRequestBlocking']
+        }, (granted) => {
+            if (granted) {
+                listenerAddedFlag = true;
+                chrome.webRequest.onHeadersReceived.addListener((details) => {
+                    let tabEncoding = localStorage.getItem(ENCODING_PREFIX + details.tabId);
+
+                    if (tabEncoding) {
+                        let i, charsetPattern = /; ?charset=([^;]+)/;
+                        for (i = 0; i < details.responseHeaders.length; ++i) {
+                            if (details.responseHeaders[i].name.toLowerCase() === 'content-type') {
+                                let value = details.responseHeaders[i].value.toLowerCase();
+                                if (
+                                    value.startsWith('text') ||
+                                    value.startsWith('application/javascript') ||
+                                    value.startsWith('application/x-javascript') ||
+                                    value.startsWith('application/json')
+                                ) {
+                                    if (charsetPattern.test(value)) {
+                                        value = value.replace(charsetPattern.exec(value)[1], tabEncoding);
+                                    } else {
+                                        value += value.substr(-1) === ';' ? ' ' : '; ';
+                                        value += 'charset=' + tabEncoding;
+                                    }
+                                    details.responseHeaders[i].value = value;
+                                }
+                                break;
+                            }
+                        }
+                        if (i >= details.responseHeaders.length) {
+                            details.responseHeaders.push({
+                                name: 'Content-Type',
+                                value: 'text/plain; charset=' + tabEncoding
+                            });
+                        }
+                    }
+                    return {responseHeaders: details.responseHeaders};
+                }, {urls: ["<all_urls>"]}, ["responseHeaders", "blocking"]);
+            } else {
+                alert('必须接受授权,才能正常使用!');
+            }
+            callback && callback(granted);
+        });
+
+        // 标签被关闭时的检测
+        chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
+            localStorage.removeItem(ENCODING_PREFIX + tabId);
+        });
+        // 标签页有切换时
+        chrome.tabs.onActivated.addListener((activeInfo) => {
+            if (Object.keys(menuMap).length) {
+                updateMenu(activeInfo.tabId);
+            }
+        });
+        chrome.windows.onFocusChanged.addListener(() => {
+            if (Object.keys(menuMap).length) {
+                chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
+                    if (tabs.length) {
+                        updateMenu(tabs[0].id);
+                    }
+                });
+            }
+        });
+    };
+
+    return {
+        createMenu
+    };
+
+})();