All opinions expressed are those of the authors and not necessarily those of OSNews.com, our sponsors,
or our affiliates.
published on 2008-12-17 20:27:00 in the "code" category
ReMarkable.zip 24.5 KB
ReMarkable is my own
Markdown-like syntax, used
to write and publish the content on this site.
It is a plain-text method of writing articles that is then converted into HTML.
To skip the talk and see it in use, you can add ?.rem? to the end of any article on this site to see the original
ReMarkable source for the article. For example:
?/code/remarkable.rem?.
- v0.2.4?31st December ?08
-
- Added testing script to verify output (incomplete)
**strong** will now give <strong>*strong*</strong>
instead of <strong>*strong</strong>*
- Lines being conjoined even if word-wrapping was off
- Correctly indent small blocks as paragraphs, also allow small blocks within lists/blockquotes
- v0.2.3.1?17th December ?08
-
- Links were not working, bug introduced in previous version.
I need to implement some unit tests or something
- v0.2.3?17th December ?08
-
nofollow support for links, prefix URLs with ?!?
- PRE blocks now allowed within lists, definition lists and blockquotes
- Blockquotes were not converting if they were the last thing in a document
- v0.2.2?14th December ?08
-
- Soft-space as newline marker has been removed. Too many problems involved with it being
invisible unless your text editor has white-space on and differentiates spaces from
soft-spaces. Instead, use the ?not? character ?
¬?. This is located
directly on the keyboard on PCs and obtained via Alt+L on Mac.
- v0.2.1?11th December ?08
-
- Some HTML tidying not working when
$indent>0
- v0.2
-
I have a lot of HTML. In writing and tweaking the content on this site, I found I was getting bogged
down in a lot of HTML tags for relatively minor things, such as links,
abbreviations and citations.
Though I love writing in HTML, I wanted to reduce this complexity and focus more on the content than the
markup.
The first place I turned to was
Markdown, probably the most
widely known plain-text formatter. John Gruber wrote Markdown for his site,
daringfireball.net and to suit his way of writing articles.
There were a number of shortcomings with Markdown when placed against my site:
- No support for abbreviations, citations and definition lists
- Perl. No hope I?d ever be able to customise it
Working around these concerns of mine could have been possible by using another Markdown clone that
would be easier for me to customise. A project called
PHPMarkdown implements a
Markdown parser in PHP, it also adds to the syntax, providing additions like abbreviations
and definition lists.
There?s one big problem with PHPMarkdown though. It?s size. My site?s php is
almost 600 lines long. PHPMarkdown is almost 3?000 lines long. To include PHPMarkdown in my site would
be like strapping an elephant to a flea and asking it to jump a canyon.
Really then, what I knew I had to do was to write my own Markdown clone, in my own particular demeanour.
I could cherry-pick the best syntax I wanted, but ultimately make it as artful as Camen Design is itself.
At a glance, compared to Markdown, ReMarkable has:
ReMarkable adds syntax for {abbr|abbreviations}, ((small text)),
~citations~, [insertions], --deletions-- and
«inline quotations».
The PHPMarkdown
syntax doesn?t allow for optional descriptions, where as the HTML spec, and
ReMarkable does.
:: Definition Term
Description?
:: Definition Term 2
:: Definition Term 3
Description?
You can see this structure put to good use in this article.
An idea taken from PHPMarkdown, for the benefit of writing a table of contents, or others linking to
specific parts of an article, headings can have an HTML ID like so:
# Heading Level 1 # (#id)
Heading Level 2 (#id2)
======================
Heading Level 3 (#id3)
----------------------
Links with absolute URLs are automatically marked up with rel="external".
Hyperlinks directly to a file have the type="mime/type" attribute added automatically for the most
common file types. ReMarkable has an easy to modify internal list of these types automatically recognised.
The benefit of this is that a) you should be doing this anyway, and b) you can use CSS mime-type icons
like this.
ReMarkable intelligently adds <p> tags to
<li> items.
A normal list:
? Item 1
? Item 2
? Item 3
Produces:
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
If any list item contains more than one paragraph, or any other block such as another list or blockquote, paragraphs
are automatically added.
? Item 1
? Lorem ipsum dolor sit amet, consectetur adipisicing elit.
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
? Item 3
Produces:
<ul>
<li>Item 1</li>
<li>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
</p><p>
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</li>
</ul>
But, if you put blank lines between the list items:
? Item 1
? Item 2
? Item 3
ReMarkable adds paragraph tags for all list items
<ul>
<li><p>Item 1</p></li>
<li><p>Item 2</p></li>
<li><p>Item 3</p></li>
</ul>
Lastly, if a list item contains no space between the opening text, and a list within the list item,
ReMarkable does not add the first paragraph. Why? For a table of contents list:
1. Features
1.1. More Inline Syntax:
1.2. Definition Lists:
?
Produces:
<ol>
<li>
Features
<ol>
<li>More Inline Syntax:</li>
<li>Definition Lists:</li>
</ol>
?
</li>
</ol>
Notice Features
is not wrapped in a paragrah.
ReMarkable does all of these conversion cases using only one regex replace.
In order for ReMarkable to be acceptable, it had to replace my hand-written HTML.
ReMarkable outputs clean and organised HTML and does perfect word wrapping so that when you
view-source you don?t have to scroll sideways.
ReMarkable can also indent the whole output to your liking, so you can fit it into your blog template.
<pre> blocks are intelligently unindented so that your code samples don?t break trying to fit
ReMarkable output into your site design.
Whilst not on exact feature parity with PHPMarkdown, ReMarkable achieves it?s design with
very compact code.
PHPMarkdown is spread across 120 functions composing two classes.
ReMarkable is nearly 400 lines long in just one function.
Lists, definition lists and blockquotes are recursively converted (including all the conversion cases mentioned
above) in two lines of code. Needless to say, the regex kills a kitten each time you run ReMarkable.
ReMarkable?s code has been a real labour of
love. I have tried to make sure it is well commented, but the tricks being used to reduce the amount of looping, and
to achieve all that it does within one function can be difficult to understand. A future
Under
the
Hood
article will do a more detailed breakdown of
the PHP used.
The goal with ReMarkable was to be able to publish my entire site?s contents. That has been achieved.
Now ReMarkable is in your hands. I?m sure you?ll find a million bugs I never noticed. I don?t
write articles the same way you do. Send bugs and suggestions to
kroccamen@gmail.com
There are a number of shortcomings of ReMarkable that I?m aware of and will be tackling at various
stages of the future (as Camen Design?s needs demand, really).
- Autotext
-
For the benefit of being a) lazy and b) writing on systems where Unicode is not so easy to type,
I?d like ReMarkable to integrate a
SmartyPants
like auto-text converter to add smart quotes and other typographical highlights like en & em
dashes. Also things like automatically adding <sup> to number ordinals.
Autotext would also include syntax to automatically generate a table of contents list from
ReMarkable-headings with IDs
- Syntax highlighting for PRE blocks
-
This won?t be rolled into ReMarkable itself, but instead be a separate add-on module
(which will also allow you to use a different more better syntax-highlighter than my
own). At the moment I?m manually marking up my code examples as there is no current
syntax-highlighter that is small enough and able to deal with my website?s position of having no
classes.
I intend to write a tiny and simple syntax highlighter, that works without classes, to
automatically markup (not just colour) my code samples automatically.
- Tables?
-
Syntax for writing tables will be difficult to add in elegant way. A lot of thought will have to be put into
this as it must maintain clean markup and work primarily without classes. (It?s a sin of software to force
the artist to use a particular class-name, when that is their decision and shouldn?t be taken out of their
hands). How would you like it if you bought a canvas to paint on, but the canvas mandated that you must
paint only fruit?
Any suggestions though for these features, is always welcome.
That said however, ReMarkable was not designed to ever be all things to all people. In accepting
suggestions and fixes into my version of the code, these are ReMarkable?s priorities:
- HTML5, UTF-8. No classes
-
If you need every HTML tag to have a class or ID you need to learn
how to write better code.
ReMarkable doesn?t output any HTML5 specific tags, so it?s safe to use in
HTML4
- Sloppy writing is not a fringe case
-
ReMarkable will never allow escaping of characters. That?s a cop out to avoid
properly designing the syntax.
Any weird text you?re writing that?s firing off ReMarkable syntax is more than
likely a computer term or technical quote and should be wrapped in `code` spans.
For example: I copied the ~luser folder to ~root
would be recognised as a
citation between the two tildes. Regardless of any literal readability, these folder names
(including the tilde) are not part of the English language. Use
I copied the `~luser` folder to `~root`
instead.
If the bug can be solved by following the syntax documentation correctly, or by changing two or
three letters in your source, then it?s not a bug.
- Code is Art
-
If I can?t maintain elegance and beauty in the code then it can?t be worth it.
Enjoy.
Comments
published on 2008-12-16 10:17:00 in the "code" category
?. the Need for CSS-Hacks
In a world of imperfect browsers, the CSS-hack can be both a beautiful thing, and also an ugly thing too.
It is unavoidable that at some point some feature or design you wish to implement hits a limitation or parsing /
rendering bug of one (or more) browsers you are supporting.
If this has never happened to you; well done?you?re an IE only web-developer who?s never stepped
outside of Microsoft software, nor table-based design. You?re probably confused by the term CSS
.
If, however, you do not own that privileged position of ignorance, everybody comes across the need to target a
particular bit of CSS to a particular browser.
?. the Question of Maintenance
There are many
arguments about if CSS-hacks
should be totally avoided, embraced, or properly managed somehow.
Firstly, to think they can be avoided is naïve. I have a website that only supports Acid2 compliant browsers, uses
CSS3 liberally, and doesn?t support IE one iota?and still I have CSS-hacks
to deal with browser idiosyncrasies.
The next two lines of argument are either a) just embed hacks in your normal document?it?s less maintenance to
only edit one document and b) keep hacks to a separate file where they can be managed individually, ideally using
conditional comments to target IE specifically or Javascript to correct behaviour.
Embedding CSS-hacks in stylesheets increases maintenance by making them an integral part of testing in
all browsers. CSS designed to correct one browser may have undesired effects on another browser. Or a
hack that has been used before, may no longer work on a newer version of a browser, but now you have to scramble to
somehow support both browsers.
A hack is anything that has the potential to fail disastrously
each time something changes expectedly.
Having to make corrections to your whole stylesheet to please one browser, is unnecessary maintenance. Having all
your failure points in one document is not less maintenance. I have not very fond memories of having to rewrite large
portions of a stylesheet because of being unable to please one browser without effecting
sic others.
The answer therefore is to tie CSS-hacks?or at least alternative CSS?directly to the
browser it fixes, so that it does not becoming a ticking time bomb for other browsers and future versions.
In the case of IE, conditional comments give very precise targeting
capabilities. Conditional comments are an excellent solution for applying alternative CSS, rather than
relying on CSS-hacks preying on broken parsing. However, there are a couple of let-downs:
- IE Only
- Conditional Comments rest inside the HTML
Having to maintain HTML because of a browser, is like suddenly waking up one day to discover that the
letter Z has been officially depreciated by the European Union and now you have to update all your documents to conform.
Your HTML, like diamonds, should be forever.
Lastly, using a Javascript fix is only increasing the length of thread you have to follow when something breaks. If
suddenly you find that a CSS property you apply does not have the expected behaviour in IE,
but gives different results with the Javascript fix on, and then off: you now have a maintenance nightmare that
involves back-tracking through ?x?-tons of Javascript, that likely, you didn?t write yourself.
What if a new version of a browser comes out and your Javascript fix doesn?t work with that browser, but also, the
site design won?t render correctly without it? Now you?re forced to either remove the Javascript and do the
CSS again, properly, from scratch; or update the Javascript with all the work that entails.
A solution is needed that:
- Works for all browsers and does not rely on browser-specific capabilities to implement
- Negates the need for CSS-hacks, and instead encourages alternative CSS
- Targets browsers/versions specifically or according to a range
- Does not fail when a new browser or version arrives on the scene
?. the Answer Is Still Targeting
We all know that user-agent targeting is bad. It defeats the purpose of having standards to work across all browsers.
However, thus far, we have, by proxy, ascertained that there are two types of CSS:
- CSS that works in all browsers
- CSS that does not work in all browsers
The maintenance problems so far outlined are because there is no clean separation of these two?except for
IE conditional comments, with the acknowledgement that they are an incomplete solution.
We have also ascertained that browser-specific CSS is eventually required given imperfect browsers. You
can either choose to compromise on your design to avoid this, or compromise on the browser and keep the design.
Either way, the end-user should never be compromised on.
It?s important to state that writing standards-compliant, proper CSS is always desired. Legacy
browsers are exactly that: legacy. Therefore a solution to dividing the two types of CSS must primarily
acknowledge that proper CSS comes first and does not require any maintenance going forward. The current
solutions mentioned earlier do not give weight to the better CSS over the bad CSS.
Basically, with a perfect solution, a perfect browser would never parse any hack or CSS intended for
only one browser?it would be ignorant of legacy browsers.
The important thing with User-Agent targeting is the ability to also not target user-agents. Some believe
user-agent targeting to be a form of quicksand that has you chasing after every browser ever made.
A browser that applies the standards, and requires no browser-specific CSS to render the
design, does not need to be targeted. No solution is actually needed.
My proposal is therefore a solution only for legacy browsers. If a browser does not need browser-specific
CSS to get it to render a design right, then it requires zero maintenance on part of this solution.
There is no interference by the solution to browsers that do not need it.
The Solution
Apache?s mod_rewrite module allows us to take a file requested by the browser, and
provide a different file instead, based on some matching or non-matching criteria.
What if we had a ?fixes.css? file that was different for each browser that needs to be targeted, but
void by default so that any browser that doesn?t need fixes, doesn?t get any?
We start with two stylesheets declared in the HTML head element:
<link rel="stylesheet" type="text/css" href="css/main.css" />
<link rel="stylesheet" type="text/css" href="css/fixes.css" />
You write your main stylesheet using absolutely no CSS-hacks or browser-specific
workarounds. Write for the future. As more and more browsers come on board with Acid 2 / 3,
CSS3 compatibility &c. they should automatically fall into working
with your site?zero maintenance needed.
Remember, this mod_rewrite solution is only to bring non-complaint browsers into spec.
Ideally, for example, you?d write your stylesheet to meet Acid 2 capabilities and when IE8 is released
the site just works
, and the IE7 workarounds stay with IE7.
The actual ?fixes.css? file itself is, therefore, completely blank.
In your ?.htaccess? file use the following two lines to target a browser and rewrite the ?fixes.css? file to
a browser-specific version: (IE7 in this example)
(Assuming you?ve already got ?RewriteEngine on? in your ?.htaccess? file and
?RewriteBase?
if needed.)
RewriteCond %{HTTP_USER_AGENT} MSIEs7.(?!.*Opera)
RewriteRule ^(.*fixes).css$ /$1.ie7.css [L]
This selects a user-agent containing MSIE 7.
as long as it?s not followed by Opera
at some point (to
ignore Opera spoofing as IE). The ?fixes.css? file is then rewritten to a ?fixes.ie7.css? file
where you may store the IE7 specific fixes you need to apply.
Now users of IE7 will receive a different ?fixes.css? than users of any other browser.
It?s a bit like having a user style on your own website. You
can apply a CSS ?patch? to the site for specific browsers, keeping your main stylesheet legacy free
and future-facing.
Potential Uses
-
Use @font-face to render titles using embedded fonts, but fall back to images on
unsupported browsers
-
Use box-shadow and text-shadow effects in the main stylesheet, but fall
back to transparent PNGs or generated content to replicate the effect in older browsers
-
Provide a ?lo-fi? design for legacy browsers (try viewing
this site in a good
browser, and then in IE6)
In short, old browsers shouldn?t prevent you from using the latest and greatest that up-to-date browsers offer.
It?s up to you to keep legacy where it belongs.
Addressing Concerns
?Aha!?, I hear you say. ?But surely this creates more maintenance, now we have many
CSS files!?
With this solution, when you make a browser-specific correction, you only need to test in that browser itself. Less
maintenance. Without this solution, a browser-specific fix also gets parsed by all browsers, and you need to test
them as well. More maintenance.
?But now you have to maintain the ?.htaccess? file!?
As browsers get more capable, the less browser-specific CSS you will need to target, if at all. An old
browser doesn?t stop being an old browser. As long as you?re not changing the HTML, this solution
can safely bit-rot without ever being looked at.
This solution also allows you to react smoothly and quickly to an unexpected regression between versions of browsers.
Imagine you try out a beta browser like Opera 10 or
Firefox 3.1 and you suddenly find
your design breaks with it. You can?without touching a line of your existing main stylesheet?add two lines to the
?.htaccess? file to detect the new browser, and then develop, on a new sheet, the necessary fixes without
compromising any of the existing CSS. You can then choose to leave that as is, or then once working roll
it back into the main sheet. This is significantly less panic-prone than having to apply fixes for an unreleased
browser to a live, perfectly working stylesheet.
Imagine you want to stop supporting a legacy browser. With this method, you remove the two lines in the
?.htaccess? file, delete the specific ?fixes.css? file and that?s it?browser unsupported. Without this
solution, you would have to manually unpick the CSS-hacks from your main stylesheet and slowly rub-out
any influence that browser had on the design of the CSS. Sometimes the only way to truly remove a
browser?s influence from a large bit of CSS is to simply rewrite it (due to all the extra capabilities
opened up with newer versions that you should now be making use of).
?What about people/browsers spoofing user-agents??
Not a problem. Seriously. Writing the right regex to spot lame attempts at spoofing is not difficult. Many browsers
add like Gecko / khtml
despite this being patently false. It?s becoming more common even to add
Firefox
into Gecko browsers given Firefox?s weight in the market. It?s sad, really, that some have given
in to this pathetic behaviour.
If you?re literally browsing with a completely false user-agent by default, you are a) 0.01% of the
population and b) have a personality disorder, or something. Spoofing has it?s uses, but it?s legacy as well and
should be sent the way of the dodo (if browser vendors stop with this ridiculous behaviour of saying they?re
engines they are nothing like).
In other words, the answer is: learn regex.
The HTTP-Request Tax
I hate wasting HTTP-Requests. If you want a fast site, it?s not bandwidth or file size that matters;
no, it?s the number of HTTP-Requests. Each one could have potential delays up to 1?2 seconds in
worse cases.
So there?s a severe flaw with this solution, the browser has to fetch two CSS files, even if the
browser doesn?t need any fixes. This is a tax on good behaviour!
There is a workaround for this that presents only one stylesheet to compliant browsers, but two stylesheets to those
browsers that need fixes.
If you present just one stylesheet in the header:
<link rel="stylesheet" type="text/css" href="css/main.css" />
And then, in the ?.htaccess? file, redirect ?main.css? to the fix sheets, for those legacy browsers:
RewriteCond %{HTTP_USER_AGENT} MSIEs7.(?!.*Opera)
RewriteRule ^(.*)main.css$ /$1fixes.ie7.css [L]
# ...
# after legacy fixes, redirect ?main.css? to the actual main sheet ?_main.css?
RewriteRule ^(.*)(?<!_)main.css$ /$1_main.css [L]
And at the top of each fixes sheet, just simply import the main stylesheet.
(The main sheet uses a dummy name to prevent the @import from getting stuck in an infinite loop.)
@import "_main.css";
/* browser specific fixes here... */
This way, a browser that needs correction gets the fixes sheet first (with the main stylesheet imported at the top)
and a browser that doesn?t need any fixes just gets the main sheet alone.
Example Reference
For those with worn C and V keys, here?s some additional rewrite conditions to select particular browsers (Add the
RewriteRule according to your chosen method). If you?ve any suggestions for good examples, do
send them my way
If you want some sample user-agent strings to work out the right regex needed for a particular browser,
here?s a good list.
Internet Explorer (Any Version):
RewriteCond %{HTTP_USER_AGENT} MSIEsd.(?!.*Opera)
Change d
to any number to select a particular version
Internet Explorer, Version ?X? and Below:
RewriteCond %{HTTP_USER_AGENT} MSIEs(d).(?!.*Opera)
RewriteCond %1 <=7
Change the <=
to
>= to target a particular version and above.
Firefox, Versions Before 3.0:
RewriteCond %{HTTP_USER_AGENT} Gecko/(d{8})(?!.*Opera)
RewriteCond %1 <20080529
Do not ever try detect Firefox using ?Firefox?. Remember that Gecko,
the rendering engine that powers Firefox is used in many other browsers too that would have equal
capabilities, such as Camino. Many browsers now
spoof as Firefox too, so always detect using the Gecko date of the browser in the user-agent.
iPhone:
RewriteCond %{HTTP_USER_AGENT} iPhone|iPod
Enjoy.
Comments
published on 2008-11-13 19:35:00 in the "code" category
I received this email:
Hi Kroc,
I stumbled on your website today and was quite impressed with quite a few different things about it (the
design, the tone of your writing, &c.).
The one thing in particular, and something I wanted to question you on, was your reference to
HTML5. Something I know nothing about. In the post I came across you talked about a guy named
Sam Ruby and how he referred to it as minimalist
code. Anyway that?s beside the point. I?m really
interested in using no IDs and/or classes, but know nothing about HTML5.
So here?s my question, ? do you recommend any other resources or tutorials for someone like
me? I rely very heavily on classes and my stuff is sloppy for the most part. I?d love to convert my site
but have no idea where to start.
Any advice or words of wisdom would be greatly appreciated. Thanks in advance.
Joe Holst
Hello Sir,
You only require one thing, and then to do three things in order to succeed in your goals here.
Firstly, you need to get some willpower. You already seem to have that, as you?ve taken interest to email me to ask
about where to start. Without the want to write better code, no learning in the world can help!
It should be noted that absolutely nothing I?m doing is undocumented; in that fact none of the code on my website
is even special?all it is, is the representation of my personal drive for quality, as I measure it.
I don?t think willpower is going to be a problem for you if you already twig that HTML5 and cleaner
code is the direction you might want to go. Some people don?t ever progress beyond writing
IE-only junk, and that?s not down to skill level, it?s a willpower
problem.
Secondly, you need to do three things:
- revise,
- revise,
- revise.
I proof-read and break my code over and over again, to chip away what niggles me here and there. Getting rid of
classes is a one-by-one process, because each class has a use that may be totally unrelated to the other classes in
the document. Each class is it?s own problem, some big, some small?some requiring a complete rewrite even.
I?m quite happy to break my entire codebase for a week?rewriting and reorganising everything?just to get one
tiny annoyance out of sight and out of mind.
If you proof read your codebase you?ll spot various things that could be better, all of varying difficulty levels,
some maybe without a clear solution. Start by picking something that annoys you, that you know could be done better,
and fix it? even if it?s just tidying up a comment so that it looks nicer. Polish your code.
That is how I work. I scan through my code and look at it objectively. I think about where I can make it cleaner,
tidier, less complicated, better documented, easier for others to understand; anything that catches my eye.
I pick something that I personally feel motivated toward (I have no boss on my personal site, so I only have to fix
what I care about; and in that, the quality, through passion, is maintained) and I set about fixing it. Sometimes
that?s a big problem?like what I?m working on right now: a Markdown clone, so as to reduce the
amount of HTML I?m writing for minor things like abbreviations, links and citations
ReMarkable?or sometimes it?s a small thing like shaving
a few lines off here and there. I do whatever my heart feels capable of doing that day. I try never strain myself by
doing work I?m not interested in?that?s for secular work.
Once I?ve made my fix, I go through the whole process again. Often whilst I?m implementing one fix it unearths
other annoyances that I want to solve and I?ll either get distracted and go off and fix those, or wait until I?ve
finished the thing I started on and be well set with another task to do afterwards?with a much stronger
understanding of the problem to drive me forward with the design issues.
O, the design issues.
I am a slave to my code sometimes. I will not accept a sloppy solution. I pace around a lot. I wrestle with the
architectural design of the code in my mind for days. I spend 100 hours writing 29
lines of code. Because to me, good code is not about how l33t your programming knowledge is, good code is about
how much you rethink what you?re trying to do. What cohesive statement are you trying to make with your code?
Sometimes your code is not just about trying to solve a problem,
it?s trying to solve a problem using your personality.
But getting back to HTML5?
Before you learn HTML5, first learn HTML4. I know that sounds stupid, you may very well
think you already know HTML4. In learning HTML5, I first referred to
this list. Apart from the depreciated ones, do
you know how to use all of them? I found that there were a number of HTML4 tags that I rarely used, that
could easily replace sloppy <div>s and classes.
I see this often, and it really annoys me.
<div id="header">
<h1>Title</h1>
</div>
Elements that are not <div>s can be styled just the same as a <div>.
A <h1> is not somehow magically unable to have borders or backgrounds or margins or padding or
anything a <div> can.
People seem to get this mindset that only <div>s can be used as boxes.
Here?s a list of elements you can use instead of <div>s.
P, BLOCKQUOTE (with P inside),
H1/H2/H3?, ADDRESS,
DL/DT/DD, UL/OL/LI, HR
(Note: You can?t put a block level element in another. i.e. you can?t have a
H1 inside a P or vice-versa)
All of these can be styled with any effect?meaning that you can get rid of a <div> and/or
class, by just referring to the element directly, or by it?s parent.
For example:
<h1>Website Title</h1>
<ol id="menu">
<li>menu 1</li>
<li>menu 2</li>
</ol>
<h2>Article title</h2>
Is better than
<div id="title">Website Title</div>
<div id="menu">
<div class="menuitem">menu 1</div>
<div class="menuitem">menu 2</div>
</div>
<div class="title2">Article title</div>
And for that matter, why would you have a class for a menu item, when the menu is perfectly identifiable? Even in
this bad example, you could still get rid of the menuitem class, and just refer to them with
#menu div {...}.
An <ol> makes a perfect menu. It is after all, an Ordered List. Get to know what each of the
element names means, how you would think of that in a standard word processor document, and then how that can be
applied to your site, imagining your site as a word processor document without any CSS. Your menu would
be a table of contents of sorts, and therefore would obviously be an Ordered List.
Here?s a different example I helped someone with:
<div id="leftcol">
<h2 class="blue">Recent Project</h2>
?
</div>
<div id="rightcol">
<h2 class="green">News Updates</h2>
?
</div>
He wanted the headings on the left blue, and the headings on the right, green. Which is fair enough.
However, could you not just select the column, and do away with the need for the classes?
/* as a rough example */
#leftcol h2 {color: blue;}
#rightcol h2 {color: green;}
Knowing, and using more elements, instead of resorting to <div>s all the time, allows you to use
CSS to select those elements more widely as well as specifically. Here, both of these are
<h2>
s. Now if they were <div>s, we would have to use classes,
because there would likely be yet more <div>s in the columns and you couldn?t say
#leftcol div without turning many things blue or green instead of just what you wanted.
Getting rid of <span>s with classes requires knowing the meaning of the many inline elements.
Google them.
ABBR, ACRONYM, BIG, CITE,
CODE, DEL, DFN, EM, INS, KBD,
Q, SAMP, SMALL, STRONG, SUB, SUP,
VAR
Think of these elements outside of the browser, on a printed piece of paper. You can then bombard them with
CSS to make them look like anything?even if they don?t look anything like what they?re supposed
represent?but their use will be semantically sound, having the right meaning in your website.
Learn the selectors.
If you know the selectors and the the tags well enough, then you only need a class (or ID) when you
cannot differentiate two elements from each other with the browser you are supporting. Since I?m using
CSS3 and not supporting IE at all, I don?t need
any classes because I?ve made the right choice of tags, and can differentiate all of them with the right
CSS selectors.
If you want clean code using few, if any, classes then right away ditch IE6. Stop supporting it, tell
people to upgrade. Without + and > selectors, IE6 is too frightened to go
anywhere that isn?t within sight of a class or ID.
IE7 does support + and >, and
whilst it lacks in many other areas, it has the necessary basics to write good HTML/CSS.
Check what your targeted browsers support.
Once you have made a decent HTML4 site, then you will look at the HTML5 specification, and
it will make sense?you will know what to do with it.
Kind regards,
Comments
published on 2008-10-29 15:21:00 in the "code" category
Update 2: The script is failing the test
suite, I?ll have to update again once I?ve solved this, but it looks tricky - PHP and Unicode issues.
Update: Fixed a couple of major problems:
1. HTML entities were not being removed before processing
2. Made a typo when porting from Javascript that caused some failures
John Gruber originally made available his
script to Title Case text, working around the fringe-cases.
From this, a number of ports were
made of the script of which particularly noteworthy
David Gouch?s Javascript port that was
smaller, simpler and handled more fringe
cases.
I?ve ported this to PHP and put it to use on this site. My version is based on David Gouch?s
Javascript port, unlike the WordPress
port which is, frankly, crap.
Code below.
//original Title Case script © John Gruber <daringfireball.net>
//javascript port © David Gouch <individed.com>
//PHP port of the above by Kroc Camen <camendesign.com>
//this is required for PHP to not break unicode characters in your titles when using `strtolower`/`strtoupper`
//you can place this near the top of your script, or within the function itself
mb_internal_encoding ("UTF-8");
function titleCase ($title) {
//remove HTML, storing it for later
// HTML elements to ignore | tags | entities
$regx = '/<(code|var)[^>]*>.*?</1>|<[^>]+>|&S+;/';
preg_match_all ($regx, $title, $html, PREG_OFFSET_CAPTURE);
$title = preg_replace ($regx, '', $title);
//break by punctuation, find the start of words
preg_match_all ('/[w&`'??"?.@:/{([<>_]+-? */', $title, $matches, PREG_OFFSET_CAPTURE);
foreach ($matches[0] as &$m) $title = substr_replace ($title, $m[0]=
//find words that should be lowercase
$m[1]>0 && mb_substr ($title, $m[1]-2, 1) !== ':' && preg_match (
'/^(a(nd?|s|t)?|b(ut|y)|en|for|i[fn]|o[fnr]|t(he|o)|vs?.?|via)[ -]/i', $m[0]
//convert them to lowercase
) ? mb_strtolower ($m[0])
//else: brackets and other wrappers
: ( preg_match ('/['"_{([]/', mb_substr ($title, $m[1]-1, 3))
//convert first letter within wrapper to uppercase
? mb_substr ($m[0], 0, 1).mb_strtoupper (mb_substr ($m[0], 1, 1)).mb_substr ($m[0], 2)
//else: do not uppercase these cases
: ( preg_match ('/[A-Z]+|&|[w]+[._][w]+/', mb_substr ($m[0], 1)) ||
preg_match ('/[])}]/', mb_substr ($title, $m[1]-1, 3))
? $m[0]
: mb_strtoupper (mb_substr ($m[0], 0, 1)).mb_substr ($m[0], 1)
)),
$m[1], strlen ($m[0])
);
//restore the HTML
foreach ($html[0] as &$tag) $title = substr_replace ($title, $tag[0], $tag[1], 0);
return $title;
}
Anything broken, please let me know.
Kind regards,
Comments
People are working on getting Perl support for Google App Engine, led by Brad Fitzpatrick (of Livejournal, memcached, etc. fame) at Google.
They've created a new module, Sys::Protect, to simulate the restricted Perl interpreter that would have to exist for Google App Engine. There's some discussion of why they didn't use Safe, but it sounds like it's based only on rumors of Safe problems, not anything concrete.
Safe is built on Opcode, and Sys::Protect appears to work the same way Safe + Opcode do, by blocking certain Perl opcodes. All the problems I've heard of and personally experienced with Safe were because it was working just fine -- but being terribly annoying because many common Perl modules do things a typical Safe compartment disallows. That's because most Perl module writers don't use Safe and thus never encounter such problems. It seems likely that Sys::Protect and a hardened Perl Google App Engine environment will have the same problem and will have to modify many common modules if they're to be used.
Moving on, posters are talking about having support for Moose, Catalyst, CGI::Application, POE, Template::Toolkit, HTML::Template ... well, a lot. I guess that makes sense but it will be a lot of work and complicates the picture compared to the simple Python and custom Django-only initial unveiling of Google App Engine.
If you're interested in Perl support for Google App Engine, log into your Google account, visit the "issue" page, and click on the star by the title to vote in favor of Perl support.
Comments

After reading a ridiculous post on "
surviving the digg effect on a shared host," (and then laughing ridiculously at it), I decided to write a
real tutorial on real-live ways not only to survive the digg effect, but also a simple but powerful way to improve your site's performance. Read more within.
Tags:
Code,
Development,
Digg,
PHP,
High Performance
Comments

Some time ago, I wrote an application for my company. Like most weblets I've written, this used PHP and either MySQL or MSSQL for the backend. This particular application logged all phone calls. As part of the record, it would record the caller's account number, which is a 5 or 6 digit integer.
So, I got a phone call from the director of our customer contact department this week. He was concerned about the reports. He made a decision last week that when a call came in that was a lead - in other words, a non-customer, that his people would fill the phone number from the caller ID into the account number field. But when he ran his export reports, he found that hisn techs had entered this phone number for ALL of the calls: 429-496-7295. That's weird, he said. So he called me and asked why that was. I checked all the calls and most were from one woman, so my first instinct was "Check if her browser has autocomplete turned on". But he swore that he tried it too and gotten the same result.
I checked the database and sure enough, it was right there: 429-496-7295, in all of the fields. So I went back to the code. In short, I took the input from the form, and declared it like this:
$accountnum = (int) $_POST['accountnum'];
Pretty straightforward: explicitly declare the type. So, I started my debugging by attempting to manually enter the data into the database. Sure enough: the account key field showed this: 4294967295.
So, I went back to the PHP and started by dumping out the raw SQL query:
INSERT INTO calls ('','x','x','x','4294967295','x','x');
What? So the database automatically converts it to this weird phone number and PHP does too? Suddenly it occured to me. One of the benefits of 64-bit computing is the ability to address more memory. There are limits to what can be done in 32-bit computing, and one is that
integers have a limit! In this case, a database field called "integer" is limited to numbers between -2,147,483,648 and +2,147,483,647. It just so happens that the number is the same length as a US phone number - 10 digits. Changing the db field to "BIGINT" allowed me to manually run the SQL query and it worked. But the app still didn't.
PHP's int() and (int) $var syntaxes both conform to the integer limit. So I devised a work around:
$ac = $_POST['accountnum'];
if(!is_numeric($ac) { $ac = (int) $ac; }
It's not gorgeous, but it will more than suffice for an internal app. We web programmers don't usually have to deal with big integers, so it's totally possible that web developers would never have had occasion to handle a situation like this. Here's looking forward to native 64-bit for our next server, though.
Tags:
Code,
PHP,
Programming,
Development,
Nerd
Comments

This is going to be a very nerdy post, because I'm going to get into some actual PHP code. I've been thinking a lot about efficient threading. The implementation of threading on
OSNews is very complex, because it involves lots of math in order to properly construct and align tables. Furthermore, because we don't use CSS for positioning, it's accomplished via 'align' commands and TWO templates, which is really clumsy, because between flat mode, admin mode, collapsed threading mode, and expanded threaded mode, we have several templates, and since they are all independent, they tend to unintentionally vary, so you might see different things in replies and threads. My goal in writing a threaded display for firsttube.com was to avoid all of the pitfalls in that implementation and come up with something clean. Read on for the gory details.
Tags:
Code,
PHP,
Lesson,
Threading,
CSS,
OSNews,
Meta,
Nerd
Comments

I am going to start a new practice here. Every now and again I'm going to post some PHP code with some explanation. Today, I'm going to write about what I've been calling "pretty URLs" and how to create and manage them in PHP.
PHP includes a variable in the superglobal scope $_SERVER called "PATH_INFO." PATH_INFO includes information entered after the name of the requested script.
Let's use firsttube.com as an example. The URL of a story is constructed as such:
http://firsttube.com/read.php/[id]/[url_friendly_title].html
The story is also accessible as /read.php?id=[id]
So how do we construct this so-called "pretty URL?" Using PATH_INFO. Read on for details.
Tags:
Code,
tubecode,
PHP
Comments