Custom Vim HTML syntax - html

I have a script that reads an HTML file and replaces occurrences of ~%foo%~ with a value set by Perl. Something like this:
<span class="~%classname%~">~%hi_mom%~</span>
Would produce something like this in the browser:
<span class="classyclass">Hello World</span>
Right so I want to use Vim syntax highlighting to distinguish the occurrences ~%foo%~ in the HTML. By default, the HTML syntax highlighting will make an HTML element's attribute values Magenta and I want the ~%foo%~ portion to be DarkMagenta. I'm on the right track because if I comment out the tokenQuoted lines (or token lines) I get the desired results but with both matches and highlights uncommented the token highlighting overrides the tokenQuoted highlighting.
syntax match token containedin=ALLBUT,htmlString,htmlValue '\~%[^%]\+%\~'
syntax match tokenQuoted containedin=htmlString,htmlValue '\~%[^%]\+%\~'
" tokenQuoted assumes htmlString/htmlValue (:highlight String) is Magenta
highlight token term=none ctermfg=White guifg=White
highlight tokenQuoted term=none ctermfg=DarkMagenta guifg=DarkMagenta
The file I'm working in is sourced after the default html.vim is sourced via
autocmd *.html ~/.vim/syntax/html.vim in .vimrc.

The problem is that token match is not being excluded from being contained in the tokenQuoted match. To get the desired results, i.e. highlighting quoted tokens different from non quoted tokens, use the following in your syntax file.
syntax match token containedin=ALLBUT,htmlString,htmlValue,tokenQuoted '\~%[^%]\+%\~'
syntax match tokenQuoted containedin=htmlString,htmlValue '\~%[^%]\+%\~'
highlight token term=none ctermfg=White guifg=White
highlight tokenQuoted term=none ctermfg=DarkMagenta guifg=DarkMagenta
Or if it makes sense to use a syntax region rather than a match, replace the syntax match lines above with the following.
syntax region token contained start=+\~%+ end=+%\~+ containedin=ALLBUT,htmlString,tokenQuoted
syntax region tokenQuoted contained start=+\~%+ end=+%\~+ containedin=htmlString
I guess I should also mention that when I was testing this I just created the file ~/.vim/syntax/html.vim and added the above content. There was no need to add anything to my .vimrc file.

Related

Createing a Sphinx code-block, with inline text parsing

I'm trying to create a directive, that will allow me to parse links inside a Sphinx CodeBlock directive. I looked at the ParsedLiteral directive from docutils, which does something like that, only it doesn't do syntax highlighting, like CodeBlock. I tried replacing the part of CodeBlock (in sphinx/directives/code.py), which generates the literal_block:
literal: Element = nodes.literal_block(code, code)
with
text_nodes, messages = self.state.inline_text(code, self.lineno)
literal: Element = nodes.literal_block(code, "", *text_nodes)
which is what docutils ParsedLiteraldirective does, but I of course kept the rest of the Sphinx CodeBlock. This parses the code correctly, but does not apply the correct syntax highlighting, so I'm wondering where the syntax highlighting is taking place, and why it's not taking place in my modified CodeBlock directive.
I'm very confused as to why this is the case and I'm looking for some input from smarter people than me.
Syntax highlights are applied at the translation phase, see sphinx.writers.html.HTMLTranslator.visit_literal_block:
def visit_literal_block(self, node: Element) -> None:
if node.rawsource != node.astext(): # <<< LOOK AT HERE
# most probably a parsed-literal block -- don't highlight
return super().visit_literal_block(node)
lang = node.get('language', 'default')
linenos = node.get('linenos', False)
# do highlight...
Once the node's rawsource is not equal to its text, the highlight will not be applied.
In your example, code is not equal to text_nodes.as_text() obviously.
Just set literal.rawsource to literal.as_text() can fix the syntax highlight.

regex interprete markdown but ignore HTML

In a string like
Hallo, this is <code>`code`</code> and this `is code again`.
To analyse it, parse it with regex?
In this example the user just typed the far right ` at the very last. The first "code" has obviously already been surrounded by HTML.
I need a regex to get the next code indicated part.
There always be one series, that is valid markdown AND not already surrounded by the corresponding HTML tags.
How to get this specific series (regardless if it's *, **, ___, ` or whatever)?
So what you want is a regex that only matches the markdown that isn't surrounded by HTML tags right ?
You can use something like this :
/(?:[^<>]|^)(`[^<>].*?`)/
This will only match the text placed inside `` that aren't directly placed next to a < or > character. This way, no matter what the HTML tag is inside the <...>, the `code` won't match.
See this Regex101.com
If you want to match every emphasized string that is not tagged with "code" you can use
(?<!<code>)`[\w ]+`
You can test it on regex101.com

How to use Resource File for html parameters?

