├── .gitattributes ├── README.md ├── release ├── myNewTabWE-1.0.xpi ├── myNewTabWE-1.1.xpi ├── myNewTabWE-1.10.xpi ├── myNewTabWE-1.11.1.xpi ├── myNewTabWE-1.11.xpi ├── myNewTabWE-1.2.1.xpi ├── myNewTabWE-1.2.xpi ├── myNewTabWE-1.3.xpi ├── myNewTabWE-1.4.xpi ├── myNewTabWE-1.5.xpi ├── myNewTabWE-1.6.1.xpi ├── myNewTabWE-1.6.xpi ├── myNewTabWE-1.7.xpi ├── myNewTabWE-1.8.1.xpi ├── myNewTabWE-1.8.xpi ├── myNewTabWE-1.9.1.xpi ├── myNewTabWE-1.9.xpi └── updates.json └── src ├── css ├── customize.css ├── index.css ├── options.css └── weather.css ├── html ├── customize.html ├── index.html └── options.html ├── image ├── change.svg ├── config.svg ├── default.svg ├── download.svg └── home.svg ├── js ├── calendar.min.js ├── customize.js ├── index.js └── options.js └── manifest.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # myNewTabWE by sakuyaa 2 | 3 | [myNewTabMod](https://github.com/sakuyaa/myNewTabMod/)这个扩展的WebExtension版本,由于API限制部分功能无法实现。 4 | -------------------------------------------------------------------------------- /release/myNewTabWE-1.0.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.0.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.1.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.1.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.10.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.10.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.11.1.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.11.1.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.11.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.11.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.2.1.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.2.1.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.2.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.2.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.3.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.3.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.4.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.4.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.5.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.5.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.6.1.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.6.1.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.6.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.6.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.7.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.7.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.8.1.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.8.1.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.8.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.8.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.9.1.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.9.1.xpi -------------------------------------------------------------------------------- /release/myNewTabWE-1.9.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakuyaa/myNewTabWE/335c6f74b83f79bfef3dec4386b1bb3bffeb8b5a/release/myNewTabWE-1.9.xpi -------------------------------------------------------------------------------- /release/updates.json: -------------------------------------------------------------------------------- 1 | { 2 | "addons": { 3 | "myNewTabWE@sakuyaa": { 4 | "updates": [ 5 | { 6 | "version": "1.0", 7 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.0.xpi", 8 | "applications": { 9 | "gecko": { 10 | "strict_min_version": "56.0" 11 | } 12 | } 13 | }, { 14 | "version": "1.1", 15 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.1.xpi", 16 | "applications": { 17 | "gecko": { 18 | "strict_min_version": "56.0" 19 | } 20 | } 21 | }, { 22 | "version": "1.2", 23 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.2.xpi", 24 | "applications": { 25 | "gecko": { 26 | "strict_min_version": "56.0" 27 | } 28 | } 29 | }, { 30 | "version": "1.2.1", 31 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.2.1.xpi", 32 | "applications": { 33 | "gecko": { 34 | "strict_min_version": "56.0" 35 | } 36 | } 37 | }, { 38 | "version": "1.3", 39 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.3.xpi", 40 | "applications": { 41 | "gecko": { 42 | "strict_min_version": "56.0" 43 | } 44 | } 45 | }, { 46 | "version": "1.4", 47 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.4.xpi", 48 | "applications": { 49 | "gecko": { 50 | "strict_min_version": "56.0" 51 | } 52 | } 53 | }, { 54 | "version": "1.5", 55 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.5.xpi", 56 | "applications": { 57 | "gecko": { 58 | "strict_min_version": "56.0" 59 | } 60 | } 61 | }, { 62 | "version": "1.6", 63 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.6.xpi", 64 | "applications": { 65 | "gecko": { 66 | "strict_min_version": "56.0" 67 | } 68 | } 69 | }, { 70 | "version": "1.6.1", 71 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.6.1.xpi", 72 | "applications": { 73 | "gecko": { 74 | "strict_min_version": "56.0" 75 | } 76 | } 77 | }, { 78 | "version": "1.7", 79 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.7.xpi", 80 | "applications": { 81 | "gecko": { 82 | "strict_min_version": "56.0" 83 | } 84 | } 85 | }, { 86 | "version": "1.8", 87 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.8.xpi", 88 | "applications": { 89 | "gecko": { 90 | "strict_min_version": "56.0" 91 | } 92 | } 93 | }, { 94 | "version": "1.8.1", 95 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.8.1.xpi", 96 | "applications": { 97 | "gecko": { 98 | "strict_min_version": "56.0" 99 | } 100 | } 101 | }, { 102 | "version": "1.9", 103 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.9.xpi", 104 | "applications": { 105 | "gecko": { 106 | "strict_min_version": "56.0" 107 | } 108 | } 109 | }, { 110 | "version": "1.9.1", 111 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.9.1.xpi", 112 | "applications": { 113 | "gecko": { 114 | "strict_min_version": "56.0" 115 | } 116 | } 117 | }, { 118 | "version": "1.10", 119 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.10.xpi", 120 | "applications": { 121 | "gecko": { 122 | "strict_min_version": "56.0" 123 | } 124 | } 125 | }, { 126 | "version": "1.11", 127 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.11.xpi", 128 | "applications": { 129 | "gecko": { 130 | "strict_min_version": "56.0" 131 | } 132 | } 133 | }, { 134 | "version": "1.11.1", 135 | "update_link": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/myNewTabWE-1.11.1.xpi", 136 | "applications": { 137 | "gecko": { 138 | "strict_min_version": "56.0" 139 | } 140 | } 141 | } 142 | ] 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /src/css/customize.css: -------------------------------------------------------------------------------- 1 | /************************************************** 2 | * myNewTabWE by sakuyaa. 3 | * 4 | * https://github.com/sakuyaa/ 5 | **************************************************/ 6 | body { 7 | background-color: #EEEEEE; 8 | font-family: "microsoft yahei", sans-serif; 9 | margin: 1.5em 3em; 10 | } 11 | 12 | button { 13 | background-color: #F9F9F9; 14 | border: .1em solid gray; 15 | border-radius: .5em; 16 | padding: .3em 1em; 17 | } 18 | button:hover { 19 | background-color: #CCCCCC; 20 | } 21 | button:active { /*点击效果*/ 22 | background-color: #BBBBBB; 23 | } 24 | textarea { 25 | tab-size: 4; 26 | background-color: #F9F9F9; 27 | overflow-y: hidden; 28 | padding: 0; /*使其宽度100%能居中*/ 29 | resize: none; 30 | width: 100%; 31 | } 32 | textarea:focus { /*输入框聚焦效果*/ 33 | box-shadow: 0 0 1em 0 #999999; 34 | transition: box-shadow .1s ease-in-out; 35 | } 36 | 37 | .group { 38 | border: .1em solid gray; 39 | border-radius: .5em; 40 | margin: 1em 0; 41 | } 42 | .header { 43 | background-color: #DDDDDD; 44 | border-bottom: .1em solid gray; 45 | border-top-left-radius: .5em; 46 | border-top-right-radius: .5em; 47 | padding: .5em 1em; 48 | } 49 | .header button { 50 | float: right; /*按钮靠右*/ 51 | margin: -.2em .2em; 52 | } 53 | .content { 54 | padding: .5em 1em; 55 | } 56 | -------------------------------------------------------------------------------- /src/css/index.css: -------------------------------------------------------------------------------- 1 | /************************************************** 2 | * myNewTabWE by sakuyaa. 3 | * 4 | * https://github.com/sakuyaa/ 5 | **************************************************/ 6 | /*天气*/ 7 | #weather { 8 | left: 0; 9 | position: fixed; 10 | top: .5em; 11 | z-index: 1; 12 | } 13 | 14 | html, body { 15 | height: 100%; 16 | } 17 | body { 18 | align-items: center; 19 | background-attachment: fixed; 20 | background-color: #EDEDED; 21 | background-position: center; 22 | background-repeat: no-repeat; 23 | background-size: cover; 24 | display: flex; 25 | flex-direction: column; 26 | font-family: "Microsoft YaHei", sans-serif; 27 | margin: 0; /*避免容器大小100%造成的滚动条*/ 28 | } 29 | /*上下空白高度比例1:3*/ 30 | header { 31 | flex-grow: 1; 32 | } 33 | footer { 34 | flex-grow: 3; 35 | } 36 | 37 | /*日历整体*/ 38 | #date { 39 | color: #1E90FF; 40 | font: bold 3em Arial, "Microsoft YaHei", sans-serif; 41 | margin: .25em 0; 42 | text-align: center; 43 | text-shadow: .1em .1em .1em black; 44 | z-index: 9; 45 | } 46 | /*农历*/ 47 | #lunar { 48 | color: #333; 49 | font-size: .75em; 50 | text-shadow: .1em .1em .1em silver; 51 | } 52 | /*节日*/ 53 | .festival { 54 | color: orangered; 55 | } 56 | /*法定假日*/ 57 | .holiday { 58 | color: red; 59 | } 60 | 61 | /*导航整体面板*/ 62 | #navs { 63 | background-color: rgba(0, 0, 0, .5); 64 | backdrop-filter: blur(5px); 65 | border: .1em solid gray; 66 | border-radius: 1em; 67 | margin-bottom: 1em; /*导航底部保留空间*/ 68 | max-width: 80%; /*最大宽度*/ 69 | z-index: 9; 70 | } 71 | /*导航链接*/ 72 | #navs a { 73 | color: white; 74 | outline: none; /*不显示虚框*/ 75 | text-decoration: none; 76 | } 77 | /*导航图标*/ 78 | #navs img { 79 | height: 1em; 80 | margin-bottom: -.15em; /*与文字对齐*/ 81 | margin-right: .2em; /*与文字的间隔*/ 82 | width: 1em; 83 | } 84 | 85 | /*导航标题*/ 86 | #navtitle { 87 | border-bottom: .15em solid rgba(123, 123, 123, .65); 88 | color: rgba(255, 255, 255, .65); 89 | font-size: 1.25em; 90 | font-weight: bold; 91 | padding: .4em .8em; 92 | } 93 | /*导航标题按钮*/ 94 | #navtitle a { 95 | float: right; 96 | opacity: .5; 97 | padding: 0 .2em; 98 | } 99 | #navtitle a:hover { 100 | opacity: .8; 101 | } 102 | 103 | /*导航表格*/ 104 | #navtable { 105 | padding: .25em 1em; 106 | } 107 | /*设置导航分类*/ 108 | #navtable th { 109 | color: rgba(255, 255, 255, .6); 110 | padding: .3em 0; 111 | text-align: left; 112 | vertical-align: top; 113 | width: 6em; 114 | } 115 | /*设置导航单元大小*/ 116 | #navtable td { 117 | float: left; /*超出自动换行*/ 118 | padding: .3em .2em; 119 | width: 7.2em; /*文字长度6加上图标1和图标文字间的间隔0.2*/ 120 | } 121 | /*设置导航链接*/ 122 | #navtable a { 123 | opacity: .8; 124 | } 125 | #navtable a:hover { 126 | opacity: 1; 127 | text-shadow: 0 1px rgba(64, 64, 255, 0.9), 0 1px 1px rgba(64, 64, 255, 0.9), 0 -1px 1px rgba(64, 64, 255, 0.9), 1px 0 1px rgba(64, 64, 255, 0.9), -1px 0 1px rgba(64, 64, 255, 0.9), 0 0 3px rgba(64, 64, 255, 0.9); 128 | transition: color 0.423s ease, text-shadow 0.423s ease; 129 | } 130 | -------------------------------------------------------------------------------- /src/css/options.css: -------------------------------------------------------------------------------- 1 | /************************************************** 2 | * myNewTabWE by sakuyaa. 3 | * 4 | * https://github.com/sakuyaa/ 5 | **************************************************/ 6 | body { 7 | background-color: #EEEEEE; 8 | font-family: "microsoft yahei", sans-serif; 9 | margin: 1.5em 3em; 10 | } 11 | table { 12 | width: 100%; 13 | } 14 | tr:hover { 15 | background-color: #DDDDDD; 16 | } 17 | th { 18 | background-color: #EEEEEE; /*表头保持背景色*/ 19 | padding: .3em; 20 | } 21 | td { 22 | padding: .3em; 23 | } 24 | button { 25 | background-color: #F9F9F9; 26 | border: .1em solid gray; 27 | border-radius: .5em; 28 | padding: .3em 1em; 29 | } 30 | button:hover { 31 | background-color: #CCCCCC; 32 | } 33 | button:active { /*点击效果*/ 34 | background-color: #BBBBBB; 35 | } 36 | input { 37 | background-color: #F9F9F9; 38 | } 39 | input:focus { /*输入框聚焦效果*/ 40 | box-shadow: 0 0 1em 0 #999999; 41 | transition: box-shadow .1s ease-in-out; 42 | } 43 | 44 | .group { 45 | border: .1em solid gray; 46 | border-radius: .5em; 47 | margin: 1em 0; 48 | } 49 | .header { 50 | background-color: #DDDDDD; 51 | border-bottom: .1em solid gray; 52 | border-top-left-radius: .5em; 53 | border-top-right-radius: .5em; 54 | padding: .5em 1em; 55 | } 56 | .header button { 57 | float: right; /*按钮靠右*/ 58 | margin: -.2em .2em; 59 | } 60 | .content { 61 | padding: .5em 1em; 62 | } 63 | .group-table { 64 | table-layout: fixed; /*固定表格布局*/ 65 | } 66 | .group-table td { /*修剪文本*/ 67 | overflow: hidden; 68 | text-overflow: ellipsis; 69 | white-space: nowrap; 70 | } 71 | .group-table th:first-child { 72 | width: 7em; /*固定表格布局需要对第一行各项控制宽度*/ 73 | } 74 | .group-table th:nth-child(2) { 75 | width: 2em; 76 | } 77 | .group-table th:last-child { /*操作列*/ 78 | width: 15em; 79 | } 80 | .group-table td:nth-child(2), .group-table td:last-child { /*图标按钮居中*/ 81 | text-align: center; 82 | } 83 | .group-table img { 84 | height: 1em; 85 | margin-bottom: -.15em; /*与文字对齐*/ 86 | width: 1em; 87 | } 88 | 89 | #edit-modal { /*模态框遮罩*/ 90 | align-items: center; 91 | background-color: rgba(0, 0, 0, .6); 92 | display: none; /*flex*/ 93 | height: 100%; 94 | justify-content: center; 95 | left: 0; 96 | position: fixed; 97 | top: 0; 98 | width: 100%; 99 | z-index: 9; 100 | } 101 | #edit-modal .content { /*保持背景颜色和圆弧边框*/ 102 | background-color: #EEEEEE; 103 | border-bottom-left-radius: .5em; 104 | border-bottom-right-radius: .5em; 105 | } 106 | #edit-modal input:not([size]), #user-image-src, #title, #weather-src { /*除图标列之外输入框长度*/ 107 | width: 99%; 108 | } 109 | #confirm { /*确认取消按钮位置*/ 110 | border-top: .1em solid gray; 111 | padding-top: .5em; 112 | text-align: center; 113 | } 114 | #logo { 115 | text-align: center; 116 | } 117 | #logo a { 118 | color: black; 119 | font-size: 2.5em; 120 | opacity: .8; 121 | text-decoration: none; 122 | } 123 | #logo img { /*图片文字对齐*/ 124 | height: 1.3em; 125 | vertical-align: top; 126 | } 127 | #config td:first-child { /*选项文字宽度*/ 128 | width: 12em; 129 | } 130 | #image-upload { 131 | float: right; /*按钮靠右*/ 132 | padding: 0 .3em; 133 | } 134 | -------------------------------------------------------------------------------- /src/css/weather.css: -------------------------------------------------------------------------------- 1 | /************************************************** 2 | * myNewTabWE by sakuyaa. 3 | * 4 | * https://github.com/sakuyaa/ 5 | **************************************************/ 6 | /*使其自适应网页宽度*/ 7 | body { 8 | float: left; 9 | } 10 | /*链接白字蓝光*/ 11 | a { 12 | color: rgba(255, 255, 255, 1) !important; 13 | text-decoration: none; 14 | text-shadow: 0 1px rgba(64, 64, 255, 0.9), 0 1px 1px rgba(64, 64, 255, 0.9), 0 -1px 1px rgba(64, 64, 255, 0.9), 15 | 1px 0 1px rgba(64, 64, 255, 0.9), -1px 0 1px rgba(64, 64, 255, 0.9), 0 0 3px rgba(64, 64, 255, 0.9) !important; 16 | } 17 | -------------------------------------------------------------------------------- /src/html/customize.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 定制页面 7 | 8 | 9 | 10 | 11 |

