-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild-inline.html
More file actions
162 lines (162 loc) · 7.24 KB
/
Copy pathbuild-inline.html
File metadata and controls
162 lines (162 loc) · 7.24 KB
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>内联版 bookmarklet 生成器</title>
<style>
body { font: 14px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei", sans-serif; padding: 24px; max-width: 920px; margin: 0 auto; color: #222; }
h1 { font-size: 20px; margin: 0 0 12px; }
h2 { font-size: 16px; margin: 22px 0 8px; border-left: 3px solid #2196f3; padding-left: 8px; }
p, li { color: #555; }
code { background: #f4f4f4; padding: 1px 6px; border-radius: 3px; font-family: ui-monospace, Consolas, monospace; font-size: 13px; }
pre, .out { background: #f7f7f7; border: 1px solid #eee; padding: 12px; border-radius: 6px; overflow: auto; max-height: 220px; font-family: ui-monospace, Consolas, monospace; font-size: 12px; word-break: break-all; white-space: pre-wrap; }
.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin: 12px 0; }
button { background: #2196f3; color: #fff; border: 0; padding: 8px 14px; border-radius: 6px; cursor: pointer; font-size: 13px; }
button.copy { background: #4caf50; }
a.drag {
display: inline-block;
background: linear-gradient(180deg, #ffd54f, #ffb300);
color: #222;
padding: 10px 20px;
border-radius: 8px;
text-decoration: none;
font-weight: 700;
cursor: grab;
box-shadow: 0 2px 6px rgba(0,0,0,.15);
user-select: none;
}
.tip { background: #fff7e0; border-left: 3px solid #ffb300; padding: 10px 14px; border-radius: 4px; margin: 14px 0; }
.ok { color: #2e7d32; }
.bad { color: #c62828; }
label { font-weight: 600; }
.meta { color: #888; font-size: 12px; }
</style>
</head>
<body>
<h1>内联版 Bookmarklet 生成器</h1>
<p>把整段 <code>camera-mock.js</code> 直接编码进 <code>javascript:</code> URL,<b>不依赖外部加载</b>,可以绕过 CSP <code>script-src</code> 限制。</p>
<div class="tip">
页面打开后会自动尝试 fetch 同目录的 <code>camera-mock.js</code>。如果你是双击本 HTML 打开(<code>file://</code> 协议),可能会因为本地跨域失败 —— 这时请改用<b>方式 B</b> 手动粘贴源码。
</div>
<h2>① 加载源码</h2>
<div class="row">
<button id="reload">从同目录加载 camera-mock.js</button>
<span class="meta" id="meta">未加载</span>
</div>
<p>或者手动粘贴:</p>
<textarea id="src" rows="6" style="width:100%;box-sizing:border-box;font-family:ui-monospace,Consolas,monospace;font-size:12px;padding:8px;border:1px solid #ddd;border-radius:6px;" placeholder="把 camera-mock.js 的全部内容粘贴到这里"></textarea>
<div class="row">
<button id="build">生成 Bookmarklet</button>
<label><input type="checkbox" id="mini" checked /> 简易压缩</label>
</div>
<h2>② 拖到书签栏</h2>
<p>把下面这个按钮直接拖到 Chrome / Edge / Firefox 的书签栏即可:</p>
<div class="row">
<a id="drag" class="drag" href="#" draggable="true">📷 摄像头注入(内联)</a>
<button class="copy" id="copy">复制 URL</button>
<span class="meta" id="size"></span>
</div>
<h2>③ URL 预览</h2>
<div class="out" id="out">等待生成…</div>
<h2>iOS Safari 安装</h2>
<ol>
<li>用上面"复制 URL"按钮 → 通过 AirDrop / 微信发到手机。</li>
<li>iPhone Safari 打开任意页面 → 分享 → 添加书签 → 命名"摄像头注入" → 保存。</li>
<li>书签列表 → 编辑刚才那条 → 把 URL 整段替换为复制的 <code>javascript:...</code>。</li>
</ol>
<h2>常见问题</h2>
<ul>
<li><b>Chrome bookmarklet 长度限制:</b>实测 1MB 以内都能用,本工具产物大约 30KB,安全。</li>
<li><b>iOS Safari 上限约 80KB:</b>本产物在限制内。</li>
<li><b>仍然没反应:</b>F12 看 Console;如果连 Console 都没任何输出,把书签 URL 拷出来检查是不是被 Chrome 改成了 https:// 开头。</li>
</ul>
<script>
var rawSrc = '';
function setMeta(t, ok) {
var el = document.getElementById('meta');
el.textContent = t;
el.className = 'meta ' + (ok ? 'ok' : 'bad');
}
function loadSameDir() {
fetch('./camera-mock.js?_=' + Date.now())
.then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.text(); })
.then(function (t) {
rawSrc = t;
document.getElementById('src').value = t;
setMeta('已加载 ' + t.length + ' 字符', true);
build();
})
.catch(function (e) {
setMeta('加载失败:' + e.message + '(请手动粘贴)', false);
});
}
function minify(src) {
var out = '';
var i = 0, len = src.length;
while (i < len) {
var c = src[i], n = src[i + 1];
if (c === '"' || c === "'" || c === '`') {
var q = c;
out += c; i++;
while (i < len) {
var cc = src[i];
out += cc;
if (cc === '\\') { out += src[i + 1] || ''; i += 2; continue; }
i++;
if (cc === q) break;
}
continue;
}
if (c === '/' && n === '*') {
i += 2;
while (i < len && !(src[i] === '*' && src[i + 1] === '/')) i++;
i += 2;
continue;
}
if (c === '/' && n === '/') {
while (i < len && src[i] !== '\n') i++;
continue;
}
out += c;
i++;
}
out = out.replace(/[\r\n\t]+/g, '\n').replace(/[ ]{2,}/g, ' ').replace(/\n[ ]+/g, '\n').replace(/\n{2,}/g, '\n');
return out.trim();
}
function build() {
var src = document.getElementById('src').value;
if (!src.trim()) { setOut('请先加载或粘贴源码'); return; }
try {
var code = document.getElementById('mini').checked ? minify(src) : src;
var wrapped = '(function(){' + code + '})();';
var url = 'javascript:' + encodeURIComponent(wrapped);
setOut(url);
document.getElementById('drag').href = url;
document.getElementById('size').textContent = '长度:' + url.length + ' 字符';
} catch (e) {
setOut('压缩失败:' + e.message + '\n请取消"简易压缩"再试一次');
}
}
function setOut(t) { document.getElementById('out').textContent = t; }
document.getElementById('reload').addEventListener('click', loadSameDir);
document.getElementById('build').addEventListener('click', build);
document.getElementById('mini').addEventListener('change', build);
document.getElementById('src').addEventListener('input', function () {
clearTimeout(window.__bt);
window.__bt = setTimeout(build, 300);
});
document.getElementById('copy').addEventListener('click', function () {
var t = document.getElementById('out').textContent;
if (!t || t === '等待生成…') return;
navigator.clipboard.writeText(t).then(function () { alert('已复制'); }, function () {
var r = document.createRange();
r.selectNodeContents(document.getElementById('out'));
var s = getSelection(); s.removeAllRanges(); s.addRange(r);
alert('请按 Ctrl+C 复制');
});
});
loadSameDir();
</script>
</body>
</html>