You can download this mode here.
A GitHub repository is available: https://github.com/fxbois/web-mode/
web-mode.el is also available on melpa and on melpa stable.
web-mode.el is GPL and Free Software.
First drop the file web-mode.el in a directory defined in your load-path.
Then, add in your .emacs
(require 'web-mode)
(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode))
Using web-mode for editing plain HTML files can be done this way
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
You can also edit plain js, jsx, css, scss, xml files.
If you use use-package, use the config below
(use-package web-mode
:ensure t
:mode
(("\\.phtml\\'" . web-mode)
("\\.php\\'" . web-mode)
("\\.tpl\\'" . web-mode)
("\\.[agj]sp\\'" . web-mode)
("\\.as[cp]x\\'" . web-mode)
("\\.erb\\'" . web-mode)
("\\.mustache\\'" . web-mode)
("\\.djhtml\\'" . web-mode)))
A specific engine can be forced with web-mode-engines-alist.
(setq web-mode-engines-alist
'(("php" . "\\.phtml\\'")
("blade" . "\\.blade\\."))
)
Using this association list is required as soon as the file extension is unknown (by web-mode) or is too general (e.g. *.html). In summary, you may have to set both auto-mode-alist and web-mode-engines-alist.
Since the version v10, you can also put a fragment like -*- engine:ENGINE_NAME -*- in a comment at the beginning of your template (web-mode-enable-engine-detection must be set to t in your .emacs)
<?php /* -*- engine:php -*- */ ?>
<span><?=$x?></span>
The recognized file extensions are listed in the Engine families paragraph.
web-mode.el can deal with many content types: html, xml, javascript, jsx, json, css. This was needed to edit *.js.erb files for example: js files that embed ruby blocks.
Sometimes, web-mode.el can not guess the content type with the file extension.
e.g. you want to associate *.api files with web-mode.
The var web-mode-content-types-alist can be used to associate a file path with a content type
(add-to-list 'auto-mode-alist '("\\.api\\'" . web-mode))
(add-to-list 'auto-mode-alist '("/some/react/path/.*\\.js[x]?\\'" . web-mode))
(setq web-mode-content-types-alist
'(("json" . "/some/path/.*\\.api\\'")
("xml" . "/other/path/.*\\.api\\'")
("jsx" . "/some/react/path/.*\\.js[x]?\\'")))
(defun my-web-mode-hook ()
"Hooks for Web mode."
(setq web-mode-markup-indent-offset 2)
)
(add-hook 'web-mode-hook 'my-web-mode-hook)
(setq web-mode-markup-indent-offset 2)
CSS offset indentation
(setq web-mode-css-indent-offset 2)
Script/code offset indentation (for JavaScript, Java, PHP, Ruby, Go, VBScript, Python, etc.)
(setq web-mode-code-indent-offset 2)
By default, tag attributes are indented like this:
<img src="pix.png"
class="noborder"/>
You can force a fixed indentation with web-mode-attr-indent-offset
<img src="pix.png"
class="noborder"/>
web-mode inherits from 'standard-indent when this var is bound.
(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))
(setq web-mode-style-padding 1)
For <script> parts
(setq web-mode-script-padding 1)
For multi-line blocks
(setq web-mode-block-padding 0)
(setq web-mode-comment-style 2)
(set-face-attribute 'web-mode-css-rule-face nil :foreground "Pink3")
Available faces:effects web-mode-folded-face, web-mode-warning-face, web-mode-whitespace-face, web-mode-html-entity-face (with web-mode-enable-html-entities-fontification), web-mode-comment-keyword-face
html web-mode-doctype-face, web-mode-html-tag-face, web-mode-html-tag-bracket-face, web-mode-html-attr-name-face, web-mode-html-attr-value-face, web-mode-html-attr-equal-face, web-mode-html-tag-namespaced-face, web-mode-html-tag-custom-face, web-mode-attr-tag-custom-face
json web-mode-json-key-face, web-mode-json-context-face, web-mode-json-string-face
css web-mode-css-at-rule-face, web-mode-css-property-name-face, web-mode-css-function-face, web-mode-css-priority-face, web-mode-css-pseudo-class-face, web-mode-css-selector-face, web-mode-css-string-face
code web-mode-builtin-face, web-mode-comment-face, web-mode-constant-face, web-mode-filter-face, web-mode-function-call-face, web-mode-function-name-face, web-mode-keyword-face, web-mode-preprocessor-face, web-mode-string-face, web-mode-symbol-face, web-mode-type-face, web-mode-variable-name-face
block web-mode-block-control-face, web-mode-block-delimiter-face, web-mode-block-face (see web-mode-enable-block-face), web-mode-block-string-face, web-mode-block-comment-face
part web-mode-part-face (see web-mode-enable-part-face), web-mode-script-face, web-mode-style-face, web-mode-part-string-face, web-mode-part-comment-face, web-mode-javascript-string-face
content fontification web-mode-bold-face, web-mode-italic-face, web-mode-underline-face
other web-mode-annotation-tag-face web-mode-annotation-type-face
(define-key web-mode-map (kbd "C-n") 'web-mode-tag-match)
(setq web-mode-extra-snippets
'(("erb" . (("toto" . "<% toto | %>\n\n<% end %>")))
("php" . (("dowhile" . "<?php do { ?>\n\n<?php } while (|); ?>")
("debug" . "<?php error_log(__LINE__); ?>")))
))
The character | is used to locate the cursor position (this is optional)
(setq web-mode-extra-auto-pairs
'(("erb" . (("beg" "end")))
("php" . (("beg" "end")
("beg" "end")))
))
(setq web-mode-enable-auto-pairing t)
CSS colorization
(setq web-mode-enable-css-colorization t)
Block face: can be used to set blocks background and default foreground
(see web-mode-block-face)
(setq web-mode-enable-block-face t)
Part face: can be used to set parts background and default foreground
(see web-mode-script-face and web-mode-style-face
which inheritate from web-mode-part-face)
(setq web-mode-enable-part-face t)
Comment keywords (see web-mode-comment-keyword-face)
(setq web-mode-enable-comment-interpolation t)
Heredoc (cf. PHP strings) fontification (when the identifier is <<<EOTHTML or
<<<EOTJAVASCRIPT)
(setq web-mode-enable-heredoc-fontification t)
(setq web-mode-extra-constants '(("php" . ("CONS1" "CONS2")))
Also available:
web-mode-extra-keywords,
web-mode-extra-types
(setq web-mode-enable-current-element-highlight t)
You can also highlight the current column with
(setq web-mode-enable-current-column-highlight t)
If you have auto-complete installed, you can set up per-language ac-sources with web-mode-ac-sources-alist:
(setq web-mode-ac-sources-alist
'(("css" . (ac-source-css-property))
("html" . (ac-source-words-in-buffer ac-source-abbrev))))
To find a language's name, run the function web-mode-language-at-pos while in a block of it.
All hooks in web-mode-before-auto-complete-hooks are run just before auto-completion starts. This is useful for adapting ac-sources meant for a single language to web-mode, like ac-source-yasnippet.
Here is a sample config for editing PHP templates, using php-auto-yasnippets, emmet-mode, and ac-emmet:
(setq web-mode-ac-sources-alist
'(("php" . (ac-source-yasnippet ac-source-php-auto-yasnippets))
("html" . (ac-source-emmet-html-aliases ac-source-emmet-html-snippets))
("css" . (ac-source-css-property ac-source-emmet-css-snippets))))
(add-hook 'web-mode-before-auto-complete-hooks
'(lambda ()
(let ((web-mode-cur-language
(web-mode-language-at-pos)))
(if (string= web-mode-cur-language "php")
(yas-activate-extra-mode 'php-mode)
(yas-deactivate-extra-mode 'php-mode))
(if (string= web-mode-cur-language "css")
(setq emmet-use-css-transform t)
(setq emmet-use-css-transform nil)))))
General
|
DOM
|
Block
|
HTML element
|
HTML tag
|
HTML attribute
|
name | cousins | extensions | example |
---|---|---|---|
django | twig, jinja, erlydtl, swig, liquid, selmer (Clojure), clabango, swig, nunjucks | *.djhtml, *twig*, *.dtl, *.tmpl, *.njk | |
php | *.php, *.psp, *.ctp | ||
erb | eruby, ember, erubis, embedded javascript | *.erb, *.rhtml, *.ejs | |
velocity | cheetah, vtl | *.vsl, *.vtl, *.vm | |
blade | laravel | *blade* | |
go | gtl | *.gohtml, *.gotmpl | |
jsp | *.jsp, *.gsp | ||
freemarker | *.ftl | ||
aspx | *.aspx, *.ascx | ||
asp | *.asp | ||
razor | play, play2 | *.cshtml, *.vbhtml | |
ctemplate | mustache, handlebars, ember, hapax, ngtemplate, meteor, blaze, velvet | *.hbs, *.mustache | |
smarty | *.tpl | ||
dust | *.dust | ||
closure | *.soy | ||
underscorejs | |||
template-toolkit | *.tt, *.tt3 | ||
mako | *.mako | ||
lsp | *.lsp |
(add-hook 'local-write-file-hooks
(lambda ()
(delete-trailing-whitespace)
nil))
M-x byte-compile-file
(add-to-list 'auto-mode-alist '("\\.php\\'" . php-mode))
(add-to-list 'auto-mode-alist '("\\.blade\\.php\\'" . web-mode))
Never forget that the matching is done on the path and not just on the filename. If your templates are stored in a subdirectory called views, html or templates, you can use such a configuration line:
(add-to-list 'auto-mode-alist '("/\\(views\\|html\\|templates\\)/.*\\.php\\'" . web-mode))
(local-set-key (kbd "RET") 'newline-and-indent)
You can also use M-x electric-indent-mode.(defun my-web-mode-hook ()
(setq web-mode-enable-auto-pairing nil))
(add-hook 'web-mode-hook 'my-web-mode-hook)
(defun sp-web-mode-is-code-context (id action context)
(and (eq action 'insert)
(not (or (get-text-property (point) 'part-side)
(get-text-property (point) 'block-side)))))
(sp-local-pair 'web-mode "<" nil :when '(sp-web-mode-is-code-context))
Special thanks to Johan Ekenberg for this tip.
To report a bug, submit an issue on GitHub (note: a screenshot, an example on gist and the output of M-x web-mode-debug are always useful). It may also be a good idea to look at the *Messages* buffer.
For general questions (install, config, etc), use emacs.stackexchange.com (do not forget to associate the web-mode tag).
François-Xavier Bois - < fxbois AT Google Mail Service >
Founder and CTO of Kernix, Digital Agency (Web/Mobile/Data) in Paris (FR).
web-mode.el has been presented to the 7th European Lisp Symposium with the paper: Heterogeneous recursive code parsing with Emacs Lisp.
Friendly links:
Scopalto - Magazines gratuits au format pdf
How to summarize data using Python Pandas