qml.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. Language: QML
  3. Requires: javascript.js, xml.js
  4. Author: John Foster <jfoster@esri.com>
  5. Description: Syntax highlighting for the Qt Quick QML scripting language, based mostly off
  6. the JavaScript parser.
  7. Website: https://doc.qt.io/qt-5/qmlapplications.html
  8. Category: scripting
  9. */
  10. function qml(hljs) {
  11. const regex = hljs.regex;
  12. const KEYWORDS = {
  13. keyword:
  14. 'in of on if for while finally var new function do return void else break catch '
  15. + 'instanceof with throw case default try this switch continue typeof delete '
  16. + 'let yield const export super debugger as async await import',
  17. literal:
  18. 'true false null undefined NaN Infinity',
  19. built_in:
  20. 'eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent '
  21. + 'encodeURI encodeURIComponent escape unescape Object Function Boolean Error '
  22. + 'EvalError InternalError RangeError ReferenceError StopIteration SyntaxError '
  23. + 'TypeError URIError Number Math Date String RegExp Array Float32Array '
  24. + 'Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array '
  25. + 'Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require '
  26. + 'module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect '
  27. + 'Behavior bool color coordinate date double enumeration font geocircle georectangle '
  28. + 'geoshape int list matrix4x4 parent point quaternion real rect '
  29. + 'size string url variant vector2d vector3d vector4d '
  30. + 'Promise'
  31. };
  32. const QML_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9\\._]*';
  33. // Isolate property statements. Ends at a :, =, ;, ,, a comment or end of line.
  34. // Use property class.
  35. const PROPERTY = {
  36. className: 'keyword',
  37. begin: '\\bproperty\\b',
  38. starts: {
  39. className: 'string',
  40. end: '(:|=|;|,|//|/\\*|$)',
  41. returnEnd: true
  42. }
  43. };
  44. // Isolate signal statements. Ends at a ) a comment or end of line.
  45. // Use property class.
  46. const SIGNAL = {
  47. className: 'keyword',
  48. begin: '\\bsignal\\b',
  49. starts: {
  50. className: 'string',
  51. end: '(\\(|:|=|;|,|//|/\\*|$)',
  52. returnEnd: true
  53. }
  54. };
  55. // id: is special in QML. When we see id: we want to mark the id: as attribute and
  56. // emphasize the token following.
  57. const ID_ID = {
  58. className: 'attribute',
  59. begin: '\\bid\\s*:',
  60. starts: {
  61. className: 'string',
  62. end: QML_IDENT_RE,
  63. returnEnd: false
  64. }
  65. };
  66. // Find QML object attribute. An attribute is a QML identifier followed by :.
  67. // Unfortunately it's hard to know where it ends, as it may contain scalars,
  68. // objects, object definitions, or javascript. The true end is either when the parent
  69. // ends or the next attribute is detected.
  70. const QML_ATTRIBUTE = {
  71. begin: QML_IDENT_RE + '\\s*:',
  72. returnBegin: true,
  73. contains: [
  74. {
  75. className: 'attribute',
  76. begin: QML_IDENT_RE,
  77. end: '\\s*:',
  78. excludeEnd: true,
  79. relevance: 0
  80. }
  81. ],
  82. relevance: 0
  83. };
  84. // Find QML object. A QML object is a QML identifier followed by { and ends at the matching }.
  85. // All we really care about is finding IDENT followed by { and just mark up the IDENT and ignore the {.
  86. const QML_OBJECT = {
  87. begin: regex.concat(QML_IDENT_RE, /\s*\{/),
  88. end: /\{/,
  89. returnBegin: true,
  90. relevance: 0,
  91. contains: [ hljs.inherit(hljs.TITLE_MODE, { begin: QML_IDENT_RE }) ]
  92. };
  93. return {
  94. name: 'QML',
  95. aliases: [ 'qt' ],
  96. case_insensitive: false,
  97. keywords: KEYWORDS,
  98. contains: [
  99. {
  100. className: 'meta',
  101. begin: /^\s*['"]use (strict|asm)['"]/
  102. },
  103. hljs.APOS_STRING_MODE,
  104. hljs.QUOTE_STRING_MODE,
  105. { // template string
  106. className: 'string',
  107. begin: '`',
  108. end: '`',
  109. contains: [
  110. hljs.BACKSLASH_ESCAPE,
  111. {
  112. className: 'subst',
  113. begin: '\\$\\{',
  114. end: '\\}'
  115. }
  116. ]
  117. },
  118. hljs.C_LINE_COMMENT_MODE,
  119. hljs.C_BLOCK_COMMENT_MODE,
  120. {
  121. className: 'number',
  122. variants: [
  123. { begin: '\\b(0[bB][01]+)' },
  124. { begin: '\\b(0[oO][0-7]+)' },
  125. { begin: hljs.C_NUMBER_RE }
  126. ],
  127. relevance: 0
  128. },
  129. { // "value" container
  130. begin: '(' + hljs.RE_STARTERS_RE + '|\\b(case|return|throw)\\b)\\s*',
  131. keywords: 'return throw case',
  132. contains: [
  133. hljs.C_LINE_COMMENT_MODE,
  134. hljs.C_BLOCK_COMMENT_MODE,
  135. hljs.REGEXP_MODE,
  136. { // E4X / JSX
  137. begin: /</,
  138. end: />\s*[);\]]/,
  139. relevance: 0,
  140. subLanguage: 'xml'
  141. }
  142. ],
  143. relevance: 0
  144. },
  145. SIGNAL,
  146. PROPERTY,
  147. {
  148. className: 'function',
  149. beginKeywords: 'function',
  150. end: /\{/,
  151. excludeEnd: true,
  152. contains: [
  153. hljs.inherit(hljs.TITLE_MODE, { begin: /[A-Za-z$_][0-9A-Za-z$_]*/ }),
  154. {
  155. className: 'params',
  156. begin: /\(/,
  157. end: /\)/,
  158. excludeBegin: true,
  159. excludeEnd: true,
  160. contains: [
  161. hljs.C_LINE_COMMENT_MODE,
  162. hljs.C_BLOCK_COMMENT_MODE
  163. ]
  164. }
  165. ],
  166. illegal: /\[|%/
  167. },
  168. {
  169. // hack: prevents detection of keywords after dots
  170. begin: '\\.' + hljs.IDENT_RE,
  171. relevance: 0
  172. },
  173. ID_ID,
  174. QML_ATTRIBUTE,
  175. QML_OBJECT
  176. ],
  177. illegal: /#/
  178. };
  179. }
  180. export { qml as default };