summaryrefslogtreecommitdiff
path: root/elpa/web-mode-20220319.653
diff options
context:
space:
mode:
authormattkae <mattkae@protonmail.com>2022-06-07 08:21:30 -0400
committermattkae <mattkae@protonmail.com>2022-06-07 08:21:30 -0400
commitb07628dddf418d4f47b858e6c35fd3520fbaeed2 (patch)
tree376cd7b4b5daed06ac397ac23ae041e4b365ad08 /elpa/web-mode-20220319.653
parentbecff06c71d277647eda4378203d03ab36e141eb (diff)
Flycheck mode and typescript
Diffstat (limited to 'elpa/web-mode-20220319.653')
-rw-r--r--elpa/web-mode-20220319.653/web-mode-autoloads.el27
-rw-r--r--elpa/web-mode-20220319.653/web-mode-pkg.el2
-rw-r--r--elpa/web-mode-20220319.653/web-mode.el14434
-rw-r--r--elpa/web-mode-20220319.653/web-mode.elcbin0 -> 342991 bytes
4 files changed, 14463 insertions, 0 deletions
diff --git a/elpa/web-mode-20220319.653/web-mode-autoloads.el b/elpa/web-mode-20220319.653/web-mode-autoloads.el
new file mode 100644
index 0000000..e03ab05
--- /dev/null
+++ b/elpa/web-mode-20220319.653/web-mode-autoloads.el
@@ -0,0 +1,27 @@
+;;; web-mode-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*-
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+
+;;;### (autoloads nil "web-mode" "web-mode.el" (0 0 0 0))
+;;; Generated autoloads from web-mode.el
+
+(autoload 'web-mode "web-mode" "\
+Major mode for editing web templates.
+
+\(fn)" t nil)
+
+(register-definition-prefixes "web-mode" '("web-mode-"))
+
+;;;***
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; web-mode-autoloads.el ends here
diff --git a/elpa/web-mode-20220319.653/web-mode-pkg.el b/elpa/web-mode-20220319.653/web-mode-pkg.el
new file mode 100644
index 0000000..a27b094
--- /dev/null
+++ b/elpa/web-mode-20220319.653/web-mode-pkg.el
@@ -0,0 +1,2 @@
+;;; Generated package description from web-mode.el -*- no-byte-compile: t -*-
+(define-package "web-mode" "20220319.653" "major mode for editing web templates" '((emacs "23.1")) :commit "efa853e5cfff8e0bcacbda9d1c6696b33da91b03" :authors '(("François-Xavier Bois")) :maintainer '("François-Xavier Bois" . "fxbois@gmail.com") :keywords '("languages") :url "https://web-mode.org")
diff --git a/elpa/web-mode-20220319.653/web-mode.el b/elpa/web-mode-20220319.653/web-mode.el
new file mode 100644
index 0000000..5cc209a
--- /dev/null
+++ b/elpa/web-mode-20220319.653/web-mode.el
@@ -0,0 +1,14434 @@
+;;; web-mode.el --- major mode for editing web templates -*- coding: utf-8; lexical-binding: t; -*-
+
+;; Copyright 2011-2022 François-Xavier Bois
+
+;; Version: 17.2.0
+;; Package-Version: 20220319.653
+;; Package-Commit: efa853e5cfff8e0bcacbda9d1c6696b33da91b03
+;; Author: François-Xavier Bois
+;; Maintainer: François-Xavier Bois <fxbois@gmail.com>
+;; Package-Requires: ((emacs "23.1"))
+;; URL: https://web-mode.org
+;; Repository: http://github.com/fxbois/web-mode
+;; Created: July 2011
+;; Keywords: languages
+;; License: GNU General Public License >= 3
+;; Distribution: This file is not part of Emacs
+
+;;; Commentary:
+
+;;==============================================================================
+;; WEB-MODE is sponsored by ** Kernix ** Best Digital Agency & Data Lab (Paris)
+;;==============================================================================
+
+;;; Code:
+
+;;---- CONSTS ------------------------------------------------------------------
+
+(defconst web-mode-version "17.1.4"
+ "Web Mode version.")
+
+;;---- GROUPS ------------------------------------------------------------------
+
+(defgroup web-mode nil
+ "Major mode for editing web templates"
+ :group 'languages
+ :prefix "web-"
+ :link '(url-link :tag "Site" "https://web-mode.org")
+ :link '(url-link :tag "Repository" "https://github.com/fxbois/web-mode"))
+
+(defgroup web-mode-faces nil
+ "Faces for syntax highlighting."
+ :group 'web-mode
+ :group 'faces)
+
+;;---- CUSTOMS -----------------------------------------------------------------
+
+(defcustom web-mode-block-padding 0
+ "Multi-line block (php, ruby, java, python, asp, etc.) left padding.
+ -1 to have to code aligned on the column 0."
+ :type '(choice (integer :tags "Number of spaces")
+ (const :tags "No indent" nil))
+ :group 'web-mode)
+
+(defcustom web-mode-part-padding 1
+ "Part elements (script, style) left padding."
+ :type '(choice (integer :tags "Number of spaces")
+ (const :tags "No indent" nil))
+ :group 'web-mode)
+
+(defcustom web-mode-script-padding web-mode-part-padding
+ "Script element left padding."
+ :type '(choice (integer :tags "Number of spaces")
+ (const :tags "No indent" nil))
+ :group 'web-mode)
+
+(defcustom web-mode-style-padding web-mode-part-padding
+ "Style element left padding."
+ :type '(choice (integer :tags "Number of spaces")
+ (const :tags "No indent" nil))
+ :group 'web-mode)
+
+(defcustom web-mode-attr-indent-offset nil
+ "Html attribute indentation level."
+ :type '(choice (integer :tags "Number of spaces")
+ (const :tags "Default" nil))
+ :safe #'(lambda (v) (or (integerp v) (booleanp v)))
+ :group 'web-mode)
+
+(defcustom web-mode-attr-value-indent-offset nil
+ "Html attribute value indentation level."
+ :type '(choice (integer :tags "Number of spaces")
+ (const :tags "Default" nil))
+ :safe #'(lambda (v) (or (integerp v) (booleanp v)))
+ :group 'web-mode)
+
+(defcustom web-mode-markup-indent-offset
+ (if (and (boundp 'standard-indent) standard-indent) standard-indent 2)
+ "Html indentation level."
+ :type 'integer
+ :safe #'integerp
+ :group 'web-mode)
+
+(defcustom web-mode-css-indent-offset
+ (if (and (boundp 'standard-indent) standard-indent) standard-indent 2)
+ "CSS indentation level."
+ :type 'integer
+ :safe #'integerp
+ :group 'web-mode)
+
+(defcustom web-mode-code-indent-offset
+ (if (and (boundp 'standard-indent) standard-indent) standard-indent 2)
+ "Code (javascript, php, etc.) indentation level."
+ :type 'integer
+ :safe #'integerp
+ :group 'web-mode)
+
+(defcustom web-mode-sql-indent-offset 4
+ "Sql (inside strings) indentation level."
+ :type 'integer
+ :safe #'integerp
+ :group 'web-mode)
+
+(defcustom web-mode-enable-css-colorization (display-graphic-p)
+ "In a CSS part, set background according to the color: #xxx, rgb(x,x,x)."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-comment-interpolation nil
+ "Enable highlight of keywords like FIXME, TODO, etc. in comments."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-comment-annotation nil
+ "Enable annotation in comments (jsdoc, phpdoc, etc.)."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-auto-indentation (display-graphic-p)
+ "Auto-indentation."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-auto-closing (display-graphic-p)
+ "Auto-closing."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-auto-pairing (display-graphic-p)
+ "Auto-pairing."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-auto-opening (display-graphic-p)
+ "Html element auto-opening."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-auto-quoting (display-graphic-p)
+ "Add double quotes after the character = in a tag."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-auto-expanding nil
+ "e.g. s/ expands to <span>|</span>."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-curly-brace-indentation nil
+ "Indent lines beginning with {."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-control-block-indentation t
+ "Control blocks increase indentation."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-current-element-highlight nil
+ "Enable current element highlight."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-current-column-highlight nil
+ "Show column for current element."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-whitespace-fontification nil
+ "Enable whitespaces."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-html-entities-fontification nil
+ "Enable html entities fontification."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-block-face nil
+ "Enable block face (useful for setting a background for example).
+See web-mode-block-face."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-part-face nil
+ "Enable part face (useful for setting background of <style> or <script>
+ elements for example). See web-mode-part-face."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-inlays nil
+ "Enable inlays (e.g. LaTeX) highlighting."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-sexp-functions t
+ "Enable specific sexp functions."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-string-interpolation t
+ "Enable string interpolation fontification (php and erb)."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-literal-interpolation t
+ "Enable template literal fontification. e.g. css` `."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-sql-detection nil
+ "Enable fontification and indentation of sql queries in strings."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-heredoc-fontification t
+ "Enable heredoc fontification. The identifier should contain JS, JAVASCRIPT, CSS or HTML."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-element-content-fontification nil
+ "Enable element content fontification. The content of an element can have a face associated."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-element-tag-fontification nil
+ "Enable tag name fontification."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-front-matter-block nil
+ "Enable front matter block (data at the beginning the template between --- and ---)."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-engine-detection nil
+ "Detect such directive -*- engine: ENGINE -*- at the top of the file."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-enable-optional-tags nil
+ "Enable omission of certain closing tags (e.g. a li open tag followed by a li open tag is valid)."
+ :type 'boolean
+ :group 'web-mode)
+
+(defcustom web-mode-comment-style 1
+ "Comment style : 1 = default, 2 = force server comments outside a block."
+ :group 'web-mode
+ :type '(choice (const :tag "Default" 1)
+ (const :tag "Force engine comments" 2)))
+
+(defcustom web-mode-indent-style 2
+ "Indentation style."
+ :group 'web-mode
+ :type '(choice (const :tag "Default (all lines are indented)" 2)
+ (const :tag "Text at the beginning of line is not indented" 1)))
+
+(defcustom web-mode-auto-close-style 1
+ "Auto-close style."
+ :group 'web-mode
+ :type '(choice (const :tag "Auto-close on </" 1)
+ (const :tag "Auto-close on > and </" 2)
+ (const :tag "Auto-close on < and >/>" 3)))
+
+(defcustom web-mode-auto-quote-style 1
+ "Auto-quoting style."
+ :group 'web-mode
+ :type '(choice (const :tag "Auto-quotes with double quote" 1)
+ (const :tag "Auto-quotes with single quote" 2)
+ (const :tag "Auto-quotes with paren (for jsx)" 3)))
+
+(defcustom web-mode-extra-expanders '()
+ "A list of additional expanders."
+ :type '(alist :key-type string :value-type string)
+ :group 'web-mode)
+
+(defcustom web-mode-extra-auto-pairs '()
+ "A list of additional auto-pairs."
+ :type '(alist :key-type string :value-type string)
+ :group 'web-mode)
+
+(defcustom web-mode-extra-snippets '()
+ "A list of additional snippets."
+ :type '(alist :key-type string :value-type string)
+ :group 'web-mode)
+
+(defcustom web-mode-extra-builtins '()
+ "A list of additional builtins."
+ :type '(alist :key-type string :value-type string)
+ :group 'web-mode)
+
+(defcustom web-mode-extra-constants '()
+ "A list of additional constants."
+ :type '(alist :key-type string :value-type string)
+ :group 'web-mode)
+
+(defcustom web-mode-extra-keywords '()
+ "A list of additional keywords."
+ :type '(alist :key-type string :value-type string)
+ :group 'web-mode)
+
+(defcustom web-mode-extra-types '()
+ "A list of additional types."
+ :type '(alist :key-type string :value-type string)
+ :group 'web-mode)
+
+(defcustom web-mode-extra-control-blocks '()
+ "A list of additional control blocks."
+ :type '(alist :key-type string :value-type (repeat string))
+ :group 'web-mode)
+
+(defcustom web-mode-tests-directory (concat default-directory "tests/")
+ "Directory containing all the unit tests."
+ :type 'directory
+ :group 'web-mode)
+
+(defcustom web-mode-jsx-depth-faces
+ nil
+ ;;'(web-mode-jsx-depth-1-face web-mode-jsx-depth-2-face web-mode-jsx-depth-3-face web-mode-jsx-depth-4-face web-mode-jsx-depth-5-face)
+ "Each jsx depth has is own face."
+ :type '(repeat face)
+ :group 'web-mode)
+
+(defcustom web-mode-commands-like-expand-region
+ '(web-mode-mark-and-expand er/expand-region mc/mark-next-like-this)
+ "Add it to here if you have some wrapper function for er/expand-region"
+ :type '(repeat function)
+ :group 'web-mode)
+
+(defcustom web-mode-comment-formats
+ '(("java" . "/*")
+ ("javascript" . "/*")
+ ("typescript" . "//")
+ ("php" . "/*")
+ ("css" . "/*"))
+ "Default comment format for a language"
+ :type '(alist :key-type string :value-type string)
+ :group 'web-mode)
+
+(defcustom web-mode-script-template-types
+ '("text/x-handlebars"
+ "text/x-jquery-tmpl"
+ "text/x-jsrender"
+ "text/html"
+ "text/ng-template"
+ "text/x-template"
+ "text/mustache"
+ "text/x-dust-template")
+ "<script> block types that are interpreted as HTML."
+ :type '(repeat string)
+ :group 'web-mode)
+
+;;---- FACES -------------------------------------------------------------------
+
+(defface web-mode-error-face
+ '((t :background "red"))
+ "Face for warning."
+ :group 'web-mode-faces)
+
+(defface web-mode-warning-face
+ '((t :inherit font-lock-warning-face))
+ "Face for warning."
+ :group 'web-mode-faces)
+
+(defface web-mode-preprocessor-face
+ '((t :inherit font-lock-preprocessor-face))
+ "Face for preprocessor commands."
+ :group 'web-mode-faces)
+
+(defface web-mode-preprocessor-face
+ '((t :inherit font-lock-preprocessor-face))
+ "Face for preprocessor."
+ :group 'web-mode-faces)
+
+(defface web-mode-block-delimiter-face
+ '((t :inherit font-lock-preprocessor-face))
+ "Face for block delimiters."
+ :group 'web-mode-faces)
+
+(defface web-mode-block-control-face
+ '((t :inherit font-lock-preprocessor-face))
+ "Face for preprocessor."
+ :group 'web-mode-faces)
+
+(defface web-mode-builtin-face
+ '((t :inherit font-lock-builtin-face))
+ "Face for builtins."
+ :group 'web-mode-faces)
+
+(defface web-mode-symbol-face
+ '((t :foreground "goldenrod2"))
+ "Face for symbols."
+ :group 'web-mode-faces)
+
+(defface web-mode-doctype-face
+ '((t :foreground "Grey"))
+ "Face for html doctype."
+ :group 'web-mode-faces)
+
+(defface web-mode-html-tag-face
+ '((((class color) (min-colors 88) (background dark)) :foreground "Snow4")
+ (((class color) (min-colors 88) (background light)) :foreground "Snow4")
+ (((class color) (min-colors 16) (background dark)) :foreground "Snow4")
+ (((class color) (min-colors 16) (background light)) :foreground "Grey15")
+ (((class color) (min-colors 8)) :foreground "Snow4")
+ (((type tty) (class mono)) :inverse-video t)
+ (t :foreground "Snow4"))
+ "Face for html tags."
+ :group 'web-mode-faces)
+
+(defface web-mode-html-tag-custom-face
+ '((t :inherit web-mode-html-tag-face))
+ "Face for html custom tags (e.g. <polymer-element>)."
+ :group 'web-mode-faces)
+
+(defface web-mode-html-tag-unclosed-face
+ '((t :inherit web-mode-html-tag-face :underline t))
+ "Face for unclosed tags."
+ :group 'web-mode-faces)
+
+(defface web-mode-html-tag-namespaced-face
+ '((t :inherit web-mode-block-control-face))
+ "Face for html namespaced tags (e.g. <c:forEach>)."
+ :group 'web-mode-faces)
+
+(defface web-mode-html-tag-bracket-face
+ '((((class color) (min-colors 88) (background dark)) :foreground "Snow3")
+ (((class color) (min-colors 88) (background light)) :foreground "Grey14")
+ (((class color) (min-colors 16) (background dark)) :foreground "Snow3")
+ (((class color) (min-colors 16) (background light)) :foreground "Grey14")
+ (((class color) (min-colors 8)) :foreground "Snow3")
+ (((type tty) (class mono)) :inverse-video t)
+ (t :foreground "Snow3"))
+ "Face for html tags angle brackets (<, > and />)."
+ :group 'web-mode-faces)
+
+(defface web-mode-html-attr-name-face
+ '((((class color) (min-colors 88) (background dark)) :foreground "Snow3")
+ (((class color) (min-colors 88) (background light)) :foreground "Snow4")
+ (((class color) (min-colors 16) (background dark)) :foreground "Snow3")
+ (((class color) (min-colors 16) (background light)) :foreground "Grey13")
+ (((class color) (min-colors 8)) :foreground "Snow3")
+ (((type tty) (class mono)) :inverse-video t)
+ (t :foreground "Snow4"))
+ "Face for html attribute names."
+ :group 'web-mode-faces)
+
+(defface web-mode-html-attr-custom-face
+ '((t :inherit web-mode-html-attr-name-face))
+ "Face for custom attribute names (e.g. data-*)."
+ :group 'web-mode-faces)
+
+(defface web-mode-html-attr-engine-face
+ '((t :inherit web-mode-block-delimiter-face))
+ "Face for custom engine attribute names (e.g. ng-*)."
+ :group 'web-mode-faces)
+
+(defface web-mode-html-attr-equal-face
+ '((t :inherit web-mode-html-attr-name-face))
+ "Face for the = character between name and value."
+ :group 'web-mode-faces)
+
+(defface web-mode-html-attr-value-face
+ '((t :inherit font-lock-string-face))
+ "Face for html attribute values."
+ :group 'web-mode-faces)
+
+(defface web-mode-block-attr-name-face
+ '((t :foreground "#8fbc8f"))
+ "Face for block attribute names."
+ :group 'web-mode-faces)
+
+(defface web-mode-block-attr-value-face
+ '((t :foreground "#5f9ea0"))
+ "Face for block attribute values."
+ :group 'web-mode-faces)
+
+(defface web-mode-variable-name-face
+ '((t :inherit font-lock-variable-name-face))
+ "Face for variable names."
+ :group 'web-mode-faces)
+
+(defface web-mode-css-selector-face
+ '((t :inherit font-lock-keyword-face))
+ "Face for CSS rules."
+ :group 'web-mode-faces)
+
+(defface web-mode-css-pseudo-class-face
+ '((t :inherit font-lock-builtin-face))
+ "Face for CSS pseudo-classes."
+ :group 'web-mode-faces)
+
+(defface web-mode-css-at-rule-face
+ '((t :inherit font-lock-constant-face))
+ "Face for CSS at-rules."
+ :group 'web-mode-faces)
+
+(defface web-mode-css-property-name-face
+ '((t :inherit font-lock-variable-name-face))
+ "Face for CSS props."
+ :group 'web-mode-faces)
+
+(defface web-mode-css-color-face
+ '((t :inherit font-lock-builtin-face))
+ "Face for CSS colors (#xxx)."
+ :group 'web-mode-faces)
+
+(defface web-mode-css-priority-face
+ '((t :inherit font-lock-builtin-face))
+ "Face for CSS priority (!important)."
+ :group 'web-mode-faces)
+
+(defface web-mode-css-function-face
+ '((t :inherit font-lock-builtin-face))
+ "Face for CSS functions."
+ :group 'web-mode-faces)
+
+(defface web-mode-css-variable-face
+ '((t :inherit web-mode-variable-name-face :slant italic))
+ "Face for CSS vars."
+ :group 'web-mode-faces)
+
+(defface web-mode-function-name-face
+ '((t :inherit font-lock-function-name-face))
+ "Face for function names."
+ :group 'web-mode-faces)
+
+(defface web-mode-filter-face
+ '((t :inherit font-lock-function-name-face))
+ "Face for function names."
+ :group 'web-mode-faces)
+
+(defface web-mode-function-call-face
+ '((t :inherit font-lock-function-name-face))
+ "Face for function calls."
+ :group 'web-mode-faces)
+
+(defface web-mode-string-face
+ '((t :inherit font-lock-string-face))
+ "Face for strings."
+ :group 'web-mode-faces)
+
+(defface web-mode-block-string-face
+ '((t :inherit web-mode-string-face))
+ "Face for block strings."
+ :group 'web-mode-faces)
+
+(defface web-mode-part-string-face
+ '((t :inherit web-mode-string-face))
+ "Face for part strings."
+ :group 'web-mode-faces)
+
+(defface web-mode-javascript-string-face
+ '((t :inherit web-mode-string-face))
+ "Face for javascript strings."
+ :group 'web-mode-faces)
+
+(defface web-mode-interpolate-color1-face
+ '((t :inherit web-mode-string-face))
+ "Face for element interpolation strings."
+ :group 'web-mode-faces)
+
+(defface web-mode-interpolate-color2-face
+ '((t :inherit web-mode-string-face))
+ "Face for element interpolation strings."
+ :group 'web-mode-faces)
+
+(defface web-mode-interpolate-color3-face
+ '((t :inherit web-mode-string-face))
+ "Face for element interpolation strings."
+ :group 'web-mode-faces)
+
+(defface web-mode-css-string-face
+ '((t :inherit web-mode-string-face))
+ "Face for css strings."
+ :group 'web-mode-faces)
+
+(defface web-mode-json-key-face
+ '((t :foreground "plum"))
+ "Face for json key strings."
+ :group 'web-mode-faces)
+
+(defface web-mode-json-context-face
+ '((t :foreground "orchid3"))
+ "Face for json context strings."
+ :group 'web-mode-faces)
+
+(defface web-mode-json-string-face
+ '((t :inherit web-mode-string-face))
+ "Face for json strings."
+ :group 'web-mode-faces)
+
+(defface web-mode-comment-face
+ '((t :inherit font-lock-comment-face))
+ "Face for comments."
+ :group 'web-mode-faces)
+
+(defface web-mode-block-comment-face
+ '((t :inherit web-mode-comment-face))
+ "Face for server comments."
+ :group 'web-mode-faces)
+
+(defface web-mode-part-comment-face
+ '((t :inherit web-mode-comment-face))
+ "Face for part comments."
+ :group 'web-mode-faces)
+
+(defface web-mode-json-comment-face
+ '((t :inherit web-mode-comment-face))
+ "Face for json comments."
+ :group 'web-mode-faces)
+
+(defface web-mode-javascript-comment-face
+ '((t :inherit web-mode-comment-face))
+ "Face for javascript comments."
+ :group 'web-mode-faces)
+
+(defface web-mode-css-comment-face
+ '((t :inherit web-mode-comment-face))
+ "Face for css comments."
+ :group 'web-mode-faces)
+
+(defface web-mode-annotation-face
+ '((t :inherit web-mode-comment-face))
+ "Face for code annotations."
+ :group 'web-mode-faces)
+
+(defface web-mode-annotation-tag-face
+ '((t :inherit web-mode-annotation-face :underline t))
+ "Face for @tags in code annotations."
+ :group 'web-mode-faces)
+
+(defface web-mode-annotation-type-face
+ '((t :inherit web-mode-annotation-face :weight bold))
+ "Face for types in code annotations."
+ :group 'web-mode-faces)
+
+(defface web-mode-annotation-value-face
+ '((t :inherit web-mode-annotation-face :slant italic))
+ "Face for values in code annotations."
+ :group 'web-mode-faces)
+
+(defface web-mode-annotation-html-face
+ '((t :inherit web-mode-annotation-face :slant italic))
+ "Face for HTML tags in code annotations."
+ :group 'web-mode-faces)
+
+(defface web-mode-constant-face
+ '((t :inherit font-lock-constant-face))
+ "Face for language constants."
+ :group 'web-mode-faces)
+
+(defface web-mode-type-face
+ '((t :inherit font-lock-type-face))
+ "Face for language types."
+ :group 'web-mode-faces)
+
+(defface web-mode-keyword-face
+ '((t :inherit font-lock-keyword-face))
+ "Face for language keywords."
+ :group 'web-mode-faces)
+
+(defface web-mode-param-name-face
+ '((t :foreground "Snow3"))
+ "Face for server attribute names."
+ :group 'web-mode-faces)
+
+(defface web-mode-whitespace-face
+ '((t :background "DarkOrchid4"))
+ "Face for whitespaces."
+ :group 'web-mode-faces)
+
+(defface web-mode-inlay-face
+ '((((class color) (min-colors 88) (background dark)) :background "Black")
+ (((class color) (min-colors 88) (background light)) :background "LightYellow1")
+ (((class color) (min-colors 16) (background dark)) :background "Brey18")
+ (((class color) (min-colors 16) (background light)) :background "LightYellow1")
+ (((class color) (min-colors 8)) :background "Black")
+ (((type tty) (class mono)) :inverse-video t)
+ (t :background "Grey"))
+ "Face for inlays. Must be used in conjunction with web-mode-enable-inlays."
+ :group 'web-mode-faces)
+
+(defface web-mode-block-face
+ '((((class color) (min-colors 88) (background dark)) :background "Black")
+ (((class color) (min-colors 88) (background light)) :background "LightYellow1")
+ (((class color) (min-colors 16) (background dark)) :background "Grey18")
+ (((class color) (min-colors 16) (background light)) :background "LightYellow1")
+ (((class color) (min-colors 8)) :background "Black")
+ (((type tty) (class mono)) :inverse-video t)
+ (t :background "Grey"))
+ "Face for blocks (useful for setting a background for example).
+Must be used in conjunction with web-mode-enable-block-face."
+ :group 'web-mode-faces)
+
+(defface web-mode-part-face
+ '((t :inherit web-mode-block-face))
+ "Face for parts."
+ :group 'web-mode-faces)
+
+(defface web-mode-script-face
+ '((t :inherit web-mode-part-face))
+ "Face for javascript inside a script element."
+ :group 'web-mode-faces)
+
+(defface web-mode-style-face
+ '((t :inherit web-mode-part-face))
+ "Face for css inside a style element."
+ :group 'web-mode-faces)
+
+(defface web-mode-folded-face
+ '((t :underline t))
+ "Overlay face for folded."
+ :group 'web-mode-faces)
+
+(defface web-mode-bold-face
+ '((t :weight bold))
+ "bold face."
+ :group 'web-mode-faces)
+
+(defface web-mode-italic-face
+ '((t :slant italic))
+ "bold face."
+ :group 'web-mode-faces)
+
+(defface web-mode-underline-face
+ '((t :underline t))
+ "bold face."
+ :group 'web-mode-faces)
+
+(defface web-mode-current-element-highlight-face
+ '((t :background "#000000" :foreground "#ffffff"))
+ "Overlay face for element highlight."
+ :group 'web-mode-faces)
+
+(defface web-mode-current-column-highlight-face
+ '((t :background "#3e3c36"))
+ "Overlay face for current column."
+ :group 'web-mode-faces)
+
+(defface web-mode-comment-keyword-face
+ '((t :weight bold :box t))
+ "Comment keywords."
+ :group 'web-mode-faces)
+
+(defface web-mode-sql-keyword-face
+ '((t :weight bold :slant italic))
+ "Sql keywords."
+ :group 'web-mode-faces)
+
+(defface web-mode-html-entity-face
+ '((t :slant italic))
+ "Face html entities (e.g. &#8211;, &eacute;)."
+ :group 'web-mode-faces)
+
+;; https://material.io/tools/color/#!/?view.left=0&view.right=0
+(defface web-mode-jsx-depth-1-face
+ '((t :background "#000053"))
+ "jsx depth 1"
+ :group 'web-mode-faces)
+
+(defface web-mode-jsx-depth-2-face
+ '((t :background "#001970"))
+ "jsx"
+ :group 'web-mode-faces)
+
+(defface web-mode-jsx-depth-3-face
+ '((t :background "#002984"))
+ "jsx"
+ :group 'web-mode-faces)
+
+(defface web-mode-jsx-depth-4-face
+ '((t :background "#49599a"))
+ "jsx"
+ :group 'web-mode-faces)
+
+(defface web-mode-jsx-depth-5-face
+ '((t :background "#9499b7"))
+ "jsx"
+ :group 'web-mode-faces)
+
+;;---- VARS --------------------------------------------------------------------
+
+(defvar font-lock-beg)
+(defvar font-lock-end)
+
+(defvar web-mode-auto-pairs nil)
+(defvar web-mode-block-regexp nil)
+(defvar web-mode-change-beg nil)
+(defvar web-mode-change-end nil)
+(defvar web-mode-chunk-length 64)
+(defvar web-mode-column-overlays nil)
+(defvar web-mode-comments-invisible nil)
+(defvar web-mode-content-type "")
+(defvar web-mode-engine nil)
+;;(defvar web-mode-engine-attr-regexp nil)
+(defvar web-mode-engine-font-lock-keywords nil)
+(defvar web-mode-engine-token-regexp nil)
+(defvar web-mode-expand-initial-pos nil)
+(defvar web-mode-expand-initial-scroll nil)
+(defvar web-mode-expand-previous-state "")
+;;(defvar web-mode-font-lock-keywords '(web-mode-font-lock-highlight))
+(defvar web-mode-skip-fontification nil)
+(defvar web-mode-inlay-regexp nil)
+(defvar web-mode-is-scratch nil)
+(defvar web-mode-jshint-errors 0)
+(defvar web-mode-minor-engine nil)
+(defvar web-mode-obarray nil)
+(defvar web-mode-overlay-tag-start nil)
+(defvar web-mode-overlay-tag-end nil)
+(defvar web-mode-part-beg nil)
+(defvar web-mode-scan-beg nil)
+(defvar web-mode-scan-end nil)
+(defvar web-mode-snippets nil)
+(defvar web-mode-time nil)
+
+(defvar web-mode-offsetless-elements
+ '())
+
+(defvar web-mode-indentless-elements
+ '("code" "pre" "textarea"))
+
+(defvar web-mode-indentless-attributes
+ '("onclick" "onmouseover" "onmouseout" "onsubmit"))
+
+(defvar web-mode-void-elements
+ '("area" "base" "br" "col" "command" "embed" "hr" "img" "input" "keygen"
+ "link" "meta" "param" "source" "track" "wbr" "tmpl_var"))
+
+(defvar web-mode-part-content-types
+ '("css" "javascript" "json" "jsx" "markdown" "pug" "ruby"
+ "sass" "sql" "stylus" "typescript"))
+
+(defvar web-mode-javascript-languages '("javascript" "jsx" "ejs"))
+
+;; NOTE: without 'syntax-table forward-word fails (#377)
+(defvar web-mode-scan-properties
+ (list 'tag-beg 'tag-end 'tag-name 'tag-type
+ 'tag-attr 'tag-attr-beg 'tag-attr-end
+ 'part-side 'part-token
+ 'jsx-beg 'jsx-end 'jsx-depth
+ 'block-side 'block-token 'block-controls 'block-beg 'block-end
+ 'syntax-table)
+ "Text properties used for code regions/tokens and html nodes.")
+
+(defvar web-mode-start-tag-regexp "<\\([[:alpha:]][[:alnum:].:_-]*\\|>\\)"
+ "Regular expression for HTML/XML start tag.")
+
+(defvar web-mode-tag-regexp "</?\\([[:alpha:]][[:alnum:].:_-]*\\)"
+ "Regular expression for HTML/XML tag.")
+
+(defvar web-mode-dom-regexp "<\\(/?>\\|/?[[:alpha:]][[:alnum:].:_-]*\\|!--\\|!\\[CDATA\\[\\|!doctype\\|!DOCTYPE\\|\?xml\\)")
+
+(defvar web-mode-whitespaces-regexp
+ "^[ \t]\\{2,\\}$\\| \t\\|\t \\|[ \t]+$\\|^[ \n\t]+\\'\\|^[ \t]?[\n]\\{2,\\}"
+ "Regular expression for whitespaces.")
+
+(defvar web-mode-imenu-regexp-list
+ '(("<\\(h[1-9]\\)\\([^>]*\\)>\\([^<]*\\)" 1 3 ">")
+ ("^[ \t]*<\\([@a-z]+\\)[^>]*>? *$" 1 "id=\"\\([a-zA-Z0-9_]+\\)\"" "#" ">"))
+ "Regexps to match imenu items (see https://web-mode.org/doc/imenu.txt)")
+
+;; https://www.gnu.org/software/emacs/manual/html_node/ccmode/Syntactic-Symbols.html
+(defvar web-mode-indentation-params
+ '(("lineup-args" . t)
+ ("lineup-calls" . t)
+ ("lineup-concats" . t)
+ ("lineup-quotes" . t)
+ ("lineup-ternary" . t)
+ ("case-extra-offset" . t)
+ ))
+
+(defvar web-mode-engines
+ '(("angular" . ("angularjs"))
+ ("archibus" . ())
+ ("artanis" . ())
+ ("asp" . ())
+ ("aspx" . ())
+ ("blade" . ("laravel"))
+ ("cl-emb" . ())
+ ("clip" . ())
+ ("closure" . ("soy"))
+ ("ctemplate" . ("mustache" "handlebars" "hapax" "ngtemplate" "ember"
+ "kite" "meteor" "blaze" "ractive" "velvet"))
+ ("django" . ("dtl" "twig" "swig" "jinja" "jinja2" "erlydtl" "liquid"
+ "clabango" "selmer" "nunjucks"))
+ ("dust" . ("dustjs"))
+ ("ejs" . ())
+ ("elixir" . ("phoenix"))
+ ("erb" . ("eruby" "erubis"))
+ ("expressionengine" . ("ee"))
+ ("freemarker" . ())
+ ("go" . ("gtl" "hugo"))
+ ("hero" . ())
+ ("json-t" . ())
+ ("jsp" . ("grails"))
+ ("mako" . ())
+ ("marko" . ())
+ ("mason" . ("poet"))
+ ("lsp" . ("lisp"))
+ ("mojolicious" . ())
+ ("php" . ())
+ ("python" . ())
+ ("razor" . ("play" "play2"))
+ ("riot" . ())
+ ("smarty" . ())
+ ("spip" . ())
+ ("svelte" . ("svelte"))
+ ("template-toolkit" . ())
+ ("thymeleaf" . ())
+ ("underscore" . ("underscore.js"))
+ ("velocity" . ("vtl" "cheetah" "ssp"))
+ ("vue" . ("vuejs" "vue.js"))
+ ("web2py" . ())
+ ("xoops" . ())
+ )
+ "Engine name aliases")
+
+(defvar web-mode-content-types
+ '(("css" . "\\.\\(s?css\\|css\\.erb\\)\\'")
+ ("javascript" . "\\.\\([mc]?js\\|js\\.erb\\)\\'")
+ ("typescript" . "\\.\\(ts\\|ts\\.erb\\)\\'")
+ ("json" . "\\.\\(api\\|json\\|jsonld\\)\\'")
+ ("jsx" . "\\.[jt]sx\\'")
+ ("xml" . "\\.xml\\'")
+ ("html" . "."))
+ "content types")
+
+(defvar web-mode-engine-attr-regexps
+ '(("angular" . "ng-")
+ ("thymeleaf" . "th:")
+ ("vue" . "v-"))
+ "Engine custom attributes")
+
+(defvar web-mode-engine-attr-regexp
+ "^ng[-]\\|^th[:]\\|^v[-]\\|^[@:#(\[*]"
+ "Engine custom attributes")
+
+(defvar web-mode-last-enabled-feature nil)
+
+(defvar web-mode-features
+ '(("css-colorization" . web-mode-enable-css-colorization)
+ ("element-highlight" . web-mode-enable-current-element-highlight)
+ ("column-highlight" . web-mode-enable-current-column-highlight)
+ ("whitespace-fontification" . web-mode-enable-whitespace-fontification)
+ ("element-tag-fontification" . web-mode-enable-element-tag-fontification)
+ ("block-face" . web-mode-enable-block-face)
+ ("part-face" . web-mode-enable-part-face)))
+
+(defvar web-mode-comment-prefixing t)
+
+(defvar web-mode-engine-file-regexps
+ '(("angular" . "\\.component.html\\'")
+ ("archibus" . "\\.axvw\\'")
+ ("artanis" . "\\.html\\.tpl\\'")
+ ("asp" . "\\.asp\\'")
+ ("aspx" . "\\.as[cp]x\\'")
+ ("blade" . "\\.blade\\.php\\'")
+ ("cl-emb" . "\\.clemb\\'")
+ ("clip" . "\\.ctml\\'")
+ ("closure" . "\\.soy\\'")
+ ("ctemplate" . "\\.\\(chtml\\|mustache\\)\\'")
+ ("django" . "\\.\\(djhtml\\|tmpl\\|dtl\\|liquid\\|j2\\|njk\\)\\'")
+ ("dust" . "\\.dust\\'")
+ ("elixir" . "\\.[hl]?eex\\'")
+ ("ejs" . "\\.ejs\\'")
+ ("erb" . "\\.\\(erb\\|rhtml\\|erb\\.html\\)\\'")
+ ("expressionengine" . "\\.ee\\'")
+ ("freemarker" . "\\.ftl\\'")
+ ("go" . "\\.go\\(html\\|tmpl\\)\\'")
+ ("handlebars" . "\\.\\(hb\\.html\\|hbs\\)\\'")
+ ("hero" . "\\.hero\\'")
+ ("jinja" . "\\.jinja\\'")
+ ("jsp" . "\\.[gj]sp\\'")
+ ("lsp" . "\\.lsp\\'")
+ ("mako" . "\\.mako?\\'")
+ ("marko" . "\\.marko\\'")
+ ("mason" . "\\.mas\\'")
+ ("mojolicious" . "\\.epl?\\'")
+ ("php" . "\\.\\(p[hs]p\\|ctp\\|inc\\)\\'")
+ ("python" . "\\.pml\\'")
+ ("razor" . "\\.\\(cs\\|vb\\)html\\|\\.razor\\'")
+ ("riot" . "\\.tag\\'")
+ ("smarty" . "\\.tpl\\'")
+ ("svelte" . "\\.svelte\\'")
+ ("template-toolkit" . "\\.tt.?\\'")
+ ("thymeleaf" . "\\.thtml\\'")
+ ("velocity" . "\\.v\\(sl\\|tl\\|m\\)\\'")
+ ("vue" . "\\.vue\\'")
+ ("xoops" . "\\.xoops'")
+ ;; regexp on the path, not just the extension
+ ("django" . "[st]wig")
+ ("razor" . "scala")
+ ("spip" . "spip")
+ )
+ "Engine file extensions.")
+
+(defvar web-mode-content-types-alist nil
+ "A list of filename patterns and corresponding web-mode content types. For example,
+(setq web-mode-content-types-alist
+ '((\"json\" . \"/some/path/.*\\.api\\'\")
+ (\"jsx\" . \"/some/react/path/.*\\.js[x]?\\'\")))")
+
+(defvar web-mode-engines-alist nil
+ "A list of filename patterns and corresponding web-mode engine. For example,
+(setq web-mode-engines-alist
+ '((\"php\" . \"\\\\.phtml\\\\'\")
+ (\"blade\" . \"\\\\.blade\\\\.\")))")
+
+(defvar web-mode-smart-quotes
+ '("«" . "»")
+ "Preferred smart quotes")
+
+(defvar web-mode-xml-chars
+ '((?\& . "&amp;")
+ (?\< . "&lt;")
+ (?\> . "&gt;"))
+ "XML chars")
+
+(defvar web-mode-html-entities
+ ;; #985
+ ;; remove ("gt" . 62) ("lt" . 60) ("amp" . 38)
+ '(("AElig" . 198) ("Aacute" . 193) ("Acirc" . 194) ("Agrave" . 192)
+ ("Alpha" . 913) ("Aring" . 197) ("Atilde" . 195) ("Auml" . 196)
+ ("Beta" . 914)
+ ("Ccedil" . 199) ("Chi" . 935)
+ ("Dagger" . 8225) ("Delta" . 916)
+ ("ETH" . 208) ("Eacute" . 201) ("Ecirc" . 202) ("Egrave" . 200)
+ ("Epsilon" . 917) ("Eta" . 919) ("Euml" . 203)
+ ("Gamma" . 915)
+ ("Iacute" . 205) ("Icirc" . 206) ("Igrave" . 204) ("Iota" . 921)
+ ("Iuml" . 207)
+ ("Kappa" . 922)
+ ("Lambda" . 923)
+ ("Mu" . 924)
+ ("Ntilde" . 209) ("Nu" . 925)
+ ("OElig" . 338) ("Oacute" . 211) ("Ocirc" . 212) ("Ograve" . 210)
+ ("Omega" . 937) ("Omicron" . 927) ("Oslash" . 216) ("Otilde" . 213)
+ ("Ouml" . 214)
+ ("Phi" . 934) ("Pi" . 928) ("Prime" . 8243) ("Psi" . 936)
+ ("Rho" . 929)
+ ("Scaron" . 352) ("Sigma" . 931)
+ ("THORN" . 222) ("Tau" . 932) ("Theta" . 920)
+ ("UArr" . 8657) ("Uacute" . 218) ("Uacute" . 250) ("Ucirc" . 219)
+ ("Ugrave" . 217) ("Upsih" . 978)
+ ("Upsilon" . 933) ("Uuml" . 220) ("Uuml" . 252)
+ ("Xi" . 926)
+ ("Yacute" . 221) ("Yuml" . 376)
+ ("Zeta" . 918)
+ ("aacute" . 225) ("acirc" . 226) ("acute" . 180) ("aelig" . 230)
+ ("agrave" . 224) ("alefsym" . 8501) ("alpha" . 945)
+ ("ang" . 8736) ("apos" . 39) ("aring" . 229) ("asymp" . 8776)
+ ("atilde" . 227) ("auml" . 228)
+ ("bdquo" . 8222) ("beta" . 946) ("brvbar" . 166) ("bull" . 8226)
+ ("cap" . 8745) ("ccedil" . 231) ("cedil" . 184) ("cent" . 162)
+ ("chi" . 967) ("circ" . 710) ("clubs" . 9827) ("cong" . 8773)
+ ("copy" . 169) ("crarr" . 8629) ("cup" . 8746) ("curren" . 164)
+ ("dArr" . 8659) ("dagger" . 8224) ("darr" . 8595) ("deg" . 176)
+ ("delta" . 948) ("diams" . 9830) ("divide" . 247)
+ ("eacute" . 233) ("ecirc" . 234) ("egrave" . 232) ("empty" . 8709)
+ ("emsp" . 8195) ("ensp" . 8194) ("epsilon" . 949) ("equiv" . 8801)
+ ("eta" . 951) ("eth" . 240) ("euml" . 235) ("euro" . 8364) ("exist" . 8707)
+ ("fnof" . 402) ("forall" . 8704) ("frac12" . 189) ("frac14" . 188)
+ ("frac34" . 190) ("frasl" . 8260)
+ ("gamma" . 947) ("ge" . 8805)
+ ("hArr" . 8660) ("harr" . 8596) ("hearts" . 9829) ("hellip" . 8230)
+ ("iacute" . 237) ("icirc" . 238) ("iexcl" . 161) ("igrave" . 236)
+ ("image" . 8465) ("infin" . 8734) ("int" . 8747) ("iota" . 953)
+ ("iquest" . 191) ("isin" . 8712) ("iuml" . 239)
+ ("kappa" . 954)
+ ("lArr" . 8656) ("lambda" . 955) ("lang" . 9001) ("laquo" . 171)
+ ("larr" . 8592) ("lceil" . 8968) ("ldquo" . 8220) ("le" . 8804)
+ ("lfloor" . 8970) ("lowast" . 8727) ("loz" . 9674) ("lrm" . 8206)
+ ("lsaquo" . 8249) ("lsquo" . 8249)
+ ("macr" . 175) ("mdash" . 8212) ("micro" . 181) ("middot" . 183)
+ ("minus" . 8722) ("mu" . 956)
+ ("nabla" . 8711) ("nbsp" . 160) ("ndash" . 8211) ("ne" . 8800)
+ ("ni" . 8715) ("not" . 172) ("notin" . 8713) ("nsub" . 8836)
+ ("ntilde" . 241) ("nu" . 957) ("oacute" . 243) ("ocirc" . 244)
+ ("oelig" . 339) ("ograve" . 242) ("oline" . 8254) ("omega" . 969)
+ ("omicron" . 959) ("oplus" . 8853) ("or" . 8744) ("ordf" . 170)
+ ("ordm" . 186) ("oslash" . 248) ("otilde" . 245) ("otimes" . 8855)
+ ("ouml" . 246)
+ ("para" . 182) ("part" . 8706) ("permil" . 8240) ("perp" . 8869)
+ ("phi" . 966) ("pi" . 960) ("piv" . 982) ("plusmn" . 177) ("pound" . 163)
+ ("prime" . 8242) ("prod" . 8719) ("prop" . 8733) ("psi" . 968)
+ ("quot" . 34)
+ ("rArr" . 8658) ("radic" . 8730) ("rang" . 9002) ("raquo" . 187)
+ ("rarr" . 8594) ("rceil" . 8969) ("rdquo" . 8221) ("real" . 8476)
+ ("reg" . 174) ("rfloor" . 8971) ("rho" . 961) ("rlm" . 8207)
+ ("rsaquo" . 8250) ("rsquo" . 8250) ("sbquo" . 8218)
+ ("scaron" . 353) ("sdot" . 8901) ("sect" . 167) ("shy" . 173)
+ ("sigma" . 963) ("sigmaf" . 962) ("sim" . 8764) ("spades" . 9824)
+ ("sub" . 8834) ("sube" . 8838) ("sum" . 8721) ("sup" . 8835)
+ ("sup1" . 185) ("sup2" . 178) ("sup3" . 179) ("supe" . 8839)
+ ("szlig" . 223)
+ ("tau" . 964) ("there4" . 8756) ("theta" . 952) ("thetasym" . 977)
+ ("thinsp" . 8201) ("thorn" . 254) ("tilde" . 732) ("times" . 215)
+ ("trade" . 8482)
+ ("uarr" . 8593) ("ucirc" . 251) ("ugrave" . 249) ("uml" . 168)
+ ("upsilon" . 965)
+ ("weierp" . 8472)
+ ("xi" . 958)
+ ("yacute" . 253) ("yen" . 165) ("yuml" . 255)
+ ("zeta" . 950) ("zwj" . 8205) ("zwnj" . 8204)))
+
+;; http://webdesign.about.com/od/localization/l/blhtmlcodes-ascii.htm
+(defvar web-mode-display-table
+ (let ((table (make-display-table)))
+ (aset table 9 (vector ?\xBB ?\t))
+ (aset table 10 (vector ?\xB6 ?\n))
+ (aset table 32 (vector ?\xB7))
+ table)
+ "Display table used when switching to the whitespace visualization.")
+
+(defvar web-mode-expanders
+ '(("a/" . "<a href=\"|\"></a>")
+ ("b/" . "<table><tbody><tr><td>|</td><td></td></tr></tbody></table>")
+ ("c/" . "<div class=\"|\"></div>")
+ ("d/" . "<div>|</div>")
+ ("e/" . "<em>|</em>")
+ ("f/" . "<form>|</form>")
+ ("g/" . "<strong>|</strong>")
+ ("h/" . "<h1>|</h1>")
+ ("i/" . "<img src=\"|\" />")
+ ("j/" . "<script>|</script>")
+ ("l/" . "<li>|</li>")
+ ("m/" . "<main>|</main>")
+ ("n/" . "<input type=\"|\" />")
+ ("p/" . "<p>|</p>")
+ ("q/" . "<quote>|</quote>")
+ ("s/" . "<span>|</span>")
+ ("t/" . "<td>|</td>")
+ ("u/" . "<ul><li>|</li><li></li></ul>")
+ ("x/" . "<textarea>|</textarea>")
+ ("2/" . "<h2>|</h2>")
+ ("3/" . "<h3>|</h3>")
+ ("?/" . "<?php | ?>")))
+
+(defvar web-mode-engines-auto-pairs
+ '(("angular" . (("{{ " . " }}")))
+ ("artanis" . (("<% " . " %>")
+ ("<%=" . " | %>")
+ ("<@css" . " | %>")
+ ("<@icon" . " | %>")
+ ("<@include" . " | %>")
+ ("<@js" . " | %>")))
+ ("asp" . (("<% " . " %>")))
+ ("aspx" . (("<% " . " %>")
+ ("<%=" . "%>")
+ ("<%#" . "%>")
+ ("<%$" . "%>")
+ ("<%@" . "%>")
+ ("<%:" . "%>")
+ ("<%-" . "- | --%>")))
+ ("blade" . (("{{{" . " | }}}")
+ ("{{ " . " }}")
+ ("{!!" . " | !!}")
+ ("@{{" . " | }}")
+ ("{{-" . "- | --}}")))
+ ("cl-emb" . (("<% " . " %>")
+ ("<%=" . " | %>")
+ ("<%#" . " | %>")))
+ ("ctemplate" . (("{{ " . "| }}")
+ ("{{{" . " | }}}")
+ ("{~{" . " | }}")
+ ("{{~" . "{ | }}}")
+ ("{{!" . "-- | --}}")
+ ("{{^" . "}}")
+ ("{{/" . "}}")
+ ("{{#" . "}}")))
+ ("django" . (("{{ " . " }}")
+ ("{% " . " %}")
+ ("{%-" . " | %}")
+ ("{# " . " #}")))
+ ("elixir" . (("<% " . " %>")
+ ("<%=" . " | %>")
+ ("<%%" . " | %>")
+ ("<%#" . " | %>")))
+ ("ejs" . (("<% " . " %>")
+ ("<%=" . "%>")
+ ("<%#" . "%>")
+ ("<%-" . "%>")))
+ ("erb" . (("<% " . " %>")
+ ("<%=" . " %>")
+ ("<%#" . "%>")
+ ("<%-" . " %>")))
+ ("freemarker" . (("<% " . " %>")
+ ("<#-" . "- | -->")
+ ("${ " . " }")
+ ("[% " . " %]")
+ ("[# " . " #]")
+ ("[#-" . "- | --]")))
+ ("go" . (("{{ " . " }}")
+ ("{{-" . " | -}}")))
+ ("hero" . (("<% " . " %>")
+ ("<%=" . " | %>")
+ ("<%!" . " | %>")
+ ("<%:" . " | %>")
+ ("<%#" . " | %>")
+ ("<%@" . " | %>")
+ ("<%~" . " | %>")
+ ("<%+" . " | %>")))
+ ("jsp" . (("<% " . " %>")
+ ("<%-" . "- | --%>")
+ ("<%=" . "%>")
+ ("<%!" . "%>")
+ ("<%@" . "%>")
+ ("${ " . " }")))
+ ("lsp" . (("<% " . " %>")
+ ("<%%" . " | %>")
+ ("<%#" . " | %>")))
+ ("mako" . (("<% " . " %>")
+ ("<%!" . " | %>")
+ ("${ " . " }")))
+ ("marko" . (("${ " . " }")))
+ ("mason" . (("<% " . " %>")
+ ("<& " . " &>")))
+ ("mojolicious" . (("<% " . " %>")
+ ("<%=" . " | %>")
+ ("<%%" . " | %>")
+ ("<%#" . " | %>")))
+ ("php" . (("<?p" . "hp | ?>")
+ ("<? " . " ?>")
+ ("<?=" . "?>")))
+ ("template-toolkit" . (("[% " . " %]")
+ ("[%-" . " | %]")
+ ("[%#" . " | %]")))
+ ("riot" . (("={ " . " }")))
+ ("underscore" . (("<% " . " %>")))
+ ("vue" . (("{{ " . " }}")))
+ ("web2py" . (("{{ " . " }}")
+ ("{{=" . "}}")))
+ (nil . (("<!-" . "- | -->")))
+ ))
+
+(defvar web-mode-engines-snippets
+ '(("artanis" . (("if" . "<% (if (|) %>\n\n<% ) %>")
+ ("when" . "<% (when (|) %>\n\n<% ) %>")
+ ("unless" . "<% (unless (|) %>\n\n<% ) %>")
+ ("cond" . "<% (cond %>\n<% [(|) %>\n\n<% ] %>\n<% [else %>\n\n<% ] %>\n<% ) %>")
+ ("let" . "<% (let ([|]) %>\n\n<% ) %>")
+ ("let*" . "<% (let* ([|]) %>\n\n<% ) %>")
+ ("do" . "<% (do ([|]) %>\n<% [()] %>\n\n<% ) %>")
+ ("for-each" . "<% (for-each %>\n|\n\n<% ) %>")
+ ("case" . "<% (case | %>\n<% [() %>\n\n<% ] %>\n<% [() %>\n\n<% ] %>\n<% ) %>")))
+ ("ejs" . (("for" . "<% for (|) { %>\n\n<% } %>")
+ ("if" . "<% if (|) { %>\n\n<% } %>")))
+ ("erb" . (("each" . "<% |.each do %>\n\n<% end %>")
+ ("if" . "<% if | %>\n\n<% end %>")
+ ("when" . "<% when | %>\n\n<% end %>")
+ ("unless" . "<% unless | %>\n\n<% end %>")))
+ ("php" . (("if" . "<?php if (|): ?>\n\n<?php endif; ?>")
+ ("while" . "<?php while (|): ?>\n\n<?php endwhile; ?>")
+ ("for" . "<?php for (| ; ; ): ?>\n\n<?php endfor; ?>")
+ ("foreach" . "<?php foreach (| as ): ?>\n\n<?php endforeach; ?>")
+ ("each" . "<?php foreach (| as ): ?>\n\n<?php endforeach; ?>")
+ ("switch" . "<?php switch (|): ?>\n<?php case 1: ?>\n\n<?php break ;?>\n<?php case 2: ?>\n\n<?php break ;?>\n<?php endswitch;?>")))
+ ("django" . (("block" . "{% block | %}\n\n{% endblock %}")
+ ("comment" . "{% comment | %}\n\n{% endcomment %}")
+ ("css" . "{% stylesheet %}\n\n{% endstylesheet %}")
+ ("cycle" . "{% cycle | as %}\n\n{% endcycle %}")
+ ("filter" . "{% filter | %}\n\n{% endfilter %}")
+ ("for" . "{% for | in %}\n\n{% endfor %}")
+ ("if" . "{% if | %}\n\n{% endif %}")
+ ("ifequal" . "{% ifequal | %}\n\n{% endifequal %}")
+ ("ifnotequal" . "{% ifnotequal | %}\n\n{% endifnotequal %}")
+ ("js" . "{% javascript | %}\n\n{% endjavascript %}")
+ ("schema" . "{% javascript | %}\n\n{% endschema %}")
+ ("safe" . "{% safe | %}\n\n{% endsafe %}")))
+ ("mako" . (("if" . "% if |:\n% endif")
+ ("for" . "% for | in :\n% endfor")
+ ("doc" . "<%doc>\n|\n</%doc>")
+ ("inherit" . "<%inherit file=\"|\" />")
+ ("namespace" . "<%namespace name=\"|\" file=\"\" import=\"\"/>")
+ ("block" . "<%block name=\"|\">\n</%block>")))
+ ("template-toolkit" . (("if" . "[% IF | %]\n\n[% END %]")))
+ (nil . (("html5" . "<!doctype html>\n<html>\n<head>\n<title></title>\n<meta charset=\"utf-8\" />\n</head>\n<body>\n|\n</body>\n</html>")
+ ("table" . "<table><tbody>\n<tr>\n<td>|</td>\n<td></td>\n</tr>\n</tbody></table>")
+ ("ul" . "<ul>\n<li>|</li>\n<li></li>\n</ul>")))
+ ))
+
+(defvar web-mode-engine-token-regexps
+ (list
+ '("artanis" . "\"\\|#|\\|;")
+ '("asp" . "//\\|/\\*\\|\"\\|''")
+ '("ejs" . "//\\|/\\*\\|\"\\|'")
+ '("erb" . "\"\\|'\\|#\\|<<[-]?['\"]?\\([[:alnum:]_]+\\)['\"]?")
+ '("lsp" . "\"\\|#|\\|;")
+ '("mako" . "\"\\|'\\|#")
+ '("mason" . "\"\\|'\\|#")
+ '("mojolicious" . "\"\\|'")
+ '("php" . "//\\|/\\*\\|#\\|\"\\|'\\|<<<['\"]?\\([[:alnum:]]+\\)['\"]?")
+ '("python" . "\"\\|'\\|#")
+ '("web2py" . "\"\\|'"))
+ "Engine regexps used to identify tokens (strings / comments) in blocks.")
+
+(defvar web-mode-engine-open-delimiter-regexps
+ (list
+ '("angular" . "{{")
+ '("artanis" . "<%\\|<@\\(css\\|icon\\|include\\|js\\)")
+ '("asp" . "<%\\|</?[[:alpha:]]+:[[:alpha:]]+\\|</?[[:alpha:]]+Template")
+ '("aspx" . "<%.")
+ '("blade" . "{{.\\|{!!\\|@{{\\|@[[:alpha:]]")
+ '("cl-emb" . "<%")
+ '("closure" . "{.\\|/\\*\\| //")
+ '("clip" . "</?c:[[:alpha:]-]+")
+ '("ctemplate" . "[$]?{[{~].")
+ '("django" . "{[#{%]\\|^#")
+ '("dust" . "{.")
+ '("elixir" . "<%")
+ '("ejs" . "<%")
+ '("erb" . "<%\\|^%.")
+ '("expressionengine" . "{.")
+ '("freemarker" . "<%\\|${\\|</?[[:alpha:]]+:[[:alpha:]]\\|</?[@#]\\|\\[/?[@#].")
+ '("go" . "{{.")
+ '("hero" . "<%")
+ '("jsp" . "<%\\|${")
+ '("lsp" . "<%")
+ '("mako" . "</?%\\|${\\|^[ \t]*%.\\|^[ \t]*##")
+ '("marko" . "${")
+ '("mason" . "</?[&%]\\|^%.")
+ '("mojolicious" . "<%\\|^[ \t]*%.")
+ '("php" . "<\\?")
+ '("python" . "<\\?")
+ '("razor" . "@.\\|^[ \t]*}")
+ '("riot" . "{.\\|/// begin script")
+ '("smarty" . "{[[:alpha:]#$/*\"]")
+ '("spip" . "\\[(#REM)\\|(\\|#[A-Z0-9_]\\|{\\|<:")
+ '("template-toolkit" . "\\[%\\(.\\|$\\)\\|%%#")
+ '("underscore" . "<%")
+ '("velocity" . "#[[:alpha:]#*]\\|$[[:alpha:]!{]")
+ '("vue" . "{{\\|[:@][-[:alpha:]]+=\"")
+ '("web2py" . "{{")
+ '("xoops" . "<{[[:alpha:]#$/*\"]")
+ '("svelte" . "{.")
+ )
+ "Engine regexps used to identify blocks.")
+
+(defvar web-mode-normalization-rules
+ '(("tag-case" . "lower-case")
+ ("attr-case" . "lower-case")
+ ("special-chars" . "unicode") ;"unicode" "entities"
+ ("css-indentation" . t)
+ ("smart-apostrophes" . t)
+ ("smart-quotes" . t)
+ ("whitespaces" . t)
+ ("indentation" . t))
+ "Normalization rules")
+
+(defvar web-mode-element-tag-faces
+ (list
+ '("h1" . web-mode-underline-face)
+ '("h2" . web-mode-underline-face)
+ '("h3" . web-mode-underline-face)
+ '("h4" . web-mode-underline-face)
+ '("title" . web-mode-underline-face)
+ '("em" . web-mode-italic-face)
+ '("strong" . web-mode-bold-face)
+ ))
+
+(defvar web-mode-element-content-faces
+ (list
+ '("h1" . web-mode-underline-face)
+ '("h2" . web-mode-underline-face)
+ '("h3" . web-mode-underline-face)
+ '("h4" . web-mode-underline-face)
+ '("title" . web-mode-underline-face)
+ '("em" . web-mode-italic-face)
+ '("strong" . web-mode-bold-face)
+ ))
+
+(defvar web-mode-comment-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "comment" web-mode-extra-keywords))
+ '("FIXME" "TODO" "BUG" "KLUDGE" "WORKAROUND" "OPTIMIZE" "HACK" "REFACTOR" "REVIEW"))))
+
+(defvar web-mode-links
+ '(("\\.\\(png\\|jpe?g\\|gif\\|webp\\)$" "<img src=\"%s\" alt=\"\" />" nil 4)
+ ("\\.svg$" "<object data=\"%s\" type=\"image/svg+xml\"></object>" nil 0)
+ ("\\.js$" "<script type=\"text/javascript\" src=\"%s\"></script>" t 0)
+ ("\\.css$" "<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\" />" t 0)
+ ("\\.html?$" "<a href=\"%s\"></a>" nil 4))
+ "List of elements and extensions for `web-mode-file-link'. It
+consists of a string that contains the regular expression that
+matches the appropriate files, a format string with element that
+contains the link (%s should be put where the path goes,) a bool
+that tells if the element belongs in the <head> element, and
+number of characters to move back if needed (or 0 if point
+shouldn't be moved back.)")
+
+(defvar web-mode-sql-queries
+ (regexp-opt
+ '("SELECT" "INSERT" "UPDATE" "DELETE" "select" "insert" "update" "delete")))
+
+(defvar web-mode-sql-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "sql" web-mode-extra-keywords))
+ '("SELECT" "INSERT" "UPDATE" "DELETE"
+ "FROM" "WHERE" "GROUP BY" "LIKE" "LIMIT" "HAVING" "JOIN" "LEFT" "INNER"
+ "FULL" "OUTER" "VALUES" "ORDER BY" "SEPARATOR" "ASC" "DESC"
+ "AND" "OR" "ON" "WHEN" "ELSE" "END" "THEN"))))
+
+(defvar web-mode-python-constants
+ (regexp-opt
+ (append
+ (cdr (assoc "python" web-mode-extra-constants))
+ '("True" "False" "None" "__debug__" "NotImplemented" "Ellipsis"))))
+
+(defvar web-mode-elixir-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "elixir" web-mode-extra-keywords))
+ '("after" "and" "bc" "case" "catch" "cond" "defcallback" "defdelegate" "defexception" "defgaurdp" "defguard" "defimpl" "defmodule" "defoverridable" "defprotocol" "defrecord" "defrecordp" "defstruct" "do" "else" "end" "exit" "fn" "for" "form_for" "if" "in" "lc" "not" "or" "quote" "raise" "receive" "rescue" "super" "throw" "try" "unless" "unquote" "when" "with"))))
+
+
+(defvar web-mode-elixir-constants
+ (regexp-opt
+ (append
+ (cdr (assoc "elixir" web-mode-extra-constants))
+ '("nil" "true" "false"))))
+
+(defvar web-mode-erlang-constants
+ (regexp-opt
+ (append
+ (cdr (assoc "erlang" web-mode-extra-constants))
+ '("true" "false"))))
+
+(defvar web-mode-erlang-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "erlang" web-mode-extra-keywords))
+ '("else" "if" "do" "end"))))
+
+(defvar web-mode-cl-emb-constants
+ (regexp-opt
+ '("nil" "t" "raw" "escape")))
+
+(defvar web-mode-cl-emb-keywords
+ (regexp-opt
+ '("if" "else" "endif" "unless" "endunless" "var" "repeat"
+ "endrepeat" "loop" "endloop" "include" "call" "with"
+ "endwith" "set" "genloop" "endgenloop" "insert")))
+
+(defvar web-mode-artanis-constants
+ (regexp-opt
+ '("#f" "#t")))
+
+(defvar web-mode-artanis-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "artanis" web-mode-extra-keywords))
+ '("begin" "cut" "cute" "if" "when" "unless" "cond" "case"
+ "do" "quote" "syntax" "lambda" "lambda*" "and" "and-let*"
+ "or" "else" "delay" "receive" "use-modules" "match"
+ "match-lambda" "match-lambda*" "match-let" "match-let*"
+ "match-letrec" "let" "let*" "letrec" "letrec*" "and-let*"
+ "let-syntax" "letrec-syntax" "syntax-rules" "syntax-case"
+ "define" "define-syntax" "define-macro"
+ "define-condition-type" "define-immutable-record-type"
+ "define-record-type" "define-values" "parameterize" "for-each"
+ "require-extension" "set!" "test-approximate" "test-assert"
+ "test-begin" "test-end" "test-eq" "test-equal" "test-eqv"
+ "test-error" "test-group" "test-group-with-cleanup" "test-with-runner"))))
+
+(defvar web-mode-lsp-constants
+ (regexp-opt
+ '("nil" "t")))
+
+(defvar web-mode-lsp-keywords
+ (regexp-opt
+ '("dolist" "let" "while" "cond" "when" "progn" "if"
+ "dotimes" "unless" "lambda"
+ "loop" "for" "and" "or" "in" "do" "defun")))
+
+(defvar web-mode-php-constants
+ (regexp-opt
+ (append
+ (cdr (assoc "php" web-mode-extra-constants))
+ '("TRUE" "FALSE" "NULL" "true" "false" "null"
+ "STR_PAD_LEFT" "STR_PAD_RIGHT"
+ "ENT_COMPAT" "ENT_QUOTES" "ENT_NOQUOTES" "ENT_IGNORE"
+ "ENT_SUBSTITUTE" "ENT_DISALLOWED" "ENT_HTML401" "ENT_XML1"
+ "ENT_XHTML" "ENT_HTML5" "JSON_PRETTY_PRINT"
+ "LIBXML_NOBLANKS"))))
+
+(defvar web-mode-php-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "php" web-mode-extra-keywords))
+ '("abstract" "and" "array" "as" "break" "case" "catch" "class" "clone"
+ "const" "continue" "declare" "default" "die" "do" "echo" "else" "elseif"
+ "empty" "enddeclare" "endfor" "endforeach" "endif" "endswitch" "endwhile"
+ "eval" "exit" "extends" "final" "finally" "fn" "for" "foreach" "function"
+ "global" "goto" "if" "implements" "include" "include_once" "instanceof"
+ "insteadof" "interface" "isset" "list" "namespace" "new" "or" "parent"
+ "print" "private" "protected" "public" "require" "require_once" "return"
+ "self" "static" "switch" "trait" "try" "throw" "unset" "use" "var"
+ "while" "xor" "yield" "yield from"))))
+
+(defvar web-mode-php-types
+ (eval-when-compile
+ (regexp-opt
+ '("array" "bool" "boolean" "callable" "float" "int" "integer"
+ "iterable" "mixed" "object" "resource" "string" "void"))))
+
+(defvar web-mode-css-at-rules
+ (eval-when-compile
+ (regexp-opt
+ '("charset" "import" "media" "page" "font-face"
+ "namespace" "supports" "document"
+ "keyframes" "-moz-keyframes" "-webkit-keyframes"
+ "mixin" "viewport"))))
+
+(defvar web-mode-css-pseudo-classes
+ (eval-when-compile
+ (regexp-opt
+ '("active" "after" "before" "checked" "disabled" "empty" "enabled"
+ "first" "first-child" "first-letter" "first-line" "first-of-type" "focus"
+ "hover" "lang" "last-child" "last-of-type" "left" "link"
+ "not" "nth-child" "nth-last-child" "nth-last-of-type" "nth-of-type"
+ "only-child" "only-of-type"
+ "right" "root" "selection" "target" "visited"))))
+
+(defvar web-mode-python-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "python" web-mode-extra-keywords))
+ '("and" "as" "assert" "break" "class" "continue" "def" "del"
+ "elif" "else" "except" "finally" "for" "from" "global"
+ "if" "import" "in" "is" "lambda" "nonlocal" "not" "or" "pass"
+ "raise" "return" "try" "while" "with" "yield"))))
+
+(defvar web-mode-jsp-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "jsp" web-mode-extra-keywords))
+ '("case" "catch" "do" "else" "end" "false" "for" "function"
+ "if" "in" "include"
+ "new" "package" "page" "private" "protected" "public"
+ "return" "tag" "taglib" "throw" "throws" "true" "try" "void" "while"))))
+
+(defvar web-mode-erb-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "erb" web-mode-extra-keywords))
+ '("alias" "and" "begin" "break" "case" "class" "def" "defined?" "do"
+ "elsif" "else" "end" "ensure" "fail" "for" "if" "in"
+ "module" "next" "not" "or" "redo" "rescue" "retry" "return"
+ "then" "super" "unless" "undef" "until" "when" "while" "yield"
+ "__ENCODING__" "__FILE__" "__LINE__"))))
+
+(defvar web-mode-mason-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "mason" web-mode-extra-keywords))
+ '("and" "base" "close" "die" "each" "else" "elsif" "eval" "exists"
+ "foreach" "grep" "if" "length" "local" "my" "next" "open" "or"
+ "package" "pop" "ref" "return" "stat" "sub" "tie"
+ "undef" "unless" "use" "while"))))
+
+(defvar web-mode-erb-builtins
+ (regexp-opt
+ (append
+ (cdr (assoc "erb" web-mode-extra-builtins))
+
+ '("__callee__" "__dir__" "__method__"
+ "abort" "at_exit" "autoload" "autoload?"
+ "binding" "block_given?" "caller" "catch"
+ "eval" "exec" "exit" "exit!" "fail" "fork" "format"
+ "lambda" "load" "loop" "open"
+ "p" "print" "printf" "proc" "putc" "puts"
+ "raise" "rand" "readline" "readlines" "require" "require_relative"
+ "sleep" "spawn" "sprintf" "srand" "syscall" "system"
+ "throw" "trap" "warn"
+ "alias_method" "attr" "attr_accessor" "attr_reader" "attr_writer"
+ "define_method" "extend" "include" "module_function"
+ "prepend" "private" "protected" "public"
+ "refine" "using"
+
+ "error_message_on" "error_messages_for" "form" "input"
+ "auto_discovery_link_tag" "image_tag" "javascript_include_tag"
+ "stylesheet_link_tag" "image_path" "path_to_image"" "
+ "javascript_path" "path_to_javascript" "register_javascript_expansion"
+ "register_javascript_include_default" "register_stylesheet_expansion"
+ "stylesheet_path" "path_to_stylesheet" "atom_feed" "entry" "updated"
+ "benchmark" "cache" "capture" "content_for" "distance_of_time_in_words"
+ "distance_of_time_in_words_to_now" "time_ago_in_words" "date_select"
+ "datetime_select" "time_select" "select_date" "select_datetime"
+ "select_day" "select_hour" "select_minute" "select_month" "select_second"
+ "select_time" "select_year" "debug"
+ "check_box" "fields_for" "file_field" "form_for" "hidden_field"
+ "label" "password_field" "radio_button" "text_area" "text_field"
+ "check_box_tag" "field_set_tag" "file_field_tag" "form_with" "form_tag"
+ "hidden_field_tag" "image_submit_tag" "label_tag" "password_field_tag"
+ "radio_button_tag" "select_tag" "submit_tag" "text_area_tag"
+ "text_field_tag"
+ "collection_select" "country_options_for_select" "country_select"
+ "option_groups_from_collection_for_select" "options_for_select"
+ "options_from_collection_for_select" "select"
+ "time_zone_options_for_select"
+ "time_zone_select" "button_to_function" "define_javascript_functions"
+ "escape_javascript" "javascript_tag" "link_to_function"" "
+ "number_to_currency" "number_to_human_size" "number_to_percentage"
+ "number_to_phone" "number_with_delimiter" "number_with_precision"
+ "evaluate_remote_response" "form_remote_for" "form_remote_tag"
+ "link_to_remote" "observe_field" "observe_field"
+ "periodically_call_remote"
+ "remote_form_for" "remote_function" "submit_to_remote" "update_page"
+ "update_page_tag" "dom_class" "dom_id" "partial_path" "sanitize"
+ "sanitize_css" "strip_links" "strip_tags"
+ "cdata_section" "content_tag" "escape_once" "tag"
+ "auto_link" "concat" "cycle" "excerpt" "highlight" "markdown" "pluralize"
+ "reset_cycle" "simple_format" "textilize" "textilize_without_paragraph"
+ "truncate" "word_wrap" "button_to" "current_page?" "link_to" "link_to_if"
+ "link_to_unless" "link_to_unless_current" "mail_to" "url_for"
+ "action_name" "atom_feed" "audio_path" "audio_tag"
+ "content_tag_for" "controller" "controller_name" "action_name"
+ "controller_path" "convert_to_model" "cookies" "csrf_meta_tag"
+ "csrf_meta_tags" "headers"
+ "current_cycle" "div_for" "email_field" "email_field_tag"
+ "favicon_link_tag" "flash" "l" "button_tag"
+ "grouped_collection_select" "grouped_options_for_select"
+ "image_alt" "j" "javascript_cdata_section"
+ "localize" "logger" "number_field"
+ "number_field_tag" "number_to_human" "params" "path_to_audio"
+ "path_to_video" "phone_field" "phone_field_tag" "provide"
+ "range_field" "range_field_tag" "raw" "render" "request"
+ "request_forgery_protection_token" "response" "safe_concat"
+ "safe_join" "search_field" "search_field_tag"
+ "session" "t" "telephone_field" "telephone_field_tag"
+ "time_tag" "translate" "url_field" "url_field_tag"
+ "url_options" "video_path" "video_tag" "simple_form_for"
+ "javascript_pack_tag" "stylesheet_pack_tag" "csp_meta_tag"
+
+ ))))
+
+(defvar web-mode-asp-constants
+ (regexp-opt
+ (append
+ (cdr (assoc "asp" web-mode-extra-constants))
+ '("adAsyncExecute" "adAsyncFetch" "adAsyncFetchNonBlocking" "adCmdFile"
+ "adCmdStoredProc" "adCmdTable" "adCmdTableDirect" "adCmdText" "adCmdUnknown"
+ "adCmdUnspecified" "adExecuteNoRecords" "adExecuteRecord" "adExecuteStream"
+ "adLockBatchOptimistic" "adLockOptimistic" "adLockPessimistic"
+ "adLockReadOnly" "adLockUnspecified" "adOpenDynamic" "adOpenForwardOnly"
+ "adOpenKeyset" "adOpenStatic" "adOpenUnspecified" "adOptionUnspecified"
+ "Empty" "Nothing" "Null" "True" "False"
+ "vbBack" "vbCr" "vbCrLf" "vbFormFeed" "vbLf" "vbNewLine" "vbNullChar"
+ "vbNullString" "vbObjectError" "vbScript" "vbTab" "vbVerticalTab"))))
+
+(defvar web-mode-asp-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "asp" web-mode-extra-keywords))
+ '("Abs" "And" "Array" "Asc" "Atn"
+ "CBool" "CByte" "CCur" "CDate" "CDbl" "CInt" "CLng" "CSng" "CStr"
+ "Call" "Case" "Chr" "Class" "Const" "Cos" "CreateObject"
+ "Date" "DateAdd" "DateDiff" "DatePart" "DateSerial" "DateValue"
+ "Day" "Dim" "Do"
+ "Each" "Else" "ElseIf" "End" "Erase" "Err" "Eval" "Exit" "Exp"
+ "Explicit"
+ "Filter" "Fix" "For" "FormatCurrency" "FormatDateTime"
+ "FormatNumber" "FormatPercent" "Function"
+ "GetLocale" "GetObject" "GetRef" "Hex" "Hour"
+ "If" "In" "InStr" "InStrRev" "InputBox" "Int" "IsArray" "IsDate"
+ "IsEmpty" "IsNull" "IsNumeric" "IsObject" "Join"
+ "LBound" "LCase" "LTrim" "Language" "Left" "Len" "Let"
+ "LoadPicture" "Log" "Loop"
+ "Mid" "Minute" "Month" "MonthName" "MsgBox"
+ "New" "Next" "Not" "Now"
+ "Oct" "On" "Option" "Or" "Preserve" "Private" "Public"
+ "RGB" "RTrim" "Redim" "Rem" "Replace" "Right" "Rnd" "Round"
+ "ScriptEngine" "ScriptEngineBuildVersion"
+ "ScriptEngineMajorVersion" "ScriptEngineMinorVersion"
+ "Second" "Select" "Set" "SetLocale" "Sgn" "Sin" "Space" "Split"
+ "Sqr" "StrComp" "StrReverse" "String" "Sub"
+ "Tan" "Then" "Time" "TimeSerial" "TimeValue" "Timer" "To" "Trim"
+ "TypeName"
+ "UBound" "UCase" "Until" "VarType"
+ "Weekday" "WeekdayName" "Wend" "With" "While" "Year"))))
+
+(defvar web-mode-asp-types
+ (regexp-opt
+ (append
+ (cdr (assoc "asp" web-mode-extra-types))
+ '("Application" "ASPError" "Request" "Response" "Server" "Session"))))
+
+(defvar web-mode-aspx-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "aspx" web-mode-extra-keywords))
+ '("case" "catch" "do" "else" "end" "for" "foreach" "function"
+ "if" "in" "include" "new" "package" "page" "return"
+ "tag" "throw" "throws" "try" "while"))))
+
+(defvar web-mode-smarty-keywords
+ (regexp-opt '("as")))
+
+(defvar web-mode-velocity-keywords
+ (eval-when-compile
+ (regexp-opt '("in" "true" "false"))))
+
+(defvar web-mode-freemarker-keywords
+ (eval-when-compile
+ (regexp-opt '("as" "list"))))
+
+(defvar web-mode-go-keywords
+ (eval-when-compile
+ (regexp-opt
+ '("const" "define" "else" "end"
+ "for" "func" "if" "import"
+ "pipeline" "range" "return" "struct"
+ "template" "type" "var" "with"))))
+
+(defvar web-mode-go-functions
+ (eval-when-compile
+ (regexp-opt
+ '("and" "call" "ge" "html" "index" "js" "len" "not" "or"
+ "print" "printf" "println" "urlquery" "where"))))
+
+(defvar web-mode-go-types
+ (regexp-opt
+ (append
+ (cdr (assoc "go" web-mode-extra-types))
+ '("int" "string"))))
+
+(defvar web-mode-closure-keywords
+ (eval-when-compile
+ (regexp-opt '("in" "and" "not" "or"))))
+
+(defvar web-mode-svelte-keywords
+ (regexp-opt '("as")))
+
+(defvar web-mode-django-control-blocks
+ (append
+ (cdr (assoc "django" web-mode-extra-control-blocks))
+ '(
+
+ "assets" "autoescape"
+ "block" "blocktrans"
+ "cache" "call" "capture" "comment"
+ "draw"
+ "embed"
+ "filter" "for" "foreach" "form"
+ "if" "ifchanged" "ifequal" "ifnotequal"
+ "macro"
+ "random" "raw"
+ "safe" "sandbox" "spaceless"
+ "tablerow"
+ "unless"
+ "verbatim"
+ "with"
+
+ "endassets" "endautoescape"
+ "endblock" "endblocktrans"
+ "endcache" "endcall" "endcapture" "endcomment"
+ "draw"
+ "endembed"
+ "endfilter" "endfor" "endforeach" "endform"
+ "endif" "endifchanged" "endifequal" "endifnotequal"
+ "endmacro"
+ "endrandom" "endraw"
+ "endsafe" "endsandbox" "endspaceless"
+ "endtablerow"
+ "endunless"
+ "endverbatim"
+ "endwith"
+
+ ;; "set" "endset" ;#504
+
+ "csrf_token" "cycle" "debug"
+ "elif" "else" "elseif" "elsif" "empty" "extends"
+ "firstof" "include" "load" "lorem" "now" "regroup" "ssi"
+ "trans" "templatetag" "url" "widthratio"
+
+ ;; #805
+ "graph" "endgraph"
+ "javascript" "endjavascript"
+ "schema" "endschema"
+ "stylesheet" "endstylesheet"
+
+ )))
+
+(defvar web-mode-django-control-blocks-regexp
+ (regexp-opt web-mode-django-control-blocks t))
+
+(defvar web-mode-django-keywords
+ (eval-when-compile
+ (regexp-opt
+ '("and" "as" "assign"
+ "break"
+ "cache" "call" "case" "context" "continue"
+ "do"
+ "flush" "from"
+ "ignore" "import" "in" "is"
+ "layout" "load"
+ "missing"
+ "none" "not"
+ "or"
+ "pluralize"
+ "random"
+ "set" ;#504
+ "unless" "use"
+ "var"
+ ))))
+
+(defvar web-mode-django-types
+ (eval-when-compile
+ (regexp-opt '("null" "false" "true"))))
+
+(defvar web-mode-blade-control-blocks
+ (append
+ (cdr (assoc "blade" web-mode-extra-control-blocks))
+ '("component" "foreach" "forelse" "for" "if" "section" "slot" "switch" "unless" "while")
+ ))
+
+(defvar web-mode-blade-control-blocks-regexp
+ (regexp-opt web-mode-blade-control-blocks t))
+
+(defvar web-mode-directives
+ (eval-when-compile
+ (regexp-opt
+ '("include" "page" "taglib"
+ "Assembly" "Control" "Implements" "Import"
+ "Master" "OutputCache" "Page" "Reference" "Register"))))
+
+(defvar web-mode-template-toolkit-keywords
+ (regexp-opt
+ '("block" "call" "case" "catch" "clear" "default" "do"
+ "else" "elsif" "end" "filter" "final" "for"
+ "foreach" "get" "if" "in" "include" "insert" "is" "last"
+ "macro" "meta" "or" "perl" "process" "rawperl" "return"
+ "set" "stop" "switch" "tags" "throw" "try"
+ "unless" "use" "while" "wrapper")))
+
+(defvar web-mode-perl-keywords
+ (regexp-opt
+ '("__DATA__" "__END__" "__FILE__" "__LINE__" "__PACKAGE__"
+ "and" "cmp" "continue" "CORE" "do" "else" "elsif" "eq" "exp"
+ "for" "foreach" "ge" "gt" "if" "le" "lock" "lt" "m" "ne" "no"
+ "or" "package" "q" "qq" "qr" "qw" "qx" "s" "sub"
+ "tr" "unless" "until" "while" "xor" "y"
+ "my" "use" "print" "say")))
+
+(defvar web-mode-javascript-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "javascript" web-mode-extra-keywords))
+ '("as" "async" "await" "break" "case" "catch" "class" "const" "continue"
+ "debugger" "default" "delete" "do" "else" "enum" "eval"
+ "export" "extends" "finally" "for" "from" "function" "get" "if"
+ "implements" "import" "in" "instanceof" "interface" "let"
+ "new" "of" "package" "private" "protected" "public"
+ "return" "set" "static" "super" "switch"
+ "throw" "try" "type" "typeof" "var" "void" "while" "with" "yield"))))
+
+(defvar web-mode-javascript-constants
+ (regexp-opt
+ '("false" "null" "undefined" "Infinity" "NaN" "true" "arguments" "this")))
+
+(defvar web-mode-razor-keywords
+ (regexp-opt
+ (append
+ (cdr (assoc "razor" web-mode-extra-keywords))
+ '("false" "true" "foreach" "if" "else" "in" "var" "for" "display"
+ "match" "case" "to"
+ "Html"))))
+
+(defvar web-mode-selector-font-lock-keywords
+ (list
+ '("$[[:alnum:]-]+" 0 'web-mode-css-variable-face)
+ (cons (concat "@\\(" web-mode-css-at-rules "\\)\\_>")
+ '(0 'web-mode-css-at-rule-face))
+ '("\\_<\\(all\|braille\\|embossed\\|handheld\\|print\\|projection\\|screen\\|speech\\|tty\\|tv\\|and\\|or\\)\\_>"
+ 1 'web-mode-keyword-face)
+ '("[^,]+" 0 'web-mode-css-selector-face)
+ (cons (concat ":\\([ ]*[[:alpha:]][^,{]*\\)") '(0 'web-mode-css-pseudo-class-face t t))
+ ))
+
+(defvar web-mode-declaration-font-lock-keywords
+ (list
+ '("--[[:alnum:]-]+" 0 'web-mode-css-variable-face)
+ '("$[[:alnum:]-]+" 0 'web-mode-css-variable-face)
+ (cons (concat "@\\(" web-mode-css-at-rules "\\)\\_>") '(1 'web-mode-css-at-rule-face))
+ '("\\([[:alpha:]-]+\\)[ ]?:" 0 'web-mode-css-property-name-face)
+ '("\\([[:alpha:]-]+\\)[ ]?(" 1 'web-mode-css-function-face)
+ '("#[[:alnum:]]\\{1,6\\}" 0 'web-mode-css-color-face t t)
+ '("![ ]?important" 0 'web-mode-css-priority-face t t)
+ '("\\([^,]+\\)[ ]+{" 1 'web-mode-css-selector-face)
+ '("'[^']*'\\|\"[^\"]*\"" 0 'web-mode-string-face t t)
+ ))
+
+(defvar web-mode-html-font-lock-keywords
+ (list
+ '("</?[[:alnum:]]+[ >]\\|>" 0 'web-mode-html-tag-face t)
+ '(" \\([[:alnum:]-]+=\\)\\(\"[^\"]+\"\\)"
+ (1 'web-mode-html-attr-name-face)
+ (2 'web-mode-html-attr-value-face))
+ ))
+
+;; voir https://www.gnu.org/software/emacs/manual/html_node/elisp/Search_002dbased-Fontification.html
+(defvar web-mode-javascript-font-lock-keywords
+ (list
+ '("@\\([[:alnum:]_]+\\)\\_>" 0 'web-mode-keyword-face)
+ '("\\([[:alnum:]]+\\)[`]" 0 'web-mode-preprocessor-face)
+ (cons (concat "\\_<\\(function\\*\\)\\_>") '(1 'web-mode-keyword-face))
+ (cons (concat "\\([ \t}{(]\\|^\\)\\(" web-mode-javascript-keywords "\\)\\_>") '(2 'web-mode-keyword-face))
+ (cons (concat "\\_<\\(" web-mode-javascript-constants "\\)\\_>") '(0 'web-mode-constant-face))
+ '("\\_<\\([$]\\)(" 1 'web-mode-type-face)
+ '("\\_<\\(new\\|instanceof\\|class\\|extends\\) \\([[:alnum:]_.]+\\)\\_>" 2 'web-mode-type-face)
+ '("\\_<\\([[:alnum:]_]+\\):[ ]*function[ ]*(" 1 'web-mode-function-name-face)
+ '("\\_<\\(function\\|get\\|set\\)[ ]+\\([[:alnum:]_]+\\)"
+ (1 'web-mode-keyword-face)
+ (2 'web-mode-function-name-face))
+ '("\\([[:alnum:]_]+\\)[ ]*([^)]*)[ \n]*{" 1 'web-mode-function-name-face)
+ '("([ ]*\\([[:alnum:]_]+\\)[ ]*=>" 1 'web-mode-function-name-face)
+ '("[ ]*\\([[:alnum:]_]+\\)[ ]*=[ ]*([^)]*)[ ]*=>[ ]*{" 1 'web-mode-function-name-face)
+ '("\\_<\\(var\\|let\\|const\\)[ ]+\\([[:alnum:]_]+\\)" 2 'web-mode-variable-name-face)
+ '("({" "\\([[:alnum:]_]+\\)[, }]+" nil nil (1 'web-mode-variable-name-face)) ;#738
+ '("\\([[:alnum:]_]+\\)[ ]*=> [{(]" 1 'web-mode-variable-name-face)
+ ;; #989
+ ;; '("\\(function\\|[,=]\\|^\\)[ ]*("
+ ;; ("\\([[:alnum:]_]+\\)\\([ ]*=[^,)]*\\)?[,)]" nil nil (1 'web-mode-variable-name-face)))
+ '("\\([[:alnum:]_]+\\):" 1 'web-mode-variable-name-face)
+ '("\\_<\\([[:alnum:]_-]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("[a-zA-Z]<\\([a-zA-Z]+\\)[,>]" 1 'web-mode-type-face)
+ ))
+
+(defvar web-mode-stylus-font-lock-keywords
+ (list
+ '("^[ \t]*\\([[:alnum:]().-]+\\)$" 1 'web-mode-css-selector-face)
+ '("^[ \t]*\\([[:alnum:]-]+[ ]*:\\)" 1 'web-mode-css-property-name-face)
+ ))
+
+(defvar web-mode-sass-font-lock-keywords
+ (list
+ '("^[ \t]*\\([[:alnum:]().-]+\\|&:\\(before\\|after\\)\\)$" 1 'web-mode-css-selector-face)
+ '("^[ \t]*\\([[:alnum:]-]+[ ]*:\\)" 1 'web-mode-css-property-name-face)
+ ))
+
+(defvar web-mode-pug-font-lock-keywords
+ (list
+ '("^[ \t]*\\(#?[[:alnum:].-]+\\)" 1 'web-mode-css-selector-face)
+ ;;'("^[ \t]*\\(#[[:alnum:]-]+\\)" 0 'web-mode-css-selector-face)
+ '(" \\([@:]?\\sw+[ ]?=\\)" 1 'web-mode-param-name-face)
+ ))
+
+(defvar web-mode-sql-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-sql-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ '("\\_<\\([[:alnum:]_-]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ ))
+
+(defvar web-mode-markdown-font-lock-keywords
+ (list
+ '("^[ ]*[*].*$" 0 'web-mode-variable-name-face)
+ '("^[ ]*#.*$" 0 'web-mode-comment-face)
+ ))
+
+(defvar web-mode-html-tag-font-lock-keywords
+ (list
+ '("\\(</?\\)\\([[:alnum:]]+\\)"
+ (1 'web-mode-html-tag-bracket-face)
+ (2 'web-mode-html-tag-face))
+ '("\"[^\"]*\"" 0 'web-mode-html-attr-value-face)
+ '("\\([[:alnum:]]+\\)" 1 'web-mode-html-attr-name-face)
+ '("/?>" 0 'web-mode-html-tag-bracket-face)
+ ))
+
+(defvar web-mode-dust-font-lock-keywords
+ (list
+ '("{[#:/?@><+^]\\([[:alpha:]_.]+\\)" 1 'web-mode-block-control-face)
+ '(":\\([[:alpha:]]+\\)" 1 'web-mode-keyword-face)
+ '("\\_<\\([[:alnum:]_]+=\\)\\(\"[^\"]*\"\\|[[:alnum:]_]*\\)"
+ (1 'web-mode-block-attr-name-face)
+ (2 'web-mode-block-attr-value-face))
+ '("\\\([[:alnum:]_.]+\\)" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-expressionengine-font-lock-keywords
+ (list
+ '("{/?\\([[:alpha:]_]+:[[:alpha:]_:]+\\|if\\)" 1 'web-mode-block-control-face)
+ '(":\\([[:alpha:]_]+\\)" 1 'web-mode-keyword-face)
+ '(" {\\([[:alpha:]_]+\\)}" 1 'web-mode-keyword-face t)
+ '("\\_<\\([[:alnum:]_]+=\\)\\(\"[^\"]*\"\\|[[:alnum:]_]*\\)"
+ (1 'web-mode-block-attr-name-face)
+ (2 'web-mode-block-attr-value-face))
+ '("\\\([[:alnum:]_.]+\\)" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-svelte-font-lock-keywords
+ (list
+ (cons (concat "[ ]\\(" web-mode-svelte-keywords "\\)[ ]") '(1 'web-mode-keyword-face))
+ '("{[#:/@]\\([[:alpha:]_.]+\\)" 1 'web-mode-block-control-face)
+ '("\\_<\\([[:alnum:]_]+=\\)\\(\"[^\"]*\"\\|[[:alnum:]_]*\\)"
+ (1 'web-mode-block-attr-name-face)
+ (2 'web-mode-block-attr-value-face))
+ '("\\\([[:alnum:]_.]+\\)" 0 'web-mode-variable-name-face)
+ '("\\_<\\([$]\\)\\([[:alnum:]_]+\\)" (1 'web-mode-constant-face) (2 'web-mode-variable-name-face))
+ ))
+
+(defvar web-mode-template-toolkit-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-template-toolkit-keywords "\\)\\_>") '(1 'web-mode-keyword-face))
+ '("\\\([[:alpha:]][[:alnum:]_]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("\\\([[:alpha:]][[:alnum:]_]+\\)" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-smarty-font-lock-keywords
+ (list
+ (cons (concat "[ ]\\(" web-mode-smarty-keywords "\\)[ ]") '(1 'web-mode-keyword-face))
+ '("{/?\\([[:alpha:]_]+\\)" 1 'web-mode-block-control-face)
+ '("\\([}{]\\)" 0 'web-mode-block-delimiter-face)
+ '("\\_<\\([$]\\)\\([[:alnum:]_]+\\)" (1 nil) (2 'web-mode-variable-name-face))
+ '("\\_<\\(\\sw+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '(" \\(\\sw+[ ]?=\\)" 1 'web-mode-param-name-face)
+ '(" \\(\\sw+\\)[ }]" 1 'web-mode-param-name-face)
+ '("|\\([[:alnum:]_]+\\)" 1 'web-mode-function-call-face)
+ '("\\(->\\)\\(\\sw+\\)" (1 nil) (2 'web-mode-variable-name-face))
+ '("[.]\\([[:alnum:]_-]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("[.]\\([[:alnum:]_]+\\)" 1 'web-mode-variable-name-face)
+ '("#\\([[:alnum:]_]+\\)#" 1 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-velocity-font-lock-keywords
+ (list
+ '("#{?\\([[:alpha:]_]+\\)\\_>" (1 'web-mode-block-control-face))
+ (cons (concat "\\_<\\(" web-mode-velocity-keywords "\\)\\_>") '(1 'web-mode-keyword-face t t))
+ '("#macro([ ]*\\([[:alpha:]]+\\)[ ]+" 1 'web-mode-function-name-face)
+ '("\\(def\\|define\\) \\([[:alnum:]_-]+\\)(" 2 'web-mode-function-name-face)
+ '("[.]\\([[:alnum:]_-]+\\)" 1 'web-mode-variable-name-face)
+ '("\\_<\\($[!]?[{]?\\)\\([[:alnum:]_-]+\\)[}]?" (1 nil) (2 'web-mode-variable-name-face))
+ ))
+
+(defvar web-mode-mako-tag-font-lock-keywords
+ (list
+ '("</?%\\([[:alpha:]:]+\\)" 1 'web-mode-block-control-face)
+ '("\\_<\\([[:alpha:]]+=\\)\\(\"[^\"]*\"\\)"
+ (1 'web-mode-block-attr-name-face t t)
+ (2 'web-mode-block-attr-value-face t t))
+ ))
+
+(defvar web-mode-mako-block-font-lock-keywords
+ (list
+ '("\\_<\\(\\sw+\\)[ ]?(" 1 'web-mode-function-call-face)
+ (cons (concat "\\_<\\(" web-mode-python-constants "\\)\\_>") '(1 'web-mode-constant-face))
+ (cons (concat "\\_<\\(" web-mode-python-keywords "\\)\\_>") '(1 'web-mode-keyword-face))
+ (cons (concat "\\_<\\(endfor\\|endif\\|endwhile\\)\\_>") '(1 'web-mode-keyword-face))
+ ))
+
+(defvar web-mode-web2py-font-lock-keywords
+ (list
+ '("\\_<\\(\\sw+\\)[ ]?(" 1 'web-mode-function-call-face)
+ (cons (concat "\\_<\\(" web-mode-python-constants "\\)\\_>") '(1 'web-mode-constant-face))
+ (cons (concat "\\_<\\(" web-mode-python-keywords "\\)\\_>") '(1 'web-mode-keyword-face))
+ (cons (concat "\\_<\\(block\\|extend\\|super\\|end\\|include\\)\\_>") '(1 'web-mode-keyword-face))
+ ))
+
+(defvar web-mode-django-expr-font-lock-keywords
+ (list
+ '("|[ ]?\\([[:alpha:]_]+\\)\\_>" 1 'web-mode-filter-face)
+ (cons (concat "\\_<\\(" web-mode-django-types "\\)\\_>") '(1 'web-mode-type-face))
+ '("\\_<\\([[:alpha:]_]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("[[:alnum:]_]+" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-django-code-font-lock-keywords
+ (list
+ '("{%[ ]*\\(set\\)[ ]+\\([[:alpha:]]+\\)[ ]*%}"
+ (1 'web-mode-block-control-face)
+ (2 'web-mode-variable-name-face))
+ (cons (concat "\\({%\\|#\\)[ ]*\\(" web-mode-django-control-blocks-regexp "\\)[ %]") '(2 'web-mode-block-control-face))
+ '("\\({%\\|#\\)[ ]*\\(end[[:alpha:]]+\\)\\_>" 2 'web-mode-block-control-face) ;#504
+ (cons (concat "\\_<\\(" web-mode-django-keywords "\\)\\_>") '(1 'web-mode-keyword-face))
+ (cons (concat "\\_<\\(" web-mode-django-types "\\)\\_>") '(1 'web-mode-type-face))
+ '("|[ ]?\\([[:alpha:]_]+\\)\\_>" 1 'web-mode-function-call-face)
+ '("\\_<\\([[:alpha:]_]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("[[:alnum:]_.]+" 0 'web-mode-variable-name-face)
+ '("[[:alnum:]_]+\\([.][[:alnum:]_]+\\)+" 0 'web-mode-variable-name-face t t)
+ ))
+
+(defvar web-mode-ctemplate-font-lock-keywords
+ (list
+ '("{[~]?{[#/>^]?[ ]*\\([[:alnum:]_.-]+\\)" 1 'web-mode-block-control-face)
+ '("[ \t]+\\([[:alnum:]_-]+\\)="
+ (1 'web-mode-block-attr-name-face))
+ '("\"[^\"]+\"" 0 'web-mode-block-string-face)
+ ))
+
+(defvar web-mode-razor-font-lock-keywords
+ (list
+ '("@\\([[:alnum:]_.]+\\)[ ]*[({]" 1 'web-mode-block-control-face)
+ (cons (concat "\\_<\\(" web-mode-razor-keywords "\\)\\_>") '(1 'web-mode-keyword-face))
+ '("\\_<\\(String\\)\\_>" 1 'web-mode-type-face)
+ '("\\([[:alnum:]]+:\\)" 1 'web-mode-symbol-face)
+ '("\\(@[[:alnum:]_.]+\\)" 1 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-riot-font-lock-keywords
+ (list
+ '("\\(parent\\|opts\\|tags\\|this\\)\\.\\([[:alnum:]_.]+\\)"
+ (1 'web-mode-constant-face)
+ (2 'web-mode-variable-name-face))
+ '("\\([[:alnum:]_.]+\\)" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-closure-font-lock-keywords
+ (list
+ '("{\\([@/]?[[:alpha:]]+[?]?\\)" 1 'web-mode-block-control-face)
+ '("{[@]?param[?]?[ ]+\\([[:alnum:]]+[:]?\\)" 1 'web-mode-symbol-face)
+ '("\\_<\\(true\\|false\\|null\\)\\_>" 1 'web-mode-type-face)
+ '("\\\_<[[:alpha:]]+:[ ]+\\([[:alpha:]]+\\)" 1 'web-mode-type-face)
+ (cons (concat "\\_<\\(" web-mode-closure-keywords "\\)\\_>") '(1 'web-mode-keyword-face))
+ '("{\\(alias\\|call\\|delcall\\|delpackage\\|deltemplate\\|namespace\\|template\\)[ ]+\\([[:alnum:].]+\\)" 2 'web-mode-constant-face)
+ '("\\(allowemptydefault\\|data\\|desc\\|meaning\\|autoescape\\|private\\|variant\\)=" 0 'web-mode-block-attr-name-face)
+ '("|\\([[:alpha:]]+\\)" 1 'web-mode-function-call-face)
+ '("\\_<\\([[:alnum:]]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("$\\([[:alnum:]._]+\\)" 1 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-go-font-lock-keywords
+ (list
+ '("{{[-]?[ ]*\\([[:alpha:]]+\\)" 1 'web-mode-block-control-face)
+ '("\\_<func \\([[:alnum:]]+\\)" 1 'web-mode-function-name-face)
+ '("\\_<type \\([[:alnum:]]+\\)" 1 'web-mode-type-face)
+ (cons (concat "\\_<\\(" web-mode-go-types "\\)\\_>") '(0 'web-mode-type-face))
+ (cons (concat "\\_<\\(" web-mode-go-keywords "\\)\\_>") '(1 'web-mode-keyword-face))
+ (cons (concat "\\_<\\(" web-mode-go-functions "\\)\\_>") '(1 'web-mode-function-call-face))
+ '("[$.]\\([[:alnum:]_]+\\)" 1 'web-mode-variable-name-face t t)
+ '("|[ ]?\\([[:alpha:]_]+\\)\\_>" 1 'web-mode-filter-face)
+ ))
+
+(defvar web-mode-expression-font-lock-keywords
+ (list
+ '("[[:alpha:]_]" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-angular-font-lock-keywords
+ (list
+ '("[[:alpha:]_]" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-underscore-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-javascript-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ '("\\_<\\(_\.[[:alpha:]]+\\)(" 1 'web-mode-function-call-face)
+ '("\\_<new \\([[:alnum:]_.]+\\)\\_>" 1 'web-mode-type-face)
+ '("\\_<\\([[:alnum:]_]+\\):[ ]*function[ ]*(" 1 'web-mode-function-name-face)
+ '("\\_<\\(var\\)\\_>[ ]+\\([[:alnum:]_]+\\)"
+ (1 'web-mode-keyword-face)
+ (2 'web-mode-variable-name-face))
+ ))
+
+(defvar web-mode-vue-font-lock-keywords
+ (list
+ '("\\_<\\([[:alnum:]_-]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("[[:alpha:]_]" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-engine-tag-font-lock-keywords
+ (list
+ '("</?\\([[:alpha:]]+\\(?:Template\\|[:.][[:alpha:]-]+\\)\\)" 1 'web-mode-block-control-face)
+ '("\\_<\\([[:alpha:]-]+=\\)\\(\"[^\"]*\"\\)"
+ (1 'web-mode-block-attr-name-face t t)
+ (2 'web-mode-block-attr-value-face t t))
+ '("\\_<\\([[:alpha:]-]+=\\)\\('[^']*\'\\)"
+ (1 'web-mode-block-attr-name-face t t)
+ (2 'web-mode-block-attr-value-face t t))
+ ))
+
+(defvar web-mode-jsp-font-lock-keywords
+ (list
+ '("\\(throws\\|new\\|extends\\)[ ]+\\([[:alnum:].]+\\)" 2 'web-mode-type-face)
+ (cons (concat "\\_<\\(" web-mode-jsp-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ '("\\(public\\|private\\)[ ]+\\([[:alpha:]]+\\)[ ]+\\([[:alnum:]._]+\\)[ ]?("
+ (2 'web-mode-type-face)
+ (3 'web-mode-function-name-face))
+ '("\\_<\\([[:alnum:]._]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("@\\(\\sw*\\)" 1 'web-mode-variable-name-face)
+ '("\\_<\\([[:alnum:].]+\\)[ ]+[{[:alpha:]]+" 1 'web-mode-type-face)
+ ))
+
+(defvar web-mode-asp-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-asp-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ (cons (concat "\\_<\\(" web-mode-asp-types "\\)\\_>") '(0 'web-mode-type-face))
+ (cons (concat "\\_<\\(" web-mode-asp-constants "\\)\\_>") '(0 'web-mode-constant-face))
+ '("\\(Class\\|new\\) \\([[:alnum:]_]+\\)" 2 'web-mode-type-face)
+ '("Const \\([[:alnum:]_]+\\)" 1 'web-mode-constant-face)
+ '("\\_<dim\\_>"
+ (0 'web-mode-keyword-face)
+ ("[[:alnum:]_]+" nil nil (0 'web-mode-variable-name-face)))
+ '("\\_<\\(public\\|private\\|sub\\|function\\)\\_> \\([[:alnum:]_]+\\)[ ]*(" 2 'web-mode-function-name-face)
+ '("\\_<\\(public\\|private\\|dim\\)\\_> \\([[:alnum:]_]+\\)" 2 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-aspx-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-aspx-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ '("\\_<\\([[:alnum:].]+\\)[ ]+[[:alpha:]]+" 1 'web-mode-type-face)
+ ))
+
+(defvar web-mode-uel-font-lock-keywords
+ (list
+ '("[$#{]{\\|}" 0 'web-mode-preprocessor-face)
+ '("\\([[:alpha:]_]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("|[ ]*\\(trim\\|x\\|u\\)" 1 'web-mode-function-call-face)
+ '("[[:alpha:]_]" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-php-var-interpolation-font-lock-keywords
+ (list
+ '("[[:alpha:]_]" 0 'web-mode-variable-name-face)
+ '("\".+\"\\|'.*'" 0 'web-mode-string-face)
+ ))
+
+(defvar web-mode-marko-font-lock-keywords
+ (list
+ '("[[:alnum:]_]+" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-freemarker-square-font-lock-keywords
+ (list
+ '("\\[/?[#@]\\([[:alpha:]_.]*\\)" 1 'web-mode-block-control-face)
+ '("#\\(macro\\|function\\) \\([[:alpha:]]+\\)" 2 'web-mode-function-name-face)
+ (cons (concat "\\_<\\(" web-mode-freemarker-keywords "\\)\\_>") '(1 'web-mode-keyword-face))
+ '("\\_<\\([[:alnum:]._]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("[[:alpha:]]\\([[:alnum:]_]+\\)?" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-freemarker-font-lock-keywords
+ (list
+ '("</?[#@]\\([[:alpha:]_.]*\\)" 1 'web-mode-block-control-face)
+ '("#\\(macro\\|function\\) \\([[:alpha:]]+\\)" 2 'web-mode-function-name-face)
+ (cons (concat "\\_<\\(" web-mode-freemarker-keywords "\\)\\_>") '(1 'web-mode-keyword-face))
+ '("\\_<\\([[:alnum:]._]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("[[:alpha:]]\\([[:alnum:]_]+\\)?" 0 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-directive-font-lock-keywords
+ (list
+ '("<%@[ ]*\\([[:alpha:]]+\\)[ ]+" 1 'web-mode-block-control-face)
+ '("\\_<\\([[:alpha:]]+=\\)\\(\"[^\"]*\"\\)"
+ (1 'web-mode-block-attr-name-face t t)
+ (2 'web-mode-block-attr-value-face t t))
+ ))
+
+(defvar web-mode-erb-font-lock-keywords
+ (list
+ '("[^:]\\(:[[:alnum:]_]+\\)" 1 'web-mode-symbol-face)
+ '("\\([[:alnum:]_]+:\\)[ ]+" 1 'web-mode-symbol-face)
+ (cons (concat "\\_<\\(" web-mode-erb-builtins "\\)\\_>") '(0 'web-mode-builtin-face))
+ (cons (concat "\\_<\\(" web-mode-erb-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ '("\\_<\\(self\\|true\\|false\\|nil\\)\\_>" 0 'web-mode-variable-name-face)
+ '("[@$]@?\\([[:alnum:]_]+\\)" 0 'web-mode-variable-name-face)
+ '("class[ ]+\\([[:alnum:]_]+\\)" 1 'web-mode-type-face)
+ '("def[ ]+\\([[:alnum:]_]+\\)" 1 'web-mode-function-name-face)
+ '("\\(?:\\_<\\|::\\)\\([A-Z]+[[:alnum:]_]+\\)" 1 (unless (eq (char-after) ?\() 'web-mode-type-face))
+ '("/[^/]+/" 0 'web-mode-string-face)
+ ))
+
+(defvar web-mode-ejs-font-lock-keywords
+ web-mode-javascript-font-lock-keywords)
+
+(defvar web-mode-python-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-python-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ ))
+
+(defvar web-mode-elixir-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-elixir-keywords "\\)\\_>") '(0 'web-mode-builtin-face))
+ (cons (concat "\\_<\\(" web-mode-elixir-constants "\\)\\_>") '(0 'web-mode-constant-face))
+ '("def[ ]+\\([[:alnum:]_]+\\)" 1 'web-mode-function-name-face)
+ '("@\\([[:alnum:]_]+\\)" 0 'web-mode-variable-name-face)
+ '("[ ]\\(:[[:alnum:]-_]+\\)" 1 'web-mode-symbol-face)
+ ))
+
+(defvar web-mode-erlang-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-erlang-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ (cons (concat "\\_<\\(" web-mode-erlang-constants "\\)\\_>") '(0 'web-mode-constant-face))
+ '("@\\([[:alnum:]_]+\\)" 0 'web-mode-variable-name-face)
+ '("[ ]\\(:[[:alnum:]-_]+\\)" 1 'web-mode-symbol-face)
+ ))
+
+(defvar web-mode-mason-code-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-mason-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ '("sub[ ]+\\([[:alnum:]_]+\\)" 1 'web-mode-function-name-face)
+ '("\\_<\\([[:alnum:]_]+\\)[ ]?::" 1 'web-mode-type-face)
+ '("\\([@]\\)\\([[:alnum:]#_]*\\)" (1 nil) (2 'web-mode-variable-name-face))
+ '("\\_<\\([$%]\\)\\([[:alnum:]@#_]*\\)" (1 nil) (2 'web-mode-variable-name-face))
+ '("{\\([[:alnum:]_]+\\)}" 1 'web-mode-variable-name-face)
+ '("\\_<\\(\\sw+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("[[:alnum:]_][ ]?::[ ]?\\([[:alnum:]_]+\\)" 1 'web-mode-variable-name-face)
+ '("->[ ]?\\([[:alnum:]_]+\\)" 1 'web-mode-variable-name-face)
+ '("\\(?:method\\|def\\) \\([[:alnum:]._]+\\)" 1 'web-mode-function-name-face)
+ '("|[ ]*\\([[:alnum:],]+\\)[ ]*%>" 1 'web-mode-filter-face)
+ ))
+
+(defvar web-mode-mason-block-font-lock-keywords
+ (list
+ '("<[/]?%\\([[:alpha:]]+\\)" 1 'web-mode-block-control-face)
+ '("[[:alpha:]]" 0 'web-mode-block-attr-value-face)
+ ))
+
+(defvar web-mode-mojolicious-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-perl-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ '("\\_<\\(begin\\|end\\)\\_>" 1 'web-mode-constant-face)
+ '("\\_<\\([$]\\)\\([[:alnum:]_]*\\)" (1 nil) (2 'web-mode-variable-name-face))
+ ))
+
+(defvar web-mode-lsp-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-lsp-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ (cons (concat "\\_<\\(" web-mode-lsp-constants "\\)\\_>") '(1 'web-mode-constant-face))
+ '("[ ]\\(:[[:alnum:]-_]+\\)" 1 'web-mode-symbol-face)
+ '("(defun \\([[:alnum:]-:]+\\)" 1 'web-mode-function-name-face)
+ '("(defvar \\([[:alnum:]-:]+\\)" 1 'web-mode-variable-name-face)
+ ))
+
+(defvar web-mode-cl-emb-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-cl-emb-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ (cons (concat "\\_<\\(" web-mode-cl-emb-constants "\\)\\_>") '(0 'web-mode-constant-face))
+ '("\\(@\\)" 1 'web-mode-function-call-face)
+ (list (concat "\\(@" web-mode-cl-emb-keywords "\\)[ ]+\\([[:alnum:]_]+\\)")
+ '(1 'web-mode-keyword-face)
+ '(2 'web-mode-variable-name-face))
+ ))
+
+(defvar web-mode-artanis-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-artanis-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ (cons (concat "\\_<\\(" web-mode-artanis-constants "\\)\\_>") '(0 'web-mode-constant-face))
+ '("(define[*]? (\\([[:alnum:]-:_!#$%^&*=+/?<>.]+\\)" 1 'web-mode-function-name-face)
+ '("\\(#:[[:alnum:]-:_!#$%^&*=+/?<>.]+\\)" 1 'web-mode-builtin-face)
+ ))
+
+(defvar web-mode-php-font-lock-keywords
+ (list
+ (cons (concat "\\_<\\(" web-mode-php-keywords "\\)\\_>") '(0 'web-mode-keyword-face))
+ (cons (concat "\\_<\\(" web-mode-php-types "\\)\\_>") '(1 'web-mode-type-face))
+ (cons (concat "\\_<\\(" web-mode-php-constants "\\)\\_>") '(0 'web-mode-constant-face))
+ '("function[ ]+\\([[:alnum:]_]+\\)" 1 'web-mode-function-name-face)
+ '("\\_<\\([[:alnum:]_]+\\)[ ]?(" 1 'web-mode-function-call-face)
+ '("[[:alnum:]_][ ]?::[ ]?\\([[:alnum:]_]+\\)" 1 'web-mode-constant-face)
+ '("->[ ]?\\([[:alnum:]_]+\\)" 1 'web-mode-variable-name-face)
+ '("\\_<\\([[:alnum:]_]+\\)[ ]?::" 1 'web-mode-type-face)
+ '("\\_<\\(instanceof\\|class\\|extends\\|new\\)[ ]+\\([[:alnum:]_]+\\)" 2 'web-mode-type-face)
+ '("\\(\\_<\\|[+-]\\)\\([$]\\)\\([[:alnum:]_]*\\)" (2 nil) (3 'web-mode-variable-name-face))
+ ))
+
+(defvar web-mode-spip-font-lock-keywords
+ (list
+ '("<:.+:>" 0 'web-mode-block-string-face)
+ '("#[A-Z0-9_]+" 0 'web-mode-variable-name-face)
+ '("|[a-z0-9_=!?<>]+" 0 'web-mode-function-call-face)
+ '("(\\([[:alnum:]_ ]+\\))" 1 'web-mode-constant-face)
+ ))
+
+(defvar web-mode-latex-font-lock-keywords
+ (list
+ '("[[:alnum:]_]+" 0 'web-mode-function-name-face t t)
+ ))
+
+(defvar web-mode-blade-font-lock-keywords
+ (append
+ (list
+ '("@\\([[:alpha:]_]+\\)" (1 'web-mode-block-control-face)))
+ web-mode-php-font-lock-keywords))
+
+(defvar web-mode-engines-font-lock-keywords
+ '(("angular" . web-mode-angular-font-lock-keywords)
+ ("artanis" . web-mode-artanis-font-lock-keywords)
+ ("blade" . web-mode-blade-font-lock-keywords)
+ ("cl-emb" . web-mode-cl-emb-font-lock-keywords)
+ ("closure" . web-mode-closure-font-lock-keywords)
+ ("ctemplate" . web-mode-ctemplate-font-lock-keywords)
+ ("dust" . web-mode-dust-font-lock-keywords)
+ ("elixir" . web-mode-elixir-font-lock-keywords)
+ ("ejs" . web-mode-ejs-font-lock-keywords)
+ ("erb" . web-mode-erb-font-lock-keywords)
+ ("expressionengine" . web-mode-expressionengine-font-lock-keywords)
+ ("go" . web-mode-go-font-lock-keywords)
+ ("hero" . web-mode-go-font-lock-keywords)
+ ("lsp" . web-mode-lsp-font-lock-keywords)
+ ("marko" . web-mode-marko-font-lock-keywords)
+ ("mojolicious" . web-mode-mojolicious-font-lock-keywords)
+ ("php" . web-mode-php-font-lock-keywords)
+ ("python" . web-mode-python-font-lock-keywords)
+ ("razor" . web-mode-razor-font-lock-keywords)
+ ("riot" . web-mode-riot-font-lock-keywords)
+ ("smarty" . web-mode-smarty-font-lock-keywords)
+ ("spip" . web-mode-spip-font-lock-keywords)
+ ("template-toolkit" . web-mode-template-toolkit-font-lock-keywords)
+ ("underscore" . web-mode-underscore-font-lock-keywords)
+ ("web2py" . web-mode-web2py-font-lock-keywords)
+ ("velocity" . web-mode-velocity-font-lock-keywords)
+ ("vue" . web-mode-vue-font-lock-keywords)
+ ("xoops" . web-mode-smarty-font-lock-keywords)
+ ("svelte" . web-mode-svelte-font-lock-keywords)
+ )
+ "Engines font-lock keywords")
+
+(defvar web-mode-prettify-symbols-alist
+ '(("=>" . 8658)
+ (">=" . 8805)
+ ("<=" . 8804)))
+
+(defvar web-mode-before-auto-complete-hooks nil
+ "List of functions to run before triggering the auto-complete library.
+
+Auto-complete sources will sometimes need some tweaking to work
+nicely with web-mode. This hook gives users the chance to adjust
+the environment as needed for ac-sources, right before they're used.")
+
+(defvar web-mode-ignore-ac-start-advice nil
+ "If not nil 'defadvice' for 'ac-start' will be ignored.
+
+Can be set inside a hook in 'web-mode-before-auto-complete-hooks' to
+non nil to ignore the defadvice which sets ac-sources according to current
+language. This is needed if the corresponding auto-completion triggers
+another auto-completion with different ac-sources (e.g. ac-php)")
+
+(defvar web-mode-ac-sources-alist nil
+ "alist mapping language names to ac-sources for that language.")
+
+(defvar web-mode-trace nil
+ "Activate debug tracing.")
+
+(defvar web-mode-syntax-table
+ (let ((table (make-syntax-table)))
+ (modify-syntax-entry ?- "_" table)
+ (modify-syntax-entry ?_ "_" table) ;#563
+ (modify-syntax-entry ?< "." table)
+ (modify-syntax-entry ?> "." table)
+ (modify-syntax-entry ?& "." table)
+ (modify-syntax-entry ?/ "." table)
+ (modify-syntax-entry ?= "." table)
+ (modify-syntax-entry ?% "." table)
+ table)
+ "Syntax table used to reveal whitespaces.")
+
+(defvar web-mode-map
+ (let ((map (make-sparse-keymap)))
+
+ (define-key map [menu-bar wm] (cons "Web-Mode" (make-sparse-keymap)))
+ (define-key map [menu-bar wm dom] (cons "Dom" (make-sparse-keymap)))
+ (define-key map [menu-bar wm blk] (cons "Block" (make-sparse-keymap)))
+ (define-key map [menu-bar wm attr] (cons "Html Attr" (make-sparse-keymap)))
+ (define-key map [menu-bar wm tag] (cons "Html Tag" (make-sparse-keymap)))
+ (define-key map [menu-bar wm elt] (cons "Html Element" (make-sparse-keymap)))
+
+ (define-key map [menu-bar wm sep-1] '(menu-item "--"))
+
+ (define-key map [menu-bar wm dom dom-xpa] '(menu-item "XPath" web-mode-dom-xpath))
+ (define-key map [menu-bar wm dom dom-tra] '(menu-item "Traverse" web-mode-dom-traverse))
+ (define-key map [menu-bar wm dom dom-err] '(menu-item "Show error(s)" web-mode-dom-errors-show))
+ (define-key map [menu-bar wm dom dom-ent] '(menu-item "Replace html entities" web-mode-dom-entities-replace))
+ (define-key map [menu-bar wm dom dom-quo] '(menu-item "Replace dumb quotes" web-mode-dom-quotes-replace))
+ (define-key map [menu-bar wm dom dom-apo] '(menu-item "Replace apostrophes" web-mode-dom-apostrophes-replace))
+ (define-key map [menu-bar wm dom dom-nor] '(menu-item "Normalize" web-mode-dom-normalize))
+
+ (define-key map [menu-bar wm blk blk-sel] '(menu-item "Select" web-mode-block-select))
+ (define-key map [menu-bar wm blk blk-pre] '(menu-item "Previous" web-mode-block-previous))
+ (define-key map [menu-bar wm blk blk-nex] '(menu-item "Next" web-mode-block-next))
+ (define-key map [menu-bar wm blk blk-kil] '(menu-item "Kill" web-mode-block-kill))
+ (define-key map [menu-bar wm blk blk-end] '(menu-item "End" web-mode-block-end))
+ (define-key map [menu-bar wm blk blk-clo] '(menu-item "Close" web-mode-block-close))
+ (define-key map [menu-bar wm blk blk-beg] '(menu-item "Beginning" web-mode-block-beginning))
+
+ (define-key map [menu-bar wm attr attr-ins] '(menu-item "Insert" web-mode-attribute-insert))
+ (define-key map [menu-bar wm attr attr-end] '(menu-item "End" web-mode-attribute-end))
+ (define-key map [menu-bar wm attr attr-beg] '(menu-item "Beginning" web-mode-attribute-beginning))
+ (define-key map [menu-bar wm attr attr-sel] '(menu-item "Select" web-mode-attribute-select))
+ (define-key map [menu-bar wm attr attr-kil] '(menu-item "Kill" web-mode-attribute-kill))
+ (define-key map [menu-bar wm attr attr-nex] '(menu-item "Next" web-mode-attribute-next))
+ (define-key map [menu-bar wm attr attr-pre] '(menu-item "Previous" web-mode-attribute-previous))
+ (define-key map [menu-bar wm attr attr-tra] '(menu-item "Transpose" web-mode-attribute-transpose))
+
+ (define-key map [menu-bar wm tag tag-beg] '(menu-item "Sort Attributes" web-mode-tag-attributes-sort))
+ (define-key map [menu-bar wm tag tag-sel] '(menu-item "Select" web-mode-tag-select))
+ (define-key map [menu-bar wm tag tag-pre] '(menu-item "Previous" web-mode-tag-previous))
+ (define-key map [menu-bar wm tag tag-nex] '(menu-item "Next" web-mode-tag-next))
+ (define-key map [menu-bar wm tag tag-end] '(menu-item "End" web-mode-tag-end))
+ (define-key map [menu-bar wm tag tag-beg] '(menu-item "Beginning" web-mode-tag-beginning))
+
+ (define-key map [menu-bar wm elt elt-con] '(menu-item "Contract" web-mode-element-contract))
+ (define-key map [menu-bar wm elt elt-ext] '(menu-item "Extract" web-mode-element-extract))
+ (define-key map [menu-bar wm elt elt-van] '(menu-item "Vanish" web-mode-element-vanish))
+ (define-key map [menu-bar wm elt elt-exc] '(menu-item "Transpose" web-mode-element-transpose))
+ (define-key map [menu-bar wm elt elt-sel] '(menu-item "Select" web-mode-element-select))
+ (define-key map [menu-bar wm elt elt-ren] '(menu-item "Rename" web-mode-element-rename))
+ (define-key map [menu-bar wm elt elt-pre] '(menu-item "Previous" web-mode-element-previous))
+ (define-key map [menu-bar wm elt elt-par] '(menu-item "Parent" web-mode-element-parent))
+ (define-key map [menu-bar wm elt elt-nex] '(menu-item "Next" web-mode-element-next))
+ (define-key map [menu-bar wm elt elt-mut] '(menu-item "Mute blanks" web-mode-element-mute-blanks))
+ (define-key map [menu-bar wm elt elt-del] '(menu-item "Kill" web-mode-element-kill))
+ (define-key map [menu-bar wm elt elt-end] '(menu-item "End" web-mode-element-end))
+ (define-key map [menu-bar wm elt elt-inn] '(menu-item "Content (select)" web-mode-element-content-select))
+ (define-key map [menu-bar wm elt elt-clo] '(menu-item "Close" web-mode-element-close))
+ (define-key map [menu-bar wm elt elt-ins] '(menu-item "Insert" web-mode-element-insert))
+ (define-key map [menu-bar wm elt elt-ins] '(menu-item "Word to tag" web-mode-element-insert-at-point))
+ (define-key map [menu-bar wm elt elt-dup] '(menu-item "Clone" web-mode-element-clone))
+ (define-key map [menu-bar wm elt elt-cfo] '(menu-item "Children fold" web-mode-element-children-fold-or-unfold))
+ (define-key map [menu-bar wm elt elt-chi] '(menu-item "Child" web-mode-element-child))
+ (define-key map [menu-bar wm elt elt-beg] '(menu-item "Beginning" web-mode-element-beginning))
+
+ (define-key map [menu-bar wm fol] '(menu-item "Fold/Unfold" web-mode-fold-or-unfold))
+ (define-key map [menu-bar wm hig] '(menu-item "Fontify buffer" web-mode-buffer-fontify))
+ (define-key map [menu-bar wm ind] '(menu-item "Indent buffer" web-mode-buffer-indent))
+ (define-key map [menu-bar wm nav] '(menu-item "Tag/Block navigation" web-mode-navigate))
+ (define-key map [menu-bar wm exp] '(menu-item "Mark and Expand" web-mode-mark-and-expand))
+ (define-key map [menu-bar wm spa] '(menu-item "Toggle whitespaces" web-mode-whitespaces-show))
+ (define-key map [menu-bar wm sni] '(menu-item "Insert snippet" web-mode-snippet-insert))
+
+ ;;--------------------------------------------------------------------------
+ ;; "C-c <LETTER>" are reserved for users
+
+ (define-key map (kbd "C-c C-a b") 'web-mode-attribute-beginning)
+ (define-key map (kbd "C-c C-a e") 'web-mode-attribute-end)
+ (define-key map (kbd "C-c C-a i") 'web-mode-attribute-insert)
+ (define-key map (kbd "C-c C-a n") 'web-mode-attribute-next)
+ (define-key map (kbd "C-c C-a s") 'web-mode-attribute-select)
+ (define-key map (kbd "C-c C-a k") 'web-mode-attribute-kill)
+ (define-key map (kbd "C-c C-a p") 'web-mode-attribute-previous)
+ (define-key map (kbd "C-c C-a t") 'web-mode-attribute-transpose)
+
+ (define-key map (kbd "C-c C-b b") 'web-mode-block-beginning)
+ (define-key map (kbd "C-c C-b c") 'web-mode-block-close)
+ (define-key map (kbd "C-c C-b e") 'web-mode-block-end)
+ (define-key map (kbd "C-c C-b k") 'web-mode-block-kill)
+ (define-key map (kbd "C-c C-b n") 'web-mode-block-next)
+ (define-key map (kbd "C-c C-b p") 'web-mode-block-previous)
+ (define-key map (kbd "C-c C-b s") 'web-mode-block-select)
+
+ (define-key map (kbd "C-c C-d a") 'web-mode-dom-apostrophes-replace)
+ (define-key map (kbd "C-c C-d d") 'web-mode-dom-errors-show)
+ (define-key map (kbd "C-c C-d e") 'web-mode-dom-entities-replace)
+ (define-key map (kbd "C-c C-d n") 'web-mode-dom-normalize)
+ (define-key map (kbd "C-c C-d q") 'web-mode-dom-quotes-replace)
+ (define-key map (kbd "C-c C-d t") 'web-mode-dom-traverse)
+ (define-key map (kbd "C-c C-d x") 'web-mode-dom-xpath)
+
+ (define-key map (kbd "C-c C-e /") 'web-mode-element-close)
+ (define-key map (kbd "C-c C-e a") 'web-mode-element-content-select)
+ (define-key map (kbd "C-c C-e b") 'web-mode-element-beginning)
+ (define-key map (kbd "C-c C-e c") 'web-mode-element-clone)
+ (define-key map (kbd "C-c C-e d") 'web-mode-element-child)
+ (define-key map (kbd "C-c C-e e") 'web-mode-element-end)
+ (define-key map (kbd "C-c C-e f") 'web-mode-element-children-fold-or-unfold)
+ (define-key map (kbd "C-c C-e i") 'web-mode-element-insert)
+ (define-key map (kbd "C-c C-e I") 'web-mode-element-insert-at-point)
+ (define-key map (kbd "C-c C-e k") 'web-mode-element-kill)
+ (define-key map (kbd "C-c C-e m") 'web-mode-element-mute-blanks)
+ (define-key map (kbd "C-c C-e n") 'web-mode-element-next)
+ (define-key map (kbd "C-c C-e p") 'web-mode-element-previous)
+ (define-key map (kbd "C-c C-e r") 'web-mode-element-rename)
+ (define-key map (kbd "C-c C-e s") 'web-mode-element-select)
+ (define-key map (kbd "C-c C-e t") 'web-mode-element-transpose)
+ (define-key map (kbd "C-c C-e u") 'web-mode-element-parent)
+ (define-key map (kbd "C-c C-e v") 'web-mode-element-vanish)
+ (define-key map (kbd "C-c C-e w") 'web-mode-element-wrap)
+ (define-key map (kbd "C-c C-e +") 'web-mode-element-extract)
+ (define-key map (kbd "C-c C-e -") 'web-mode-element-contract)
+
+ (define-key map (kbd "C-c C-t a") 'web-mode-tag-attributes-sort)
+ (define-key map (kbd "C-c C-t b") 'web-mode-tag-beginning)
+ (define-key map (kbd "C-c C-t e") 'web-mode-tag-end)
+ (define-key map (kbd "C-c C-t m") 'web-mode-tag-match)
+ (define-key map (kbd "C-c C-t n") 'web-mode-tag-next)
+ (define-key map (kbd "C-c C-t p") 'web-mode-tag-previous)
+ (define-key map (kbd "C-c C-t s") 'web-mode-tag-select)
+
+ ;;--------------------------------------------------------------------------
+
+ ;;(define-key map (kbd "M-q") 'fill-paragraph)
+ (define-key map (kbd "M-;") 'web-mode-comment-or-uncomment)
+
+ ;;C-c C-a : attribute
+ ;;C-c C-b : block
+ ;;C-c C-d : dom
+ ;;C-c C-e : element
+ (define-key map (kbd "C-c C-f") 'web-mode-fold-or-unfold)
+ (define-key map (kbd "C-c C-h") 'web-mode-buffer-fontify)
+ (define-key map (kbd "C-c C-i") 'web-mode-buffer-indent)
+ (define-key map (kbd "C-c C-j") 'web-mode-jshint)
+ (define-key map (kbd "C-c C-l") 'web-mode-file-link)
+ (define-key map (kbd "C-c C-m") 'web-mode-mark-and-expand)
+ (define-key map (kbd "C-c C-n") 'web-mode-navigate)
+ (define-key map (kbd "C-c C-r") 'web-mode-reload)
+ (define-key map (kbd "C-c C-s") 'web-mode-snippet-insert)
+ ;;C-c C-t : tag
+ (define-key map (kbd "C-c C-w") 'web-mode-whitespaces-show)
+
+ map)
+ "Keymap for `web-mode'.")
+
+;;---- COMPATIBILITY -----------------------------------------------------------
+
+(eval-and-compile
+
+ ;; compatibility with emacs < 23
+ (defun web-mode-string-match-p (regexp string &optional start)
+ "Same as `string-match' except it does not change the match data."
+ (let ((inhibit-changing-match-data t))
+ (string-match regexp string start)))
+
+ (unless (fboundp 'string-match-p)
+ (fset 'string-match-p (symbol-function 'web-mode-string-match-p)))
+
+ ;; compatibility with emacs < 23.3
+ (if (fboundp 'with-silent-modifications)
+ (defalias 'web-mode-with-silent-modifications 'with-silent-modifications)
+ (defmacro web-mode-with-silent-modifications (&rest body)
+ `(let ((old-modified-p (buffer-modified-p))
+ (inhibit-modification-hooks t)
+ (buffer-undo-list t))
+ (unwind-protect
+ ,@body
+ (restore-buffer-modified-p old-modified-p)))))
+
+ ;; compatibility with emacs < 24.3
+ (defun web-mode-buffer-narrowed-p ()
+ (if (fboundp 'buffer-narrowed-p)
+ (buffer-narrowed-p)
+ (/= (- (point-max) (point-min)) (buffer-size))))
+
+ ;; compatibility with emacs < 24
+ (defalias 'web-mode-prog-mode
+ (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))
+
+ ;; compatibility with emacs < 24.3
+ (unless (fboundp 'setq-local)
+ (defmacro setq-local (var val)
+ `(set (make-local-variable ',var) ,val)))
+
+ ;; compatability with emacs < 24.4
+ (defun web-mode-string-suffix-p (suffix string)
+ "Return t if STRING ends with SUFFIX."
+ (and (string-match (rx-to-string `(: ,suffix eos) t)
+ string)
+ t))
+
+ (unless (fboundp 'string-suffix-p)
+ (fset 'string-suffix-p (symbol-function 'web-mode-string-suffix-p)))
+
+ (unless (fboundp 'seq-some)
+ (defun seq-some (pred seq)
+ (unless (null seq)
+ (or (funcall pred (car seq))
+ (seq-some pred (cdr seq))))))
+ ) ;eval-and-compile
+
+;;---- MAJOR MODE --------------------------------------------------------------
+
+;;;###autoload
+(define-derived-mode web-mode web-mode-prog-mode "Web"
+ "Major mode for editing web templates."
+
+ (make-local-variable 'web-mode-attr-indent-offset)
+ (make-local-variable 'web-mode-attr-value-indent-offset)
+ (make-local-variable 'web-mode-auto-pairs)
+ (make-local-variable 'web-mode-block-regexp)
+ (make-local-variable 'web-mode-change-beg)
+ (make-local-variable 'web-mode-change-end)
+ (make-local-variable 'web-mode-code-indent-offset)
+ (make-local-variable 'web-mode-column-overlays)
+ (make-local-variable 'web-mode-comment-formats)
+ (make-local-variable 'web-mode-comment-style)
+ (make-local-variable 'web-mode-content-type)
+ (make-local-variable 'web-mode-css-indent-offset)
+ (make-local-variable 'web-mode-display-table)
+ (make-local-variable 'web-mode-django-control-blocks)
+ (make-local-variable 'web-mode-django-control-blocks-regexp)
+ (make-local-variable 'web-mode-enable-block-face)
+ (make-local-variable 'web-mode-enable-inlays)
+ (make-local-variable 'web-mode-enable-part-face)
+ (make-local-variable 'web-mode-enable-sexp-functions)
+ (make-local-variable 'web-mode-engine)
+ (make-local-variable 'web-mode-engine-attr-regexp)
+ (make-local-variable 'web-mode-engine-file-regexps)
+ (make-local-variable 'web-mode-engine-open-delimiter-regexps)
+ (make-local-variable 'web-mode-engine-token-regexp)
+ (make-local-variable 'web-mode-expand-initial-pos)
+ (make-local-variable 'web-mode-expand-initial-scroll)
+ (make-local-variable 'web-mode-expand-previous-state)
+ (make-local-variable 'web-mode-indent-style)
+ (make-local-variable 'web-mode-indentless-attributes)
+ (make-local-variable 'web-mode-indentless-elements)
+ (make-local-variable 'web-mode-is-scratch)
+ (make-local-variable 'web-mode-skip-fontification)
+ (make-local-variable 'web-mode-jshint-errors)
+ (make-local-variable 'web-mode-last-enabled-feature)
+ (make-local-variable 'web-mode-markup-indent-offset)
+ (make-local-variable 'web-mode-minor-engine)
+ (make-local-variable 'web-mode-overlay-tag-end)
+ (make-local-variable 'web-mode-overlay-tag-start)
+ (make-local-variable 'web-mode-part-beg)
+ (make-local-variable 'web-mode-scan-beg)
+ (make-local-variable 'web-mode-scan-end)
+ (make-local-variable 'web-mode-sql-indent-offset)
+ (make-local-variable 'web-mode-time)
+ (make-local-variable 'web-mode-trace)
+
+ (make-local-variable 'font-lock-beg)
+ (make-local-variable 'font-lock-end)
+
+ (make-local-variable 'comment-end)
+ (make-local-variable 'comment-region-function)
+ (make-local-variable 'comment-start)
+ (make-local-variable 'fill-paragraph-function)
+ (make-local-variable 'font-lock-defaults)
+ (make-local-variable 'font-lock-extend-region-functions)
+ (make-local-variable 'font-lock-support-mode)
+ (make-local-variable 'font-lock-unfontify-region-function)
+ (make-local-variable 'imenu-case-fold-search)
+ (make-local-variable 'imenu-create-index-function)
+ (make-local-variable 'imenu-generic-expression)
+ (make-local-variable 'indent-line-function)
+ (make-local-variable 'parse-sexp-lookup-properties)
+ (make-local-variable 'uncomment-region-function)
+ (make-local-variable 'yank-excluded-properties)
+
+ (setq web-mode-time (current-time))
+
+ (setq comment-end "-->"
+ comment-region-function 'web-mode-comment-or-uncomment-region
+ comment-start "<!--"
+ fill-paragraph-function 'web-mode-fill-paragraph
+ ;;font-lock-defaults '(web-mode-font-lock-keywords t)
+ font-lock-defaults '('(web-mode-fontify) t)
+ font-lock-extend-region-functions '(web-mode-extend-region)
+ font-lock-support-mode nil
+ font-lock-unfontify-region-function 'web-mode-unfontify-region
+ imenu-case-fold-search t
+ imenu-create-index-function 'web-mode-imenu-index
+ indent-line-function 'web-mode-indent-line
+ parse-sexp-lookup-properties t
+ yank-excluded-properties t
+ uncomment-region-function 'web-mode-comment-or-uncomment-region
+ prettify-symbols-alist web-mode-prettify-symbols-alist)
+
+ (substitute-key-definition #'indent-new-comment-line
+ #'web-mode-comment-indent-new-line
+ web-mode-map global-map)
+
+ (add-hook 'after-change-functions #'web-mode-on-after-change nil t)
+ (add-hook 'after-save-hook #'web-mode-on-after-save t t)
+ (add-hook 'change-major-mode-hook #'web-mode-on-exit nil t)
+ (add-hook 'post-command-hook #'web-mode-on-post-command nil t)
+
+ (cond
+ ((boundp 'yas-after-exit-snippet-hook)
+ (add-hook 'yas-after-exit-snippet-hook
+ 'web-mode-yasnippet-exit-hook
+ t t))
+ ((boundp 'yas/after-exit-snippet-hook)
+ (add-hook 'yas/after-exit-snippet-hook
+ 'web-mode-yasnippet-exit-hook
+ t t))
+ )
+
+ (when web-mode-enable-whitespace-fontification
+ (web-mode-whitespaces-on))
+
+ (when web-mode-enable-sexp-functions
+ (setq-local forward-sexp-function #'web-mode-forward-sexp))
+
+ (web-mode-guess-engine-and-content-type)
+ (setq web-mode-change-beg (point-min)
+ web-mode-change-end (point-max))
+ (when (> (point-max) 256000)
+ (web-mode-buffer-fontify))
+
+ (when (and (boundp 'hs-special-modes-alist)
+ (not (assoc major-mode hs-special-modes-alist)))
+ (add-to-list 'hs-special-modes-alist '(web-mode "{" "}" "/[*/]" web-mode-forward-sexp nil))
+ ) ;when
+
+ ;; compatibility with emacs < 24
+ (if (fboundp 'prog-mode)
+ (put 'web-mode 'derived-mode-parent 'prog-mode))
+
+ (cond
+ ((not (buffer-file-name))
+ )
+ ((string-match-p "web-mode-benchmark.html" (buffer-file-name))
+ (web-mode-measure "end"))
+ ) ;cond
+
+ )
+
+;;---- INVALIDATION ------------------------------------------------------------
+
+;; 1/ after-change
+;; 2/ extend-region
+;; 3/ scan
+;; 4/ fontify
+;; 5/ post-command
+
+(defun web-mode-on-after-change (beg end len)
+ (when web-mode-trace
+ (message "after-change: pos(%d) beg(%d) end(%d) len(%d) this-command(%S)"
+ (point) beg end len this-command))
+ (when (or (null web-mode-change-beg) (< beg web-mode-change-beg))
+ (setq web-mode-change-beg beg))
+ (when (or (null web-mode-change-end) (> end web-mode-change-end))
+ (setq web-mode-change-end end)))
+
+(defun web-mode-extend-region ()
+ (when web-mode-trace
+ (message "extend-region: font-lock-beg(%S) font-lock-end(%S) web-mode-change-beg(%S) web-mode-change-end(%S) web-mode-skip-fontification(%S)"
+ font-lock-beg font-lock-end web-mode-change-beg web-mode-change-end web-mode-skip-fontification))
+ (when (and (string= web-mode-engine "php")
+ (and (>= font-lock-beg 6) (<= font-lock-beg 9))
+ (or (message (buffer-substring-no-properties 1 6)) t)
+ (string= (buffer-substring-no-properties 1 6) "<?php"))
+ (setq font-lock-beg (point-min)
+ font-lock-end (point-max))
+ )
+ (when (or (null web-mode-change-beg) (< font-lock-beg web-mode-change-beg))
+ (when web-mode-trace (message "extend-region: font-lock-beg(%S) < web-mode-change-beg(%S)" font-lock-beg web-mode-change-beg))
+ (setq web-mode-change-beg font-lock-beg))
+ (when (or (null web-mode-change-end) (> font-lock-end web-mode-change-end))
+ (when web-mode-trace (message "extend-region: font-lock-end(%S) > web-mode-change-end(%S)" font-lock-end web-mode-change-end))
+ (setq web-mode-change-end font-lock-end))
+ (when font-lock-dont-widen
+ (setq web-mode-change-beg (max web-mode-change-beg (point-min))
+ web-mode-change-end (min web-mode-change-end (point-max))))
+ (let ((region (web-mode-scan web-mode-change-beg web-mode-change-end)))
+ (when region
+ ;;(message "region: %S" region)
+ (setq font-lock-beg (car region)
+ font-lock-end (cdr region))
+ ) ;when
+ ) ;let
+ nil)
+
+(defun web-mode-scan (&optional beg end)
+ (when web-mode-trace
+ (message "scan: beg(%S) end(%S) web-mode-change-beg(%S) web-mode-change-end(%S)"
+ beg end web-mode-change-beg web-mode-change-end))
+ (unless beg (setq beg web-mode-change-beg))
+ (unless end (setq end web-mode-change-end))
+ ;;(message "%S %S %S" web-mode-content-type (get-text-property beg 'part-side) (get-text-property end 'part-side))
+ (when (and end (> end (point-max)))
+ (setq end (point-max)))
+ (setq web-mode-change-beg nil
+ web-mode-change-end nil)
+ (cond
+ ((or (null beg) (null end))
+ nil)
+ ((and (member web-mode-engine '("php" "asp"))
+ (get-text-property beg 'block-side)
+ (get-text-property end 'block-side)
+ (> beg (point-min))
+ (not (eq (get-text-property (1- beg) 'block-token) 'delimiter-beg))
+ (not (eq (get-text-property end 'block-token) 'delimiter-end)))
+ ;;(message "invalidate block (%S > %S)" beg end)
+ (web-mode-invalidate-block-region beg end))
+ ((and (or (member web-mode-content-type
+ '("css" "javascript" "json" "jsx" "sass" "stylus" "typescript"))
+ (and (get-text-property beg 'part-side)
+ (get-text-property end 'part-side)
+ (> beg (point-min))
+ (get-text-property (1- beg) 'part-side))
+ ))
+ ;;(message "invalidate part (%S > %S)" beg end)
+ (web-mode-invalidate-part-region beg end))
+ (t
+ ;;(message "invalidate default (%S > %S)" beg end)
+ (web-mode-invalidate-region beg end))
+ ) ;cond
+ )
+
+(defun web-mode-invalidate-region (reg-beg reg-end)
+ (when web-mode-trace
+ (message "invalidate-region: point(%S) reg-beg(%S) reg-end(%S)" (point) reg-beg reg-end))
+ (setq reg-beg (web-mode-invalidate-region-beginning-position reg-beg)
+ reg-end (web-mode-invalidate-region-end-position reg-end))
+ ;;(message "invalidate-region: reg-beg(%S) reg-end(%S)" reg-beg reg-end)
+ (web-mode-scan-region reg-beg reg-end))
+
+(defun web-mode--command-is-self-insert-p ()
+ "Return non-nil if `this-command' is `self-insert-command'.
+Also return non-nil if it is the command `self-insert-command' is remapped to."
+ (memq this-command (list 'self-insert-command
+ (key-binding [remap self-insert-command]))))
+
+(defun web-mode-on-post-command ()
+ (when (and web-mode-trace
+ (not (member this-command
+ '(left-char right-char previous-line next-line save-buffer mwheel-scroll end-of-line beginning-of-line))))
+ (message "post-command: this-command(%S) web-mode-change-beg(%S) web-mode-change-end(%S) previous-state(%S)"
+ this-command web-mode-change-beg web-mode-change-end web-mode-expand-previous-state))
+ (let (ctx n char)
+ (when (and web-mode-expand-previous-state
+ (not (member this-command web-mode-commands-like-expand-region)))
+ (when (eq this-command 'keyboard-quit)
+ (goto-char web-mode-expand-initial-pos))
+ (deactivate-mark)
+ (when web-mode-expand-initial-scroll
+ (set-window-start (selected-window) web-mode-expand-initial-scroll)
+ )
+ (setq web-mode-expand-previous-state nil
+ web-mode-expand-initial-pos nil
+ web-mode-expand-initial-scroll nil))
+
+ (when (member this-command '(yank))
+ ;;(setq web-mode-skip-fontification nil)
+ (when (and web-mode-scan-beg web-mode-scan-end global-font-lock-mode)
+ (save-excursion
+ (font-lock-fontify-region web-mode-scan-beg web-mode-scan-end))
+ (when web-mode-enable-auto-indentation
+ (indent-region web-mode-scan-beg web-mode-scan-end))
+ ) ;and
+ )
+
+ (when (and (< (point) 16) web-mode-change-beg web-mode-change-end)
+ (web-mode-detect-content-type))
+
+ (when (and web-mode-change-beg web-mode-change-end
+ web-mode-enable-engine-detection
+ (or (null web-mode-engine) (string= web-mode-engine "none"))
+ (< (point) web-mode-chunk-length)
+ (web-mode-detect-engine))
+ (web-mode-on-engine-setted)
+ (web-mode-buffer-fontify))
+
+ (when (> (point) 1)
+ (setq char (char-before)))
+
+ (cond
+ ((null char)
+ )
+ ((and (>= (point) 3)
+ (web-mode--command-is-self-insert-p)
+ (not (member (get-text-property (point) 'part-token) '(comment string)))
+ (not (eq (get-text-property (point) 'tag-type) 'comment))
+ )
+ (setq ctx (web-mode-auto-complete)))
+ ((and web-mode-enable-auto-opening
+ (member this-command '(newline electric-newline-and-maybe-indent newline-and-indent))
+ (or (and (not (eobp))
+ (eq (char-after) ?\<)
+ (eq (get-text-property (point) 'tag-type) 'end)
+ (looking-back ">\n[ \t]*" (point-min))
+ (setq n (length (match-string-no-properties 0)))
+ (eq (get-text-property (- (point) n) 'tag-type) 'start)
+ (string= (get-text-property (- (point) n) 'tag-name)
+ (get-text-property (point) 'tag-name))
+ )
+ (and (get-text-property (1- (point)) 'block-side)
+ (string= web-mode-engine "php")
+ (looking-back "<\\?php[ ]*\n" (point-min))
+ (looking-at-p "[ ]*\\?>"))))
+ (newline-and-indent)
+ (forward-line -1)
+ (indent-according-to-mode)
+ )
+ ) ;cond
+
+ (cond
+
+ ((not web-mode-enable-auto-opening)
+ )
+ ((and (member this-command '(newline electric-newline-and-maybe-indent newline-and-indent))
+ (get-text-property (point) 'part-side)
+ (eq (get-text-property (point) 'part-token) 'string))
+ (indent-according-to-mode)
+ (when (and web-mode-change-end (> web-mode-change-end (point-max)))
+ (message "post-command: enlarge web-mode-change-end")
+ (setq web-mode-change-end (point-max))
+ )
+ )
+ ((and (web-mode--command-is-self-insert-p)
+ (or (and ctx
+ (or (plist-get ctx :auto-closed)
+ (plist-get ctx :auto-expanded)))
+ (and (> (point) (point-min))
+ (get-text-property (1- (point)) 'tag-end)
+ (get-text-property (line-beginning-position) 'tag-beg))))
+ (indent-according-to-mode)
+ (when (and web-mode-change-end (> web-mode-change-end (point-max)))
+ (message "post-command: enlarge web-mode-change-end")
+ (setq web-mode-change-end (point-max))
+ )
+ )
+ ((and (web-mode--command-is-self-insert-p)
+ (member (get-text-property (point) 'part-side) '(javascript jsx css))
+ (looking-back "^[ \t]+[]})]" (point-min)))
+ (indent-according-to-mode)
+ (when (and web-mode-change-end (> web-mode-change-end (point-max)))
+ (message "post-command: enlarge web-mode-change-end")
+ (setq web-mode-change-end (point-max))
+ )
+ )
+ ) ; cond web-mode-enable-auto-opening
+
+ (when web-mode-enable-current-element-highlight
+ (web-mode-highlight-current-element))
+
+ (when (and web-mode-enable-current-column-highlight
+ (not (web-mode-buffer-narrowed-p)))
+ (web-mode-column-show))
+
+ (when (and web-mode-trace (not (member this-command
+ '(left-char right-char previous-line next-line save-buffer mwheel-scroll end-of-line beginning-of-line))))
+ (when (or web-mode-change-beg web-mode-change-end)
+ (message "post-command: web-mode-change-beg(%S) web-mode-change-end(%S)"
+ web-mode-change-end web-mode-change-end))
+ (message "-------------------------------------------------------------------")
+ )
+
+ ))
+
+;; NOTE: il est important d'identifier des caractères en fin de ligne
+;; web-mode-block-tokenize travaille en effet sur les fins de lignes pour
+;; les commentaires de type //
+(defun web-mode-invalidate-block-region (pos-beg pos-end)
+ ;; (message "pos-beg(%S) pos-end(%S)" pos-beg pos-end)
+ (save-excursion
+ (let (beg end code-beg code-end)
+ ;;(message "invalidate-block-region: pos-beg(%S)=%S" pos-beg (get-text-property pos 'block-side))
+ ;;(message "code-beg(%S) code-end(%S) pos-beg(%S) pos-end(%S)" code-beg code-end pos-beg pos-end)
+ (cond
+ ((not (and (setq code-beg (web-mode-block-code-beginning-position pos-beg))
+ (setq code-end (web-mode-block-code-end-position pos-beg))
+ (>= pos-beg code-beg)
+ (<= pos-end code-end)
+ (> code-end code-beg)))
+ (web-mode-invalidate-region pos-beg pos-end))
+ ((member web-mode-engine '("asp"))
+ (goto-char pos-beg)
+ (forward-line -1)
+ (setq beg (line-beginning-position))
+ (when (> code-beg beg)
+ (setq beg code-beg))
+ (goto-char pos-beg)
+ (forward-line)
+ (setq end (line-end-position))
+ (when (< code-end end)
+ (setq end code-end))
+ ;; ?? pas de (web-mode-block-tokenize beg end) ?
+ (web-mode-block-tokenize beg end)
+ (cons beg end)
+ ) ;asp
+ (t
+ (goto-char pos-beg)
+ ;;(message "pos-beg=%S" pos-beg)
+ (when (string= web-mode-engine "php")
+ (cond
+ ((and (looking-back "\*" (point-min))
+ (looking-at-p "/"))
+ (search-backward "/*" code-beg))
+ ) ;cond
+ ) ;when
+ (if (web-mode-block-rsb "[;{}(][ ]*\n" code-beg)
+ (setq beg (match-end 0))
+ (setq beg code-beg))
+ (goto-char pos-end)
+ (if (web-mode-block-rsf "[;{})][ ]*\n" code-end)
+ (setq end (1- (match-end 0)))
+ (setq end code-end))
+ (web-mode-block-tokenize beg end)
+ ;;(message "beg(%S) end(%S)" beg end)
+ (cons beg end)
+ )
+ ) ;cond
+ )))
+
+(defun web-mode-invalidate-part-region (pos-beg pos-end)
+ (save-excursion
+ (let (beg end part-beg part-end language)
+ (if (member web-mode-content-type web-mode-part-content-types)
+ (setq language web-mode-content-type)
+ (setq language (symbol-name (get-text-property pos-beg 'part-side))))
+ (setq part-beg (web-mode-part-beginning-position pos-beg)
+ part-end (web-mode-part-end-position pos-beg))
+ ;;(message "language(%S) pos-beg(%S) pos-end(%S) part-beg(%S) part-end(%S)"
+ ;; language pos-beg pos-end part-beg part-end)
+ (goto-char pos-beg)
+ (cond
+ ((not (and part-beg part-end
+ (>= pos-beg part-beg)
+ (<= pos-end part-end)
+ (> part-end part-beg)))
+ (web-mode-invalidate-region pos-beg pos-end))
+ ((member language '("javascript" "json" "jsx" "typescript"))
+ (if (web-mode-javascript-rsb "[;{}(][ ]*\n" part-beg)
+ (setq beg (match-end 0))
+ (setq beg part-beg))
+ (goto-char pos-end)
+ (if (web-mode-javascript-rsf "[;{})][ ]*\n" part-end)
+ (setq end (match-end 0))
+ (setq end part-end))
+ (web-mode-scan-region beg end language))
+ ((member language '("css" "sass"))
+ (let (rule1 rule2)
+ (setq rule1 (web-mode-css-rule-current pos-beg))
+ (setq rule2 rule1)
+ (when (> pos-end (cdr rule1))
+ (setq rule2 (web-mode-css-rule-current pos-end)))
+ (setq beg (car rule1)
+ end (cdr rule2))
+ )
+ (web-mode-scan-region beg end language))
+ (t
+ (setq beg part-beg
+ end part-end)
+ (web-mode-scan-region beg end language))
+ ) ;cond
+ )))
+
+(defun web-mode-invalidate-region-beginning-position (pos)
+ (save-excursion
+ (goto-char pos)
+
+ (cond
+ ((and (looking-at-p ">") ;#1151
+ (looking-back "--" (point-min)))
+ (search-backward "<!--" nil t))
+ ((and (bolp) (not (bobp)))
+ (backward-char))
+ )
+
+ (beginning-of-line)
+ ;;(message "pos=%S point=%S %S" pos (point) (text-properties-at (point)))
+ (setq pos (point-min))
+ (let ((continue (not (bobp))))
+ (while continue
+ (cond
+ ((bobp)
+ (setq continue nil))
+ ;; NOTE: Going back to the previous start tag is necessary
+ ;; when inserting a part endtag (e.g. </script>).
+ ;; Indeed, parts must be identified asap.
+ ((and (progn (back-to-indentation) t)
+ (get-text-property (point) 'tag-beg)
+ (eq (get-text-property (point) 'tag-type) 'start))
+ (setq pos (point)
+ continue nil))
+ (t
+ (forward-line -1))
+ ) ;cond
+ ) ;while
+ ;;(message "pos=%S" pos)
+ pos)))
+
+(defun web-mode-invalidate-region-end-position (pos)
+ (save-excursion
+ (goto-char pos)
+ ;;(message "pos=%S %S" pos (get-text-property pos 'block-token))
+ (when (string= web-mode-engine "jsp")
+ (cond
+ ((and (looking-back "<%" (point-min))
+ (looking-at-p "--"))
+ (search-forward "--%>"))
+ ((and (looking-back "-- %" (point-min))
+ (looking-at-p ">"))
+ (search-forward "--%>"))
+ ) ;cond
+ ) ;when
+ (setq pos (point-max))
+ (let ((continue (not (eobp))))
+ (while continue
+ (end-of-line)
+ ;;(message "%S %S" (point) (get-text-property (point) 'block-token))
+ (cond
+ ((eobp)
+ (setq continue nil))
+ ((and (not (get-text-property (point) 'tag-type))
+ (not (get-text-property (point) 'part-side))
+ (not (get-text-property (point) 'block-side)))
+ (setq pos (point)
+ continue nil))
+ (t
+ (forward-line))
+ ) ;cond
+ ) ;while
+ pos)))
+
+(defun web-mode-buffer-scan ()
+ "Scan entine buffer."
+ (interactive)
+ (web-mode-scan-region (point-min) (point-max)))
+
+(defun web-mode-scan-region (beg end &optional content-type)
+ "Identify nodes/parts/blocks and syntactic symbols (strings/comments/etc.)."
+ ;;(message "scan-region: beg(%d) end(%d) content-type(%S)" beg end content-type)
+ (setq web-mode-scan-beg beg
+ web-mode-scan-end end)
+ (web-mode-with-silent-modifications
+ (save-excursion
+ (save-restriction
+ (save-match-data
+ (let ((inhibit-point-motion-hooks t)
+ (inhibit-quit t))
+ (remove-list-of-text-properties beg end web-mode-scan-properties)
+ (cond
+ ((and content-type (string= content-type "php"))
+ )
+ ((and content-type (member content-type web-mode-part-content-types))
+ (put-text-property beg end 'part-side
+ (cond
+ ((string= content-type "javascript") 'javascript)
+ ((string= content-type "json") 'json)
+ ((string= content-type "jsx") 'jsx)
+ ((string= content-type "css") 'css)
+ ((string= content-type "sql") 'sql)
+ ((string= content-type "pug") 'pug)
+ ((string= content-type "sass") 'sass)
+ ((string= content-type "stylus") 'stylus)
+ ((string= content-type "markdown") 'markdown)
+ ((string= content-type "ruby") 'ruby)
+ ((string= content-type "typescript") 'typescript)
+ ))
+ (web-mode-scan-blocks beg end)
+ (web-mode-part-scan beg end content-type))
+ ((member web-mode-content-type web-mode-part-content-types)
+ (web-mode-scan-blocks beg end)
+ (web-mode-part-scan beg end))
+ ((string= web-mode-engine "riot")
+ (web-mode-scan-elements beg end)
+ (web-mode-scan-blocks beg end)
+ (web-mode-part-foreach beg end 'web-mode-part-scan))
+ (t
+ (web-mode-scan-blocks beg end)
+ (web-mode-scan-elements beg end)
+ (web-mode-part-foreach beg end 'web-mode-part-scan))
+ ) ;cond
+ (cons beg end)
+ ))))))
+
+;;---- LEXER BLOCKS ------------------------------------------------------------
+
+(defun web-mode-scan-blocks (reg-beg reg-end)
+ "Identifies blocks (with block-side, block-beg, block-end text properties)."
+ (save-excursion
+
+ (let ((i 0) open close closing-string sub1 sub2 pos tagopen tmp delim-open delim-close part-beg part-end tagclose)
+
+ (goto-char reg-beg)
+
+ ;;(message "%S: %Sx%S" (point) reg-beg reg-end)
+ ;;(message "regexp=%S" web-mode-block-regexp)
+ (while (and (< i 2000)
+ (> reg-end (point))
+ web-mode-block-regexp
+ (re-search-forward web-mode-block-regexp reg-end t)
+ (not (eobp)))
+
+ (setq i (1+ i)
+ closing-string nil
+ close nil
+ tagopen (match-string 0)
+ open (match-beginning 0)
+ delim-open nil
+ delim-close nil
+ pos nil)
+
+ (let ((l (length tagopen)))
+ (when (member (string-to-char tagopen) '(?\s ?\t))
+ (setq tagopen (replace-regexp-in-string "\\`[ \t]*" "" tagopen))
+ (setq open (+ open (- l (length tagopen))))
+ (setq l (length tagopen))
+ )
+ (setq sub1 (substring tagopen 0 1)
+ sub2 (substring tagopen 0 (if (>= l 2) 2 1)))
+ )
+ ;;(message " found block #(%S) at pos=(%S), part-type=(%S)" i open (get-text-property open 'part-side))
+ (cond
+
+ ((string= web-mode-engine "php")
+ (unless (member (char-after) '(?x ?X))
+ (setq closing-string '("<\\?". "\\?>")))
+ (cond
+ ((looking-at-p "<?php")
+ (setq delim-open "<?php"))
+ ((eq (char-after) ?\=)
+ (setq delim-open "<?="))
+ (t
+ (setq delim-open "<?"))
+ ) ;cond
+ (setq delim-close "?>")
+ ) ;php
+
+ ((string= web-mode-engine "erb")
+ (cond
+ ((string= sub2 "<%")
+ (setq closing-string '("<%". "%>")
+ delim-open "<%\\(==\\|[=-]\\)?"
+ delim-close "[-]?%>"))
+ (t
+ (setq closing-string "EOL"
+ delim-open "%"))
+ )
+ ) ;erb
+
+ ((string= web-mode-engine "django")
+ (cond
+ ((string= sub2 "{{")
+ (setq closing-string "EODQ"
+ ;;(setq closing-string '("{{" . "}}")
+ delim-open "{{"
+ delim-close "}}"))
+ ((string= sub2 "{%")
+ (setq closing-string "%}"
+ delim-open "{%[+-]?"
+ delim-close "[-]?%}"))
+ ((string= sub2 "{#")
+ (setq closing-string "#}"))
+ (t
+ (setq closing-string "EOL"
+ delim-open "#[#]?"))
+ )
+ ) ;django
+
+ ((string= web-mode-engine "ejs")
+ (setq closing-string "%>"
+ delim-open "<%[=-]?"
+ delim-close "[-]?%>")
+ ) ;ejs
+
+ ((string= web-mode-engine "lsp")
+ (setq closing-string "%>"
+ delim-open "<%[%#]?"
+ delim-close "%>")
+ ) ;lsp
+
+ ((string= web-mode-engine "mako")
+ (cond
+ ((and (string= tagopen "<%")
+ (member (char-after) '(?\s ?\n ?\!)))
+ (setq closing-string "%>"
+ delim-open "<%[!]?"
+ delim-close "%>"))
+ ((member sub2 '("<%" "</"))
+ (setq closing-string ">"
+ delim-open "</?%"
+ delim-close "/?>"))
+ ((string= sub2 "${")
+ (setq closing-string "}"
+ delim-open "${"
+ delim-close "}"))
+ (t
+ (setq closing-string "EOL"
+ delim-open "%"))
+ )
+ ) ;mako
+
+ ((string= web-mode-engine "cl-emb")
+ (cond
+ ((string= tagopen "<%#")
+ (setq closing-string "#%>"))
+ ((string= sub2 "<%")
+ (setq closing-string "%>"
+ delim-open "<%[=%]?"
+ delim-close "%>"))
+ )
+ ) ;cl-emb
+
+ ((string= web-mode-engine "artanis")
+ (cond
+ ((string= tagopen "<%;")
+ (setq closing-string "%>"))
+ ((string= tagopen "<%#|")
+ (setq closing-string "|#%>"))
+ ((string= sub2 "<@")
+ (setq closing-string "%>"
+ delim-open "<@\\(css\\|icon\\|include\\|js\\)"
+ delim-close "%>"))
+ ((string= sub2 "<%")
+ (setq closing-string "%>"
+ delim-open "<%[=]?"
+ delim-close "%>"))
+ )
+ ) ;artanis
+
+ ((string= web-mode-engine "elixir")
+ (cond
+ ((member (char-after) '(?\#))
+ (setq closing-string "%>"))
+ (t
+ (setq closing-string "%>"
+ delim-open "<%[=%]?"
+ delim-close "%>"))
+ )
+ ) ;elixir
+
+ ((string= web-mode-engine "mojolicious")
+ (cond
+ ((string= tagopen "<%#")
+ (setq closing-string "%>"))
+ ((string= sub2 "<%")
+ (setq closing-string "%>"
+ delim-open "<%\\(==\\|[=%]\\)?"
+ delim-close "%>"))
+ ((string= sub2 "%#")
+ (setq closing-string "EOL"))
+ (t
+ (setq closing-string "EOL"
+ delim-open "%\\(==\\|[=%]\\)?"))
+ )
+ ) ;mojolicious
+
+ ((string= web-mode-engine "ctemplate")
+ (cond
+ ((member tagopen '("{{{" "{{~"))
+ (setq closing-string "}~?}}"
+ delim-open "{{~?{"
+ delim-close "}~?}}")
+ )
+ ((string= tagopen "{~{")
+ (setq closing-string "}~?}"
+ delim-open "{~{"
+ delim-close "}~?}")
+ )
+ ((string= tagopen "{{!")
+ (setq closing-string (if (looking-at-p "--") "--}}" "}}"))
+ )
+ ((string= sub2 "{{")
+ (setq closing-string "}~?}"
+ delim-open "{{[>#/%^&]?"
+ delim-close "}~?}"))
+ (t
+ (setq closing-string "}}"
+ delim-open "${{"
+ delim-close "}}"))
+ )
+ ) ;ctemplate
+
+ ((string= web-mode-engine "aspx")
+ (setq closing-string "%>"
+ delim-open "<%[:=#@$]?"
+ delim-close "%>")
+ ) ;aspx
+
+ ((string= web-mode-engine "asp")
+ (cond
+ ((string= sub2 "<%")
+ (setq closing-string "%>"
+ delim-open "<%[:=#@$]?"
+ delim-close "%>"))
+ (t
+ (setq closing-string ">"
+ delim-open "</?"
+ delim-close "/?>"))
+ )
+ ) ;asp
+
+ ((string= web-mode-engine "jsp")
+ (cond
+ ((looking-at-p "--")
+ (setq closing-string "--%>"))
+ ((string= sub2 "<%")
+ (setq closing-string "%>"
+ delim-open "<%\\([!=@]\\|#=\\)?"
+ delim-close "[-]?%>"))
+ ((string= sub2 "${")
+ (setq closing-string "}"
+ delim-open "${"
+ delim-close "}"))
+ )
+ ) ;jsp
+
+ ((string= web-mode-engine "clip")
+ (setq closing-string ">"
+ delim-open "</?"
+ delim-close "/?>")
+ ) ;clip
+
+ ((string= web-mode-engine "blade")
+ (cond
+ ((string= tagopen "{{-")
+ (setq closing-string "--}}"))
+ ((string= tagopen "{!!")
+ (setq closing-string "!!}"
+ delim-open "{!!"
+ delim-close "!!}"))
+ ((string= tagopen "@{{")
+ (setq closing-string nil))
+ ((string= tagopen "{{{")
+ (setq closing-string "}}}"
+ delim-open "{{{"
+ delim-close "}}}"))
+ ((string= sub2 "{{")
+ (setq closing-string "}}"
+ delim-open "{{"
+ delim-close "}}"))
+ ((looking-at-p "[[:alnum:]]+\\.[[:alpha:]]+")
+ )
+ ((looking-at-p "[[:alnum:]]+(")
+ (setq closing-string ")"
+ delim-open "@"))
+ ((string= sub1 "@")
+ (setq closing-string "EOB"
+ delim-open "@"))
+ )
+ ) ;blade
+
+ ((string= web-mode-engine "smarty")
+ (cond
+ ((string= tagopen "{*")
+ (setq closing-string "*}")
+ )
+ ((string= tagopen "{#")
+ (setq closing-string "#}"
+ delim-open "{#"
+ delim-close "#}")
+ )
+ (t
+ (setq closing-string (cons "{" "}")
+ delim-open "{/?"
+ delim-close "}")
+ ) ;t
+ ) ;cond
+ ) ;smarty
+
+ ((string= web-mode-engine "hero")
+ (setq closing-string "%>"
+ delim-open "<%==?\\([biufsv]\\|bs\\)?\\|<%[:~@+!]?"
+ delim-close "%>")
+ ) ;hero
+
+ ((string= web-mode-engine "xoops")
+ (cond
+ ((string= tagopen "<{*")
+ (setq closing-string "*}>")
+ )
+ ((string= tagopen "<{#")
+ (setq closing-string "#}>"
+ delim-open "<{#"
+ delim-close "#}>")
+ )
+ (t
+ (setq closing-string (cons "<{" "}>")
+ delim-open "<{/?"
+ delim-close "}>")
+ ) ;t
+ ) ;cond
+ ) ;xoops
+
+ ((string= web-mode-engine "web2py")
+ (setq closing-string "}}"
+ delim-open "{{[=]?"
+ delim-close "}}")
+ ) ;web2py
+
+ ((string= web-mode-engine "expressionengine")
+ (cond
+ ((string= sub2 "{!--")
+ (setq closing-string "--}"))
+ (t
+ (setq closing-string '("{". "}")
+ delim-open "{/?"
+ delim-close "}")
+ )
+ )
+ ) ;expressionengine
+
+ ((string= web-mode-engine "dust")
+ (cond
+ ((string= sub2 "{!")
+ (setq closing-string "!}"))
+ (t
+ (setq closing-string '("{". "}")
+ delim-open "{[#/:?@><+^]?"
+ delim-close "/?}")
+ )
+ )
+ ) ;dust
+
+ ((string= web-mode-engine "svelte")
+ (cond
+ ((string= sub2 "{!")
+ (setq closing-string "!}"))
+ ((string= sub2 "{}")
+ (setq closing-string nil
+ delim-open nil
+ delim-close nil))
+ (t
+ (setq closing-string '("{". "}")
+ delim-open "{[#/:?@><+^]?"
+ delim-close "/?}")
+ )
+ )
+ ) ;svelte
+
+ ((string= web-mode-engine "closure")
+ (cond
+ ((string= sub2 "//")
+ (setq closing-string "EOL")
+ )
+ ((string= sub2 "/*")
+ (setq closing-string "*/")
+ )
+ (t
+ (setq closing-string "}"
+ delim-open "{/?"
+ delim-close "/?}")
+ )
+ )
+ ) ;closure
+
+ ((string= web-mode-engine "go")
+ (setq closing-string "}}"
+ delim-open "{{-?"
+ delim-close "-?}}")
+ ) ;go
+
+ ((string= web-mode-engine "angular")
+ (setq closing-string "}}"
+ delim-open "{{"
+ delim-close "}}")
+ ) ;angular
+
+ ((string= web-mode-engine "vue")
+ (cond
+ ((string-match-p "[:@][-[:alpha:]]+=\"" tagopen)
+ (setq closing-string "\""
+ delim-open tagopen
+ delim-close "\""))
+ ((string= tagopen "{{")
+ (setq closing-string "}}"
+ delim-open "{{"
+ delim-close "}}")))
+ ) ;vue
+
+ ((string= web-mode-engine "mason")
+ (cond
+ ((and (member sub2 '("<%" "</"))
+ (looking-at "[[:alpha:]]+"))
+ (if (member (match-string-no-properties 0) '("after" "around" "augment" "before" "def" "filter" "method" "override"))
+ (setq closing-string ">"
+ delim-open "<[/]?%"
+ delim-close ">")
+ (setq closing-string (concat "</%" (match-string-no-properties 0) ">")
+ delim-open "<[^>]+>"
+ delim-close "<[^>]+>")
+ ) ;if
+ )
+ ((and (string= sub2 "<%")
+ (eq (char-after) ?\s))
+ (setq closing-string "%>"
+ delim-open "<%"
+ delim-close "%>"))
+ ((string= tagopen "</&")
+ (setq closing-string ">"
+ delim-open "</&"
+ delim-close ">")
+ )
+ ((string= sub2 "<&")
+ (setq closing-string "&>"
+ delim-open "<&[|]?"
+ delim-close "&>"))
+ (t
+ (setq closing-string "EOL"
+ delim-open "%"))
+ )
+ ) ;mason
+
+ ((string= web-mode-engine "underscore")
+ (setq closing-string "%>"
+ delim-open "<%"
+ delim-close "%>")
+ ) ;underscore
+
+ ((string= web-mode-engine "template-toolkit")
+ (cond
+ ((string= tagopen "%%#")
+ (setq closing-string "EOL"))
+ ((string= tagopen "[%#")
+ (setq closing-string "%]"))
+ (t
+ (setq closing-string "%]"
+ delim-open "\\[%[-+]?"
+ delim-close "[-=+]?%\\]"))
+ )
+ ) ;template-toolkit
+
+ ((string= web-mode-engine "freemarker")
+ (cond
+ ((and (string= sub2 "<#") (eq (char-after) ?\-))
+ (setq closing-string "-->"))
+ ((string= sub1 "<")
+ (setq closing-string ">"
+ delim-open "</?[#@]"
+ delim-close "/?>"))
+ ((string= sub1 "[")
+ (setq closing-string "]"
+ delim-open "\\[/?[#@]"
+ delim-close "/?\\]"))
+ (t
+ (setq closing-string "}"
+ delim-open "${"
+ delim-close "}"))
+ )
+ ) ;freemarker
+
+ ((string= web-mode-engine "velocity")
+ (cond
+ ((string= sub2 "##")
+ (setq closing-string "EOL"))
+ ((string= sub2 "#*")
+ (setq closing-string "*#"))
+ (t
+ (setq closing-string "EOV"
+ delim-open "#"))
+ )
+ ) ;velocity
+
+ ((string= web-mode-engine "razor")
+ (cond
+ ((string= sub2 "@@")
+ (forward-char 2)
+ (setq closing-string nil))
+ ((string= sub2 "@*")
+ (setq closing-string "*@"))
+ ((string= sub1 "@")
+ (setq closing-string "EOR"
+ delim-open "@"))
+ ((and (string= sub1 "}")
+ (looking-at-p "[ ]*\n"))
+ ;;(setq closing-string "EOC")
+ (save-excursion
+ (let (paren-pos)
+ (setq paren-pos (web-mode-part-opening-paren-position (1- (point))))
+ (if (and paren-pos (get-text-property paren-pos 'block-side))
+ (setq closing-string "EOC")
+ (setq closing-string nil)
+ ) ;if
+ ) ;let
+ ) ;save-excursion
+ ;;(message "%s %S %S" sub2 (point) (get-text-property (point) 'part-side))
+ )
+ ((string= sub1 "}")
+ ;;(message "%s: %s" (point) sub1)
+ (save-excursion
+ (let (paren-pos)
+ (setq paren-pos (web-mode-part-opening-paren-position (1- (point))))
+ (if (and paren-pos (get-text-property paren-pos 'block-side))
+ (setq closing-string "EOR")
+ (setq closing-string nil)
+ ) ;if
+ ) ;let
+ ) ;save-excursion
+ ) ;case }
+ ) ;cond
+ ) ;razor
+
+ ((and (string= web-mode-engine "riot")
+ (not (get-text-property open 'part-side)))
+ (setq closing-string (if (string= tagopen "{") "}" "/// end script")
+ delim-open "{"
+ delim-close "}")
+ ) ;riot
+
+ ((string= web-mode-engine "spip")
+ (cond
+ ((and (string= sub1 "#")
+ (looking-at "[A-Z0-9_]+"))
+ (setq closing-string (match-string-no-properties 0)))
+ ((string= sub1 "(")
+ (setq closing-string '("(" . ")")))
+ ((string= sub1 "{")
+ (setq closing-string '("{" . "}")))
+ ((string= sub2 "<:")
+ (setq closing-string ":>"))
+ (t
+ (setq closing-string "]"))
+ ))
+
+ ((string= web-mode-engine "marko")
+ (setq closing-string "}"
+ delim-open "${"
+ delim-close "}")
+ ) ;marko
+
+ ) ;cond
+
+ (when closing-string
+ (cond
+
+ ((listp closing-string)
+ (cond
+ ((web-mode-rsf-balanced (car closing-string) (cdr closing-string) reg-end t)
+ (setq close (match-end 0)
+ pos (point))
+ )
+ ((and (string= web-mode-engine "php")
+ (string= "<?" sub2))
+
+ (if (or (text-property-not-all (1+ open) (point-max) 'tag-beg nil)
+ (text-property-not-all (1+ open) (point-max) 'block-beg nil)
+ (looking-at-p "[ \t\n]*<"))
+ (setq close nil
+ delim-close nil
+ pos (point))
+ (setq close (point-max)
+ delim-close nil
+ pos (point-max))
+ ) ;if
+ ) ;case
+ ) ;cond
+ ) ;case listp
+
+ ((and (string= web-mode-engine "smarty")
+ (string= closing-string "}"))
+ (goto-char open)
+ (setq tmp (web-mode-closing-delimiter-position
+ "}"
+ (point)
+ (line-end-position)))
+ (if tmp
+ (setq tmp (1+ tmp))
+ (setq tmp (line-end-position)))
+ (goto-char tmp)
+ (setq close (point)
+ pos (point))
+ )
+
+ ((and (member web-mode-engine '("closure"))
+ (string= closing-string "}"))
+ (when (web-mode-closure-skip reg-beg reg-end)
+ (setq close (point)
+ pos (point))
+ ;;(message "close=%S pos=%S" close pos)
+ ) ;when
+ )
+
+ ((string= closing-string "EOB")
+ (web-mode-blade-skip open)
+ (setq close (point)
+ pos (point)))
+
+ ((string= closing-string "EOL")
+ (end-of-line)
+ (setq close (point)
+ pos (point)))
+
+ ((string= closing-string "EOC")
+ (setq close (point)
+ pos (point)))
+
+ ((string= closing-string "EODQ")
+ (when (web-mode-django-skip reg-beg reg-end)
+ (setq close (point)
+ pos (point))
+ ))
+
+ ((string= closing-string "EOR")
+ (web-mode-razor-skip open)
+ (setq close (if (> (point) reg-end) reg-end (point))
+ pos (if (> (point) reg-end) reg-end (point)))
+ (goto-char pos))
+
+ ((string= closing-string "EOV")
+ (web-mode-velocity-skip open)
+ (setq close (point)
+ pos (point)))
+
+ ((and (member web-mode-engine '("ctemplate"))
+ (re-search-forward closing-string reg-end t))
+ (setq close (match-end 0)
+ pos (point)))
+
+ ((search-forward closing-string reg-end t)
+ (setq close (match-end 0)
+ pos (point)))
+ ) ;cond
+
+ (when (and close (>= reg-end pos))
+ ;;(message "pos(%S) : open(%S) close(%S)" pos open close)
+ (put-text-property open (1+ open) 'block-beg 0)
+ (put-text-property open (1+ open) 'block-controls 0)
+ (put-text-property open close 'block-side t)
+ (put-text-property (1- close) close 'block-end t)
+ (when delim-open
+ (web-mode-block-delimiters-set open close delim-open delim-close))
+ (web-mode-block-scan open close)
+ (cond
+ ((and (string= web-mode-engine "erb")
+ (looking-at-p "<%= javascript_tag do %>"))
+ (setq tagopen "<%= javascript_tag do %>"))
+ ((and (string= web-mode-engine "mojolicious")
+ (looking-at-p "%= javascript begin"))
+ (setq tagopen "%= javascript begin"))
+ ((and (string= web-mode-engine "mako")
+ (looking-at-p "<%block filter=\"collect_js\">"))
+ (setq tagopen "<%block filter=\"collect_js\">"))
+ ((and (string= web-mode-engine "mako")
+ (looking-at-p "<%block filter=\"collect_css\">"))
+ (setq tagopen "<%block filter=\"collect_css\">"))
+ ((and (string= web-mode-engine "django")
+ (looking-at-p "{% javascript %}"))
+ (setq tagopen "{% javascript %}"))
+ ((and (string= web-mode-engine "django")
+ (looking-at-p "{% schema %}"))
+ (setq tagopen "{% schema %}"))
+ ((and (string= web-mode-engine "django")
+ (looking-at-p "{% stylesheet %}"))
+ (setq tagopen "{% stylesheet %}"))
+ )
+ ;;(message "%S %s" (point) tagopen)
+ (when (and (member tagopen '("<r:script" "<r:style"
+ "<c:js" "<c:css"
+ "<%= javascript_tag do %>"
+ "<%block filter=\"collect_js\">"
+ "<%block filter=\"collect_css\">"
+ "{% javascript %}"
+ "{% schema %}"
+ "{% stylesheet %}"
+ "%= javascript begin"))
+ (setq part-beg close)
+ (setq tagclose
+ (cond
+ ((string= tagopen "<r:script") "</r:script")
+ ((string= tagopen "<r:style") "</r:style")
+ ((string= tagopen "<c:js") "</c:js")
+ ((string= tagopen "<c:css") "</c:css")
+ ((string= tagopen "{% javascript %}") "{% endjavascript %}")
+ ((string= tagopen "{% schema %}") "{% endschema %}")
+ ((string= tagopen "{% stylesheet %}") "{% endstylesheet %}")
+ ((string= tagopen "%= javascript begin") "% end")
+ ((string= tagopen "<%= javascript_tag do %>") "<% end %>")
+ ((member tagopen '("<%block filter=\"collect_js\">"
+ "<%block filter=\"collect_css\">")) "</%block")
+ ))
+ (web-mode-sf tagclose)
+ (setq part-end (match-beginning 0))
+ (> part-end part-beg))
+ ;;(message "end=%S" (point))
+ (put-text-property part-beg part-end
+ 'part-side
+ (cond
+ ((member tagopen '("<r:style" "<c:css" "<%block filter=\"collect_css\">" "{% stylesheet %}")) 'css)
+ (t 'javascript)))
+ (setq pos part-beg
+ part-beg nil
+ part-end nil)
+ ) ;when
+ ) ;when close
+
+ (if pos (goto-char pos))
+
+ ) ;when closing-string
+
+ ) ;while
+
+ (cond
+ ((>= i 2000)
+ (message "scan-blocks ** warning (%S) **" i))
+ ((string= web-mode-engine "razor")
+ (web-mode-block-foreach reg-beg reg-end 'web-mode-block-scan))
+ ((string= web-mode-engine "django")
+ (web-mode-scan-engine-comments reg-beg reg-end
+ "{% comment %}" "{% endcomment %}"))
+ ((string= web-mode-engine "mako")
+ (web-mode-scan-engine-comments reg-beg reg-end
+ "<%doc>" "</%doc>"))
+ ((string= web-mode-engine "mason")
+ (web-mode-scan-engine-comments reg-beg reg-end
+ "<%doc>" "</%doc>"))
+ ) ;cond
+
+ )))
+
+(defun web-mode-scan-engine-comments (reg-beg reg-end tag-start tag-end)
+ "Scan engine comments (mako, django)."
+ (save-excursion
+ (let (beg end (continue t))
+ (goto-char reg-beg)
+ (while (and continue
+ (< (point) reg-end)
+ (re-search-forward tag-start reg-end t))
+ (goto-char (match-beginning 0))
+ (setq beg (point))
+ (if (not (re-search-forward tag-end reg-end t))
+ (setq continue nil)
+ (setq end (point))
+ (remove-list-of-text-properties beg end web-mode-scan-properties)
+ (add-text-properties beg end '(block-side t block-token comment))
+ (put-text-property beg (1+ beg) 'block-beg 0)
+ (put-text-property (1- end) end 'block-end t)
+ ) ;if
+ ) ;while
+ )))
+
+(defun web-mode-closure-skip (reg-beg reg-end)
+ (let (regexp char pos inc continue found)
+ (setq regexp "[\"'{}]"
+ inc 0)
+ (while (and (not found) (re-search-forward regexp reg-end t))
+ (setq char (char-before))
+ (cond
+ ((get-text-property (point) 'block-side)
+ (setq found t))
+ ((eq char ?\{)
+ (setq inc (1+ inc)))
+ ((eq char ?\})
+ (cond
+ ((and (not (eobp))
+ (< inc 1))
+ (setq found t
+ pos (point)))
+ ((> inc 0)
+ (setq inc (1- inc)))
+ )
+ )
+ ((eq char ?\')
+ (setq continue t)
+ (while (and continue (search-forward "'" reg-end t))
+ (setq continue (web-mode-string-continue-p reg-beg))
+ )
+ )
+ ((eq char ?\")
+ (setq continue t)
+ (while (and continue (search-forward "\"" reg-end t))
+ (setq continue (web-mode-string-continue-p reg-beg))
+ )
+ )
+ ) ;cond
+ ) ;while
+ pos))
+
+(defun web-mode-django-skip (reg-beg reg-end)
+ (let (regexp char pos inc continue found)
+ (setq regexp "[\"'{}]"
+ inc 0)
+ (while (and (not found) (re-search-forward regexp reg-end t))
+ (setq char (char-before))
+ (cond
+ ((get-text-property (point) 'block-side)
+ (setq found t))
+ ((eq char ?\{)
+ (setq inc (1+ inc)))
+ ((eq char ?\})
+ (cond
+ ((and (not (eobp))
+ (eq (char-after) ?\})
+ (< inc 2))
+ (forward-char)
+ (setq found t
+ pos (1+ (point))))
+ ((> inc 0)
+ (setq inc (1- inc)))
+ )
+ )
+ ((eq char ?\')
+ (setq continue t)
+ (while (and continue (search-forward "'" reg-end t))
+ (setq continue (web-mode-string-continue-p reg-beg))
+ )
+ )
+ ((eq char ?\")
+ (setq continue t)
+ (while (and continue (search-forward "\"" reg-end t))
+ (setq continue (web-mode-string-continue-p reg-beg))
+ )
+ )
+ ) ;cond
+ ) ;while
+ pos))
+
+(defun web-mode-blade-skip (pos)
+ (goto-char pos)
+ (forward-char)
+ (skip-chars-forward "a-zA-Z0-9_-"))
+
+(defun web-mode-velocity-skip (pos)
+ (goto-char pos)
+ (let ((continue t) (i 0))
+ (when (eq ?\# (char-after))
+ (forward-char))
+ (when (member (char-after) '(?\$ ?\@))
+ (forward-char))
+ (when (member (char-after) '(?\!))
+ (forward-char))
+ (cond
+ ((member (char-after) '(?\{))
+ (search-forward "}" nil t))
+ ((looking-at-p "def \\|define ")
+ (search-forward ")" (line-end-position) t))
+ (t
+ (setq continue t)
+ (while continue
+ (skip-chars-forward "a-zA-Z0-9_-")
+ (when (> (setq i (1+ i)) 500)
+ (message "velocity-skip ** warning (%S) **" pos)
+ (setq continue nil))
+ (when (member (char-after) '(?\())
+ (search-forward ")" nil t))
+ (if (member (char-after) '(?\.))
+ (forward-char)
+ (setq continue nil))
+ ) ;while
+ ) ;t
+ ) ;cond
+ ))
+
+(defun web-mode-razor-skip (pos)
+ (goto-char pos)
+ (let ((continue t) (i 0))
+ (while continue
+ (skip-chars-forward " =@a-zA-Z0-9_-")
+ (cond
+ ((> (setq i (1+ i)) 500)
+ (message "razor-skip ** warning **")
+ (setq continue nil))
+ ((and (eq (char-after) ?\*)
+ (eq (char-before) ?@))
+ (when (not (search-forward "*@" nil t))
+ (setq continue nil))
+ )
+ ((looking-at-p "@[({]")
+ (forward-char)
+ (when (setq pos (web-mode-closing-paren-position (point)))
+ (goto-char pos))
+ (forward-char)
+ )
+ ((and (not (eobp)) (eq ?\( (char-after)))
+ (cond
+ ((looking-at-p "[ \n]*[<@]")
+ (setq continue nil))
+ ((setq pos (web-mode-closing-paren-position))
+ (goto-char pos)
+ (forward-char))
+ (t
+ (forward-char))
+ ) ;cond
+ )
+ ((and (not (eobp)) (eq ?\< (char-after)) (looking-back "[a-z]" (point-min)))
+ (setq pos (point))
+ (cond
+ ;; #988
+ ((search-forward ">" (line-end-position) t)
+ (goto-char pos)
+ (setq continue nil)
+ )
+ (t
+ (setq continue nil))
+ ) ;cond
+ )
+ ((and (not (eobp)) (eq ?\. (char-after)))
+ (forward-char))
+ ((and (not (eobp)) (looking-at-p "[ \n]*else"))
+ (re-search-forward "[ \t]*else")
+ )
+ ((looking-at-p "[ \n]*{")
+ (search-forward "{")
+ (search-forward "=>" (point-at-eol) 't)
+ (if (looking-at-p "[ \n]*[<@]")
+ (setq continue nil)
+ (backward-char)
+ (when (setq pos (web-mode-closing-paren-position))
+ (goto-char pos))
+ (forward-char)
+ ) ;if
+ )
+ ((looking-at-p "}")
+ (forward-char))
+ (t
+ (setq continue nil))
+ ) ;cond
+ ) ;while
+ ))
+
+(defun web-mode-block-delimiters-set (reg-beg reg-end delim-open delim-close)
+ "Set text-property 'block-token to 'delimiter-(beg|end) on block delimiters (e.g. <?php and ?>)"
+ ;;(message "reg-beg(%S) reg-end(%S) delim-open(%S) delim-close(%S)" reg-beg reg-end delim-open delim-close)
+ (when (member web-mode-engine
+ '("artanis" "asp" "aspx" "cl-emb" "clip" "closure" "ctemplate" "django" "dust"
+ "elixir" "ejs" "erb" "expressionengine" "freemarker" "go" "hero" "jsp" "lsp"
+ "mako" "mason" "mojolicious"
+ "smarty" "template-toolkit" "web2py" "xoops" "svelte"))
+ (save-excursion
+ (when delim-open
+ (goto-char reg-beg)
+ (looking-at delim-open)
+ (setq delim-open (match-string-no-properties 0)))
+ (when delim-close
+ (goto-char reg-end)
+ (looking-back delim-close reg-beg t)
+ (setq delim-close (match-string-no-properties 0)))
+ ))
+ (when delim-open
+ (put-text-property reg-beg (+ reg-beg (length delim-open))
+ 'block-token 'delimiter-beg))
+ (when delim-close
+ (put-text-property (- reg-end (length delim-close)) reg-end
+ 'block-token 'delimiter-end))
+ )
+
+(defun web-mode-block-foreach (reg-beg reg-end func)
+ (let ((i 0) (continue t) (block-beg reg-beg) (block-end nil))
+ (while continue
+ (setq block-end nil)
+ (unless (get-text-property block-beg 'block-beg)
+ (setq block-beg (web-mode-block-next-position block-beg)))
+ (when (and block-beg (< block-beg reg-end))
+ (setq block-end (web-mode-block-end-position block-beg)))
+ (cond
+ ((> (setq i (1+ i)) 2000)
+ (message "process-blocks ** warning (%S) **" (point))
+ (setq continue nil))
+ ((or (null block-end) (> block-end reg-end))
+ (setq continue nil))
+ (t
+ (setq block-end (1+ block-end))
+ (funcall func block-beg block-end)
+ (setq block-beg block-end)
+ ) ;t
+ ) ;cond
+ ) ;while
+ ))
+
+(defun web-mode-block-scan (block-beg block-end)
+ (let (sub1 sub2 sub3 regexp token-type)
+
+ ;;(message "block-beg=%S block-end=%S" block-beg block-end)
+ ;;(remove-text-properties block-beg block-end web-mode-scan-properties)
+
+ (goto-char block-beg)
+
+ (cond
+ ((>= (point-max) (+ block-beg 3))
+ (setq sub3 (buffer-substring-no-properties block-beg (+ block-beg 3))
+ sub2 (buffer-substring-no-properties block-beg (+ block-beg 2))
+ sub1 (buffer-substring-no-properties block-beg (+ block-beg 1)))
+ )
+ ((>= (point-max) (+ block-beg 2))
+ (setq sub3 (buffer-substring-no-properties block-beg (+ block-beg 2))
+ sub2 (buffer-substring-no-properties block-beg (+ block-beg 2))
+ sub1 (buffer-substring-no-properties block-beg (+ block-beg 1)))
+ )
+ (t
+ (setq sub1 (buffer-substring-no-properties block-beg (+ block-beg 1)))
+ (setq sub2 sub1
+ sub3 sub1)
+ )
+ )
+
+ (cond
+
+ ((member web-mode-engine '("php" "lsp" "python" "web2py" "mason"))
+ (setq regexp web-mode-engine-token-regexp))
+
+ ((string= web-mode-engine "mako")
+ (cond
+ ((string= sub2 "##")
+ (setq token-type 'comment)
+ )
+ (t
+ (setq regexp web-mode-engine-token-regexp))
+ )
+ ) ;mako
+
+ ((string= web-mode-engine "django")
+ (cond
+ ((member sub2 '("{{" "{%"))
+ (setq regexp "\"\\|'"))
+ ((string= sub2 "{#")
+ (setq token-type 'comment))
+ )
+ ) ;django
+
+ ((string= web-mode-engine "ctemplate")
+ (cond
+ ((string= sub3 "{{!")
+ (setq token-type 'comment))
+ ((member sub2 '("{{"))
+ )
+ )
+ ) ;ctemplate
+
+ ((string= web-mode-engine "go")
+ (cond
+ ((string= sub3 "{{/")
+ (setq token-type 'comment))
+ ((string= sub2 "{{")
+ (setq regexp "\"\\|'"))
+ )
+ ) ;go
+
+ ((string= web-mode-engine "hero")
+ (cond
+ ((string= sub3 "<%#")
+ (setq token-type 'comment))
+ (t
+ (setq regexp "\"\\|'"))
+ )
+ ) ;hero
+
+ ((string= web-mode-engine "razor")
+ (cond
+ ((string= sub2 "@*")
+ (setq token-type 'comment))
+ (t
+ (setq regexp "//\\|@\\*\\|\"\\|'"))
+ )
+ ) ;razor
+
+ ((string= web-mode-engine "blade")
+ (cond
+ ((string= sub3 "{{-")
+ (setq token-type 'comment))
+ (t
+ (setq regexp "\"\\|'"))
+ )
+ ) ;blade
+
+ ((string= web-mode-engine "cl-emb")
+ (cond
+ ((string= sub3 "<%#")
+ (setq token-type 'comment))
+ (t
+ (setq regexp "\"\\|'"))
+ )
+ ) ;cl-emb
+
+ ((string= web-mode-engine "artanis")
+ (cond
+ ((string= sub3 "<%;")
+ (setq token-type 'comment))
+ ((string= sub3 "<%#|")
+ (setq token-type 'comment))
+ (t
+ (setq regexp "\""))
+ )
+ ) ;artanis
+
+ ((string= web-mode-engine "elixir")
+ (cond
+ ((string= sub3 "<%#")
+ (setq token-type 'comment))
+ (t
+ (setq regexp "\"\\|'"))
+ )
+ ) ;elixir
+
+ ((string= web-mode-engine "mojolicious")
+ (cond
+ ((or (string= sub2 "%#") (string= sub3 "<%#"))
+ (setq token-type 'comment))
+ (t
+ (setq regexp "\"\\|'"))
+ )
+ ) ;mojolicious
+
+ ((string= web-mode-engine "velocity")
+ (cond
+ ((member sub2 '("##" "#*"))
+ (setq token-type 'comment))
+ ((member sub1 '("$" "#"))
+ (setq regexp "\"\\|'"))
+ )
+ ) ;velocity
+
+ ((string= web-mode-engine "jsp")
+ (cond
+ ((string= sub3 "<%-")
+ (setq token-type 'comment))
+ ((string= sub3 "<%@")
+ (setq regexp "/\\*"))
+ ((member sub2 '("${" "#{"))
+ (setq regexp "\"\\|'"))
+ ((string= sub2 "<%")
+ (setq regexp "//\\|/\\*\\|\"\\|'"))
+ )
+ ) ;jsp
+
+ ((string= web-mode-engine "clip")
+ (setq regexp nil)
+ ) ;clip
+
+ ((and (string= web-mode-engine "asp")
+ (string= sub2 "<%"))
+ (setq regexp "//\\|/\\*\\|\"\\|''")
+ ) ;asp
+
+ ((string= web-mode-engine "aspx")
+ (cond
+ ((string= sub3 "<%-")
+ (setq token-type 'comment))
+ ((string= sub3 "<%@")
+ (setq regexp "/\\*"))
+ ((string= sub3 "<%$")
+ (setq regexp "\"\\|'"))
+ (t
+ (setq regexp "//\\|/\\*\\|\"\\|'"))
+ )
+ ) ;aspx
+
+ ((string= web-mode-engine "freemarker")
+ (cond
+ ((member sub3 '("<#-" "[#-"))
+ (setq token-type 'comment))
+ ((member sub2 '("${" "#{"))
+ (setq regexp "\"\\|'"))
+ ((or (member sub2 '("<@" "[@" "<#" "[#"))
+ (member sub3 '("</@" "[/@" "</#" "[/#")))
+ (setq regexp "\"\\|'"))
+ )
+ ) ;freemarker
+
+ ((member web-mode-engine '("ejs" "erb"))
+ (cond
+ ((string= sub3 "<%#")
+ (setq token-type 'comment))
+ (t
+ (setq regexp web-mode-engine-token-regexp))
+ )
+ ) ;erb
+
+ ((string= web-mode-engine "template-toolkit")
+ (cond
+ ((member sub3 '("[%#" "%%#"))
+ (setq token-type 'comment))
+ (t
+ (setq regexp "#\\|\"\\|'"))
+ )
+ ) ;template-toolkit
+
+ ((string= web-mode-engine "underscore")
+ (setq regexp "/\\*\\|\"\\|'")
+ ) ;underscore
+
+ ((string= web-mode-engine "angular")
+ (setq regexp "#\\|\"\\|'")) ;angular
+
+ ((string= web-mode-engine "vue")
+ ) ;vue
+
+ ((string= web-mode-engine "smarty")
+ (cond
+ ((string= sub2 "{*")
+ (setq token-type 'comment))
+ (t
+ (setq regexp "\"\\|'")))
+ ) ;smarty
+
+ ((string= web-mode-engine "xoops")
+ (cond
+ ((string= sub3 "<{*")
+ (setq token-type 'comment))
+ (t
+ (setq regexp "\"\\|'")))
+ ) ;xoops
+
+ ((string= web-mode-engine "spip")
+ (if (string= (buffer-substring-no-properties
+ block-beg (+ block-beg 7))
+ "[(#REM)")
+ (setq token-type 'comment
+ regexp "\\]")))
+
+ ((string= web-mode-engine "dust")
+ (cond
+ ((string= sub2 "{!")
+ (setq token-type 'comment))
+ (t
+ (setq regexp "\"\\|'"))
+ )
+ ) ;dust
+
+ ((string= web-mode-engine "expressionengine")
+ (cond
+ ((string= sub2 "{!")
+ (setq token-type 'comment))
+ (t
+ (setq regexp "\"\\|'")))
+ ) ;expressionengine
+
+ ((string= web-mode-engine "closure")
+ (cond
+ ((member sub2 '("/*" "//"))
+ (setq token-type 'comment))
+ (t
+ (setq regexp "\"\\|'"))
+ )
+ ) ;closure
+
+ ((string= web-mode-engine "svelte")
+ ) ;svelte
+
+ ) ;cond
+
+ (cond
+ (token-type
+ (put-text-property block-beg block-end 'block-token token-type))
+ ((and regexp
+ (> (- block-end block-beg) 6))
+ (web-mode-block-tokenize
+ (web-mode-block-code-beginning-position block-beg)
+ (web-mode-block-code-end-position block-beg)
+ regexp)
+ )
+ ) ;cond
+
+ ))
+
+(defun web-mode-block-tokenize (reg-beg reg-end &optional regexp)
+ (unless regexp (setq regexp web-mode-engine-token-regexp))
+ ;;(message "tokenize: reg-beg(%S) reg-end(%S) regexp(%S)" reg-beg reg-end regexp)
+ ;;(message "tokenize: reg-beg(%S) reg-end(%S) command(%S)" reg-beg reg-end this-command)
+ ;;(message "%S>%S : %S" reg-beg reg-end (buffer-substring-no-properties reg-beg reg-end))
+ (save-excursion
+ (let ((pos reg-beg) beg char match continue (flags 0) token-type token-end)
+
+ (remove-list-of-text-properties reg-beg reg-end '(block-token))
+
+ ;; TODO : vérifier la cohérence
+ (put-text-property reg-beg reg-end 'block-side t)
+
+ (goto-char reg-beg)
+
+ (when (> (point) reg-end)
+ (message "block-tokenize ** reg-beg(%S) > reg-end(%S) **" reg-beg reg-end))
+
+ (while (and (< (point) reg-end) (re-search-forward regexp reg-end t))
+ (setq beg (match-beginning 0)
+ match (match-string 0)
+ continue t
+ token-type 'comment
+ token-end (if (< reg-end (line-end-position)) reg-end (line-end-position))
+ char (aref match 0))
+ (cond
+
+ ((and (string= web-mode-engine "asp") (string= match "''"))
+ (goto-char token-end))
+
+ ((and (string= web-mode-engine "razor") (eq char ?\'))
+ (cond
+ ((looking-at-p "\\(.\\|[\\][bfntr]\\|[\\]u....\\)'")
+ (search-forward "'" reg-end t)
+ (setq token-type 'string)
+ )
+ (t
+ (re-search-forward "[[:alnum:]_-]+")
+ (setq token-type 'symbol)
+ )))
+
+ ((eq char ?\')
+ (setq token-type 'string)
+ (while (and continue (search-forward "'" reg-end t))
+ (setq continue (web-mode-string-continue-p reg-beg))
+ ))
+
+ ((eq char ?\")
+ (setq token-type 'string)
+ (while (and continue (search-forward "\"" reg-end t))
+ (setq continue (web-mode-string-continue-p reg-beg))
+ ))
+
+ ((string= match "//")
+ (goto-char token-end))
+
+ ((eq char ?\;)
+ (goto-char token-end))
+
+ ((string= match "#|")
+ (unless (search-forward "|#" reg-end t)
+ (goto-char token-end)))
+
+ ((eq char ?\#)
+ (goto-char token-end))
+
+ ((string= match "/*")
+ (unless (search-forward "*/" reg-end t)
+ (goto-char token-end))
+ )
+
+ ((string= match "@*")
+ (unless (search-forward "*@" reg-end t)
+ (goto-char token-end)))
+
+ ((eq char ?\<)
+ (setq token-type 'string)
+ (re-search-forward (concat "^[ ]*" (match-string 1)) reg-end t))
+
+ (t
+ (message "block-tokenize ** token end (%S) **" beg)
+ (setq token-type nil))
+
+ ) ;cond
+
+ (put-text-property beg (point) 'block-token token-type)
+
+ (when (eq token-type 'comment)
+ (put-text-property beg (1+ beg) 'syntax-table (string-to-syntax "<"))
+ (if (or (< (point) (line-end-position)) (= (point) (point-max)))
+ (put-text-property (1- (point)) (point) 'syntax-table (string-to-syntax ">")) ;#445 #480
+ (put-text-property (point) (1+ (point)) 'syntax-table (string-to-syntax ">")) ;#377
+ )
+ )
+
+ ) ;while
+
+ (web-mode-block-controls-unset pos)
+
+ )))
+
+(defun web-mode-set-php-controls (reg-beg reg-end)
+ (goto-char reg-beg)
+ (let (match controls
+ (continue t)
+ (regexp "endif\\|endforeach\\|endfor\\|endwhile\\|elseif\\|else\\|if\\|foreach\\|for\\|while"))
+ (while continue
+ (if (not (web-mode-block-rsf regexp reg-end))
+ (setq continue nil)
+ (setq match (match-string-no-properties 0))
+;; (message "%S %S" match (point))
+ (cond
+ ((and (member match '("else" "elseif"))
+ (looking-at-p "[ ]*[:(]"))
+ (setq controls (append controls (list (cons 'inside "if"))))
+ )
+ ((and (>= (length match) 3)
+ (string= (substring match 0 3) "end"))
+ (setq controls (append controls (list (cons 'close (substring match 3)))))
+ )
+ ((and (progn (skip-chars-forward "[ ]") t)
+ (eq (char-after) ?\()
+ (web-mode-closing-paren reg-end)
+ ;;(progn (message "ixi%S" (point)))
+ (looking-at-p ")[ ]*:"))
+ (setq controls (append controls (list (cons 'open match))))
+ )
+ ) ;cond
+ ) ;if
+ ) ;while
+ ;;(message "%S-%S %S" reg-beg reg-end controls)
+ (when (and controls (> (length controls) 1))
+ (setq controls (web-mode-block-controls-reduce controls)))
+ controls))
+
+(defun web-mode-block-controls-reduce (controls)
+ (when (and (eq (car (car controls)) 'open)
+ (member (cons 'close (cdr (car controls))) controls))
+ (setq controls nil))
+ controls)
+
+(defun web-mode-block-controls-unset (pos)
+ (cond
+ ((null (get-text-property pos 'block-side))
+ (message "block-controls-unset ** invalid value (%S) **" pos))
+ ((or (get-text-property pos 'block-beg)
+ (setq pos (web-mode-block-beginning-position pos)))
+ (put-text-property pos (1+ pos) 'block-controls 0))
+ (t
+ (message "block-controls-unset ** failure (%S) **" (point)))
+ ))
+
+(defun web-mode-block-controls-get (pos)
+ (web-mode-with-silent-modifications
+ (let ((controls nil))
+ (cond
+ ((null (get-text-property pos 'block-side))
+ (message "block-controls-get ** invalid value (%S) **" pos))
+ ((or (get-text-property pos 'block-beg)
+ (setq pos (web-mode-block-beginning-position pos)))
+ (setq controls (get-text-property pos 'block-controls))
+ (when (integerp controls)
+ (web-mode-block-controls-set pos (web-mode-block-end-position pos))
+ (setq controls (get-text-property pos 'block-controls))
+ )
+ )
+ (t
+ (message "block-controls-get ** failure (%S) **" (point)))
+ ) ;cond
+ controls)))
+
+(defun web-mode-block-controls-set (reg-beg reg-end)
+ (save-excursion
+ (goto-char reg-beg)
+ (let (controls pos type control)
+
+ (cond
+
+ ((null web-mode-engine)
+ (message "block-controls-set ** unknown engine (%S) **" web-mode-engine)
+ )
+
+ ((string= web-mode-engine "php")
+ (setq controls (web-mode-set-php-controls reg-beg reg-end))
+ (when (web-mode-block-starts-with "}" reg-beg)
+ (setq controls (append controls (list (cons 'close "{")))))
+ (when (web-mode-block-ends-with (cons "{" "}") reg-beg)
+ (setq controls (append controls (list (cons 'open "{")))))
+ ) ;php
+
+ ((string= web-mode-engine "ejs")
+ (cond
+ ((web-mode-block-ends-with "}[ ]*else[ ]*{" reg-beg)
+ (setq controls (append controls (list (cons 'inside "{")))))
+ ((web-mode-block-starts-with "}" reg-beg)
+ (setq controls (append controls (list (cons 'close "{")))))
+ ((web-mode-block-ends-with "{" reg-beg)
+ (setq controls (append controls (list (cons 'open "{")))))
+ )
+ ) ;ejs
+
+ ((string= web-mode-engine "erb")
+ (cond
+ ((web-mode-block-starts-with "else\\|elsif\\|when" reg-beg)
+ (setq controls (append controls (list (cons 'inside "ctrl")))))
+ ((web-mode-block-starts-with "end" reg-beg)
+ (setq controls (append controls (list (cons 'close "ctrl")))))
+ ((web-mode-block-ends-with " do\\( |.*|\\)?" reg-beg)
+ (setq controls (append controls (list (cons 'open "ctrl")))))
+ ((and (web-mode-block-starts-with "\\(for\\|if\\|unless\\|case\\)\\_>" reg-beg)
+ (not (web-mode-block-ends-with "end" reg-end)))
+ (setq controls (append controls (list (cons 'open "ctrl")))))
+ )
+ ) ;erb
+
+ ((string= web-mode-engine "django")
+ (cond
+ ((and (string= web-mode-minor-engine "jinja") ;#504
+ (web-mode-block-starts-with "else\\_>" reg-beg))
+ (let ((continue t)
+ (pos reg-beg)
+ (ctrl nil))
+ (while continue
+ (cond
+ ((null (setq pos (web-mode-block-control-previous-position 'open pos)))
+ (setq continue nil))
+ ((member (setq ctrl (cdr (car (get-text-property pos 'block-controls)))) '("if" "ifequal" "ifnotequal" "for"))
+ (setq continue nil)
+ )
+ ) ;cond
+ )
+ (setq controls (append controls (list (cons 'inside (or ctrl "if")))))
+ )
+ )
+ ((web-mode-block-starts-with "form_start[ ]*(" reg-beg)
+ (setq controls (append controls (list (cons 'open "form_start")))))
+ ((web-mode-block-starts-with "form_end[ ]*(" reg-beg)
+ (setq controls (append controls (list (cons 'close "form_start")))))
+ ((not (eq (char-after (1+ reg-beg)) ?\%))
+ )
+ ((web-mode-block-starts-with "\\(else\\|els?if\\)" reg-beg)
+ (let ((continue t)
+ (pos reg-beg)
+ (ctrl nil))
+ (while continue
+ (cond
+ ((null (setq pos (web-mode-block-control-previous-position 'open pos)))
+ (setq continue nil))
+ ((member (setq ctrl (cdr (car (get-text-property pos 'block-controls)))) '("if" "ifequal" "ifnotequal"))
+ (setq continue nil)
+ )
+ ) ;cond
+ ) ;while
+ (setq controls (append controls (list (cons 'inside (or ctrl "if")))))
+ ) ;let
+ ) ;case else
+ ((web-mode-block-starts-with "\\(empty\\)" reg-beg)
+ (setq controls (append controls (list (cons 'inside "for")))))
+ ((web-mode-block-starts-with "end\\([[:alpha:]]+\\)" reg-beg)
+ (setq controls (append controls (list (cons 'close (match-string-no-properties 1))))))
+ ((web-mode-block-starts-with "set [[:alpha:]]+[ ]*%}" reg-beg)
+ (setq controls (append controls (list (cons 'open "set")))))
+ ((web-mode-block-starts-with (concat web-mode-django-control-blocks-regexp "[ %]") reg-beg)
+ (let (control)
+ (setq control (match-string-no-properties 1))
+ ;;(message "%S %S %S" control (concat "end" control) web-mode-django-control-blocks)
+ (when (member (concat "end" control) web-mode-django-control-blocks)
+ (setq controls (append controls (list (cons 'open control))))
+ ) ;when
+ ) ;let
+ ) ;case
+ ) ;cond
+ ) ;django
+
+ ((string= web-mode-engine "smarty")
+ (cond
+ ((and (eq (char-after (1+ reg-beg)) ?\/)
+ (web-mode-block-starts-with "\\([[:alpha:]]+\\)" reg-beg))
+ (setq controls (append controls (list (cons 'close (match-string-no-properties 1))))))
+ ((web-mode-block-starts-with "\\(else\\|elseif\\)" reg-beg)
+ (setq controls (append controls (list (cons 'inside "if")))))
+ ((web-mode-block-starts-with "\\(block\\|foreach\\|for\\|if\\|section\\|while\\)")
+ (setq controls (append controls (list (cons 'open (match-string-no-properties 1))))))
+ )
+ ) ;smarty
+
+ ((string= web-mode-engine "expressionengine")
+ (cond
+ ((and (eq (char-after (1+ reg-beg)) ?\/)
+ (web-mode-block-starts-with "\\(if\\)" reg-beg))
+ (setq controls (append controls (list (cons 'close (match-string-no-properties 1))))))
+ ((web-mode-block-starts-with "\\(if:else\\|if:ifelse\\)" reg-beg)
+ (setq controls (append controls (list (cons 'inside "if")))))
+ ((web-mode-block-starts-with "\\(if\\)")
+ (setq controls (append controls (list (cons 'open (match-string-no-properties 1))))))
+ )
+ ) ;expressionengine
+
+ ((string= web-mode-engine "xoops")
+ (cond
+ ((and (eq (char-after (+ reg-beg 2)) ?\/)
+ (web-mode-block-starts-with "\\([[:alpha:]]+\\)" reg-beg))
+ (setq controls (append controls (list (cons 'close (match-string-no-properties 1))))))
+ ((web-mode-block-starts-with "\\(else\\|elseif\\)" reg-beg)
+ (setq controls (append controls (list (cons 'inside "if")))))
+ ((web-mode-block-starts-with "\\(block\\|foreach\\|for\\|if\\|section\\|while\\)")
+ (setq controls (append controls (list (cons 'open (match-string-no-properties 1))))))
+ )
+ ) ;xoops
+
+ ((string= web-mode-engine "web2py")
+ (cond
+ ((web-mode-block-starts-with "def" reg-beg)
+ (setq controls (append controls (list (cons 'open "def")))))
+ ((web-mode-block-starts-with "return" reg-beg)
+ (setq controls (append controls (list (cons 'close "def")))))
+ ((web-mode-block-starts-with "block" reg-beg)
+ (setq controls (append controls (list (cons 'open "block")))))
+ ((web-mode-block-starts-with "end" reg-beg)
+ (setq controls (append controls (list (cons 'close "block")))))
+ ((web-mode-block-starts-with "pass" reg-beg)
+ (setq controls (append controls (list (cons 'close "ctrl")))))
+ ((web-mode-block-starts-with "\\(except\\|finally\\|els\\)" reg-beg)
+ (setq controls (append controls (list (cons 'inside "ctrl")))))
+ ((web-mode-block-starts-with "\\(if\\|for\\|try\\|while\\)")
+ (setq controls (append controls (list (cons 'open "ctrl")))))
+ )
+ ) ;web2py
+
+ ((string= web-mode-engine "dust")
+ (cond
+ ((eq (char-after (1- reg-end)) ?\/)
+ )
+ ((eq (char-after (1+ reg-beg)) ?\:)
+ (setq pos (web-mode-block-control-previous-position 'open reg-beg))
+ (when pos
+ (setq controls (append controls
+ (list
+ (cons 'inside
+ (cdr (car (web-mode-block-controls-get pos))))))))
+ )
+ ((looking-at "{/\\([[:alpha:].]+\\)")
+ (setq controls (append controls (list (cons 'close (match-string-no-properties 1))))))
+ ((looking-at "{[#?@><+^]\\([[:alpha:].]+\\)")
+ (setq controls (append controls (list (cons 'open (match-string-no-properties 1))))))
+ )
+ ) ;dust
+
+ ((member web-mode-engine '("mojolicious"))
+ (cond
+ ((web-mode-block-ends-with "begin" reg-beg)
+ (setq controls (append controls (list (cons 'open "begin")))))
+ ((web-mode-block-starts-with "end" reg-beg)
+ (setq controls (append controls (list (cons 'close "begin")))))
+ ((web-mode-block-starts-with "}[ ]*else[ ]*{" reg-beg)
+ (setq controls (append controls (list (cons 'inside "{")))))
+ ((web-mode-block-starts-with "}" reg-beg)
+ (setq controls (append controls (list (cons 'close "{")))))
+ ((web-mode-block-ends-with "{" reg-beg)
+ (setq controls (append controls (list (cons 'open "{")))))
+ )
+ ) ;mojolicious
+
+ ((member web-mode-engine '("aspx" "underscore"))
+ (cond
+ ((and (web-mode-block-starts-with "}" reg-beg)
+ (web-mode-block-ends-with "{" reg-beg))
+ (setq controls (append controls (list (cons 'inside "{")))))
+ ((web-mode-block-starts-with "}" reg-beg)
+ (setq controls (append controls (list (cons 'close "{")))))
+ ((web-mode-block-ends-with "{" reg-beg)
+ (setq controls (append controls (list (cons 'open "{")))))
+ )
+ ) ;aspx underscore
+
+ ((member web-mode-engine '("jsp" "asp" "clip"))
+ (cond
+ ((eq (char-after (1- reg-end)) ?\/)
+ )
+ ((looking-at "</?\\([[:alpha:]]+\\(?:[:.][[:alpha:]]+\\)\\|[[:alpha:]]+Template\\)")
+ (setq control (match-string-no-properties 1)
+ type (if (eq (aref (match-string-no-properties 0) 1) ?\/) 'close 'open))
+ (when (not (member control '("h:inputtext" "jsp:usebean" "jsp:forward" "struts:property")))
+ (setq controls (append controls (list (cons type control)))))
+ )
+ (t
+ (when (web-mode-block-starts-with "}" reg-beg)
+ (setq controls (append controls (list (cons 'close "{")))))
+ (when (web-mode-block-ends-with "{" reg-beg)
+ (setq controls (append controls (list (cons 'open "{")))))
+ )
+ )
+ ) ;jsp asp
+
+ ((string= web-mode-engine "mako")
+ (cond
+ ((looking-at "</?%\\([[:alpha:]]+\\(?:[:][[:alpha:]]+\\)?\\)")
+ (cond
+ ((eq (char-after (- (web-mode-block-end-position reg-beg) 1)) ?\/)
+ )
+ (t
+ (setq control (match-string-no-properties 1)
+ type (if (eq (aref (match-string-no-properties 0) 1) ?\/) 'close 'open))
+ (setq controls (append controls (list (cons type control)))))
+ )
+ )
+ ((web-mode-block-starts-with "\\(else\\|elif\\)" reg-beg)
+ (setq controls (append controls (list (cons 'inside "if")))))
+ ((web-mode-block-starts-with "end\\(if\\|for\\)" reg-beg)
+ (setq controls (append controls (list (cons 'close (match-string-no-properties 1))))))
+ ((and (web-mode-block-starts-with "if\\|for" reg-beg)
+ (web-mode-block-ends-with ":" reg-beg))
+ (setq controls (append controls (list (cons 'open (match-string-no-properties 0))))))
+ )
+ ) ;mako
+
+ ((string= web-mode-engine "mason")
+ (cond
+ ((looking-at "</?%\\(after\\|around\\|augment\\|before\\|def\\|filter\\|method\\|override\\)")
+ (setq control (match-string-no-properties 1)
+ type (if (eq (aref (match-string-no-properties 0) 1) ?\/) 'close 'open))
+ (setq controls (append controls (list (cons type control))))
+ )
+ )
+ ) ;mason
+
+ ((string= web-mode-engine "ctemplate")
+ (cond
+ ((looking-at-p "{{else") ;#721
+ (let ((continue t)
+ (pos reg-beg)
+ (ctrl nil))
+ (while continue
+ (cond
+ ((null (setq pos (web-mode-block-control-previous-position 'open pos)))
+ (setq continue nil))
+ ((member (setq ctrl (cdr (car (get-text-property pos 'block-controls)))) '("if" "each"))
+ (setq continue nil)
+ )
+ ) ;cond
+ ) ;while
+ (setq controls (append controls (list (cons 'inside (or ctrl "if")))))
+ )
+ )
+
+ ((looking-at "{{[#^/][ ]*\\([[:alpha:]_.-]+\\)")
+ (setq control (match-string-no-properties 1)
+ type (if (eq (aref (match-string-no-properties 0) 2) ?\/) 'close 'open))
+ (setq controls (append controls (list (cons type control))))
+ )
+ )
+ ) ;ctemplate
+
+ ((string= web-mode-engine "blade")
+ (cond
+ ((not (eq (char-after) ?\@))
+ )
+ ((web-mode-block-starts-with
+ "section\(\s*\\(['\"]\\).*\\1\s*,\s*\\(['\"]\\).*\\2\s*\)" reg-beg)
+ )
+ ((web-mode-block-starts-with "case\\|break" reg-beg)
+ (setq type (if (eq (aref (match-string-no-properties 0) 0) ?b) 'close 'open))
+ (setq controls (append controls (list (cons type "case"))))
+ )
+ ((web-mode-block-starts-with
+ (concat "\\(?:end\\)?\\(" web-mode-blade-control-blocks-regexp "\\)")
+ reg-beg)
+ (setq control (match-string-no-properties 1)
+ type (if (eq (aref (match-string-no-properties 0) 0) ?e) 'close 'open))
+ (setq controls (append controls (list (cons type control))))
+ )
+ ((web-mode-block-starts-with "stop\\|show\\|overwrite" reg-beg)
+ (setq controls (append controls (list (cons 'close "section")))))
+ ((web-mode-block-starts-with "else\\|elseif" reg-beg)
+ (setq controls (append controls (list (cons 'inside "if")))))
+ ((web-mode-block-starts-with "empty" reg-beg)
+ (setq controls (append controls (list (cons 'inside "forelse")))))
+ )
+ ) ;blade
+
+ ((string= web-mode-engine "closure")
+ (cond
+ ((eq (char-after (1- reg-end)) ?\/)
+ )
+ ((looking-at "alias\\|namespace")
+ )
+ ((web-mode-block-starts-with "ifempty" reg-beg)
+ (setq controls (append controls (list (cons 'inside "foreach")))))
+ ((web-mode-block-starts-with "else\\|elseif" reg-beg)
+ (setq controls (append controls (list (cons 'inside "if")))))
+ ((web-mode-block-starts-with "case\\|default" reg-beg)
+ (setq controls (append controls (list (cons 'inside "switch")))))
+ ((looking-at
+ "{/?\\(call\\|deltemplate\\|for\\|foreach\\|if\\|let\\|literal\\|msg\\|param\\|switch\\|template\\)")
+ (setq control (match-string-no-properties 1)
+ type (if (eq (aref (match-string-no-properties 0) 1) ?\/) 'close 'open))
+ (setq controls (append controls (list (cons type control))))
+ )
+ )
+ ) ;closure
+
+ ((string= web-mode-engine "go")
+ (cond
+ ((web-mode-block-starts-with "end\\_>" reg-beg)
+ (setq controls (append controls (list (cons 'close "ctrl")))))
+ ((web-mode-block-starts-with "else\\_>" reg-beg)
+ (setq controls (append controls (list (cons 'inside "ctrl")))))
+ ((web-mode-block-starts-with "\\(range\\|with\\|if\\|define\\|block\\)\\_>" reg-beg)
+ (setq controls (append controls (list (cons 'open "ctrl")))))
+ )
+ ) ;go
+
+ ((string= web-mode-engine "template-toolkit")
+ (cond
+ ((web-mode-block-starts-with "end" reg-beg)
+ (setq controls (append controls (list (cons 'close "ctrl")))))
+ ((web-mode-block-starts-with "els\\|catch\\|final" reg-beg)
+ (setq controls (append controls (list (cons 'inside "ctrl")))))
+ ((web-mode-block-starts-with "filter\\|foreach\\|if\\|last\\|next\\|perl\\|rawperl\\|try\\|unless\\|while" reg-beg)
+ (setq controls (append controls (list (cons 'open "ctrl")))))
+ )
+ ) ;template-toolkit
+
+ ((string= web-mode-engine "cl-emb")
+ (cond
+ ((web-mode-block-starts-with "@else" reg-beg)
+ (setq controls (append controls (list (cons 'inside "if")))))
+ ((web-mode-block-starts-with "@\\(?:end\\)?\\(if\\|unless\\|repeat\\|loop\\|with\\|genloop\\)" reg-beg)
+ (setq control (match-string-no-properties 1)
+ type (if (eq (aref (match-string-no-properties 0) 1) ?e) 'close 'open))
+ (setq controls (append controls (list (cons type control)))))
+ )
+ ) ;cl-emb
+
+ ((string= web-mode-engine "elixir")
+ (cond
+ ((web-mode-block-starts-with "end" reg-beg)
+ (setq controls (append controls (list (cons 'close "ctrl")))))
+ ((web-mode-block-starts-with "else" reg-beg)
+ (setq controls (append controls (list (cons 'inside "ctrl")))))
+ ((web-mode-block-ends-with " do" reg-beg)
+ (setq controls (append controls (list (cons 'open "ctrl")))))
+ ((web-mode-block-ends-with " ->" reg-beg)
+ (setq controls (append controls (list (cons 'open "ctrl")))))
+ )
+ ) ;elixir
+
+ ((string= web-mode-engine "velocity")
+ (cond
+ ((web-mode-block-starts-with "{?end" reg-beg)
+ (setq controls (append controls (list (cons 'close "ctrl")))))
+ ((web-mode-block-starts-with "{?els" reg-beg)
+ (setq controls (append controls (list (cons 'inside "ctrl")))))
+ ((web-mode-block-starts-with "{?\\(def\\|if\\|for\\|foreach\\|macro\\)" reg-beg)
+ ;;((web-mode-block-starts-with "{?\\(define\\|\\|if\\|for\\|foreach\\|macro\\)" reg-beg)
+ (setq controls (append controls (list (cons 'open "ctrl")))))
+ )
+ ) ;velocity
+
+ ((string= web-mode-engine "freemarker")
+ (cond
+ ((looking-at "[<[]#\\(import\\|include\\|assign\\|return\\|local\\)")
+ )
+ ((eq (char-after (1- reg-end)) ?\/)
+ )
+ ((looking-at "[<[]#\\(break\\|case\\|default\\)")
+ (setq controls (append controls (list (cons 'inside "switch"))))
+ )
+ ((looking-at "[<[]#els")
+ (setq controls (append controls (list (cons 'inside "if"))))
+ )
+ ((looking-at "</?\\([[:alpha:]]+\\(?:[:][[:alpha:]]+\\)?\\)")
+ (setq control (match-string-no-properties 1)
+ type (if (eq (aref (match-string-no-properties 0) 1) ?\/) 'close 'open))
+ (setq controls (append controls (list (cons type control))))
+ )
+ ((looking-at "[<[]/?\\(@\\)")
+ (setq control (match-string-no-properties 1)
+ type (if (eq (aref (match-string-no-properties 0) 1) ?\/) 'close 'open))
+ (setq controls (append controls (list (cons type control))))
+ )
+ ((looking-at "[<[]/?#\\([[:alpha:]]+\\(?:[:][[:alpha:]]+\\)?\\)")
+ (setq control (match-string-no-properties 1)
+ type (if (eq (aref (match-string-no-properties 0) 1) ?\/) 'close 'open))
+ (setq controls (append controls (list (cons type control))))
+ )
+ (t
+ (when (web-mode-block-starts-with "}" reg-beg)
+ (setq controls (append controls (list (cons 'close "{")))))
+ (when (web-mode-block-ends-with "{" reg-beg)
+ (setq controls (append controls (list (cons 'open "{")))))
+ )
+ )
+ ) ;freemarker
+
+ ((string= web-mode-engine "razor")
+ (when (web-mode-block-starts-with "}" reg-beg)
+ (setq controls (append controls (list (cons 'close "{")))))
+ (when (web-mode-block-ends-with "{" reg-beg)
+ (setq controls (append controls (list (cons 'open "{")))))
+ ) ;razor
+
+ ((string= web-mode-engine "lsp")
+ (when (web-mode-block-starts-with ")" reg-beg)
+ (setq controls (append controls (list (cons 'close "(")))))
+ (when (web-mode-block-is-opened-sexp reg-beg reg-end)
+ (setq controls (append controls (list (cons 'open "(")))))
+ ) ;lsp
+
+ ((string= web-mode-engine "hero")
+ (cond
+ ((web-mode-block-ends-with "}[ ]*else[ ]*{" reg-beg)
+ (setq controls (append controls (list (cons 'inside "{")))))
+ ((web-mode-block-starts-with "}" reg-beg)
+ (setq controls (append controls (list (cons 'close "{")))))
+ ((web-mode-block-ends-with "{" reg-beg)
+ (setq controls (append controls (list (cons 'open "{")))))
+ )
+ ) ;hero
+
+ ((string= web-mode-engine "svelte")
+ (cond
+ ((eq (char-after (1- reg-end)) ?\/)
+ )
+ ((eq (char-after (1+ reg-beg)) ?\:)
+ (setq pos (web-mode-block-control-previous-position 'open reg-beg))
+ (when pos
+ (setq controls (append controls
+ (list
+ (cons 'inside
+ (cdr (car (web-mode-block-controls-get pos))))))))
+ )
+ ((looking-at "{/\\([[:alpha:].]+\\)")
+ (setq controls (append controls (list (cons 'close (match-string-no-properties 1))))))
+ ((looking-at "{[#?><+^]\\([[:alpha:].]+\\)")
+ (setq controls (append controls (list (cons 'open (match-string-no-properties 1))))))
+ )
+ ) ;svelte
+
+ ) ;cond engine
+
+ (put-text-property reg-beg (1+ reg-beg) 'block-controls controls)
+ ;;(message "(%S) controls=%S" reg-beg controls)
+
+ )))
+
+(defun web-mode-block-is-opened-sexp (reg-beg reg-end)
+ (let ((n 0))
+ (save-excursion
+ (goto-char reg-beg)
+ (while (web-mode-block-rsf "[()]" reg-end)
+ (if (eq (char-before) ?\() (setq n (1+ n)) (setq n (1- n)))))
+ (> n 0)))
+
+;;---- LEXER PARTS -------------------------------------------------------------
+
+(defun web-mode-scan-elements (reg-beg reg-end)
+ (save-excursion
+ (let (part-beg part-end flags limit close-expr props tname tbeg tend element-content-type (regexp web-mode-dom-regexp) part-close-tag char)
+ ;;(message "scan-elements: reg-beg(%S) reg-end(%S)" reg-beg reg-end)
+ (goto-char reg-beg)
+
+ (while (web-mode-dom-rsf regexp reg-end)
+
+ ;;(message "%S: %S (%S %S)" (point) (match-string-no-properties 0) reg-beg reg-end)
+
+ (setq flags 0
+ tname (downcase (match-string-no-properties 1))
+ char (aref tname 0)
+ tbeg (match-beginning 0)
+ tend nil
+ element-content-type nil
+ limit reg-end
+ part-beg nil
+ part-end nil
+ props nil
+ close-expr nil
+ part-close-tag nil)
+
+ ;;(message "tname[%S] tbeg(%S) point(%S)" tname tbeg (point))
+
+ (cond
+
+ ((member tname '("/>" ">")) ;;jsx fragment #952
+ (setq tname "_fragment_"
+ tend (point))
+ (if (eq char ?\/)
+ (setq props (list 'tag-name tname 'tag-type 'end)
+ flags (logior flags 20)) ;; 16 + 4
+ (setq props (list 'tag-name tname 'tag-type 'start)
+ flags (logior flags 16))
+ ) ;if
+ )
+
+ ((not (member char '(?\! ?\?)))
+ (cond
+ ((string-match-p "-" tname)
+ (setq flags (logior flags 2)))
+ ((string-match-p ":" tname)
+ (setq flags (logior flags 32)))
+ )
+ (cond
+ ((eq char ?\/)
+ (setq props (list 'tag-name (substring tname 1) 'tag-type 'end)
+ flags (logior flags 4)
+ limit (if (> reg-end (line-end-position)) (line-end-position) reg-end))
+ )
+ ((web-mode-element-is-void tname)
+ ;;(message "void: tag=%S" tname)
+ (setq props (list 'tag-name tname 'tag-type 'void)))
+ (t
+ (setq props (list 'tag-name tname 'tag-type 'start)))
+ ) ;cond
+ ) ; not <! <?
+ ((and (eq char ?\!) (eq (aref tname 1) ?\-))
+ (setq close-expr "-->"
+ props '(tag-type comment)))
+ ((string= tname "?xml")
+ (setq ;;regexp web-mode-tag-regexp2
+ close-expr "?>"
+ props '(tag-type declaration)))
+ ((string= tname "![cdata[")
+ (setq close-expr "]]>"
+ props '(tag-type cdata)))
+ ((string= tname "!doctype")
+ (setq ;;regexp web-mode-tag-regexp2
+ props '(tag-type doctype)))
+ ) ;cond - special tags
+
+ (cond
+
+ (tend
+ )
+
+ ((and (null close-expr) (eq (char-after) ?\>))
+ (setq flags (logior flags 16)
+ tend (1+ (point)))
+ ;;(message "end=%S" tend)
+ )
+
+ ((and (null close-expr)
+ (looking-at "[ ]\\(class\\|id\\|href\\|style\\)=\"[[:alnum:]_=:/?;#. -]*\">"))
+ (let ((beg (1+ (point)))
+ (end (+ (point) (length (match-string-no-properties 0)))))
+ (setq flags (logior flags 17)
+ tend end)
+ (put-text-property beg (1+ beg) 'tag-attr-beg 0)
+ (put-text-property beg (1- end) 'tag-attr t)
+ (put-text-property (- end 2) (1- end) 'tag-attr-end (length (match-string-no-properties 1)))
+ ) ;let
+ )
+
+ ((null close-expr)
+ (setq flags (logior flags (web-mode-attr-skip reg-end)))
+ (when (> (logand flags 8) 0)
+ (setq props (plist-put props 'tag-type 'void)))
+ (setq tend (point)))
+
+ ((web-mode-dom-sf close-expr limit t)
+ (setq tend (point)))
+
+ (t
+ (setq tend (line-end-position)))
+
+ ) ;cond
+
+ (cond
+ ((string= tname "style")
+ (let (style)
+ (setq style (buffer-substring-no-properties tbeg tend)
+ part-close-tag "</style>")
+ (cond
+ ((string-match-p " lang[ ]*=[ ]*[\"']stylus" style)
+ (setq element-content-type "stylus"))
+ ((string-match-p " lang[ ]*=[ ]*[\"']sass" style)
+ (setq element-content-type "sass"))
+ (t
+ (setq element-content-type "css"))
+ ) ;cond
+ ) ;let
+ ) ;style
+ ((string= tname "script")
+ (let (script)
+ (setq script (buffer-substring-no-properties tbeg tend)
+ part-close-tag "</script>")
+ (cond
+ ((string-match-p " type[ ]*=[ ]*[\"']text/\\(jsx\\|babel\\)" script)
+ (setq element-content-type "jsx"))
+ ((string-match-p " type[ ]*=[ ]*[\"']text/\\(markdown\\|template\\)" script)
+ (setq element-content-type "markdown"))
+ ((string-match-p " type[ ]*=[ ]*[\"']text/ruby" script)
+ (setq element-content-type "ruby"))
+ ((seq-some (lambda (x)
+ (string-match-p (concat "type[ ]*=[ ]*[\"']" x) script))
+ web-mode-script-template-types)
+ (setq element-content-type "html"
+ part-close-tag nil))
+ ((string-match-p " type[ ]*=[ ]*[\"']application/\\(ld\\+json\\|json\\)" script)
+ (setq element-content-type "json"))
+ ((string-match-p " lang[ ]*=[ ]*[\"']\\(typescript\\|ts\\)" script)
+ (setq element-content-type "typescript"))
+ (t
+ (setq element-content-type "javascript"))
+ ) ;cond
+ ) ;let
+ ) ;script
+ ((and (string= tname "template") (string-match-p " lang" (buffer-substring-no-properties tbeg tend)))
+ (let (template)
+ (setq template (buffer-substring-no-properties tbeg tend)
+ part-close-tag "</template>")
+ (cond
+ ((string-match-p " lang[ ]*=[ ]*[\"']pug" template)
+ (setq element-content-type "pug"))
+ (t
+ (setq element-content-type "html"))
+ ) ;cond
+ ) ;let
+ ) ;style
+ ((and (string= web-mode-engine "archibus")
+ (string= tname "sql"))
+ (setq element-content-type "sql"
+ part-close-tag "</sql>"))
+ )
+
+ (add-text-properties tbeg tend props)
+ (put-text-property tbeg (1+ tbeg) 'tag-beg flags)
+ (put-text-property (1- tend) tend 'tag-end t)
+
+ (when (and part-close-tag
+ (web-mode-dom-sf part-close-tag reg-end t)
+ (setq part-beg tend)
+ (setq part-end (match-beginning 0))
+ (> part-end part-beg))
+ (put-text-property part-beg part-end 'part-side
+ (intern element-content-type web-mode-obarray))
+ (setq tend part-end)
+ ) ;when
+
+ (goto-char tend)
+
+ ) ;while
+
+ )))
+
+;; FLAGS: tag
+;; (1)attrs (2)custom (4)slash-beg (8)slash-end (16)bracket-end (32)namespaced
+
+;; FLAGS: attr
+;; (1)custom-attr (2)engine-attr (4)spread-attr[jsx] (8)code-value
+;; SPECS: https://www.w3.org/TR/2012/WD-html-markup-20120329/syntax.html#attr-value-unquoted
+
+;; STATES: attr
+;; (0)nil (1)space (2)name (3)space-before (4)equal (5)space-after
+;; (6)value-uq (7)value-sq (8)value-dq (9)value-bq : jsx attr={}
+
+(defun web-mode-attr-skip (limit)
+
+ (let ((tag-flags 0) (attr-flags 0) (continue t) (attrs 0) (counter 0) (brace-depth 0)
+ (pos-ori (point)) (state 0) (equal-offset 0) (go-back nil)
+ (is-jsx (or (string= web-mode-content-type "jsx") (eq (get-text-property (point) 'part-type) 'jsx)))
+ attr name-beg name-end val-beg char pos escaped spaced quoted)
+
+ (while continue
+
+ (setq pos (point)
+ char (char-after)
+ ;;spaced (eq char ?\s)
+ spaced (member char '(?\s ?\n))
+ )
+
+ (when quoted (setq quoted (1+ quoted)))
+
+ (cond
+
+ ((>= pos limit)
+ (setq continue nil)
+ (setq go-back t)
+ (setq attrs (+ attrs (web-mode-attr-scan pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags)))
+ )
+
+ ((or (and (= state 8) (not (member char '(?\" ?\\))))
+ (and (= state 7) (not (member char '(?\' ?\\))))
+ (and (= state 9) (not (member char '(?} ?\\))))
+ )
+ (when (and (= state 9) (eq char ?\{))
+ (setq brace-depth (1+ brace-depth)))
+ )
+
+ ((and (= state 9) (eq char ?\}) (> brace-depth 1))
+ (setq brace-depth (1- brace-depth)))
+
+ ((get-text-property pos 'block-side)
+ (when (= state 2)
+ (setq name-end pos))
+ )
+
+ ((and (= state 2) is-jsx (eq char ?\}) (eq attr-flags 4))
+ (setq name-end pos)
+ (setq attrs (+ attrs (web-mode-attr-scan pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags)))
+ (setq state 0
+ attr-flags 0
+ equal-offset 0
+ name-beg nil
+ name-end nil
+ val-beg nil)
+ )
+
+ ((or (and (= state 8) (eq ?\" char) (not escaped))
+ (and (= state 7) (eq ?\' char) (not escaped))
+ (and (= state 9) (eq ?\} char) (= brace-depth 1))
+ )
+
+ ;;(message "%S %S" (point) attr-flags)
+ (setq attrs (+ attrs (web-mode-attr-scan pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags)))
+ (setq state 0
+ attr-flags 0
+ equal-offset 0
+ name-beg nil
+ name-end nil
+ val-beg nil)
+ )
+
+ ((and (member state '(4 5)) (member char '(?\' ?\" ?\{)))
+ (setq val-beg pos)
+ (setq quoted 1)
+ (setq state (cond ((eq ?\' char) 7)
+ ((eq ?\" char) 8)
+ (t 9)))
+ (when (= state 9)
+ (setq brace-depth 1))
+ )
+
+ ((and (eq ?\= char) (member state '(2 3)))
+ (setq equal-offset (- pos name-beg)
+ name-end (1- pos))
+ (setq state 4)
+ (setq attr (buffer-substring-no-properties name-beg (1+ name-end)))
+ (when (and web-mode-indentless-attributes (member (downcase attr) web-mode-indentless-attributes))
+ ;;(message "onclick")
+ (setq attr-flags (logior attr-flags 8)))
+ )
+
+ ((and spaced (= state 0))
+ (setq state 1)
+ )
+
+ ((and (eq char ?\<) (not (member state '(7 8 9))))
+ (setq continue nil)
+ (setq go-back t)
+ (setq attrs (+ attrs (web-mode-attr-scan pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags)))
+ )
+
+ ((and (eq char ?\>) (not (member state '(7 8 9))))
+ (setq tag-flags (logior tag-flags 16))
+ (when (eq (char-before) ?\/)
+ (setq tag-flags (logior tag-flags 8))
+ )
+ (setq continue nil)
+ (when name-beg
+ (setq attrs (+ attrs (web-mode-attr-scan pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags))))
+ )
+
+ ((and spaced (member state '(1 3 5)))
+ )
+
+ ((and spaced (= state 2))
+ (setq state 3)
+ )
+
+ ((and (eq char ?\/) (member state '(4 5)))
+ (setq attrs (+ attrs (web-mode-attr-scan pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags)))
+ (setq state 1
+ attr-flags 0
+ equal-offset 0
+ name-beg nil
+ name-end nil
+ val-beg nil)
+ )
+
+ ((and (eq char ?\/) (member state '(0 1)))
+ )
+
+ ((and spaced (= state 4))
+ (setq state 5)
+ )
+
+ ((and (= state 3)
+ (or (and (>= char 97) (<= char 122)) ;a - z
+ (and (>= char 65) (<= char 90)) ;A - Z
+ (eq char ?\-)))
+ (setq attrs (+ attrs (web-mode-attr-scan pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags)))
+ (setq state 2
+ attr-flags 0
+ equal-offset 0
+ name-beg pos
+ name-end pos
+ val-beg nil)
+ )
+
+ ((and (eq char ?\n) (not (member state '(7 8 9))))
+ (setq attrs (+ attrs (web-mode-attr-scan pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags)))
+ (setq state 1
+ attr-flags 0
+ equal-offset 0
+ name-beg nil
+ name-end nil
+ val-beg nil)
+ )
+
+ ((and (= state 6) (member char '(?\s ?\n))) ;#1150
+ (setq attrs (+ attrs (web-mode-attr-scan pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags)))
+ (setq state 1
+ attr-flags 0
+ equal-offset 0
+ name-beg nil
+ name-end nil
+ val-beg nil)
+ )
+
+ ((and quoted (= quoted 2) (member char '(?\s ?\n ?\>)))
+ (when (eq char ?\>)
+ (setq tag-flags (logior tag-flags 16))
+ (setq continue nil))
+ (setq state 6)
+ (setq attrs (+ attrs (web-mode-attr-scan pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags)))
+ (setq state 1
+ attr-flags 0
+ equal-offset 0
+ name-beg nil
+ name-end nil
+ val-beg nil)
+ )
+
+ ((and (not spaced) (= state 1))
+ (when (and is-jsx (eq char ?\{))
+ (setq attr-flags 4))
+ (setq state 2)
+ (setq name-beg pos
+ name-end pos)
+ )
+
+ ((member state '(4 5))
+ (setq val-beg pos)
+ (setq state 6)
+ )
+
+ ((= state 1)
+ (setq state 2)
+ )
+
+ ((= state 2)
+ (setq name-end pos)
+ (when (and nil (= attr-flags 0) (member char '(?\- ?\:)))
+ (let (attr)
+ (setq attr (buffer-substring-no-properties name-beg (1+ name-end)))
+ (cond
+ ((member attr '("http-equiv"))
+ (setq attr-flags (1- attr-flags))
+ )
+ ;;((and web-mode-engine-attr-regexp
+ ;; (string-match-p web-mode-engine-attr-regexp attr))
+ ;; (setq attr-flags (logior attr-flags 2))
+ ;; )
+ ((and (eq char ?\-) (not (string= attr "http-")))
+ (setq attr-flags (logior attr-flags 1)))
+ ) ;cond
+ ) ;let
+ ) ;when attr-flags = 1
+ ) ;state=2
+
+ ) ;cond
+
+ ;;(message "point(%S) end(%S) state(%S) c(%S) name-beg(%S) name-end(%S) val-beg(%S) attr-flags(%S) equal-offset(%S)" pos end state char name-beg name-end val-beg attr-flags equal-offset tag-flags)
+
+ (when (and quoted (>= quoted 2))
+ (setq quoted nil))
+
+ (setq escaped (eq ?\\ char))
+ (when (null go-back)
+ (forward-char))
+
+ ) ;while
+
+ (when (> attrs 0) (setq tag-flags (logior tag-flags 1)))
+
+ tag-flags))
+
+(defun web-mode-attr-scan (pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags)
+ ;;(message "point(%S) state(%S) c(%c) name-beg(%S) name-end(%S) val-beg(%S) attr-flags(%S) equal-offset(%S) tag-flags(%S)"
+ ;; pos state char name-beg name-end val-beg attr-flags equal-offset tag-flags)
+ (when (null attr-flags) (setq attr-flags 0))
+ (when (and name-beg name-end web-mode-engine-attr-regexp)
+ (let (name)
+ (setq name (buffer-substring-no-properties name-beg (1+ name-end)))
+ ;;(message "%S" name)
+ (cond
+ ((string-match-p "^data[-]" name)
+ (setq attr-flags (logior attr-flags 1))
+ )
+ ((string-match-p web-mode-engine-attr-regexp name)
+ (setq attr-flags (logior attr-flags 2))
+ )
+ )
+ ) ;name
+ )
+ ;;(message "%S" name)
+ (cond
+ ((null name-beg)
+ 0)
+ ((or (and (= state 8) (not (eq ?\" char)))
+ (and (= state 7) (not (eq ?\' char))))
+ (put-text-property name-beg (1+ name-beg) 'tag-attr-beg attr-flags)
+ (put-text-property name-beg val-beg 'tag-attr t)
+ (put-text-property (1- val-beg) val-beg 'tag-attr-end equal-offset)
+ 1)
+ ((and (member state '(4 5)) (null val-beg))
+ (put-text-property name-beg (1+ name-beg) 'tag-attr-beg attr-flags)
+ (put-text-property name-beg (+ name-beg equal-offset 1) 'tag-attr t)
+ (put-text-property (+ name-beg equal-offset) (+ name-beg equal-offset 1) 'tag-attr-end equal-offset)
+ 1)
+ (t
+ (let (val-end)
+ (if (null val-beg)
+ (setq val-end name-end)
+ (setq val-end pos)
+ (cond
+ ((null char)
+ (setq val-end (1- val-end)))
+ ((member char '(?\s ?\n ?\/))
+ (setq val-end (1- val-end)))
+ ((eq char ?\>)
+ (if (= (logand tag-flags 8) 8)
+ (progn
+ ;;(message "tag-flags=%S %S" tag-flags (logand tag-flags 8))
+ (setq val-end (- val-end 2)))
+ (setq val-end (- val-end 1)))
+ ;; (message "val-end=%S" val-end)
+ )
+ )
+ )
+ (put-text-property name-beg (1+ name-beg) 'tag-attr-beg attr-flags)
+ (put-text-property name-beg (1+ val-end) 'tag-attr t)
+ (put-text-property val-end (1+ val-end) 'tag-attr-end equal-offset)
+ ) ;let
+ 1) ;t
+ ) ;cond
+ )
+
+(defun web-mode-part-foreach (reg-beg reg-end func)
+ (let ((i 0) (continue t) (part-beg reg-beg) (part-end nil))
+ (while continue
+ (setq part-end nil)
+ (unless (get-text-property part-beg 'part-side)
+ (setq part-beg (web-mode-part-next-position part-beg)))
+ (when (and part-beg (< part-beg reg-end))
+ (setq part-end (web-mode-part-end-position part-beg)))
+ (cond
+ ((> (setq i (1+ i)) 100)
+ (message "process-parts ** warning (%S) **" (point))
+ (setq continue nil))
+ ((or (null part-end) (> part-end reg-end))
+ (setq continue nil))
+ (t
+ (setq part-end (1+ part-end))
+ (funcall func part-beg part-end)
+ (setq part-beg part-end))
+ ) ;cond
+ ) ;while
+ ))
+
+(defun web-mode-part-scan (reg-beg reg-end &optional content-type depth)
+ (save-excursion
+ (let (token-re ch-before ch-at ch-next token-type beg continue)
+ ;;(message "%S %S" reg-beg reg-end)
+ (cond
+ (content-type
+ )
+ ((member web-mode-content-type web-mode-part-content-types)
+ (setq content-type web-mode-content-type))
+ (t
+ (setq content-type (symbol-name (get-text-property reg-beg 'part-side))))
+ ) ;cond
+
+ (goto-char reg-beg)
+
+ (cond
+ ((member content-type '("javascript" "json"))
+ (setq token-re "/\\|\"\\|'\\|`"))
+ ((member content-type '("typescript"))
+ (setq token-re "\"\\|'\\|`\\|//\\|/\\*"))
+ ((member content-type '("jsx"))
+ (setq token-re "/\\|\"\\|'\\|`\\|</?[[:alpha:]>]"))
+ ((string= web-mode-content-type "css")
+ (setq token-re "\"\\|'\\|/\\*\\|//"))
+ ((string= content-type "css")
+ (setq token-re "\"\\|'\\|/\\*"))
+ (t
+ (setq token-re "/\\*\\|\"\\|'"))
+ )
+
+ (while (and token-re (< (point) reg-end) (web-mode-dom-rsf token-re reg-end t))
+
+ (setq beg (match-beginning 0)
+ token-type nil
+ continue t
+ ch-at (char-after beg)
+ ch-next (or (char-after (1+ beg)) ?\d)
+ ch-before (or (char-before beg) ?\d))
+
+ ;;(message "[%S>%S|%S] %S %c %c %c" reg-beg reg-end depth beg ch-before ch-at ch-next)
+
+ (cond
+
+ ((eq ?\' ch-at)
+ (while (and continue (search-forward "'" reg-end t))
+ (cond
+ ((get-text-property (1- (point)) 'block-side)
+ (setq continue t))
+ (t
+ (setq continue (web-mode-string-continue-p reg-beg)))
+ )
+ ) ;while
+ (setq token-type 'string))
+
+ ((eq ?\` ch-at)
+ (while (and continue (search-forward "`" reg-end t))
+ (cond
+ ((get-text-property (1- (point)) 'block-side)
+ (setq continue t))
+ (t
+ (setq continue (web-mode-string-continue-p reg-beg)))
+ )
+ ) ;while
+ (setq token-type 'string))
+
+ ((eq ?\" ch-at)
+ (while (and continue (search-forward "\"" reg-end t))
+ (cond
+ ((get-text-property (1- (point)) 'block-side)
+ (setq continue t))
+ (t
+ (setq continue (web-mode-string-continue-p reg-beg)))
+ ) ;cond
+ ) ;while
+ (cond
+ ((string= content-type "json")
+ (if (looking-at-p "[ ]*:")
+ (cond
+ ((eq ?\@ (char-after (1+ beg)))
+ (setq token-type 'context))
+ (t
+ (setq token-type 'key))
+ )
+ (setq token-type 'string))
+ ) ;json
+ (t
+ (setq token-type 'string))
+ ) ;cond
+ )
+
+ ((and (eq ?\< ch-at)
+ (not (or (and (>= ch-before 97) (<= ch-before 122))
+ (and (>= ch-before 65) (<= ch-before 90)))))
+ ;;(message "before [%S>%S|%S] pt=%S" reg-beg reg-end depth (point))
+ (search-backward "<")
+ (if (web-mode-jsx-skip reg-end)
+ (web-mode-jsx-scan-element beg (point) depth)
+ (forward-char))
+ ;;(message "after [%S>%S|%S] pt=%S" reg-beg reg-end depth (point))
+ )
+
+ ((and (eq ?\/ ch-at) (member content-type '("javascript" "jsx")))
+ (cond
+ ((eq ?\\ ch-before)
+ )
+ ((eq ?\* ch-next)
+ ;;(message "--> %S %S" (point) reg-end)
+ (when (search-forward "*/" reg-end t)
+ (setq token-type 'comment))
+ )
+ ((eq ?\/ ch-next)
+ (setq token-type 'comment)
+ (goto-char (if (< reg-end (line-end-position)) reg-end (line-end-position)))
+ )
+ ((and (looking-at-p ".*/")
+ (looking-back "\\(^\\|case\\|[[(,=:!&|?{};]\\)[ ]*/" (point-min)))
+ ;;(re-search-forward "/[gimyu]*" reg-end t))
+ (let ((eol (line-end-position)))
+ (while (and continue (search-forward "/" eol t))
+ (cond
+ ((get-text-property (1- (point)) 'block-side)
+ (setq continue t))
+ ((looking-back "\\\\+/" reg-beg t)
+ (setq continue (= (mod (- (point) (match-beginning 0)) 2) 0)))
+ (t
+ (re-search-forward "[gimyu]*" eol t)
+ (setq token-type 'string)
+ (setq continue nil))
+ )
+ ) ;while
+ ) ;let
+ )
+ ) ;cond
+ )
+
+ ((eq ?\/ ch-next)
+ ;;(message "%S" (point))
+ (cond
+ ((and (string= content-type "css")
+ (eq ?/ ch-at)
+ (eq ?: ch-before))
+ )
+ (t
+ (unless (eq ?\\ ch-before)
+ (setq token-type 'comment)
+ (goto-char (if (< reg-end (line-end-position)) reg-end (line-end-position)))
+ )
+ )
+ )
+
+ )
+
+ ((eq ?\* ch-next)
+ (cond
+ ((search-forward "*/" reg-end t)
+ (setq token-type 'comment))
+ ((not (eobp))
+ (forward-char))
+ ) ;cond
+ )
+
+ ) ;cond
+
+ (when (and beg (>= reg-end (point)) token-type)
+ (put-text-property beg (point) 'part-token token-type)
+ (cond
+ ((eq token-type 'comment)
+ (put-text-property beg (1+ beg) 'syntax-table (string-to-syntax "<"))
+ (when (< (point) (point-max))
+ (if (< (point) (line-end-position))
+ (put-text-property (1- (point)) (point) 'syntax-table (string-to-syntax ">")) ;#445
+ (put-text-property (point) (1+ (point)) 'syntax-table (string-to-syntax ">")) ;#377
+ )
+ ) ;when
+ ) ;comment
+ ((eq token-type 'string)
+ (put-text-property beg (1+ beg) 'syntax-table (string-to-syntax "|"))
+ (when (< (point) (point-max))
+ (if (< (point) (line-end-position))
+ (put-text-property (1- (point)) (point) 'syntax-table (string-to-syntax "|"))
+ (put-text-property (point) (1+ (point)) 'syntax-table (string-to-syntax "|"))
+ )
+ ) ;when
+ ) ;string
+ ) ;cond
+ ) ;when
+
+ (when (> (point) reg-end)
+ (message "reg-beg(%S) reg-end(%S) token-type(%S) point(%S)" reg-beg reg-end token-type (point)))
+
+ ;;(message "#[%S>%S|%S] %S %c %c %c | (%S)" reg-beg reg-end depth beg ch-before ch-at ch-next (point))
+
+ ) ;while
+
+ )))
+
+(defun web-mode-string-continue-p (reg-beg)
+ "Is `point' preceeded by an odd number of backslashes?"
+ (let ((p (1- (point))))
+ (while (and (< reg-beg p) (eq ?\\ (char-before p)))
+ (setq p (1- p)))
+ (= (mod (- (point) p) 2) 0)))
+
+;; css rule = selector(s) + declaration (properties)
+(defun web-mode-css-rule-next (limit)
+ (let (at-rule var-rule sel-beg sel-end dec-beg dec-end chunk)
+ (skip-chars-forward "\n\t ")
+ (setq sel-beg (point))
+ (when (and (< (point) limit)
+ (web-mode-part-rsf "[{;]" limit))
+ (setq sel-end (1- (point)))
+ (cond
+ ((eq (char-before) ?\{)
+ (setq dec-beg (point))
+ (setq dec-end (web-mode-closing-paren-position (1- dec-beg) limit))
+ (if dec-end
+ (progn
+ (goto-char dec-end)
+ (forward-char))
+ (setq dec-end limit)
+ (goto-char limit))
+ )
+ (t
+ )
+ ) ;cond
+ (setq chunk (buffer-substring-no-properties sel-beg sel-end))
+ (cond
+ ((string-match "@\\([[:alpha:]-]+\\)" chunk)
+ (setq at-rule (match-string-no-properties 1 chunk)))
+ ((string-match "\\$\\([[:alpha:]-]+\\)" chunk)
+ (setq var-rule (match-string-no-properties 1 chunk)))
+ ) ;cond
+ ) ;when
+ (if (not sel-end)
+ (progn (goto-char limit) nil)
+ (list :at-rule at-rule
+ :var-rule var-rule
+ :sel-beg sel-beg
+ :sel-end sel-end
+ :dec-beg dec-beg
+ :dec-end dec-end)
+ ) ;if
+ ))
+
+(defun web-mode-css-rule-current (&optional pos part-beg part-end)
+ "Current CSS rule boundaries."
+ (unless pos (setq pos (point)))
+ (unless part-beg (setq part-beg (web-mode-part-beginning-position pos)))
+ (unless part-end (setq part-end (web-mode-part-end-position pos)))
+ (save-excursion
+ (let (beg end)
+ (goto-char pos)
+ (if (not (web-mode-part-sb "{" part-beg))
+ (progn
+ (setq beg part-beg)
+ (if (web-mode-part-sf ";" part-end)
+ (setq end (1+ (point)))
+ (setq end part-end))
+ ) ;progn
+ (setq beg (point))
+ (setq end (web-mode-closing-paren-position beg part-end))
+ (if end
+ (setq end (1+ end))
+ (setq end (line-end-position)))
+;; (message "%S >>beg%S >>end%S" pos beg end)
+ (if (> pos end)
+
+ ;;selectors
+ (progn
+ (goto-char pos)
+ (if (web-mode-part-rsb "[};]" part-beg)
+ (setq beg (1+ (point)))
+ (setq beg part-beg)
+ ) ;if
+ (goto-char pos)
+ (if (web-mode-part-rsf "[{;]" part-end)
+ (cond
+ ((eq (char-before) ?\;)
+ (setq end (point))
+ )
+ (t
+ (setq end (web-mode-closing-paren-position (1- (point)) part-end))
+ (if end
+ (setq end (1+ end))
+ (setq end part-end))
+ )
+ ) ;cond
+ (setq end part-end)
+ )
+ ) ;progn selectors
+
+ ;; declaration
+ (goto-char beg)
+ (if (web-mode-part-rsb "[}{;]" part-beg)
+ (setq beg (1+ (point)))
+ (setq beg part-beg)
+ ) ;if
+ ) ;if > pos end
+ )
+;; (message "beg(%S) end(%S)" beg end)
+ (when (eq (char-after beg) ?\n)
+ (setq beg (1+ beg)))
+ (cons beg end)
+ )))
+
+(defun web-mode-jsx-skip (reg-end)
+ (let ((continue t) (pos nil) (i 0) tag)
+ (looking-at "<\\([[:alpha:]][[:alnum:]:-]*\\)")
+ (setq tag (match-string-no-properties 1))
+ ;;(message "point=%S tag=%S" (point) tag)
+ (save-excursion
+ (while continue
+ (cond
+ ((> (setq i (1+ i)) 1000)
+ (message "jsx-skip ** warning **")
+ (setq continue nil))
+ ((looking-at "<[[:alpha:]][[:alnum:]:-]*[ ]*/>")
+ (goto-char (match-end 0))
+ (setq pos (point))
+ (setq continue nil))
+ ((not (web-mode-dom-rsf ">\\([ \t\n]*[\];,)':}|&]\\)\\|{" reg-end))
+ (setq continue nil)
+ )
+ ((eq (char-before) ?\{)
+ (backward-char)
+ (web-mode-closing-paren reg-end)
+ (forward-char)
+ )
+ (t
+ (setq continue nil)
+ (setq pos (match-beginning 1))
+ ) ;t
+ ) ;cond
+ ) ;while
+ ) ;save-excursion
+ (when pos (goto-char pos))
+ ;;(message "jsx-skip: %S" pos)
+ pos))
+
+;; (defun web-mode-jsx-skip2 (reg-end)
+;; (let ((continue t) (pos nil) (i 0) (tag nil) (regexp nil) (counter 1))
+;; (looking-at "<\\([[:alpha:]][[:alnum:]:-]*\\)")
+;; (setq tag (match-string-no-properties 1))
+;; (setq regexp (concat "</?" tag))
+;; ;;(message "point=%S tag=%S" (point) tag)
+;; (save-excursion
+;; (while continue
+;; (cond
+;; ((> (setq i (1+ i)) 100)
+;; (message "jsx-skip ** warning **")
+;; (setq continue nil))
+;; ((looking-at "<[[:alpha:]][[:alnum:]:-]*[ ]*/>")
+;; (goto-char (match-end 0))
+;; (setq pos (point))
+;; (setq continue nil))
+;; ((not (web-mode-dom-rsf ">\\([ \t\n]*[\];,)':}]\\)\\|{" reg-end))
+;; (setq continue nil)
+;; )
+;; ((eq (char-before) ?\{)
+;; (backward-char)
+;; (web-mode-closing-paren reg-end)
+;; (forward-char)
+;; )
+;; (t
+;; (setq continue nil)
+;; (setq pos (match-beginning 1))
+;; ) ;t
+;; ) ;cond
+;; ) ;while
+;; ) ;save-excursion
+;; (when pos (goto-char pos))
+;; ;;(message "jsx-skip: %S" pos)
+;; pos))
+
+;; http://facebook.github.io/jsx/
+;; https://github.com/facebook/jsx/blob/master/AST.md
+(defun web-mode-jsx-scan-element (reg-beg reg-end depth)
+ (unless depth (setq depth 1))
+ (save-excursion
+ (let (token-beg token-end regexp)
+ (goto-char reg-beg)
+ (put-text-property reg-beg (1+ reg-beg) 'jsx-beg depth)
+ (put-text-property (1- reg-end) reg-end 'jsx-end depth)
+ (put-text-property reg-beg reg-end 'jsx-depth depth)
+ (goto-char reg-beg)
+ (web-mode-scan-elements reg-beg reg-end)
+ (web-mode-jsx-scan-expression reg-beg reg-end (1+ depth))
+ )))
+
+(defun web-mode-jsx-scan-expression (reg-beg reg-end depth)
+ (let ((continue t) beg end)
+ (save-excursion
+ (goto-char reg-beg)
+ ;;(message "reg-beg=%S reg-end=%S" reg-beg reg-end)
+ (while (and continue (search-forward "{" reg-end t))
+ (backward-char)
+ (setq beg (point)
+ end (web-mode-closing-paren reg-end))
+ (cond
+ ((eq (get-text-property beg 'part-token) 'comment)
+ (forward-char))
+ ((not end)
+ (setq continue nil))
+ (t
+ (setq end (1+ end))
+ (put-text-property beg end 'jsx-depth depth)
+ (put-text-property beg (1+ beg) 'jsx-beg depth)
+ (put-text-property (1- end) end 'jsx-end depth)
+ (web-mode-part-scan beg end "jsx" (1+ depth))
+ ) ;t
+ ) ;cond
+ ) ;while
+ ) ;save-excursion
+ ))
+
+(defun web-mode-jsx-is-html (&optional pos)
+ (interactive)
+ (unless pos (setq pos (point)))
+ (let (ret (depth (get-text-property pos 'jsx-depth)))
+ (cond
+ ((or (null depth) (<= pos 2))
+ (setq pos nil))
+ ((and (= depth 1) (get-text-property pos 'jsx-beg))
+ (setq pos nil))
+ ((get-text-property pos 'tag-end)
+ (setq pos nil))
+ ((get-text-property pos 'tag-attr-beg)
+ (setq pos nil))
+ ((get-text-property pos 'jsx-beg)
+ (setq pos (null (get-text-property pos 'tag-beg))))
+ ((setq pos (web-mode-jsx-depth-beginning-position pos))
+ (setq pos (not (null (get-text-property pos 'tag-beg)))))
+ (t
+ (setq pos nil))
+ ) ;cond
+ ;;(message "is-html: %S (depth=%S)" pos depth)
+ pos))
+
+(defun web-mode-jsx-is-expr (&optional pos)
+ (cond
+ ((and (get-text-property pos 'jsx-beg)
+ (not (get-text-property pos 'tag-beg)))
+ nil)
+ (t
+ (setq pos (web-mode-jsx-depth-beginning-position pos))
+ (null (get-text-property pos 'tag-beg)))
+ ) ;cond
+ )
+
+(defun web-mode-jsx-depth-beginning-position (&optional pos target-depth)
+ (interactive)
+ (unless pos (setq pos (point)))
+ (unless target-depth (setq target-depth (get-text-property pos 'jsx-depth)))
+ (cond
+ ((or (null target-depth) (bobp))
+ (setq pos nil))
+ ((and (get-text-property pos 'jsx-beg) (= target-depth (get-text-property pos 'jsx-depth)))
+ )
+ (t
+ (let ((continue t) depth)
+ (while continue
+ (setq pos (previous-single-property-change pos 'jsx-depth))
+ (cond
+ ((or (null pos)
+ (null (setq depth (get-text-property pos 'jsx-depth))))
+ (setq continue nil
+ pos nil))
+ ((and (get-text-property pos 'jsx-beg) (= target-depth depth))
+ (setq continue nil))
+ ) ;cond
+ ) ;while
+ ) ;let
+ ) ;t
+ ) ;cond
+ ;;(message "beg: %S" pos)
+ pos)
+
+(defun web-mode-jsx-element-next (reg-end)
+ (let (continue beg end)
+ (setq beg (point))
+ (unless (get-text-property beg 'jsx-depth)
+ (setq beg (next-single-property-change beg 'jsx-beg)))
+ (setq continue (and beg (< beg reg-end))
+ end beg)
+ (while continue
+ (setq end (next-single-property-change end 'jsx-end))
+ (cond
+ ((or (null end) (> end reg-end))
+ (setq continue nil
+ end nil))
+ ((eq (get-text-property end 'jsx-depth) 1)
+ (setq continue nil))
+ (t
+ (setq end (1+ end)))
+ ) ;cond
+ ) ;while
+ ;;(message "beg=%S end=%S" beg end)
+ (if (and beg end (< beg end)) (cons beg end) nil)))
+
+(defun web-mode-jsx-expression-next (reg-end)
+ (let (beg end depth continue pos)
+ (setq beg (point))
+ ;;(message "pt=%S" beg)
+ (unless (and (get-text-property beg 'jsx-beg) (null (get-text-property beg 'tag-beg)))
+ ;;(setq beg (next-single-property-change beg 'jsx-beg))
+ (setq continue t
+ pos (1+ beg))
+ (while continue
+ (setq pos (next-single-property-change pos 'jsx-beg))
+ (cond
+ ((null pos)
+ (setq continue nil
+ beg nil))
+ ((> pos reg-end)
+ (setq continue nil
+ beg nil))
+ ((null (get-text-property pos 'jsx-beg))
+ )
+ ((null (get-text-property pos 'tag-beg))
+ (setq continue nil
+ beg pos))
+ ;;(t
+ ;; (setq pos (1+ pos)))
+ ) ;cond
+ ) ;while
+ ) ;unless
+ ;;(message "beg=%S" beg)
+ (when (and beg (< beg reg-end))
+ (setq depth (get-text-property beg 'jsx-beg)
+ continue (not (null depth))
+ pos beg)
+ ;;(message "beg=%S" beg)
+ (while continue
+ (setq pos (next-single-property-change pos 'jsx-end))
+ ;;(message "pos=%S" pos)
+ (cond
+ ((null pos)
+ (setq continue nil))
+ ((> pos reg-end)
+ (setq continue nil))
+ ((eq depth (get-text-property pos 'jsx-end))
+ (setq continue nil
+ end pos))
+ (t
+ ;;(setq pos (1+ pos))
+ )
+ ) ;cond
+ ) ;while
+ ) ;when
+ ;;(message "%S > %S" beg end)
+ (if (and beg end) (cons beg end) nil)))
+
+(defun web-mode-jsx-depth-next (reg-end)
+ (let (beg end depth continue pos)
+ (setq beg (point))
+ ;;(message "pt=%S" beg)
+ (unless (get-text-property beg 'jsx-beg)
+ ;;(setq beg (next-single-property-change beg 'jsx-beg))
+ ;;(setq pos (1+ beg))
+ (setq pos (next-single-property-change (1+ beg) 'jsx-beg))
+ (cond
+ ((null pos)
+ (setq beg nil))
+ ((>= pos reg-end)
+ (setq beg nil))
+ (t
+ (setq beg pos))
+ ) ;cond
+ ) ;unless
+ ;;(message "beg=%S" beg)
+ (when beg
+ (setq depth (get-text-property beg 'jsx-beg)
+ continue (not (null depth))
+ pos beg)
+ ;;(message "beg=%S" beg)
+ (while continue
+ (setq pos (next-single-property-change pos 'jsx-end))
+ ;;(message "pos=%S" pos)
+ (cond
+ ((null pos)
+ (setq continue nil))
+ ((> pos reg-end)
+ (setq continue nil))
+ ((eq depth (get-text-property pos 'jsx-end))
+ (setq continue nil
+ end pos))
+ (t
+ ;;(setq pos (1+ pos))
+ )
+ ) ;cond
+ ) ;while
+ ) ;when
+ ;;(message "%S > %S" beg end)
+ (if (and beg end) (cons beg end) nil)))
+
+(defun web-mode-jsx-beginning ()
+ (interactive)
+ (let (depth (continue t) (reg-beg (point-min)) (pos (point)))
+ (setq depth (get-text-property pos 'jsx-depth))
+ (cond
+ ((not depth)
+ )
+ ((get-text-property (1- pos) 'jsx-beg)
+ (goto-char (1- pos)))
+ (t
+ (while continue
+ (setq pos (previous-single-property-change pos 'jsx-beg))
+ ;;(message "pos=%S" pos)
+ (cond
+ ((null pos)
+ (setq continue nil))
+ ((<= pos reg-beg)
+ (setq continue nil))
+ ((eq depth (get-text-property pos 'jsx-beg))
+ (setq continue nil))
+ ) ;cond
+ ) ;while
+ (web-mode-go pos)
+ ) ;t
+ ) ;cond
+ ))
+
+(defun web-mode-jsx-end ()
+ (interactive)
+ (let (depth (continue t) (reg-end (point-max)) (pos (point)))
+ (setq depth (get-text-property pos 'jsx-depth))
+ (cond
+ ((not depth)
+ )
+ ((get-text-property pos 'jsx-end)
+ (goto-char (+ pos 1)))
+ (t
+ (while continue
+ (setq pos (next-single-property-change pos 'jsx-end))
+ ;;(message "pos=%S" pos)
+ (cond
+ ((null pos)
+ (setq continue nil))
+ ((> pos reg-end)
+ (setq continue nil))
+ ((eq depth (get-text-property pos 'jsx-end))
+ (setq continue nil))
+ ) ;cond
+ ) ;while
+ (web-mode-go pos 1)
+ ) ;t
+ ) ;cond
+ ))
+
+;;---- FONTIFICATION -----------------------------------------------------------
+
+(defun web-mode-fontify (limit)
+ (when web-mode-trace
+ (message "fontify: point(%S) limit(%S)" (point) limit))
+ (cond
+ ;;(web-mode-skip-fontification
+ ;; nil)
+ (t
+ (web-mode-with-silent-modifications
+ (save-excursion
+ (save-restriction
+ (save-match-data
+ (let ((beg (point))
+ (buffer-undo-list t)
+ (end limit)
+ (inhibit-point-motion-hooks t)
+ (inhibit-quit t))
+ (remove-list-of-text-properties beg end '(font-lock-face face))
+ (cond
+ ((and (get-text-property beg 'block-side)
+ (not (get-text-property beg 'block-beg)))
+ (web-mode-fontify-block beg end))
+ ((or (member web-mode-content-type web-mode-part-content-types)
+ (get-text-property beg 'part-side))
+ (web-mode-fontify-part beg end)
+ (web-mode-block-foreach beg end 'web-mode-fontify-block))
+ ((string= web-mode-engine "none")
+ (web-mode-fontify-tags beg end)
+ (web-mode-part-foreach beg end 'web-mode-fontify-part))
+ (t
+ (web-mode-fontify-tags beg end)
+ (web-mode-part-foreach beg end 'web-mode-fontify-part)
+ (web-mode-block-foreach beg end 'web-mode-fontify-block))
+ ) ;cond
+ (when web-mode-enable-element-content-fontification
+ (web-mode-fontify-elements beg end))
+ (when web-mode-enable-whitespace-fontification
+ (web-mode-fontify-whitespaces beg end))
+ ) ;let
+ ))))
+ nil) ;t
+ ))
+
+(defun web-mode-buffer-fontify ()
+ (interactive)
+ (cond
+ ((and (fboundp 'font-lock-flush) global-font-lock-mode)
+ (font-lock-flush)
+ (font-lock-ensure))
+ (t ;emacs 24
+ ;;(font-lock-fontify-buffer)
+ (and global-font-lock-mode
+ (font-lock-fontify-region (point-min) (point-max))))
+ ))
+
+(defun web-mode-unfontify-region (beg end)
+ ;;(message "unfontify: %S %S" beg end)
+ )
+
+(defun web-mode-fontify-region (beg end keywords)
+;; (message "beg=%S end=%S keywords=%S" beg end (symbol-name keywords))
+ (save-excursion
+ (let ((font-lock-keywords keywords)
+ (font-lock-multiline nil)
+ (font-lock-keywords-case-fold-search
+ (member web-mode-engine '("archibus" "asp" "template-toolkit")))
+ (font-lock-keywords-only t)
+ (font-lock-extend-region-functions nil))
+ (when (and (listp font-lock-keywords) global-font-lock-mode)
+ (font-lock-fontify-region beg end)
+ )
+ )))
+
+(defun web-mode-fontify-tags (reg-beg reg-end &optional depth)
+ (let ((continue t))
+ (goto-char reg-beg)
+ (when (and (not (get-text-property (point) 'tag-beg))
+ (not (web-mode-tag-next)))
+ (setq continue nil))
+ (when (and continue (>= (point) reg-end))
+ (setq continue nil))
+ (while continue
+ (cond
+ (depth
+ (when (eq depth (get-text-property (point) 'jsx-depth))
+ (web-mode-fontify-tag))
+ )
+ (t
+ (web-mode-fontify-tag))
+ ) ;cond
+ (when (or (not (web-mode-tag-next))
+ (>= (point) reg-end))
+ (setq continue nil))
+ ) ;while
+ (when web-mode-enable-inlays
+ (when (null web-mode-inlay-regexp)
+ (setq web-mode-inlay-regexp (regexp-opt '("\\[" "\\(" "\\begin{align}"))))
+ (let (beg end expr)
+ (goto-char reg-beg)
+ (while (web-mode-dom-rsf web-mode-inlay-regexp reg-end)
+ (setq beg (match-beginning 0)
+ end nil
+ expr (substring (match-string-no-properties 0) 0 2))
+ (setq expr (cond
+ ((string= expr "\\[") "\\]")
+ ((string= expr "\\(") "\\)")
+ (t "\\end{align}")))
+ (when (and (web-mode-dom-sf expr reg-end)
+ (setq end (match-end 0))
+ (not (text-property-any beg end 'tag-end t)))
+ (font-lock-append-text-property beg end 'font-lock-face 'web-mode-inlay-face)
+ ) ;when
+ ) ;while
+ ) ;let
+ ) ;when
+ (when web-mode-enable-html-entities-fontification
+ (let (beg end)
+ (goto-char reg-beg)
+ (while (web-mode-dom-rsf "&\\([#]?[[:alnum:]]\\{2,8\\}\\);" reg-end)
+ (setq beg (match-beginning 0)
+ end (match-end 0))
+ (when (not (text-property-any beg end 'tag-end t))
+ (font-lock-append-text-property beg end 'font-lock-face 'web-mode-html-entity-face)
+ ) ;when
+ ) ;while
+ ) ;let
+ ) ;when
+ ))
+
+(defun web-mode-fontify-tag (&optional beg end)
+ (unless beg (setq beg (point)))
+ (unless end (setq end (1+ (web-mode-tag-end-position beg))))
+ (let (name type face flags slash-beg slash-end bracket-end)
+ (setq flags (get-text-property beg 'tag-beg)
+ type (get-text-property beg 'tag-type)
+ name (get-text-property beg 'tag-name))
+ (setq bracket-end (> (logand flags 16) 0))
+ (cond
+ ((eq type 'comment)
+ (put-text-property beg end 'font-lock-face 'web-mode-comment-face)
+ (when (and web-mode-enable-comment-interpolation (> (- end beg) 5))
+ (web-mode-interpolate-comment beg end nil)))
+ ((eq type 'cdata)
+ (put-text-property beg end 'font-lock-face 'web-mode-doctype-face))
+ ((eq type 'doctype)
+ (put-text-property beg end 'font-lock-face 'web-mode-doctype-face))
+ ((eq type 'declaration)
+ (put-text-property beg end 'font-lock-face 'web-mode-doctype-face))
+ (name
+ (setq slash-beg (> (logand flags 4) 0)
+ slash-end (> (logand flags 8) 0)
+ bracket-end (> (logand flags 16) 0))
+ (setq face (cond
+ ((not bracket-end) 'web-mode-html-tag-unclosed-face)
+ ((and web-mode-enable-element-tag-fontification
+ (setq face (cdr (assoc name web-mode-element-tag-faces))))
+ face)
+ ((> (logand flags 32) 0) 'web-mode-html-tag-namespaced-face)
+ ((> (logand flags 2) 0) 'web-mode-html-tag-custom-face)
+ (t 'web-mode-html-tag-face)))
+ (put-text-property beg (+ beg (if slash-beg 2 1))
+ 'font-lock-face 'web-mode-html-tag-bracket-face)
+ (unless (string= name "_fragment_")
+ (put-text-property (+ beg (if slash-beg 2 1))
+ (+ beg (if slash-beg 2 1) (length name))
+ 'font-lock-face face))
+ (when (or slash-end bracket-end)
+ (put-text-property (- end (if slash-end 2 1)) end 'font-lock-face 'web-mode-html-tag-bracket-face)
+ ) ;when
+ (when (> (logand flags 1) 0)
+ ;;(message "%S>%S" beg end)
+ (web-mode-fontify-attrs beg end))
+ ) ;case name
+ ) ;cond
+ ))
+
+(defun web-mode-fontify-attrs (reg-beg reg-end)
+ (let ((continue t) (pos reg-beg) beg end flags offset face)
+ ;;(message "fontify-attrs %S>%S" reg-beg reg-end)
+ (while continue
+ (setq beg (web-mode-attribute-next-position pos reg-end))
+ (cond
+ ((or (null beg) (>= beg reg-end))
+ (setq continue nil))
+ (t
+ (setq flags (or (get-text-property beg 'tag-attr-beg) 0))
+ (setq face (cond
+ ((= (logand flags 1) 1) 'web-mode-html-attr-custom-face)
+ ((= (logand flags 2) 2) 'web-mode-html-attr-engine-face)
+ ((= (logand flags 4) 4) nil)
+ (t 'web-mode-html-attr-name-face)))
+ ;;(setq end (if (get-text-property beg 'tag-attr-end) beg (web-mode-attribute-end-position beg)))
+ (setq end (web-mode-attribute-end-position beg))
+ ;;(message "beg=%S end=%S" beg end)
+ (cond
+ ((or (null end) (>= end reg-end))
+ (setq continue nil))
+ (t
+ (setq offset (get-text-property end 'tag-attr-end))
+ (if (= offset 0)
+ (put-text-property beg (1+ end) 'font-lock-face face)
+ (put-text-property beg (+ beg offset) 'font-lock-face face)
+ (put-text-property (+ beg offset) (+ beg offset 1)
+ 'font-lock-face
+ 'web-mode-html-attr-equal-face)
+ (when (not (get-text-property (+ beg offset 1) 'jsx-beg))
+ (put-text-property (+ beg offset 1) (1+ end)
+ 'font-lock-face
+ 'web-mode-html-attr-value-face)
+ )
+ ) ;if offset
+ (setq pos (1+ end))
+ ) ;t
+ ) ;cond
+ ) ;t
+ );cond
+ ) ;while
+ ))
+
+(defun web-mode-fontify-block (reg-beg reg-end)
+ (when web-mode-trace
+ (message "fontify-block: reg-beg(%S) reg-end(%S) engine(%S) keywords(%S)"
+ reg-beg reg-end web-mode-engine (not (null web-mode-engine-font-lock-keywords))))
+
+ (let (sub1 sub2 sub3 continue char keywords token-type face beg end (buffer (current-buffer)))
+
+ ;; NOTE: required for blocks inside tag attrs
+ (remove-list-of-text-properties reg-beg reg-end '(font-lock-face))
+
+ (goto-char reg-beg)
+
+ (when (null web-mode-engine-font-lock-keywords)
+ (setq sub1 (buffer-substring-no-properties
+ reg-beg (+ reg-beg 1))
+ sub2 (buffer-substring-no-properties
+ reg-beg (+ reg-beg 2))
+ sub3 (buffer-substring-no-properties
+ reg-beg (+ reg-beg (if (>= (point-max) (+ reg-beg 3)) 3 2))))
+ )
+
+ (cond
+
+ ((and (get-text-property reg-beg 'block-beg)
+ (eq (get-text-property reg-beg 'block-token) 'comment))
+ (put-text-property reg-beg reg-end 'font-lock-face 'web-mode-comment-face)
+ ) ;comment block
+
+ (web-mode-engine-font-lock-keywords
+ (setq keywords web-mode-engine-font-lock-keywords))
+
+ ((string= web-mode-engine "django")
+ (cond
+ ((string= sub2 "{{")
+ (setq keywords web-mode-django-expr-font-lock-keywords))
+ ((string= sub2 "{%")
+ (setq keywords web-mode-django-code-font-lock-keywords))
+ ((string= sub1 "#")
+ (setq keywords web-mode-django-code-font-lock-keywords))
+ )) ;django
+
+ ((string= web-mode-engine "mako")
+ (cond
+ ((member sub3 '("<% " "<%\n" "<%!"))
+ (setq keywords web-mode-mako-block-font-lock-keywords))
+ ((eq (aref sub2 0) ?\%)
+ (setq keywords web-mode-mako-block-font-lock-keywords))
+ ((member sub2 '("<%" "</"))
+ (setq keywords web-mode-mako-tag-font-lock-keywords))
+ ((member sub2 '("${"))
+ (setq keywords web-mode-uel-font-lock-keywords))
+ )) ;mako
+
+ ((string= web-mode-engine "mason")
+ ;;(message "%S %S" sub2 sub3)
+ (cond
+ ((member sub3 '("<% " "<%\n" "<&|"))
+ (setq keywords web-mode-mason-code-font-lock-keywords))
+ ((eq (aref sub2 0) ?\%)
+ (setq keywords web-mode-mason-code-font-lock-keywords))
+ ((and (or (string= sub2 "<%") (string= sub3 "</%"))
+ (not (member sub3 '("<%c" "<%i" "<%p"))))
+ (setq keywords web-mode-mason-block-font-lock-keywords))
+ (t
+ (setq keywords web-mode-mason-code-font-lock-keywords))
+ )) ;mason
+
+ ((string= web-mode-engine "jsp")
+ (cond
+ ((string= sub3 "<%@")
+ (setq keywords web-mode-directive-font-lock-keywords))
+ ((member sub2 '("${" "#{"))
+ (setq keywords web-mode-uel-font-lock-keywords))
+ ((string= sub2 "<%")
+ (setq keywords web-mode-jsp-font-lock-keywords))
+ )) ;jsp
+
+ ((string= web-mode-engine "asp")
+ (cond
+ ((or (string= sub2 "<%")
+ (not (string= sub1 "<")))
+ (setq keywords web-mode-asp-font-lock-keywords))
+ (t
+ (setq keywords web-mode-engine-tag-font-lock-keywords))
+ )) ;asp
+
+ ((string= web-mode-engine "clip")
+ (setq keywords web-mode-engine-tag-font-lock-keywords)
+ ) ;clip
+
+ ((string= web-mode-engine "aspx")
+ (cond
+ ((string= sub3 "<%@")
+ (setq keywords web-mode-directive-font-lock-keywords))
+ ((string= sub3 "<%$")
+ (setq keywords web-mode-expression-font-lock-keywords))
+ (t
+ (setq keywords web-mode-aspx-font-lock-keywords))
+ )) ;aspx
+
+ ((string= web-mode-engine "freemarker")
+ (cond
+ ((member sub2 '("${" "#{"))
+ (setq keywords web-mode-uel-font-lock-keywords))
+ ((or (member sub2 '("<@" "[@" "<#" "[#"))
+ (member sub3 '("</@" "[/@" "</#" "[/#")))
+ (setq keywords (if (eq ?\[ (aref sub2 0))
+ web-mode-freemarker-square-font-lock-keywords
+ web-mode-freemarker-font-lock-keywords)))
+ (t
+ (setq keywords web-mode-engine-tag-font-lock-keywords))
+ )) ;freemarker
+
+ ) ;cond
+
+ (when keywords
+ (web-mode-fontify-region reg-beg reg-end keywords)
+ (setq continue t)
+ (setq end reg-beg)
+ (while continue
+ (if (get-text-property end 'block-token)
+ (setq beg end)
+ (setq beg (next-single-property-change end 'block-token buffer reg-end)))
+ (setq end nil)
+ (when beg (setq char (char-after beg)))
+ (if (and beg (< beg reg-end))
+ (progn
+ (setq token-type (get-text-property beg 'block-token))
+ (setq face (cond
+ ((eq token-type 'string) 'web-mode-block-string-face)
+ ((eq token-type 'comment) 'web-mode-block-comment-face)
+ ((eq token-type 'symbol) 'web-mode-symbol-face)
+ (t 'web-mode-block-delimiter-face)))
+ (setq end (next-single-property-change beg 'block-token buffer reg-end))
+;; (message "end=%S" end)
+ (if (and end (<= end reg-end))
+ (progn
+ ;;(message "%S > %S face(%S)" beg end face)
+ (remove-list-of-text-properties beg end '(face))
+ (put-text-property beg end 'font-lock-face face)
+ )
+ (setq continue nil
+ end nil)
+ ) ;if end
+ ) ;progn beg
+ (setq continue nil
+ end nil)
+ ) ;if beg
+ (when (and beg end)
+ (save-match-data
+ (when (and web-mode-enable-heredoc-fontification
+ (eq char ?\<)
+ (> (- end beg) 8)
+ (string-match-p "JS\\|JAVASCRIPT\\|HTM\\|CSS" (buffer-substring-no-properties beg end)))
+ (setq keywords
+ (cond
+ ((string-match-p "H" (buffer-substring-no-properties beg (+ beg 8)))
+ web-mode-html-font-lock-keywords)
+ (t
+ web-mode-javascript-font-lock-keywords)
+ ))
+ (web-mode-fontify-region beg end keywords)
+ )
+ ) ;save-match-data
+ (when (and web-mode-enable-string-interpolation
+ (member char '(?\" ?\<))
+ (member web-mode-engine '("php" "erb"))
+ (> (- end beg) 4))
+ (web-mode-interpolate-block-string beg end)
+ ) ;when
+ (when (and web-mode-enable-comment-interpolation
+ (eq token-type 'comment)
+ (> (- end beg) 3))
+ (web-mode-interpolate-comment beg end t)
+ ) ;when
+ (when (and web-mode-enable-comment-annotation
+ (eq token-type 'comment)
+ (> (- end beg) 3))
+ (web-mode-annotate-comment beg end)
+ ) ;when
+ (when (and web-mode-enable-sql-detection
+ (eq token-type 'string)
+ (> (- end beg) 6)
+ (web-mode-looking-at-p (concat "\\(.\\|<<<[[:alnum:]]+\\)[ \n]*" web-mode-sql-queries) beg)
+ )
+ (web-mode-interpolate-sql-string beg end)
+ ) ;when
+ ) ;when beg end
+ ) ;while continue
+ ) ;when keywords
+
+ (when (and (member web-mode-engine '("mako"))
+ (> (- reg-end reg-beg) 12)
+ (eq ?\< (char-after reg-beg)))
+ (web-mode-interpolate-block-tag reg-beg reg-end))
+
+ (when web-mode-enable-block-face
+ (font-lock-append-text-property reg-beg reg-end 'face 'web-mode-block-face))
+
+ ))
+
+(defun web-mode-fontify-part (reg-beg reg-end &optional depth)
+ (save-excursion
+ (let (start continue token-type face pos beg end string-face comment-face content-type)
+ ;;(message "fontify-part: reg-beg(%S) reg-end(%S)" reg-beg reg-end)
+ (if (member web-mode-content-type web-mode-part-content-types)
+ (setq content-type web-mode-content-type)
+ (setq content-type (symbol-name (get-text-property reg-beg 'part-side))))
+ ;;(message "content-type=%S" content-type)
+ (unless depth
+ (when (string= content-type "jsx") (setq depth 0))
+ )
+ (setq string-face 'web-mode-part-string-face
+ comment-face 'web-mode-part-comment-face)
+ (cond
+ ((member content-type '("javascript" "jsx"))
+ (setq string-face 'web-mode-javascript-string-face
+ comment-face 'web-mode-javascript-comment-face)
+ (web-mode-fontify-region reg-beg reg-end web-mode-javascript-font-lock-keywords))
+ ((string= content-type "json")
+ (setq string-face 'web-mode-json-string-face
+ comment-face 'web-mode-json-comment-face)
+ (web-mode-fontify-region reg-beg reg-end web-mode-javascript-font-lock-keywords))
+ ((string= content-type "css")
+ (setq string-face 'web-mode-css-string-face
+ comment-face 'web-mode-css-comment-face)
+ (web-mode-fontify-css-rules reg-beg reg-end))
+ ((string= content-type "sql")
+ (web-mode-fontify-region reg-beg reg-end web-mode-sql-font-lock-keywords))
+ ((string= content-type "stylus")
+ (web-mode-fontify-region reg-beg reg-end web-mode-stylus-font-lock-keywords))
+ ((string= content-type "sass")
+ (web-mode-fontify-region reg-beg reg-end web-mode-sass-font-lock-keywords))
+ ((string= content-type "pug")
+ (web-mode-fontify-region reg-beg reg-end web-mode-pug-font-lock-keywords))
+ ((string= content-type "markdown")
+ (web-mode-fontify-region reg-beg reg-end web-mode-markdown-font-lock-keywords))
+ ((string= content-type "ruby")
+ (web-mode-fontify-region reg-beg reg-end web-mode-erb-font-lock-keywords))
+ ((string= content-type "typescript")
+ (web-mode-fontify-region reg-beg reg-end web-mode-javascript-font-lock-keywords))
+ ) ;cond
+
+ (goto-char reg-beg)
+
+ ;;(when (string= content-type "jsx") (web-mode-fontify-tags reg-beg reg-end))
+ ;;(setq continue (and pos (< pos reg-end)))
+ (setq continue t
+ pos reg-beg)
+ (while continue
+ (if (get-text-property pos 'part-token)
+ (setq beg pos)
+ (setq beg (next-single-property-change pos 'part-token)))
+ (cond
+ ((or (null beg) (>= beg reg-end))
+ (setq continue nil
+ end nil))
+ ((and (eq depth 0) (get-text-property beg 'jsx-depth))
+ (setq pos (or (next-single-property-change beg 'jsx-depth) (point-max))))
+ (t
+ ;;(message "%c" (char-after beg))
+ (setq token-type (get-text-property beg 'part-token))
+ (setq face (cond
+ ((eq token-type 'string) string-face)
+ ((eq token-type 'comment) comment-face)
+ ((eq token-type 'context) 'web-mode-json-context-face)
+ ((eq token-type 'key) 'web-mode-json-key-face)
+ (t nil)))
+ (setq end (or (next-single-property-change beg 'part-token) (point-max))
+ pos end)
+ (cond
+ ((or (null end) (> end reg-end))
+ (setq continue nil
+ end nil))
+ (t
+ (when face
+ (remove-list-of-text-properties beg end '(face))
+ (put-text-property beg end 'font-lock-face face))
+ (cond
+ ((< (- end beg) 6)
+ )
+ ((eq token-type 'string)
+ (cond
+ ((and (eq (char-after beg) ?\`)
+ web-mode-enable-literal-interpolation
+ (member content-type '("javascript" "jsx")))
+ (web-mode-interpolate-javascript-literal beg end)
+ )
+ ((and (eq (char-after beg) ?\")
+ web-mode-enable-string-interpolation
+ (member content-type '("javascript" "jsx")))
+ (web-mode-interpolate-javascript-string beg end))
+ ) ;cond
+ ) ;case string
+ ((eq token-type 'comment)
+ (when web-mode-enable-comment-interpolation
+ (web-mode-interpolate-comment beg end t))
+ (when web-mode-enable-comment-annotation
+ (web-mode-annotate-comment beg end))
+ )
+ ) ;cond
+ ) ;t
+ ) ;cond
+ ) ;t
+ ) ;cond
+ ) ;while
+
+ (when (and (string= web-mode-content-type "html") web-mode-enable-part-face)
+ (font-lock-append-text-property reg-beg reg-end 'face
+ (cond
+ ((string= content-type "javascript")
+ 'web-mode-script-face)
+ ((string= content-type "css")
+ 'web-mode-style-face)
+ (t
+ 'web-mode-part-face)))
+ )
+
+ (when (and web-mode-enable-css-colorization (string= content-type "stylus"))
+ (goto-char reg-beg)
+ (while (and (re-search-forward "#[0-9a-fA-F]\\{6\\}\\|#[0-9a-fA-F]\\{3\\}\\|rgba?([ ]*\\([[:digit:]]\\{1,3\\}\\)[ ]*,[ ]*\\([[:digit:]]\\{1,3\\}\\)[ ]*,[ ]*\\([[:digit:]]\\{1,3\\}\\)\\(.*?\\))" end t)
+ (<= (point) reg-end))
+ (web-mode-colorize (match-beginning 0) (match-end 0))
+ )
+ )
+
+ (when (and (eq depth 0) (string= content-type "jsx"))
+ (let (pair elt-beg elt-end exp-beg exp-end exp-depth)
+ (goto-char reg-beg)
+ (while (setq pair (web-mode-jsx-element-next reg-end))
+ ;;(message "elt-pair=%S" pair)
+ (setq elt-beg (car pair)
+ elt-end (cdr pair))
+ (remove-list-of-text-properties elt-beg (1+ elt-end) '(face))
+ (web-mode-fontify-tags elt-beg elt-end 1)
+ (goto-char elt-beg)
+ (while (setq pair (web-mode-jsx-expression-next elt-end))
+ ;;(message "exp-pair=%S elt-end=%S" pair elt-end)
+ (setq exp-beg (car pair)
+ exp-end (cdr pair))
+ (when (eq (char-after exp-beg) ?\{)
+ ;;(message "%S : %c %c" exp-beg (char-after (+ exp-beg 1)) (char-after (+ exp-beg 2)))
+ (cond
+ ;;((and (eq (char-after (+ exp-beg 1)) ?\/) (eq (char-after (+ exp-beg 2)) ?\*))
+ ;; (put-text-property exp-beg (1+ exp-end) 'font-lock-face 'web-mode-part-comment-face)
+ ;; )
+ (t
+ (setq exp-depth (get-text-property exp-beg 'jsx-depth))
+ (remove-list-of-text-properties exp-beg exp-end '(font-lock-face))
+ (put-text-property exp-beg (1+ exp-beg) 'font-lock-face 'web-mode-block-delimiter-face)
+ (when (and (eq (get-text-property exp-beg 'tag-attr-beg) 4) (web-mode-looking-at-p "\.\.\." (1+ exp-beg)))
+ (put-text-property exp-beg (+ exp-beg 4) 'font-lock-face 'web-mode-block-delimiter-face))
+ (put-text-property exp-end (1+ exp-end) 'font-lock-face 'web-mode-block-delimiter-face)
+ (web-mode-fontify-tags (1+ exp-beg) exp-end (1+ exp-depth))
+ (web-mode-fontify-part (1+ exp-beg) exp-end exp-depth)
+ (web-mode-fontify-region (1+ exp-beg) exp-end web-mode-javascript-font-lock-keywords)
+ ) ;t
+ ) ;cond
+ ) ;when
+ (goto-char (1+ exp-beg))
+ ) ;while exp
+
+ (when (and elt-beg web-mode-jsx-depth-faces)
+ (let (depth-beg depth-end jsx-face)
+ (goto-char elt-beg)
+ (while (setq pair (web-mode-jsx-depth-next reg-end))
+ ;;(message "depth-pair=%S" pair)
+ (setq depth-beg (car pair)
+ depth-end (cdr pair)
+ depth (get-text-property depth-beg 'jsx-depth)
+ jsx-face (elt web-mode-jsx-depth-faces (1- depth)))
+ ;;(message "%S" jsx-face)
+ (font-lock-prepend-text-property depth-beg (1+ depth-end) 'face jsx-face)
+ (goto-char (+ depth-beg 2))
+ )
+ ) ;let
+ )
+
+ (goto-char (1+ elt-end))
+ ) ;while elt
+ ) ;let
+ ) ;when
+
+ ) ;let
+ ) ;save-excursion
+ )
+
+(defun web-mode-fontify-css-rules (part-beg part-end)
+ (save-excursion
+ (goto-char part-beg)
+ (let (rule (continue t) (i 0) (at-rule nil) (var-rule nil))
+ (while continue
+ (setq rule (web-mode-css-rule-next part-end))
+ ;;(message "rule=%S" rule)
+ (cond
+ ((> (setq i (1+ i)) 1000)
+ (message "fontify-css-rules ** too much rules **")
+ (setq continue nil))
+ ((null rule)
+ (setq continue nil))
+ ((and (setq at-rule (plist-get rule :at-rule))
+ (not (member at-rule '("charset" "font-face" "import" "viewport")))
+ (plist-get rule :dec-end))
+ (web-mode-fontify-css-rule (plist-get rule :sel-beg)
+ (plist-get rule :sel-end)
+ nil nil)
+ (web-mode-fontify-css-rules (plist-get rule :dec-beg)
+ (plist-get rule :dec-end)))
+ (t
+ (web-mode-fontify-css-rule (plist-get rule :sel-beg)
+ (plist-get rule :sel-end)
+ (plist-get rule :dec-beg)
+ (plist-get rule :dec-end)))
+ ) ;cond
+ ) ;while
+ ) ;let
+ ))
+
+(defun web-mode-fontify-css-rule (sel-beg sel-end dec-beg dec-end)
+ (save-excursion
+ ;;(let ((end sel-end))
+ ;;(message "sel-beg=%S sel-end=%S dec-beg=%S dec-end=%S" sel-beg sel-end dec-beg dec-end)
+ (web-mode-fontify-region sel-beg sel-end web-mode-selector-font-lock-keywords)
+ (when (and dec-beg dec-end)
+ ;;(setq end dec-end)
+ (web-mode-fontify-region dec-beg dec-end web-mode-declaration-font-lock-keywords)
+ ) ;when
+ (when (and dec-beg dec-end)
+ (goto-char dec-beg)
+ (while (and web-mode-enable-css-colorization
+ (re-search-forward "#[0-9a-fA-F]\\{6\\}\\|#[0-9a-fA-F]\\{3\\}\\|rgba?([ ]*\\([[:digit:]]\\{1,3\\}\\)[ ]*,[ ]*\\([[:digit:]]\\{1,3\\}\\)[ ]*,[ ]*\\([[:digit:]]\\{1,3\\}\\)\\(.*?\\))" dec-end t)
+ ;;(progn (message "%S %S" end (point)) t)
+ (<= (point) dec-end))
+ (web-mode-colorize (match-beginning 0) (match-end 0))
+ ) ;while
+ ) ;when
+ ;;) ;let
+ ))
+
+(defun web-mode-colorize-foreground (color)
+ (let* ((values (x-color-values color))
+ (r (car values))
+ (g (cadr values))
+ (b (car (cdr (cdr values)))))
+ (if (> 128.0 (floor (+ (* .3 r) (* .59 g) (* .11 b)) 256))
+ "white" "black")))
+
+(defun web-mode-colorize (beg end)
+ (let (str plist len)
+ (setq str (buffer-substring-no-properties beg end))
+ (setq len (length str))
+ (cond
+ ((string= (substring str 0 1) "#")
+ (setq plist (list :background str
+ :foreground (web-mode-colorize-foreground str)))
+ (put-text-property beg end 'face plist))
+ ((or (string= (substring str 0 4) "rgb(") (string= (substring str 0 5) "rgba("))
+ (setq str (format "#%02X%02X%02X"
+ (string-to-number (match-string-no-properties 1))
+ (string-to-number (match-string-no-properties 2))
+ (string-to-number (match-string-no-properties 3))))
+ (setq plist (list :background str
+ :foreground (web-mode-colorize-foreground str)))
+ (put-text-property beg end 'face plist))
+ ) ;cond
+ ))
+
+(defun web-mode-interpolate-block-tag (beg end)
+ (save-excursion
+ (goto-char (+ 4 beg))
+ (setq end (1- end))
+ (while (re-search-forward "${.*?}" end t)
+ (remove-list-of-text-properties (match-beginning 0) (match-end 0) '(face))
+ (web-mode-fontify-region (match-beginning 0) (match-end 0)
+ web-mode-uel-font-lock-keywords))
+ ))
+
+(defun web-mode-interpolate-javascript-string (beg end)
+ (save-excursion
+ (goto-char (1+ beg))
+ (setq end (1- end))
+ (while (re-search-forward "${.*?}" end t)
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'font-lock-face
+ 'web-mode-variable-name-face)
+ )
+ ))
+
+(defun web-mode-interpolate-javascript-literal (beg end)
+ (save-excursion
+ (goto-char (1+ beg))
+ (setq end (1- end))
+ (while (re-search-forward "${.*?}" end t)
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'font-lock-face
+ 'web-mode-variable-name-face)
+ )
+ (cond
+ ((web-mode-looking-back "\\(css\\|styled[[:alnum:].]+\\)" beg)
+ (goto-char (1+ beg))
+ (while (re-search-forward ".*?:" end t)
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'font-lock-face
+ 'web-mode-interpolate-color1-face)
+ )
+ ) ;case css
+ ((web-mode-looking-back "\\(template\\|html\\)" beg)
+ (goto-char (1+ beg))
+ (while (re-search-forward web-mode-tag-regexp end t)
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'font-lock-face
+ 'web-mode-interpolate-color1-face)
+ )
+ (goto-char (1+ beg))
+ (while (re-search-forward "</?\\|/?>\\| [[:alnum:]]+=" end t)
+ (cond
+ ((member (char-after (match-beginning 0)) '(?\< ?\/ ?\>))
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'font-lock-face
+ 'web-mode-interpolate-color2-face)
+ )
+ (t
+ (put-text-property (1+ (match-beginning 0)) (1- (match-end 0))
+ 'font-lock-face
+ 'web-mode-interpolate-color3-face)
+ ) ;t
+ ) ;cond
+ ) ;while
+ ) ;case html
+ ) ;cond type of literal
+ ))
+
+;; todo : parsing plus compliqué: {$obj->values[3]->name}
+(defun web-mode-interpolate-block-string (beg end)
+ (save-excursion
+ (goto-char (1+ beg))
+ (setq end (1- end))
+ (cond
+ ((string= web-mode-engine "php")
+ (while (re-search-forward "$[[:alnum:]_]+\\(->[[:alnum:]_]+\\)*\\|{[ ]*$.+?}" end t)
+;; (message "%S > %S" (match-beginning 0) (match-end 0))
+ (remove-list-of-text-properties (match-beginning 0) (match-end 0) '(font-lock-face))
+ (web-mode-fontify-region (match-beginning 0) (match-end 0)
+ web-mode-php-var-interpolation-font-lock-keywords)
+ ))
+ ((string= web-mode-engine "erb")
+ (while (re-search-forward "#{.*?}" end t)
+ (remove-list-of-text-properties (match-beginning 0) (match-end 0) '(font-lock-face))
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'font-lock-face 'web-mode-variable-name-face)
+ ))
+ ) ;cond
+ ))
+
+(defun web-mode-interpolate-comment (beg end block-side)
+ (save-excursion
+ (let ((regexp (concat "\\_<\\(" web-mode-comment-keywords "\\)\\_>")))
+ (goto-char beg)
+ (while (re-search-forward regexp end t)
+ (font-lock-prepend-text-property (match-beginning 1) (match-end 1)
+ 'font-lock-face
+ 'web-mode-comment-keyword-face)
+ ) ;while
+ )))
+
+(defun web-mode-annotate-comment (beg end)
+ (save-excursion
+ ;;(message "beg=%S end=%S" beg end)
+ (goto-char beg)
+ (when (looking-at-p "/\\*\\*")
+ (while (re-search-forward "\\(.+\\)" end t)
+ (font-lock-prepend-text-property (match-beginning 1) (match-end 1)
+ 'font-lock-face
+ 'web-mode-annotation-face))
+ (goto-char beg)
+ (while (re-search-forward "[ ]+\\({[^}]+}\\)" end t)
+ (font-lock-prepend-text-property (match-beginning 1) (match-end 1)
+ 'font-lock-face
+ 'web-mode-annotation-type-face))
+ (goto-char beg)
+ (while (re-search-forward "\\(@[[:alnum:]]+\\)" end t)
+ (font-lock-prepend-text-property (match-beginning 1) (match-end 1)
+ 'font-lock-face
+ 'web-mode-annotation-tag-face))
+ (goto-char beg)
+ (while (re-search-forward "}[[:blank:]]+\\([[:graph:]]+\\)" end t)
+ (font-lock-prepend-text-property (match-beginning 1) (match-end 1)
+ 'font-lock-face
+ 'web-mode-annotation-value-face))
+ (goto-char beg)
+ (while (re-search-forward "@see[[:blank:]]+\\([[:graph:]]+\\)" end t)
+ (font-lock-prepend-text-property (match-beginning 1) (match-end 1)
+ 'font-lock-face
+ 'web-mode-annotation-value-face))
+ (goto-char beg)
+ (while (re-search-forward "{\\(@\\(?:link\\|code\\)\\)\\s-+\\([^}\n]+\\)\\(#.+\\)?}" end t)
+ (font-lock-prepend-text-property (match-beginning 2) (match-end 2)
+ 'font-lock-face
+ 'web-mode-annotation-value-face))
+ (goto-char beg)
+ (while (re-search-forward "\\(</?\\)\\([[:alnum:]]+\\)\\s-*\\(/?>\\)" end t)
+ (font-lock-prepend-text-property (match-beginning 1) (match-end 1)
+ 'font-lock-face
+ 'web-mode-annotation-html-face)
+ (font-lock-prepend-text-property (match-beginning 2) (match-end 2)
+ 'font-lock-face
+ 'web-mode-annotation-html-face)
+ (font-lock-prepend-text-property (match-beginning 3) (match-end 3)
+ 'font-lock-face
+ 'web-mode-annotation-html-face))
+ ) ;when
+ ))
+
+(defun web-mode-interpolate-sql-string (beg end)
+ (save-excursion
+ (let ((case-fold-search t)
+ (regexp (concat "\\_<\\(" web-mode-sql-keywords "\\)\\_>")))
+ (goto-char beg)
+ (while (re-search-forward regexp end t)
+ (font-lock-prepend-text-property (match-beginning 1) (match-end 1)
+ 'font-lock-face
+ 'web-mode-sql-keyword-face)
+ ) ;while
+ )))
+
+;;---- EFFECTS -----------------------------------------------------------------
+
+(defun web-mode-fill-paragraph (&optional justify)
+ (save-excursion
+ (let ((pos (point)) fill-coll
+ prop pair beg end delim-beg delim-end chunk fill-col)
+ (cond
+ ((or (eq (get-text-property pos 'part-token) 'comment)
+ (eq (get-text-property pos 'block-token) 'comment))
+ (setq prop
+ (if (get-text-property pos 'part-token) 'part-token 'block-token))
+ (setq pair (web-mode-property-boundaries prop pos))
+ (when (and pair (> (- (cdr pair) (car pair)) 6))
+ (setq fill-coll (if (< fill-column 10) 70 fill-column))
+ (setq beg (car pair)
+ end (cdr pair))
+ (goto-char beg)
+ (setq chunk (buffer-substring-no-properties beg (+ beg 2)))
+ (cond
+ ((string= chunk "//")
+ (setq delim-beg "//"
+ delim-end "EOL"))
+ ((string= chunk "/*")
+ (setq delim-beg "/*"
+ delim-end "*/"))
+ ((string= chunk "{#")
+ (setq delim-beg "{#"
+ delim-end "#}"))
+ ((string= chunk "<!")
+ (setq delim-beg "<!--"
+ delim-end "-->"))
+ )
+ )
+ ) ;comment - case
+ ((web-mode-is-content)
+ (setq pair (web-mode-content-boundaries pos))
+ (setq beg (car pair)
+ end (cdr pair))
+ )
+ ) ;cond
+ ;;(message "beg(%S) end(%S)" beg end)
+ (when (and beg end)
+ (fill-region beg end))
+ t)))
+
+(defun web-mode-engine-syntax-check ()
+ (interactive)
+ (let ((proc nil) (errors nil)
+ (file (concat temporary-file-directory "emacs-web-mode-tmp")))
+ (write-region (point-min) (point-max) file)
+ (cond
+ ;; ((null (buffer-file-name))
+ ;; )
+ ((string= web-mode-engine "php")
+ (setq proc (start-process "php-proc" nil "php" "-l" file))
+ (set-process-filter
+ proc
+ (lambda (proc output)
+ (cond
+ ((string-match-p "No syntax errors" output)
+ (message "No syntax errors")
+ )
+ (t
+ ;; (setq output (replace-regexp-in-string temporary-file-directory "" output))
+ ;; (message output)
+ (message "Syntax error")
+ (setq errors t))
+ ) ;cond
+ ;; (delete-file file)
+ ) ;lambda
+ )
+ ) ;php
+ (t
+ (message "no syntax checker found")
+ ) ;t
+ ) ;cond
+ errors))
+
+(defun web-mode-jshint ()
+ "Run JSHint on all the JavaScript parts."
+ (interactive)
+ (let (proc lines)
+ (when (buffer-file-name)
+ (setq proc (start-process
+ "jshint-proc"
+ nil
+ (or (executable-find "jshint") "/usr/local/bin/jshint")
+ "--extract=auto"
+ (buffer-file-name)))
+ (setq web-mode-jshint-errors 0)
+ (set-process-filter proc
+ (lambda (proc output)
+ (let ((offset 0) overlay pos (old 0) msg)
+ (remove-overlays (point-min) (point-max) 'font-lock-face 'web-mode-error-face)
+ (while (string-match
+ "line \\([[:digit:]]+\\), col \\([[:digit:]]+\\), \\(.+\\)\\.$"
+ output offset)
+ (setq web-mode-jshint-errors (1+ web-mode-jshint-errors))
+ (setq offset (match-end 0))
+ (setq pos (web-mode-coord-position
+ (match-string-no-properties 1 output)
+ (match-string-no-properties 2 output)))
+ (when (get-text-property pos 'tag-beg)
+ (setq pos (1- pos)))
+ (when (not (= pos old))
+ (setq old pos)
+ (setq overlay (make-overlay pos (1+ pos)))
+ (overlay-put overlay 'font-lock-face 'web-mode-error-face)
+ )
+ (setq msg (or (overlay-get overlay 'help-echo)
+ (concat "line="
+ (match-string-no-properties 1 output)
+ " column="
+ (match-string-no-properties 2 output)
+ )))
+ (overlay-put overlay 'help-echo
+ (concat msg " ## " (match-string-no-properties 3 output)))
+ ) ;while
+ ))
+ )
+ ) ;when
+ ))
+
+(defun web-mode-dom-errors-show ()
+ "Show unclosed tags."
+ (interactive)
+ (let (beg end tag pos l n tags i cont cell overlay overlays first
+ (ori (point))
+ (errors 0)
+ (continue t)
+ )
+ (setq overlays (overlays-in (point-min) (point-max)))
+ (when overlays
+ (dolist (overlay overlays)
+ (when (eq (overlay-get overlay 'face) 'web-mode-warning-face)
+ (delete-overlay overlay)
+ )
+ )
+ )
+ (goto-char (point-min))
+ (when (not (or (get-text-property (point) 'tag-beg)
+ (web-mode-tag-next)))
+ (setq continue nil))
+ (while continue
+ (setq pos (point))
+ (setq tag (get-text-property pos 'tag-name))
+ (cond
+ ((eq (get-text-property (point) 'tag-type) 'start)
+ (setq tags (push (list tag pos) tags))
+;; (message "(%S) opening %S" pos tag)
+ )
+ ((eq (get-text-property (point) 'tag-type) 'end)
+ (setq i 0
+ l (length tags)
+ cont t)
+ (while (and (< i l) cont)
+ (setq cell (nth i tags))
+;; (message "cell=%S" cell)
+ (setq i (1+ i))
+ (cond
+ ((string= tag (nth 0 cell))
+ (setq cont nil)
+ )
+ (t
+ (setq errors (1+ errors))
+ (setq beg (nth 1 cell))
+ (setq end (web-mode-tag-end-position beg))
+ (unless first
+ (setq first beg))
+ (setq overlay (make-overlay beg (1+ end)))
+ (overlay-put overlay 'font-lock-face 'web-mode-warning-face)
+;; (message "invalid <%S> at %S" (nth 0 cell) (nth 1 cell))
+ )
+ ) ;cond
+ ) ;while
+
+ (dotimes (i i)
+ (setq tags (cdr tags)))
+
+ )
+ ) ;cond
+ (when (not (web-mode-tag-next))
+ (setq continue nil))
+ ) ;while
+ (message "%S error(s) detected" errors)
+ (if (< errors 1)
+ (goto-char ori)
+ (goto-char first)
+ (recenter))
+ ;; (message "%S" tags)
+ ))
+
+(defun web-mode-fontify-elements (beg end)
+ (save-excursion
+ (goto-char beg)
+ (let ((continue (or (get-text-property (point) 'tag-beg) (web-mode-tag-next)))
+ (i 0) (ctx nil) (face nil))
+ (while continue
+ (cond
+ ((> (setq i (1+ i)) 1000)
+ (message "fontify-elements ** too much tags **")
+ (setq continue nil))
+ ((> (point) end)
+ (setq continue nil))
+ ((not (get-text-property (point) 'tag-beg))
+ (setq continue nil))
+ ((eq (get-text-property (point) 'tag-type) 'start)
+ (when (and (setq ctx (web-mode-element-boundaries (point)))
+ (<= (car (cdr ctx)) end)
+ (setq face (cdr (assoc (get-text-property (point) 'tag-name) web-mode-element-content-faces))))
+ (font-lock-prepend-text-property (1+ (cdr (car ctx))) (car (cdr ctx))
+ 'font-lock-face face))
+ )
+ ) ;cond
+ (when (not (web-mode-tag-next))
+ (setq continue nil))
+ ) ;while
+ )))
+
+(defun web-mode-enable (feature)
+ "Enable one feature."
+ (interactive
+ (list (completing-read
+ "Feature: "
+ (let (features)
+ (dolist (elt web-mode-features)
+ (setq features (append features (list (car elt)))))
+ features))))
+ (when (and (or (not feature) (< (length feature) 1)) web-mode-last-enabled-feature)
+ (setq feature web-mode-last-enabled-feature))
+ (when feature
+ (setq web-mode-last-enabled-feature feature)
+ (setq feature (cdr (assoc feature web-mode-features)))
+ (cond
+ ((eq feature 'web-mode-enable-current-column-highlight)
+ (web-mode-column-show))
+ ((eq feature 'web-mode-enable-current-element-highlight)
+ (when (not web-mode-enable-current-element-highlight)
+ (web-mode-toggle-current-element-highlight))
+ )
+ ((eq feature 'web-mode-enable-whitespace-fontification)
+ (web-mode-whitespaces-on))
+ (t
+ (set feature t)
+ (web-mode-buffer-fontify))
+ )
+ ) ;when
+ )
+
+(defun web-mode-disable (feature)
+ "Disable one feature."
+ (interactive
+ (list (completing-read
+ "Feature: "
+ (let (features)
+ (dolist (elt web-mode-features)
+ (setq features (append features (list (car elt)))))
+ features))))
+ (when (and (or (not feature) (< (length feature) 1)) web-mode-last-enabled-feature)
+ (setq feature web-mode-last-enabled-feature))
+ (when feature
+ (setq feature (cdr (assoc feature web-mode-features)))
+ (cond
+ ((eq feature 'web-mode-enable-current-column-highlight)
+ (web-mode-column-hide))
+ ((eq feature 'web-mode-enable-current-element-highlight)
+ (when web-mode-enable-current-element-highlight
+ (web-mode-toggle-current-element-highlight))
+ )
+ ((eq feature 'web-mode-enable-whitespace-fontification)
+ (web-mode-whitespaces-off))
+ (t
+ (set feature nil)
+ (web-mode-buffer-fontify))
+ )
+ ) ;when
+ )
+
+(defun web-mode-toggle-current-element-highlight ()
+ "Toggle highlighting of the current html element."
+ (interactive)
+ (if web-mode-enable-current-element-highlight
+ (progn
+ (web-mode-delete-tag-overlays)
+ (setq web-mode-enable-current-element-highlight nil))
+ (setq web-mode-enable-current-element-highlight t)
+ ))
+
+(defun web-mode-make-tag-overlays ()
+ (unless web-mode-overlay-tag-start
+ (setq web-mode-overlay-tag-start (make-overlay 1 1)
+ web-mode-overlay-tag-end (make-overlay 1 1))
+ (overlay-put web-mode-overlay-tag-start
+ 'font-lock-face
+ 'web-mode-current-element-highlight-face)
+ (overlay-put web-mode-overlay-tag-end
+ 'font-lock-face
+ 'web-mode-current-element-highlight-face)))
+
+(defun web-mode-delete-tag-overlays ()
+ (when web-mode-overlay-tag-start
+ (delete-overlay web-mode-overlay-tag-start)
+ (delete-overlay web-mode-overlay-tag-end)))
+
+(defun web-mode-column-overlay-factory (index)
+ (let (overlay)
+ (when (null web-mode-column-overlays)
+ (dotimes (i 100)
+ (setq overlay (make-overlay 1 1))
+ (overlay-put overlay 'font-lock-face 'web-mode-current-column-highlight-face)
+ (setq web-mode-column-overlays (append web-mode-column-overlays (list overlay)))
+ )
+ ) ;when
+ (setq overlay (nth index web-mode-column-overlays))
+ (when (null overlay)
+ (setq overlay (make-overlay 1 1))
+ (overlay-put overlay 'font-lock-face 'web-mode-current-column-highlight-face)
+ (setq web-mode-column-overlays (append web-mode-column-overlays (list overlay)))
+ ) ;when
+ overlay))
+
+(defun web-mode-column-hide ()
+ (setq web-mode-enable-current-column-highlight nil)
+ (remove-overlays (point-min) (point-max)
+ 'font-lock-face
+ 'web-mode-current-column-highlight-face))
+
+(defun web-mode-column-show ()
+ (let ((index 0) overlay diff column line-to line-from)
+ (web-mode-column-hide)
+ (setq web-mode-enable-current-column-highlight t)
+ (save-excursion
+ (back-to-indentation)
+ (setq column (current-column)
+ line-to (web-mode-line-number))
+ (when (and (get-text-property (point) 'tag-beg)
+ (member (get-text-property (point) 'tag-type) '(start end))
+ (web-mode-tag-match)
+ (setq line-from (web-mode-line-number))
+ (not (= line-from line-to)))
+ (when (> line-from line-to)
+ (let (tmp)
+ (setq tmp line-from)
+ (setq line-from line-to)
+ (setq line-to tmp))
+ ) ;when
+ ;;(message "column(%S) line-from(%S) line-to(%S)" column line-from line-to)
+ (goto-char (point-min))
+ (when (> line-from 1)
+ (forward-line (1- line-from)))
+ (while (<= line-from line-to)
+ (setq overlay (web-mode-column-overlay-factory index))
+ (setq diff (- (line-end-position) (point)))
+ (cond
+ ((or (and (= column 0) (= diff 0))
+ (> column diff))
+ (end-of-line)
+ (move-overlay overlay (point) (point))
+ (overlay-put overlay
+ 'after-string
+ (concat
+ (if (> column diff) (make-string (- column diff) ?\s) "")
+ (propertize " "
+ 'font-lock-face
+ 'web-mode-current-column-highlight-face)
+ ) ;concat
+ )
+ )
+ (t
+ (move-to-column column)
+ (overlay-put overlay 'after-string nil)
+ (move-overlay overlay (point) (1+ (point)))
+ )
+ ) ;cond
+ (setq line-from (1+ line-from))
+ (forward-line)
+ (setq index (1+ index))
+ ) ;while
+ ) ;when
+ ) ;save-excursion
+ ) ;let
+ )
+
+(defun web-mode-highlight-current-element ()
+ (let ((ctx (web-mode-element-boundaries)) len)
+ (cond
+ ((null ctx)
+ (web-mode-delete-tag-overlays))
+ ((eq (get-text-property (caar ctx) 'tag-type) 'void) ;; #1046
+ (web-mode-make-tag-overlays)
+ (setq len (length (get-text-property (caar ctx) 'tag-name)))
+ (move-overlay web-mode-overlay-tag-start (+ (caar ctx) 1) (+ (caar ctx) 1 len))
+ )
+ (t
+ (web-mode-make-tag-overlays)
+ (setq len (length (get-text-property (caar ctx) 'tag-name)))
+ (move-overlay web-mode-overlay-tag-start (+ (caar ctx) 1) (+ (caar ctx) 1 len))
+ (move-overlay web-mode-overlay-tag-end (+ (cadr ctx) 2) (+ (cadr ctx) 2 len))
+ ) ;t
+ ) ;cond
+ ))
+
+(defun web-mode-fontify-whitespaces (beg end)
+ (save-excursion
+ (goto-char beg)
+ (while (re-search-forward web-mode-whitespaces-regexp end t)
+ (add-text-properties (match-beginning 0) (match-end 0)
+ '(face web-mode-whitespace-face))
+ ) ;while
+ ))
+
+(defun web-mode-whitespaces-show ()
+ "Toggle whitespaces."
+ (interactive)
+ (if web-mode-enable-whitespace-fontification
+ (web-mode-whitespaces-off)
+ (web-mode-whitespaces-on)))
+
+(defun web-mode-whitespaces-on ()
+ "Show whitespaces."
+ (interactive)
+ (when web-mode-display-table
+ (setq buffer-display-table web-mode-display-table))
+ (setq web-mode-enable-whitespace-fontification t))
+
+(defun web-mode-whitespaces-off ()
+ (setq buffer-display-table nil)
+ (setq web-mode-enable-whitespace-fontification nil))
+
+(defun web-mode-use-tabs ()
+ "Tweaks vars to be compatible with TAB indentation."
+ (let (offset)
+ (setq web-mode-block-padding 0)
+ (setq web-mode-script-padding 0)
+ (setq web-mode-style-padding 0)
+ (setq offset
+ (cond
+ ((and (boundp 'tab-width) tab-width) tab-width)
+ ((and (boundp 'standard-indent) standard-indent) standard-indent)
+ (t 4)))
+ ;; (message "offset(%S)" offset)
+ (setq web-mode-attr-indent-offset offset)
+ (setq web-mode-code-indent-offset offset)
+ (setq web-mode-css-indent-offset offset)
+ (setq web-mode-markup-indent-offset offset)
+ (setq web-mode-sql-indent-offset offset)
+ (add-to-list 'web-mode-indentation-params '("lineup-args" . nil))
+ (add-to-list 'web-mode-indentation-params '("lineup-calls" . nil))
+ (add-to-list 'web-mode-indentation-params '("lineup-concats" . nil))
+ (add-to-list 'web-mode-indentation-params '("lineup-ternary" . nil))
+ ))
+
+(defun web-mode-element-children-fold-or-unfold (&optional pos)
+ "Fold/Unfold all the children of the current html element."
+ (interactive)
+ (unless pos (setq pos (point)))
+ (save-excursion
+ (dolist (child (reverse (web-mode-element-children pos)))
+ (goto-char child)
+ (web-mode-fold-or-unfold))
+ ))
+
+(defun web-mode-fold-or-unfold (&optional pos)
+ "Toggle folding on an html element or a control block."
+ (interactive)
+ (web-mode-scan)
+ (web-mode-with-silent-modifications
+ (save-excursion
+ (if pos (goto-char pos))
+ (let (beg-inside beg-outside end-inside end-outside overlay overlays regexp)
+ (when (looking-back "^[\t ]*" (point-min))
+ (back-to-indentation))
+ (setq overlays (overlays-at (point)))
+ (dolist (elt overlays)
+ (when (and (not overlay)
+ (eq (overlay-get elt 'font-lock-face) 'web-mode-folded-face))
+ (setq overlay elt)))
+ (cond
+ ;; *** unfolding
+ (overlay
+ (setq beg-inside (overlay-start overlay)
+ end-inside (overlay-end overlay))
+ (remove-overlays beg-inside end-inside)
+ (put-text-property beg-inside end-inside 'invisible nil)
+ )
+ ;; *** block folding
+ ((and (get-text-property (point) 'block-side)
+ (cdr (web-mode-block-is-control (point))))
+ (setq beg-outside (web-mode-block-beginning-position (point)))
+ (setq beg-inside (1+ (web-mode-block-end-position (point))))
+ (when (web-mode-block-match)
+ (setq end-inside (point))
+ (setq end-outside (1+ (web-mode-block-end-position (point)))))
+ )
+ ;; *** html comment folding
+ ((eq (get-text-property (point) 'tag-type) 'comment)
+ (setq beg-outside (web-mode-tag-beginning-position))
+ (setq beg-inside (+ beg-outside 4))
+ (setq end-outside (web-mode-tag-end-position))
+ (setq end-inside (- end-outside 3))
+ )
+ ;; *** tag folding
+ ((or (member (get-text-property (point) 'tag-type) '(start end))
+ (web-mode-element-parent))
+ (when (not (web-mode-element-is-collapsed (point)))
+ (web-mode-tag-beginning)
+ (when (eq (get-text-property (point) 'tag-type) 'end)
+ (web-mode-tag-match))
+ (setq beg-outside (point))
+ (web-mode-tag-end)
+ (setq beg-inside (point))
+ (goto-char beg-outside)
+ (when (web-mode-tag-match)
+ (setq end-inside (point))
+ (web-mode-tag-end)
+ (setq end-outside (point)))
+ )
+ )
+ ) ;cond
+ (when (and beg-inside beg-outside end-inside end-outside)
+ (setq overlay (make-overlay beg-outside end-outside))
+ (overlay-put overlay 'font-lock-face 'web-mode-folded-face)
+ (put-text-property beg-inside end-inside 'invisible t))
+ ))))
+
+;;---- TRANSFORMATION ----------------------------------------------------------
+
+(defun web-mode-buffer-change-tag-case (&optional type)
+ "Change html tag case."
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (let ((continue t) f)
+ (setq f (if (member type '("upper" "uppercase" "upper-case")) 'uppercase 'downcase))
+ (when (and (not (get-text-property (point) 'tag-beg))
+ (not (web-mode-tag-next)))
+ (setq continue nil))
+ (while continue
+ (skip-chars-forward "<!/")
+ (if (looking-at "\\([[:alnum:]:-]+\\)")
+ (replace-match (funcall f (match-string 0)) t))
+;; (message "tag: %S (%S)"
+;; (get-text-property (point) 'tag-name)
+;; (point))
+ (unless (web-mode-tag-next)
+ (setq continue nil))
+ ) ;while
+ )))
+
+(defun web-mode-buffer-change-attr-case (&optional type)
+ "Change case of html attribute names."
+ (interactive)
+ (unless type (setq type "downcase"))
+ (save-excursion
+ (goto-char (point-min))
+ (let ((continue t)
+ (fun (if (eq (aref (downcase type) 0) ?u) 'uppercase 'downcase)))
+ (while continue
+ (cond
+ ((not (web-mode-attribute-next))
+ (setq continue nil))
+ ((looking-at "\\([[:alnum:]-]+\\)")
+ (replace-match (funcall fun (match-string 0)) t)
+ )
+ ) ;cond
+ ) ;while
+ )))
+
+;; tag-case=lower|upper-case , attr-case=lower|upper-case
+;; special-chars=unicode|html-entities
+;; smart-apostrophes=bool , smart-quotes=bool , indentation=bool
+(defun web-mode-dom-normalize ()
+ "Normalize buffer"
+ (interactive)
+ (save-excursion
+ (let ((rules web-mode-normalization-rules) elt)
+ (when (setq elt (cdr (assoc "tag-case" rules)))
+ (web-mode-buffer-change-tag-case elt))
+ (when (setq elt (cdr (assoc "attr-case" rules)))
+ (web-mode-buffer-change-attr-case elt))
+ (when (setq elt (cdr (assoc "css-indentation" rules)))
+ (web-mode-css-indent))
+ (when (setq elt (cdr (assoc "smart-apostrophes" rules)))
+ (web-mode-dom-apostrophes-replace))
+ (when (setq elt (cdr (assoc "smart-quotes" rules)))
+ (web-mode-dom-quotes-replace))
+ (when (setq elt (cdr (assoc "special-chars" rules)))
+ (if (string= elt "entities")
+ (web-mode-dom-entities-encode)
+ (web-mode-dom-entities-replace)))
+ (when (setq elt (cdr (assoc "whitespaces" rules)))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (forward-line)
+ (delete-blank-lines))
+ (delete-trailing-whitespace)
+ (untabify (point-min) (point-max)))
+ (when (setq elt (cdr (assoc "indentation" rules)))
+ (web-mode-buffer-indent))
+ )))
+
+(defun web-mode-dom-apostrophes-replace ()
+ "Replace char(') with char(’) in the innerText of html elements."
+ (interactive)
+ (save-excursion
+ (let ((min (point-min)) (max (point-max)))
+ (when mark-active
+ (setq min (region-beginning)
+ max (region-end))
+ (deactivate-mark))
+ (goto-char min)
+ (while (web-mode-content-rsf "\\([[:alpha:]]\\)'\\([[:alpha:]]\\)" max)
+ (replace-match "\\1’\\2"))
+ )))
+
+(defun web-mode-dom-entities-encode ()
+ (save-excursion
+ (let (regexp ms elt (min (point-min)) (max (point-max)))
+ (when mark-active
+ (setq min (region-beginning)
+ max (region-end))
+ (deactivate-mark))
+ (goto-char min)
+ (setq regexp "[")
+ (dolist (pair web-mode-html-entities)
+ (setq regexp (concat regexp (char-to-string (cdr pair))))
+ )
+ (setq regexp (concat regexp "]"))
+ (while (web-mode-content-rsf regexp max)
+ (setq elt (match-string-no-properties 0))
+ (setq elt (aref elt 0))
+ (setq elt (car (rassoc elt web-mode-html-entities)))
+ (replace-match (concat "&" elt ";"))
+ (setq max (+ max (length elt) 1))
+ ) ;while
+ )))
+
+(defun web-mode-dom-entities-replace ()
+ "Replace html entities (e.g. &eacute; &#233; or &#x00E9; become é)"
+ (interactive)
+ (save-excursion
+ (let (ms pair elt (min (point-min)) (max (point-max)))
+ (when mark-active
+ (setq min (region-beginning)
+ max (region-end))
+ (deactivate-mark))
+ (goto-char min)
+ (while (web-mode-content-rsf "&\\([#]?[[:alnum:]]\\{2,8\\}\\);" max)
+ (setq elt nil)
+ (setq ms (match-string-no-properties 1))
+ (cond
+ ((not (eq (aref ms 0) ?\#))
+ (and (setq pair (assoc ms web-mode-html-entities))
+ (setq elt (cdr pair))
+ (setq elt (char-to-string elt))))
+ ((eq (aref ms 1) ?x)
+ (setq elt (substring ms 2))
+ (setq elt (downcase elt))
+ (setq elt (string-to-number elt 16))
+ (setq elt (char-to-string elt)))
+ (t
+ (setq elt (substring ms 1))
+ (setq elt (char-to-string (string-to-number elt))))
+ ) ;cond
+ (when elt (replace-match elt))
+ ) ;while
+ )))
+
+(defun web-mode-dom-xml-replace ()
+ "Replace &, > and < in html content."
+ (interactive)
+ (save-excursion
+ (let (expr (min (point-min)) (max (point-max)))
+ (when mark-active
+ (setq min (region-beginning)
+ max (region-end))
+ (deactivate-mark))
+ (goto-char min)
+ (while (web-mode-content-rsf "[&<>]" max)
+ (replace-match (cdr (assq (char-before) web-mode-xml-chars)) t t))
+ )))
+
+(defun web-mode-dom-quotes-replace ()
+ "Replace dumb quotes."
+ (interactive)
+ (save-excursion
+ (let (expr (min (point-min)) (max (point-max)))
+ (when mark-active
+ (setq min (region-beginning)
+ max (region-end))
+ (deactivate-mark))
+ (goto-char min)
+ (setq expr (concat (car web-mode-smart-quotes) "\\2" (cdr web-mode-smart-quotes)))
+ (while (web-mode-content-rsf "\\(\"\\)\\(.\\{1,200\\}\\)\\(\"\\)" max)
+ (replace-match expr)
+ ) ;while
+ )))
+
+;;---- INDENTATION -------------------------------------------------------------
+
+;; todo : passer de règle en règle et mettre un \n à la fin
+(defun web-mode-css-indent ()
+ (save-excursion
+ (goto-char (point-min))
+ (let ((continue t) rule part-end)
+ (while continue
+ (cond
+ ((not (web-mode-part-next))
+ (setq continue nil))
+ ((eq (get-text-property (point) 'part-side) 'css)
+ (setq part-end (web-mode-part-end-position))
+ (while (setq rule (web-mode-css-rule-next part-end))
+ (when (not (looking-at-p "[[:space:]]*\\($\\|<\\)"))
+ (newline)
+ (indent-according-to-mode)
+ (setq part-end (web-mode-part-end-position)))
+ )
+ )
+ ) ;cond
+ )
+ )))
+
+(defun web-mode-buffer-indent ()
+ "Indent all buffer."
+ (interactive)
+ (let ((debug t) (ts (current-time)) (sub nil))
+ (indent-region (point-min) (point-max))
+ (when debug
+ (setq sub (time-subtract (current-time) ts))
+ (message "buffer-indent: time elapsed = %Ss %9Sµs" (nth 1 sub) (nth 2 sub)))
+ (delete-trailing-whitespace)))
+
+(defun web-mode-point-context (pos)
+ "POS should be at the beginning of the indentation."
+ (save-excursion
+ (let (curr-char curr-indentation curr-line
+ language
+ options
+ reg-beg reg-col
+ prev-char prev-indentation prev-line prev-pos
+ token
+ part-language
+ depth)
+
+ (setq reg-beg (point-min)
+ reg-col 0
+ token "live"
+ options ""
+ language ""
+ prev-line ""
+ prev-char 0
+ prev-pos nil)
+
+ (when (get-text-property pos 'part-side)
+ (setq part-language (symbol-name (get-text-property pos 'part-side))))
+
+ ;;(message "part-language=%S" part-language)
+
+ (cond
+
+ ((and (bobp) (member web-mode-content-type '("html" "xml")))
+ (setq language web-mode-content-type)
+ )
+
+ ((string= web-mode-content-type "css")
+ (setq language "css"
+ curr-indentation web-mode-css-indent-offset))
+
+ ((member web-mode-content-type '("javascript" "json" "typescript"))
+ (setq language web-mode-content-type
+ curr-indentation web-mode-code-indent-offset))
+
+ ((or (string= web-mode-content-type "jsx")
+ (and part-language (string= part-language "jsx")))
+ (setq language "jsx"
+ curr-indentation web-mode-code-indent-offset)
+ (cond
+ ((web-mode-jsx-is-html pos)
+ (setq curr-indentation web-mode-markup-indent-offset
+ options "is-html"))
+ ((and (setq depth (get-text-property pos 'jsx-depth)) (> depth 1))
+ (when (get-text-property pos 'jsx-beg)
+ (setq depth (1- depth)))
+ (setq reg-beg (web-mode-jsx-depth-beginning-position pos depth))
+ (setq reg-beg (1+ reg-beg))
+ ;;(message "%S" (point))
+ (save-excursion
+ (goto-char reg-beg)
+ ;;(message "pt=%S" reg-beg)
+ (cond
+ ((and (not (looking-at-p "[ ]*$"))
+ (looking-back "^[[:space:]]*{" (point-min)))
+ (setq reg-col (+ (current-indentation) ;; #1027
+ (cond
+ ((looking-at "[ ]+") (1+ (length (match-string-no-properties 0))))
+ (t 0))
+ ))
+ )
+ ((looking-at-p "[ ]*\\[[ ]*$") ;; #0659
+ (setq reg-col (current-indentation))
+ )
+ ((and (looking-back "=[ ]*{" (point-min)) ;; #0739 #1022
+ (not (looking-at-p "[[:space:]]*<")))
+ (setq reg-col (current-indentation))
+ )
+ ;;((and (looking-back "=[ ]*{" (point-min)) ;; #0739
+ ;; (looking-at-p "{[ ]*"))
+ ;; (setq reg-col (current-indentation))
+ ;; )
+ ((get-text-property (1- (point)) 'tag-beg)
+ ;;(message "point=%S" (point))
+ (setq reg-col (current-indentation))
+ )
+ (t
+ (message "%S : %S %S" (point) (current-indentation) web-mode-code-indent-offset)
+ ;;(setq reg-col (+ (current-indentation) web-mode-code-indent-offset web-mode-jsx-expression-padding)))
+ (setq reg-col (+ (current-indentation) web-mode-code-indent-offset)))
+ )
+
+ ;;(message "%S %S %S" (point) (current-indentation) reg-col)
+ ) ;save-excursion
+ )
+ ((string= web-mode-content-type "jsx")
+ (setq reg-beg (point-min)))
+ (t
+ (setq reg-beg (or (web-mode-part-beginning-position pos) (point-min)))
+ (save-excursion
+ (goto-char reg-beg)
+ (search-backward "<" nil t)
+ (setq reg-col (current-column))
+ ) ;save-excursion
+ )
+ ) ;cond
+ ;;(message "jsx reg-beg=%S" reg-beg)
+ ) ;jsx
+
+ ((string= web-mode-content-type "php")
+ (setq language "php"
+ curr-indentation web-mode-code-indent-offset))
+
+ ((or (string= web-mode-content-type "xml"))
+ (setq language "xml"
+ curr-indentation web-mode-markup-indent-offset))
+
+ ;; TODO: est ce util ?
+ ((and (get-text-property pos 'tag-beg)
+ (get-text-property pos 'tag-name)
+ ;;(not (get-text-property pos 'part-side))
+ )
+ (setq language "html"
+ curr-indentation web-mode-markup-indent-offset))
+
+ ((and (get-text-property pos 'block-side)
+ (not (get-text-property pos 'block-beg)))
+
+ (setq reg-beg (or (web-mode-block-beginning-position pos) (point-min)))
+ (goto-char reg-beg)
+ (setq reg-col (current-column))
+ ;;(message "%S %S" reg-beg reg-col)
+ (setq language web-mode-engine)
+ (setq curr-indentation web-mode-code-indent-offset)
+
+ (cond
+ ((string= web-mode-engine "blade")
+ (save-excursion
+ (when (web-mode-rsf "{[{!]+[ ]*")
+ (setq reg-col (current-column))))
+ (setq reg-beg (+ reg-beg 2))
+ )
+ ((string= web-mode-engine "razor")
+ ;;(setq reg-beg (+ reg-beg 2))
+ ;;(setq reg-col (current-column))
+ )
+ ;; tests/demo.chtml
+ ((string= web-mode-engine "ctemplate")
+ (save-excursion
+ (when (web-mode-rsf "{{#?")
+ (setq reg-col (current-column))))
+ )
+ ((string= web-mode-engine "dust")
+ (save-excursion
+ (when (web-mode-rsf "{@")
+ (setq reg-col (current-column))))
+ )
+ ((string= web-mode-engine "svelte")
+ (save-excursion
+ (when (web-mode-rsf "{@")
+ (setq reg-col (current-column))))
+ )
+ ((string= web-mode-engine "template-toolkit")
+ (setq reg-beg (+ reg-beg 3)
+ reg-col (+ reg-col 3))
+ )
+ ((and (string= web-mode-engine "jsp")
+ (web-mode-looking-at "<%@" reg-beg))
+ (save-excursion
+ (goto-char reg-beg)
+ (looking-at "<%@[ ]*[[:alpha:]]+[ ]+\\|</?[[:alpha:]]+[:.][[:alpha:]]+[ ]+")
+ (goto-char (match-end 0))
+ (setq reg-col (current-column))
+ )
+ )
+ ((and (string= web-mode-engine "freemarker")
+ (web-mode-looking-at "<@\\|<%@\\|<[[:alpha:]]" reg-beg))
+ (save-excursion
+ (goto-char reg-beg)
+ (looking-at "<@[[:alpha:].]+[ ]+\\|<%@[ ]*[[:alpha:]]+[ ]+\\|<[[:alpha:]]+:[[:alpha:]]+[ ]+")
+ (goto-char (match-end 0))
+ (setq reg-col (current-column))
+ )
+ )
+ ) ;cond
+ ) ;block-side
+
+ ((and part-language (member part-language
+ '("css" "javascript" "json" "sql" "markdown"
+ "pug" "ruby" "sass" "stylus" "typescript")))
+ (setq reg-beg (or (web-mode-part-beginning-position pos) (point-min)))
+ (goto-char reg-beg)
+ (if (and (string= web-mode-engine "mojolicious")
+ (looking-back "javascript begin" (point-min)))
+ (search-backward "%" nil t)
+ (search-backward "<" nil t))
+ (setq reg-col (current-column))
+ (setq language part-language)
+ (cond
+ ((string= language "css")
+ (setq curr-indentation web-mode-css-indent-offset))
+ ((string= language "sql")
+ (setq curr-indentation web-mode-sql-indent-offset))
+ ((string= language "markdown")
+ (setq curr-indentation web-mode-code-indent-offset))
+ ((string= language "pug")
+ (setq curr-indentation web-mode-code-indent-offset))
+ ((string= language "sass")
+ (setq curr-indentation web-mode-code-indent-offset))
+ ((string= language "stylus")
+ (setq curr-indentation web-mode-code-indent-offset))
+ ((string= language "ruby")
+ (setq curr-indentation web-mode-code-indent-offset))
+ ((string= language "typescript")
+ (setq curr-indentation web-mode-code-indent-offset))
+ (t
+ (setq language "javascript"
+ curr-indentation web-mode-code-indent-offset))
+ )
+ ) ;part-side
+
+ (t
+ (setq language "html"
+ curr-indentation web-mode-markup-indent-offset)
+ )
+
+ ) ;cond
+
+ (cond
+ ((or (and (> pos (point-min))
+ (eq (get-text-property pos 'part-token) 'comment)
+ (eq (get-text-property (1- pos) 'part-token) 'comment)
+ (progn
+ (setq reg-beg (previous-single-property-change pos 'part-token))
+ t))
+ (and (> pos (point-min))
+ (eq (get-text-property pos 'block-token) 'comment)
+ (eq (get-text-property (1- pos) 'block-token) 'comment)
+ (progn
+ (setq reg-beg (previous-single-property-change pos 'block-token))
+ t))
+ (and (> pos (point-min))
+ (eq (get-text-property pos 'tag-type) 'comment)
+ (not (get-text-property pos 'tag-beg))
+ (progn
+ (setq reg-beg (web-mode-tag-beginning-position pos))
+ t))
+ )
+ (setq token "comment"))
+ ((or (and (> pos (point-min))
+ (member (get-text-property pos 'part-token)
+ '(string context key))
+ (member (get-text-property (1- pos) 'part-token)
+ '(string context key)))
+ (and (eq (get-text-property pos 'block-token) 'string)
+ (eq (get-text-property (1- pos) 'block-token) 'string)))
+ (setq token "string"))
+ )
+
+ (goto-char pos)
+ (setq curr-line (web-mode-trim
+ (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position))))
+ (setq curr-char (if (string= curr-line "") 0 (aref curr-line 0)))
+
+ (when (or (member language '("php" "blade" "javascript" "typescript" "jsx" "razor" "css"))
+ (and (member language '("html" "xml"))
+ (not (eq ?\< curr-char))))
+ (let (prev)
+ (cond
+ ((member language '("html" "xml" "javascript" "jsx" "css"))
+ (when (setq prev (web-mode-part-previous-live-line reg-beg))
+ (setq prev-line (nth 0 prev)
+ prev-indentation (nth 1 prev)
+ prev-pos (nth 2 prev))
+ )
+ )
+ ((setq prev (web-mode-block-previous-live-line))
+ (setq prev-line (car prev)
+ prev-indentation (cdr prev))
+ (setq prev-line (web-mode-clean-block-line prev-line)))
+ ) ;cond
+ ) ;let
+ (when (>= (length prev-line) 1)
+ (setq prev-char (aref prev-line (1- (length prev-line))))
+ (setq prev-line (substring-no-properties prev-line))
+ )
+ )
+
+ (cond
+ ((not (member web-mode-content-type '("html" "xml")))
+ )
+ ((member language '("javascript" "typescript" "jsx" "ruby"))
+ (setq reg-col (if web-mode-script-padding (+ reg-col web-mode-script-padding) 0)))
+ ((member language '("css" "sql" "markdown" "pug" "sass" "stylus"))
+ (setq reg-col (if web-mode-style-padding (+ reg-col web-mode-style-padding) 0)))
+ ((not (member language '("html" "xml")))
+ (setq reg-col
+ (cond
+ ((not web-mode-block-padding) reg-col)
+ ((eq web-mode-block-padding -1) 0)
+ (t (+ reg-col web-mode-block-padding))
+ ) ;cond
+ ) ;setq
+ )
+ )
+
+ (list :curr-char curr-char
+ :curr-indentation curr-indentation
+ :curr-line curr-line
+ :language language
+ :options options
+ :prev-char prev-char
+ :prev-indentation prev-indentation
+ :prev-line prev-line
+ :prev-pos prev-pos
+ :reg-beg reg-beg
+ :reg-col reg-col
+ :token token)
+ )))
+
+(defun web-mode-indent-line ()
+
+ (web-mode-scan)
+
+ (let ((offset nil)
+ (char nil)
+ (debug nil)
+ (inhibit-modification-hooks nil)
+ (adjust t))
+
+ (save-excursion
+ (back-to-indentation)
+ (setq char (char-after))
+ (let* ((pos (point))
+ (ctx (web-mode-point-context pos))
+ (curr-char (plist-get ctx :curr-char))
+ (curr-indentation (plist-get ctx :curr-indentation))
+ (curr-line (plist-get ctx :curr-line))
+ (language (plist-get ctx :language))
+ (prev-char (plist-get ctx :prev-char))
+ (prev-indentation (plist-get ctx :prev-indentation))
+ (prev-line (plist-get ctx :prev-line))
+ (prev-pos (plist-get ctx :prev-pos))
+ (reg-beg (plist-get ctx :reg-beg))
+ (reg-col (plist-get ctx :reg-col))
+ (token (plist-get ctx :token))
+ (options (plist-get ctx :options))
+ (chars (list curr-char prev-char))
+ (tmp nil)
+ (is-js (member language '("javascript" "jsx" "ejs" "typescript"))))
+
+ (when (member language '("json" "typescript"))
+ (setq language "javascript"))
+
+ ;;(message "%S %S" (plist-get ctx :language) language)
+ ;;(message "curr-char=[%c] prev-char=[%c]\n%S" curr-char prev-char ctx)
+ ;;(message "options=%S" ctx)
+
+ (cond
+
+ ((or (bobp) (= (line-number-at-pos pos) 1))
+ (when debug (message "I100(%S) first line" pos))
+ (setq offset 0))
+
+ ;; #123 #1145
+ ((and web-mode-enable-front-matter-block
+ (eq (char-after (point-min)) ?\-)
+ (or (looking-at-p "---")
+ (search-forward "---" (point-max) t)))
+ (when debug (message "I108(%S) front-matter-block" pos))
+ (setq offset nil))
+
+ ;; #1073
+ ((get-text-property pos 'invisible)
+ (when debug (message "I110(%S) invible" pos))
+ (setq offset nil))
+
+ ((string= token "string")
+ (when debug (message "I120(%S) string" pos))
+ (cond
+ ((web-mode-is-token-end pos)
+ (if (get-text-property pos 'block-side)
+ (web-mode-block-token-beginning)
+ (web-mode-part-token-beginning))
+ (setq offset (current-indentation))
+ )
+ ((and web-mode-enable-sql-detection
+ (web-mode-block-token-starts-with (concat "[ \n]*" web-mode-sql-queries)))
+ (save-excursion
+ (let (col)
+ (web-mode-block-string-beginning)
+ (skip-chars-forward "[ \"'\n]")
+ (setq col (current-column))
+ (goto-char pos)
+ (if (looking-at-p "\\(SELECT\\|INSERT\\|DELETE\\|UPDATE\\|FROM\\|LEFT\\|JOIN\\|WHERE\\|GROUP BY\\|LIMIT\\|HAVING\\|\)\\)")
+ (setq offset col)
+ (setq offset (+ col web-mode-sql-indent-offset)))
+ )
+ ) ;save-excursion
+ )
+ ((and is-js
+ (web-mode-is-ql-string pos "Relay\.QL"))
+ (setq offset (web-mode-relayql-indentation pos))
+ )
+ ((and is-js
+ (web-mode-is-ql-string pos "gql"))
+ (setq offset (web-mode-relayql-indentation pos "gql"))
+ )
+ ((and is-js
+ (web-mode-is-ql-string pos "graphql"))
+ (setq offset (web-mode-relayql-indentation pos "graphql"))
+ )
+ ((and is-js
+ (web-mode-is-css-string pos))
+ (when debug (message "I127(%S) css string" pos))
+ (setq offset (web-mode-token-css-indentation pos))
+ )
+ ((and is-js
+ (web-mode-is-html-string pos))
+ (when debug (message "I128(%S) html string" pos))
+ (setq offset (web-mode-token-html-indentation pos))
+ )
+ (t
+ (setq offset nil))
+ ) ;cond
+ ) ;case string
+
+ ((string= token "comment")
+ (when debug (message "I130(%S) comment" pos))
+ (if (eq (get-text-property pos 'tag-type) 'comment)
+ (web-mode-tag-beginning)
+ (goto-char (car
+ (web-mode-property-boundaries
+ (if (eq (get-text-property pos 'part-token) 'comment)
+ 'part-token
+ 'block-token)
+ pos))))
+ (setq offset (current-column))
+ (cond
+ ((string= web-mode-engine "freemarker")
+ (setq offset (+ (current-indentation) 2)))
+ ((member (buffer-substring-no-properties (point) (+ (point) 2)) '("/*" "{*" "@*"))
+ (cond
+ ((eq ?\* curr-char)
+ (setq offset (+ offset 1)))
+ (t
+ (setq offset (+ offset 3)))
+ ) ;cond
+ )
+ ((string= (buffer-substring-no-properties (point) (+ (point) 4)) "<!--")
+ (cond
+ ((string-match-p "^<!\\[endif" curr-line)
+ )
+ ((looking-at-p "<!--\\[if")
+ (setq offset (+ offset web-mode-markup-indent-offset)))
+ ((string-match-p "^-->" curr-line)
+ (setq offset offset))
+ ((string-match-p "^-" curr-line)
+ (setq offset (+ offset 3)))
+ (t
+ (setq offset (+ offset 5)))
+ ) ;cond
+ )
+ ((and (string= web-mode-engine "django") (looking-back "{% comment %}" (point-min)))
+ (setq offset (- offset 12)))
+ ((and (string= web-mode-engine "mako") (looking-back "<%doc%>" (point-min)))
+ (setq offset (- offset 6)))
+ ((and (string= web-mode-engine "mason") (looking-back "<%doc%>" (point-min)))
+ (setq offset (- offset 6)))
+ ) ;cond
+ ) ;case comment
+
+ ((and (string= web-mode-engine "mason")
+ (string-match-p "^%" curr-line))
+ (when debug (message "I140(%S) mason" pos))
+ (setq offset 0))
+
+ ((and (string= web-mode-engine "django")
+ (string-match-p "^#" curr-line))
+ (when debug (message "I144(%S) django line statements" pos))
+ (setq offset 0))
+
+ ((and (get-text-property pos 'block-beg)
+ (or (web-mode-block-is-close pos)
+ (web-mode-block-is-inside pos)))
+ (when debug (message "I150(%S) block-match" pos))
+ (cond
+ ((not (web-mode-block-match))
+ )
+ ((and (string= web-mode-engine "closure")
+ (string-match-p "{\\(case\\|default\\)" curr-line))
+ (setq offset (+ (current-indentation) web-mode-markup-indent-offset)))
+ (t
+ (setq offset (current-indentation))
+ (if (and (string= web-mode-engine "blade")
+ (string-match-p "@break" curr-line))
+ (setq offset (+ (current-indentation) offset)))
+ )
+ ) ;cond
+ )
+
+ ((eq (get-text-property pos 'block-token) 'delimiter-end)
+ (when debug (message "I160(%S) block-beginning" pos))
+ (when (web-mode-block-beginning)
+ (setq reg-col (current-indentation))
+ (setq offset (current-column))))
+
+ ((or (and (get-text-property pos 'tag-beg)
+ (eq (get-text-property pos 'tag-type) 'end))
+ (and (eq (get-text-property pos 'tag-type) 'comment)
+ (string-match-p "<!--#\\(else\\|elif\\|endif\\)" curr-line)))
+ (when debug (message "I170(%S) tag-match" pos))
+ (when (web-mode-tag-match)
+ (setq offset (current-indentation))))
+
+ ((and (member language '("jsx"))
+ (eq curr-char ?\})
+ (get-text-property pos 'jsx-end))
+ (when debug (message "I180(%S) jsx-expr-end" pos))
+ (web-mode-go (1- reg-beg))
+ (setq reg-col nil)
+ ;;(setq offset (current-column)))
+ (setq offset (current-indentation)))
+
+ ((and (member language '("html" "xml" "javascript" "jsx"))
+ (get-text-property pos 'tag-type)
+ (not (get-text-property pos 'tag-beg))
+ ;;(or (not (string= language "jsx"))
+ ;; (string= options "is-html"))
+ (not (and (string= language "jsx")
+ (or (string= options "is-html")
+ (web-mode-jsx-is-expr pos))))
+ )
+ (when debug (message "I190(%S) attr-indent" pos))
+ (cond
+ ((and (not (get-text-property pos 'tag-attr-beg))
+ (get-text-property pos 'tag-attr)
+ (get-text-property (1- pos) 'tag-attr)
+ (web-mode-attribute-beginning)
+ (not (string-match-p "^/?>" curr-line))
+ ;;(progn (message "pos=%S point=%S" pos (point)) t)
+ )
+
+ (cond
+ ((eq (logand (get-text-property (point) 'tag-attr-beg) 8) 8)
+ (setq offset nil))
+ ((not (web-mode-tag-beginning))
+ (message "** tag-beginning ** failure")
+ (setq offset nil))
+ (web-mode-attr-value-indent-offset
+ (setq offset (+ (current-column) web-mode-attr-value-indent-offset)))
+ ((web-mode-dom-rsf "=[ ]*[\"']?" pos)
+ ;;(message "%S" (point))
+ (setq offset (current-column)))
+ (t
+ (setq offset (+ (current-column) web-mode-markup-indent-offset)))
+ ) ;cond
+ ) ;and
+ ((not (web-mode-tag-beginning))
+ (message "** error ** unable to jump to tag beg"))
+ ((string-match-p "^/?>" curr-line)
+ (setq offset (web-mode-column-at-pos (web-mode-tag-beginning-position pos)))
+ )
+ (web-mode-attr-indent-offset
+ (setq offset (+ (current-column) web-mode-attr-indent-offset)))
+ ((looking-at-p (concat web-mode-start-tag-regexp "[ ]*\n"))
+ ;;(message "%S: %S" (point) (web-mode-inside-block-control pos))
+ (setq offset (+ (current-column) (or web-mode-attr-indent-offset web-mode-code-indent-offset)))
+ ;; #1109
+ (setq tmp (web-mode-inside-block-control pos))
+ (when (and tmp (> tmp (point)))
+ (setq offset (+ offset (or web-mode-attr-indent-offset web-mode-code-indent-offset))))
+ )
+ ((web-mode-attribute-next)
+ (setq offset (current-column)))
+ ) ;cond
+ ) ;attr-indent
+
+ ((or (member language '("html" "xml"))
+ (and (member language '("jsx"))
+ (string= options "is-html")))
+ (when debug (message "I200(%S) web-mode-markup-indentation" pos))
+ ;; https://www.w3.org/TR/html5/syntax.html#optional-tags
+ (when web-mode-enable-optional-tags
+ (save-excursion
+ (let (tag-name parent-tag-name parent-tag-pos)
+ (when (and (setq tag-name (get-text-property pos 'tag-name))
+ (setq parent-tag-pos (web-mode-element-parent-position pos))
+ (setq parent-tag-name (get-text-property parent-tag-pos 'tag-name))
+ (or (and (string= parent-tag-name "p") (member tag-name '("p" "address", "article", "aside", "blockquote", "div", "dl", "fieldset", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "header", "hgroup", "hr", "main", "nav", "ol", "pre", "section", "table", "ul")))
+ (and (string= parent-tag-name "li") (member tag-name '("li")))
+ (and (string= parent-tag-name "dt") (member tag-name '("dt" "dd")))
+ (and (string= parent-tag-name "td") (member tag-name '("td" "th")))
+ (and (string= parent-tag-name "th") (member tag-name '("td" "th")))
+ ))
+ (when debug (message "I205(%S) %S(%S) auto-closing" pos parent-tag-name parent-tag-pos))
+ (setq offset (web-mode-indentation-at-pos parent-tag-pos))
+ )))) ; when let save-excursion when
+
+ (when (string= web-mode-engine "closure")
+ (save-excursion
+ (when (and (re-search-backward "{/?switch" nil t)
+ (string= (match-string-no-properties 0) "{switch"))
+ (setq offset (+ (current-indentation) (* 2 web-mode-markup-indent-offset)))
+ )
+ ))
+ (cond
+ ((not (null offset))
+ )
+ ((get-text-property pos 'tag-beg)
+ (setq offset (web-mode-markup-indentation pos))
+ )
+ ((and web-mode-indentless-elements
+ (not (string= language "jsx"))
+ (null (get-text-property pos 'block-side))
+ (null (get-text-property pos 'part-side))
+ (and (null (get-text-property pos 'tag-beg))
+ (save-excursion
+ (and (web-mode-element-parent)
+ (member (get-text-property (point) 'tag-name) web-mode-indentless-elements))))
+ )
+ (setq offset nil))
+ ((or (eq (length curr-line) 0)
+ (= web-mode-indent-style 2)
+ (get-text-property pos 'tag-beg)
+ (get-text-property pos 'reg-beg))
+ (setq offset (web-mode-markup-indentation pos))
+ )
+ )
+ )
+
+ ((string= language "ctemplate")
+ (when debug (message "I210(%S) ctemplate" pos))
+ (setq offset reg-col))
+
+ ((string= language "expressionengine")
+ (when debug (message "I212(%S) expressionengine" pos))
+ (setq offset (+ reg-col (or web-mode-attr-indent-offset web-mode-code-indent-offset))))
+
+ ((string= language "asp")
+ (when debug (message "I230(%S) asp" pos))
+ (setq offset (web-mode-asp-indentation pos
+ curr-line
+ reg-col
+ curr-indentation
+ reg-beg)))
+
+ ((member language '("lsp" "cl-emb" "artanis"))
+ (when debug (message "I240(%S) lsp" pos))
+ (setq offset (web-mode-lisp-indentation pos ctx)))
+
+ ((and (member curr-char '(?\}))
+ (string= language "razor")
+ (get-text-property pos 'block-end))
+ (when debug (message "I245(%S) razor closing" pos))
+ (goto-char reg-beg)
+ ;;(message "%S %S" (point) (current-column))
+ (setq offset (current-column)
+ reg-col nil)
+ )
+
+ ((member curr-char '(?\} ?\) ?\]))
+ (when debug (message "I250(%S) closing-paren" pos))
+ (let (ori pos2)
+ (setq pos2 pos)
+ ;; #1096
+ (when (looking-at-p ".[\]})]+")
+ (skip-chars-forward "[\]})]")
+ (backward-char)
+ (setq pos2 (point))
+ ) ;when
+ (if (get-text-property pos 'block-side)
+ (setq ori (web-mode-block-opening-paren-position pos2 reg-beg))
+ (setq ori (web-mode-part-opening-paren-position pos2 reg-beg)))
+ ;;(message "ori=%S" ori)
+ (cond
+ ((null ori)
+ (setq offset reg-col))
+ ((and (goto-char ori)
+ (looking-back ")[ ]*" (point-min)) ;; peut-on se passer du looking-back ?
+ (re-search-backward ")[ ]*" nil t)
+ (web-mode-block-opening-paren reg-beg))
+ (back-to-indentation)
+ (setq offset (current-indentation))
+ )
+ (t
+ (goto-char ori)
+ (back-to-indentation)
+ (setq offset (current-indentation))
+ ;;(message "ori=%S offset=%S" ori offset)
+ (when (get-text-property pos 'jsx-depth)
+ ;;(when (get-text-property pos 'jsx-end)
+ (setq adjust nil))
+ ) ;t
+ ) ;cond
+ ) ;let
+ )
+
+ ((member language '("mako" "web2py"))
+ (when debug (message "I254(%S) python (mako/web2py)" pos))
+ (setq offset (web-mode-python-indentation pos
+ curr-line
+ reg-col
+ curr-indentation
+ reg-beg)))
+
+ ((member language '("erb" "ruby"))
+ (when debug (message "I260(%S) erb" pos))
+ (setq offset (web-mode-ruby-indentation pos
+ curr-line
+ reg-col
+ curr-indentation
+ reg-beg)))
+
+ ((string= language "css")
+ (when debug (message "I270(%S) css-indentation" pos))
+ ;;(message "prev=%c" prev-char)
+ (cond
+ ((eq prev-char ?:)
+ (setq offset (+ prev-indentation web-mode-css-indent-offset)))
+ ((eq prev-char ?,)
+ (setq offset prev-indentation))
+ (t
+ (setq offset (car (web-mode-css-indentation pos
+ reg-col
+ curr-indentation
+ language
+ reg-beg))))))
+
+ ((string= language "sql")
+ (when debug (message "I280(%S) sql" pos))
+ (setq offset (car (web-mode-sql-indentation pos
+ reg-col
+ curr-indentation
+ language
+ reg-beg))))
+
+ ((string= language "markdown")
+ (when debug (message "I290(%S) markdown" pos))
+ (setq offset (car (web-mode-markdown-indentation pos
+ reg-col
+ curr-indentation
+ language
+ reg-beg))))
+
+ ((string= language "stylus")
+ (when debug (message "I294(%S) stylus" pos))
+ (setq offset (car (web-mode-stylus-indentation pos
+ reg-col
+ curr-indentation
+ language
+ reg-beg))))
+ ((string= language "sass")
+ (when debug (message "I296(%S) sass" pos))
+ (setq offset (car (web-mode-stylus-indentation pos
+ reg-col
+ curr-indentation
+ language
+ reg-beg))))
+
+ ((string= language "pug")
+ (when debug (message "I298(%S) pug" pos))
+ (setq offset (car (web-mode-pug-indentation pos
+ reg-col
+ curr-indentation
+ language
+ reg-beg))))
+
+ ((and (string= language "razor")
+ (string-match-p "^\\." curr-line)
+ (string-match-p "^\\." prev-line))
+ (when debug (message "I300(%S) razor" pos))
+ (setq offset prev-indentation))
+
+ ((and (string= language "razor")
+ (string-match-p "^case " curr-line)
+ (string-match-p "^case " prev-line))
+ (when debug (message "I310(%S) razor case" pos))
+ (search-backward "case ")
+ (setq offset (current-column)))
+
+ ((and is-js
+ (member ?\. chars)
+ (not (string-match-p "^\\.\\.\\." curr-line)))
+ (when debug (message "I320(%S) javascript-calls" pos))
+ (let (pair)
+ (setq pair (web-mode-javascript-calls-beginning-position pos reg-beg))
+ ;;(message "%S" pair)
+ (when pair
+ (goto-char (car pair))
+ ;;(message "%S %S" (point) pair)
+ (cond
+ ((cdr (assoc "lineup-calls" web-mode-indentation-params))
+ ;;(message "ici")
+ ;;(search-forward ".")
+ (if (cdr pair)
+ (progn
+ (goto-char (cdr pair))
+ (setq offset (current-column))
+ (looking-at "\\.\\([ \t\n]*\\)")
+ (setq offset (- offset (length (match-string-no-properties 1))))
+ (unless (eq curr-char ?\.) (setq offset (1+ offset)))
+ ) ;progn
+ ;; TODO: cela devrait etre fait dans web-mode-javascript-calls-beginning-position
+ (skip-chars-forward " \t\n")
+ (setq offset (+ (current-indentation) web-mode-code-indent-offset))
+ ) ;if
+ )
+ (t
+ (setq offset (+ (current-indentation) web-mode-code-indent-offset))
+ ) ;t
+ ) ;cond
+ ) ;when
+ ) ;let
+ )
+
+ ((and is-js
+ (member ?\+ chars))
+ (when debug (message "I330(%S) javascript-string" pos))
+ ;;(message "js-concat")
+ (cond
+ ((not (web-mode-javascript-string-beginning pos reg-beg))
+ )
+ ((null (cdr (assoc "lineup-concats" web-mode-indentation-params)))
+ (setq offset (+ (current-indentation) web-mode-code-indent-offset)))
+ ((not (eq curr-char ?\+))
+ (setq offset (current-column)))
+ (t
+ (setq offset (current-column))
+ (when (not (looking-back "\\(^[ \t]+\\|if[ ]*[(]?\\)" (point-min)))
+ (goto-char pos)
+ (looking-at "\\+[ \t\n]*")
+ (setq offset (- offset (length (match-string-no-properties 0)))))
+ )
+ )
+ )
+
+ ;; #579 , #742
+ ((and (member language '("javascript" "jsx" "ejs" "php"))
+ (string-match-p "=[>]?$" prev-line))
+ (when debug (message "I340(%S)" pos))
+ (setq offset (+ prev-indentation web-mode-code-indent-offset))
+ ;;(message "ici%S" offset)
+ )
+
+ ;; #1016
+ ((and (member language '("javascript" "jsx" "ejs"))
+ (string-match-p "^[ \t]*|}" curr-line))
+ (when debug (message "I346(%S) flow-exact-object-type-end" pos))
+ (when (re-search-backward "{|" reg-beg t)
+ (setq offset (current-indentation))
+ )
+ )
+
+ ;; #446, #638, #800, #978, #998
+ ((and (member language '("javascript" "jsx" "ejs" "php"))
+ (or (string-match-p "[&|?:+-]$" prev-line)
+ (string-match-p "^[&|?:+-]" curr-line))
+ (not (and (string= language "php")
+ (string-match-p "^->" curr-line)))
+ (not (and (string= language "php")
+ (string-match-p "^?[a-zA-z]*" curr-line)))
+ (not (and (string= language "php")
+ (string-match-p "\\(else[ ]?:\\|if[ ]?([^)]*)[ ]?:\\)" prev-line)))
+ (not (string-match-p "^\\(++\\|--\\)" curr-line))
+ (not (and is-js
+ (string-match-p "]:\\|{|$" prev-line)))
+ (not (and (eq prev-char ?\:)
+ (string-match-p "^\\(case\\|default\\)" prev-line)))
+ )
+ ;;(message "prev=%S" prev-line)
+ (when debug (message "I350(%S) multiline statement" pos))
+ (let (is-ternary)
+ (setq is-ternary (or (string-match-p "[?:]$" prev-line)
+ (string-match-p "^[?:]" curr-line)))
+ (cond
+ ((not (funcall (if is-js
+ 'web-mode-javascript-statement-beginning
+ 'web-mode-block-statement-beginning)
+ pos reg-beg is-ternary))
+ )
+ ((null (cdr (assoc "lineup-ternary" web-mode-indentation-params)))
+ (setq offset (+ (current-indentation) web-mode-code-indent-offset)))
+ (t
+ (setq offset (current-column))
+ (when (and (member curr-char '(?\+ ?\- ?\& ?\| ?\? ?\:))
+ (not (looking-back "\\(^[ \t]+\\|if[ ]*[(]?\\)" (point-min)))) ; #743
+ (goto-char pos)
+ (looking-at "\\(||\\|&&\\|[&|?:+-]\\)[ \t\n]*")
+ (setq offset (- offset (length (match-string-no-properties 0)))))
+ )
+ ) ;cond
+ ) ;let
+ )
+
+ ((and is-js
+ (eq prev-char ?\()
+ (string-match-p "=>[ ]*([ ]*$" prev-line))
+ (when debug (message "I355(%S) => (" pos))
+ (setq offset (+ prev-indentation web-mode-code-indent-offset))
+ )
+
+ ((and is-js
+ (or (member ?\, chars)
+ (member prev-char '(?\( ?\[))))
+ (when debug (message "I360(%S) javascript-args" pos))
+ (cond
+ ((not (web-mode-javascript-args-beginning pos reg-beg))
+ (message "no js args beg")
+ )
+ ((or (not (cdr (assoc "lineup-args" web-mode-indentation-params)))
+ (looking-at-p "|?\n") ;; #1016
+ ;;(eq (char-after) ?\n)
+ )
+ (if (and reg-col (> reg-col (current-indentation)))
+ (setq offset (+ reg-col web-mode-code-indent-offset))
+ (setq offset (+ (current-indentation) web-mode-code-indent-offset)))
+ )
+ ((not (eq curr-char ?\,))
+ (setq offset (current-column)))
+ (t
+ (setq offset (current-column))
+ (goto-char pos)
+ (looking-at ",[ \t\n]*")
+ (setq offset (- offset (length (match-string-no-properties 0)))))
+ ) ;cond
+ )
+
+ ((and is-js
+ (or (eq prev-char ?\))
+ (string-match-p "\\(^\\|[}[:space:]]+\\)else$" prev-line)))
+ (when debug (message "I370(%S)" pos))
+ (cond
+ ((and (string-match-p "else$" prev-line)
+ (not (string-match-p "^{" curr-line)))
+ (setq offset (+ prev-indentation web-mode-code-indent-offset))
+ )
+ ((and (string-match-p "else$" prev-line)
+ (string-match-p "^{" curr-line)
+ web-mode-enable-curly-brace-indentation)
+ (setq offset (+ prev-indentation web-mode-code-indent-offset))
+ )
+ ((setq tmp (web-mode-part-is-opener prev-pos reg-beg))
+ ;;(message "is-opener")
+ (if (or (not (looking-at-p "{")) ;; #1020, #1053, #1160
+ web-mode-enable-curly-brace-indentation)
+ (setq offset (+ tmp web-mode-code-indent-offset))
+ (setq offset tmp))
+ )
+ (t
+ (setq offset
+ (car (web-mode-javascript-indentation pos
+ reg-col
+ curr-indentation
+ language
+ reg-beg)))
+ ) ;t
+ ) ;cond
+
+ )
+
+ ;; TODO : a retoucher completement car le code js a ete place ci-dessus
+ ;;((and (member language '("javascript" "jsx" "ejs" "php"))
+ ((and (member language '("php"))
+ (or (and (eq prev-char ?\))
+ (string-match-p "^\\(for\\|foreach\\|if\\|else[ ]*if\\|while\\)[ ]*(" prev-line))
+ (and is-js
+ (web-mode-part-is-opener prev-pos reg-beg))
+ (string-match-p "^else$" prev-line))
+ (not (string-match-p "^\\([{.]\\|->\\)" curr-line)))
+ (when debug (message "I380(%S)" pos))
+ (cond
+ ((and (eq prev-char ?\))
+ (string-match-p "^\\(for\\|if\\|while\\)[ ]*(" prev-line))
+ (setq offset (+ prev-indentation web-mode-code-indent-offset))
+ )
+ ((member language '("javascript" "jsx"))
+ (setq offset
+ (+ (car (web-mode-javascript-indentation pos
+ reg-col
+ curr-indentation
+ language
+ reg-beg))
+ web-mode-code-indent-offset))
+ )
+ (t
+ (setq offset (+ prev-indentation web-mode-code-indent-offset))
+ )
+ )
+ )
+
+ ((and (member language '("php" "blade")) (string-match-p "^->" curr-line))
+ (when debug (message "I390(%S) block-calls" pos))
+ (cond
+ ((not (web-mode-block-calls-beginning pos reg-beg))
+ )
+ ((cdr (assoc "lineup-calls" web-mode-indentation-params))
+ ;;(message "point=%S" (point))
+ (if (looking-back "::[ ]*" (point-min))
+ (progn
+ (re-search-backward "::[ ]*")
+ (setq offset (current-column))
+ ;;(message "ici%S offset=%S" (point) offset)
+ )
+ (search-forward "->")
+ (setq offset (- (current-column) 2)))
+ )
+ (t
+ (setq offset (+ (current-indentation) web-mode-code-indent-offset)))
+ ))
+
+ ((and is-js (member ?\, chars))
+ (when debug (message "I400(%S) part-args" pos))
+ (cond
+ ((not (web-mode-part-args-beginning pos reg-beg))
+ ;;(message "ici")
+ )
+ ((cdr (assoc "lineup-args" web-mode-indentation-params))
+ (setq offset (current-column))
+ ;;(message "offset=%S" offset)
+ (when (eq curr-char ?\,)
+ (goto-char pos)
+ (looking-at ",[ \t\n]*")
+ (setq offset (- offset (length (match-string-no-properties 0)))))
+ )
+ (t
+ (setq offset (+ (current-indentation) web-mode-code-indent-offset)))
+ ))
+
+ ((member ?\, chars)
+ (when debug (message "I401(%S) block-args" pos))
+ (cond
+ ((not (web-mode-block-args-beginning pos reg-beg))
+ ;;(message "ici")
+ )
+ ((cdr (assoc "lineup-args" web-mode-indentation-params))
+ (setq offset (current-column))
+ ;;(message "offset=%S" offset)
+ (when (eq curr-char ?\,)
+ (goto-char pos)
+ (looking-at ",[ \t\n]*")
+ (setq offset (- offset (length (match-string-no-properties 0)))))
+ )
+ (t
+ (setq offset (+ (current-indentation) web-mode-code-indent-offset)))
+ ))
+
+
+ ((and (string= language "php") (member ?\. chars))
+ (when debug (message "I410(%S) block-string" pos))
+ (cond
+ ((not (web-mode-block-string-beginning pos reg-beg))
+ )
+ ((null (cdr (assoc "lineup-concats" web-mode-indentation-params)))
+ (setq offset (+ (current-indentation) web-mode-code-indent-offset)))
+ ((not (eq curr-char ?\.))
+ (setq offset (current-column)))
+ (t
+ (setq offset (current-column))
+ (goto-char pos)
+ (when (cdr (assoc "lineup-quotes" web-mode-indentation-params))
+ (looking-at "\\.[ \t\n]*")
+ (setq offset (- offset (length (match-string-no-properties 0)))))
+ )))
+
+ ((member language '("javascript" "jsx" "ejs" "underscore"))
+ (when debug (message "I420(%S) javascript-indentation" pos))
+ (setq offset (car (web-mode-javascript-indentation pos
+ reg-col
+ curr-indentation
+ language
+ reg-beg))))
+
+ (t
+ (when debug (message "I430(%S) bracket-indentation" pos))
+ (setq offset (car (web-mode-bracket-indentation pos
+ reg-col
+ curr-indentation
+ language
+ reg-beg))))
+
+ ) ;cond
+
+ (when (and offset reg-col adjust (< offset reg-col)) (setq offset reg-col))
+
+ ) ;let
+ ) ;save-excursion
+
+ (when offset
+ ;;(message "offset=%S" offset)
+ (let ((diff (- (current-column) (current-indentation))))
+ (when (not (= offset (current-indentation)))
+ (setq web-mode-change-beg (line-beginning-position)
+ web-mode-change-end (+ web-mode-change-beg offset)))
+ (setq offset (max 0 offset))
+ (indent-line-to offset)
+ (if (> diff 0) (move-to-column (+ (current-column) diff)))
+ (when (and (string= web-mode-engine "mason")
+ (= offset 0)
+ (eq char ?\%))
+ (save-excursion
+ (font-lock-fontify-region (line-beginning-position) (line-end-position)))
+ ) ;when
+ ) ;let
+ ) ;when
+
+ ))
+
+(defun web-mode-bracket-level (pos limit)
+ (save-excursion
+ (let ((continue t)
+ (regexp "[\]\[}{)(]")
+ (char nil)
+ (map nil)
+ (key nil)
+ (value 0)
+ (open '(?\( ?\{ ?\[)))
+ (goto-char pos)
+ (while (and continue (re-search-backward regexp limit t))
+ (setq char (aref (match-string-no-properties 0) 0))
+ (setq key (cond ((eq char ?\)) ?\()
+ ((eq char ?\}) ?\{)
+ ((eq char ?\]) ?\[)
+ (t char)))
+ (setq value (or (plist-get map key) 0))
+ (setq value (if (member char open) (1+ value) (1- value)))
+ (setq map (plist-put map key value))
+ (setq continue (< value 1))
+ ;;(message "pos=%S char=%c key=%c value=%S" (point) char key value)
+ ) ;while
+ (if (>= value 1) (current-indentation) nil)
+ )))
+
+(defun web-mode-token-html-indentation (pos)
+ (save-excursion
+ (let (beg (continue t) end level map offset regexp tag val void (css-beg 0))
+ (goto-char pos)
+ ;;(message "pos=%S" pos)
+ (setq beg (web-mode-part-token-beginning-position pos))
+ (save-excursion
+ (when (and (> (- pos beg) 5)
+ (re-search-backward "</?[a-zA-Z0-9]+" beg t)
+ (string= "<style" (downcase (match-string-no-properties 0))))
+ (setq css-beg (point))
+ )
+ )
+ ;;(message "beg=%S" beg)
+ (cond
+ ((eq (char-after pos) ?\`)
+ (setq offset (web-mode-indentation-at-pos beg)))
+ ((web-mode-looking-back "`[ \n\t]*" pos)
+ (setq offset (+ (web-mode-indentation-at-pos beg) web-mode-markup-indent-offset)))
+ ((looking-at "</\\([a-zA-Z0-9]+\\)")
+ (setq tag (match-string-no-properties 1)
+ regexp (concat "</?" tag)
+ level -1)
+ (while (and continue (re-search-backward regexp beg t))
+ (cond
+ ((eq (aref (match-string-no-properties 0) 1) ?\/)
+ (setq level (1- level)))
+ (t
+ (setq level (1+ level)))
+ ) ;cond
+ (when (= level 0)
+ (setq continue nil
+ offset (current-indentation)))
+ ) ;while
+ )
+ ((> css-beg 0)
+ ;;(message "CSS")
+ (cond
+ ((member (char-after) '(?\) ?\} ?\]))
+ (web-mode-go (web-mode-token-opening-paren-position pos (+ css-beg 8) ""))
+ (setq offset (current-indentation))
+ )
+ ((setq level (web-mode-bracket-level pos (+ css-beg 8)))
+ (setq offset (+ level web-mode-css-indent-offset))
+ )
+ (t
+ (setq offset (+ (web-mode-indentation-at-pos css-beg) web-mode-style-padding))
+ ) ;t
+ )
+ )
+ ((looking-at "[a-zA-Z-]+[ ]?=")
+ (re-search-backward "<[a-zA-Z]+[ ]*" beg t)
+ (setq offset (+ (current-column) (length (match-string-no-properties 0))))
+ )
+ ((looking-at-p "/>")
+ (search-backward "<" beg t)
+ (setq offset (current-column))
+ )
+ (t
+ (setq regexp "</?\\([a-zA-Z0-9]+\\)")
+ ;;(message "point=%S" (point))
+ (while (and continue (re-search-backward regexp beg t))
+ (setq tag (downcase (match-string-no-properties 1))
+ end nil
+ void nil)
+ (cond
+ ((eq (aref (match-string-no-properties 0) 1) ?/)
+ (setq end t))
+ ((web-mode-element-is-void tag)
+ (setq void t))
+ (t
+ (save-excursion
+ (when (and (search-forward ">" pos t) (eq (char-before (1- (point))) ?\/))
+ (setq void t))
+ ) ;save-excursion
+ ) ;t
+ ) ;cond
+ (unless void
+ (setq val (or (lax-plist-get map tag) 0))
+ (setq val (if end (1- val) (1+ val)))
+ (setq map (lax-plist-put map tag val))
+ ;;(message "val=%S tag=%S end=%S | %S" val tag end (plist-get map tag))
+ (setq continue (not (> val 0)))
+ ) ;unless
+ ;(message "pos=%S tag=%S val=%S end=%S void=%S" (point) tag val end void)
+ ) ;while
+ (cond
+ ((> val 0)
+ ;;(message "point=%S" (point))
+ ;;(goto-char (1+ beg))
+ ;;(forward-char)
+ ;;(re-search-forward "[[:space:]]*")
+ (setq offset (+ (current-indentation) web-mode-markup-indent-offset)))
+ (t
+ (setq offset (current-indentation)))
+ )
+ ) ;t
+ ) ;cond
+ offset)))
+
+(defun web-mode-token-css-indentation (pos)
+ (save-excursion
+ (let (offset)
+ (goto-char pos)
+ (web-mode-part-token-beginning)
+ (setq offset (+ web-mode-css-indent-offset (current-indentation)))
+ ) ;let
+ ))
+
+(defun web-mode-relayql-indentation (pos &optional prefix)
+ (unless prefix (setq prefix "relayql"))
+ (let (beg offset level char)
+ (setq char (char-after))
+ (setq beg (web-mode-part-token-beginning-position pos))
+ (goto-char beg)
+ (cond
+ ((member char '(?\`))
+ (setq offset (current-indentation))
+ )
+ ((member char '(?\) ?\} ?\]))
+ (web-mode-go (web-mode-token-opening-paren-position pos beg prefix))
+ (setq offset (current-indentation))
+ )
+ ((setq level (web-mode-bracket-level pos beg))
+ (setq offset (+ level web-mode-code-indent-offset))
+ )
+ (t
+ (setq offset (+ (current-indentation) web-mode-code-indent-offset))
+ )
+ )
+ offset))
+
+(defun web-mode-markup-indentation (pos)
+ (let (offset beg ret jsx-depth)
+ (when (and (setq jsx-depth (get-text-property pos 'jsx-depth))
+ (get-text-property pos 'jsx-beg)
+ (not (get-text-property pos 'tag-beg)))
+ (setq jsx-depth (1- jsx-depth)))
+ ;;(when (setq beg (web-mode-markup-indentation-origin pos jsx-depth))
+ (cond
+ ((not (setq beg (web-mode-markup-indentation-origin pos jsx-depth)))
+ (setq offset 0))
+ ((null (setq ret (web-mode-element-is-opened beg pos)))
+ (setq offset (web-mode-indentation-at-pos beg)))
+ ((eq ret t)
+ (setq offset (+ (web-mode-indentation-at-pos beg)
+ web-mode-markup-indent-offset)))
+ (t
+ (setq offset ret))
+ ) ;cond
+ ;;(message "markup-indentation-origin=%S (jsx-depth=%S)" beg jsx-depth)
+ ;;) ;when beg
+ offset))
+
+(defun web-mode-css-indentation (pos initial-column language-offset language &optional limit)
+ (let ((open-ctx (web-mode-bracket-up pos language limit)) offset)
+ (cond
+ ((or (null open-ctx) (null (plist-get open-ctx :pos)))
+ (setq offset initial-column))
+ (t
+ (setq offset (+ (plist-get open-ctx :indentation) language-offset)))
+ ) ;cond
+ (cons (if (< offset initial-column) initial-column offset) open-ctx)
+ ))
+
+(defun web-mode-sql-indentation (pos initial-column language-offset language &optional limit)
+ (let ((open-ctx (web-mode-bracket-up pos language limit)) offset)
+ ;;(message "%S %S %S %S %S" pos (point) initial-column language-offset open-ctx)
+ (cond
+ ((and (not (null open-ctx)) (not (null (plist-get open-ctx :pos))))
+ (setq offset (+ (plist-get open-ctx :column) 1)))
+ ((looking-at-p "\\(SELECT\\|INSERT\\|DELETE\\|UPDATE\\|FROM\\|LEFT\\|JOIN\\|WHERE\\|GROUP BY\\|LIMIT\\|HAVING\\|ON\\|select\\|insert\\|delete\\|update\\|from\\|left\\|join\\|where\\|group by\\|limit\\|having\\|on\\|AND\\|and\\|OR\\|or\\)")
+ (setq offset initial-column))
+ (t
+ (setq offset (+ initial-column language-offset)))
+ ) ;cond
+ (cons (if (< offset initial-column) initial-column offset) open-ctx)
+ ))
+
+(defun web-mode-markdown-indentation (pos initial-column language-offset language &optional limit)
+ (let (offset)
+ (save-excursion
+ (goto-char pos)
+ (setq offset (current-column))
+ ) ;save-excursion
+ ;;(message "%S %S %S %S" pos (point) initial-column language-offset)
+ (cons (if (<= offset initial-column) initial-column offset) nil)))
+
+(defun web-mode-stylus-indentation (pos initial-column language-offset language &optional limit)
+ (let (offset)
+ (save-excursion
+ (goto-char pos)
+ (setq offset (current-column))
+ (if (looking-at-p "[[:alnum:]-]+:")
+ (setq offset (+ initial-column language-offset))
+ (setq offset initial-column))
+ ) ;save-excursion
+ ;;(message "%S %S %S %S" pos (point) initial-column language-offset)
+ (cons (if (<= offset initial-column) initial-column offset) nil)))
+
+(defun web-mode-sass-indentation (pos initial-column language-offset language &optional limit)
+ (let (offset)
+ (save-excursion
+ (goto-char pos)
+ (setq offset (current-column))
+ (if (looking-at-p "[[:alnum:]-]+:")
+ (setq offset (+ initial-column language-offset))
+ (setq offset initial-column))
+ ) ;save-excursion
+ ;;(message "%S %S %S %S" pos (point) initial-column language-offset)
+ (cons (if (<= offset initial-column) initial-column offset) nil)))
+
+(defun web-mode-pug-indentation (pos initial-column language-offset language &optional limit)
+ nil
+ )
+
+(defun web-mode-javascript-indentation (pos initial-column language-offset language &optional limit)
+ (let (open-ctx indentation offset sub)
+ (setq open-ctx (web-mode-bracket-up pos language limit))
+ ;;(message "pos(%S) initial-column(%S) language-offset(%S) language(%S) limit(%S)" pos initial-column language-offset language limit)
+ ;;(message "javascript-indentation: %S\nchar=%c" open-ctx (plist-get open-ctx :char))
+ (setq indentation (plist-get open-ctx :indentation))
+ (when (and initial-column (> initial-column indentation))
+ (setq indentation initial-column)
+ )
+ (setq case-fold-search nil) ; #1006
+ (cond
+ ((or (null open-ctx) (null (plist-get open-ctx :pos)))
+ (setq offset initial-column))
+ ((and (member language '("javascript" "jsx" "ejs"))
+ (eq (plist-get open-ctx :char) ?\{)
+ (web-mode-looking-back "switch[ ]*" (plist-get open-ctx :pos)))
+ (setq sub (if (cdr (assoc "case-extra-offset" web-mode-indentation-params)) 0 1))
+ (cond
+ ((looking-at-p "case\\|default")
+ (setq offset (+ indentation (* language-offset (- 1 sub)))))
+ (t
+ (setq offset (+ indentation (* language-offset (- 2 sub)))))
+ ) ;cond switch
+ )
+ (t
+ (setq offset (+ indentation language-offset)))
+ ) ;cond
+ (setq case-fold-search t)
+ (cons (if (< offset initial-column) initial-column offset) open-ctx)
+ ))
+
+(defun web-mode-bracket-indentation (pos initial-column language-offset language &optional limit)
+ (save-excursion
+ (let* ((ctx (web-mode-bracket-up pos language limit))
+ (char (plist-get ctx :char))
+ (pos (plist-get ctx :pos))
+ (indentation (plist-get ctx :indentation)))
+ ;;(message "pos(%S) initial-column(%S) language-offset(%S) language(%S) limit(%S)" pos initial-column language-offset language limit)
+ ;;(message "bracket-up: %S, %c" ctx char)
+ (cond
+ ((null pos)
+ (setq indentation initial-column))
+ ((and (member language '("php"))
+ (eq char ?\{)
+ (web-mode-looking-back "switch[ ]*" pos)
+ (not (looking-at-p "case\\|default")))
+ (setq indentation (+ indentation (* language-offset 2)))
+ )
+ ((and (member language '("php"))
+ (eq char ?\{)
+ (goto-char pos)
+ (web-mode-looking-back "[)][ ]*" pos)
+ (search-backward ")")
+ (web-mode-block-opening-paren limit))
+ (setq indentation (+ (current-indentation) language-offset))
+ )
+ (t
+ (setq indentation (+ indentation language-offset))
+ )
+ ) ;cond
+ (cons (if (< indentation initial-column) initial-column indentation) ctx)
+ )))
+
+(defun web-mode-ruby-indentation (pos line initial-column language-offset limit)
+ (unless limit (setq limit nil))
+ (let (h offset prev-line prev-indentation open-ctx)
+ (setq open-ctx (web-mode-bracket-up pos "ruby" limit))
+ ;;(message "%S" open-ctx)
+ (if (plist-get open-ctx :pos)
+ (cond
+ ((web-mode-looking-at-p ".[ \t\n]+" (plist-get open-ctx :pos))
+ (setq offset (+ (plist-get open-ctx :indentation) language-offset)))
+ (t
+ (setq offset (1+ (plist-get open-ctx :column))))
+ )
+ (setq h (web-mode-previous-line pos limit))
+ (setq offset initial-column)
+ (when h
+ (setq prev-line (car h))
+ (setq prev-indentation (cdr h))
+ (cond
+ ((string-match-p ",$" prev-line)
+ (save-excursion
+ (goto-char limit)
+ (looking-at "<%=? [a-z]+ ")
+ (setq offset (+ initial-column (length (match-string-no-properties 0))))
+ ) ;save-excursion
+ )
+ ((string-match-p "^[ ]*\\(end\\|else\\|elsif\\|when\\)" line)
+ (setq offset (- prev-indentation language-offset))
+ )
+ ((string-match-p "[ ]+\\(do\\)" prev-line)
+ (setq offset (+ prev-indentation language-offset))
+ )
+ ((string-match-p "^[ ]*\\(when\\|if\\|else\\|elsif\\|unless\\|for\\|while\\|def\\|class\\)" prev-line)
+ (setq offset (+ prev-indentation language-offset))
+ )
+ (t
+ (setq offset prev-indentation)
+ )
+ )
+ ) ;when
+ ) ;if
+ offset))
+
+(defun web-mode-python-indentation (pos line initial-column language-offset limit)
+ (unless limit (setq limit nil))
+ (let (h offset prev-line prev-indentation ctx)
+ (setq ctx (web-mode-bracket-up pos "python" limit))
+ ;;(message "point-ctx=%S" ctx)
+ (if (plist-get ctx :pos)
+ (cond
+ ((web-mode-looking-at-p ".[ \t\n]+" (plist-get ctx :pos))
+ (setq offset (+ (plist-get ctx :indentation) language-offset)))
+ (t
+ (setq offset (1+ (plist-get ctx :column))))
+ )
+ ;; else
+ (setq h (web-mode-previous-line pos limit))
+ (setq offset initial-column)
+ (when h
+ (setq prev-line (car h))
+ (setq prev-indentation (cdr h))
+ (cond
+ ((string-match-p "^\\(pass\\|else\\|elif\\|when\\|except\\)" line)
+ (setq offset (- prev-indentation language-offset))
+ )
+ ((string-match-p "\\(if\\|else\\|elif\\|for\\|while\\|try\\|except\\)" prev-line)
+ (setq offset (+ prev-indentation language-offset))
+ )
+ (t
+ (setq offset prev-indentation)
+ )
+ ) ;cond
+ ) ;when
+ ) ;if
+ ;;offset
+ (if (< offset initial-column) initial-column offset)
+ ))
+
+(defun web-mode-lisp-indentation (pos point-ctx)
+ (let (offset open-ctx)
+ (setq open-ctx (web-mode-bracket-up pos "lsp" (plist-get point-ctx :reg-beg)))
+ ;;(message "point-ctx=%S" point-ctx)
+ ;;(message "open-ctx=%S" open-ctx)
+ (cond
+ ((null (plist-get open-ctx :pos))
+ (setq offset (plist-get point-ctx :reg-col)))
+ ((member (plist-get point-ctx :curr-char) '(?\( ?\)))
+ (if (web-mode-looking-at-p "((" (plist-get open-ctx :pos))
+ (setq offset (+ (plist-get open-ctx :column) 1))
+ (setq offset (+ (plist-get open-ctx :column) web-mode-code-indent-offset)))
+ )
+ (t
+ (goto-char (plist-get open-ctx :pos))
+ (forward-char)
+ (web-mode-rsf "[[:alnum:]-:]+ ")
+ (setq offset (current-column))
+ )
+ ) ;cond
+ offset))
+
+(defun web-mode-asp-indentation (pos line initial-column language-offset limit)
+ (unless limit (setq limit nil))
+ (let (h out prev-line prev-indentation)
+ (setq h (web-mode-previous-line pos limit))
+ (setq out initial-column)
+ (when h
+ (setq prev-line (car h))
+ (setq prev-indentation (cdr h))
+ ;;(message "line=%S" line)
+ (cond
+ ((string-match-p "''" line)
+ (setq out prev-indentation))
+ ;; ----------------------------------------------------------------------
+ ;; unindent
+ ((string-match-p "\\_<\\(\\(end \\(if\\|function\\|class\\|sub\\|with\\)\\)\\|else\\|elseif\\|next\\|loop\\)\\_>" line)
+ (setq out (- prev-indentation language-offset)))
+ ;; ----------------------------------------------------------------------
+ ;; select case statement
+ ((string-match-p "\\_<\\(select case\\)\\_>" line)
+ (setq out (- prev-indentation 0)))
+ ((string-match-p "\\_<\\(end select\\)" line)
+ (setq out (- prev-indentation (* 2 language-offset))))
+ ((and (string-match-p "\\_<\\(case\\)\\_>" line) (not (string-match-p "\\_<\\(select case\\)\\_>" prev-line)))
+ (setq out (- prev-indentation language-offset)))
+ ;; ----------------------------------------------------------------------
+ ;; do nothing
+ ((string-match-p "\\_<\\(\\(end \\(if\\|function\\|class\\|sub\\|select\\|with\\)\\)\\|loop\\( until\\| while\\)?\\)\\_>" prev-line)
+ (setq out (+ prev-indentation 0)))
+ ;; indent
+ ((string-match-p "\\_<\\(\\(select \\)?case\\|else\\|elseif\\|unless\\|for\\|class\\|with\\|do\\( until\\| while\\)?\\|while\\|\\(public \\|private \\)?\\(function\\|sub\\|class\\)\\)\\_>" prev-line)
+ (setq out (+ prev-indentation language-offset)))
+ ;; single line if statement
+ ((string-match-p "\\_<if\\_>.*\\_<then\\_>[ \t]*[[:alpha:]]+" prev-line)
+ (setq out (+ prev-indentation 0)))
+ ;; normal if statement
+ ((string-match-p "\\_<\\if\\_>" prev-line)
+ (setq out (+ prev-indentation language-offset)))
+ (t
+ (setq out prev-indentation))
+ )
+ ) ;when
+ out))
+
+(defun web-mode-block-previous-live-line ()
+ (save-excursion
+ (let ((continue t) (line "") (pos (point)))
+ (beginning-of-line)
+ (while (and continue (not (bobp)) (forward-line -1))
+ (when (not (web-mode-block-is-token-line))
+ (setq line (web-mode-trim (buffer-substring (point) (line-end-position)))))
+ (when (not (string= line ""))
+ (setq continue nil))
+ ) ;while
+ (if (string= line "")
+ (progn (goto-char pos) nil)
+ (cons line (current-indentation)))
+ )))
+
+(defun web-mode-part-is-opener (pos reg-beg)
+ (save-excursion
+ (save-match-data
+ (if (and pos
+ (web-mode-go (web-mode-part-opening-paren-position pos))
+ (>= (point) reg-beg)
+ (looking-back "\\(^\\|[ \t]\\)\\(if\\|for\\|while\\)[ ]*" (point-min)))
+ (current-indentation)
+ nil)
+ )))
+
+(defun web-mode-part-previous-live-line (reg-beg)
+ (unless reg-beg (setq reg-beg (point-min)))
+ ;;(message "reg-beg=%S" reg-beg)
+ (save-excursion
+ (let ((continue (> (point) reg-beg))
+ (line "")
+ bol-pos
+ eol-pos
+ pos)
+ (beginning-of-line)
+ (while (and continue (> (point) reg-beg) (forward-line -1))
+ (setq bol-pos (point)
+ eol-pos (line-end-position))
+ (when (> reg-beg bol-pos)
+ (setq bol-pos reg-beg))
+ (when (not (web-mode-part-is-token-line bol-pos))
+ (setq line (web-mode-trim (buffer-substring bol-pos eol-pos)))
+ (when (not (string= line "")) (setq continue nil))
+ ) ;when
+ ) ;while
+ (cond
+ ((string= line "")
+ nil)
+ (t
+ (setq continue t)
+ (setq pos (1- eol-pos))
+ (while (and (>= pos bol-pos) continue)
+ (cond
+ ((eq (char-after pos) ?\s)
+ (setq pos (1- pos)))
+ ((get-text-property pos 'part-token)
+ (setq pos (1- pos)))
+ (t
+ (setq continue nil))
+ ) ;cond
+ ) ;while
+ ;;(message "%S %S : %S" bol-pos eol-pos pos)
+ (setq line (web-mode-clean-part-line line))
+ (list line (current-indentation) pos))
+ ) ;cond
+ )))
+
+(defun web-mode-in-code-block (open close &optional prop)
+ (save-excursion
+ (let ((pos (point)) pos-open pos-close start end ret)
+ (when prop
+ (setq start pos
+ end pos)
+ (when (eq (get-text-property pos prop) (get-text-property (1- pos) prop))
+ (setq start (or (previous-single-property-change pos prop) (point-min))))
+ (when (eq (get-text-property pos prop) (get-text-property (1+ pos) prop))
+ (setq end (next-single-property-change pos prop)))
+ ;; (message "start(%S) end(%S)" start end)
+ )
+ (setq ret (and (web-mode-sb open start t)
+ (setq pos-open (point))
+ (web-mode-sf close end t)
+ (setq pos-close (point))
+ (>= pos-close pos)))
+ (if ret
+ (cons pos-open pos-close)
+ ret)
+ )))
+
+(defun web-mode-clean-part-line (input)
+ (let ((out "")
+ (beg 0)
+ (keep t)
+ (n (length input)))
+ (dotimes (i n)
+ (if (or (get-text-property i 'block-side input)
+ (eq (get-text-property i 'part-token input) 'comment)
+ (eq (get-text-property i 'tag-type input) 'comment))
+ (when keep
+ (setq out (concat out (substring input beg i))
+ beg 0
+ keep nil))
+ (when (null keep)
+ (setq beg i
+ keep t))
+ ) ;if
+ ) ;dotimes
+ (if (> beg 0) (setq out (concat out (substring input beg n))))
+ (setq out (if (= (length out) 0) input out))
+ (web-mode-trim out)
+ ))
+
+(defun web-mode-clean-block-line (input)
+ (let ((out "")
+ (beg 0)
+ (keep t)
+ (n (length input)))
+ (dotimes (i n)
+ (if (or (not (get-text-property i 'block-side input))
+ (member (get-text-property i 'block-token input)
+ '(comment delimiter-beg delimiter-end)))
+ (when keep
+ (setq out (concat out (substring input beg i))
+ beg 0
+ keep nil))
+ (when (null keep)
+ (setq beg i
+ keep t))
+ ) ;if
+ ) ;dotimes
+ (if (> beg 0) (setq out (concat out (substring input beg n))))
+ (setq out (if (= (length out) 0) input out))
+ (web-mode-trim out)
+ ;; (message "%S [%s] > [%s]" beg input out)
+ ))
+
+(defun web-mode-language-at-pos (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((get-text-property pos 'block-side)
+ web-mode-engine)
+ ((get-text-property pos 'part-side)
+ (symbol-name (get-text-property pos 'part-side)))
+ (t
+ web-mode-content-type)
+ ) ;cond
+ )
+
+(defun web-mode-coord-position (line column)
+ (save-excursion
+ (when (stringp line) (setq line (string-to-number line)))
+ (when (stringp column) (setq column (string-to-number column)))
+ (goto-char (point-min))
+ (forward-line (1- line))
+ (move-to-column (1- column))
+ (point)))
+
+(defun web-mode-is-single-line-block (pos)
+ (= (web-mode-line-number (web-mode-block-beginning-position pos))
+ (web-mode-line-number (web-mode-block-end-position pos))))
+
+(defun web-mode-line-number (&optional pos)
+ (setq pos (or pos (point)))
+ (+ (count-lines 1 pos) (if (= (web-mode-column-at-pos pos) 0) 1 0)))
+
+(defun web-mode-block-is-control (pos)
+ (save-excursion
+ (let (control state controls pair)
+ (goto-char pos)
+ (setq controls (web-mode-block-controls-get pos))
+ (setq pair (car controls))
+ (cond
+ ((eq (car pair) 'inside)
+ )
+ ((eq (car pair) 'open)
+ (setq state t
+ control (cdr pair)))
+ ((eq (car pair) 'close)
+ (setq state nil
+ control (cdr pair)))
+ ) ;cond
+ ;; (message "engine=%S control=%S state=%S" web-mode-engine control state)
+ (if control (cons control state) nil)
+ )))
+
+(defun web-mode-block-is-opening-control (pos)
+ (save-excursion
+ (let (controls pair)
+ (goto-char pos)
+ (if (and (setq controls (web-mode-block-controls-get pos))
+ (= (length controls) 1)
+ (setq pair (car controls))
+ (eq (car pair) 'open))
+ (cdr pair)
+ nil)
+ )))
+
+(defun web-mode-markup-indentation-origin (pos jsx-depth)
+ (save-excursion
+ (let* ((found (bobp))
+ (jsx-beg nil)
+ (types '(start end void))
+ (type nil))
+ (when jsx-depth
+ (setq jsx-beg (web-mode-jsx-depth-beginning-position pos jsx-depth)))
+ (while (not found)
+ (forward-line -1)
+ (if (bobp)
+ (setq pos (point)
+ found t)
+ (back-to-indentation)
+ (when (and jsx-beg (< (point) jsx-beg))
+ (goto-char jsx-beg))
+ (setq pos (point))
+ (setq type (get-text-property pos 'tag-type))
+ (setq found (or (and (null jsx-depth)
+ (null (get-text-property pos 'part-side))
+ (get-text-property pos 'tag-beg)
+ (member type types)
+ (null (get-text-property (1- pos) 'invisible)))
+ (and (null jsx-depth)
+ (null (get-text-property pos 'part-side))
+ (eq (get-text-property pos 'tag-type) 'comment)
+ (web-mode-looking-at-p "<!--#\\(endif\\|if\\)" pos)
+ (null (get-text-property (1- pos) 'invisible)))
+ (and jsx-depth
+ (get-text-property pos 'tag-beg)
+ (member type types)
+ (null (get-text-property (1- pos) 'invisible))
+ (eq (get-text-property pos 'jsx-depth) jsx-depth))
+ (and (get-text-property pos 'block-beg)
+ (not type)
+ (web-mode-block-is-control pos)
+ (not (looking-at-p "{% commen\\|@break")))))
+ ) ;if
+ ) ;while
+ ;;(message "indent-origin=%S" pos)
+ pos)))
+
+;;TODO : prendre en compte part-token
+;; state=t <=> start tag
+(defun web-mode-element-is-opened (pos limit)
+ (let (tag
+ last-end-tag
+ tag-pos block-pos
+ state
+ n
+ ret
+ (continue t)
+ controls
+ control
+ (buffer (current-buffer))
+ (h (make-hash-table :test 'equal))
+ (h2 (make-hash-table :test 'equal)))
+
+;; (message "pos-ori=%S limit=%S" pos limit)
+
+ (while continue
+ (setq control nil
+ controls nil
+ last-end-tag nil
+ tag nil)
+
+ (cond
+ ((and (eq (get-text-property pos 'tag-type) 'comment)
+ (web-mode-looking-at "<!--#\\(endif\\|if\\)" pos))
+ ;;(message "pos=%S" pos)
+ (setq tag "#if")
+ (setq n (gethash tag h 0))
+ (if (string= (match-string-no-properties 1) "if")
+ (puthash tag (1+ n) h)
+ (puthash tag (1- n) h))
+ ;;(setq tag-pos pos)
+ )
+ ((get-text-property pos 'tag-beg)
+ (when (member (get-text-property pos 'tag-type) '(start end))
+ (setq tag (get-text-property pos 'tag-name)
+ state (eq (get-text-property pos 'tag-type) 'start))
+ (if (null state) (setq last-end-tag (cons tag pos)))
+ (setq n (gethash tag h 0))
+ (cond
+ ((null state)
+ (when (> n 0) (puthash tag (1- n) h))
+ (puthash tag (1- n) h2))
+ ((member tag web-mode-offsetless-elements)
+ )
+ (t
+ (puthash tag (1+ n) h)
+ (puthash tag (1+ n) h2))
+ ) ;cond
+ ) ;when
+ (when (setq pos (web-mode-tag-end-position pos))
+ (setq tag-pos nil)
+ (when (and block-pos (> pos block-pos))
+ (setq block-pos nil))
+ ) ;when
+ )
+ ((and web-mode-enable-control-block-indentation
+ (get-text-property pos 'block-beg))
+ (when (setq controls (web-mode-block-controls-get pos))
+ (dolist (control controls)
+ (setq tag (cdr control))
+ (setq n (gethash tag h 0))
+ (cond
+ ((eq (car control) 'inside)
+ )
+ ((eq (car control) 'open)
+ (puthash tag (1+ n) h))
+ ((> n 0)
+ (puthash tag (1- n) h))
+ ) ;cond
+ ) ;dolist
+ )
+ (when (setq pos (web-mode-block-end-position pos))
+ (setq block-pos nil)
+ (when (and tag-pos (> pos tag-pos))
+ (setq tag-pos nil))
+ )
+ )
+ ) ;cond
+
+;; (message "tag=%S end-pos=%S" tag pos)
+
+ (when (and pos (< pos limit))
+ (when (or (null tag-pos) (>= pos tag-pos))
+ (setq tag-pos (web-mode-tag-next-position pos limit))
+;; (message "from=%S tag-next-pos=%S" pos tag-pos)
+ )
+ (when (or (null block-pos) (>= pos block-pos))
+ (setq block-pos (web-mode-block-next-position pos limit))
+;; (message "from=%S block-next-pos=%S" pos block-pos)
+ )
+ )
+
+ (cond
+ ((null pos)
+ )
+ ((and (null tag-pos)
+ (null block-pos))
+ (setq pos nil))
+ ((and tag-pos block-pos)
+ (if (< tag-pos block-pos)
+ (progn
+ (setq pos tag-pos)
+ (setq tag-pos nil))
+ (setq pos block-pos)
+ (setq block-pos nil))
+ )
+ ((null tag-pos)
+ (setq pos block-pos)
+ (setq block-pos nil))
+ (t
+ (setq pos tag-pos)
+ (setq tag-pos nil))
+ )
+
+ (when (or (null pos)
+ (>= pos limit))
+ (setq continue nil))
+ ) ;while
+
+ ;;(message "hashtable=%S" h)
+ (maphash (lambda (k v) (if (> v 0) (setq ret t))) h)
+
+ (when (and (null ret)
+ last-end-tag
+ (> (hash-table-count h2) 1)
+ (< (gethash (car last-end-tag) h2) 0))
+;; (message "last-end-tag=%S" last-end-tag)
+ (save-excursion
+ (goto-char (cdr last-end-tag))
+ (web-mode-tag-match)
+ (when (not (= (point) (cdr last-end-tag)))
+ (setq n (point))
+ (back-to-indentation)
+ (if (= n (point)) (setq ret (current-indentation))))
+ ))
+
+ ret))
+
+(defun web-mode-previous-line (pos limit)
+ (save-excursion
+ (let (beg end line (continue t))
+ (goto-char pos)
+ (while continue
+ (forward-line -1)
+ (setq end (line-end-position))
+ (setq line (buffer-substring-no-properties (point) end))
+ (when (or (not (string-match-p "^[ \t]*$" line))
+ (bobp)
+ (<= (point) limit))
+ (setq continue nil))
+ )
+ (if (<= (point) limit)
+ ;;todo : affiner (le + 3 n est pas générique cf. <?php <% <%- etc.)
+ (setq beg (if (< (+ limit 3) end) (+ limit 3) end))
+ (setq beg (line-beginning-position))
+ ) ;if
+ (setq line (buffer-substring-no-properties beg end))
+ (cons line (current-indentation))
+ )))
+
+(defun web-mode-bracket-up (pos language &optional limit)
+ (unless limit (setq limit nil))
+ ;;(message "pos(%S) language(%S) limit(%S)" pos language limit)
+ (save-excursion
+ (goto-char pos)
+ (let ((continue t)
+ (regexp "[\]\[}{)(]")
+ (char nil)
+ (column nil)
+ (indentation nil)
+ (map nil)
+ (key nil)
+ (value 0)
+ (open '(?\( ?\{ ?\[))
+ (searcher nil)
+ (opener nil))
+ (cond
+ ((get-text-property pos 'block-side)
+ (setq searcher 'web-mode-block-rsb
+ opener 'web-mode-block-opening-paren-position))
+ (t
+ (setq searcher 'web-mode-part-rsb
+ opener 'web-mode-part-opening-paren-position))
+ )
+ (while (and continue (funcall searcher regexp limit))
+ (setq char (aref (match-string-no-properties 0) 0))
+ (setq key (cond ((eq char ?\)) ?\()
+ ((eq char ?\}) ?\{)
+ ((eq char ?\]) ?\[)
+ (t char)))
+ (setq value (or (plist-get map key) 0))
+ (setq value (if (member char open) (1+ value) (1- value)))
+ (setq map (plist-put map key value))
+ (setq continue (< value 1))
+ ;;(message "pos=%S char=%c key=%c value=%S map=%S" (point) char key value map)
+ ) ;while
+ (setq column (current-column)
+ indentation (current-indentation))
+ (when (and (> value 0)
+ (eq char ?\{)
+ (looking-back ")[ ]*" (point-min)))
+ (search-backward ")")
+ (when (setq pos (funcall opener (point) limit))
+ (goto-char pos)
+ ;;(message "pos=%S" pos)
+ (setq indentation (current-indentation)))
+ ) ;when
+ (list :pos (if (> value 0) (point) nil)
+ :char char
+ :column column
+ :indentation indentation)
+ ) ;let
+ ))
+
+(defun web-mode-count-char-in-string (char string)
+ (let ((n 0))
+ (dotimes (i (length string))
+ (if (eq (elt string i) char)
+ (setq n (1+ n))))
+ n))
+
+(defun web-mode-mark-and-expand ()
+ "Mark and expand."
+ (interactive)
+ (web-mode-mark (point)))
+
+(defun web-mode-mark (pos)
+ (let ((beg pos) (end pos) prop reg-beg boundaries)
+
+ (if mark-active
+ (setq reg-beg (region-beginning))
+ (setq web-mode-expand-initial-pos (point)
+ web-mode-expand-initial-scroll (window-start))
+ )
+
+ ;; (message "regs=%S %S %S %S" (region-beginning) (region-end) (point-min) (point-max))
+ ;; (message "before=%S" web-mode-expand-previous-state)
+
+ (cond
+
+ ((and mark-active
+ (= (region-beginning) (point-min))
+ (or (= (region-end) (point-max))
+ (= (1+ (region-end)) (point-max))))
+ (deactivate-mark)
+ (goto-char (or web-mode-expand-initial-pos (point-min)))
+ (setq web-mode-expand-previous-state nil)
+ (when web-mode-expand-initial-scroll
+ (set-window-start (selected-window) web-mode-expand-initial-scroll))
+ )
+
+ ((string= web-mode-expand-previous-state "elt-content")
+ (web-mode-element-parent)
+ ;;(message "pos=%S" (point))
+ (web-mode-element-select)
+ (setq web-mode-expand-previous-state "html-parent"))
+
+ ((and (member (get-text-property pos 'block-token) '(comment string))
+ (not (member web-mode-expand-previous-state '("block-token" "block-body" "block-side"))))
+ (when (eq (get-text-property pos 'block-token) (get-text-property (1- pos) 'block-token))
+ (setq beg (or (previous-single-property-change pos 'block-token) (point-min))))
+ (when (eq (get-text-property pos 'block-token) (get-text-property (1+ pos) 'block-token))
+ (setq end (next-single-property-change pos 'block-token)))
+ (set-mark beg)
+ (goto-char end)
+ (exchange-point-and-mark)
+ (setq web-mode-expand-previous-state "block-token"))
+
+ ((and (get-text-property pos 'block-side)
+ (not (member web-mode-expand-previous-state '("block-body" "block-side")))
+ (not (member web-mode-engine '(django go)))
+ (setq boundaries (web-mode-in-code-block "{" "}" 'block-side)))
+ (set-mark (car boundaries))
+ (goto-char (cdr boundaries))
+ (exchange-point-and-mark)
+ (setq web-mode-expand-previous-state "block-body"))
+
+ ((and (get-text-property pos 'block-side)
+ (not (member web-mode-expand-previous-state '("block-side"))))
+ (set-mark (web-mode-block-beginning-position pos))
+ (goto-char (1+ (web-mode-block-end-position pos)))
+ (exchange-point-and-mark)
+ (setq web-mode-expand-previous-state "block-side"))
+
+ ((and (get-text-property pos 'part-token)
+ (not (string= web-mode-expand-previous-state "part-token")))
+ (when (eq (get-text-property pos 'part-token) (get-text-property (1- pos) 'part-token))
+ (setq beg (previous-single-property-change pos 'part-token)))
+ (when (eq (get-text-property pos 'part-token) (get-text-property (1+ pos) 'part-token))
+ (setq end (next-single-property-change pos 'part-token)))
+ (set-mark beg)
+ (goto-char end)
+ (exchange-point-and-mark)
+ (setq web-mode-expand-previous-state "part-token"))
+
+ ((and (get-text-property pos 'part-side)
+ (not (string= web-mode-expand-previous-state "client-part"))
+ (setq boundaries (web-mode-in-code-block "{" "}" 'part-side)))
+ (set-mark (car boundaries))
+ (goto-char (cdr boundaries))
+ (exchange-point-and-mark)
+ (setq web-mode-expand-previous-state "client-part"))
+
+ ((and (get-text-property pos 'part-side)
+ (not (string= web-mode-expand-previous-state "part-side")))
+ (when (eq (get-text-property pos 'part-side) (get-text-property (1- pos) 'part-side))
+ (setq beg (previous-single-property-change pos 'part-side)))
+ (when (eq (get-text-property pos 'part-side) (get-text-property (1+ pos) 'part-side))
+ (setq end (next-single-property-change pos 'part-side)))
+ (when (eq (char-after beg) ?\n)
+ (setq beg (1+ beg)))
+ (set-mark beg)
+ (goto-char end)
+ (when (looking-back "^[ \t]+" (point-min))
+ (beginning-of-line))
+ (exchange-point-and-mark)
+ (setq web-mode-expand-previous-state "part-side"))
+
+ ((and (get-text-property pos 'tag-attr)
+ (not (member web-mode-expand-previous-state '("html-attr" "html-tag"))))
+ (web-mode-attribute-select pos)
+ (setq web-mode-expand-previous-state "html-attr"))
+
+ ((and (eq (get-text-property pos 'tag-type) 'comment)
+ (not (member web-mode-expand-previous-state '("html-tag" "html-comment" "html-elt" "html-parent"))))
+ (web-mode-tag-select)
+ (setq web-mode-expand-previous-state "html-comment"))
+
+ ((and (get-text-property pos 'tag-name)
+ (not (member web-mode-expand-previous-state '("html-tag" "html-elt" "html-parent"))))
+ (web-mode-tag-select)
+ (setq web-mode-expand-previous-state "html-tag"))
+
+ ((and (get-text-property pos 'tag-beg)
+ (string= web-mode-expand-previous-state "html-tag"))
+ (web-mode-element-select)
+ (setq web-mode-expand-previous-state "html-elt"))
+
+ (t
+ (cond
+ ((not (web-mode-element-parent))
+ (push-mark (point))
+ (push-mark (point-max) nil t)
+ (goto-char (point-min))
+ (setq web-mode-expand-previous-state "mark-whole"))
+ ((not (= (web-mode-tag-end-position (point)) (1- beg)))
+ (web-mode-element-content-select)
+ (setq web-mode-expand-previous-state "elt-content"))
+ (t
+ (web-mode-element-select)
+ (setq web-mode-expand-previous-state "html-parent"))
+ )
+ ) ;t
+
+ ) ;cond
+
+ ;;(message "w=%S" (window-end))
+ ;;(message "after=%S" web-mode-expand-previous-state)
+
+ ))
+
+(defun web-mode-block-kill ()
+ "Kill the current block."
+ (interactive)
+ (web-mode-block-select)
+ (when mark-active
+ (kill-region (region-beginning) (region-end))))
+
+(defun web-mode-block-select ()
+ "Select the current block."
+ (interactive)
+ (let (beg)
+ (when (setq beg (web-mode-block-beginning-position (point)))
+ (goto-char beg)
+ (set-mark (point))
+ (web-mode-block-end)
+ (exchange-point-and-mark))
+ beg))
+
+(defun web-mode-tag-select ()
+ "Select the current html tag."
+ (interactive)
+ (let (beg)
+ (when (setq beg (web-mode-tag-beginning-position (point)))
+ (goto-char beg)
+ (set-mark (point))
+ (web-mode-tag-end)
+ (exchange-point-and-mark))
+ beg))
+
+(defun web-mode-element-content-select ()
+ "Select the content of a html element."
+ (interactive)
+ (let (pos beg end)
+ (web-mode-element-select)
+ (when mark-active
+ (setq pos (point))
+ (deactivate-mark)
+ (web-mode-tag-match)
+ (setq end (point))
+ (goto-char pos)
+ (web-mode-tag-end)
+ (set-mark (point))
+ (goto-char end)
+ (exchange-point-and-mark)
+ )))
+
+(defun web-mode-element-select ()
+ "Select the current html element (including opening and closing tags)."
+ (interactive)
+ (let* ((pos (point))
+ (type (get-text-property pos 'tag-type)))
+ (cond
+ ((not type)
+ (web-mode-element-parent)
+ (unless (= (point) pos) (web-mode-element-select)))
+ ((member type '(start void))
+ (web-mode-tag-beginning)
+ (set-mark (point))
+ (web-mode-tag-match)
+ (web-mode-tag-end)
+ (exchange-point-and-mark))
+ (t
+ (web-mode-tag-match)
+ (set-mark (point))
+ (web-mode-tag-match)
+ (web-mode-tag-end)
+ (exchange-point-and-mark))
+ )))
+
+(defun web-mode-element-is-collapsed (&optional pos)
+ (unless pos (setq pos (point)))
+ (let (boundaries)
+ (and (setq boundaries (web-mode-element-boundaries pos))
+ (or (= (car (car boundaries)) (car (cdr boundaries)))
+ (= (cdr (car boundaries)) (1- (car (cdr boundaries)))))
+ )))
+
+(defun web-mode-element-contract ()
+ "Flatten elements."
+ (interactive)
+ (let (beg end (continue t) replacement boundaries)
+ (cond
+ ((or (not (get-text-property (point) 'tag-type))
+ (not (member (get-text-property (point) 'tag-type) '(start end))))
+ (web-mode-element-parent))
+ ((eq (get-text-property (point) 'tag-type) 'end)
+ (web-mode-tag-match))
+ ) ;cond
+ (setq boundaries (web-mode-element-boundaries (point)))
+ (setq beg (car (car boundaries))
+ end (cdr (cdr boundaries)))
+ (goto-char beg)
+ ;;(message "beg(%S) end(%S)" beg end)
+ (while continue
+ (if (or (not (re-search-forward ">[ \t\r\n]+\\|[ \t\r\n]+<"))
+ (>= (point) end))
+ (setq continue nil)
+ (setq end (+ (- end (length (match-string-no-properties 0))) 1))
+ (setq replacement (if (eq (char-before) ?\<) "<" ">"))
+ (replace-match replacement nil nil)
+ ;;(message "end(%S)" end))
+ )
+ ) ;while
+ (goto-char beg)
+ ))
+
+(defun web-mode-element-extract ()
+ "Flatten element."
+ (interactive)
+ (let (beg end (continue t) save boundaries)
+ (cond
+ ((or (not (get-text-property (point) 'tag-type))
+ (not (member (get-text-property (point) 'tag-type) '(start end))))
+ (web-mode-element-parent))
+ ((eq (get-text-property (point) 'tag-type) 'end)
+ (web-mode-tag-match))
+ ) ;cond
+ (setq boundaries (web-mode-element-boundaries (point)))
+ (setq beg (car (car boundaries))
+ end (cdr (cdr boundaries)))
+ (goto-char beg)
+ (while continue
+ (if (or (not (and (or (get-text-property (point) 'tag-type) (web-mode-tag-next))
+ (web-mode-tag-end)))
+ (>= (point) end))
+ (setq continue nil)
+ (setq save (point))
+ ;;(message "point(%S)" (point))
+ (skip-chars-forward "\n\t ")
+ (when (get-text-property (point) 'tag-type)
+ (newline)
+ (indent-according-to-mode)
+ (setq end (+ end (- (point) save))))
+ ) ;if
+ ) ;while
+ (goto-char beg)
+ ))
+
+(defun web-mode-element-transpose ()
+ "Transpose two html elements."
+ (interactive)
+ (let (pos start1 end1 start2 end2)
+ (save-excursion
+ (setq pos (point))
+ (cond
+ ((get-text-property pos 'tag-type)
+ (setq start1 (web-mode-element-beginning-position pos)
+ end1 (1+ (web-mode-element-end-position pos)))
+ )
+ ((setq start1 (web-mode-element-parent-position pos))
+ (setq end1 (1+ (web-mode-element-end-position pos)))
+ )
+ ) ;cond
+ (when (and start1 end1 (> end1 0))
+ (goto-char end1)
+ (unless (get-text-property (point) 'tag-beg)
+ (skip-chars-forward "\n\t "))
+ (when (get-text-property (point) 'tag-beg)
+ (setq start2 (web-mode-element-beginning-position (point))
+ end2 (1+ (web-mode-element-end-position (point))))
+ )
+ )
+ (transpose-regions start1 end1 start2 end2)
+ ) ;save-excursion
+ start2))
+
+(defun web-mode-element-children-comment (&optional pos)
+ "Comment all the children of the current html element."
+ (interactive)
+ (unless pos (setq pos (point)))
+ (save-excursion
+ (dolist (child (reverse (web-mode-element-children pos)))
+ (goto-char child)
+ (web-mode-comment (point)))
+ ))
+
+(defun web-mode-element-mute-blanks ()
+ "Mute blanks."
+ (interactive)
+ (let (pos parent beg end children elt)
+ (setq pos (point))
+ (save-excursion
+ (when (and (setq parent (web-mode-element-boundaries pos))
+ (web-mode-element-child-position (point)))
+ (setq children (reverse (web-mode-element-children)))
+ (goto-char (car (cdr parent)))
+ (dolist (child children)
+ (setq elt (web-mode-element-boundaries child))
+ (when (> (point) (1+ (cddr elt)))
+ (when (and (not (eq (get-text-property (point) 'part-token) 'comment))
+ (not (eq (get-text-property (1+ (cddr elt)) 'part-token) 'comment)))
+ (web-mode-insert-text-at-pos "-->" (point))
+ (web-mode-insert-text-at-pos "<!--" (1+ (cddr elt))))
+ )
+ (goto-char child)
+ )
+ (when (and (> (point) (1+ (cdr (car parent))))
+ (not (eq (get-text-property (point) 'part-token) 'comment))
+ (not (eq (get-text-property (1+ (cdr (car parent))) 'part-token) 'comment)))
+ (web-mode-insert-text-at-pos "-->" (point))
+ (web-mode-insert-text-at-pos "<!--" (1+ (cdr (car parent)))))
+ ) ;when
+ )))
+
+(defun web-mode-element-children (&optional pos)
+ (unless pos (setq pos (point)))
+ (let ((continue t) (i 0) child children)
+ (save-excursion
+ (when (and (member (get-text-property pos 'tag-type) '(start end))
+ (setq child (web-mode-element-child-position pos)))
+ (while continue
+ (cond
+ ((> (setq i (1+ i)) 100)
+ (setq continue nil)
+ (message "element-children ** warning **"))
+ ((= i 1)
+ (goto-char child))
+ ((web-mode-element-sibling-next)
+ )
+ (t
+ (setq continue nil))
+ ) ;cond
+ (when continue
+ (setq children (append children (list (point)))))
+ ) ;while
+ ) ;when
+ ) ;save-excursion
+ ;;(message "%S" children)
+ children))
+
+(defun web-mode-property-boundaries (prop &optional pos)
+ "property boundaries (cdr is 1+)"
+ (unless pos (setq pos (point)))
+ (let (beg end val)
+ (setq val (get-text-property pos prop))
+ (if (null val)
+ val
+ (if (or (bobp)
+ (not (eq (get-text-property (1- pos) prop) val)))
+ (setq beg pos)
+ (setq beg (previous-single-property-change pos prop))
+ (when (null beg) (setq beg (point-min))))
+ (if (or (eobp)
+ (not (eq (get-text-property (1+ pos) prop) val)))
+ (setq end pos)
+ (setq end (next-single-property-change pos prop))
+ (when (null end) (setq end (point-min))))
+ (cons beg end))))
+
+(defun web-mode-content-boundaries (&optional pos)
+ (unless pos (setq pos (point)))
+ (let (beg end)
+ (setq beg (or (previous-property-change pos (current-buffer))
+ (point-max)))
+ (setq end (or (next-property-change pos (current-buffer))
+ (point-min)))
+ (while (and (< beg end) (member (char-after beg) '(?\s ?\n)))
+ (setq beg (1+ beg)))
+ (while (and (> end beg) (member (char-after (1- end)) '(?\s ?\n)))
+ (setq end (1- end)))
+;; (message "beg(%S) end(%S)" beg end)
+ (cons beg end)
+ ))
+
+(defun web-mode-element-boundaries (&optional pos)
+ "Return ((start-tag-beg . start-tag-end) . (end-tag-beg . end-tag-end))
+First level car and cdr are the same with void elements.
+Pos should be in a tag."
+ (unless pos (setq pos (point)))
+ (let (start-tag-beg start-tag-end end-tag-beg end-tag-end)
+ (cond
+ ((eq (get-text-property pos 'tag-type) 'start)
+ (setq start-tag-beg (web-mode-tag-beginning-position pos)
+ start-tag-end (web-mode-tag-end-position pos))
+ (when (setq pos (web-mode-tag-match-position pos))
+ (setq end-tag-beg pos
+ end-tag-end (web-mode-tag-end-position pos)))
+ )
+ ((eq (get-text-property pos 'tag-type) 'end)
+ (setq end-tag-beg (web-mode-tag-beginning-position pos)
+ end-tag-end (web-mode-tag-end-position pos))
+ (when (setq pos (web-mode-tag-match-position pos))
+ (setq start-tag-beg pos
+ start-tag-end (web-mode-tag-end-position pos)))
+ )
+ ((eq (get-text-property pos 'tag-type) 'void)
+ (setq start-tag-beg (web-mode-tag-beginning-position pos)
+ start-tag-end (web-mode-tag-end-position pos))
+ (setq end-tag-beg start-tag-beg
+ end-tag-end start-tag-end)
+ )
+ ) ;cond
+ (if (and start-tag-beg start-tag-end end-tag-beg end-tag-end)
+ (cons (cons start-tag-beg start-tag-end) (cons end-tag-beg end-tag-end))
+ nil)
+ ))
+
+(defun web-mode-surround ()
+ "Surround each line of the current REGION with a start/end tag."
+ (interactive)
+ (when mark-active
+ (let (beg end line-beg line-end pos tag tag-start tag-end)
+ (save-excursion
+ (combine-after-change-calls
+ (setq tag (read-from-minibuffer "Tag name? ")
+ tag-start (concat "<" tag ">")
+ tag-end (concat "</" tag ">")
+ pos (point)
+ beg (region-beginning)
+ end (region-end)
+ line-beg (web-mode-line-number beg)
+ line-end (web-mode-line-number end))
+ (goto-char end)
+ (unless (bolp)
+ (insert tag-end)
+ (back-to-indentation)
+ (when (> beg (point))
+ (goto-char beg))
+ (insert tag-start))
+ (while (> line-end line-beg)
+ (forward-line -1)
+ (setq line-end (1- line-end))
+ (unless (looking-at-p "[[:space:]]*$")
+ (end-of-line)
+ (insert tag-end)
+ (back-to-indentation)
+ (when (> beg (point))
+ (goto-char beg))
+ (insert tag-start))
+ ) ;while
+ (deactivate-mark)
+ ) ;combine-after-change-calls
+ ) ;save-excursion
+ )))
+
+(defun web-mode-lify-region ()
+ "Transform current REGION in an html list (<li>line1</li>...)"
+ (interactive)
+ (let (beg end lines)
+ (save-excursion
+ (combine-after-change-calls
+ (when mark-active
+ (setq beg (region-beginning)
+ end (region-end))
+ (setq lines (buffer-substring beg end))
+ (kill-region beg end)
+ (setq lines (replace-regexp-in-string "^[ \t]*" "<li>" lines))
+ (setq lines (replace-regexp-in-string "$" "</li>" lines))
+ (web-mode-insert-and-indent lines)
+ ) ;when
+ ) ;combine-after-change-calls
+ ) ;save-excursion
+ ) ;let
+ )
+
+(defun web-mode-element-wrap (&optional tag-name)
+ "Wrap current REGION with start and end tags.
+Prompt user if TAG-NAME isn't provided."
+ (interactive)
+ (let (beg end pos tag sep)
+ (save-excursion
+ (setq tag (or tag-name (read-from-minibuffer "Tag name? ")))
+ (setq pos (point))
+ (cond
+ (mark-active
+ (setq beg (region-beginning)
+ end (region-end)))
+ ((get-text-property pos 'tag-type)
+ (setq beg (web-mode-element-beginning-position pos)
+ end (1+ (web-mode-element-end-position pos))))
+ ((setq beg (web-mode-element-parent-position pos))
+ (setq end (1+ (web-mode-element-end-position pos))))
+ )
+ ;; (message "beg(%S) end(%S)" beg end)
+ (when (and beg end (> end 0))
+ (setq sep (if (get-text-property beg 'tag-beg) "\n" ""))
+ (web-mode-insert-text-at-pos (concat sep "</" tag ">") end)
+ (web-mode-insert-text-at-pos (concat "<" tag ">" sep) beg)
+ (when (string= sep "\n") (indent-region beg (+ end (* (+ 3 (length tag)) 2))))
+ )
+ ) ;save-excursion
+ (web-mode-go beg)))
+
+(defun web-mode-element-vanish (&optional arg)
+ "Vanish the current html element. The content of the element is kept."
+ (interactive "p")
+ (let (type (pos (point)) start-b start-e end-b end-e)
+ (while (>= arg 1)
+ (setq type (get-text-property pos 'tag-type))
+ (when type
+ (cond
+ ((member type '(void))
+ (web-mode-element-kill)
+ (set-mark (point))
+ (web-mode-tag-match)
+ (web-mode-tag-end)
+ (exchange-point-and-mark))
+ ((member type '(start))
+ (setq start-b (web-mode-tag-beginning-position)
+ start-e (web-mode-tag-end-position))
+ (when (web-mode-tag-match)
+ (setq end-b (web-mode-tag-beginning-position)
+ end-e (web-mode-tag-end-position)))
+ )
+ (t
+ (setq end-b (web-mode-tag-beginning-position)
+ end-e (web-mode-tag-end-position))
+ (when (web-mode-tag-match)
+ (setq start-b (web-mode-tag-beginning-position)
+ start-e (web-mode-tag-end-position)))
+ ) ;t
+ ) ;cond
+ (when (and start-b end-b)
+ (goto-char end-b)
+ (delete-region end-b (1+ end-e))
+ (delete-blank-lines)
+ (goto-char start-b)
+ (delete-region start-b (1+ start-e))
+ (delete-blank-lines)
+ (web-mode-buffer-indent)
+ )
+ ;; (message "start %S %S - end %S %S" start-b start-e end-b end-e))
+ ) ;when
+ (skip-chars-forward "[:space:]\n")
+ (setq arg (1- arg))
+ ) ;while
+ ) ;let
+ )
+
+(defun web-mode-element-kill (&optional arg)
+ "Kill the current html element."
+ (interactive "p")
+ (while (>= arg 1)
+ (setq arg (1- arg))
+ (web-mode-element-select)
+ (when mark-active
+ (kill-region (region-beginning) (region-end)))
+ ) ;while
+ )
+
+(defun web-mode-element-clone (&optional arg)
+ "Clone the current html element."
+ (interactive "p")
+ (let (col pos)
+ (while (>= arg 1)
+ (setq arg (1- arg)
+ col 0)
+ (web-mode-element-select)
+ (when mark-active
+ (save-excursion
+ (goto-char (region-beginning))
+ (setq col (current-column)))
+ (kill-region (region-beginning) (region-end))
+ (yank)
+ (newline)
+ (indent-line-to col)
+ (setq pos (point))
+ (yank)
+ (goto-char pos))
+ )
+ ) ;let
+ )
+
+(defun web-mode-element-insert ()
+ "Insert an html element."
+ (interactive)
+ (let (tag-name)
+ (cond
+ ((and (get-text-property (point) 'tag-type)
+ (not (get-text-property (point) 'tag-beg)))
+ (message "element-insert ** invalid context **"))
+ ((not (and (setq tag-name (read-from-minibuffer "Tag name? "))
+ (> (length tag-name) 0)))
+ (message "element-insert ** failure **"))
+ ((web-mode-element-is-void tag-name)
+ (insert (concat "<" (replace-regexp-in-string "/" "" tag-name) "/>"))
+ )
+ (mark-active
+ (let ((beg (region-beginning)) (end (region-end)))
+ (deactivate-mark)
+ (goto-char end)
+ (insert "</" tag-name ">")
+ (goto-char beg)
+ (insert "<" tag-name ">")
+ )
+ )
+ (t
+ (insert (concat "<" tag-name ">" "</" tag-name ">"))
+ (web-mode-sb "</")
+ )
+ ) ;cond
+ ))
+
+(defun web-mode-element-insert-at-point ()
+ "Replace the word at point with a html tag of it."
+ (interactive)
+ (let ((tag-name (thing-at-point 'word)))
+ (cond
+ ((web-mode-element-is-void tag-name)
+ (backward-kill-word 1)
+ (insert (concat "<" (replace-regexp-in-string "/" "" tag-name) "/>"))
+ )
+ (mark-active
+ (setq tag-name (buffer-substring (region-beginning) (region-end)))
+ (delete-region (region-beginning) (region-end))
+ (insert (concat "<" tag-name ">" "</" tag-name ">"))
+ (web-mode-sb "</")
+ )
+ (tag-name ; do nothing is there isn's word at point
+ (backward-kill-word 1)
+ (insert (concat "<" tag-name ">" "</" tag-name ">"))
+ (web-mode-sb "</")
+ )
+ ) ;cond
+ ))
+
+(defun web-mode-element-rename (&optional tag-name)
+ "Rename the current html element."
+ (interactive)
+ (save-excursion
+ (let (pos)
+ (unless tag-name (setq tag-name (read-from-minibuffer "New tag name? ")))
+ (when (and (> (length tag-name) 0)
+ (web-mode-element-beginning)
+ (looking-at "<\\([[:alnum:]]+\\(:?[[:alpha:]_-]+\\)?\\)"))
+ (setq pos (point))
+ (unless (web-mode-element-is-void)
+ (save-match-data
+ (web-mode-tag-match)
+ (if (looking-at "</[ ]*\\([[:alnum:]]+\\(:?[[:alpha:]_-]+\\)?\\)")
+ (replace-match (concat "</" tag-name))
+ )))
+ (goto-char pos)
+ (replace-match (concat "<" tag-name))
+ ))))
+
+(defun web-mode-current-trimmed-line ()
+ (web-mode-trim (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position))))
+
+(defun web-mode-trim (string)
+ (replace-regexp-in-string "\\`[ \t\n]*" "" (replace-regexp-in-string "[ \t\n]*\\'" "" string)))
+
+(defun web-mode-is-token-end (pos)
+ (let (block-token part-token)
+ (setq block-token (get-text-property pos 'block-token))
+ (setq part-token (get-text-property pos 'part-token))
+ (cond
+ ((not (or block-token part-token))
+ nil)
+ ((>= (1+ pos) (point-max))
+ t)
+ ((and block-token
+ (not (string= (get-text-property (1+ pos) 'block-token) block-token)))
+ t)
+ ((and part-token
+ (not (string= (get-text-property (1+ pos) 'part-token) part-token)))
+ t)
+ (t
+ nil)
+ ) ;cond
+ ))
+
+(defun web-mode-block-is-token-line ()
+ (save-excursion
+ (let ((continue t) (counter 0))
+ (beginning-of-line)
+ (back-to-indentation)
+ (while (and continue (not (eolp)))
+ (cond
+ ((get-text-property (point) 'block-token)
+ (setq counter (1+ counter)))
+ ((not (member (following-char) '(?\s ?\t)))
+ (setq continue nil
+ counter 0))
+ ) ;cond
+ (forward-char)
+ ) ;while
+ (> counter 0)
+ )))
+
+(defun web-mode-part-is-token-line (pos)
+ (save-excursion
+ (let ((continue t)
+ (counter 0))
+ (goto-char pos)
+ (setq continue (not (eolp)))
+ (while continue
+ (forward-char)
+ (cond
+ ((eolp)
+ (setq continue nil))
+ ((or (get-text-property (point) 'block-side)
+ (member (get-text-property (point) 'part-token) '(comment string)))
+ (setq counter (1+ counter)))
+ ((not (member (following-char) '(?\s ?\t)))
+ (setq continue nil
+ counter 0))
+ )
+ ) ;while
+ (> counter 0))))
+
+(defun web-mode-is-content (&optional pos)
+ (unless pos (setq pos (point)))
+ (not (or (get-text-property pos 'part-side)
+ (get-text-property pos 'tag-type)
+ (get-text-property pos 'block-side)
+ )))
+
+(defun web-mode-is-comment-or-string (&optional pos)
+ (unless pos (setq pos (point)))
+ (not (null (or (eq (get-text-property pos 'tag-type) 'comment)
+ (member (get-text-property pos 'block-token) '(comment string))
+ (member (get-text-property pos 'part-token) '(comment string))))))
+
+;; NOTE: we look at the firt one
+(defun web-mode-block-is-open (&optional pos)
+ (unless pos (setq pos (point))))
+
+;; NOTE: we look at the last one
+(defun web-mode-block-is-close (&optional pos)
+ (unless pos (setq pos (point)))
+ (and (get-text-property pos 'block-side)
+ (eq (caar (web-mode-block-controls-get pos)) 'close)))
+
+;; NOTE: we look at the first one
+(defun web-mode-block-is-inside (&optional pos)
+ (unless pos (setq pos (point)))
+ (and (get-text-property pos 'block-side)
+ (eq (caar (web-mode-block-controls-get pos)) 'inside)))
+
+(defun web-mode-element-is-void (&optional tag)
+ (cond
+ ((and (not tag) (eq (get-text-property (point) 'tag-type) 'void))
+ t)
+ ((and tag (member tag '("div" "li" "a" "p" "h1" "h2" "h3" "ul" "span" "article" "section" "td" "tr")))
+ nil)
+ ((and tag (string-suffix-p "/" tag))
+ t)
+ ((and tag (string= web-mode-content-type "jsx"))
+ (member (downcase tag) '("img" "br" "hr")))
+ (tag
+ (car (member (downcase tag) web-mode-void-elements)))
+ (t
+ nil)
+ ))
+
+;;---- COMMENT ------------------------------------------------------------------
+
+(defun web-mode-toggle-comments ()
+ "Toggle comments visbility."
+ (interactive)
+ (web-mode-with-silent-modifications
+ (save-excursion
+ (if web-mode-comments-invisible
+ (remove-overlays))
+ (setq web-mode-comments-invisible (null web-mode-comments-invisible))
+ (let ((continue t)
+ (pos (point-min))
+ (visibility web-mode-comments-invisible)
+ overlay end)
+ (while continue
+ (setq pos (next-single-property-change pos 'font-lock-face))
+ (if (null pos)
+ (setq continue nil)
+ (when (eq (get-text-property pos 'font-lock-face) 'web-mode-comment-face)
+ (setq end (next-single-property-change pos 'font-lock-face))
+ (put-text-property pos end 'invisible visibility)
+ (when visibility
+ (setq overlay (make-overlay pos end)))
+ (goto-char pos)
+ )
+ )
+ )
+ ) ;let
+ )))
+
+(defun web-mode-comment-or-uncomment-region (beg end &optional arg)
+ (interactive)
+ (save-excursion
+ (push-mark end)
+ (goto-char beg)
+ (setq mark-active t)
+ (web-mode-comment-or-uncomment)
+ (pop-mark)))
+
+(defun web-mode-comment-or-uncomment ()
+ "Comment or uncomment line(s), block or region at POS."
+ (interactive)
+ ;; TODO : if mark is at eol, mark--
+ (if (and (not mark-active) (looking-at-p "[[:space:]]*$"))
+ (web-mode-comment-insert)
+ (when (and (use-region-p) (eq (point) (region-end)))
+ (if (bolp) (backward-char))
+ (exchange-point-and-mark))
+ (if (eq (get-text-property (point) 'block-token) 'delimiter-beg)
+ (web-mode-block-skip-blank-forward (point) '(delimiter-beg))
+ (skip-chars-forward "[:space:]" (line-end-position)))
+ (cond
+ ;; #1147
+ ((and (get-text-property (point) 'jsx-beg)
+ (eq (get-text-property (1+ (point)) 'part-token) 'comment))
+ (web-mode-uncomment (1+ (point))))
+ ((or (eq (get-text-property (point) 'tag-type) 'comment)
+ (eq (get-text-property (point) 'block-token) 'comment)
+ (eq (get-text-property (point) 'part-token) 'comment))
+ (web-mode-uncomment (point)))
+ (t
+ (web-mode-comment (point)))
+ )
+ ) ;if
+ )
+
+(defun web-mode-comment-indent-new-line (&optional soft)
+ (interactive)
+ (let (ctx)
+ (setq ctx (web-mode-comment-context))
+ (cond
+ ((null ctx)
+ (newline 1))
+ (t
+ (newline 1)
+ (indent-line-to (plist-get ctx :col))
+ (insert (concat (plist-get ctx :prefix) "")))
+ ) ;cond
+ ))
+
+(defun web-mode-comment-context (&optional pos)
+ (cond
+ (pos
+ )
+ ((and (eolp) (not (bobp)))
+ (setq pos (1- (point))))
+ (t
+ (setq pos (point)))
+ ) ;cond
+ (let (beg col prefix type format)
+ (cond
+ ((eq (get-text-property pos 'block-token) 'comment)
+ (setq type "block"))
+ ((eq (get-text-property pos 'tag-type) 'comment)
+ (setq type "tag"))
+ ((eq (get-text-property pos 'part-token) 'comment)
+ (setq type "part"))
+ )
+ (if (null type) nil
+ (save-excursion
+ (goto-char pos)
+ (web-mode-comment-beginning)
+ (setq beg (point)
+ col (current-column))
+ (cond
+ ((looking-at-p "/\\*")
+ (setq format "/*"
+ prefix " * "))
+ ((looking-at-p "//")
+ (setq format "//"
+ prefix "//"))
+ ((looking-at-p "#")
+ (setq format "#"
+ prefix "#"))
+ ((looking-at-p ";")
+ (setq format ";"
+ prefix ";"))
+ ((looking-at-p "''")
+ (setq format "''"
+ prefix "''"))
+ ) ;cond
+ (list :beg beg :col col :prefix prefix :type type :format format)))))
+
+(defun web-mode-comment-insert ()
+ (let ((alt nil) (language nil) (pos (point)))
+ (setq language (web-mode-language-at-pos pos))
+ (setq alt (cdr (assoc language web-mode-comment-formats)))
+ ;;(message "language=%S" language)
+ (cond
+ ((get-text-property pos 'block-side)
+ (cond
+ ((and alt (string= alt "//"))
+ (insert "// "))
+ (t
+ (insert "/* */")
+ (search-backward " */"))
+ ) ;cond
+ ) ;case block-side
+ ((get-text-property pos 'part-side)
+ (cond
+ ((and alt (string= alt "//"))
+ (insert "// "))
+ (t
+ (insert "/* */")
+ (search-backward " */"))
+ ) ;cond
+ ) ;case part-side
+ (t
+ (insert "<!-- -->")
+ (search-backward " -->")
+ ) ;case html
+ ) ;cond
+ ))
+
+(defun web-mode-comment (pos)
+ (let (ctx language col sel beg end tmp block-side single-line-block pos-after content)
+
+ (setq pos-after pos)
+
+ (setq block-side (get-text-property pos 'block-side))
+ (setq single-line-block (web-mode-is-single-line-block pos))
+
+ (cond
+
+ ((and block-side (string= web-mode-engine "erb"))
+ (web-mode-comment-erb-block pos)
+ )
+
+ ((and block-side (string= web-mode-engine "artanis"))
+ (web-mode-comment-artanis-block pos)
+ )
+
+ ((and single-line-block block-side
+ (intern-soft (concat "web-mode-comment-" web-mode-engine "-block")))
+ (funcall (intern (concat "web-mode-comment-" web-mode-engine "-block")) pos)
+ )
+
+ (t
+ (setq ctx (web-mode-point-context
+ (if mark-active (region-beginning) (line-beginning-position))))
+ ;;(message "%S" ctx)
+ (setq language (plist-get ctx :language))
+ (setq col (current-column))
+ (cond
+ (mark-active
+ ;;(message "%S %S" (point) col)
+ )
+ ((and (member language '("html" "xml"))
+ (get-text-property (progn (back-to-indentation) (point)) 'tag-beg))
+ (web-mode-element-select))
+ (t
+ (end-of-line)
+ (set-mark (line-beginning-position)))
+ ) ;cond
+
+ (setq beg (region-beginning)
+ end (region-end))
+
+ (when (> (point) (mark))
+ (exchange-point-and-mark))
+
+ (if (and (eq (char-before end) ?\n)
+ (not (eq (char-after end) ?\n)))
+ (setq end (1- end)))
+
+ (setq sel (buffer-substring-no-properties beg end))
+
+ (cond
+
+ ((member language '("html" "xml"))
+ (cond
+ ((and (= web-mode-comment-style 2) (string= web-mode-engine "django"))
+ (setq content (concat "{# " sel " #}")))
+ ((and (= web-mode-comment-style 2) (member web-mode-engine '("ejs" "erb")))
+ (setq content (concat "<%# " sel " %>")))
+ ((and (= web-mode-comment-style 2) (string= web-mode-engine "artanis"))
+ (setq content (concat "<%; " sel " %>")))
+ ((and (= web-mode-comment-style 2) (string= web-mode-engine "aspx"))
+ (setq content (concat "<%-- " sel " --%>")))
+ ((and (= web-mode-comment-style 2) (string= web-mode-engine "smarty"))
+ (setq content (concat "{* " sel " *}")))
+ ((and (= web-mode-comment-style 2) (string= web-mode-engine "expressionengine"))
+ (setq content (concat "{!-- " sel " --}")))
+ ((and (= web-mode-comment-style 2) (string= web-mode-engine "xoops"))
+ (setq content (concat "<{* " sel " *}>")))
+ ((and (= web-mode-comment-style 2) (string= web-mode-engine "hero"))
+ (setq content (concat "<%# " sel " %>")))
+ ((and (= web-mode-comment-style 2) (string= web-mode-engine "blade"))
+ (setq content (concat "{{-- " sel " --}}")))
+ ((and (= web-mode-comment-style 2) (string= web-mode-engine "ctemplate"))
+ (setq content (concat "{{!-- " sel " --}}")))
+ ((and (= web-mode-comment-style 2) (string= web-mode-engine "razor"))
+ (setq content (concat "@* " sel " *@")))
+ (t
+ (setq content (concat "<!-- " sel " -->"))
+ (when (< (length sel) 1)
+ (search-backward " -->")
+ (setq pos-after nil))
+ ))
+ ) ;case html
+
+ ((member language '("php" "javascript" "typescript" "java" "jsx"))
+ (let (alt)
+ (setq alt (cdr (assoc language web-mode-comment-formats)))
+ ;;(message "language=%S alt=%S sel=%S col=%S" language alt sel col)
+ (cond
+ ((and alt (string= alt "//"))
+ (setq content (replace-regexp-in-string (concat "\n[ ]\\{" (number-to-string col) "\\}") "\n" sel))
+ (setq content (replace-regexp-in-string (concat "\n") "\n// " content))
+ (setq content (concat "// " content)))
+ ((get-text-property pos 'jsx-depth)
+ (setq content (concat "{/* " sel " */}")))
+ (web-mode-comment-prefixing
+ (setq content (replace-regexp-in-string (concat "\n[ ]\\{" (number-to-string col) "\\}") "\n* " sel))
+ (setq content (concat "/* " content " */")))
+ (t
+ (setq content (concat "/* " sel " */")))
+ ) ;cond
+ ) ;let
+ )
+
+ ((member language '("erb"))
+ (setq content (replace-regexp-in-string "^[ ]*" "#" sel)))
+
+ ((member language '("asp"))
+ (setq content (replace-regexp-in-string "^[ ]*" "''" sel)))
+
+ (t
+ (setq content (concat "/* " sel " */")))
+
+ ) ;cond
+
+ (when content
+ (delete-region beg end)
+ (deactivate-mark)
+ (let (beg end)
+ (setq beg (point-at-bol))
+ (insert content)
+ (setq end (point-at-eol))
+ (indent-region beg end)
+ )
+ ) ;when
+
+ ) ;t
+ ) ;cond
+
+ (when pos-after (goto-char pos-after))
+
+ ))
+
+(defun web-mode-comment-ejs-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-insert-text-at-pos "//" (+ beg 2))))
+
+(defun web-mode-comment-erb-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-insert-text-at-pos "#" (+ beg 2))))
+
+(defun web-mode-comment-artanis-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-insert-text-at-pos ";" (+ beg 2))))
+
+(defun web-mode-comment-django-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-insert-text-at-pos "#" end)
+ (web-mode-insert-text-at-pos "#" (1+ beg))))
+
+(defun web-mode-comment-dust-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-insert-text-at-pos "!" end)
+ (web-mode-insert-text-at-pos "!" (1+ beg))))
+
+(defun web-mode-comment-aspx-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-insert-text-at-pos "#" end)
+ (web-mode-insert-text-at-pos "#" (1+ beg))))
+
+(defun web-mode-comment-jsp-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-insert-text-at-pos "--" (+ beg 2))))
+
+(defun web-mode-comment-go-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-insert-text-at-pos "*/" (1- end))
+ (web-mode-insert-text-at-pos "/*" (+ beg (if (web-mode-looking-at "{{" beg) 2 0)))))
+
+(defun web-mode-comment-php-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-insert-text-at-pos "*/" (- end 2))
+ (web-mode-insert-text-at-pos "/*" (+ beg 1 (if (web-mode-looking-at "<\\?php" beg) 5 3)))))
+
+(defun web-mode-comment-svelte-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-insert-text-at-pos "!" end)
+ (web-mode-insert-text-at-pos "!" (1+ beg))))
+
+(defun web-mode-comment-boundaries (&optional pos)
+ (interactive)
+ (unless pos (setq pos (point)))
+ (let ((beg pos) (end pos) prop)
+ (save-excursion
+ (goto-char pos)
+ (setq prop
+ (cond
+ ((eq (get-text-property pos 'block-token) 'comment) 'block-token)
+ ((eq (get-text-property pos 'tag-type) 'comment) 'tag-type)
+ ((eq (get-text-property pos 'part-token) 'comment) 'part-token)
+ (t nil)
+ ))
+ (if (null prop)
+ (setq beg nil
+ end nil)
+ (when (and (not (bobp))
+ (eq (get-text-property pos prop) (get-text-property (1- pos) prop)))
+ (setq beg (or (previous-single-property-change pos prop) (point-min))))
+ (when (and (not (eobp))
+ (eq (get-text-property pos prop) (get-text-property (1+ pos) prop)))
+ (setq end (or (next-single-property-change pos prop) (point-max)))))
+ (message "beg(%S) end(%S) point-max(%S)" beg end (point-max))
+ (when (and beg (string= (buffer-substring-no-properties beg (+ beg 2)) "//"))
+ (goto-char end)
+ (while (and (looking-at-p "\n[ ]*//")
+ (not (eobp)))
+ (search-forward "//")
+ (backward-char 2)
+ ;;(message "%S" (point))
+ (setq end (next-single-property-change (point) prop))
+ (goto-char end)
+ ;;(message "%S" (point))
+ ) ;while
+ ) ;when
+ ;;(when end (setq end (1- end))) ;; #1021
+ ) ;save-excursion
+ ;;(message "beg=%S end=%S" beg end)
+ (if (and beg end) (cons beg end) nil)
+ ))
+
+(defun web-mode-uncomment (pos)
+ (let ((beg pos) (end pos) (sub2 "") comment boundaries)
+ (save-excursion
+ (cond
+ ((and (get-text-property pos 'block-side)
+ (intern-soft (concat "web-mode-uncomment-" web-mode-engine "-block")))
+ (funcall (intern (concat "web-mode-uncomment-" web-mode-engine "-block")) pos))
+ ((and (setq boundaries (web-mode-comment-boundaries pos))
+ (setq beg (car boundaries))
+ (setq end (1+ (cdr boundaries)))
+ (> (- end beg) 4))
+ (when (and (eq (get-text-property beg 'part-token) 'comment)
+ (> beg 1) ;#1158
+ (get-text-property (1- beg) 'jsx-beg))
+ (setq beg (1- beg)
+ end (1+ end)))
+ (setq comment (buffer-substring-no-properties beg end))
+ (setq sub2 (substring comment 0 2))
+ (cond
+ ((member sub2 '("<!" "<%"))
+ (setq comment (replace-regexp-in-string "\\(^<[!%]--[ ]?\\|[ ]?--[%]?>$\\)" "" comment)))
+ ((string= sub2 "{#")
+ (setq comment (replace-regexp-in-string "\\(^{#[ ]?\\|[ ]?#}$\\)" "" comment)))
+ ((string= sub2 "{/") ;jsx comments
+ (setq comment (replace-regexp-in-string "\\(^{/\\*[ ]?\\|[ ]?\\*/}$\\)" "" comment)))
+ ((string= sub2 "/*")
+ ;;(message "%S" comment)
+ ;;(setq comment (replace-regexp-in-string "\\(\\*/\\|^/\\*[ ]?\\|^[ \t]*\\*\\)" "" comment))
+ (setq comment (replace-regexp-in-string "\\([ ]?\\*/$\\|^/\\*[ ]?\\)" "" comment))
+ (setq comment (replace-regexp-in-string "\\(^[ \t]*\\*\\)" "" comment))
+ ;;(message "%S" comment)
+ )
+ ((string= sub2 "''")
+ (setq comment (replace-regexp-in-string "''" "" comment)))
+ ((string= sub2 "//")
+ (setq comment (replace-regexp-in-string "^ *//" "" comment)))
+ ) ;cond
+ (delete-region beg end)
+ (web-mode-insert-and-indent comment)
+ (goto-char beg)
+ )
+ ) ;cond
+ (indent-according-to-mode)
+ )))
+
+(defun web-mode-uncomment-erb-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (cond
+ ((string= (buffer-substring-no-properties beg (+ beg 4)) "<%#=")
+ (web-mode-remove-text-at-pos 1 (+ beg 2)))
+ ((string-match-p "<[%[:alpha:]]" (buffer-substring-no-properties (+ beg 2) (- end 2)))
+ (web-mode-remove-text-at-pos 2 (1- end))
+ (web-mode-remove-text-at-pos 3 beg))
+ (t
+ (web-mode-remove-text-at-pos 1 (+ beg 2)))
+ ) ;cond
+ )
+ )
+
+(defun web-mode-uncomment-artanis-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (cond
+ ((string= (buffer-substring-no-properties beg (+ beg 4)) "<%;=")
+ (web-mode-remove-text-at-pos 1 (+ beg 2)))
+ ((string-match-p "<[%[:alpha:]]" (buffer-substring-no-properties (+ beg 2) (- end 2)))
+ (web-mode-remove-text-at-pos 2 (1- end))
+ (web-mode-remove-text-at-pos 3 beg))
+ (t
+ (web-mode-remove-text-at-pos 1 (+ beg 2)))
+ ) ;cond
+ )
+ )
+
+(defun web-mode-uncomment-ejs-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-remove-text-at-pos 1 (+ beg 2))))
+
+(defun web-mode-uncomment-django-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (cond
+ ((web-mode-looking-at-p "{#[{%]" beg)
+ (web-mode-remove-text-at-pos 1 (1- end))
+ (web-mode-remove-text-at-pos 1 (1+ beg))
+ )
+ (t
+ (web-mode-remove-text-at-pos 2 (1- end))
+ (web-mode-remove-text-at-pos 2 beg))
+ ) ;cond
+ ))
+
+(defun web-mode-uncomment-ctemplate-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-remove-text-at-pos 5 (- end 4))
+ (web-mode-remove-text-at-pos 5 beg)))
+
+(defun web-mode-uncomment-dust-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-remove-text-at-pos 1 (1- end))
+ (web-mode-remove-text-at-pos 1 (1+ beg))))
+
+(defun web-mode-uncomment-aspx-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-remove-text-at-pos 1 (1- end))
+ (web-mode-remove-text-at-pos 1 (1+ beg))))
+
+(defun web-mode-uncomment-jsp-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-remove-text-at-pos 2 (+ beg 2))))
+
+(defun web-mode-uncomment-go-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-remove-text-at-pos 2 (+ beg 2))
+ (web-mode-remove-text-at-pos 2 (- end 5))))
+
+(defun web-mode-uncomment-svelte-block (pos)
+ (let (beg end)
+ (setq beg (web-mode-block-beginning-position pos)
+ end (web-mode-block-end-position pos))
+ (web-mode-remove-text-at-pos 1 (1- end))
+ (web-mode-remove-text-at-pos 1 (1+ beg))))
+
+(defun web-mode-snippet-names ()
+ (mapcar #'car web-mode-snippets))
+
+(defun web-mode-snippet-insert (code)
+ "Insert a snippet."
+ (interactive
+ (list (completing-read "Snippet: " (web-mode-snippet-names))))
+ (let (beg
+ (continue t)
+ (counter 0)
+ end
+ sel
+ snippet
+ (l (length web-mode-snippets))
+ pos)
+ (when mark-active
+ (setq sel (web-mode-trim (buffer-substring-no-properties
+ (region-beginning) (region-end))))
+ (delete-region (region-beginning) (region-end)))
+ (while (and continue (< counter l))
+ (setq snippet (nth counter web-mode-snippets))
+ (when (string= (car snippet) code)
+ (setq continue nil))
+ (setq counter (1+ counter)))
+ (when snippet
+ (setq snippet (cdr snippet))
+ (setq beg (point-at-bol))
+ (insert snippet)
+ (setq pos (point)
+ end (point))
+ (cond
+ ((string-match-p "¦" snippet)
+ (search-backward "¦")
+ (delete-char 1)
+ (setq pos (point)
+ end (1- end)))
+ ((string-match-p "|" snippet)
+ (search-backward "|")
+ (delete-char 1)
+ (setq pos (point)
+ end (1- end)))
+ ) ;cond
+ (when sel
+ (insert sel)
+ (setq pos (point)
+ end (+ end (length sel))))
+ (goto-char end)
+ (setq end (point-at-eol))
+ (unless sel (goto-char pos))
+ (indent-region beg end))
+ ))
+
+(defun web-mode-looking-at (regexp pos)
+ (save-excursion
+ (goto-char pos)
+ (looking-at regexp)))
+
+(defun web-mode-looking-at-p (regexp pos)
+ (save-excursion
+ (goto-char pos)
+ (looking-at-p regexp)))
+
+(defun web-mode-looking-back (regexp pos &optional limit greedy)
+ (save-excursion
+ (goto-char pos)
+ (if limit
+ (looking-back regexp limit greedy)
+ (looking-back regexp (point-min)))))
+
+(defun web-mode-insert-text-at-pos (text pos)
+ (let ((mem web-mode-enable-auto-pairing))
+ (setq web-mode-enable-auto-pairing nil)
+ (save-excursion
+ (goto-char pos)
+ (insert text)
+ (setq web-mode-enable-auto-pairing mem)
+ )))
+
+(defun web-mode-remove-text-at-pos (n &optional pos)
+ (unless pos (setq pos (point)))
+ (delete-region pos (+ pos n)))
+
+(defun web-mode-insert-and-indent (text)
+ (let (beg end)
+ (setq beg (point-at-bol))
+ (insert text)
+ (setq end (point-at-eol))
+ (indent-region beg end)
+ ))
+
+(defun web-mode-column-at-pos (pos)
+ (save-excursion
+ (goto-char pos)
+ (current-column)))
+
+(defun web-mode-indentation-at-pos (pos)
+ (save-excursion
+ (goto-char pos)
+ (current-indentation)))
+
+(defun web-mode-navigate (&optional pos)
+ "Move point to the matching opening/closing tag/block."
+ (interactive)
+ (unless pos (setq pos (point)))
+ (let (init)
+ (goto-char pos)
+ (setq init (point))
+ (when (> (current-indentation) (current-column))
+ (back-to-indentation))
+ (setq pos (point))
+ (cond
+ ((and (get-text-property pos 'block-side)
+ (web-mode-block-beginning)
+ (web-mode-block-controls-get (point)))
+ (web-mode-block-match))
+ ((member (get-text-property pos 'tag-type) '(start end))
+ (web-mode-tag-beginning)
+ (web-mode-tag-match))
+ (t
+ (goto-char init))
+ )
+ ))
+
+(defun web-mode-block-match (&optional pos)
+ (unless pos (setq pos (point)))
+ (let (pos-ori controls control (counter 1) type (continue t) pair)
+ (setq pos-ori pos)
+ (goto-char pos)
+ (setq controls (web-mode-block-controls-get pos))
+ ;;(message "controls=%S" controls)
+ (cond
+ (controls
+ (setq pair (car controls))
+ (setq control (cdr pair))
+ (setq type (car pair))
+ (when (eq type 'inside) (setq type 'close))
+ (while continue
+ (cond
+ ((and (> pos-ori 1) (bobp))
+ (setq continue nil))
+ ((or (and (eq type 'open) (not (web-mode-block-next)))
+ (and (eq type 'close) (not (web-mode-block-previous))))
+ (setq continue nil)
+ )
+ ((null (setq controls (web-mode-block-controls-get (point))))
+ )
+ (t
+ ;;TODO : est il nécessaire de faire un reverse sur controls si on doit matcher backward
+ (dolist (pair controls)
+ (cond
+ ((not (string= (cdr pair) control))
+ )
+ ((eq (car pair) 'inside)
+ )
+ ((eq (car pair) type)
+ (setq counter (1+ counter)))
+ (t
+ (setq counter (1- counter)))
+ )
+ ) ;dolist
+ (when (= counter 0)
+ (setq continue nil))
+ ) ;t
+ ) ;cond
+ ) ;while
+ (if (= counter 0) (point) nil)
+ ) ;controls
+ (t
+ (goto-char pos-ori)
+ nil
+ ) ;controls = nul
+ ) ;conf
+ ))
+
+(defun web-mode-tag-match (&optional pos)
+ "Move point to the matching opening/closing tag."
+ (interactive)
+ (unless pos (setq pos (point)))
+ (let (regexp name)
+ (cond
+ ((eq (get-text-property pos 'tag-type) 'void)
+ (web-mode-tag-beginning))
+ ((and (eq (get-text-property pos 'tag-type) 'comment)
+ (web-mode-looking-at-p "<!--#\\(elif\\|else\\|endif\\|if\\)" pos))
+ (setq regexp "<!--#\\(end\\)?if")
+ (if (web-mode-looking-at-p "<!--#if" pos)
+ (web-mode-tag-fetch-closing regexp pos)
+ (web-mode-tag-fetch-opening regexp pos))
+ )
+ (t
+ (setq name (get-text-property pos 'tag-name))
+ (when (string= name "_fragment_") (setq name ">"))
+ (setq regexp (concat "</?" name))
+ (when (member (get-text-property pos 'tag-type) '(start end))
+ (web-mode-tag-beginning)
+ (setq pos (point)))
+ (if (eq (get-text-property pos 'tag-type) 'end)
+ (web-mode-tag-fetch-opening regexp pos)
+ (web-mode-tag-fetch-closing regexp pos))
+ ) ;t
+ ) ;cond
+ t))
+
+(defun web-mode-tag-fetch-opening (regexp pos)
+ (let ((counter 1) (n 0) (is-comment nil) (types '(start end)))
+ (when (eq (aref regexp 1) ?\!)
+ (setq types '(comment)
+ is-comment t))
+ (goto-char pos)
+ (while (and (> counter 0) (re-search-backward regexp nil t))
+ (when (and (get-text-property (point) 'tag-beg)
+ (member (get-text-property (point) 'tag-type) types))
+ (setq n (1+ n))
+ (cond
+ ((and is-comment
+ (eq (aref (match-string-no-properties 0) 5) ?e))
+ (setq counter (1+ counter)))
+ (is-comment
+ (setq counter (1- counter)))
+ ((eq (get-text-property (point) 'tag-type) 'end)
+ (setq counter (1+ counter)))
+ (t
+ (setq counter (1- counter))
+ )
+ )
+ )
+ )
+ (if (= n 0) (goto-char pos))
+ ))
+
+(defun web-mode-tag-fetch-closing (regexp pos)
+ (let ((counter 1) (is-comment nil) (n 0))
+ (when (eq (aref regexp 1) ?\!)
+ (setq is-comment t))
+ (goto-char pos)
+ (web-mode-tag-end)
+ (while (and (> counter 0) (re-search-forward regexp nil t))
+ (when (get-text-property (match-beginning 0) 'tag-beg)
+ (setq n (1+ n))
+ (cond
+ ((and is-comment
+ (eq (aref (match-string-no-properties 0) 5) ?e))
+ (setq counter (1- counter)))
+ (is-comment
+ (setq counter (1+ counter)))
+ ((eq (get-text-property (point) 'tag-type) 'end)
+ (setq counter (1- counter)))
+ (t
+ (setq counter (1+ counter)))
+ )
+ ) ;when
+ ) ;while
+ (if (> n 0)
+ (web-mode-tag-beginning)
+ (goto-char pos))
+ ))
+
+(defun web-mode-element-tag-name (&optional pos)
+ (unless pos (setq pos (point)))
+ (save-excursion
+ (goto-char pos)
+ (if (and (web-mode-tag-beginning)
+ (looking-at web-mode-tag-regexp))
+ (match-string-no-properties 1)
+ nil)))
+
+(defun web-mode-element-close ()
+ "Close html element."
+ (interactive)
+ (let (jmp epp ins tag)
+
+ (if (and (eq (char-before) ?\>)
+ (web-mode-element-is-void (get-text-property (1- (point)) 'tag-name)))
+ (unless (eq (char-before (1- (point))) ?\/)
+ (backward-char)
+ (insert "/")
+ (forward-char))
+ (setq epp (web-mode-element-parent-position)))
+
+ ;;(message "epp=%S" epp)
+ (when epp
+ (setq tag (get-text-property epp 'tag-name))
+ (setq tag (web-mode-element-tag-name epp))
+ ;;(message "tag=%S %c" tag (char-before))
+ (cond
+ ((or (null tag) (web-mode-element-is-void tag))
+ (setq epp nil))
+ ((looking-back "</" (point-min))
+ (setq ins tag))
+ ((looking-back "<" (point-min))
+ (setq ins (concat "/" tag)))
+ (t
+ ;;auto-close-style = 2
+ ;;(message "%S %c" (point) (char-after))
+ (when (and (looking-at-p "[[:alpha:]]") (> (length tag) 4))
+ (dolist (elt '("div" "span" "strong" "pre" "li"))
+ (when (and (string-match-p (concat "^" elt) tag) (not (string= tag elt)))
+ (setq tag elt)
+ (put-text-property epp (point) 'tag-name tag))
+ )
+ ) ;when
+ (if (web-mode-element-is-void (get-text-property (point) 'tag-name))
+ (setq ins nil
+ epp nil)
+ (setq ins (concat "</" tag)))
+ )
+ ) ;cond
+ (when ins
+ (unless (looking-at-p "[ ]*>")
+ (setq ins (concat ins ">")))
+ (insert ins)
+ (setq tag (downcase tag))
+ (save-excursion
+ (search-backward "<")
+ (setq jmp (and (eq (char-before) ?\>)
+ (string= (get-text-property (1- (point)) 'tag-name) tag)))
+ (if jmp (setq jmp (point)))
+ ) ;save-excursion
+ (if jmp (goto-char jmp))
+ ) ;when not ins
+ ) ;when epp
+ epp))
+
+(defun web-mode-detect-content-type ()
+ (cond
+ ((and (string= web-mode-engine "none")
+ (< (point) 16)
+ (eq (char-after 1) ?\#)
+ (string-match-p "php" (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position))))
+ (web-mode-set-engine "php"))
+ ((and (string= web-mode-content-type "javascript")
+ (< (point) web-mode-chunk-length)
+ (eq (char-after (point-min)) ?\/)
+ (string-match-p "@jsx" (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position))))
+ (web-mode-set-content-type "jsx"))
+ ))
+
+(defun web-mode-auto-complete ()
+ "Autocomple at point."
+ (interactive)
+ (let ((pos (point))
+ (char (char-before))
+ (chunk (buffer-substring-no-properties (- (point) 2) (point)))
+ (expanders nil) (tag nil)
+ (auto-closed nil)
+ (auto-expanded nil)
+ (auto-paired nil)
+ (auto-quoted nil))
+
+ ;;-- auto-closing
+ (when web-mode-enable-auto-closing
+
+ (cond
+
+ ((and (= web-mode-auto-close-style 3)
+ (eq char ?\<))
+ (insert "/>")
+ (backward-char 2)
+ (setq auto-closed t))
+
+ ((and (= web-mode-auto-close-style 3)
+ (eq char ?\>)
+ (looking-at-p "/>"))
+ (save-excursion
+ (re-search-backward web-mode-start-tag-regexp)
+ (setq tag (match-string-no-properties 1)))
+ (insert "<")
+ (forward-char)
+ (insert tag)
+ (setq auto-closed t))
+
+ ((and (>= pos 4)
+ (or (string= "</" chunk)
+ ;;(progn (message "%c" char) nil)
+ (and (= web-mode-auto-close-style 2)
+ (or (string= web-mode-content-type "jsx")
+ (not (get-text-property pos 'part-side)))
+ (string-match-p "[[:alnum:]'\"]>" chunk)))
+ (not (get-text-property (- pos 2) 'block-side))
+ (web-mode-element-close))
+ (setq auto-closed t))
+
+ ) ;cond
+ ) ;when
+
+ ;;-- auto-pairing
+ (when (and web-mode-enable-auto-pairing
+ (>= pos 4)
+ (not auto-closed))
+ (let ((i 0) expr after pos-end (l (length web-mode-auto-pairs)))
+ (setq pos-end (if (> (+ pos 32) (line-end-position))
+ (line-end-position)
+ (+ pos 10)))
+ (setq chunk (buffer-substring-no-properties (- pos 3) pos)
+ after (buffer-substring-no-properties pos pos-end))
+ (while (and (< i l) (not auto-paired))
+ (setq expr (elt web-mode-auto-pairs i)
+ i (1+ i))
+ ;;(message "chunk=%S expr=%S after=%S" chunk expr after)
+ (when (and (string= (car expr) chunk)
+ (not (string-match-p (regexp-quote (cdr expr)) after)))
+ (setq auto-paired t)
+ (insert (cdr expr))
+ (if (string-match-p "|" (cdr expr))
+ (progn
+ (search-backward "|")
+ (delete-char 1))
+ (goto-char pos))
+ ) ;when
+ ) ;while
+ ) ;let
+ )
+
+ ;;-- auto-expanding
+ (when (and web-mode-enable-auto-expanding
+ (not auto-closed)
+ (not auto-paired)
+ (eq char ?\/)
+ (looking-back "\\(^\\|[[:punct:][:space:]>]\\)./" (point-min))
+ (or (web-mode-jsx-is-html (1- pos))
+ (and (not (get-text-property (1- pos) 'tag-type))
+ (not (get-text-property (1- pos) 'part-side))))
+ (not (get-text-property (1- pos) 'block-side))
+ )
+ (setq expanders (append web-mode-expanders web-mode-extra-expanders))
+ (let ((i 0) pair (l (length expanders)))
+ (setq chunk (buffer-substring-no-properties (- pos 2) pos))
+ ;;(message "%S" chunk)
+ (while (and (< i l) (not auto-expanded))
+ (setq pair (elt expanders i)
+ i (1+ i))
+ (when (string= (car pair) chunk)
+ (setq auto-expanded t)
+ (delete-char -2)
+ (insert (cdr pair))
+ (when (string-match-p "|" (cdr pair))
+ (search-backward "|")
+ (delete-char 1))
+ ) ;when
+ ) ;while
+ ) ;let
+ )
+
+ ;;-- auto-quoting
+ (when (and web-mode-enable-auto-quoting
+ (>= pos 4)
+ (not (get-text-property pos 'block-side))
+ (not auto-closed)
+ (not auto-paired)
+ (not auto-expanded)
+ (get-text-property (- pos 2) 'tag-attr))
+ (cond
+ ((and (eq char ?\=)
+ (not (looking-at-p "[ ]*[\"']")))
+ (cond ((= web-mode-auto-quote-style 2)
+ (insert "''"))
+ ((= web-mode-auto-quote-style 3)
+ (insert "{}"))
+ (t
+ (insert "\"\"")))
+ (if (looking-at-p "[ \n>]")
+ (backward-char)
+ (insert " ")
+ (backward-char 2)
+ )
+ (setq auto-quoted t))
+ ((and (eq char ?\")
+ (looking-back "=[ ]*\"" (point-min))
+ (not (looking-at-p "[ ]*[\"]")))
+ (insert-and-inherit "\"")
+ (backward-char)
+ (setq auto-quoted t))
+ ((and (eq char ?\')
+ (looking-back "=[ ]*'" (point-min))
+ (not (looking-at-p "[ ]*[']")))
+ (insert-and-inherit "'")
+ (backward-char)
+ (setq auto-quoted t))
+ ((and (eq char ?\{)
+ (eq (get-text-property pos 'part-side) 'jsx)
+ (looking-back "=[ ]*{" (point-min))
+ (not (looking-at-p "[ ]*[}]")))
+ (insert-and-inherit "}")
+ (backward-char)
+ (setq auto-quoted t))
+ ((and (eq char ?\")
+ (eq (char-after) ?\"))
+ (delete-char 1)
+ (cond
+ ((looking-back "=\"\"" (point-min))
+ (backward-char))
+ ((eq (char-after) ?\s)
+ (forward-char))
+ (t
+ (insert " "))
+ ) ;cond
+ )
+ ) ;cond
+ ) ;when
+
+ ;;--
+ (cond
+ ((or auto-closed auto-paired auto-expanded auto-quoted)
+ (when (and web-mode-change-end (>= (line-end-position) web-mode-change-end))
+ (setq web-mode-change-end (line-end-position)))
+ (list :auto-closed auto-closed
+ :auto-paired auto-paired
+ :auto-expanded auto-expanded
+ :auto-quoted auto-quoted))
+ (t
+ nil)
+ )
+
+ ))
+
+(defun web-mode-dom-xpath (&optional pos)
+ "Display html path."
+ (interactive)
+ (unless pos (setq pos (point)))
+ (save-excursion
+ (goto-char pos)
+ (let (path tag)
+ (while (web-mode-element-parent)
+ (looking-at web-mode-tag-regexp)
+ (setq tag (match-string-no-properties 1))
+ (setq path (cons tag path))
+ )
+ (message "/%s" (mapconcat 'identity path "/"))
+ )))
+
+(defun web-mode-block-ends-with (regexp &optional pos)
+ (unless pos (setq pos (point)))
+ (save-excursion
+ (goto-char pos)
+ (save-match-data
+ (if (stringp regexp)
+ (and (web-mode-block-end)
+ (progn (backward-char) t)
+ (web-mode-block-skip-blank-backward)
+ (progn (forward-char) t)
+ (looking-back regexp (point-min)))
+ (let ((pair regexp)
+ (block-beg (web-mode-block-beginning-position pos))
+ (block-end (web-mode-block-end-position pos)))
+ (and (web-mode-block-end)
+ (web-mode-block-sb (car pair) block-beg)
+ (not (web-mode-sf (cdr pair) block-end)))
+ ) ;let
+ ) ;if
+ )))
+
+(defun web-mode-block-token-starts-with (regexp &optional pos)
+ (unless pos (setq pos (point)))
+ (save-excursion
+ (and (goto-char pos)
+ (web-mode-block-token-beginning)
+ (skip-chars-forward "[\"']")
+ (looking-at regexp))
+ ))
+
+(defun web-mode-block-starts-with (regexp &optional pos)
+ (unless pos (setq pos (point)))
+ (save-excursion
+ (and (web-mode-block-beginning)
+ (web-mode-block-skip-blank-forward)
+ (looking-at regexp))
+ ))
+
+(defun web-mode-block-skip-blank-backward (&optional pos)
+ (unless pos (setq pos (point)))
+ (let ((continue t))
+ (goto-char pos)
+ (while continue
+ (if (and (get-text-property (point) 'block-side)
+ (not (bobp))
+ (or (member (char-after) '(?\s ?\n))
+ (member (get-text-property (point) 'block-token)
+ '(delimiter-beg delimiter-end comment))))
+ (backward-char)
+ (setq continue nil))
+ ) ;while
+ (point)))
+
+(defun web-mode-block-skip-blank-forward (&optional pos props)
+ (unless pos (setq pos (point)))
+ (unless props (setq props '(delimiter-beg delimiter-end comment)))
+ (let ((continue t))
+ (goto-char pos)
+ (while continue
+ (if (and (get-text-property (point) 'block-side)
+ (or (member (char-after) '(?\s ?\n ?\t))
+ (member (get-text-property (point) 'block-token) props)))
+ (forward-char)
+ (setq continue nil))
+ ) ;while
+ (point)))
+
+(defun web-mode-tag-attributes-sort (&optional pos)
+ "Sort the attributes inside the current html tag."
+ (interactive)
+ (unless pos (setq pos (point)))
+ (save-excursion
+ (let (attrs (continue t) min max tag-beg tag-end attr attr-name attr-beg attr-end indent indentation sorter ins)
+ (if (not (member (get-text-property pos 'tag-type) '(start void)))
+ nil
+ (setq tag-beg (web-mode-tag-beginning-position pos)
+ tag-end (web-mode-tag-end-position))
+;; (message "%S %S" tag-beg tag-end)
+ (goto-char tag-beg)
+ (while continue
+ (if (or (not (web-mode-attribute-next))
+ (>= (point) tag-end))
+ (setq continue nil)
+ ;;(message "attr=%S" (point))
+ (setq attr-beg (web-mode-attribute-beginning-position)
+ attr-end (1+ (web-mode-attribute-end-position)))
+ (when (null min)
+ (setq min attr-beg))
+ (setq max attr-end)
+ (goto-char attr-beg)
+ (setq attr (buffer-substring-no-properties attr-beg attr-end))
+ (if (string-match "^\\([[:alnum:]-]+\\)=" attr)
+ (setq attr-name (match-string-no-properties 1 attr))
+ (setq attr-name attr))
+ (setq indent (looking-back "^[ \t]*" (point-min)))
+ (setq attrs (append attrs (list (list attr-beg attr-end attr-name attr indent))))
+ ) ;if
+ ) ;while
+ ) ;if in tag
+ (when attrs
+ (setq sorter (function
+ (lambda (elt1 elt2)
+ (string< (nth 2 elt1) (nth 2 elt2))
+ )))
+ (setq attrs (sort attrs sorter))
+ (delete-region (1- min) max)
+ (setq ins "")
+ (dolist (elt attrs)
+ (if (and (nth 4 elt) (> (length ins) 1))
+ (setq ins (concat ins "\n"))
+ (setq ins (concat ins " ")))
+ (setq ins (concat ins (nth 3 elt)))
+ )
+ (goto-char (1- min))
+ (insert ins)
+ (web-mode-tag-beginning)
+ (setq min (line-beginning-position))
+ (web-mode-tag-end)
+ (setq max (line-end-position))
+ (indent-region min max)
+ )
+ ;;(message "attrs=%S" attrs)
+ )))
+
+(defun web-mode-attribute-insert ()
+ "Insert an attribute inside current tag."
+ (interactive)
+ (let (attr attr-name attr-value)
+ (cond
+ ((not (member (get-text-property (point) 'tag-type) '(start void)))
+ (message "attribute-insert ** invalid context **"))
+ ((not (and (setq attr-name (read-from-minibuffer "Attribute name? "))
+ (> (length attr-name) 0)))
+ (message "attribute-insert ** failure **"))
+ (t
+ (setq attr (concat " " attr-name))
+ (when (setq attr-value (read-from-minibuffer "Attribute value? "))
+ (setq attr (concat attr "=\"" attr-value "\"")))
+ (web-mode-tag-end)
+ (if (looking-back "/>" (point-min))
+ (backward-char 2)
+ (backward-char))
+ (insert attr)
+ ) ;t
+ ) ;cond
+ ))
+
+(defun web-mode-attribute-transpose (&optional pos)
+ "Transpose the current html attribute."
+ (interactive)
+ (unless pos (setq pos (point)))
+ (let (ret attr-beg attr-end next-beg next-end tag-end)
+ (when (and (get-text-property pos 'tag-attr)
+ (setq next-beg (web-mode-attribute-next-position pos))
+ (setq next-end (web-mode-attribute-end-position next-beg))
+ (setq tag-end (web-mode-tag-end-position pos))
+ (> tag-end next-end))
+ (setq attr-beg (web-mode-attribute-beginning-position pos)
+ attr-end (web-mode-attribute-end-position pos))
+ ;; (message "%S %S - %S %S" attr-beg attr-end next-beg next-end)
+ (transpose-regions attr-beg (1+ attr-end) next-beg (1+ next-end))
+ )))
+
+(defun web-mode-attribute-select (&optional pos)
+ "Select the current html attribute."
+ (interactive)
+ (unless pos (setq pos (point)))
+ (if (null (get-text-property pos 'tag-attr))
+ nil
+ (goto-char pos)
+ (web-mode-attribute-beginning)
+ (set-mark (point))
+ (web-mode-attribute-end)
+ (exchange-point-and-mark)
+ (point)
+ ))
+
+(defun web-mode-attribute-kill (&optional arg)
+ "Kill the current html attribute."
+ (interactive "p")
+ (unless arg (setq arg 1))
+ (while (>= arg 1)
+ (setq arg (1- arg))
+ (web-mode-attribute-select)
+ (when mark-active
+ (let ((beg (region-beginning)) (end (region-end)))
+ (save-excursion
+ (goto-char end)
+ (when (looking-at "[ \n\t]*")
+ (setq end (+ end (length (match-string-no-properties 0)))))
+ ) ;save-excursion
+ (kill-region beg end)
+ ) ;let
+ ) ;when
+ ) ;while
+ ;; Delete a potential space before the closing ">".
+ (when (and (looking-at ">")
+ (looking-back " " (point-min)))
+ (delete-char -1))
+ )
+
+(defun web-mode-block-close (&optional pos)
+ "Close the first unclosed control block."
+ (interactive)
+ (unless pos (setq pos (point)))
+ (let ((continue t)
+ (h (make-hash-table :test 'equal)) ctx ctrl n closing-block)
+ (save-excursion
+ (while (and continue (web-mode-block-previous))
+ (when (setq ctx (web-mode-block-is-control (point)))
+ (setq ctrl (car ctx))
+ (setq n (gethash ctrl h 0))
+ (if (cdr ctx)
+ (puthash ctrl (1+ n) h)
+ (puthash ctrl (1- n) h))
+ (when (> (gethash ctrl h) 0)
+ (setq continue nil))
+ )
+ ) ;while
+ ) ;save-excursion
+ (when (and (null continue)
+ (setq closing-block (web-mode-closing-block ctrl)))
+ (insert closing-block)
+ (indent-according-to-mode))
+ ))
+
+(defun web-mode-closing-block (type)
+ (cond
+ ((string= web-mode-engine "php") (concat "<?php end" type "; ?>"))
+ ((string= web-mode-engine "django") (concat "{% end" type " %}"))
+ ((string= web-mode-engine "ctemplate") (concat "{{/" type "}}"))
+ ((string= web-mode-engine "blade")
+ (if (string= type "section") (concat "@show") (concat "@end" type)))
+ ((string= web-mode-engine "dust") (concat "{/" type "}"))
+ ((string= web-mode-engine "mako") (concat "% end" type))
+ ((string= web-mode-engine "closure") (concat "{/" type "}"))
+ ((string= web-mode-engine "smarty") (concat "{/" type "}"))
+ ((string= web-mode-engine "expressionengine") (concat "{/" type "}"))
+ ((string= web-mode-engine "xoops") (concat "<{/" type "}>"))
+ ((string= web-mode-engine "svelte") (concat "{/" type "}"))
+ ((string= web-mode-engine "underscore") "<% } %>")
+ ((string= web-mode-engine "lsp") "<% ) %>")
+ ((string= web-mode-engine "erb") "<% } %>")
+ ((string= web-mode-engine "erb") "<% end %>")
+ ((string= web-mode-engine "artanis") "<% ) %>")
+ ((string= web-mode-engine "hero") "<% } %>")
+ ((string= web-mode-engine "go") "{{end}}")
+ ((string= web-mode-engine "velocity") "#end")
+ ((string= web-mode-engine "velocity") "#{end}")
+ ((string= web-mode-engine "template-toolkit") "[% end %]")
+ ((member web-mode-engine '("asp" "jsp"))
+ (if (string-match-p "[:.]" type) (concat "</" type ">") "<% } %>"))
+ (t nil)
+ ) ;cond
+ )
+
+;;---- POSITION ----------------------------------------------------------------
+
+(defun web-mode-comment-beginning-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (car (web-mode-comment-boundaries pos)))
+
+(defun web-mode-comment-end-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cdr (web-mode-comment-boundaries pos)))
+
+(defun web-mode-part-opening-paren-position (pos &optional limit)
+ (save-restriction
+ (unless limit (setq limit nil))
+ (goto-char pos)
+ (let* ((n -1)
+ (paren (char-after))
+ (pairs '((?\) . "[)(]")
+ (?\] . "[\]\[]")
+ (?\} . "[}{]")
+ (?\> . "[><]")))
+ (regexp (cdr (assoc paren pairs)))
+ (continue (not (null regexp)))
+ (counter 0))
+ (while (and continue (re-search-backward regexp limit t))
+ (cond
+ ((> (setq counter (1+ counter)) 500)
+ (message "part-opening-paren-position ** warning **")
+ (setq continue nil))
+ ((or (web-mode-is-comment-or-string)
+ (get-text-property (point) 'block-side))
+ )
+ ((eq (char-after) paren)
+ (setq n (1- n)))
+ (t
+ (setq n (1+ n))
+ (setq continue (not (= n 0))))
+ )
+ ) ;while
+ (if (= n 0) (point) nil)
+ )))
+
+(defun web-mode-token-opening-paren-position (pos limit context)
+ (save-restriction
+ (unless limit (setq limit nil))
+ (goto-char pos)
+ (let* ((n -1)
+ (paren (char-after))
+ (pairs '((?\) . "[)(]")
+ (?\] . "[\]\[]")
+ (?\} . "[}{]")
+ (?\> . "[><]")))
+ (regexp (cdr (assoc paren pairs)))
+ (continue (not (null regexp)))
+ (counter 0))
+ (while (and continue (re-search-backward regexp limit t))
+ (cond
+ ((> (setq counter (1+ counter)) 200)
+ (message "token-opening-paren-position ** warning **")
+ (setq continue nil))
+ ((get-text-property (point) 'block-side)
+ )
+ ((eq (char-after) paren)
+ (setq n (1- n)))
+ (t
+ (setq n (1+ n))
+ (setq continue (not (= n 0))))
+ )
+ ) ;while
+ (if (= n 0) (point) nil)
+ )))
+
+(defun web-mode-closing-paren-position (&optional pos limit)
+ (save-excursion
+ (unless pos (setq pos (point)))
+ (unless limit (setq limit nil))
+ (goto-char pos)
+ (let* ((n 0)
+ (block-side (and (get-text-property pos 'block-side)
+ (not (string= web-mode-engine "razor"))))
+ (paren (char-after))
+ (pairs '((?\( . "[)(]")
+ (?\[ . "[\]\[]")
+ (?\{ . "[}{]")
+ (?\< . "[><]")))
+ (regexp (cdr (assoc paren pairs)))
+ (continue (not (null regexp))))
+ (while (and continue (re-search-forward regexp limit t))
+ (cond
+ ((or (web-mode-is-comment-or-string (1- (point)))
+ (and block-side (not (get-text-property (point) 'block-side))))
+ ;;(message "pt=%S" (point))
+ )
+ ((eq (char-before) paren)
+ (setq n (1+ n)))
+ (t
+ (setq n (1- n))
+ (setq continue (not (= n 0)))
+ )
+ ) ;cond
+ ) ;while
+ (if (= n 0) (1- (point)) nil)
+ )))
+
+(defun web-mode-closing-delimiter-position (delimiter &optional pos limit)
+ (unless pos (setq pos (point)))
+ (unless limit (setq limit nil))
+ (save-excursion
+ (goto-char pos)
+ (setq pos nil)
+ (let ((continue t))
+ (while (and continue (re-search-forward delimiter limit t))
+ (setq continue nil
+ pos (1- (point)))
+ ) ;while
+ pos)))
+
+(defun web-mode-tag-match-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (save-excursion
+ (web-mode-tag-match pos)
+ (if (= pos (point)) nil (point))))
+
+(defun web-mode-tag-beginning-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (let (beg end depth)
+ (setq depth (get-text-property pos 'jsx-depth))
+ (when (and depth (get-text-property pos 'tag-attr-beg))
+ (setq depth (get-text-property (1- pos) 'jsx-depth)))
+ (cond
+ ((null pos)
+ (setq end nil))
+ ((get-text-property pos 'tag-beg)
+ (setq beg pos))
+ ((and (> pos 1) (get-text-property (1- pos) 'tag-beg))
+ (setq beg (1- pos)))
+ ((get-text-property pos 'tag-type)
+ (setq beg (previous-single-property-change pos 'tag-beg))
+ (when beg (setq beg (1- beg)))
+ (cond
+ ((not (get-text-property beg 'tag-beg))
+ (setq beg nil))
+ ((and depth (not (eq depth (get-text-property beg 'jsx-depth))))
+ (let ((continue (> beg (point-min))))
+ (while continue
+ (setq beg (previous-single-property-change beg 'tag-beg))
+ (when beg (setq beg (1- beg)))
+ (cond
+ ((null beg)
+ (setq continue nil))
+ ((not (get-text-property beg 'tag-beg))
+ (setq continue nil
+ beg nil))
+ ((eq depth (get-text-property beg 'jsx-depth))
+ (setq continue nil))
+ ) ;cond
+ ) ;while
+ ) ;let
+ )
+ ) ;cond
+ )
+ (t
+ (setq beg nil))
+ ) ;cond
+ beg))
+
+(defun web-mode-tag-end-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (let (end depth)
+ (setq depth (get-text-property pos 'jsx-depth))
+ (when (and depth (get-text-property pos 'tag-attr-beg))
+ (setq depth (get-text-property (1- pos) 'jsx-depth)))
+ (cond
+ ((null pos)
+ (setq end nil))
+ ((get-text-property pos 'tag-end)
+ (setq end pos))
+ ((get-text-property pos 'tag-type)
+ (setq end (next-single-property-change pos 'tag-end))
+ (cond
+ ((not (get-text-property end 'tag-end))
+ (setq end nil))
+ ((and depth (not (eq depth (get-text-property end 'jsx-depth))))
+ (let ((continue (< end (point-max))))
+ (while continue
+ (setq end (1+ end))
+ (setq end (next-single-property-change end 'tag-end))
+ (cond
+ ((null end)
+ (setq continue nil))
+ ((not (get-text-property end 'tag-end))
+ (setq continue nil
+ end nil))
+ ((eq depth (get-text-property end 'jsx-depth))
+ (setq continue nil))
+ ) ;cond
+ ) ;while
+ ) ;let
+ )
+ ) ;cond
+ )
+ (t
+ (setq end nil))
+ ) ;cond
+ end))
+
+;; TODO: prendre en compte jsx-depth
+(defun web-mode-tag-next-position (&optional pos limit)
+ (unless pos (setq pos (point)))
+ (unless limit (setq limit (point-max)))
+ (cond
+ ((or (>= pos (point-max)) (>= pos limit)) nil)
+ (t
+ (when (get-text-property pos 'tag-beg) (setq pos (1+ pos)))
+ (setq pos (next-single-property-change pos 'tag-beg))
+ (if (and pos (<= pos limit)) pos nil))
+ ))
+
+;; TODO: prendre en compte jsx-depth
+(defun web-mode-tag-previous-position (&optional pos limit)
+ (unless pos (setq pos (point)))
+ (unless limit (setq limit (point-min)))
+ (cond
+ ((or (<= pos (point-min)) (<= pos limit)) nil)
+ (t
+ (when (get-text-property pos 'tag-beg) (setq pos (1- pos)))
+ (web-mode-go (previous-single-property-change pos 'tag-beg) -1))
+ ))
+
+;; TODO: prendre en compte jsx-depth
+(defun web-mode-attribute-beginning-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((null (get-text-property pos 'tag-attr))
+ nil)
+ ((get-text-property pos 'tag-attr-beg)
+ pos)
+ ((and (> pos (point-min)) (get-text-property (1- pos) 'tag-attr-beg))
+ (1- pos))
+ (t
+ (setq pos (previous-single-property-change pos 'tag-attr-beg))
+ (setq pos (1- pos)))
+ ))
+
+;; TODO: retoucher en incluant un param limit et en s'inspirant de
+;; web-mode-attribute-next-position
+(defun web-mode-attribute-end-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (let (beg end depth flags)
+ ;;(message "pos=%S" pos)
+ (setq depth (get-text-property pos 'jsx-depth))
+ (cond
+ ((null pos)
+ (setq end nil))
+ ((get-text-property pos 'tag-attr-end)
+ (setq end pos))
+ ((get-text-property pos 'tag-attr)
+ (setq end (next-single-property-change pos 'tag-attr-end))
+ (when (and depth
+ end
+ (setq beg (web-mode-attribute-beginning-position end))
+ (setq flags (get-text-property pos 'tag-attr-beg))
+ (eq (logand flags 4) 4))
+ (setq depth (1- (get-text-property beg 'jsx-depth)))
+ ;;(message "%S %S" beg end)
+ )
+ (cond
+ ((not (get-text-property end 'tag-attr-end))
+ (setq end nil))
+ ((and depth
+ (eq depth (get-text-property end 'jsx-depth))
+ (not (eq depth (get-text-property end 'jsx-end))))
+ )
+ ((and depth (eq (1+ depth) (get-text-property end 'jsx-depth)))
+ )
+ ((and depth (not (eq (1+ depth) (get-text-property end 'jsx-depth))))
+ (let ((continue (< end (point-max))))
+ (while continue
+ (setq end (1+ end))
+ (setq end (next-single-property-change end 'tag-attr-end))
+ (cond
+ ((null end)
+ (setq continue nil))
+ ((not (get-text-property end 'tag-attr-end))
+ (setq continue nil
+ end nil))
+ ((eq (1+ depth) (get-text-property end 'jsx-depth))
+ (setq continue nil))
+ ) ;cond
+ ) ;while
+ ) ;let
+ )
+ ) ;cond
+ )
+ (t
+ (setq end nil))
+ ) ;cond
+ end))
+
+;; attention si pos est au debut d'un spread attributes, cela
+;; risque de poser pb
+(defun web-mode-attribute-next-position (&optional pos limit)
+ (unless pos (setq pos (point)))
+ (unless limit (setq limit (point-max)))
+ (let (continue depth)
+ (when (get-text-property pos 'tag-attr-beg)
+ (setq pos (1+ pos)))
+ (if (< pos limit)
+ (setq continue t
+ depth (get-text-property pos 'jsx-depth))
+ (setq continue nil
+ pos nil))
+ (while continue
+ (setq pos (next-single-property-change pos 'tag-attr-beg))
+ (cond
+ ((null pos)
+ (setq continue nil))
+ ((>= pos limit)
+ (setq continue nil
+ pos nil))
+ ((null depth)
+ (setq continue nil))
+ ((and (eq (get-text-property pos 'tag-attr-beg) 4)
+ (eq (1+ depth) (get-text-property pos 'jsx-depth)))
+ (setq continue nil))
+ ((eq depth (get-text-property pos 'jsx-depth))
+ (setq continue nil))
+ (t
+ (setq pos (1+ pos)
+ continue (< pos limit)))
+ )
+ ) ;while
+ pos))
+
+(defun web-mode-attribute-previous-position (&optional pos limit)
+ (unless pos (setq pos (point)))
+ (unless limit (setq limit (point-min)))
+ (let (continue depth)
+ (cond
+ ((and (> pos (point-min)) (get-text-property (1- pos) 'tag-attr-beg))
+ (setq pos (1- pos)
+ continue nil))
+ (t
+ (when (get-text-property pos 'tag-attr-beg)
+ (setq pos (1- pos)))
+ (if (> pos limit)
+ (setq continue t
+ depth (get-text-property pos 'jsx-depth))
+ (setq continue nil
+ pos nil))
+ ) ;t
+ ) ;cond
+ (while continue
+ (setq pos (previous-single-property-change pos 'tag-attr-beg))
+ (cond
+ ((null pos)
+ (setq continue nil))
+ ((< pos limit)
+ (setq continue nil
+ pos nil))
+ ;;((null depth)
+ ;; (setq continue nil))
+ ((and depth (eq depth (get-text-property pos 'jsx-depth)))
+ (setq pos (1- pos)
+ continue nil))
+ (depth
+ (setq pos nil
+ continue (> pos limit)))
+ (t
+ (setq pos (1- pos)
+ continue nil))
+ ) ;cond
+ ) ;while
+ pos))
+
+;; TODO: prendre en compte jsx-depth
+(defun web-mode-element-beginning-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((null (get-text-property pos 'tag-type))
+ (setq pos (web-mode-element-parent-position)))
+ ((eq (get-text-property pos 'tag-type) 'end)
+ (setq pos (web-mode-tag-match-position pos))
+ (setq pos (if (get-text-property pos 'tag-beg) pos nil)))
+ ((member (get-text-property pos 'tag-type) '(start void))
+ (setq pos (web-mode-tag-beginning-position pos)))
+ (t
+ (setq pos nil))
+ ) ;cond
+ pos)
+
+;; TODO: prendre en compte jsx-depth
+(defun web-mode-element-end-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((null (get-text-property pos 'tag-type))
+ (setq pos (web-mode-element-parent-position pos))
+ (when pos
+ (setq pos (web-mode-tag-match-position pos))
+ (when pos (setq pos (web-mode-tag-end-position pos)))
+ )
+ )
+ ((member (get-text-property pos 'tag-type) '(end void comment))
+ (setq pos (web-mode-tag-end-position pos))
+ )
+ ((member (get-text-property pos 'tag-type) '(start))
+ (setq pos (web-mode-tag-match-position pos))
+ (when pos (setq pos (web-mode-tag-end-position pos))))
+ (t
+ (setq pos nil))
+ ) ;cond
+ pos)
+
+(defun web-mode-element-child-position (&optional pos)
+ (save-excursion
+ (let (child close)
+ (unless pos (setq pos (point)))
+ (goto-char pos)
+ (cond
+ ((eq (get-text-property pos 'tag-type) 'start)
+ (web-mode-tag-match)
+ (setq close (point))
+ (goto-char pos)
+ )
+ ((eq (get-text-property pos 'tag-type) 'void)
+ )
+ ((eq (get-text-property pos 'tag-type) 'end)
+ (web-mode-tag-beginning)
+ (setq close (point))
+ (web-mode-tag-match)
+ )
+ ((web-mode-element-parent-position pos)
+ (setq pos (point))
+ (web-mode-tag-match)
+ (setq close (point))
+ (goto-char pos)
+ )
+ ) ;cond
+ (when (and close
+ (web-mode-element-next)
+ (< (point) close))
+ (setq child (point))
+ )
+ child)))
+
+(defun web-mode-element-parent-position (&optional pos)
+ (let (n tag-type tag-name (continue t) (tags (make-hash-table :test 'equal)))
+ (save-excursion
+ (if pos (goto-char pos))
+ (while (and continue (web-mode-tag-previous))
+ (setq pos (point)
+ tag-type (get-text-property pos 'tag-type)
+ tag-name (get-text-property pos 'tag-name)
+ n (gethash tag-name tags 0))
+ (when (member tag-type '(end start))
+ (if (eq tag-type 'end)
+ (puthash tag-name (1- n) tags)
+ (puthash tag-name (1+ n) tags)
+ (when (= n 0) (setq continue nil))
+ ) ;if
+ ) ;when
+ ) ;while
+ ) ;save-excursion
+ (if (null continue) pos nil)))
+
+(defun web-mode-element-previous-position (&optional pos limit)
+ (unless pos (setq pos (point)))
+ (unless limit (setq limit (point-min)))
+ (save-excursion
+ (goto-char pos)
+ (let ((continue (not (bobp)))
+ (props '(start void comment)))
+ (while continue
+ (setq pos (web-mode-tag-previous))
+ (cond
+ ((or (null pos) (< (point) limit))
+ (setq continue nil
+ pos nil))
+ ((member (get-text-property (point) 'tag-type) props)
+ (setq continue nil))
+ )
+ ) ;while
+ pos)))
+
+(defun web-mode-element-next-position (&optional pos limit)
+ (unless pos (setq pos (point)))
+ (unless limit (setq limit (point-max)))
+ (save-excursion
+ (goto-char pos)
+ (let ((continue (not (eobp)))
+ (props '(start void comment)))
+ (while continue
+ (setq pos (web-mode-tag-next))
+ (cond
+ ((or (null pos) (> (point) limit))
+ (setq continue nil
+ pos nil))
+ ((member (get-text-property (point) 'tag-type) props)
+ (setq continue nil))
+ )
+ ) ;while
+;; (message "pos=%S" pos)
+ pos)))
+
+(defun web-mode-part-end-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((member web-mode-content-type web-mode-part-content-types)
+ (setq pos (point-max)))
+ ((not (get-text-property pos 'part-side))
+ (setq pos nil))
+ ((= pos (point-max))
+ (setq pos nil))
+ ((not (get-text-property (1+ pos) 'part-side))
+ pos)
+ (t
+ (setq pos (next-single-property-change pos 'part-side)))
+ ) ;cond
+ pos)
+
+(defun web-mode-part-beginning-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ (web-mode-part-beg
+ (setq pos web-mode-part-beg))
+ ((member web-mode-content-type web-mode-part-content-types)
+ (setq pos (point-min)
+ web-mode-part-beg (point-min)))
+ ((not (get-text-property pos 'part-side))
+ (setq pos nil))
+ ((= pos (point-min))
+ (setq pos nil))
+ ((not (get-text-property (1- pos) 'part-side))
+ pos)
+ (t
+ (setq pos (previous-single-property-change pos 'part-side)))
+ ) ;cond
+ pos)
+
+(defun web-mode-part-next-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((and (= pos (point-min)) (get-text-property pos 'part-side))
+ )
+ ((not (get-text-property pos 'part-side))
+ (setq pos (next-single-property-change pos 'part-side)))
+ ((and (setq pos (web-mode-part-end-position pos)) (>= pos (point-max)))
+ (setq pos nil))
+ ((and (setq pos (1+ pos)) (not (get-text-property pos 'part-side)))
+ (setq pos (next-single-property-change pos 'part-side)))
+ ) ;cond
+ pos)
+
+(defun web-mode-block-match-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (save-excursion
+ (web-mode-block-match pos)
+ (if (= pos (point)) nil (point))))
+
+;; type may be nil
+(defun web-mode-block-control-previous-position (type &optional pos)
+ (unless pos (setq pos (point)))
+ (let ((continue t) controls)
+ (while continue
+ (setq pos (web-mode-block-previous-position pos))
+ (cond
+ ((null pos)
+ (setq continue nil
+ pos nil))
+ ((null type)
+ (setq continue nil))
+ ((and (setq controls (web-mode-block-controls-get pos))
+ (eq (car (car controls)) type))
+ (setq continue nil))
+ ) ;cond
+ ) ;while
+ pos))
+
+(defun web-mode-inside-block-control (&optional pos)
+ (unless pos (setq pos (point)))
+ (setq pos (web-mode-block-control-previous-position nil pos))
+ (if (and pos (member (car (car (web-mode-block-controls-get pos))) '(open inside)))
+ pos
+ nil))
+
+(defun web-mode-block-opening-paren-position (pos limit)
+ (save-excursion
+ (when (> limit pos)
+ (message "block-opening-paren-position: limit(%S) > pos(%S)" limit pos))
+ (goto-char pos)
+ (let (c
+ n
+ pt
+ (continue (> pos limit))
+ (pairs '((?\) . ?\()
+ (?\] . ?\[)
+ (?\} . ?\{)))
+ (h (make-hash-table :test 'equal))
+ (regexp "[\]\[)(}{]"))
+ (while (and continue (re-search-backward regexp limit t))
+ (cond
+ ((web-mode-is-comment-or-string)
+ )
+ (t
+ (setq c (char-after))
+ (cond
+ ((member c '(?\( ?\{ ?\[))
+ (setq n (gethash c h 0))
+ (if (= n 0)
+ (setq continue nil
+ pt (point))
+ (puthash c (1+ n) h)
+ ))
+ (t
+ (setq c (cdr (assoc c pairs)))
+ (setq n (gethash c h 0))
+ (puthash c (1- n) h))
+ ) ;cond
+ ) ;t
+ ) ;cond
+ ) ;while
+ pt)))
+
+(defun web-mode-block-code-beginning-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (when (and (setq pos (web-mode-block-beginning-position pos))
+ (eq (get-text-property pos 'block-token) 'delimiter-beg))
+ (setq pos (next-single-property-change pos 'block-token)))
+ pos)
+
+(defun web-mode-block-beginning-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((or (and (get-text-property pos 'block-side) (= pos (point-min)))
+ (get-text-property pos 'block-beg))
+ )
+ ((and (> pos (point-min)) (get-text-property (1- pos) 'block-beg))
+ (setq pos (1- pos)))
+ ((get-text-property pos 'block-side)
+ (setq pos (previous-single-property-change pos 'block-beg))
+ (setq pos (if (and pos (> pos (point-min))) (1- pos) (point-min))))
+ (t
+ (setq pos nil))
+ ) ;cond
+ pos)
+
+(defun web-mode-block-string-beginning-position (pos &optional block-beg)
+ (unless pos (setq pos (point)))
+ (unless block-beg (setq block-beg (web-mode-block-beginning-position pos)))
+ (let (char (ori pos) (continue (not (null pos))))
+ (while continue
+ (setq char (char-after pos))
+ (cond
+ ((< pos block-beg)
+ (setq continue nil
+ pos block-beg))
+ ((and (member (get-text-property pos 'block-token) '(string comment))
+ (eq (get-text-property pos 'block-token) (get-text-property (1- pos) 'block-token)))
+ (setq pos (web-mode-block-token-beginning-position pos))
+ )
+ ((member char '(?\) ?\]))
+ (setq pos (web-mode-block-opening-paren-position pos block-beg))
+ (setq pos (1- pos))
+ )
+ ((and (> ori pos) (member char '(?\( ?\= ?\[ ?\? ?\: ?\; ?\, ?\`)))
+ (if (and (eq char ?\:) ; #1024
+ (web-mode-looking-at ":" pos))
+ (setq pos (1- pos))
+ (web-mode-looking-at ".[ \t\n]*" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))
+ continue nil)
+ )
+ )
+ ((web-mode-looking-at "\\(return\\|echo\\|include\\|print\\)[ \n]" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))
+ continue nil))
+ (t
+ (setq pos (web-mode-rsb-position pos "[\]\[}{)(=?;,`:]\\|\\(return\\|echo\\|include\\|print\\)" block-beg))
+ (when (not pos)
+ (message "block-string-beginning-position ** search failure **")
+ (setq continue nil
+ pos block-beg)))
+ ) ;cond
+ ) ;while
+ ;;(message "pos=%S" pos)
+ pos))
+
+(defun web-mode-block-statement-beginning-position (pos block-beg is-ternary)
+ (unless pos (setq pos (point)))
+ (setq pos (1- pos))
+ (unless block-beg (setq block-beg (web-mode-block-beginning-position pos)))
+ (let (char (continue (not (null pos))))
+ (while continue
+ (setq char (char-after pos))
+ (cond
+ ((< pos block-beg)
+ (setq continue nil
+ pos block-beg))
+ ((and (member (get-text-property pos 'block-token) '(string comment))
+ (eq (get-text-property pos 'block-token) (get-text-property (1- pos) 'block-token)))
+ (setq pos (web-mode-block-token-beginning-position pos)))
+ ((member char '(?\) ?\] ?\}))
+ (setq pos (web-mode-block-opening-paren-position pos block-beg))
+ (setq pos (1- pos)))
+ ((and (eq char ?\=)
+ (web-mode-looking-back "[<>!=]+" pos block-beg t))
+ (setq pos (- pos 1 (length (match-string-no-properties 0))))
+ ;;(setq pos (1- pos))
+ ;;(message "%S pos=%S" (match-string-no-properties 0) pos)
+ )
+ ((member char '(?\( ?\[ ?\{ ?\=))
+ (setq continue nil)
+ (web-mode-looking-at ".[ \t\n]*" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))))
+ ((web-mode-looking-at "\\(return\\|echo\\|include\\|print\\)[ \n]" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))
+ continue nil))
+ (t
+ (setq pos (web-mode-rsb-position pos "[\]\[}{)(=]\\|\\(return\\|echo\\|include\\|print\\)" block-beg))
+ (when (not pos)
+ (message "block-statement-beginning-position ** search failure **")
+ (setq continue nil
+ pos block-beg)))
+ ) ;cond
+ ) ;while
+ pos))
+
+(defun web-mode-block-args-beginning-position (pos &optional block-beg)
+ (unless pos (setq pos (point)))
+ (setq pos (1- pos)) ;#512
+ (unless block-beg (setq block-beg (web-mode-block-beginning-position pos)))
+ (let (char (continue (not (null pos))))
+ (while continue
+ (setq char (char-after pos))
+ (cond
+ ((< pos block-beg)
+ (message "block-args-beginning-position ** failure **")
+ (setq continue nil
+ pos block-beg))
+ ((and (member (get-text-property pos 'block-token) '(string comment))
+ (eq (get-text-property pos 'block-token) (get-text-property (1- pos) 'block-token)))
+ (setq pos (web-mode-block-token-beginning-position pos)))
+ ((member char '(?\) ?\] ?\}))
+ (setq pos (web-mode-block-opening-paren-position pos block-beg))
+ (setq pos (1- pos)))
+ ((member char '(?\( ?\[ ?\{))
+ (setq continue nil)
+ (web-mode-looking-at ".[ \t\n]*" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))))
+ ((and (string= web-mode-engine "php")
+ (web-mode-looking-at "\\(extends\\|implements\\)[ \n]" pos))
+ (setq pos (+ pos (length (match-string-no-properties 0)))
+ continue nil))
+ (t
+ (setq pos (web-mode-rsb-position pos "[\]\[}{)(]\\|\\(extends\\|implements\\)" block-beg))
+ (when (not pos)
+ (message "block-args-beginning-position ** search failure **")
+ (setq pos block-beg
+ continue nil))
+ ) ;t
+ ) ;cond
+ ) ;while
+ pos))
+
+(defun web-mode-block-calls-beginning-position (pos &optional block-beg)
+ (unless pos (setq pos (point)))
+ (unless block-beg (setq block-beg (web-mode-block-beginning-position pos)))
+ (let (char (continue (not (null pos))))
+ (while continue
+ (setq char (char-after pos))
+ (cond
+ ((< pos block-beg)
+ (message "block-calls-beginning-position ** failure **")
+ (setq continue nil
+ pos block-beg))
+ ((and (member (get-text-property pos 'block-token) '(string comment))
+ (eq (get-text-property pos 'block-token) (get-text-property (1- pos) 'block-token)))
+ (setq pos (web-mode-block-token-beginning-position pos)))
+ ((member char '(?\) ?\]))
+ (setq pos (web-mode-block-opening-paren-position pos block-beg))
+ (setq pos (1- pos)))
+ ((member char '(?\( ?\[ ?\{ ?\} ?\= ?\? ?\: ?\; ?\,))
+ (web-mode-looking-at ".[ \t\n]*" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))
+ continue nil))
+ ((web-mode-looking-at "\\(return\\|else\\)[ \n]" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))
+ continue nil))
+ (t
+ (setq pos (web-mode-rsb-position pos "[\]\[}{)(=?:;,]\\|\\(return\\|else\\)" block-beg))
+ (when (not pos)
+ (message "block-calls-beginning-position ** search failure **")
+ (setq pos block-beg
+ continue nil))
+ ) ;t
+ ) ;cond
+ ) ;while
+ pos))
+
+(defun web-mode-javascript-string-beginning-position (pos &optional reg-beg)
+ (unless pos (setq pos (point)))
+ (let ((char nil)
+ (blockside (get-text-property pos 'block-side))
+ (i 0)
+ (continue (not (null pos))))
+ (unless reg-beg
+ (if blockside
+ (setq reg-beg (web-mode-block-beginning-position pos))
+ (setq reg-beg (web-mode-part-beginning-position pos)))
+ )
+ (while continue
+ (setq char (char-after pos))
+ (cond
+ ((> (setq i (1+ i)) 20000)
+ (message "javascript-string-beginning-position ** warning (%S) **" pos)
+ (setq continue nil
+ pos nil))
+ ((null pos)
+ (message "javascript-string-beginning-position ** invalid pos **")
+ (setq continue nil))
+ ((< pos reg-beg)
+ (message "javascript-string-beginning-position ** failure **")
+ (setq continue nil
+ pos reg-beg))
+ ((and blockside
+ (member (get-text-property pos 'block-token) '(string comment))
+ (eq (get-text-property pos 'block-token) (get-text-property (1- pos) 'block-token)))
+ (setq pos (web-mode-block-token-beginning-position pos)))
+ ((and (not blockside)
+ (member (get-text-property pos 'part-token) '(string comment))
+ (eq (get-text-property pos 'part-token) (get-text-property (1- pos) 'part-token)))
+ (setq pos (web-mode-part-token-beginning-position pos)))
+ ((and (not blockside)
+ (get-text-property pos 'block-side))
+ (when (setq pos (web-mode-block-beginning-position pos))
+ (setq pos (1- pos))))
+ ((member char '(?\) ?\] ?\}))
+ (setq pos (web-mode-part-opening-paren-position pos reg-beg))
+ (setq pos (1- pos)))
+ ((member char '(?\( ?\{ ?\[ ?\= ?\? ?\: ?\; ?\, ?\& ?\|))
+ (setq continue nil)
+ (web-mode-looking-at ".[ \t\n]*" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))))
+ ((web-mode-looking-at "\\(return\\)[ \n]" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))
+ continue nil))
+ (t
+ (setq pos (web-mode-rsb-position pos "[\]\[}{)(=?:;,&|]\\|\\(return\\)" reg-beg))
+ (when (not pos)
+ (message "javascript-string-beginning-position ** search failure **")
+ (setq continue nil
+ pos reg-beg)))
+ ) ;cond
+ ) ;while
+ ;;(message "js-statement-beg:%S" pos)
+ pos))
+
+;; TODO: reg-beg : jsx-beg
+;; TODO: skipper les expr dont la depth est superieure
+
+;; NOTE: blockside is useful for ejs
+(defun web-mode-javascript-statement-beginning-position (pos reg-beg is-ternary)
+ (unless pos (setq pos (point)))
+ (setq pos (1- pos))
+ (let ((char nil)
+ (blockside (get-text-property pos 'block-side))
+ (i 0)
+ (is-jsx (string= web-mode-content-type "jsx"))
+ (depth-o nil) (depth-l nil)
+ (continue (not (null pos)))
+ (regexp "[\]\[}{)(=:]\\|\\(return\\)"))
+ (when is-ternary
+ (setq regexp (concat regexp "\\|[><]")))
+ (setq depth-o (get-text-property pos 'jsx-depth))
+ (unless reg-beg
+ (cond
+ (blockside
+ (setq reg-beg (web-mode-block-beginning-position pos)))
+ (is-jsx
+ (setq reg-beg (web-mode-jsx-depth-beginning-position pos)))
+ (t
+ (setq reg-beg (web-mode-part-beginning-position pos)))
+ ) ;cond
+ ) ;unless
+ (while continue
+ (setq char (char-after pos))
+ (cond
+ ((> (setq i (1+ i)) 20000)
+ (message "javascript-statement-beginning-position ** warning (%S) **" pos)
+ (setq continue nil
+ pos nil))
+ ((null pos)
+ (message "javascript-statement-beginning-position ** invalid pos **")
+ (setq continue nil))
+ ((< pos reg-beg)
+ (when (not is-jsx)
+ (message "javascript-statement-beginning-position ** failure **"))
+ (setq continue nil
+ pos reg-beg))
+ ((and is-jsx
+ (progn (setq depth-l (get-text-property pos 'jsx-depth)) t)
+ (not (eq depth-l depth-o)))
+ ;;(message "%S > depth-o(%S) depth-l(%S)" pos depth-o depth-l)
+ (setq pos (previous-single-property-change pos 'jsx-depth))
+ (setq pos (1- pos))
+ ;;(message "--> %S %S" pos (get-text-property pos 'jsx-depth))
+ )
+ ((and blockside
+ (member (get-text-property pos 'block-token) '(string comment))
+ (eq (get-text-property pos 'block-token) (get-text-property (1- pos) 'block-token)))
+ (setq pos (web-mode-block-token-beginning-position pos)))
+ ((and (not blockside)
+ (member (get-text-property pos 'part-token) '(string comment))
+ (eq (get-text-property pos 'part-token) (get-text-property (1- pos) 'part-token)))
+ (setq pos (web-mode-part-token-beginning-position pos)))
+ ((and (not blockside)
+ (get-text-property pos 'block-side))
+ (when (setq pos (web-mode-block-beginning-position pos))
+ (setq pos (1- pos))))
+ ((member char '(?\) ?\] ?\}))
+ (setq pos (web-mode-part-opening-paren-position pos reg-beg))
+ (setq pos (1- pos)))
+ ((and (eq char ?\=)
+ (web-mode-looking-back "[<>!=]+" pos reg-beg t))
+ (setq pos (- pos 1 (length (match-string-no-properties 0)))))
+ ((member char '(?\( ?\{ ?\[ ?\= ?\< ?\>))
+ (web-mode-looking-at ".[ \t\n]*" pos)
+ (setq continue nil
+ pos (+ pos (length (match-string-no-properties 0)))))
+
+ ((web-mode-looking-at "\\(return\\)[ \n]" pos)
+ (setq continue nil
+ pos (+ pos (length (match-string-no-properties 0)))))
+ ((and (eq char ?\:)
+ (web-mode-looking-back "[{,][ \t\n]*[[:alnum:]_]+[ ]*" pos))
+ (web-mode-looking-at ".[ \t\n]*" pos)
+ (setq continue nil
+ pos (+ pos (length (match-string-no-properties 0)))))
+ (t
+ (setq pos (web-mode-rsb-position pos regexp reg-beg))
+ (when (not pos)
+ (cond
+ (is-jsx
+ (when (web-mode-looking-at "[ \n]*" reg-beg)
+ (setq pos (+ reg-beg (length (match-string-no-properties 0)))))
+ (setq continue nil))
+ (t
+ (message "javascript-statement-beginning-position ** search failure **")
+ (setq continue nil
+ pos reg-beg))
+ ) ;cond
+ )
+ ) ;t
+ ) ;cond
+ ) ;while
+ ;;(message "%S -------" pos)
+ pos))
+
+(defun web-mode-javascript-args-beginning-position (pos &optional reg-beg)
+ (unless pos (setq pos (point)))
+ (setq pos (1- pos))
+ (let ((char nil)
+ (blockside (get-text-property pos 'block-side))
+ (i 0)
+ (continue (not (null pos))))
+ (unless reg-beg
+ (if blockside
+ (setq reg-beg (web-mode-block-beginning-position pos))
+ (setq reg-beg (web-mode-part-beginning-position pos)))
+ )
+ (while continue
+ (setq char (char-after pos))
+ ;;(message "pos(%S) char(%c)" pos char)
+ (cond
+ ((> (setq i (1+ i)) 20000)
+ (message "javascript-args-beginning-position ** warning (%S) **" pos)
+ (setq continue nil
+ pos nil))
+ ((null pos)
+ (message "javascript-args-beginning-position ** invalid pos **")
+ (setq continue nil))
+ ((< pos reg-beg)
+ (message "javascript-args-beginning-position ** failure(position) **")
+ (setq continue nil
+ pos reg-beg))
+ ((and blockside
+ (member (get-text-property pos 'block-token) '(string comment))
+ (eq (get-text-property pos 'block-token) (get-text-property (1- pos) 'block-token)))
+ (setq pos (web-mode-block-token-beginning-position pos)))
+ ((and (not blockside)
+ (member (get-text-property pos 'part-token) '(string comment))
+ (eq (get-text-property pos 'part-token) (get-text-property (1- pos) 'part-token)))
+ (setq pos (web-mode-part-token-beginning-position pos)))
+ ((and (not blockside)
+ (get-text-property pos 'block-side))
+ (when (setq pos (web-mode-block-beginning-position pos))
+ (setq pos (1- pos)))
+ )
+ ((member char '(?\) ?\] ?\}))
+ (when (setq pos (web-mode-part-opening-paren-position pos reg-beg))
+ (setq pos (1- pos))))
+ ((member char '(?\( ?\[ ?\{))
+ (web-mode-looking-at ".[ ]*" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))
+ continue nil)
+ )
+ ((web-mode-looking-at "\\(var\\|let\\|return\\|const\\)[ \n]" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))
+ continue nil))
+ (t
+ (setq pos (web-mode-rsb-position pos "[\]\[}{)(]\\|\\(var\\|let\\|return\\|const\\)" reg-beg))
+ (when (not pos)
+ (message "javascript-args-beginning-position ** search failure **")
+ (setq continue nil
+ pos reg-beg)))
+ ) ;cond
+ ) ;while
+ ;;(message "=%S" pos)
+ pos))
+
+(defun web-mode-javascript-calls-beginning-position (pos &optional reg-beg)
+ (unless pos (setq pos (point)))
+ ;;(message "pos=%S" pos)
+ (let ((char nil)
+ (dot-pos nil)
+ (blockside (get-text-property pos 'block-side))
+ (i 0)
+ (continue (not (null pos))))
+ (unless reg-beg
+ (setq reg-beg (if blockside
+ (web-mode-block-beginning-position pos)
+ (web-mode-part-beginning-position pos))))
+ (while continue
+ (setq char (char-after pos))
+ ;;(message "%S| %S=%c" reg-beg pos char)
+ (cond
+ ((> (setq i (1+ i)) 20000)
+ (message "javascript-calls-beginning-position ** warning (%S) **" pos)
+ (setq continue nil
+ pos nil))
+ ((null pos)
+ (message "javascript-calls-beginning-position ** invalid pos **")
+ (setq continue nil))
+ ((< pos reg-beg)
+ (setq continue nil
+ pos reg-beg))
+ ((and blockside
+ (member (get-text-property pos 'block-token) '(string comment))
+ (eq (get-text-property pos 'block-token) (get-text-property (1- pos) 'block-token)))
+ (setq pos (web-mode-block-token-beginning-position pos)))
+ ((and (not blockside)
+ (member (get-text-property pos 'part-token) '(string comment))
+ (eq (get-text-property pos 'part-token) (get-text-property (1- pos) 'part-token)))
+ (setq pos (web-mode-part-token-beginning-position pos)))
+ ((and (not blockside)
+ (get-text-property pos 'block-side))
+ (when (setq pos (web-mode-block-beginning-position pos))
+ (setq pos (1- pos))))
+ ((and (member char '(?\.)) (> i 1))
+ (setq dot-pos pos
+ pos (1- pos)))
+ ((member char '(?\) ?\]))
+ (when (setq pos (web-mode-part-opening-paren-position pos reg-beg))
+ (setq pos (1- pos)))
+ )
+ ((member char '(?\( ?\{ ?\} ?\[ ?\= ?\? ?\: ?\; ?\, ?\& ?\| ?\>))
+ (web-mode-looking-at ".[ \t\n]*" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))
+ continue nil))
+ ((web-mode-looking-at "\\(return\\|else\\|const\\)[ \n]" pos)
+ (setq pos (+ pos (length (match-string-no-properties 0)))
+ continue nil))
+ (t
+ (setq pos (web-mode-rsb-position pos "[\]\[}{)(=?:;,&|>.]\\|\\(return\\|else\\|const\\)" reg-beg))
+ (when (not pos)
+ (message "javascript-calls-beginning-position ** search failure **")
+ (setq pos reg-beg
+ continue nil))
+ ) ;t
+ ) ;cond
+ ) ;while
+ ;;(message "pos=%S dot-pos=%S" pos dot-pos)
+ (if (null pos) pos (cons pos dot-pos))
+ ))
+
+(defun web-mode-part-token-beginning-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((not (get-text-property pos 'part-token))
+ nil)
+ ((or (= pos (point-min))
+ (and (> pos (point-min))
+ (not (get-text-property (1- pos) 'part-token))))
+ pos)
+ (t
+ (setq pos (previous-single-property-change pos 'part-token))
+ (if (and pos (> pos (point-min))) pos (point-min)))
+ ))
+
+(defun web-mode-part-token-end-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((not (get-text-property pos 'part-token))
+ nil)
+ ((or (= pos (point-max))
+ (not (get-text-property (1+ pos) 'part-token)))
+ pos)
+ (t
+ (1- (next-single-property-change pos 'part-token)))
+ ))
+
+(defun web-mode-block-token-beginning-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((not (get-text-property pos 'block-token))
+ nil)
+ ((or (= pos (point-min))
+ (and (> pos (point-min))
+ (not (get-text-property (1- pos) 'block-token))))
+ pos)
+ (t
+ (setq pos (previous-single-property-change pos 'block-token))
+ (if (and pos (> pos (point-min))) pos (point-min)))
+ ))
+
+(defun web-mode-block-token-end-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((not (get-text-property pos 'block-token))
+ nil)
+ ((or (= pos (point-max))
+ (not (get-text-property (1+ pos) 'block-token)))
+ pos)
+ (t
+ (1- (next-single-property-change pos 'block-token)))
+ ))
+
+(defun web-mode-block-code-end-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (setq pos (web-mode-block-end-position pos))
+ (cond
+ ((not pos)
+ nil)
+ ((and (eq (get-text-property pos 'block-token) 'delimiter-end)
+ (eq (get-text-property (1- pos) 'block-token) 'delimiter-end))
+ (previous-single-property-change pos 'block-token))
+ ((= pos (1- (point-max))) ;; TODO: comparer plutot avec line-end-position
+ (point-max))
+ (t
+ pos)
+ ))
+
+(defun web-mode-block-end-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((get-text-property pos 'block-end)
+ pos)
+ ((get-text-property pos 'block-side)
+ (or (next-single-property-change pos 'block-end)
+ (point-max)))
+ (t
+ nil)
+ ))
+
+(defun web-mode-block-previous-position (&optional pos)
+ (unless pos (setq pos (point)))
+ (cond
+ ((= pos (point-min))
+ (setq pos nil))
+ ((get-text-property pos 'block-side)
+ (setq pos (web-mode-block-beginning-position pos))
+ (cond
+ ((or (null pos) (= pos (point-min)))
+ (setq pos nil)
+ )
+ ((and (setq pos (previous-single-property-change pos 'block-beg))
+ (> pos (point-min)))
+ (setq pos (1- pos))
+ )
+ )
+ ) ;block-side
+ ((get-text-property (1- pos) 'block-side)
+ (setq pos (web-mode-block-beginning-position (1- pos)))
+ )
+ (t
+ (setq pos (previous-single-property-change pos 'block-side))
+ (cond
+ ((and (null pos) (get-text-property (point-min) 'block-beg))
+ (setq pos (point-min)))
+ ((and pos (> pos (point-min)))
+ (setq pos (web-mode-block-beginning-position (1- pos))))
+ )
+ )
+ ) ;conf
+ pos)
+
+(defun web-mode-block-next-position (&optional pos limit)
+ (unless pos (setq pos (point)))
+ (unless limit (setq limit (point-max)))
+ (cond
+ ((and (get-text-property pos 'block-side)
+ (setq pos (web-mode-block-end-position pos))
+ (< pos (point-max))
+ (setq pos (1+ pos)))
+ (unless (get-text-property pos 'block-beg)
+ (setq pos (next-single-property-change pos 'block-side)))
+ )
+ (t
+ (setq pos (next-single-property-change pos 'block-side)))
+ ) ;cond
+ (if (and pos (<= pos limit)) pos nil))
+
+(defun web-mode-is-css-string (pos)
+ (let (beg)
+ (cond
+ ((and (setq beg (web-mode-part-token-beginning-position pos))
+ (web-mode-looking-at-p "`" beg)
+ (web-mode-looking-back "\\(styled[[:alnum:].]+\\|css\\)" beg))
+ beg)
+ (t
+ nil)
+ ) ;cond
+ ))
+
+;; Relay.QL , gql, graphql
+(defun web-mode-is-ql-string (pos prefix-regexp)
+ (let (beg)
+ (cond
+ ((and (setq beg (web-mode-part-token-beginning-position pos))
+ (web-mode-looking-back prefix-regexp beg))
+ beg)
+ (t
+ nil)
+ ) ;cond
+ ))
+
+(defun web-mode-is-html-string (pos)
+ (let (beg)
+ (cond
+ ((and (setq beg (web-mode-part-token-beginning-position pos))
+ (web-mode-looking-at-p "`[ \t\n]*<[a-zA-Z]" beg)
+ (web-mode-looking-back "\\(template\\|html\\)\\([ ]*[=:][ ]*\\)?" beg))
+ beg)
+ (t
+ nil)
+ ) ;cond
+ ))
+
+;;---- EXCURSION ---------------------------------------------------------------
+
+(defun web-mode-backward-sexp (n)
+ (interactive "p")
+ (if (< n 0) (web-mode-forward-sexp (- n))
+ (let (pos)
+ (dotimes (_ n)
+ (skip-chars-backward "[:space:]")
+ (setq pos (point))
+ (cond
+ ((bobp) nil)
+ ((get-text-property (1- pos) 'block-end)
+ (backward-char 1)
+ (web-mode-block-beginning))
+ ((get-text-property (1- pos) 'block-token)
+ (backward-char 1)
+ (web-mode-block-token-beginning))
+ ((get-text-property (1- pos) 'part-token)
+ (backward-char 1)
+ (web-mode-part-token-beginning))
+ ((get-text-property (1- pos) 'tag-end)
+ (backward-char 1)
+ (web-mode-element-beginning))
+ ((get-text-property (1- pos) 'tag-attr)
+ (backward-char 1)
+ (web-mode-attribute-beginning))
+ ((get-text-property (1- pos) 'tag-type)
+ (backward-char 1)
+ (web-mode-tag-beginning))
+ ((get-text-property (1- pos) 'jsx-end)
+ (backward-char 1)
+ (web-mode-jsx-beginning))
+ (t
+ (let ((forward-sexp-function nil))
+ (backward-sexp))
+ ) ;case t
+ ) ;cond
+ ) ;dotimes
+ ))) ;let if defun
+
+(defun web-mode-forward-sexp (n)
+ (interactive "p")
+ (if (< n 0) (web-mode-backward-sexp (- n))
+ (let (pos)
+ (dotimes (_ n)
+ (skip-chars-forward "[:space:]")
+ (setq pos (point))
+ (cond
+ ((eobp) nil)
+ ((get-text-property pos 'block-beg)
+ (web-mode-block-end))
+ ((get-text-property pos 'block-token)
+ (web-mode-block-token-end))
+ ((get-text-property pos 'part-token)
+ (web-mode-part-token-end))
+ ((get-text-property pos 'tag-beg)
+ (web-mode-element-end))
+ ((get-text-property pos 'tag-attr)
+ (web-mode-attribute-end))
+ ((get-text-property pos 'tag-type)
+ (web-mode-tag-end))
+ ((get-text-property pos 'jsx-beg)
+ (web-mode-jsx-end))
+ (t
+ (let ((forward-sexp-function nil))
+ (forward-sexp))
+ ) ;case t
+ ) ;cond
+ ) ;dotimes
+ ))) ;let if defun
+
+(defun web-mode-comment-beginning ()
+ "Fetch current comment beg."
+ (interactive)
+ (web-mode-go (web-mode-comment-beginning-position (point))))
+
+(defun web-mode-comment-end ()
+ "Fetch current comment end."
+ (interactive)
+ (web-mode-go (web-mode-comment-end-position (point)) 1))
+
+(defun web-mode-tag-beginning ()
+ "Fetch current html tag beg."
+ (interactive)
+ (web-mode-go (web-mode-tag-beginning-position (point))))
+
+(defun web-mode-tag-end ()
+ "Fetch current html tag end."
+ (interactive)
+ (web-mode-go (web-mode-tag-end-position (point)) 1))
+
+(defun web-mode-tag-previous ()
+ "Fetch previous tag."
+ (interactive)
+ (web-mode-go (web-mode-tag-previous-position (point))))
+
+(defun web-mode-tag-next ()
+ "Fetch next tag. Might be html comment or server tag (e.g. jsp)."
+ (interactive)
+ (web-mode-go (web-mode-tag-next-position (point))))
+
+(defun web-mode-attribute-beginning ()
+ "Fetch html attribute beginning."
+ (interactive)
+ (web-mode-go (web-mode-attribute-beginning-position (point))))
+
+(defun web-mode-attribute-end ()
+ "Fetch html attribute end."
+ (interactive)
+ (web-mode-go (web-mode-attribute-end-position (point)) 1))
+
+(defun web-mode-attribute-next (&optional arg)
+ "Fetch next attribute."
+ (interactive "p")
+ (unless arg (setq arg 1))
+ (cond
+ ((= arg 1) (web-mode-go (web-mode-attribute-next-position (point))))
+ ((< arg 1) (web-mode-element-previous (* arg -1)))
+ (t
+ (while (>= arg 1)
+ (setq arg (1- arg))
+ (web-mode-go (web-mode-attribute-next-position (point)))
+ )
+ )
+ )
+ )
+
+(defun web-mode-attribute-previous (&optional arg)
+ "Fetch previous attribute."
+ (interactive "p")
+ (unless arg (setq arg 1))
+ (unless arg (setq arg 1))
+ (cond
+ ((= arg 1) (web-mode-go (web-mode-attribute-previous-position (point))))
+ ((< arg 1) (web-mode-element-next (* arg -1)))
+ (t
+ (while (>= arg 1)
+ (setq arg (1- arg))
+ (web-mode-go (web-mode-attribute-previous-position (point)))
+ )
+ )
+ )
+ )
+
+(defun web-mode-element-previous (&optional arg)
+ "Fetch previous element."
+ (interactive "p")
+ (unless arg (setq arg 1))
+ (cond
+ ((= arg 1) (web-mode-go (web-mode-element-previous-position (point))))
+ ((< arg 1) (web-mode-element-next (* arg -1)))
+ (t
+ (while (>= arg 1)
+ (setq arg (1- arg))
+ (web-mode-go (web-mode-element-previous-position (point)))
+ ) ;while
+ ) ;t
+ ) ;cond
+ )
+
+(defun web-mode-element-next (&optional arg)
+ "Fetch next element."
+ (interactive "p")
+ (unless arg (setq arg 1))
+ (cond
+ ((= arg 1) (web-mode-go (web-mode-element-next-position (point))))
+ ((< arg 1) (web-mode-element-previous (* arg -1)))
+ (t
+ (while (>= arg 1)
+ (setq arg (1- arg))
+ (web-mode-go (web-mode-element-next-position (point)))
+ ) ;while
+ ) ;t
+ ) ;cond
+ )
+
+(defun web-mode-element-sibling-next ()
+ "Fetch next sibling element."
+ (interactive)
+ (let ((pos (point)))
+ (save-excursion
+ (cond
+ ((not (get-text-property pos 'tag-type))
+ (if (and (web-mode-element-parent)
+ (web-mode-tag-match)
+ (web-mode-tag-next)
+ (member (get-text-property (point) 'tag-type) '(start void comment)))
+ (setq pos (point))
+ (setq pos nil))
+ )
+ ((member (get-text-property pos 'tag-type) '(start void))
+ (if (and (web-mode-tag-match)
+ (web-mode-tag-next)
+ (member (get-text-property (point) 'tag-type) '(start void comment)))
+ (setq pos (point))
+ (setq pos nil))
+ )
+ ((and (web-mode-tag-next)
+ (member (get-text-property (point) 'tag-type) '(start void comment)))
+ (setq pos (point)))
+ (t
+ (setq pos nil))
+ ) ;cond
+ ) ;save-excursion
+ (web-mode-go pos)))
+
+(defun web-mode-element-sibling-previous ()
+ "Fetch previous sibling element."
+ (interactive)
+ (let ((pos (point)))
+ (save-excursion
+ (cond
+ ((not (get-text-property pos 'tag-type))
+ (if (and (web-mode-element-parent)
+ (web-mode-tag-previous)
+ (web-mode-element-beginning))
+ (setq pos (point))
+ (setq pos nil))
+ )
+ ((eq (get-text-property pos 'tag-type) 'start)
+ (if (and (web-mode-tag-beginning)
+ (web-mode-tag-previous)
+ (web-mode-element-beginning))
+ (setq pos (point))
+ (setq pos nil))
+ )
+ ((and (web-mode-element-beginning)
+ (web-mode-tag-previous)
+ (web-mode-element-beginning))
+ (setq pos (point)))
+ (t
+ (setq pos nil))
+ ) ;cond
+ ) ;save-excursion
+ (web-mode-go pos)))
+
+(defun web-mode-element-beginning ()
+ "Move to beginning of element."
+ (interactive)
+ (web-mode-go (web-mode-element-beginning-position (point))))
+
+(defun web-mode-element-end ()
+ "Move to end of element."
+ (interactive)
+ (web-mode-go (web-mode-element-end-position (point)) 1))
+
+(defun web-mode-element-parent ()
+ "Fetch parent element."
+ (interactive)
+ (web-mode-go (web-mode-element-parent-position (point))))
+
+(defun web-mode-element-child ()
+ "Fetch child element."
+ (interactive)
+ (web-mode-go (web-mode-element-child-position (point))))
+
+(defun web-mode-dom-traverse ()
+ "Traverse html dom tree."
+ (interactive)
+ (cond
+ ((web-mode-element-child)
+ )
+ ((web-mode-element-sibling-next)
+ )
+ ((and (web-mode-element-parent)
+ (not (web-mode-element-sibling-next)))
+ (goto-char (point-min)))
+ (t
+ (goto-char (point-min)))
+ ) ;cond
+ )
+
+(defun web-mode-closing-paren (limit)
+ (let ((pos (web-mode-closing-paren-position (point) limit)))
+ (if (or (null pos) (> pos limit))
+ nil
+ (goto-char pos)
+ pos)
+ ))
+
+(defun web-mode-part-next ()
+ "Move point to the beginning of the next part."
+ (interactive)
+ (web-mode-go (web-mode-part-next-position (point))))
+
+(defun web-mode-part-beginning ()
+ "Move point to the beginning of the current part."
+ (interactive)
+ (web-mode-go (web-mode-part-beginning-position (point))))
+
+(defun web-mode-part-end ()
+ "Move point to the end of the current part."
+ (interactive)
+ (web-mode-go (web-mode-part-end-position (point)) 1))
+
+(defun web-mode-block-previous ()
+ "Move point to the beginning of the previous block."
+ (interactive)
+ (web-mode-go (web-mode-block-previous-position (point))))
+
+(defun web-mode-block-next ()
+ "Move point to the beginning of the next block."
+ (interactive)
+ (web-mode-go (web-mode-block-next-position (point))))
+
+(defun web-mode-block-beginning ()
+ "Move point to the beginning of the current block."
+ (interactive)
+ (web-mode-go (web-mode-block-beginning-position (point))))
+
+(defun web-mode-block-end ()
+ "Move point to the end of the current block."
+ (interactive)
+ (web-mode-go (web-mode-block-end-position (point)) 1))
+
+(defun web-mode-block-token-beginning ()
+ (web-mode-go (web-mode-block-token-beginning-position (point))))
+
+(defun web-mode-block-token-end ()
+ (web-mode-go (web-mode-block-token-end-position (point)) 1))
+
+(defun web-mode-part-token-beginning ()
+ (web-mode-go (web-mode-part-token-beginning-position (point))))
+
+(defun web-mode-part-token-end ()
+ (web-mode-go (web-mode-part-token-end-position (point)) 1))
+
+(defun web-mode-block-opening-paren (limit)
+ (web-mode-go (web-mode-block-opening-paren-position (point) limit)))
+
+(defun web-mode-block-string-beginning (&optional pos block-beg)
+ (unless pos (setq pos (point)))
+ (unless block-beg (setq block-beg (web-mode-block-beginning-position pos)))
+ (web-mode-go (web-mode-block-string-beginning-position pos block-beg)))
+
+(defun web-mode-block-statement-beginning (pos block-beg is-ternary)
+ (unless pos (setq pos (point)))
+ (unless block-beg (setq block-beg (web-mode-block-beginning-position pos)))
+ (web-mode-go (web-mode-block-statement-beginning-position pos block-beg is-ternary)))
+
+(defun web-mode-block-args-beginning (&optional pos block-beg)
+ (unless pos (setq pos (point)))
+ (unless block-beg (setq block-beg (web-mode-block-beginning-position pos)))
+ (web-mode-go (web-mode-block-args-beginning-position pos block-beg)))
+
+(defun web-mode-block-calls-beginning (&optional pos block-beg)
+ (unless pos (setq pos (point)))
+ (unless block-beg (setq block-beg (web-mode-block-beginning-position pos)))
+ (web-mode-go (web-mode-block-calls-beginning-position pos block-beg)))
+
+(defun web-mode-javascript-string-beginning (&optional pos reg-beg)
+ (unless pos (setq pos (point)))
+ (unless reg-beg
+ (if (get-text-property pos 'block-side)
+ (setq reg-beg (web-mode-block-beginning-position pos))
+ (setq reg-beg (web-mode-part-beginning-position pos))))
+ (web-mode-go (web-mode-javascript-string-beginning-position pos reg-beg)))
+
+(defun web-mode-javascript-statement-beginning (pos reg-beg is-ternary)
+ (unless pos (setq pos (point)))
+ (unless reg-beg
+ (if (get-text-property pos 'block-side)
+ (setq reg-beg (web-mode-block-beginning-position pos))
+ (setq reg-beg (web-mode-part-beginning-position pos))))
+ (web-mode-go (web-mode-javascript-statement-beginning-position pos reg-beg is-ternary)))
+
+(defun web-mode-javascript-args-beginning (&optional pos reg-beg)
+ (unless pos (setq pos (point)))
+ (unless reg-beg
+ (setq reg-beg (if (get-text-property pos 'block-side)
+ (web-mode-block-beginning-position pos)
+ (web-mode-part-beginning-position pos))))
+ ;;(message "reg-beg%S" reg-beg)
+ (web-mode-go (web-mode-javascript-args-beginning-position pos reg-beg)))
+
+(defun web-mode-javascript-calls-beginning (&optional pos reg-beg)
+ (unless pos (setq pos (point)))
+ (unless reg-beg
+ (if (get-text-property pos 'block-side)
+ (setq reg-beg (web-mode-block-beginning-position pos))
+ (setq reg-beg (web-mode-part-beginning-position pos))))
+ (let (pair)
+ (setq pair (web-mode-javascript-calls-beginning-position pos reg-beg))
+ (when pair (web-mode-go (car pair)))
+ ))
+
+(defun web-mode-go (pos &optional offset)
+ (unless offset (setq offset 0))
+ (when pos
+ (cond
+ ((and (> offset 0) (<= (+ pos offset) (point-max)))
+ (setq pos (+ pos offset)))
+ ((and (< offset 0) (>= (+ pos offset) (point-min)))
+ (setq pos (+ pos offset)))
+ ) ;cond
+ (goto-char pos))
+ pos)
+
+;;---- SEARCH ------------------------------------------------------------------
+
+(defun web-mode-rsf-balanced (regexp-open regexp-close &optional limit noerror)
+ (unless noerror (setq noerror t))
+ (let ((continue t)
+ (level 1)
+ (pos (point))
+ ret
+ (regexp (concat regexp-open "\\|" regexp-close)))
+ (while continue
+ (setq ret (re-search-forward regexp limit noerror))
+ (cond
+ ((null ret)
+ (setq continue nil)
+ )
+ (t
+ (if (string-match-p regexp-open (match-string-no-properties 0))
+ (setq level (1+ level))
+ (setq level (1- level)))
+ (when (< level 1)
+ (setq continue nil)
+ )
+ ) ;t
+ ) ;cond
+ ) ;while
+ (when (not (= level 0)) (goto-char pos))
+ ret))
+
+(defun web-mode-block-sb (expr &optional limit noerror)
+ (unless limit (setq limit (web-mode-block-beginning-position (point))))
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (search-backward expr limit noerror))
+ (when (or (null ret)
+ (not (get-text-property (point) 'block-token)))
+ (setq continue nil)
+ ) ;when
+ ) ;while
+ ret))
+
+(defun web-mode-block-sf (expr &optional limit noerror)
+ (unless limit (setq limit (web-mode-block-end-position (point))))
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (search-forward expr limit noerror))
+ (when (or (null ret)
+ (not (get-text-property (point) 'block-token)))
+ (setq continue nil)
+ ) ;when
+ ) ;while
+ ret))
+
+(defun web-mode-block-rsb (regexp &optional limit noerror)
+ (unless limit (setq limit (web-mode-block-beginning-position (point))))
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (re-search-backward regexp limit noerror))
+ (when (or (null ret)
+ (not (get-text-property (point) 'block-token)))
+ (setq continue nil)
+ ) ;when
+ ) ;while
+ ret))
+
+(defun web-mode-block-rsf (regexp &optional limit noerror)
+ (unless limit (setq limit (web-mode-block-end-position (point))))
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (re-search-forward regexp limit noerror))
+ (when (or (null ret)
+ (not (get-text-property (point) 'block-token)))
+ (setq continue nil)
+ ) ;when
+ ) ;while
+ ret))
+
+(defun web-mode-part-sb (expr &optional limit noerror)
+ (unless limit (setq limit (web-mode-part-beginning-position (point))))
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (search-backward expr limit noerror))
+ (when (or (null ret)
+ (and (not (get-text-property (point) 'part-token))
+ (not (get-text-property (point) 'block-side)))
+ )
+ (setq continue nil)
+ ) ;when
+ ) ;while
+ ret))
+
+(defun web-mode-part-sf (expr &optional limit noerror)
+ (unless limit (setq limit (web-mode-part-end-position (point))))
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (search-forward expr limit noerror))
+ (when (or (null ret)
+ (and (not (get-text-property (point) 'part-token))
+ (not (get-text-property (point) 'block-side)))
+ )
+ (setq continue nil)
+ ) ;when
+ ) ;while
+ ret))
+
+(defun web-mode-part-rsb (regexp &optional limit noerror)
+ (unless limit (setq limit (web-mode-part-beginning-position (point))))
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (re-search-backward regexp limit noerror))
+ (when (or (null ret)
+ (and (not (get-text-property (point) 'part-token))
+ (not (get-text-property (point) 'block-side)))
+ )
+ (setq continue nil)
+ ) ;when
+ ) ;while
+ ret))
+
+(defun web-mode-part-rsf (regexp &optional limit noerror)
+ (unless limit (setq limit (web-mode-part-end-position (point))))
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (re-search-forward regexp limit t))
+ (when (or (null ret)
+ (and (not (get-text-property (point) 'part-token))
+ (not (get-text-property (point) 'block-side)))
+ )
+ (setq continue nil)
+ ) ;when
+ ) ;while
+ ret))
+
+(defun web-mode-javascript-rsb (regexp &optional limit noerror)
+ (unless limit (setq limit (web-mode-part-beginning-position (point))))
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (re-search-backward regexp limit noerror))
+ (when (or (null ret)
+ (and (not (get-text-property (point) 'part-token))
+ (not (get-text-property (point) 'block-side))
+ (not (get-text-property (point) 'jsx-depth)))
+ )
+ (setq continue nil)
+ ) ;when
+ ) ;while
+ ret))
+
+(defun web-mode-javascript-rsf (regexp &optional limit noerror)
+ (unless limit (setq limit (web-mode-part-end-position (point))))
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (re-search-forward regexp limit t))
+ (when (or (null ret)
+ (and (not (get-text-property (point) 'part-token))
+ (not (get-text-property (point) 'block-side))
+ (not (get-text-property (point) 'jsx-depth)))
+ )
+ (setq continue nil)
+ ) ;when
+ ) ;while
+ ret))
+
+(defun web-mode-dom-sf (expr &optional limit noerror)
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (search-forward expr limit noerror))
+ (if (or (null ret)
+ (not (get-text-property (- (point) (length expr)) 'block-side)))
+ (setq continue nil))
+ )
+ ret))
+
+(defun web-mode-dom-rsf (regexp &optional limit noerror)
+ (unless noerror (setq noerror t))
+ (let ((continue t) (ret nil))
+ (while continue
+ (setq ret (re-search-forward regexp limit noerror))
+ ;; (message "ret=%S point=%S limit=%S i=%S" ret (point) limit 0)
+ (cond
+ ((null ret)
+ (setq continue nil))
+ ((or (get-text-property (match-beginning 0) 'block-side)
+ (get-text-property (match-beginning 0) 'part-token))
+ )
+ (t
+ (setq continue nil))
+ ) ;cond
+ ) ;while
+ ret))
+
+(defun web-mode-rsb-position (pos regexp &optional limit noerror)
+ (unless noerror (setq noerror t))
+ (save-excursion
+ (goto-char pos)
+ (if (re-search-backward regexp limit noerror) (point) nil)
+ ))
+
+(defun web-mode-rsb (regexp &optional limit noerror)
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (re-search-backward regexp limit noerror))
+ (if (or (null ret)
+ (not (web-mode-is-comment-or-string)))
+ (setq continue nil)))
+ ret))
+
+(defun web-mode-rsf (regexp &optional limit noerror)
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (re-search-forward regexp limit noerror))
+ (if (or (null ret)
+ (not (web-mode-is-comment-or-string)))
+ (setq continue nil))
+ )
+ ret))
+
+(defun web-mode-sb (expr &optional limit noerror)
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (search-backward expr limit noerror))
+ (if (or (null ret)
+ (not (web-mode-is-comment-or-string)))
+ (setq continue nil)))
+ ret))
+
+(defun web-mode-sf (expr &optional limit noerror)
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret)
+ (while continue
+ (setq ret (search-forward expr limit noerror))
+ (if (or (null ret)
+ (not (web-mode-is-comment-or-string)))
+ (setq continue nil)))
+ ret))
+
+(defun web-mode-content-rsf (regexp &optional limit noerror)
+ (unless noerror (setq noerror t))
+ (let ((continue t) ret beg end)
+ (while continue
+ (setq ret (re-search-forward regexp limit noerror)
+ beg (if (null ret) (point) (match-beginning 0))
+ end (if (null ret) (point) (1- (match-end 0))))
+ (if (or (null ret)
+ (and (web-mode-is-content beg)
+ (web-mode-is-content end)))
+ (setq continue nil)))
+ ret))
+
+;;---- ADVICES -----------------------------------------------------------------
+
+(defadvice ac-start (before web-mode-set-up-ac-sources activate)
+ "Set `ac-sources' based on current language before running auto-complete."
+ (when (equal major-mode 'web-mode)
+ ;; set ignore each time to nil. User has to implement a hook to change it
+ ;; for each completion
+ (setq web-mode-ignore-ac-start-advice nil)
+ (run-hooks 'web-mode-before-auto-complete-hooks)
+ (unless web-mode-ignore-ac-start-advice
+ (when web-mode-ac-sources-alist
+ (let ((new-web-mode-ac-sources
+ (assoc (web-mode-language-at-pos)
+ web-mode-ac-sources-alist)))
+ (setq ac-sources (cdr new-web-mode-ac-sources)))))))
+
+;;---- MINOR MODE ADDONS -------------------------------------------------------
+
+(defun web-mode-yasnippet-exit-hook ()
+ "Yasnippet exit hook"
+ (when (and (boundp 'yas-snippet-beg) (boundp 'yas-snippet-end))
+ (indent-region yas-snippet-beg yas-snippet-end)))
+
+(defun web-mode-imenu-index ()
+ (interactive)
+ "Returns imenu items."
+ (let (toc-index
+ line)
+ (save-excursion
+ (goto-char (point-min))
+ (while (not (eobp))
+ (setq line (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position)))
+ (let (found
+ (i 0)
+ item
+ regexp
+ type
+ type-idx
+ content
+ content-idx
+ content-regexp
+ close-tag-regexp
+ concat-str
+ jumpto
+ str)
+ (while (and (not found ) (< i (length web-mode-imenu-regexp-list)))
+ (setq item (nth i web-mode-imenu-regexp-list))
+ (setq regexp (nth 0 item))
+ (setq type-idx (nth 1 item))
+ (setq content-idx (nth 2 item))
+ (setq concat-str (nth 3 item))
+ (when (not (numberp content-idx))
+ (setq content-regexp (nth 2 item)
+ close-tag-regexp (nth 4 item)
+ content-idx nil))
+
+ (when (string-match regexp line)
+
+ (cond
+ (content-idx
+ (setq type (match-string type-idx line))
+ (setq content (match-string content-idx line))
+ (setq str (concat type concat-str content))
+ (setq jumpto (line-beginning-position)))
+ (t
+ (let (limit)
+ (setq type (match-string type-idx line))
+ (goto-char (line-beginning-position))
+ (save-excursion
+ (setq limit (re-search-forward close-tag-regexp (point-max) t)))
+
+ (when limit
+ (when (re-search-forward content-regexp limit t)
+ (setq content (match-string 1))
+ (setq str (concat type concat-str content))
+ (setq jumpto (line-beginning-position))
+ )
+ )))
+ )
+ (when str (setq toc-index
+ (cons (cons str jumpto)
+ toc-index)
+ )
+ (setq found t))
+ )
+ (setq i (1+ i))))
+ (forward-line)
+ (goto-char (line-end-position)) ;; make sure we are at eobp
+ ))
+ (nreverse toc-index)))
+
+;;---- UNIT TESTING ------------------------------------------------------------
+
+(defun web-mode-test ()
+ "Executes web-mode unit tests. See `web-mode-tests-directory'."
+ (interactive)
+ (let (files ret regexp)
+ (setq regexp "^[[:alnum:]][[:alnum:]._]+\\'")
+ (setq files (directory-files web-mode-tests-directory t regexp))
+ (dolist (file files)
+ (cond
+ ((eq (string-to-char (file-name-nondirectory file)) ?\_)
+ (delete-file file))
+ (t
+ (setq ret (web-mode-test-process file)))
+ ) ;cond
+ ) ;dolist
+ ))
+
+(defun web-mode-test-process (file)
+ (with-temp-buffer
+ (let (out sig1 sig2 success err)
+ (setq-default indent-tabs-mode nil)
+ (if (string-match-p "sql" file)
+ (setq web-mode-enable-sql-detection t)
+ (setq web-mode-enable-sql-detection nil))
+ (insert-file-contents file)
+ (set-visited-file-name file)
+ (web-mode)
+ (setq sig1 (md5 (current-buffer)))
+ (delete-horizontal-space)
+ (while (not (eobp))
+ (forward-line)
+ (delete-horizontal-space)
+ (end-of-line))
+ (web-mode-buffer-indent)
+ (setq sig2 (md5 (current-buffer)))
+ (setq success (string= sig1 sig2))
+ (setq out (concat (if success "ok" "ko") " : " (file-name-nondirectory file) "\n"))
+ (princ out)
+ (setq err (concat (file-name-directory file) "_err." (file-name-nondirectory file)))
+ (if success
+ (when (file-readable-p err)
+ (delete-file err))
+ (write-file err)
+ (message "[%s]" (buffer-string))
+ ) ;if
+ out)))
+
+;;---- MISC --------------------------------------------------------------------
+
+(defun web-mode-set-engine (engine)
+ "Set the engine for the current buffer."
+ (interactive
+ (list (completing-read
+ "Engine: "
+ (let (engines)
+ (dolist (elt web-mode-engines)
+ (setq engines (append engines (list (car elt)))))
+ engines))))
+ (setq web-mode-content-type "html"
+ web-mode-engine (web-mode-engine-canonical-name engine)
+ web-mode-minor-engine engine)
+ (web-mode-on-engine-setted)
+ (web-mode-buffer-fontify))
+
+(defun web-mode-set-content-type (content-type)
+ "Set the content-type for the current buffer"
+ (interactive (list (completing-read "Content-type: " web-mode-part-content-types)))
+ (setq web-mode-content-type content-type)
+ (when (called-interactively-p 'any)
+ )
+ (web-mode-buffer-fontify))
+
+(defun web-mode-on-engine-setted ()
+ (let (elt elts)
+
+ (when (string= web-mode-engine "razor") (setq web-mode-enable-block-face t))
+ ;;(setq web-mode-engine-attr-regexp (cdr (assoc web-mode-engine web-mode-engine-attr-regexps)))
+ (setq web-mode-engine-token-regexp (cdr (assoc web-mode-engine web-mode-engine-token-regexps)))
+
+ ;;(message "%S %S %S" web-mode-engine web-mode-engine-attr-regexp web-mode-engine-token-regexp)
+
+ (when (null web-mode-minor-engine)
+ (setq web-mode-minor-engine "none"))
+
+ (setq elt (assoc web-mode-engine web-mode-engine-open-delimiter-regexps))
+ (cond
+ (elt
+ (setq web-mode-block-regexp (cdr elt)))
+ ((string= web-mode-engine "archibus")
+ (setq web-mode-block-regexp nil))
+ (t
+ (setq web-mode-engine "none"))
+ )
+
+ (unless (boundp 'web-mode-extra-auto-pairs)
+ (setq web-mode-extra-auto-pairs nil))
+
+ (setq web-mode-auto-pairs
+ (append
+ (cdr (assoc web-mode-engine web-mode-engines-auto-pairs))
+ (cdr (assoc nil web-mode-engines-auto-pairs))
+ (cdr (assoc web-mode-engine web-mode-extra-auto-pairs))
+ (cdr (assoc nil web-mode-extra-auto-pairs))))
+
+ (unless (boundp 'web-mode-extra-snippets)
+ (setq web-mode-extra-snippets nil))
+
+ (setq elts
+ (append
+ (cdr (assoc web-mode-engine web-mode-extra-snippets))
+ (cdr (assoc nil web-mode-extra-snippets))
+ (cdr (assoc web-mode-engine web-mode-engines-snippets))
+ (cdr (assoc nil web-mode-engines-snippets))))
+
+ ;;(message "%S" elts)
+
+ (dolist (elt elts)
+ (unless (assoc (car elt) web-mode-snippets)
+ (setq web-mode-snippets (cons elt web-mode-snippets)))
+ )
+
+ (setq web-mode-engine-font-lock-keywords
+ (symbol-value (cdr (assoc web-mode-engine web-mode-engines-font-lock-keywords))))
+
+ (when (and (string= web-mode-minor-engine "jinja")
+ (not (member "endtrans" web-mode-django-control-blocks)))
+ (add-to-list 'web-mode-django-control-blocks "endtrans")
+ (setq web-mode-django-control-blocks-regexp
+ (regexp-opt web-mode-django-control-blocks t))
+ )
+
+ (when (string= web-mode-engine "spip")
+ (modify-syntax-entry ?# "w" (syntax-table)))
+
+;; (message "%S" (symbol-value (cdr (assoc web-mode-engine web-mode-engines-font-lock-keywords))))
+
+ ))
+
+(defun web-mode-detect-engine ()
+ (save-excursion
+ (goto-char (point-min))
+ (when (re-search-forward "-\\*- engine:[ ]*\\([[:alnum:]-]+\\)[ ]*-\\*-" web-mode-chunk-length t)
+ (setq web-mode-minor-engine (match-string-no-properties 1))
+ (setq web-mode-engine (web-mode-engine-canonical-name web-mode-minor-engine)))
+ web-mode-minor-engine))
+
+(defun web-mode-guess-engine-and-content-type ()
+ (let (buff-name found)
+
+ (setq buff-name (buffer-file-name))
+ (unless buff-name (setq buff-name (buffer-name)))
+ (setq web-mode-is-scratch (string= buff-name "*scratch*"))
+ (setq web-mode-content-type nil)
+
+ (when (boundp 'web-mode-content-types-alist)
+ (setq found nil)
+ (dolist (elt web-mode-content-types-alist)
+ (when (and (not found) (string-match-p (cdr elt) buff-name))
+ (setq web-mode-content-type (car elt)
+ found t))
+ ) ;dolist
+ ) ;when
+
+ (unless web-mode-content-type
+ (setq found nil)
+ (dolist (elt web-mode-content-types)
+ (when (and (not found) (string-match-p (cdr elt) buff-name))
+ (setq web-mode-content-type (car elt)
+ found t)
+ ;;(message "%S" web-mode-content-type)
+ ) ;when
+ ) ;dolist
+ ) ;unless
+
+ (when (boundp 'web-mode-engines-alist)
+ (setq found nil)
+ (dolist (elt web-mode-engines-alist)
+ (cond
+ ((stringp (cdr elt))
+ (when (string-match-p (cdr elt) buff-name)
+ (setq web-mode-engine (car elt))))
+ ((functionp (cdr elt))
+ (when (funcall (cdr elt))
+ (setq web-mode-engine (car elt))))
+ ) ;cond
+ ) ;dolist
+ ) ;when
+
+ (unless web-mode-engine
+ (setq found nil)
+ (dolist (elt web-mode-engine-file-regexps)
+ ;;(message "%S %S" (cdr elt) buff-name)
+ (when (and (not found) (string-match-p (cdr elt) buff-name))
+ (setq web-mode-engine (car elt)
+ found t))
+ )
+ )
+
+ (when (and (or (null web-mode-engine) (string= web-mode-engine "none"))
+ (string-match-p "php" (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position))))
+ (setq web-mode-engine "php"))
+
+ (when (and (string= web-mode-content-type "javascript")
+ (string-match-p "@jsx"
+ (buffer-substring-no-properties
+ (point-min)
+ (if (< (point-max) web-mode-chunk-length)
+ (point-max)
+ web-mode-chunk-length)
+ )))
+ (setq web-mode-content-type "jsx"))
+
+ (when web-mode-engine
+ (setq web-mode-minor-engine web-mode-engine
+ web-mode-engine (web-mode-engine-canonical-name web-mode-engine))
+ )
+
+ (when (and (or (null web-mode-engine)
+ (string= web-mode-engine "none"))
+ web-mode-enable-engine-detection)
+ (web-mode-detect-engine))
+
+ (web-mode-on-engine-setted)
+
+ ))
+
+(defun web-mode-engine-canonical-name (name)
+ (let (engine)
+ (cond
+ ((null name)
+ nil)
+ ((assoc name web-mode-engines)
+ name)
+ (t
+ (dolist (elt web-mode-engines)
+ (when (and (null engine) (member name (cdr elt)))
+ (setq engine (car elt)))
+ ) ;dolist
+ engine)
+ )))
+
+(defun web-mode-on-after-save ()
+ (when web-mode-is-scratch
+ (web-mode-guess-engine-and-content-type)
+ (web-mode-buffer-fontify))
+ nil)
+
+(defun web-mode-on-exit ()
+ (web-mode-with-silent-modifications
+ (put-text-property (point-min) (point-max) 'invisible nil)
+ (remove-overlays)
+ (remove-hook 'change-major-mode-hook 'web-mode-on-exit t)
+ ))
+
+(defun web-mode-file-link (file)
+ "Insert a link to a file in html document. This function can be
+extended to support more filetypes by customizing
+`web-mode-links'."
+ (interactive
+ (list (file-relative-name (read-file-name "Link file: "))))
+ (let ((matched nil)
+ (point-line (line-number-at-pos))
+ (point-column (current-column)))
+ (dolist (type web-mode-links)
+ (when (string-match (car type) file)
+ (setq matched t)
+ (when (nth 2 type)
+ (goto-char (point-min))
+ (search-forward "</head>")
+ (backward-char 7)
+ (open-line 1))
+ (insert (format (cadr type) file))
+ (indent-for-tab-command)
+ (when (nth 2 type)
+ ;; return point where it was and fix indentation
+ (forward-line)
+ (indent-for-tab-command)
+ (if (> point-line (- (line-number-at-pos) 2))
+ (forward-line (+ (- point-line (line-number-at-pos)) 1))
+ (forward-line (- point-line (line-number-at-pos))))
+ (move-to-column point-column))
+ ;; move point back if needed
+ (backward-char (nth 3 type))))
+ (when (not matched)
+ (user-error "Unknown file type"))))
+
+(defun web-mode-reload ()
+ "Reload web-mode."
+ (interactive)
+ (web-mode-with-silent-modifications
+ (put-text-property (point-min) (point-max) 'invisible nil)
+ (remove-overlays)
+ (setq font-lock-unfontify-region-function 'font-lock-default-unfontify-region)
+ (load "web-mode.el")
+ (setq web-mode-change-beg nil
+ web-mode-change-end nil)
+ (web-mode)
+ ))
+
+(defun web-mode-measure (msg)
+ (let (sub)
+ (when (null web-mode-time) (setq web-mode-time (current-time)))
+ (setq sub (time-subtract (current-time) web-mode-time))
+ (when nil
+ (save-excursion
+ (let ((n 0))
+ (goto-char (point-min))
+ (while (web-mode-tag-next)
+ (setq n (1+ n))
+ )
+ (message "%S tags found" n)
+ )))
+ (message "%18s: time elapsed = %Ss %9Sµs" msg (nth 1 sub) (nth 2 sub))
+ ))
+
+(defun web-mode-reveal ()
+ "Display text properties at point."
+ (interactive)
+ (let (symbols out)
+ (setq out (format
+ "[point=%S engine=%S minor=%S content-type=%S language-at-pos=%S]\n"
+ (point)
+ web-mode-engine
+ web-mode-minor-engine
+ web-mode-content-type
+ (web-mode-language-at-pos (point))))
+ (setq symbols (append web-mode-scan-properties '(font-lock-face face)))
+ (dolist (symbol symbols)
+ (when symbol
+ (setq out (concat out (format "%s(%S) " (symbol-name symbol) (get-text-property (point) symbol)))))
+ )
+ (message "%s\n" out)
+ ;;(message "syntax-class=%S" (syntax-class (syntax-after (point))))
+ (message nil)))
+
+(defun web-mode-toggle-tracing ()
+ "Toggle tracing."
+ (interactive)
+ (if web-mode-trace
+ (setq web-mode-trace nil)
+ (message "** tracing on ** point(%S) web-mode-change-beg(%S) web-mode-change-end(%S) web-mode-skip-fontification(%S)"
+ (point) web-mode-change-beg web-mode-change-end web-mode-skip-fontification)
+ (setq web-mode-trace t)))
+
+(defun web-mode-debug ()
+ "Display informations useful for debugging."
+ (interactive)
+ (let ((modes nil)
+ (customs '(web-mode-enable-current-column-highlight web-mode-enable-current-element-highlight indent-tabs-mode))
+ (ignore '(abbrev-mode auto-composition-mode auto-compression-mode auto-encryption-mode auto-insert-mode blink-cursor-mode column-number-mode delete-selection-mode display-time-mode electric-indent-mode file-name-shadow-mode font-lock-mode global-font-lock-mode global-hl-line-mode line-number-mode menu-bar-mode mouse-wheel-mode recentf-mode show-point-mode tool-bar-mode tooltip-mode transient-mark-mode)))
+ (message "\n")
+ (message "--- WEB-MODE DEBUG BEG ---")
+ (message "versions: emacs(%S.%S) web-mode(%S)"
+ emacs-major-version emacs-minor-version web-mode-version)
+ (message "vars: engine(%S) minor(%S) content-type(%S) file(%S)"
+ web-mode-engine
+ web-mode-minor-engine
+ web-mode-content-type
+ (or (buffer-file-name) (buffer-name)))
+ (message "system: window(%S) config(%S)" window-system system-configuration)
+ (message "colors: fg(%S) bg(%S) "
+ (cdr (assoc 'foreground-color default-frame-alist))
+ (cdr (assoc 'background-color default-frame-alist)))
+ (mapc (lambda (mode)
+ (condition-case nil
+ (if (and (symbolp mode) (symbol-value mode) (not (member mode ignore)))
+ (push mode modes))
+ (error nil))
+ ) ;lambda
+ minor-mode-list)
+ (message "minor modes: %S" modes)
+ (message "vars:")
+ (dolist (custom customs)
+ (message (format "%s=%S " (symbol-name custom) (symbol-value custom))))
+ (message "--- WEB-MODE DEBUG END ---")
+ (switch-to-buffer "*Messages*")
+ (goto-char (point-max))
+ (recenter)
+ ))
+
+(provide 'web-mode)
+
+;;; web-mode.el ends here
+
+;; Local Variables:
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
diff --git a/elpa/web-mode-20220319.653/web-mode.elc b/elpa/web-mode-20220319.653/web-mode.elc
new file mode 100644
index 0000000..24710a4
--- /dev/null
+++ b/elpa/web-mode-20220319.653/web-mode.elc
Binary files differ