Showing posts with label css. Show all posts
Showing posts with label css. Show all posts

Friday, January 18, 2008

Source code, HTML, and an Exercise for the Reader

No clue why I want to be vague about this. Probably because I'm late for a party, but really wanted to share.

And you're smart. You'll figure it out.

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="VS Copy-Paste to HTML" >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <RichTextBox Name="m_richTextBox" TextChanged="m_richTextBox_TextChanged" />
        <TextBox Grid.Column="1" Name="m_textBoxHTML" />
    </Grid>
</Window>

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void m_richTextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        m_textBoxHTML.Clear();
        m_textBoxHTML.AppendText("<div style=\"font-family:monospace;\">" + Environment.NewLine);
        foreach (Paragraph paragraph in m_richTextBox.Document.Blocks.Cast<Paragraph>())
        {
            foreach (Run run in Decompose(paragraph.Inlines))
            {
                m_textBoxHTML.AppendText(toCleanedColoredSpan(run));
            }
            m_textBoxHTML.AppendText("<br/>" + Environment.NewLine);
        }
        m_textBoxHTML.AppendText("</div>");
    }

    private string toCleanedColoredSpan(Run run)
    {
        SolidColorBrush solidColorBrush = run.Foreground as SolidColorBrush;
        if (solidColorBrush == null)
        {
            return cleanString(run.Text);
        }
        else
        {
            if (solidColorBrush.Color == Colors.Black)
            {
                return cleanString(run.Text);
            }
            else
            {
                string colorString = solidColorBrush.Color.ToString();
                Debug.Assert(colorString.Length == 9);

                colorString = colorString.Substring(3);

                return string.Format("<span style=\"color:#{0};\">{1}</span>",
                    colorString, cleanString(run.Text));
            }
        }
    }

    private string cleanString(string source)
    {
        source = HttpUtility.HtmlEncode(source);
        source = source.Replace(" ""&nbsp;");
        return source;
    }

    private static IEnumerable<Run> Decompose(IEnumerable<Inline> inlines)
    {
        foreach (Inline inline in inlines)
        {
            if (inline is Span)
            {
                foreach (Run run in Decompose(((Span)inline).Inlines))
                {
                    yield return run;
                }
            }
            else if (inline is Run)
            {
                yield return (Run)inline;
            }
            else
            {
                throw new NotSupportedException();
            }
        }
    }
}

Remembering why I like single-vendor platforms

Now before I start a flame war, remember what I wrote in September:

I believe in open standards. The only way to protect and encourage open standards is to have many prevalent implementations of said standards.

Having said that, there are still a lot of reasons to love single-vendor, even closed, platforms.

One of those reasons: compatibility.

I had a simple goal: change my blog theme from fixed-width to fluid-width.

Code lines tend to take up a lot more space than 450px. Formatting C# for narrow columns is a pain.

I searched and hacked in vane for over an hour before I found a CSS solution.

The whole time there was a 16-year-old inside of me yelling: "Just use tables! They worked great in 1996!"

I'm going to spare you the gnarly details, but it involves negative margins. (Yes, negative margins. I almost fell off my Swiss ball.) Huge props to the folks at Dynamic Drive for their straight-forward-as-can-be-expected walk-through of fluid, two-column layouts in CSS.

After a bunch of tweaking, I got everything looking good in Firefox. I then jumped into Live Writer to start writing. I updated the cached theme for my blog. It looked really broken. Why?

Well, Live Writer uses Trident--the IE rendering engine.

After much hacking, I discovered that IE cares about the order of <div> elements in situations where Firefox doesn't. Also, Firefox respects // to mark comments in CSS. IE doesn't.

After another hour, I got things working in both.

No I haven't tested in IE6 or Safari. Please let me know if you have issues.

I'm guessing I'm one of the few who look at my blog in a browser--most probably use a blog reader.

Good idea.