I[★]
@@ -18,44 +18,43 @@
(() => {
'use strict';
- const change_star_icon_attr = (ctx) => {
- ctx.querySelectorAll([
- 'img.hatena-star-add-button[src*="s.hatena.ne.jp"]',
- ]).forEach(button => {
- // https://developer.mozilla.org/en-US/docs/Web/CSS/filter
- // NOTE order sensitive and multi effective
- button.style.filter = [
- // reset to black
- 'grayscale(1) brightness(0)',
- // w/ black to hex CSS filter generator by Barrett Sonntag c.f.
- // https://codepen.io/sosuke/pen/Pjoqqp
- // https://codepen.io/sosuke/pen/Pjoqqp/license
- // via
- // https://gist.github.com/barretts/e90d7e5251f36b183c67e02ba54c9ae1
- //
- // same as star-comment activated color
- // http://s.hatena.ne.jp/images/comment_active.gif
- // rgb(251, 208, 148) | #fbd094
- 'invert(80%)',
- 'sepia(60%)',
- 'saturate(312%)',
- 'hue-rotate(333deg)',
- 'brightness(100%)',
- 'contrast(98%)',
- ].join(' ');
+ const add_style = (() => {
+ const wall = document.head || document.body || document.documentElement;
- button.alt = button.title = 'Add Star (force quote)';
- });
- };
- change_star_icon_attr(document.body);
-
- // infinite scrolling
- // TBD use Proxy/Reflect, slightly speedup and completely capsulization
- new MutationObserver(records => {
- records.forEach(record => {
- change_star_icon_attr(record.target);
- });
- }).observe(document.body, { childList: true, subtree: true });
+ const style = wall.appendChild(Object.assign(document.createElement('style'), {
+ type: 'text/css',
+ charset: 'utf-8',
+ }));
+
+ return (css) => {
+ style.appendChild(document.createTextNode(css + '\n'));
+ };
+ })();
+
+ add_style([
+ 'img.hatena-star-add-button[src*="s.hatena.ne.jp"] {',
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/filter
+ // NOTE order sensitive and multi effective
+ 'filter:',
+ // reset to black
+ 'grayscale(1) brightness(0)',
+ // w/ black to hex CSS filter generator by Barrett Sonntag c.f.
+ // https://codepen.io/sosuke/pen/Pjoqqp
+ // https://codepen.io/sosuke/pen/Pjoqqp/license
+ // via
+ // https://gist.github.com/barretts/e90d7e5251f36b183c67e02ba54c9ae1
+ //
+ // same as star-comment activated color
+ // http://s.hatena.ne.jp/images/comment_active.gif
+ // rgb(251, 208, 148) | #fbd094
+ 'invert(80%)',
+ 'sepia(60%)',
+ 'saturate(312%)',
+ 'hue-rotate(333deg)',
+ 'brightness(100%)',
+ 'contrast(98%)',
+ '}',
+ ].join(' '));
// http://q.hatena.ne.jp/1487227736#a1262105
const to_numeric_reference = (str) => {
@@ -106,3 +105,8 @@
// https://s.hatena.ne.jp/star.deletable.json
})();
+// DEV
+//
+// perhaps fork of in 2017
+// http://let.hatelabo.jp/a-kuma3/let/hLHWycCUqaF_
+
/*
* @title I[★]
* @description greedy quote Hatena Star
* @include http://*
* @include https://*
* @contributor a-kuma3 http://let.hatelabo.jp/a-kuma3/let/hJmc_YyG8sE-
* @nitpicker noromanba
* @license MIT License https://opensource.org/licenses/MIT
* @javascript_url
*/
// TBD .com handling
// TBC spec and behavior
// e.g.
// http://let.hatelabo.jp/noromanba/let/hJmc_7WUiuhh
// https://s.hatena.ne.jp/mobile/entry?uri=http%3A%2F%2Flet.hatelabo.jp%2Fnoromanba%2Flet%2FhJmc_7WUiuhh
(() => {
'use strict';
const add_style = (() => {
const wall = document.head || document.body || document.documentElement;
const style = wall.appendChild(Object.assign(document.createElement('style'), {
type: 'text/css',
charset: 'utf-8',
}));
return (css) => {
style.appendChild(document.createTextNode(css + '\n'));
};
})();
add_style([
'img.hatena-star-add-button[src*="s.hatena.ne.jp"] {',
// https://developer.mozilla.org/en-US/docs/Web/CSS/filter
// NOTE order sensitive and multi effective
'filter:',
// reset to black
'grayscale(1) brightness(0)',
// w/ black to hex CSS filter generator by Barrett Sonntag c.f.
// https://codepen.io/sosuke/pen/Pjoqqp
// https://codepen.io/sosuke/pen/Pjoqqp/license
// via
// https://gist.github.com/barretts/e90d7e5251f36b183c67e02ba54c9ae1
//
// same as star-comment activated color
// http://s.hatena.ne.jp/images/comment_active.gif
// rgb(251, 208, 148) | #fbd094
'invert(80%)',
'sepia(60%)',
'saturate(312%)',
'hue-rotate(333deg)',
'brightness(100%)',
'contrast(98%)',
'}',
].join(' '));
// http://q.hatena.ne.jp/1487227736#a1262105
const to_numeric_reference = (str) => {
let letter = '', i = 0;
while (i < str.length) {
const code = str.codePointAt(i);
letter += code < 128 ? String.fromCharCode(code) : `&#${code};`;
i += 1;
// for surrogate pair
if (code > 0xffff) {
i += 1;
}
}
return letter;
};
// http://q.hatena.ne.jp/1487227736#a1262105
const enforce_quote = (url_string) => {
const url = new URL(url_string);
// https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
const quote = url.searchParams.get('quote');
if (!quote) {
return url_string;
}
const safed = to_numeric_reference(quote);
url.searchParams.set('quote', safed);
return url.href;
};
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
// https://s.hatena.ne.jp/js/HatenaStar.js:111
// Ten.JSONP(<URL_STRING>, <JSON_CALLBACK> [,<METHOD_NAME>])
window.Ten.JSONP = new Proxy(window.Ten.JSONP, {
construct: (target, args) => {
const url_string = args[0];
if (url_string.includes('//s.hatena.ne.jp/star.add.json')) {
args[0] = enforce_quote(url_string);
}
return Reflect.construct(target, args);
},
});
// TBD quote handling when delete surrogates from normal UI
// https://s.hatena.ne.jp/star.delete.json
// https://s.hatena.ne.jp/star.deletable.json
})();
// DEV
//
// perhaps fork of in 2017
// http://let.hatelabo.jp/a-kuma3/let/hLHWycCUqaF_
- Permalink
- このページへの個別リンクです。
- RAW
- 書かれたコードへの直接のリンクです。
- Packed
- 文字列が圧縮された書かれたコードへのリンクです。
- Userscript
- Greasemonkey 等で利用する場合の .user.js へのリンクです。
- Loader
- @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
- Metadata
- コード中にコメントで @xxx と書かれたメタデータの JSON です。