Slim templates and TailwindCSS use ' : ' in class declaration - slim-lang

TailwindCSS is looking like a great frontend tool but I'm wondering how to use it with the Rails Slim template language?
For example:
<div class="bg-red-500 sm:bg-green-500 md:bg-blue-500 lg:bg-pink-500 xl:bg-teal-500"></div>
If I run it through HTML2SLIM I get this recommendation:
.bg-red-500.sm:bg-green-500.md:bg-blue-500.lg:bg-pink-500.xl:bg-teal-500
Which produces the following HTML:
<div class="bg-red-500 sm">
<bg-green-500 class="md">
<bg-blue-500 class="lg">
<bg-pink-500 class="xl">
<bg-teal-500></bg-teal-500>
</bg-pink-500>
</bg-blue-500>
</bg-green-500>
</div>
It seems that the colon ':' is interperted as multiple html elemments. Im wondering if there's a way around this? I'd love to use Slim with TailwindCSS.
So far I've made some progress using Rails' content_tag:
= content_tag :span, 'Accounts', class: 'invisible md:visible lg:visible'
But I can only go so far with this.

Another option is to configure Tailwind to use another separator as documented here: https://tailwindcss.com/docs/configuration/#separator
// tailwind.config.js
module.exports = {
separator: "_",
}
Then you could do .sm_bg-green-500 and so on.
There are also class names like .w-1/2 in Tailwind, that are not affected by this setting. You could add custom class names to work around that, e.g.
// tailwind.config.js
module.exports = {
…
theme: {
extend: {
width: {
"1-of-2": "50%"
}
}
}
}
and then use .w-1-of-2.

It's just not possible to have these colons in the class shorthand notation. You can do the following though
div class="bg-red-500.sm::bg-green-500.md:bg-blue-500.lg:bg-pink-500.xl:bg-teal-500"
which results in the desired HTML:
<div class="bg-red-500 sm:bg-green-500 md:bg-blue-500 lg:bg-pink-500 xl:bg-teal-500"></div>

Related

Angulardart markdown directive not working

I'm trying to do the following:
import 'dart:html';
import 'package:angular/angular.dart';
import 'package:markdown/markdown.dart' as md;
#Directive(selector: '[markdown]')
class MarkdownDirective {
#Input('markdown')
String marked;
MarkdownDirective(Element el) {
final html = md.markdownToHtml(marked);
print(el.innerHtml); // this is empty
print(html); // obv null
el.setInnerHtml(html);
}
}
I'm expecting innerHtml to have the value of the "markdown" content but it is null before it enters this directive.
<div markdown>{{report.summary}}</div>
I've tried this too and no luck:
<div [markdown]="'{{report.summary}}'" >{{report.summary}}</div>
Got interpolation ({{}}) where expression was expected at column 1 in ['{{report.summary}}'] - not understanding completely why it doesn't work./
The error message is not related to directive at all, but to it's use in <div [markdown]="'{{report.summary}}'" >{{report.summary}}</div>.
Use either [markdown]="report.summary" or markdown="{{report.summary}}", but not both. The two variants I posted are equivalent (see here).
just change how you set the markdown attribute... try:
<div markdown="**my message**"></div>
or
<div [markdown]="myVar"></div>
// somewhere in your class
String myVar = '**my message**';
Dart automatically blocks unsafe content. You would need to specifically bypass security. One way you can do that is here: https://webdev.dartlang.org/api/angular/angular.security/DomSanitizationService-class

How to prevent the <p> tag from wrapping around my input with tinymce in Rails?

