Skip to content

Commit

Permalink
[jsx] Support variables syntax in tag text: div{{v}} -> <div>{v}</div>
Browse files Browse the repository at this point in the history
  • Loading branch information
15cm committed Oct 10, 2019
1 parent 690c439 commit 672d829
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 12 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,12 @@ If you want to customize Self-closing tags style:

### 4. JSX Support
If current major-mode is in `emmet-jsx-major-modes`, then JSX features will be supported:

- Expand `.class` to `className="..."` instead of `class="..."`
- Expand value of properties as variables: `div[value={v}]` -> `<div value={v}></div>`
- Expand variables inside text: `div{{v}}` -> `<div>{v}</div>`
**Note**: '}' can be escaped using backslash, i.e. `div{{v\}}}` -> `<div>{v}}</div>`.
Please make sure your curly braces(not counting escaped ones) are always balanced.

To enable the JSX support, add your major-mode to `emmet-jsx-major-modes`:

Expand Down
48 changes: 42 additions & 6 deletions emmet-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -3101,6 +3101,31 @@ tbl))
it))
(emmet-parse "\\([^\\|]+\\)" 1 "filter name" `(,(elt it 1)))))

(defun emmet-extract-inner-text (input)
"Extract inner-text in the form of {inner_text}...
Return `(,inner-text ,input-without-inner-text) if succeeds, otherwise return
`(error ,error-message)"
(cl-labels (
(string-find-paired-right-curly-brace
(str)
(cl-labels ((char-at-pos (str pos) (string-to-char (substring str pos)))
(helper (str pos cnt)
(let ((len (length str)))
(if (>= pos len) nil
(let ((c (char-at-pos str pos)))
(cond ((char-equal c ?{) (setq cnt (+ cnt 1)))
((and (char-equal c ?}) (not (char-equal (char-at-pos str (- pos 1)) ?\\))) (setq cnt (- cnt 1))))
(if (= cnt 0) pos (helper str (+ pos 1) cnt)))))
))
(helper str 0 0))))
(let ((err '(error "expected inner text")))
(if (or (< (length input) 2) (not (char-equal (string-to-char input) ?{))) err
(emmet-aif (string-find-paired-right-curly-brace input)
`(,input
,(substring input 1 it)
,(substring input (+ it 1)))
err)))))

(defun emmet-filter (input filters)
"Construct AST with specified filters."
(emmet-pif (emmet-subexpr input)
Expand Down Expand Up @@ -3361,12 +3386,23 @@ tbl))

(defun emmet-text (input)
"A zen coding expression innertext."
(emmet-parse "{\\(\\(?:\\\\.\\|[^\\\\}]\\)*?\\)}" 2 "inner text"
(let ((txt (emmet-split-numbering-expressions (elt it 1))))
(if (listp txt)
(setq txt (cons (car txt) (cons (replace-regexp-in-string "\\\\\\(.\\)" "\\1" (cadr txt)) (cddr txt))))
(setq txt (replace-regexp-in-string "\\\\\\(.\\)" "\\1" txt)))
`((text ,txt) . ,input))))
(emmet-pif (emmet-extract-inner-text input)
(let ((txt (emmet-split-numbering-expressions (elt it 1))))
(if (listp txt)
(setq txt (cons (car txt) (cons (replace-regexp-in-string "\\\\\\(.\\)" "\\1" (cadr txt)) (cddr txt))))
(setq txt (replace-regexp-in-string "\\\\\\(.\\)" "\\1" txt)))
`((text ,txt) . ,(elt it 2)))
'(error "expected inner text")))

;; (defun emmet-text (input)
;; "A zen coding expression innertext."
;; (emmet-parse "{\\(\\(?:\\\\.\\|[^\\\\}]\\|\\\\}\\)*?\\)}" 2 "inner text"
;; (let ((txt (emmet-split-numbering-expressions (elt it 1))))
;; (if (listp txt)
;; (setq txt (cons (car txt) (cons (replace-regexp-in-string "\\\\\\(.\\)" "\\1" (cadr txt)) (cddr txt))))
;; (setq txt (replace-regexp-in-string "\\\\\\(.\\)" "\\1" txt)))
;; `((text ,txt) . ,input))
;; '(error "expected inner text")))

(defun emmet-properties (input)
"A bracketed emmet property expression."
Expand Down
48 changes: 42 additions & 6 deletions src/html-abbrev.el
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,31 @@
it))
(emmet-parse "\\([^\\|]+\\)" 1 "filter name" `(,(elt it 1)))))

(defun emmet-extract-inner-text (input)
"Extract inner-text in the form of {inner_text}...
Return `(,inner-text ,input-without-inner-text) if succeeds, otherwise return
`(error ,error-message)"
(cl-labels (
(string-find-paired-right-curly-brace
(str)
(cl-labels ((char-at-pos (str pos) (string-to-char (substring str pos)))
(helper (str pos cnt)
(let ((len (length str)))
(if (>= pos len) nil
(let ((c (char-at-pos str pos)))
(cond ((char-equal c ?{) (setq cnt (+ cnt 1)))
((and (char-equal c ?}) (not (char-equal (char-at-pos str (- pos 1)) ?\\))) (setq cnt (- cnt 1))))
(if (= cnt 0) pos (helper str (+ pos 1) cnt)))))
))
(helper str 0 0))))
(let ((err '(error "expected inner text")))
(if (or (< (length input) 2) (not (char-equal (string-to-char input) ?{))) err
(emmet-aif (string-find-paired-right-curly-brace input)
`(,input
,(substring input 1 it)
,(substring input (+ it 1)))
err)))))

(defun emmet-filter (input filters)
"Construct AST with specified filters."
(emmet-pif (emmet-subexpr input)
Expand Down Expand Up @@ -299,12 +324,23 @@

(defun emmet-text (input)
"A zen coding expression innertext."
(emmet-parse "{\\(\\(?:\\\\.\\|[^\\\\}]\\)*?\\)}" 2 "inner text"
(let ((txt (emmet-split-numbering-expressions (elt it 1))))
(if (listp txt)
(setq txt (cons (car txt) (cons (replace-regexp-in-string "\\\\\\(.\\)" "\\1" (cadr txt)) (cddr txt))))
(setq txt (replace-regexp-in-string "\\\\\\(.\\)" "\\1" txt)))
`((text ,txt) . ,input))))
(emmet-pif (emmet-extract-inner-text input)
(let ((txt (emmet-split-numbering-expressions (elt it 1))))
(if (listp txt)
(setq txt (cons (car txt) (cons (replace-regexp-in-string "\\\\\\(.\\)" "\\1" (cadr txt)) (cddr txt))))
(setq txt (replace-regexp-in-string "\\\\\\(.\\)" "\\1" txt)))
`((text ,txt) . ,(elt it 2)))
'(error "expected inner text")))

;; (defun emmet-text (input)
;; "A zen coding expression innertext."
;; (emmet-parse "{\\(\\(?:\\\\.\\|[^\\\\}]\\|\\\\}\\)*?\\)}" 2 "inner text"
;; (let ((txt (emmet-split-numbering-expressions (elt it 1))))
;; (if (listp txt)
;; (setq txt (cons (car txt) (cons (replace-regexp-in-string "\\\\\\(.\\)" "\\1" (cadr txt)) (cddr txt))))
;; (setq txt (replace-regexp-in-string "\\\\\\(.\\)" "\\1" txt)))
;; `((text ,txt) . ,input))
;; '(error "expected inner text")))

(defun emmet-properties (input)
"A bracketed emmet property expression."
Expand Down

0 comments on commit 672d829

Please sign in to comment.