doc.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // TODO: This file was created by bulk-decaffeinate.
  2. // Sanity-check the conversion and remove this comment.
  3. /*
  4. * decaffeinate suggestions:
  5. * DS102: Remove unnecessary code created because of implicit returns
  6. * DS207: Consider shorter variations of null checks
  7. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
  8. */
  9. app.models.Doc = class Doc extends app.Model {
  10. // Attributes: name, slug, type, version, release, db_size, mtime, links
  11. constructor() {
  12. super(...arguments);
  13. this.reset(this);
  14. this.slug_without_version = this.slug.split("~")[0];
  15. this.fullName = `${this.name}` + (this.version ? ` ${this.version}` : "");
  16. this.icon = this.slug_without_version;
  17. if (this.version) {
  18. this.short_version = this.version.split(" ")[0];
  19. }
  20. this.text = this.toEntry().text;
  21. }
  22. reset(data) {
  23. this.resetEntries(data.entries);
  24. this.resetTypes(data.types);
  25. }
  26. resetEntries(entries) {
  27. this.entries = new app.collections.Entries(entries);
  28. this.entries.each((entry) => {
  29. return (entry.doc = this);
  30. });
  31. }
  32. resetTypes(types) {
  33. this.types = new app.collections.Types(types);
  34. this.types.each((type) => {
  35. return (type.doc = this);
  36. });
  37. }
  38. fullPath(path) {
  39. if (path == null) {
  40. path = "";
  41. }
  42. if (path[0] !== "/") {
  43. path = `/${path}`;
  44. }
  45. return `/${this.slug}${path}`;
  46. }
  47. fileUrl(path) {
  48. return `${app.config.docs_origin}${this.fullPath(path)}?${this.mtime}`;
  49. }
  50. dbUrl() {
  51. return `${app.config.docs_origin}/${this.slug}/${app.config.db_filename}?${this.mtime}`;
  52. }
  53. indexUrl() {
  54. return `${app.indexHost()}/${this.slug}/${app.config.index_filename}?${
  55. this.mtime
  56. }`;
  57. }
  58. toEntry() {
  59. if (this.entry) {
  60. return this.entry;
  61. }
  62. this.entry = new app.models.Entry({
  63. doc: this,
  64. name: this.fullName,
  65. path: "index",
  66. });
  67. if (this.version) {
  68. this.entry.addAlias(this.name);
  69. }
  70. return this.entry;
  71. }
  72. findEntryByPathAndHash(path, hash) {
  73. let entry;
  74. if (hash && (entry = this.entries.findBy("path", `${path}#${hash}`))) {
  75. return entry;
  76. } else if (path === "index") {
  77. return this.toEntry();
  78. } else {
  79. return this.entries.findBy("path", path);
  80. }
  81. }
  82. load(onSuccess, onError, options) {
  83. if (options == null) {
  84. options = {};
  85. }
  86. if (options.readCache && this._loadFromCache(onSuccess)) {
  87. return;
  88. }
  89. const callback = (data) => {
  90. this.reset(data);
  91. onSuccess();
  92. if (options.writeCache) {
  93. this._setCache(data);
  94. }
  95. };
  96. return ajax({
  97. url: this.indexUrl(),
  98. success: callback,
  99. error: onError,
  100. });
  101. }
  102. clearCache() {
  103. app.localStorage.del(this.slug);
  104. }
  105. _loadFromCache(onSuccess) {
  106. let data;
  107. if (!(data = this._getCache())) {
  108. return;
  109. }
  110. const callback = () => {
  111. this.reset(data);
  112. onSuccess();
  113. };
  114. setTimeout(callback, 0);
  115. return true;
  116. }
  117. _getCache() {
  118. let data;
  119. if (!(data = app.localStorage.get(this.slug))) {
  120. return;
  121. }
  122. if (data[0] === this.mtime) {
  123. return data[1];
  124. } else {
  125. this.clearCache();
  126. return;
  127. }
  128. }
  129. _setCache(data) {
  130. app.localStorage.set(this.slug, [this.mtime, data]);
  131. }
  132. install(onSuccess, onError, onProgress) {
  133. if (this.installing) {
  134. return;
  135. }
  136. this.installing = true;
  137. const error = () => {
  138. this.installing = null;
  139. onError();
  140. };
  141. const success = (data) => {
  142. this.installing = null;
  143. app.db.store(this, data, onSuccess, error);
  144. };
  145. ajax({
  146. url: this.dbUrl(),
  147. success,
  148. error,
  149. progress: onProgress,
  150. timeout: 3600,
  151. });
  152. }
  153. uninstall(onSuccess, onError) {
  154. if (this.installing) {
  155. return;
  156. }
  157. this.installing = true;
  158. const success = () => {
  159. this.installing = null;
  160. onSuccess();
  161. };
  162. const error = () => {
  163. this.installing = null;
  164. onError();
  165. };
  166. app.db.unstore(this, success, error);
  167. }
  168. getInstallStatus(callback) {
  169. app.db.version(this, (value) =>
  170. callback({ installed: !!value, mtime: value }),
  171. );
  172. }
  173. isOutdated(status) {
  174. if (!status) {
  175. return false;
  176. }
  177. const isInstalled = status.installed || app.settings.get("autoInstall");
  178. return isInstalled && this.mtime !== status.mtime;
  179. }
  180. };