usercss-helper.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /* global usercss saveStyle getStyles chromeLocal */
  2. 'use strict';
  3. // eslint-disable-next-line no-var
  4. var usercssHelper = (() => {
  5. function buildMeta(style) {
  6. if (style.usercssData) {
  7. return Promise.resolve(style);
  8. }
  9. try {
  10. const {sourceCode} = style;
  11. // allow sourceCode to be normalized
  12. delete style.sourceCode;
  13. return Promise.resolve(Object.assign(usercss.buildMeta(sourceCode), style));
  14. } catch (e) {
  15. return Promise.reject(e);
  16. }
  17. }
  18. function buildCode(style) {
  19. return usercss.buildCode(style);
  20. }
  21. function wrapReject(pending) {
  22. return pending
  23. .catch(err => new Error(Array.isArray(err) ? err.join('\n') : err.message || String(err)));
  24. }
  25. // Parse the source and find the duplication
  26. function build({sourceCode, checkDup = false}, noReject) {
  27. const pending = buildMeta({sourceCode})
  28. .then(style => Promise.all([
  29. buildCode(style),
  30. checkDup && findDup(style)
  31. ]))
  32. .then(([style, dup]) => ({style, dup}));
  33. return noReject ? wrapReject(pending) : pending;
  34. }
  35. function save(style, noReject) {
  36. const pending = buildMeta(style)
  37. .then(assignVars)
  38. .then(buildCode)
  39. .then(saveStyle);
  40. return noReject ? wrapReject(pending) : pending;
  41. function assignVars(style) {
  42. if (style.reason === 'config' && style.id) {
  43. return style;
  44. }
  45. return findDup(style).then(dup => {
  46. if (dup) {
  47. style.id = dup.id;
  48. if (style.reason !== 'config') {
  49. // preserve style.vars during update
  50. usercss.assignVars(style, dup);
  51. }
  52. }
  53. return style;
  54. });
  55. }
  56. }
  57. function findDup(style) {
  58. if (style.id) {
  59. return getStyles({id: style.id}).then(s => s[0]);
  60. }
  61. return getStyles().then(styles =>
  62. styles.find(target => {
  63. if (!target.usercssData) {
  64. return false;
  65. }
  66. return target.usercssData.name === style.usercssData.name &&
  67. target.usercssData.namespace === style.usercssData.namespace;
  68. })
  69. );
  70. }
  71. function openInstallPage(tab, {url = tab.url, direct} = {}) {
  72. if (direct) {
  73. prefetchCodeForInstallation(tab.id, url);
  74. }
  75. return wrapReject(openURL({
  76. url: '/install-usercss.html' +
  77. '?updateUrl=' + encodeURIComponent(url) +
  78. '&tabId=' + tab.id +
  79. (direct ? '&direct=yes' : ''),
  80. index: tab.index + 1,
  81. openerTabId: tab.id,
  82. }));
  83. }
  84. function prefetchCodeForInstallation(tabId, url) {
  85. const key = 'tempUsercssCode' + tabId;
  86. Promise.all([
  87. download(url),
  88. chromeLocal.setValue(key, {loading: true}),
  89. ]).then(([code]) => {
  90. chromeLocal.setValue(key, code);
  91. setTimeout(() => chromeLocal.remove(key), 60e3);
  92. });
  93. }
  94. return {build, save, findDup, openInstallPage};
  95. })();