By default, the tinymce input gets passed to the DOM as a paragraph tag:
I would like to remove that element wrapper so that tinymce passes exactly what I entered in the text editor.
How do I do that ? Please if you provide a code, can you also let me know where that code gets added ?
Regards !!!
Actually I solved my problem. All I had to do was change the styling for paragraph tag :
p {margin: 0; padding: 0;}
You need to specify the forced_root_block to false. However the documentation states that not having your root block as a <p> tag can cripple the editors behaviour. Newlines will be spaced with <br> tags instead.
tinyMCE.init({
selector: 'textarea',
forced_root_block: false
});
See the documentation here
I strip out those pesky things with gsub and regex like this:
<%= #event.desc_long.gsub(/^\<p\>/,"").gsub(/\<\/p\>$/,"") %>
First .gsub removes the <p> at the start of the TinyMCE string, and the second one removes the </p> at the end. Working great for me. This would work for any language that uses regex (gsub is for rails). JavaScript example:
var str = "{TinyMCE HTML string}";
str = str.replace(/^\<p\>/,"").replace(/\<\/p\>$/,"");
Hope this helps!
EDIT:
Re: where to put it. You leave what TinyMCE puts in your database alone. Add the above only when you display it (in the view, e-mail whatever).
In case you just want to get rid of margins:
tinymce.init({
...
setup: function(ed) {
ed.on('init', function() {
var doc = this.getDoc().getElementById("tinymce");
doc.style.margin = 0;
});
},
});

Dynamic styles for different user

I need dynamic styles for each user. The problem is such that it is possible to choose between two themes, one static and the other user can change. After change current user theme value will set to sass variable and need precompile. How I can do it?
It's better to rely on pure CSS features in this one rather than compile your SCSS on each request (which will be very inefficient).
Given this base SCSS file:
.base-theme {
.color-main {
color: $blue-lighter;
}
// and so on
}
You can use this like this:
<p class="color-main"> ... </p>
Based on settings stored in the database you can generate an alternative
theme like so:
<style>
.alt-theme .color-main {
color: <%= current_user.colors.main %>;
}
</style>
and apply them later like so:
<body class="<%= user.has_theme?? 'alt-theme' : 'base-theme' %>">...</body>

Grails - Pass JSON/Map object to client

I am trying to save a JSON object to a data- field in a gsp page.
Mock controller:
def test(){
['comments': ["1": 1, "3":40 ] ]
}
GSP (I also tried (comments as JSON) )
<%# page import="grails.converters.JSON" %>
<div class='findme' data-comments="${comments as JSON}">
Result:
<div class='findme' data-comments="{" 1":1,"3":40}">
As you can see the quotes are all messed up. I tried using encodeAsHTML but it didn't work.
I ran into this recently as well and came up with two solutions:
Solution One: in the template do this:
<div class="comments" data-comments="${comments.encodeAsJSON().encodeAsHTML()}">
Solution Two: in the controller do this:
def test(){
['comments': ["1": 1, "3":40 ] as JSON]
}
and in the template do this:
<div class="comments" data-comments="${comments.encodeAsHTML()}">
I'm using jQuery to do the parsing. With either solution I get the JSON like so:
$.parseJSON($('.comments').attr('data-comments'));
I found a couple ways to do it.
<div class='findme' data-comments="${(new JSON(comments)).toString().encodeAsURL()}">
Then I have to pull it out like:
JSON.parse(unescape($('.findme').data('comments')))
Found another way to do it, but it will cause problems if you have anything that has a " in it. I think encoding it is the way to go.
${(comments as JSON).toString().replace("\"", "'")}
I have found an easy way to do that.
First you do:
<div class="comments" data-comments="${comments.encodeAsJSON()}">
And then in javascript:
eval($('.comments').attr('data-comments'));

Using harsh with generated code

I have code in #snippet.code, and I want to highlight it with harsh:
:harsh
#!harsh theme = lazy
= #snippet.code
However, this just highlights #snippet.code, so the output is:
<pre class="lazy"><span class="Keyword">=</span> <span class="Variable"><span class="Variable">#</span>snippet</span>.code
</pre>
How can I use Harsh with generated code? Thanks
You need to print out the contents of #snippet.code
It would help to know what templating engine you are using. Try:
:harsh
#!harsh theme = lazy
<%= #snippet.code %>
This should work if erb get to the code before harsh.

Resources