123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- // CodeMirror, copyright (c) by Marijn Haverbeke and others
- // Distributed under an MIT license: https://codemirror.net/LICENSE
- ;(function (mod) {
- if (typeof exports == 'object' && typeof module == 'object')
- // CommonJS
- mod(require('../../lib/codemirror'), require('../xml/xml'), require('../javascript/javascript'), require('../css/css'))
- else if (typeof define == 'function' && define.amd)
- // AMD
- define(['../../lib/codemirror', '../xml/xml', '../javascript/javascript', '../css/css'], mod)
- // Plain browser env
- else mod(CodeMirror)
- })(function (CodeMirror) {
- 'use strict'
- var defaultTags = {
- script: [
- ['lang', /(javascript|babel)/i, 'javascript'],
- ['type', /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i, 'javascript'],
- ['type', /./, 'text/plain'],
- [null, null, 'javascript'],
- ],
- style: [
- ['lang', /^css$/i, 'css'],
- ['type', /^(text\/)?(x-)?(stylesheet|css)$/i, 'css'],
- ['type', /./, 'text/plain'],
- [null, null, 'css'],
- ],
- }
- function maybeBackup(stream, pat, style) {
- var cur = stream.current(),
- close = cur.search(pat)
- if (close > -1) {
- stream.backUp(cur.length - close)
- } else if (cur.match(/<\/?$/)) {
- stream.backUp(cur.length)
- if (!stream.match(pat, false)) stream.match(cur)
- }
- return style
- }
- var attrRegexpCache = {}
- function getAttrRegexp(attr) {
- var regexp = attrRegexpCache[attr]
- if (regexp) return regexp
- return (attrRegexpCache[attr] = new RegExp('\\s+' + attr + '\\s*=\\s*(\'|")?([^\'"]+)(\'|")?\\s*'))
- }
- function getAttrValue(text, attr) {
- var match = text.match(getAttrRegexp(attr))
- return match ? /^\s*(.*?)\s*$/.exec(match[2])[1] : ''
- }
- function getTagRegexp(tagName, anchored) {
- return new RegExp((anchored ? '^' : '') + '</\\s*' + tagName + '\\s*>', 'i')
- }
- function addTags(from, to) {
- for (var tag in from) {
- var dest = to[tag] || (to[tag] = [])
- var source = from[tag]
- for (var i = source.length - 1; i >= 0; i--) dest.unshift(source[i])
- }
- }
- function findMatchingMode(tagInfo, tagText) {
- for (var i = 0; i < tagInfo.length; i++) {
- var spec = tagInfo[i]
- if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2]
- }
- }
- CodeMirror.defineMode(
- 'htmlmixed',
- function (config, parserConfig) {
- var htmlMode = CodeMirror.getMode(config, {
- name: 'xml',
- htmlMode: true,
- multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
- multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag,
- allowMissingTagName: parserConfig.allowMissingTagName,
- })
- var tags = {}
- var configTags = parserConfig && parserConfig.tags,
- configScript = parserConfig && parserConfig.scriptTypes
- addTags(defaultTags, tags)
- if (configTags) addTags(configTags, tags)
- if (configScript) for (var i = configScript.length - 1; i >= 0; i--) tags.script.unshift(['type', configScript[i].matches, configScript[i].mode])
- function html(stream, state) {
- var style = htmlMode.token(stream, state.htmlState),
- tag = /\btag\b/.test(style),
- tagName
- if (tag && !/[<>\s\/]/.test(stream.current()) && (tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) && tags.hasOwnProperty(tagName)) {
- state.inTag = tagName + ' '
- } else if (state.inTag && tag && />$/.test(stream.current())) {
- var inTag = /^([\S]+) (.*)/.exec(state.inTag)
- state.inTag = null
- var modeSpec = stream.current() == '>' && findMatchingMode(tags[inTag[1]], inTag[2])
- var mode = CodeMirror.getMode(config, modeSpec)
- var endTagA = getTagRegexp(inTag[1], true),
- endTag = getTagRegexp(inTag[1], false)
- state.token = function (stream, state) {
- if (stream.match(endTagA, false)) {
- state.token = html
- state.localState = state.localMode = null
- return null
- }
- return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState))
- }
- state.localMode = mode
- state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, '', ''))
- } else if (state.inTag) {
- state.inTag += stream.current()
- if (stream.eol()) state.inTag += ' '
- }
- return style
- }
- return {
- startState: function () {
- var state = CodeMirror.startState(htmlMode)
- return { token: html, inTag: null, localMode: null, localState: null, htmlState: state }
- },
- copyState: function (state) {
- var local
- if (state.localState) {
- local = CodeMirror.copyState(state.localMode, state.localState)
- }
- return { token: state.token, inTag: state.inTag, localMode: state.localMode, localState: local, htmlState: CodeMirror.copyState(htmlMode, state.htmlState) }
- },
- token: function (stream, state) {
- return state.token(stream, state)
- },
- indent: function (state, textAfter, line) {
- if (!state.localMode || /^\s*<\//.test(textAfter)) return htmlMode.indent(state.htmlState, textAfter, line)
- else if (state.localMode.indent) return state.localMode.indent(state.localState, textAfter, line)
- else return CodeMirror.Pass
- },
- innerMode: function (state) {
- return { state: state.localState || state.htmlState, mode: state.localMode || htmlMode }
- },
- }
- },
- 'xml',
- 'javascript',
- 'css'
- )
- CodeMirror.defineMIME('text/html', 'htmlmixed')
- })
|