Greasy Fork is available in English.

annotation-board

allow you to add annotation after selected content and copy to clipboard and save to local server

  1. // ==UserScript==
  2. // @name annotation-board
  3. // @name:zh-CN 注释墙
  4. // @description allow you to add annotation after selected content and copy to clipboard and save to local server
  5. // @description:zh-CN 选中内容后添加注释并复制到剪贴板, 同时在本地的服务其中新建一个副本, 参见 https://github.com/ezirmusitua/snippet-board
  6. // @version 0.2.0
  7. // @author jferroal
  8. // @license GPL-3.0
  9. // @require https://greasyfork.org/scripts/31793-jmul/code/JMUL.js?version=209567
  10. // @include http://*
  11. // @include https://*
  12. // @grant GM_xmlhttpRequest
  13. // @run-at document-start
  14. // @namespace https://greasyfork.org/users/34556
  15. // ==/UserScript==
  16.  
  17. (function e (t, n, r) { function s (o, u) { if (!n[o]) { if (!t[o]) { var a = typeof require === 'function' && require; if (!u && a) return a(o, !0); if (i) return i(o, !0); var f = new Error("Cannot find module '" + o + "'"); throw f.code = 'MODULE_NOT_FOUND', f } var l = n[o] = { exports: {} }; t[o][0].call(l.exports, function (e) { var n = t[o][1][e]; return s(n || e) }, l, l.exports, e, t, n, r) } return n[o].exports } var i = typeof require === 'function' && require; for (var o = 0; o < r.length; o++)s(r[o]); return s })({ 1: [function (require, module, exports) {
  18. const elements = require('./element');
  19. const request = require('./snippet.service');
  20.  
  21. class AnnotationBoard {
  22. constructor () {
  23. this.request = request;
  24. this.container = new elements.Container();
  25. this.textarea = new elements.Textarea();
  26. this.saveBtn = new elements.Button();
  27. this.saveBtn.listenClick(() => {
  28. this.textarea.copyToClipboard();
  29. this.request.save({
  30. link: window.location.href,
  31. raw_content: this.textarea.value,
  32. });
  33. this.hide();
  34. });
  35. this.container.appendChild([this.textarea, this.saveBtn]);
  36. this.container.element.appendTo(document.body);
  37. this.isShowing = false;
  38. }
  39.  
  40. show () {
  41. this.textarea.appendSelection();
  42. this.container.show();
  43. this.isShowing = true;
  44. }
  45.  
  46. shouldShow () {
  47. const isEmptySelection = !!this.textarea.element.getSelection();
  48. return !this.isShowing && isEmptySelection;
  49. }
  50.  
  51. hide () {
  52. this.isShowing = false;
  53. this.container.hide('display', 'none');
  54. }
  55.  
  56. shouldHide (event) {
  57. const target = event && event.target;
  58. if (!target && this.isShowing) {
  59. return true;
  60. } else {
  61. const inContainer = elements.Container.isContainer(target.id);
  62. const inTextarea = elements.Textarea.isTextarea(target.id);
  63. const inButton = elements.Button.isButton(target.id);
  64. return !inContainer && !inTextarea && !inButton && this.isShowing;
  65. }
  66. }
  67. }
  68.  
  69. module.exports = AnnotationBoard;
  70. }, { './element': 2, './snippet.service': 4 }],
  71. 2: [function (require, module, exports) {
  72. const JMUL = window.JMUL || {};
  73.  
  74. const AnnotationBoardId = {
  75. CONTAINER: 'annotation-container',
  76. TEXTAREA: 'annotation-textarea',
  77. BUTTON: 'annotation-button',
  78. };
  79.  
  80. class BoardContainer {
  81. constructor () {
  82. this.element = new JMUL.Element('div');
  83. this.element.setId(AnnotationBoardId.CONTAINER);
  84. BoardContainer._initCss(this.element)
  85. }
  86.  
  87. appendChild (children) {
  88. children.forEach((c) => {
  89. try {
  90. this.element.appendChild(c.element)
  91. } catch (er) {
  92. console.log(er);
  93. }
  94. });
  95. }
  96.  
  97. show () {
  98. try {
  99. const pos = JMUL.Element.getSelectedPosition();
  100. this.element.setCss({
  101. display: 'flex',
  102. flexDirection: 'column',
  103. left: pos.x,
  104. top: pos.y,
  105. });
  106. } catch (err) {
  107. console.error(err);
  108. }
  109. }
  110.  
  111. hide () {
  112. this.element.setCss({
  113. display: 'none',
  114. });
  115. }
  116.  
  117. static isContainer (id) {
  118. return AnnotationBoardId.CONTAINER === id;
  119. }
  120.  
  121. static _initCss (elem) {
  122. elem.setCss({
  123. display: 'none',
  124. fontFamily: 'Noto',
  125. border: '4px',
  126. boxShadow: '0px 3px 8px 1px rgba(0, 0, 0, 0.26)',
  127. position: 'absolute',
  128. backgroundColor: 'rgba(0, 0, 0, 0.56)',
  129. padding: '16px 4px 8px 4px',
  130. });
  131. }
  132. }
  133.  
  134. class BoardEdit {
  135. constructor () {
  136. this.element = JMUL.Decorator.selectable(new JMUL.Element('textarea'));
  137. this.element.setId(AnnotationBoardId.TEXTAREA);
  138. BoardEdit._initCss(this.element);
  139. }
  140.  
  141. appendSelection () {
  142. const prevVal = this.element.value();
  143. const selectedText = this.element.getSelection();
  144. const newVal = (!!prevVal && (prevVal + '\n') || '') + '========' + '\n' + selectedText + '\n';
  145. this.element.setValue(newVal)
  146. }
  147.  
  148. hide () {
  149. this.element.setStyle('display', 'none');
  150. }
  151.  
  152. copyToClipboard () {
  153. this.element.copyToClipboard();
  154. }
  155.  
  156. get value () {
  157. return this.element.value();
  158. }
  159.  
  160. static isTextarea (id) {
  161. return AnnotationBoardId.TEXTAREA === id;
  162. }
  163.  
  164. static _initCss (elem) {
  165. elem.setCss({
  166. fontFamily: 'Noto',
  167. width: '240px',
  168. height: '128px',
  169. backgroundColor: 'rgba(255, 255, 255, 0.87)',
  170. marginBottom: '8px',
  171. borderRadius: '4px',
  172. color: 'rgba(0, 0, 0, 0.76)',
  173. fontSize: '12px',
  174. });
  175. }
  176. }
  177.  
  178. class BoardButton {
  179. constructor () {
  180. this.element = new JMUL.Element('button');
  181. this.element.setId(AnnotationBoardId.BUTTON);
  182. this.element.setInnerHTML('复制到剪贴板');
  183. BoardButton._initCss(this.element);
  184. }
  185.  
  186. listenClick (fn) {
  187. this.element.listen('click', (e) => fn());
  188. }
  189.  
  190. static isButton (id) {
  191. return AnnotationBoardId.BUTTON === id;
  192. }
  193.  
  194. static _initCss (elem) {
  195. elem.setCss({
  196. fontFamily: 'Noto',
  197. border: 'none',
  198. borderRadius: '4px',
  199. height: '24px',
  200. backgroundColor: 'rgba(255, 255, 255, 0.87)',
  201. color: 'rgba(0, 0, 0, 0.76)',
  202. fontSize: '14px',
  203. });
  204. }
  205. }
  206.  
  207. module.exports = {
  208. Container: BoardContainer,
  209. Textarea: BoardEdit,
  210. Button: BoardButton,
  211. };
  212. }, {}],
  213. 3: [function (require, module, exports) {
  214. const AnnotationBoard = require('./annotation-board');
  215.  
  216. (function () {
  217. const annotationBoard = new AnnotationBoard();
  218. bindEvent();
  219. function bindEvent () {
  220. window.addEventListener('mouseup', (event) => {
  221. handleMouseUp(event);
  222. }, false);
  223. }
  224.  
  225. function handleMouseUp (event) {
  226. if (annotationBoard.shouldShow()) {
  227. annotationBoard.show();
  228. } else if (annotationBoard.shouldHide(event)) {
  229. annotationBoard.hide();
  230. }
  231. }
  232. })();
  233. }, { './annotation-board': 1 }],
  234. 4: [function (require, module, exports) {
  235. const JMUL = window.JMUL || {};
  236.  
  237. class SnippetService {
  238. constructor (host = 'http://127.0.0.1', port = 5000, _options = {}) {
  239. if (!SnippetService.instance) {
  240. this.host = host;
  241. this.port = port;
  242. this.options = _options;
  243. if (!this.options.headers) {
  244. this.options.headers = { 'Content-Type': 'application/json' };
  245. }
  246. SnippetService.instance = this;
  247. }
  248. return SnippetService.instance;
  249. }
  250.  
  251. save (data) {
  252. const request = new JMUL.Request(this.options);
  253. request.setMethod('POST');
  254. request.setUrl(this.host + ':' + this.port.toString() + '/snippet/api/v0.1.0');
  255. request.setData(data);
  256. request.send();
  257. }
  258. }
  259.  
  260. SnippetService.instance = undefined;
  261.  
  262. module.exports = new SnippetService();
  263. }, {}] }, {}, [3]);