12 |
13 |
14 | 定制天气 15 | 16 | 17 | 18 |
19 |
20 | 21 |
22 |
23 |
24 |
25 | 定制主页 26 | 27 | 28 | 29 |
30 |
31 | 32 |
33 |
34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 |
24 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/html/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 配置页面 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
编辑
15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 32 | 33 |
标题
网址
图标 28 | 29 | 30 | 31 |
34 |
35 | 36 | 37 |
38 |
39 |
40 |
41 | 46 |
47 |
功能
48 |
49 | 50 | 51 | 52 | 53 |
54 |
55 |
56 |
选项
57 |
58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 74 | 75 | 76 | 77 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 |
新标签页打开链接
Bing壁纸最大历史天数
壁纸尺寸 78 | UHD 79 | 1920x1080 80 | 1366x768 81 |
自动切换壁纸
自动下载壁纸
自动下载壁纸文件夹
使用自定义壁纸
自定义壁纸
主页标题
天气栏URL
112 |
113 |
114 |
115 |
导航网址
116 |
117 | 148 |
149 |
150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /src/image/change.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/image/config.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/image/default.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/image/download.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/image/home.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/js/calendar.min.js: -------------------------------------------------------------------------------- 1 | /************************************************** 2 | * Copyright © 2011-2024 sakuyaa. 3 | * All rights reserved. 4 | * 5 | * https://github.com/sakuyaa/ 6 | **************************************************/ 7 | 'use strict'; 8 | let Solar={a:['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],b:['0101*元旦','0214情人节','0305学雷锋纪念日','0308妇女节','0312植树节','0315消费者权益日','0401愚人节','0415国家安全教育日','0422世界地球日','0501*劳动节','0504青年节','0512护士节','0601儿童节','0701建党节','0801建军节','0903抗日战争胜利纪念日','0910教师节','0930烈士纪念日','1001*国庆节','1031万圣节前夜','1101万圣节','1111光棍节','1204宪法日','1213国家公祭日','1224平安夜','1225圣诞节'],c:['0520母亲节','0630父亲节','1144感恩节'],d:a=>a%400==0||(a%4==0&&a%100),e:a=>{let c=0;for(let b=1900;b{let e='';for(let d of Solar.b){if((c.getMonth()+1)*100+c.getDate()==parseInt(d.substring(0,4))){e+=d.substring(4);break;}}for(let d of Solar.c){let a=parseInt(d.substring(0,4));if((c.getMonth()+1)==parseInt(a/100)&&c.getDay()==a%10){let b=parseInt(a/10)%10;if(c.getDate()-(b-1)*7>0&&c.getDate()-b*7<=0){if(e){e+=' ';}e+=d.substring(4);break;}}}return e;},getSolar:a=>{let b={date:(a.getMonth()+1)+'月'+a.getDate()+'日 '+Solar.a[a.getDay()],festival:'',holiday:''};let c=Solar.f(a);if(c.charAt(0)=='*'){b.holiday=c.substring(1);}else{b.festival=c;}return b;}};let Lunar={a:['小寒','大寒','立春','雨水','惊蛰','春分','*清明','谷雨','立夏','小满','芒种','夏至','小暑','大暑','立秋','处暑','白露','秋分','寒露','霜降','立冬','小雪','大雪','冬至'],b:'甲乙丙丁戊己庚辛壬癸',c:'子丑寅卯辰巳午未申酉戌亥',d:'鼠牛虎兔龙蛇马羊猴鸡狗猪',e:['闰','正月','二月','三月','四月','五月','六月','七月','八月','九月','十月','冬月','腊月'],f:'初一二三四五六七八九十廿',g:['0101*春节','0115元宵','0202龙抬头','0303上巳节','0505*端午','0707七夕','0715中元节','0815*中秋','0909重阳','1001寒衣节','1015下元节','1208腊八节','1223北方小年','1224南方小年','1230除夕'],h:1900,i:0,j:[],k:1,l:1,m:true,x:{1382:-1,1393:-1,1395:-1,1408:-1,1413:1,1418:-1,1426:1,1430:-1,1474:1,1483:-1,1489:1,1493:-1,1501:1,1506:-1,1511:1,1524:1,1537:1,1544:-1,1556:-1,1568:-1,1581:-1,1587:1,1594:-1,1602:-1,1607:-1,1609:1,},y:{201111:1,201212:1,201416:1,201511:1,201615:1,201702:-1,201816:1,202123:-1,202210:1,202603:-1,202714:1,202917:1,},n:a=>{if(a in Lunar.x){return Math.floor(1.6+29.5306*a+0.4*Math.sin(1-0.45058*a))+Lunar.x[a];}return Math.floor(1.6+29.5306*a+0.4*Math.sin(1-0.45058*a));},o:(b,a)=>{if((b*100+a)in Lunar.y){return Math.floor(365.242*(b-1900)+6.2+15.22*a-1.9*Math.sin(0.262*a))+Lunar.y[b*100+a];}return Math.floor(365.242*(b-1900)+6.2+15.22*a-1.9*Math.sin(0.262*a));},p:c=>{for(;Lunar.h<=c;Lunar.h++){let a=Lunar.o(Lunar.h-1,23);while(Lunar.n(Lunar.i)<=a){Lunar.i++}if(Lunar.n(Lunar.i+12)<=Lunar.o(Lunar.h,23)){for(let b=0;b<12;b++){a=Lunar.o(Lunar.h,2*b+1);if(Lunar.n(Lunar.i+b)>a||Lunar.n(Lunar.i+b+1)<=a){Lunar.j.push(Lunar.i+b);break;}}}}},q:c=>{Lunar.m=false;Lunar.p(c.getFullYear());let b=Solar.e(c);let a=(c.getFullYear()-1900)*12-1;for(;;a++){if(Lunar.n(a+1)>b){let e=Lunar.j.length;for(let d=0;da){e=d;break;}}Lunar.k=(a-e+11)%12+1;Lunar.l=b-Lunar.n(a)+1;break;}}},r:b=>{let a=b.getFullYear();if(Solar.e(b){for(let a=0;;a++){if(Lunar.o(parseInt(a/12)+1899,a%12*2)>Solar.e(b)){return Lunar.b[a%10]+Lunar.c[a%12]+'月 ';}}},t:b=>{let a=Solar.e(b);a+=9;while(a<0){a+=60000;}return Lunar.b[a%10]+Lunar.c[a%12]+'日 ';},u:b=>{Lunar.q(b);let a=Lunar.e[Lunar.k];if(Lunar.l<=10){a+=Lunar.f[0]+Lunar.f[Lunar.l];}else if(Lunar.l<20){a+=Lunar.f[10]+Lunar.f[Lunar.l%10];}else if(Lunar.l==20){a+=Lunar.f[2]+Lunar.f[10];}else if(Lunar.l==30){a+=Lunar.f[3]+Lunar.f[10];}else{a+=Lunar.f[11]+Lunar.f[Lunar.l%10];}return Lunar.m?Lunar.e[0]+a:a;},v:b=>{for(let a=0;a<24;a++){if(Solar.e(b)==Lunar.o(b.getFullYear(),a)){return Lunar.a[a];}}return'';},w:()=>{for(let a=0;a{let d=Lunar.u(b);let a=Lunar.w();let e=Lunar.v(b);let c={date:Lunar.r(b)+Lunar.s(b)+Lunar.t(b)+d,festival:'',holiday:''};if(e.charAt(0)=='*'){c.holiday=e.substring(1);}else{c.festival=e;}if(a.charAt(0)=='*'){if(c.holiday){c.holiday+=' ';}c.holiday+=a.substring(1);}else{if(c.festival){c.festival+=' ';}if(d=='腊月廿九'&&Lunar.u(new Date(b.getFullYear(),b.getMonth(),b.getDate()+1))!='腊月三十'){c.festival+='除夕';}else{c.festival+=a;}}return c;}}; -------------------------------------------------------------------------------- /src/js/customize.js: -------------------------------------------------------------------------------- 1 | /************************************************** 2 | * myNewTabWE by sakuyaa. 3 | * 4 | * https://github.com/sakuyaa/ 5 | **************************************************/ 6 | 'use strict'; 7 | 8 | //简化函数 9 | const $id = id => document.getElementById(id); 10 | //最近修改过默认css文件的扩展版本,只针对主页 11 | const LAST_MODIFY_CSS_VERSION = '1.11.1'; 12 | 13 | let myNewTabWE = { 14 | css: { 15 | version: 0, 16 | index: '', 17 | weather: '' 18 | }, 19 | defaultCss: { //默认css 20 | index: '', 21 | weather: '' 22 | }, 23 | 24 | notify: (message, title) => { 25 | browser.notifications.create({ 26 | type: 'basic', 27 | message: message + '', 28 | title: title, 29 | iconUrl: browser.runtime.getURL('image/home.svg') 30 | }); 31 | }, 32 | 33 | //获取参数 34 | getStorage: () => { 35 | return new Promise((resolve, reject) => { 36 | browser.storage.local.get({ 37 | css: { 38 | version: 0, 39 | index: '', 40 | weather: '' 41 | } 42 | }).then(storage => { 43 | myNewTabWE.css = storage.css; 44 | resolve(); 45 | }, e => { 46 | myNewTabWE.notify(e, '获取定制css内容失败'); 47 | reject(); 48 | }); 49 | }); 50 | }, 51 | 52 | initConf: async () => { 53 | if (myNewTabWE.css.index) { //存在定制css 54 | if (LAST_MODIFY_CSS_VERSION != myNewTabWE.css.version) { 55 | $id('tips').textContent = '此扩展的默认css相对于定制主页时的默认css有改动,请检查定制css是否需要更新'; 56 | } 57 | } 58 | let response = await fetch('../css/index.css'); //读取默认css 59 | myNewTabWE.defaultCss.index = (await response.text()).split(/\*{50}\/\n/)[1]; //去除文件头备注 60 | response = await fetch('../css/weather.css'); 61 | myNewTabWE.defaultCss.weather = (await response.text()).split(/\*{50}\/\n/)[1]; 62 | if (myNewTabWE.css.weather) { 63 | $id('weather-css').value = myNewTabWE.css.weather; 64 | myNewTabWE.adjustRows($id('weather-css')); 65 | } else { 66 | $id('weather-css').value = ''; //刷新后不自动填写 67 | } 68 | if (myNewTabWE.css.index) { 69 | $id('index-css').value = myNewTabWE.css.index; 70 | myNewTabWE.adjustRows($id('index-css')); 71 | } else { 72 | $id('index-css').value = ''; //刷新后不自动填写 73 | } 74 | }, 75 | initEvent: () => { 76 | $id('weather-save').addEventListener('click', () => { 77 | myNewTabWE.css.weather = $id('weather-css').value; 78 | browser.storage.local.set({css: myNewTabWE.css}).then(null, e => { 79 | myNewTabWE.notify(e, '设置定制css内容失败'); 80 | }); 81 | }); 82 | $id('index-save').addEventListener('click', () => { 83 | myNewTabWE.css.version = $id('index-css').value == '' ? 0 : LAST_MODIFY_CSS_VERSION; 84 | myNewTabWE.css.index = $id('index-css').value; 85 | browser.storage.local.set({css: myNewTabWE.css}).then(null, e => { 86 | myNewTabWE.notify(e, '设置定制css内容失败'); 87 | }); 88 | }); 89 | $id('weather-default').addEventListener('click', () => { 90 | if (!$id('weather-css').value || confirm('是否加载默认css?')) { 91 | $id('weather-css').value = myNewTabWE.defaultCss.weather; 92 | myNewTabWE.adjustRows($id('weather-css')); 93 | } 94 | }); 95 | $id('index-default').addEventListener('click', () => { 96 | if (!$id('index-css').value || confirm('是否加载默认css?')) { 97 | $id('index-css').value = myNewTabWE.defaultCss.index; 98 | myNewTabWE.adjustRows($id('index-css')); 99 | } 100 | }); 101 | $id('weather-css').addEventListener('input', e => { 102 | myNewTabWE.adjustRows(e.target); 103 | }); 104 | $id('index-css').addEventListener('input', e => { 105 | myNewTabWE.adjustRows(e.target); 106 | }); 107 | 108 | //文本框输入Tab 109 | $id('weather-css').addEventListener('keydown', e => { 110 | if (e.key == 'Tab') { 111 | e.preventDefault(); 112 | let start = e.target.selectionStart; 113 | e.target.value = e.target.value.substring(0, start) + '\t' + 114 | e.target.value.substring(e.target.selectionEnd); 115 | e.target.setSelectionRange(start + 1, start + 1); 116 | } 117 | }); 118 | $id('index-css').addEventListener('keydown', e => { 119 | if (e.key == 'Tab') { 120 | e.preventDefault(); 121 | let start = e.target.selectionStart; 122 | e.target.value = e.target.value.substring(0, start) + '\t' + 123 | e.target.value.substring(e.target.selectionEnd); 124 | e.target.setSelectionRange(start + 1, start + 1); 125 | } 126 | }); 127 | }, 128 | 129 | init: () => { 130 | myNewTabWE.initConf(); 131 | myNewTabWE.initEvent(); 132 | }, 133 | 134 | //自动调整文本框行数 135 | adjustRows: textarea => { 136 | textarea.rows = textarea.value.split('\n').length; 137 | } 138 | }; 139 | 140 | myNewTabWE.getStorage().then(myNewTabWE.init); 141 | -------------------------------------------------------------------------------- /src/js/index.js: -------------------------------------------------------------------------------- 1 | /************************************************** 2 | * myNewTabWE by sakuyaa. 3 | * 4 | * https://github.com/sakuyaa/ 5 | **************************************************/ 6 | 'use strict'; 7 | 8 | //简化函数 9 | const $id = id => document.getElementById(id); 10 | const DEFAULT_CONFIG = { 11 | config: { 12 | autoChange: true, //自动切换壁纸 13 | autoDownload: false, //自动下载壁纸 14 | bingMaxHistory: 8, //最大历史天数,可设置[2, 8] 15 | downloadDir: 'bingImg', //相对于浏览器下载文件夹的目录 16 | newTabOpen: true, //是否新标签页打开导航链接 17 | title: '我的主页', //网页标题 18 | useBigImage: 2, //bing图片的尺寸,0为默认的1366x768,1为1920x1080,2为UHD 19 | userImage: false, //使用自定义壁纸 20 | userImageSrc: '', //自定义壁纸的URL 21 | weatherSrc: 'https://i.tianqi.com/index.php?c=code&id=8&num=3' //天气代码的URL 22 | }, 23 | sites: [], 24 | css: { 25 | index: '', 26 | weather: '' 27 | } 28 | }; 29 | 30 | let myNewTabWE = { 31 | bingIndex: 0, //Bing图片历史天数 32 | config: {}, 33 | sites: [], 34 | css: { 35 | index: '', 36 | weather: '' 37 | }, 38 | 39 | //显示桌面通知 40 | notify: (message, title) => { 41 | browser.notifications.create({ 42 | type: 'basic', 43 | message: message + '', 44 | title: title, 45 | iconUrl: browser.runtime.getURL('image/home.svg') 46 | }); 47 | }, 48 | 49 | //获取参数 50 | getStorage: () => { 51 | return new Promise((resolve, reject) => { 52 | browser.storage.local.get(DEFAULT_CONFIG).then(storage => { 53 | myNewTabWE.config = storage.config; 54 | myNewTabWE.sites = storage.sites; 55 | myNewTabWE.css = storage.css; 56 | resolve(); 57 | }, e => { 58 | myNewTabWE.notify(e, '获取myNewTabWE配置失败'); 59 | reject(); 60 | }); 61 | }); 62 | }, 63 | 64 | //初始化css 65 | initCss: () => { 66 | if (myNewTabWE.css.index) { 67 | let style = document.createElement('style'); 68 | style.appendChild(document.createTextNode(myNewTabWE.css.index)); 69 | document.head.appendChild(style); 70 | } else { 71 | let link = document.createElement('link'); 72 | link.rel = 'stylesheet'; 73 | link.href = '../css/index.css'; 74 | document.head.appendChild(link); 75 | } 76 | }, 77 | //初始化日期 78 | initDate: () => { 79 | let date = Solar.getSolar(new Date()); 80 | $id('solar-date').textContent = date.date; 81 | $id('solar-festival').textContent = date.festival; 82 | $id('solar-holiday').textContent = date.holiday; 83 | date = Lunar.getLunar(new Date()); 84 | $id('lunar-date').textContent = date.date; 85 | $id('lunar-festival').textContent = date.festival; 86 | $id('lunar-holiday').textContent = date.holiday; 87 | }, 88 | //初始化导航网址 89 | initSite: () => { 90 | let table = $id('navtable'); 91 | for(let list of myNewTabWE.sites) { 92 | if (list.name.toLowerCase() == 'yooo') { //神秘的代码 93 | let yooo = myNewTabWE.buildTr(list); 94 | yooo.setAttribute('hidden', 'hidden'); 95 | yooo.setAttribute('name', 'yooo'); 96 | table.appendChild(yooo); 97 | } else { 98 | table.appendChild(myNewTabWE.buildTr(list)); 99 | } 100 | } 101 | }, 102 | //初始化监听器 103 | initListener: () => { 104 | //神秘的代码 105 | addEventListener('keydown', e => { 106 | if ((e.key.toLowerCase() == 'q') && e.ctrlKey) { 107 | for (let yooo of document.getElementsByName('yooo')) { 108 | yooo.removeAttribute('hidden'); 109 | } 110 | } 111 | }); 112 | addEventListener('keyup', e => { 113 | for (let yooo of document.getElementsByName('yooo')) { 114 | yooo.setAttribute('hidden', 'hidden'); 115 | } 116 | }); 117 | 118 | $id('change').addEventListener('click', () => { 119 | if (myNewTabWE.isNewDate()) { 120 | myNewTabWE.bingIndex = 0; //过0点重新获取 121 | } else { 122 | myNewTabWE.bingIndex++; 123 | } 124 | myNewTabWE.getBingImage(); 125 | }); 126 | 127 | //自动判断并切换天气、日期和壁纸 128 | let lastCheckTime = new Date(); 129 | setInterval(async () => { 130 | let now = new Date(); 131 | if (now.getDate() != lastCheckTime.getDate()) { //第二天 132 | myNewTabWE.initDate(); 133 | } 134 | if (now.getDate() != lastCheckTime.getDate() || (now.getTime() - lastCheckTime.getTime()) >= 3600000) { //第二天或间隔一小时 135 | lastCheckTime = now; 136 | if (myNewTabWE.config.weatherSrc) { 137 | await myNewTabWE.delay(9876); //延迟获取避免刚唤醒后没有网络 138 | $id('weather').src = myNewTabWE.config.weatherSrc; 139 | } 140 | } 141 | if (!myNewTabWE.config.userImage && myNewTabWE.config.autoChange && myNewTabWE.isNewDate()) { 142 | await myNewTabWE.delay(9876); //延迟获取避免刚唤醒后没有网络 143 | myNewTabWE.bingIndex = 0; 144 | myNewTabWE.getBingImage(); 145 | } 146 | }, 60000); 147 | }, 148 | //初始化背景图片 149 | initImage: () => { 150 | if (myNewTabWE.config.userImage) { //使用自定义壁纸 151 | document.body.style.backgroundImage = `url("${myNewTabWE.config.userImageSrc}")`; 152 | $id('download').setAttribute('hidden', 'hidden'); 153 | } else { 154 | let imageSrc = localStorage.getItem('imageSrc'); 155 | if (imageSrc) { 156 | document.body.style.backgroundImage = `url("${imageSrc}")`; 157 | $id('download').setAttribute('download', localStorage.getItem('imageName')); 158 | if (imageSrc.startsWith('http')) { 159 | $id('download').setAttribute('href', imageSrc); 160 | } else { 161 | $id('download').setAttribute('href', URL.createObjectURL(myNewTabWE.dataURItoBlob(imageSrc))); 162 | } 163 | if (myNewTabWE.config.autoChange && myNewTabWE.isNewDate()) { 164 | myNewTabWE.getBingImage(); //过0点重新获取 165 | } 166 | } else { 167 | myNewTabWE.getBingImage(); 168 | } 169 | } 170 | }, 171 | //初始化天气 172 | initWeather: () => { 173 | return new Promise((resolve, reject) => { 174 | $id('weather').onload = async () => { 175 | for (let tab of await browser.tabs.query({url: browser.runtime.getURL('html/index.html')})) { 176 | for (let frame of await browser.webNavigation.getAllFrames({tabId: tab.id})) { 177 | if (frame.frameId) { 178 | //天气页面插入css 179 | if (myNewTabWE.css.weather) { 180 | await browser.tabs.insertCSS(tab.id, { 181 | code: myNewTabWE.css.weather, 182 | cssOrigin: 'user', 183 | frameId: frame.frameId, 184 | runAt: 'document_start' 185 | }); 186 | } else { 187 | await browser.tabs.insertCSS(tab.id, { 188 | cssOrigin: 'user', 189 | file: browser.runtime.getURL('css/weather.css'), 190 | frameId: frame.frameId, 191 | runAt: 'document_start' 192 | }); 193 | } 194 | //自动适应页面大小 195 | let size = (await browser.tabs.executeScript(tab.id, { 196 | code: '[document.body.scrollHeight, document.body.scrollWidth]', 197 | frameId: frame.frameId, 198 | runAt: 'document_end' 199 | }))[0]; 200 | $id('weather').style.height = size[0] + 'px'; 201 | $id('weather').style.width = size[1] + 'px'; 202 | } 203 | } 204 | } 205 | }; 206 | $id('weather').src = myNewTabWE.config.weatherSrc; 207 | resolve(); 208 | }); 209 | 210 | }, 211 | 212 | init: () => { 213 | document.title = myNewTabWE.config.title; 214 | myNewTabWE.initCss(); 215 | myNewTabWE.initDate(); 216 | myNewTabWE.initSite(); 217 | myNewTabWE.initListener(); 218 | myNewTabWE.initImage(); 219 | 220 | if (myNewTabWE.config.weatherSrc) { 221 | myNewTabWE.initWeather().then(null, e => { 222 | console.log('天气栏css加载失败:' + e); 223 | }); 224 | } 225 | }, 226 | 227 | getBingImage: async () => { 228 | let data, url, image; 229 | try { 230 | data = (await myNewTabWE.httpRequest(`https://cn.bing.com/HPImageArchive.aspx?format=js&n=1&mkt=zh-CN&idx=${myNewTabWE.bingIndex % myNewTabWE.config.bingMaxHistory}`, 231 | 'json', 'https://cn.bing.com/')).images[0]; 232 | url = 'https://cn.bing.com' + data.urlbase; 233 | if (myNewTabWE.config.useBigImage == 2) { 234 | url += '_UHD.jpg'; 235 | } else if (myNewTabWE.config.useBigImage == 1) { 236 | url += '_1920x1080.jpg'; 237 | } else if (myNewTabWE.config.useBigImage == 0) { 238 | url += '_1366x768.jpg'; 239 | } 240 | image = await myNewTabWE.httpRequest(url, 'blob', 'https://cn.bing.com/'); 241 | } catch (e) { 242 | myNewTabWE.notify(e, '获取图片失败'); 243 | return; 244 | } 245 | let reader = new FileReader(); 246 | reader.onload = () => { 247 | document.body.style.backgroundImage = `url("${reader.result}")`; 248 | 249 | //保存图片和获取时间 250 | localStorage.setItem('lastCheckTime', Date.now()); 251 | let imageName = data.enddate + '-' + 252 | data.copyright.replace(/\(.*?\)/g, '').trim() 253 | .replace(/(\\|\/|\*|\|)/g, '') //Win文件名不能包含下列字符 254 | .replace(/:/g, ':') 255 | .replace(/\?/g, '?') 256 | .replace(/("|<|>)/g, '\'') + '.jpg'; 257 | localStorage.setItem('imageName', imageName); 258 | if (myNewTabWE.config.useBigImage > 1) { //UHD大小超出localStorage限制 259 | localStorage.setItem('imageSrc', url); 260 | } else { 261 | localStorage.setItem('imageSrc', reader.result); 262 | } 263 | 264 | 265 | //设置图片下载链接 266 | $id('download').setAttribute('download', imageName); 267 | $id('download').setAttribute('href', URL.createObjectURL(image)); 268 | //自动下载壁纸 269 | if (myNewTabWE.config.autoDownload) { 270 | if (myNewTabWE.config.downloadDir) { 271 | imageName = myNewTabWE.config.downloadDir + '/' + imageName; 272 | } 273 | browser.downloads.download({ 274 | conflictAction: 'overwrite', //覆盖旧文件避免出现重复文件 275 | filename: imageName, 276 | url: URL.createObjectURL(image) 277 | }); 278 | } 279 | }; 280 | reader.readAsDataURL(image); 281 | }, 282 | 283 | buildTr: list => { 284 | let tr = document.createElement('tr'), 285 | th = document.createElement('th'), 286 | td, a, img, textNode, path; 287 | 288 | //添加分类 289 | th.textContent = list.name; 290 | tr.appendChild(th); 291 | 292 | //添加站点 293 | for (let site of list.list) { 294 | td = document.createElement('td'); 295 | a = document.createElement('a'); 296 | img = document.createElement('img'); 297 | textNode = document.createTextNode(site.title); 298 | 299 | a.setAttribute('href', site.url); 300 | if (myNewTabWE.config.newTabOpen) { 301 | a.setAttribute('target', '_blank'); 302 | } 303 | img.src = site.icon ? site.icon : '../image/default.svg'; 304 | 305 | a.appendChild(img); 306 | a.appendChild(textNode); 307 | td.appendChild(a); 308 | tr.appendChild(td); 309 | } 310 | return tr; 311 | }, 312 | 313 | dataURItoBlob: dataURI => { 314 | let byteString = atob(dataURI.substring(dataURI.indexOf(',') + 1)); 315 | let arrayBuffer = new ArrayBuffer(byteString.length); 316 | let array = new Uint8Array(arrayBuffer); 317 | for (let i = 0; i < byteString.length; i++) { 318 | array[i] = byteString.charCodeAt(i); 319 | } 320 | return new Blob([arrayBuffer], {type: dataURI.substring(dataURI.indexOf(':') + 1, dataURI.indexOf(';'))}); 321 | }, 322 | 323 | isNewDate: item => { 324 | let today = new Date(); 325 | today.setHours(0, 0, 0); //毫秒就不管了 326 | if (new Date(parseInt(localStorage.getItem(item ? item : 'lastCheckTime'))) < today) { 327 | return true; 328 | } 329 | return false; 330 | }, 331 | 332 | delay: async time => { 333 | let now = new Date(); 334 | await new Promise(resolve => setTimeout(resolve, time)); 335 | if ((new Date()).getTime() - now.getTime() - time > 999) { 336 | //延迟的时间比预定的还久的话,怀疑是中间电脑睡眠了,重新延迟 337 | return await myNewTabWE.delay(time); 338 | } 339 | }, 340 | 341 | httpRequest: (url, type, referrer) => { 342 | return new Promise((resolve, reject) => { 343 | let xhr = new XMLHttpRequest(); 344 | if (type) { 345 | xhr.responseType = type; 346 | } 347 | xhr.open('GET', url); 348 | if (referrer) { 349 | xhr.setRequestHeader('referrer', referrer); 350 | } 351 | xhr.onload = () => { 352 | if (xhr.status == 200) { 353 | resolve(xhr.response); 354 | } else { 355 | reject(new Error(xhr.statusText)); 356 | } 357 | }; 358 | xhr.onerror = () => { 359 | reject(new Error('网络错误')); 360 | }; 361 | xhr.send(null); 362 | }); 363 | } 364 | }; 365 | 366 | myNewTabWE.getStorage().then(myNewTabWE.init); 367 | -------------------------------------------------------------------------------- /src/js/options.js: -------------------------------------------------------------------------------- 1 | /************************************************** 2 | * myNewTabWE by sakuyaa. 3 | * 4 | * https://github.com/sakuyaa/ 5 | **************************************************/ 6 | 'use strict'; 7 | 8 | //简化函数 9 | const $id = id => document.getElementById(id); 10 | const DEFAULT_CONFIG = { 11 | config: { 12 | autoChange: true, //自动切换壁纸 13 | autoDownload: false, //自动下载壁纸 14 | bingMaxHistory: 8, //最大历史天数,可设置[2, 8] 15 | downloadDir: 'bingImg', //相对于浏览器下载文件夹的目录 16 | newTabOpen: true, //是否新标签页打开导航链接 17 | title: '我的主页', //网页标题 18 | useBigImage: 2, //bing图片的尺寸,0为1366x768,1为1920x1080,2为UHD 19 | userImage: false, //使用自定义壁纸 20 | userImageSrc: '', //自定义壁纸的URL 21 | weatherSrc: 'https://i.tianqi.com/index.php?c=code&id=8&num=3' //天气代码的URL 22 | }, 23 | sites: [] 24 | }; 25 | let upload = $id('upload'); 26 | 27 | let myNewTabWE = { 28 | config: {}, 29 | sites: [], 30 | 31 | notify: (message, title) => { 32 | browser.notifications.create({ 33 | type: 'basic', 34 | message: message + '', 35 | title: title, 36 | iconUrl: browser.runtime.getURL('image/home.svg') 37 | }); 38 | }, 39 | 40 | //获取参数 41 | getStorage: () => { 42 | return new Promise((resolve, reject) => { 43 | browser.storage.local.get(DEFAULT_CONFIG).then(storage => { 44 | myNewTabWE.config = storage.config; 45 | myNewTabWE.sites = storage.sites; 46 | resolve(); 47 | }, e => { 48 | myNewTabWE.notify(e, '获取myNewTabWE配置失败'); 49 | reject(); 50 | }); 51 | }); 52 | }, 53 | setStorage: isConfig => { 54 | if (isConfig) { //保存配置 55 | browser.storage.local.set({config: myNewTabWE.config}).then(null, e => { 56 | myNewTabWE.notify(e, '设置myNewTabWE配置失败'); 57 | }); 58 | } else { //保存网址列表 59 | browser.storage.local.set({sites: myNewTabWE.sites}).then(null, e => { 60 | myNewTabWE.notify(e, '设置myNewTabWE配置失败'); 61 | }); 62 | } 63 | }, 64 | 65 | //初始化导入导出功能 66 | initImportExport: () => { 67 | $id('import').addEventListener('click', () => { 68 | upload.setAttribute('accept', 'application/json'); 69 | upload.onchange = () => { 70 | let reader = new FileReader(); 71 | reader.onload = () => { 72 | let json, storage = {}; 73 | try { 74 | json = JSON.parse(reader.result); 75 | } catch(e) { 76 | myNewTabWE.notify(e, '导入myNewTabWE配置失败'); 77 | return; 78 | } 79 | if (json.config) { 80 | storage.config = json.config; 81 | } 82 | if (json.sites) { 83 | storage.sites = json.sites; 84 | } 85 | if (json.css) { 86 | storage.css = json.css; 87 | } 88 | browser.storage.local.clear().then(() => browser.storage.local.set(storage)).then(() => { 89 | location.reload(); //刷新网页 90 | }, e => { 91 | myNewTabWE.notify(e, '设置myNewTabWE配置失败'); 92 | }); 93 | }; 94 | reader.readAsText(upload.files[0]); 95 | }; 96 | upload.click(); 97 | }); 98 | $id('export').addEventListener('click', async () => { 99 | let storage = { 100 | css: { 101 | version: 0, 102 | index: '', 103 | weather: '' 104 | } 105 | }; 106 | try { //获取定制css内容 107 | storage = await browser.storage.local.get(storage); 108 | } catch(e) { 109 | myNewTabWE.notify(e, '获取定制css内容失败'); 110 | } 111 | browser.downloads.download({ 112 | filename: 'myNewTabWE.json', 113 | saveAs: true, 114 | url: URL.createObjectURL(new Blob([JSON.stringify({ 115 | config: myNewTabWE.config, 116 | sites: myNewTabWE.sites, 117 | css: storage.css 118 | }, null, '\t')])) 119 | }); 120 | }); 121 | }, 122 | //初始化选项 123 | initConf: () => { 124 | $id('newtab-open').checked = myNewTabWE.config.newTabOpen; 125 | if (myNewTabWE.config.bingMaxHistory > 8 || myNewTabWE.config.bingMaxHistory < 2) { 126 | myNewTabWE.config.bingMaxHistory = 8; 127 | myNewTabWE.setStorage(true); 128 | } 129 | $id('bing-max-history').value = myNewTabWE.config.bingMaxHistory; 130 | if (myNewTabWE.config.useBigImage == 2) { 131 | $id('UHD').checked = true; 132 | } else if (myNewTabWE.config.useBigImage == 1) { 133 | $id('1920').checked = true; 134 | } else if (myNewTabWE.config.useBigImage == 0) { 135 | $id('1366').checked = true; 136 | } 137 | $id('auto-change').checked = myNewTabWE.config.autoChange; 138 | $id('auto-download').checked = myNewTabWE.config.autoDownload; 139 | $id('download-dir').value = myNewTabWE.config.downloadDir; 140 | $id('user-image').checked = myNewTabWE.config.userImage; 141 | $id('user-image-src').value = myNewTabWE.config.userImageSrc; 142 | $id('title').value = myNewTabWE.config.title; 143 | $id('weather-src').value = myNewTabWE.config.weatherSrc; 144 | }, 145 | //初始化导航网址 146 | initSites: ()=> { 147 | for (let group of myNewTabWE.sites) { 148 | $id('sites').appendChild(myNewTabWE.buildGroup(group)); 149 | } 150 | $id('new-group').addEventListener('click', () => { 151 | let name = prompt('请输入分组名'); 152 | if (name != null) { 153 | let group = { 154 | name: name, 155 | list: [] 156 | }; 157 | myNewTabWE.sites.push(group); 158 | myNewTabWE.setStorage(); 159 | let node = myNewTabWE.buildGroup(group); 160 | $id('sites').appendChild(node); 161 | node.scrollIntoView({behavior: 'smooth', block: 'end'}); //与滚动区的可视区域的底端对齐 162 | } 163 | }); 164 | }, 165 | //初始化编辑界面 166 | initEdit: () => { 167 | $id('edit-upload').addEventListener('click', () => { 168 | upload.setAttribute('accept', 'image/*'); 169 | upload.onchange = () => { 170 | let reader = new FileReader(); 171 | reader.onload = () => { 172 | $id('edit-icon').value = reader.result; 173 | }; 174 | reader.readAsDataURL(upload.files[0]); 175 | }; 176 | upload.click(); 177 | }); 178 | let count = 0; //用来判断获取到的图标时的模态框是否还是原来的 179 | $id('edit-modal').setAttribute('count', count); 180 | $id('edit-geticon').addEventListener('click', () => { 181 | let iconUrl = /^https?:\/\/[^\/]+/i.exec($id('edit-url').value); //获取host 182 | if (iconUrl) { 183 | $id('edit-geticon').textContent = '正在获取'; 184 | count = parseInt($id('edit-modal').getAttribute('count')); 185 | iconUrl += '/favicon.ico'; 186 | let xhr = new XMLHttpRequest(); 187 | xhr.responseType = 'document'; 188 | xhr.open('GET', $id('edit-url').value, true); 189 | xhr.onload = () => { 190 | if (xhr.status == 200) { 191 | let icon = xhr.response.querySelector('link[rel~=icon]'); 192 | if (icon && icon.href) { 193 | iconUrl = icon.href; 194 | } else { 195 | console.log($id('edit-url').value + ' 没有指定图标,尝试获取favicon.ico'); 196 | } 197 | } else { 198 | console.log(new Error(xhr.statusText)); 199 | } 200 | //获取图标 201 | xhr = new XMLHttpRequest(); 202 | xhr.responseType = 'blob'; 203 | xhr.open('GET', iconUrl, true); 204 | xhr.onload = () => { 205 | if (count == parseInt($id('edit-modal').getAttribute('count'))) { 206 | if (xhr.status == 200) { 207 | let reader = new FileReader(); 208 | reader.onload = () => { 209 | $id('edit-icon').value = reader.result; 210 | }; 211 | reader.readAsDataURL(xhr.response); 212 | } else { 213 | myNewTabWE.notify(new Error(xhr.statusText), '获取图标失败'); 214 | } 215 | $id('edit-geticon').textContent = '自动获取'; 216 | } 217 | }; 218 | xhr.send(null); 219 | }; 220 | xhr.send(null); 221 | } else { 222 | myNewTabWE.notify($id('edit-url').value, '不是标准http网址'); 223 | } 224 | }); 225 | }, 226 | 227 | init: () => { 228 | myNewTabWE.initImportExport(); 229 | myNewTabWE.initConf(); 230 | myNewTabWE.confListener(); 231 | myNewTabWE.initSites(); 232 | myNewTabWE.initEdit(); 233 | }, 234 | 235 | //初始化选项事件 236 | confListener: () => { 237 | $id('config-default').addEventListener('click', e => { 238 | if (confirm('是否恢复默认选项?')) { 239 | myNewTabWE.config = DEFAULT_CONFIG.config; 240 | myNewTabWE.setStorage(true); 241 | myNewTabWE.initConf(); //重新初始化选项 242 | } 243 | }); 244 | $id('newtab-open').addEventListener('click', e => { 245 | myNewTabWE.config.newTabOpen = e.target.checked; 246 | myNewTabWE.setStorage(true); 247 | }); 248 | $id('bing-max-history').addEventListener('change', e => { 249 | myNewTabWE.config.bingMaxHistory = e.target.value; 250 | myNewTabWE.setStorage(true); 251 | }); 252 | $id('UHD').addEventListener('click', () => { 253 | myNewTabWE.config.useBigImage = 2; 254 | myNewTabWE.setStorage(true); 255 | }); 256 | $id('1920').addEventListener('click', () => { 257 | myNewTabWE.config.useBigImage = 1; 258 | myNewTabWE.setStorage(true); 259 | }); 260 | $id('1366').addEventListener('click', () => { 261 | myNewTabWE.config.useBigImage = 0; 262 | myNewTabWE.setStorage(true); 263 | }); 264 | $id('auto-change').addEventListener('click', e => { 265 | myNewTabWE.config.autoChange = e.target.checked; 266 | myNewTabWE.setStorage(true); 267 | }); 268 | $id('auto-download').addEventListener('click', e => { 269 | myNewTabWE.config.autoDownload = e.target.checked; 270 | myNewTabWE.setStorage(true); 271 | }); 272 | $id('download-dir').addEventListener('change', e => { 273 | myNewTabWE.config.downloadDir = e.target.value; 274 | myNewTabWE.setStorage(true); 275 | }); 276 | $id('user-image').addEventListener('click', e => { 277 | myNewTabWE.config.userImage = e.target.checked; 278 | myNewTabWE.setStorage(true); 279 | }); 280 | $id('image-upload').addEventListener('click', e => { 281 | upload.setAttribute('accept', 'image/*'); 282 | upload.onchange = () => { 283 | let reader = new FileReader(); 284 | reader.onload = () => { 285 | $id('user-image-src').value = myNewTabWE.config.userImageSrc = reader.result; 286 | myNewTabWE.setStorage(true); 287 | }; 288 | reader.readAsDataURL(upload.files[0]); 289 | }; 290 | upload.click(); 291 | }); 292 | $id('user-image-src').addEventListener('change', e => { 293 | myNewTabWE.config.userImageSrc = e.target.value; 294 | myNewTabWE.setStorage(true); 295 | }); 296 | $id('title').addEventListener('change', e => { 297 | myNewTabWE.config.title = e.target.value; 298 | myNewTabWE.setStorage(true); 299 | }); 300 | $id('weather-src').addEventListener('change', e => { 301 | myNewTabWE.config.weatherSrc = e.target.value; 302 | myNewTabWE.setStorage(true); 303 | }); 304 | }, 305 | buildGroup: group => { 306 | let node = $id('template-group').cloneNode(true); 307 | node.removeAttribute('id'); 308 | node.removeAttribute('hidden'); 309 | let table = node.querySelector('.group-table'), 310 | row = node.querySelector('.template-row'); 311 | 312 | node.querySelector('.group-name').textContent = group.name; 313 | node.querySelector('.group-up').addEventListener('click', () => { 314 | let index = myNewTabWE.sites.indexOf(group); 315 | if (index) { //不是第一个 316 | myNewTabWE.sites[index - 1] = myNewTabWE.sites.splice(index, 1, myNewTabWE.sites[index - 1])[0]; 317 | myNewTabWE.setStorage(); 318 | node.parentNode.insertBefore(node, node.previousElementSibling); 319 | node.scrollIntoView({behavior: 'smooth', block: 'start'}); 320 | } 321 | }); 322 | node.querySelector('.group-down').addEventListener('click', () => { 323 | let index = myNewTabWE.sites.indexOf(group); 324 | if (index + 1 < myNewTabWE.sites.length) { //不是最后一个 325 | myNewTabWE.sites[index + 1] = myNewTabWE.sites.splice(index, 1, myNewTabWE.sites[index + 1])[0]; 326 | myNewTabWE.setStorage(); 327 | node.parentNode.insertBefore(node.nextElementSibling, node); 328 | node.scrollIntoView({behavior: 'smooth', block: 'start'}); 329 | } 330 | }); 331 | node.querySelector('.group-add').addEventListener('click', () => { 332 | let site = { 333 | title: '', 334 | url: '', 335 | icon: '' 336 | }; 337 | myNewTabWE.editSite(site).then(() => { 338 | group.list.push(site); 339 | myNewTabWE.setStorage(); 340 | let node = myNewTabWE.buildTr(site, group.list, row.cloneNode(true)); 341 | table.appendChild(node); 342 | node.scrollIntoView({behavior: 'smooth', block: 'end'}); //与滚动区的可视区域的底端对齐 343 | }); 344 | }); 345 | node.querySelector('.group-rename').addEventListener('click', () => { 346 | let name = prompt('请输入分组名', group.name); 347 | if (name != null) { 348 | group.name = name; 349 | myNewTabWE.setStorage(); 350 | node.querySelector('.group-name').textContent = group.name; 351 | } 352 | }); 353 | node.querySelector('.group-delete').addEventListener('click', () => { 354 | myNewTabWE.sites.splice(myNewTabWE.sites.indexOf(group), 1); 355 | myNewTabWE.setStorage(); 356 | $id('sites').removeChild(node); 357 | }); 358 | for (let site of group.list) { 359 | table.appendChild(myNewTabWE.buildTr(site, group.list, row.cloneNode(true))); 360 | } 361 | return node; 362 | }, 363 | buildTr: (site, list, node) => { 364 | node.removeAttribute('class'); 365 | node.removeAttribute('hidden'); 366 | let title = node.querySelector('.row-title'), 367 | img = node.querySelector('.row-icon img'), 368 | url = node.querySelector('.row-url'); 369 | title.textContent = title.title = site.title; 370 | img.src = img.title = site.icon ? site.icon : '../image/default.svg'; 371 | url.textContent = url.title = site.url; 372 | node.querySelector('.row-up').addEventListener('click', () => { 373 | let index = list.indexOf(site); 374 | if (index) { //不是第一个 375 | list[index - 1] = list.splice(index, 1, list[index - 1])[0]; 376 | myNewTabWE.setStorage(); 377 | node.parentNode.insertBefore(node, node.previousElementSibling); 378 | } 379 | }); 380 | node.querySelector('.row-down').addEventListener('click', () => { 381 | let index = list.indexOf(site); 382 | if (index + 1 < list.length) { //不是最后一个 383 | list[index + 1] = list.splice(index, 1, list[index + 1])[0]; 384 | myNewTabWE.setStorage(); 385 | node.parentNode.insertBefore(node.nextElementSibling, node); 386 | } 387 | }); 388 | node.querySelector('.row-edit').addEventListener('click', () => { 389 | myNewTabWE.editSite(site).then(() => { 390 | title.textContent = title.title = site.title; 391 | img.src = img.title = site.icon; 392 | url.textContent = url.title = site.url; 393 | myNewTabWE.setStorage(); 394 | }); 395 | }); 396 | node.querySelector('.row-delete').addEventListener('click', () => { 397 | list.splice(list.indexOf(site), 1); 398 | myNewTabWE.setStorage(); 399 | node.parentNode.removeChild(node); 400 | }); 401 | return node; 402 | }, 403 | editSite: site => { 404 | return new Promise((resolve, reject) => { 405 | $id('edit-title').value = site.title; 406 | $id('edit-url').value = site.url; 407 | $id('edit-icon').value = site.icon; 408 | $id('edit-geticon').textContent = '自动获取'; 409 | $id('edit-confirm').onclick = () => { 410 | site.title = $id('edit-title').value; 411 | site.url = $id('edit-url').value; 412 | site.icon = $id('edit-icon').value; 413 | $id('edit-modal').style.display = 'none'; 414 | $id('edit-modal').setAttribute('count', parseInt($id('edit-modal').getAttribute('count')) + 1); 415 | resolve(); 416 | }; 417 | $id('edit-cancel').onclick = () => { 418 | $id('edit-modal').style.display = 'none'; 419 | $id('edit-modal').setAttribute('count', parseInt($id('edit-modal').getAttribute('count')) + 1); 420 | reject(); 421 | }; 422 | $id('edit-modal').style.display = 'flex'; 423 | $id('edit-title').focus(); 424 | }); 425 | } 426 | }; 427 | 428 | myNewTabWE.getStorage().then(myNewTabWE.init); 429 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "applications": { 3 | "gecko": { 4 | "id": "myNewTabWE@sakuyaa", 5 | "strict_min_version": "56.0", 6 | "update_url": "https://raw.githubusercontent.com/sakuyaa/myNewTabWE/master/release/updates.json" 7 | } 8 | }, 9 | "author": "sakuyaa", 10 | "chrome_settings_overrides": { 11 | "homepage": "html/index.html" 12 | }, 13 | "chrome_url_overrides": { 14 | "newtab": "html/index.html" 15 | }, 16 | "description": "myNewTabMod这个扩展的WebExtension版本,由于API限制部分功能无法实现", 17 | "homepage_url": "https://github.com/sakuyaa/myNewTabWE", 18 | "icons": { 19 | "48": "image/home.svg", 20 | "96": "image/home.svg" 21 | }, 22 | "manifest_version": 2, 23 | "name": "myNewTab WE", 24 | "options_ui": { 25 | "browser_style": false, 26 | "open_in_tab": true, 27 | "page": "html/options.html" 28 | }, 29 | "permissions": [ 30 | "downloads", 31 | "notifications", 32 | "storage", 33 | "tabs", 34 | "unlimitedStorage", 35 | "webNavigation", 36 | "" 37 | ], 38 | "version": "1.11.1" 39 | } --------------------------------------------------------------------------------