token_store.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*!
  2. * lunr.stemmer
  3. * Copyright (C) @YEAR Oliver Nightingale
  4. * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt
  5. */
  6. /**
  7. * lunr.TokenStore is used for efficient storing and lookup of the reverse
  8. * index of token to document ref.
  9. *
  10. * @constructor
  11. */
  12. lunr.TokenStore = function () {
  13. this.root = { docs: {} }
  14. this.length = 0
  15. }
  16. /**
  17. * Loads a previously serialised token store
  18. *
  19. * @param {Object} serialisedData The serialised token store to load.
  20. * @returns {lunr.TokenStore}
  21. * @memberOf TokenStore
  22. */
  23. lunr.TokenStore.load = function (serialisedData) {
  24. var store = new this
  25. store.root = serialisedData.root
  26. store.length = serialisedData.length
  27. return store
  28. }
  29. /**
  30. * Adds a new token doc pair to the store.
  31. *
  32. * By default this function starts at the root of the current store, however
  33. * it can start at any node of any token store if required.
  34. *
  35. * @param {String} token The token to store the doc under
  36. * @param {Object} doc The doc to store against the token
  37. * @param {Object} root An optional node at which to start looking for the
  38. * correct place to enter the doc, by default the root of this lunr.TokenStore
  39. * is used.
  40. * @memberOf TokenStore
  41. */
  42. lunr.TokenStore.prototype.add = function (token, doc, root) {
  43. var root = root || this.root,
  44. key = token.charAt(0),
  45. rest = token.slice(1)
  46. if (!(key in root)) root[key] = {docs: {}}
  47. if (rest.length === 0) {
  48. root[key].docs[doc.ref] = doc
  49. this.length += 1
  50. return
  51. } else {
  52. return this.add(rest, doc, root[key])
  53. }
  54. }
  55. /**
  56. * Checks whether this key is contained within this lunr.TokenStore.
  57. *
  58. * By default this function starts at the root of the current store, however
  59. * it can start at any node of any token store if required.
  60. *
  61. * @param {String} token The token to check for
  62. * @param {Object} root An optional node at which to start
  63. * @memberOf TokenStore
  64. */
  65. lunr.TokenStore.prototype.has = function (token) {
  66. if (!token) return false
  67. var node = this.root
  68. for (var i = 0; i < token.length; i++) {
  69. if (!node[token.charAt(i)]) return false
  70. node = node[token.charAt(i)]
  71. }
  72. return true
  73. }
  74. /**
  75. * Retrieve a node from the token store for a given token.
  76. *
  77. * By default this function starts at the root of the current store, however
  78. * it can start at any node of any token store if required.
  79. *
  80. * @param {String} token The token to get the node for.
  81. * @param {Object} root An optional node at which to start.
  82. * @returns {Object}
  83. * @see TokenStore.prototype.get
  84. * @memberOf TokenStore
  85. */
  86. lunr.TokenStore.prototype.getNode = function (token) {
  87. if (!token) return {}
  88. var node = this.root
  89. for (var i = 0; i < token.length; i++) {
  90. if (!node[token.charAt(i)]) return {}
  91. node = node[token.charAt(i)]
  92. }
  93. return node
  94. }
  95. /**
  96. * Retrieve the documents for a node for the given token.
  97. *
  98. * By default this function starts at the root of the current store, however
  99. * it can start at any node of any token store if required.
  100. *
  101. * @param {String} token The token to get the documents for.
  102. * @param {Object} root An optional node at which to start.
  103. * @returns {Object}
  104. * @memberOf TokenStore
  105. */
  106. lunr.TokenStore.prototype.get = function (token, root) {
  107. return this.getNode(token, root).docs || {}
  108. }
  109. lunr.TokenStore.prototype.count = function (token, root) {
  110. return Object.keys(this.get(token, root)).length
  111. }
  112. /**
  113. * Remove the document identified by ref from the token in the store.
  114. *
  115. * By default this function starts at the root of the current store, however
  116. * it can start at any node of any token store if required.
  117. *
  118. * @param {String} token The token to get the documents for.
  119. * @param {String} ref The ref of the document to remove from this token.
  120. * @param {Object} root An optional node at which to start.
  121. * @returns {Object}
  122. * @memberOf TokenStore
  123. */
  124. lunr.TokenStore.prototype.remove = function (token, ref) {
  125. if (!token) return
  126. var node = this.root
  127. for (var i = 0; i < token.length; i++) {
  128. if (!(token.charAt(i) in node)) return
  129. node = node[token.charAt(i)]
  130. }
  131. delete node.docs[ref]
  132. }
  133. /**
  134. * Find all the possible suffixes of the passed token using tokens
  135. * currently in the store.
  136. *
  137. * @param {String} token The token to expand.
  138. * @returns {Array}
  139. * @memberOf TokenStore
  140. */
  141. lunr.TokenStore.prototype.expand = function (token, memo) {
  142. var root = this.getNode(token),
  143. docs = root.docs || {},
  144. memo = memo || []
  145. if (Object.keys(docs).length) memo.push(token)
  146. Object.keys(root)
  147. .forEach(function (key) {
  148. if (key === 'docs') return
  149. memo.concat(this.expand(token + key, memo))
  150. }, this)
  151. return memo
  152. }
  153. /**
  154. * Returns a representation of the token store ready for serialisation.
  155. *
  156. * @returns {Object}
  157. * @memberOf TokenStore
  158. */
  159. lunr.TokenStore.prototype.toJSON = function () {
  160. return {
  161. root: this.root,
  162. length: this.length
  163. }
  164. }