aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--google-plus-commando.js139
1 files changed, 88 insertions, 51 deletions
diff --git a/google-plus-commando.js b/google-plus-commando.js
index 88adb64..1851032 100644
--- a/google-plus-commando.js
+++ b/google-plus-commando.js
@@ -36,7 +36,7 @@ THE POSSIBILITY OF SUCH DAMAGE.
// INFO {{{
let INFO =
<>
- <plugin name="GooglePlusCommando" version="2.1.5"
+ <plugin name="GooglePlusCommando" version="2.2.0"
href="http://github.com/vimpr/vimperator-plugins/blob/master/google-plus-commando.js"
summary="The handy commands for Google+"
lang="en-US"
@@ -173,6 +173,7 @@ let g:gplus_commando_map_menu = "m"
function GPCError (msg) {
if (this instanceof GPCError) {
+ liberator.log('GPCError: ' + msg);
this.toString = function () String(msg);
} else {
return new GPCError(msg);
@@ -209,6 +210,73 @@ let g:gplus_commando_map_menu = "m"
const [S, X] = (function () {
+ function role (name, prefix)
+ ((prefix || '') + '[role="' + name + '"]');
+
+ function once (obj, name, fail) {
+ let func = obj[name];
+ Object.defineProperty(
+ obj,
+ name,
+ {
+ get: let (result) function () (result || (result = func()) || fail)
+ }
+ );
+ }
+
+ function onceAll (obj, fail) {
+ for (let [n, v] in I(obj)) {
+ if (n === 'role')
+ continue;
+ if (typeof v === 'function')
+ once(obj, n, fail);
+ if (typeof v === 'object') {
+ onceAll(v, fail);
+ }
+ }
+ }
+
+ let cssRules = {
+ items: function () {
+ if (content.location.host != 'plus.google.com')
+ return;
+
+ let result = [];
+ for (let [, sheet] in IA(content.document.styleSheets)) {
+ for (let [, rule] in IA(sheet.cssRules)) {
+ result.push(rule);
+ }
+ }
+ return result;
+ },
+
+ find: function (re) {
+ let result = [];
+ for (let [, rule] in I(this.items)) {
+ if (re.test(rule.cssText)) {
+ result.push(rule);
+ }
+ }
+
+ if (result.length < 1)
+ throw GPCError('Not fount css rule: ' + re);
+
+ if (result.length == 1)
+ return result[0].selectorText;
+
+ for (let [, rule] in I(result)) {
+ liberator.log(rule.cssText);
+ }
+
+ throw GPCError('Two and more rules are found');
+ },
+
+ finder: function (re) {
+ let self = this;
+ return function () self.find(re);
+ }
+ };
+
let selector = {
role: role,
typePlusone: '[g\\:entity^="buzz:"]',
@@ -226,13 +294,11 @@ let g:gplus_commando_map_menu = "m"
}
return res;
},
- unfold: [
- '.ns.yx',
- ],
+ unfold: cssRules.finder(/url\("\/\/ssl\.gstatic\.com\/s2\/oz\/images\/stream\/expand\.png"\)/),
menu: {
- mute: '.a-Y-k.a-Y-k-ye.d-V.Ki.Sl'
+ mute: '----'
},
- menuButton: role('button', '.d-k.Jt.Oi'),
+ menuButton: cssRules.finder(/url\("\/\/ssl\.gstatic\.com\/s2\/oz\/images\/stream\/options_default\.png"\).*margin-right: -44/),
cancel: role('button', '[id$=".cancel"]'),
submit: role('button', '[id$=".post"]'),
},
@@ -250,12 +316,15 @@ let g:gplus_commando_map_menu = "m"
},
notification: '#gbi1',
viewer: {
- root: '.AY',
- prev: '.Hq.DY.m4',
- next: '.Hq.DY.n4'
+ root: function () {
+ let n = Elements.doc.querySelector(S.viewer.next);
+ return n && getSelector(n.parentNode.parentNode);
+ },
+ prev: cssRules.finder(/url\("\/\/ssl\.gstatic\.com\/s2\/oz\/images\/left-arrow2\.png"\)/),
+ next: cssRules.finder(/url\("\/\/ssl\.gstatic\.com\/s2\/oz\/images\/right-arrow2\.png"\)/)
},
dialog: {
- root: '.va-Q',
+ root: cssRules.finder(/0pt 4px 16px rgba\(0, 0, 0, 0.2\).*z-index: 1101/)
},
frames: {
notifications: {
@@ -268,12 +337,12 @@ let g:gplus_commando_map_menu = "m"
},
entry: {
entries: 'div[id^=":2."]', // :2.diz13l....
- comment: role('button', '.jp.wx'),
- mute: role('button', '.c-j.Em.il.tm')
+ comment: cssRules.finder(/rgb\(221, 221, 221\).*rgb\(153, 153, 153\)/),
+ mute: 'div[id^=":2."] > div > div:nth-child(2) > div > div > ' + role('button', 'span') // FIXME
},
}
},
- closeButton: '.Fk.o4' // Viewer 等
+ closeButton: cssRules.finder(/url\("\/\/ssl\.gstatic\.com\/s2\/oz\/images\/lightbox-sprite2.gif"\).*0%.*0%/)
};
let xpath = {
@@ -286,36 +355,10 @@ let g:gplus_commando_map_menu = "m"
]
};
-
- function once (obj) {
- function _once (obj, name, func) {
- Object.defineProperty(
- obj,
- name,
- {
- get: let (result) function () (result || (result = func()))
- }
- );
- }
-
- for (let [n, v] in I(obj)) {
- if (n === 'role')
- continue;
- if (typeof v === 'function')
- _once(obj, n, v);
- if (typeof v === 'object')
- once(v);
- }
- }
-
- once(selector);
-
+ onceAll(selector, '.MEOW_MEOW_MEOW');
+ once(cssRules, 'items');
return [selector, xpath];
-
- function role (name, prefix)
- ((prefix || '') + '[role="' + name + '"]');
-
})();
// }}}
@@ -488,8 +531,8 @@ let g:gplus_commando_map_menu = "m"
for ([, e] in Iterator(A(root.querySelectorAll('a'))))
if (!e.getAttribute('oid'))
][0],
- get unfold () root.querySelector(S.currentEntry.unfold.join(', ')),
- get unfolds () A(root.querySelectorAll(S.currentEntry.unfold.join(', '))),
+ get unfold () root.querySelector(S.currentEntry.unfold),
+ get unfolds () A(root.querySelectorAll(S.currentEntry.unfold)),
get buttons () A(self.plusone.parentNode.querySelectorAll(S.role('button'))),
get commentButton () self.buttons[0],
get commentEditor () let (e = root.querySelector(S.editable)) (e && e.parentNode),
@@ -499,13 +542,7 @@ let g:gplus_commando_map_menu = "m"
menu: {
get root () root.querySelector(S.role('menu')),
get items () A(self.menu.root.querySelectorAll(S.role('menuitem'))),
- get mute () {
- // XXX 誤爆いやなので、チェックを入れる
- let item1 = self.menu.items.slice(-2)[0];
- let item2 = self.menu.root.querySelector(S.role('menuitem', S.currentEntry.menu.mute));
- if (item1 === item2)
- return item1;
- }
+ get mute () self.menu.items.slice(-2)[0]
},
get menuButton () root.querySelector(S.currentEntry.menuButton),
get cancel () root.querySelector(S.currentEntry.cancel),
@@ -561,7 +598,7 @@ let g:gplus_commando_map_menu = "m"
get back () root.contentDocument.querySelector(S.frames.notifications.summary.back),
get comment () self.entry.current.querySelector(S.frames.notifications.entry.comment),
get mute () self.entry.current.querySelector(S.frames.notifications.entry.mute),
- get unfold () root.contentDocument.querySelector(S.currentEntry.unfold.join(', '))
+ get unfold () root.contentDocument.querySelector(S.currentEntry.unfold)
}
};
return self;