Crayon Meets Ruby

In 1.7.24 I’ve added Ruby and Ruby on Rails as a language on Crayon. Even cooler, I’ve added the <% ... %> and similar delimiter tags for eRuby/RHTML. Using Multiple Language Highlighting in Crayon, you can choose HTML as the base language with the lang="html" attribute or the [html]...[/html] Mini Tag and then through in some eRuby syntax. The red bits are Ruby, all else is XHTML. Note you can do the same thing with PHP tags, CSS tags and JavaScript tags.

Here’s the shortcode I used:

[html]
Some <strong>HTML</strong> first.

<ul style="color:red;">
<% 3.times do %>

  <li>list item</li>

<% end %>

% $s("ewfwe")

</ul>

<%= "print something" %>

Tada.
[/html]

Here’s some Ruby:

And the shortcode:

$[rb toolbar="always"]
def create_set_and_get(initial_value=0) # Note the default value of 0
  closure_value = initial_value
  return Proc.new {|x| closure_value = x}, Proc.new { closure_value }
end

setter, getter = create_set_and_get  # ie. returns two values
setter.call(21)
getter.call # => 21

#You can also use a parameter variable as a binding for the closure.
#So the above can be rewritten as...

def create_set_and_get(closure_value=0)
  return proc {|x| closure_value = x } , proc { closure_value }
end

proc {|arg| print arg}
Proc.new {|arg| print arg}
lambda {|arg| print arg}

# introduced in Ruby 1.9
->(arg) {print arg}

# In an object instance variable (denoted with '@'), remember a block.
def remember(&a_block)
  @block = a_block
end

# Invoke the above method, giving it a block which takes a name.
remember {|name| puts "Hello, #{name}!"}

# When the time is right (for the object) -- call the closure!
@block.call("Jon")
# => "Hello, Jon!"

[/rb]

Failing To Load Crayons On Pages

Some themes use a page template containing a custom loop. The issue is:

Since your theme uses a page to load a totally different query from the page it visits there’s no way for Crayon to know what you’re going to request until it reads your has_posts() request. By that time, the header is already written so there’s no chance to enqueue themes and fonts that you’ve used in your Crayons. Fortunately I’ve added a feature so that they are embedded each time if needed. This is a bit more inefficient I think, but it works by adding the required css right before each Crayon. This issue won’t occur on any other page on the site because direct links to pages and posts containing Crayons will load just fine with enqueuing, which is why the other pages worked for you.

The solution is added in 1.7.17 and 1.7.19. 1.7.17 now uses the the_posts filter by default (again) rather than the wp action which checks just the main wp query. The setting that fixes the issue is this:

It basically turns off enqueuing and prints the css in front of Crayon’s whenever it encounters a page. Posts will continue to enqueue themes in the head as usual.

Generic Stack for Objective-C

Here’s a simple stack to store any ol’ object in Objective-C.

FMStack.h
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
//    Generic Stack v1.0
// By Aram Kocharyan. http://ak.net84.net/
//
#import <Foundation/Foundation.h>
static const int kFMStackDefaultCapacity = 10;
@interface FMStack : NSObject {
    NSMutableArray *stack;
}
+ (id)stack;
+ (id)stackWithCapacity:(int)capacity;
- (id)initWithCapacity:(int)capacity;
- (void)push:(id)object;
- (id)pop;
- (void)clear;
- (int)count;
@end
FMStack.m
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//
//    Generic Stack v1.0
// By Aram Kocharyan. http://ak.net84.net/
//
#import "FMStack.h"
@implementation FMStack
+ (id)stack {
    return [[[self alloc] init] autorelease];
}
+ (id)stackWithCapacity:(int)capacity {
    return [[[self alloc] initWithCapacity:capacity] autorelease];
}
- (id)init {
return [self initWithCapacity:kFMStackDefaultCapacity];
}
- (id)initWithCapacity:(int)capacity {
    self = [super init];
if (self) {
        stack = [[NSMutableArray alloc] initWithCapacity:capacity];
    }
    return self;
}
- (void)push:(id)object {
    [stack addObject:object];
}
- (id)pop {
    id object = [stack lastObject];
    NSAssert(object != nil, @"Nothing to pop from stack");
    [stack removeObject:object];
    return object;
}
- (void)clear {
    [stack removeAllObjects];
}
- (int)count {
    return [stack count];
}
@end

