overlay.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. // Utility function that allows modes to be combined. The mode given
  4. // as the base argument takes care of most of the normal mode
  5. // functionality, but a second (typically simple) mode is used, which
  6. // can override the style of text. Both modes get to parse all of the
  7. // text, but when both assign a non-null style to a piece of code, the
  8. // overlay wins, unless the combine argument was true and not overridden,
  9. // or state.overlay.combineTokens was true, in which case the styles are
  10. // combined.
  11. ;(function (mod) {
  12. if (typeof exports == 'object' && typeof module == 'object')
  13. // CommonJS
  14. mod(require('../../lib/codemirror'))
  15. else if (typeof define == 'function' && define.amd)
  16. // AMD
  17. define(['../../lib/codemirror'], mod)
  18. // Plain browser env
  19. else mod(CodeMirror)
  20. })(function (CodeMirror) {
  21. 'use strict'
  22. CodeMirror.overlayMode = function (base, overlay, combine) {
  23. return {
  24. startState: function () {
  25. return {
  26. base: CodeMirror.startState(base),
  27. overlay: CodeMirror.startState(overlay),
  28. basePos: 0,
  29. baseCur: null,
  30. overlayPos: 0,
  31. overlayCur: null,
  32. streamSeen: null,
  33. }
  34. },
  35. copyState: function (state) {
  36. return {
  37. base: CodeMirror.copyState(base, state.base),
  38. overlay: CodeMirror.copyState(overlay, state.overlay),
  39. basePos: state.basePos,
  40. baseCur: null,
  41. overlayPos: state.overlayPos,
  42. overlayCur: null,
  43. }
  44. },
  45. token: function (stream, state) {
  46. if (stream != state.streamSeen || Math.min(state.basePos, state.overlayPos) < stream.start) {
  47. state.streamSeen = stream
  48. state.basePos = state.overlayPos = stream.start
  49. }
  50. if (stream.start == state.basePos) {
  51. state.baseCur = base.token(stream, state.base)
  52. state.basePos = stream.pos
  53. }
  54. if (stream.start == state.overlayPos) {
  55. stream.pos = stream.start
  56. state.overlayCur = overlay.token(stream, state.overlay)
  57. state.overlayPos = stream.pos
  58. }
  59. stream.pos = Math.min(state.basePos, state.overlayPos)
  60. // state.overlay.combineTokens always takes precedence over combine,
  61. // unless set to null
  62. if (state.overlayCur == null) return state.baseCur
  63. else if ((state.baseCur != null && state.overlay.combineTokens) || (combine && state.overlay.combineTokens == null)) return state.baseCur + ' ' + state.overlayCur
  64. else return state.overlayCur
  65. },
  66. indent:
  67. base.indent &&
  68. function (state, textAfter, line) {
  69. return base.indent(state.base, textAfter, line)
  70. },
  71. electricChars: base.electricChars,
  72. innerMode: function (state) {
  73. return { state: state.base, mode: base }
  74. },
  75. blankLine: function (state) {
  76. var baseToken, overlayToken
  77. if (base.blankLine) baseToken = base.blankLine(state.base)
  78. if (overlay.blankLine) overlayToken = overlay.blankLine(state.overlay)
  79. return overlayToken == null ? baseToken : combine && baseToken != null ? baseToken + ' ' + overlayToken : overlayToken
  80. },
  81. }
  82. }
  83. })