In my project we are using Resource files and i am calling the resource file by the following syntax:
#HttpContext.GetGlobalResourceObject(CustomersResource, "t_GoBackCustomer")
where CustomersResource is the Resource file name and t_GoBackCustomer is the key name. The value of the key will be like "Go Back to Previous Page". The whole value is rendering for labels and other places without any problem.
But when i use
<a title=#HttpContext.GetGlobalResourceObject(CustomersResource, "t_GoBackCustomer")>
only the first word is coming as title. i.e while pressing F12 I can see as
`<a title="Go" Back to Previous Page></a>'
Only "Go" is coming as title. The words after space is not considered as title. The same is the case for Placeholder. Can anyone say what is the mistake i am doing here?
I have found solution to my problem. I have to use the following syntax to get words with spaces.
<a title='#HttpContext.GetGlobalResourceObject(CustomersResource, "t_GoBackCustomer")'>
The single quotes did the magic. For labels and controls we no need to use single quotes. But while using for html parameters like Title and PlaceHolder we must need to use Quotes.

Passing style parameters in query string

I have a simple html page with a div element in it.
The innerHTML property of the div is set through query String.
In query string I pass html strings,i.e.
<p style='font-size:20px;color:green;'> Sun rises in the east </p> etc...
I get the appropriate output.
However, if I pass color code in style attribute say, #00990a, I am not displayed any content.
Can someone help me through this?
if theres a color code that contains a #, everything after that will be treated fragment identifier. to avoid this you have to url-encode your parameter-value (replacing # with %23 an d doing the same with other characters that have a special meaning (#&%=?#...)).
Finally your url should look like this:
PageUrl?Content=%3Cp+style%3D%27color%3A%23009900%27%3EContent%3C%2Fp%3E
Since you haven't shown us any code, I shall guess…
In a URI, # indicates the start of the fragment identifier (as ? indicates the start of the query string). Your colour is terminated the query string and starting the fragment identifier. You need to URL encode any character that has special meaning in URLs. (# is %23).
Do make sure that you sanitise the passed HTML and CSS on the server though. It is very easy to expose yourself to XSS attacks otherwise.

Proper html attribute highlighting in Vim?

While I was looking for proper html tag highlighting in Vim, I found this post. But after looking at romainl's answer (and his screenshot) and html syntax file, I wonder how can I change color of = (equal sign) after attribute to match the color of an attribute without changing html tag's color?
Exploration
Here is a very useful function I've found somewhere (a long time ago, probably on the Vim Wiki) that gives you the syntax group of the word/symbol under your cursor:
function! SynStack()
if !exists("*synstack")
return
endif
echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')
endfunc
Just place your cursor on the item you want to inspect and type :call SynStack() to echo the syntax group in the command-line.
If I place my cursor on the = in <div id="example"></div>, the output of SynStack() is ['htmlTag'].
With the cursor on <> I get ['htmlTag'] as well.
With the cursor on div I get ['htmlTag', 'htmlTagN', 'htmlTagName'] which means that the color of div (h1, p…) is defined via a special syntax group called htmlTagName that inherits from htmlTag.
Some alternative/custom syntax files may define other syntax groups with slightly varying name so my example is only valid for me. You'll have to play with SynStack() to get the correct syntax groups.
Reflexion
With the info we have gathered so far, it's obvious that the tag name (['htmlTagName']) can be styled independtly from the rest of the tag but it doesn't seem doable to highlight the = differently. Because it is part of the same syntax group as <>, the = will necessarilly be highlighted the same.
We have 2 possibilities:
a. <, = and > are the same colour while div is different.
b. <, div, = and > are all the same colour.
The original theme followed path a which I didn't like, so I had to customize it a little (path b) with the few lines in my answer to the previous question:
hi htmlTag guifg=#90b0d1 gui=NONE
hi htmlSpecialTagName guifg=#90b0d1 gui=NONE
hi htmlTagName guifg=#90b0d1 gui=NONE
hi htmlEndTag guifg=#90b0d1 gui=NONE
As it is, having the = coloured differently than <> is not possible. If we want to colorize the = we are going to edit the HTML syntax file and your colorscheme, cowboy style.
Action
The first step is to make a local copy of the default HTMl syntax file:
$ cp /usr/share/vim/vim73/syntax/html.vim ~/.vim/syntax/html.vim
The next step is to edit this file. We are going to perform two changes:
add the definition of the htmlEqualSign syntax group
Line 44 should be (Attention! Not thoroughly tested.):
syn match htmlEqualSign contained "="
add htmlEqualSign to the htmlTag group
Line 40 of ~/.vim/syntax/html.vim should be changed from:
syn region htmlTag start=+<[^/]+ end=+>+ contains=htmlTagN,htmlString,htmlArg,htmlValue,htmlTagError,htmlEvent,htmlCssDefinition,#htmlPreproc,#htmlArgCluster
to:
syn region htmlTag start=+<[^/]+ end=+>+ contains=htmlTagN,htmlString,htmlArg,htmlValue,htmlTagError,htmlEvent,htmlCssDefinition,#htmlPreproc,#htmlArgCluster,htmlEqualSign
The last step is to edit your colorscheme so that it colorizes = the way you want. You do that by adding this line somewhere in your colorscheme:
hi htmlEqualSign guifg=#00ff00
With the color of your choice, of course.
But I think that you want = to be the same color as id (that's not very clear from your question). For that, we are going to "link" the htmlEqualSign group to the one being used for attributes. Again, :call SynStack() is of great help: the syntax group for attributes is htmlArg so the line to add to your colorscheme would be:
hi link htmlEqualSign htmlArg