Adding CSS Rules With !important Using jQuery

If you have a CSS with an !important rule and you want to specify an inline rule to override this, you can set the style attribute like this: .attr('style', 'width:200px !important;') but I’ve found a better way and added a new jQuery function for it.

jQuery.style(name, value, priority);

You can use it to get values with .style(‘name’) just like .css(‘name’), get the CSSStyleDeclaration with .style(), and also set values – with the ability to specify the priority as ‘important’. See https://developer.mozilla.org/en/DOM/CSSStyleDeclaration.

Here’s a demo:

JavaScript
1
2
3
4
5
6
7
var div = $('someDiv');
console.log(div.style('color'));
div.style('color', 'red');
console.log(div.style('color'));
div.style('color', 'blue', 'important');
console.log(div.style('color'));
console.log(div.style().getPropertyPriority('color'));

Here’s the output:

null
red
blue
important

Here’s my function:

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// For those who need them (< IE 9), add support for CSS functions
var isStyleFuncSupported = CSSStyleDeclaration.prototype.getPropertyValue != null;
if (!isStyleFuncSupported) {
    CSSStyleDeclaration.prototype.getPropertyValue = function(a) {
return this.getAttribute(a);
};
CSSStyleDeclaration.prototype.setProperty = function(styleName, value, priority) {
this.setAttribute(styleName,value);
var priority = typeof priority != 'undefined' ? priority : '';
if (priority != '') {
   // Add priority manually
            var rule = new RegExp(RegExp.escape(styleName) + '\\s*:\\s*' + RegExp.escape(value) + '(\\s*;)?', 'gmi');
            this.cssText = this.cssText.replace(rule, styleName + ': ' + value + ' !' + priority + ';');
}
}
CSSStyleDeclaration.prototype.removeProperty = function(a) {
return this.removeAttribute(a);
}
CSSStyleDeclaration.prototype.getPropertyPriority = function(styleName) {
    var rule = new RegExp(RegExp.escape(styleName) + '\\s*:\\s*[^\\s]*\\s*!important(\\s*;)?', 'gmi');
return rule.test(this.cssText) ? 'important' : '';
}
}
// Escape regex chars with \
RegExp.escape = function(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
}
// The style function
jQuery.fn.style = function(styleName, value, priority) {
    // DOM node
    var node = this.get(0);
    // Ensure we have a DOM node
    if (typeof node == 'undefined') {
        return;
    }
    // CSSStyleDeclaration
    var style = this.get(0).style;
    // Getter/Setter
    if (typeof styleName != 'undefined') {
        if (typeof value != 'undefined') {
            // Set style property
            var priority = typeof priority != 'undefined' ? priority : '';
            style.setProperty(styleName, value, priority);
        } else {
            // Get style property
            return style.getPropertyValue(styleName);
        }
    } else {
        // Get CSSStyleDeclaration
        return style;
    }
}

See https://developer.mozilla.org/en/DOM/CSSStyleDeclaration for examples of how to read and set the CSS values. My issue was that I had already set !important for the width in my CSS to avoid conflicts with other theme CSS, but any changes I made to the width in jQuery would be unaffected since they would be added to the style attribute.

CSS to JSON Converter for JavaScript

I’ve put together a script that converts CSS to JSON and back to CSS. I’ll be using it to build a Theme Editor in Crayon.

JavaScript
1
2
3
4
5
6
7
8
// To JSON, ignoring order of comments etc
var json = CSSJSON.toJSON(cssString);
// To JSON, keeping order of comments etc
var json = CSSJSON.toJSON(cssString, true);
    
// To CSS
var css = CSSJSON.toCSS(jsonObject);

The sample.html file that demonstrates the script, along with the script itself, can be found on GitHub:

https://github.com/aramkocharyan/CSSJSON