script.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. export { isRemote } from 'src/common';
  2. const metaStart = '==UserScript==';
  3. const metaEnd = '==/UserScript==';
  4. export function isUserScript(text) {
  5. if (/^\s*</.test(text)) return false; // HTML
  6. if (text.indexOf(metaStart) < 0) return false; // Lack of meta block
  7. return true;
  8. }
  9. export function parseMeta(code) {
  10. // initialize meta, specify those with multiple values allowed
  11. const meta = {
  12. include: [],
  13. exclude: [],
  14. match: [],
  15. excludeMatch: [],
  16. require: [],
  17. resource: [],
  18. grant: [],
  19. };
  20. let flag = -1;
  21. code.replace(/(?:^|\n)\/\/\s*([@=]\S+)(.*)/g, (_match, group1, group2) => {
  22. if (flag < 0 && group1 === metaStart) {
  23. // start meta
  24. flag = 1;
  25. } else if (flag > 0 && group1 === metaEnd) {
  26. // end meta
  27. flag = 0;
  28. }
  29. if (flag === 1 && group1[0] === '@') {
  30. const [keyName, locale] = group1.slice(1).split(':');
  31. const camelKey = keyName.replace(/[-_](\w)/g, (m, g) => g.toUpperCase());
  32. const key = locale ? `${camelKey}:${locale.toLowerCase()}` : camelKey;
  33. const val = group2.trim();
  34. const data = meta[key];
  35. // multiple values allowed
  36. if (data && data.push) data.push(val);
  37. // only first value will be stored
  38. else if (!(key in meta)) meta[key] = val;
  39. }
  40. });
  41. meta.resources = {};
  42. meta.resource.forEach(line => {
  43. const pair = line.match(/^(\w\S*)\s+(.*)/);
  44. if (pair) meta.resources[pair[1]] = pair[2];
  45. });
  46. delete meta.resource;
  47. // @homepageURL: compatible with @homepage
  48. if (!meta.homepageURL && meta.homepage) meta.homepageURL = meta.homepage;
  49. return meta;
  50. }
  51. export function newScript() {
  52. const script = {
  53. custom: {
  54. origInclude: true,
  55. origExclude: true,
  56. origMatch: true,
  57. origExcludeMatch: true,
  58. },
  59. enabled: 1,
  60. update: 1,
  61. code: `\
  62. // ==UserScript==
  63. // @name New Script
  64. // @namespace Violentmonkey Scripts
  65. // @match *://*/*
  66. // @grant none
  67. // ==/UserScript==
  68. `,
  69. };
  70. script.meta = parseMeta(script.code);
  71. return script;
  72. }
  73. export function getScriptInfo(script) {
  74. return {
  75. id: script.id,
  76. custom: script.custom,
  77. meta: script.meta,
  78. enabled: script.enabled,
  79. update: script.update,
  80. };
  81. }
  82. export function getNameURI(script) {
  83. const ns = script.meta.namespace || '';
  84. const name = script.meta.name || '';
  85. let nameURI = `${escape(ns)}:${escape(name)}:`;
  86. if (!ns && !name) nameURI += script.id || '';
  87. return nameURI;
  88. }
  89. export function compareVersion(ver1, ver2) {
  90. const parts1 = (ver1 || '').split('.');
  91. const parts2 = (ver2 || '').split('.');
  92. for (let i = 0; i < parts1.length || i < parts2.length; i += 1) {
  93. const delta = (parseInt(parts1[i], 10) || 0) - (parseInt(parts2[i], 10) || 0);
  94. if (delta) return delta < 0 ? -1 : 1;
  95. }
  96. return 0;
  97. }