User Generated Custom CSS

User generated custom css

and then using dom:loaded with prototype

Awww, don't do that! That won't work when JavaScript is turned off.

Approach 1: Static stylesheet, dynamic values in document head

For the sake of not having to work with a dynamically created style sheet, have a separate, static CSS file with all the definitions that won't change.

<link rel="stylesheet" href="styles/static.css" type="text/css"> 
<!-- Or whatever you name it -->

All the definitions that will change, you could put into the head of the HTML document, fetching the user-changeable values from a database.

<style type="text/css">
.classname { font-size: (fontsize); } <-- Insert dynamic value here
.classname { color: (color); } <-- Insert dynamic value here
....
<style>

that way, the majority of the CSS stays in static, cacheable files, while the dynamic part won't cause another HTTP request.

Approach 2: Dynamic stylesheet

If you have a lot of dynamically changing values, put the entire style sheet into a script file and output it, replacing placeholders with the values from the database.
The downside to this is that to force the browser to reload the style sheet on changes, you'll have to work with a version approach stylesheet.css?version=400 which is pretty complex to do, but can sometimes be more desirable than littering the head section with CSS.

You decide which approach suits your situation better. I find myself choosing the first one most often.

How to create custom CSS on the fly based on account settings in a Django site?

I've used option #2 with success. There are 2 decent ways of updating the generated static files that I know of:

  1. Use a version querystring like /special_path.css?v=11452354234 where the v parameter is generated from a database field, key in memcached, or some other persistent file. Version gets updated by admin, or for development you would just make the generation not save if the parameter was something special like v=-1. You'll need a process to clean up the old generations after some time.

  2. Don't use a version querystring, but have it look first for the generated file, if it can't find it, it generates it. You can create a cron job or WSGI app that looks for filesystem changes for development, and have a hook from your admin panel that deletes generations after an update. Here's an example of the monitoring, which you would have to convert to be specific to your generations and not to Django. http://code.google.com/p/modwsgi/wiki/ReloadingSourceCode#Monitoring%5FFor%5FCode%5FChanges

What is the best way to handle user generated html content that will be viewed by the public?

That's an entirely reasonable approach. For typical applications it will be entirely sufficient.

The trickiest part of white-listing raw HTML is the style attribute and embed/object. There are legitimate reasons why someone might want to put CSS styles into an otherwise untrusted block of formatted text, or say, an embedded YouTube video. This issue comes up most commonly with feeds. You can't trust the arbitrary block of text contained within a feed entry, but you don't want to strip out, e.g., syntax highlighting CSS or flash video, because that would fundamentally change the content and potentially confuse anyone reading it. Because CSS can contain dangerous things like behaviors in IE, you may have to parse the CSS if you decide to allow the style attribute to stay in. And with embed/object you may need to white-list hostnames.

Addenda:

In worst case scenarios, HTML escaping everything in sight can lead to a very poor user experience. It's much better to use something like one of the HTML5 parsers to go through the DOM with your whitelist. This is much more flexible in terms of how you present the sanitized output to your users. You can even do things like:

<div class="sanitized">
<div class="notice">
This was sanitized for security reasons.
</div>
<div class="raw"><pre>
<script>alert("XSS!");</script>
</pre></div>
</div>

Then hide the .raw stuff with CSS, and use jQuery to bind a click handler to the .sanitized div that toggles between .raw and .notice:

CSS:

.raw {
display: none;
}

jQuery:

$('.sanitized').click(function() {
$(this).find('.notice').toggle();
$(this).find('.sanitized').toggle();
});

Prepend custom css to generated CSS files

You can solve it with jQuery:

function isIE() {
return (navigator.userAgent.toLowerCase().indexOf('msie ') != -1) || (!!navigator.userAgent.match(/Trident.*rv[:]*11\./));
}

$(function() {
if (isIE()) {
//merging all the content in your generated styles
var styles = $("style").text();
//getting rid of the many unneeded styles
$("style").remove();
//Putting back all the styles into your document
$("head").append("<style>" + styles + "</style>");
}
});

The idea is to merge the styles into a single text, remove all the styles and then create a single style tag instead of them. You need this only for IE, so I have added a function with which you can check whether it is Internet Explorer and if so, then merge the styles.

Where is custom.css in the generated html file from nbconvert?

The <link rel="stylesheet" href="custom.css"> effectively causes customized CSS styling rules to be included if the file custom.css exists in the same directory.

In case you want some customized CSS styling rules for displaying the generated html. You can add a file custom.css with those rules, in the same directory as the html file.

This is not a mandatory requirement. It is fine to not include such a file if you don't want any customized styling rules. The default CSS rules in generated HTML file will still work.

applying styles to static site html and user generated html content

Using an iframe is the way to go.

Here's some examples of how to communicate with it and access it's content.



The iframe content can call a function in the parent like this:

parent.yourFunction() 

The parent can call a function in the iframe like this:

document.getElementById('iframeid').contentWindow.yourFunction();

The parent can access the iframe's html like this:

document.getElementById('iframeid').innerHTML() = "<html><body><div>some content</div></body></html>";

Not quite what you were hoping but it's the only way to have css only apply to part of a page.

keep user-generated content from breaking layout?

  • Maybe overkill, but HTML
    Tidy
    could help if you can use it.

  • Use a WYSIWYG like
    TinyMCE
    or CKEditor that has built in cleanup methods.

Robert Koritnik's suggestion to use markdown seems brilliant, especially considering that you only allow a few harmless formatting tags.

I don't think there's anything you can do with CSS to stop layouts from breaking due to open HTML tags, so I would probably forget that idea.



Related Topics



Leave a reply



Submit