Written by pekka on 8/16/2014

Tanka.Markdown supports markdown text paragraphs where the paragraphs are separated by a blank line.

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis 
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu 
fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in 
culpa qui officia deserunt mollit anim id est laborum.

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis 
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu 
fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in 
culpa qui officia deserunt mollit anim id est laborum.

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Links

[heikura.me](http://www.heikura.me) or [heikura.me][me]

Link definitions at the bottom of the page
[me]: http://www.heikura.me

heikura.me or heikura.me

Images

![Tanka blogposts](https://dl.dropboxusercontent.com/u/5784123/blog/tanka-blog-post-list.PNG)

Tanka blogposts

Currently Tanka does not support giving size options for the images.

Emphasis

emphasis of *text* or strong emphasis of **text**

emphasis of text or strong emphasis of text

Inline code blocks

inline code block `var test = 123;` should be supported

inline code block var test = 123; should be supported.

Written by pekka on 2/25/2014

Tanka.Markdown supports codeblocks and lists.

Codeblocks

Codeblocks are pre-formatted blocks of text.

Codeblocks must be surrounded by three ` characters in the start 
and end lines. Content of the block must go between those lines. 

Code block 
will render as it is written 
with new lines
exactly the same way as you type it.

Typically codeblock is used to render piece of source code. This blogging software supports syntax highlighting of codeblocks.

public class Codeblock
{
    public string Content
    {
        get;
        set;
    }
}

Lists

Lists are paragraphs of text which are rendered as either ol or ul html tags. Multiline items are parsed and rendered as paragraphs. Item cannot yet contain multiple paragraphs of content.

Ordered

1. item
2. item
   items can continue for multiple lines and contain links [Heikura.Me](http://www.heikura.me)
3. item
  1. item

  2. item, items can continue for multiple lines and contain links Heikura.Me

  3. item

Unordered

* item
* item
* item
  • item

  • item

  • item

Written by pekka on 2/24/2014

Markdown is very popular markdown format for writing readable documents which can be parsed to render them as html. Most technology oriented writing platforms support it. As there's not strict specification anywhere there are multiple flavors of the syntax out there. Most popular flavor seems to be the GitHub flavor.

Tanka.Markdown was born out of frustration with trying to add some of my own syntax sugar to the mix. As most current C# implementations seems to be port of a parser made for some other language the codebase are a mess.

Features

Installation

Install-Package Tanka.Markdown -Pre

Code is hosted at GitHub

Supported syntax

Headings

# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6

Heading 1
=========

Heading 2
---------


Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6

Heading 1

Heading 2


This is first in series of posts about Tanka.Markdown and its capabilities.

Written by pekka on 1/20/2014

ScriptCs is a scripting framework for C#. It uses Roslyn to dynamically compile and run scripts written in C#. In common terms it's node.js for .NET. For me it seems to be the perfect choice for automating some build steps as you can write the script in familiar language C# and use the power of full .NET framework to get things done.

Script structure

So here are the steps my build needs to execute in order:

  1. Build the solution and output the results to build/

  2. Execute Xunit tests

First you need to install ScriptCs which takes couple of minutes. You can find the instructions from ScriptCs web site. Chocolatey is fast and updating is easy so I recommend you use it.

Build.csx

Here's the draft of the script. Notice that I'm using bit more script style formatting. It just feels more "scripty".

// configuration
var config = new {
};

// clean the build directory
Clean();

// if build succeeds run tests
if (Build()) {
    Test();
} else {
    Console.WriteLine("Build failed");
}

public void Clean() {

}

public bool Build() {
    return false;
}

public bool Test() {
    return false;
}

Notice the lack of class around the methods. ScriptCs uses Roslyn undercovers and it will wrap the script into a class.

Configuration

Build needs some folder paths and other variables to execute properly so let's add a class to hold this information. I don't want to specify the class so I use an anonymous class.

This should go into the beginning of your build script.

var config = new {
    buildOut = @"build",
    solutionFile = @"src\Solution.sln"
};

That should be enough for Clean and Build steps so lets see how to implement them. I'm building a Visual studio solution in this sample and as I have VS 2013 installed msbuild.exe should be on my environment PATH already.

Build tasks

So we have a basic script but it's not doing anything yet. Lets implement those methods to get the build going.

Clean

Clean will check if the build output folder exists and recursively delete it if it does.

public void Clean() {
    Console.WriteLine("Clean directory {0}", config.buildOut);

    // lets get the full path to the folder
    var fullPath = Path.GetFullPath(config.buildOut);

    // check if directory exists and delete if it does
    if (Directory.Exists(fullPath))
    	Directory.Delete(fullPath, recursive: true);
}

Build

Build the solution and output the output to buildOut -folder.

public bool Build() {
    var fullSolutionPath = Path.GetFullPath(config.solutionFile);
    var fullOut = Path.GetFullPath(config.buildOut);
    
    var info = new ProcessStartInfo("msbuild.exe");
    info.Arguments = string.Format(
        "{0} /p:OutputPath={1} /t:rebuild", 
        fullSolutionPath, 
        fullOut);
    
    var process = Process.Start(info);
    process.WaitForExit();
    
    // zero should mean all ok
    return process.ExitCode == 0 ? true : false;
}

Test

Run tests from test assemblies in the build output -folder. I'm using my own ScriptCs.Xunit2 script pack to give me an easy access to Xunit test runner.

You can install it with the following command.

scriptcs -install ScriptCs.Xunit2 -pre

Here's the actual test step

public bool Test() {
    var runner = Require<XunitRunner>();
    
    // define pattern for test assembly matching
    var pattern = "*Tests.dll";
    
    // directory to look for the test assemblies
    var testsPath = Path.GetFullPath(config.buildOut);
    
    // find test assemblies
    var files = Directory.GetFiles(testsPath, pattern);
    
    // execute tests in found assemblies
    bool testsPassed = true;
    foreach (var assemblyPath in files) {
        Console.WriteLine("Executing tests from {0}", assemblyPath);
        var result = runner.Execute(assemblyPath);
        
        Console.WriteLine("Executed  {0} tests - {1} failed - in {2} seconds", 
        	result.TestsCount,
        	result.TestsFailed,
        	result.TotalTimeInSeconds);
        	
        if (result.TestsFailed > 0)
            return false;
    }
    
    return testsPassed;
}

Summary

When you combine steps above you should have a basic build script. Which you can execute with following command.

scriptcs build.csx

In the part 2 of this blog series I'm going to add an packaging step for creating NuGet packages.

Written by pekka on 1/17/2014

Read NancyFx request body stream as string

Extension method

public static class RequestBodyExtensions
{
    public static string ReadAsString(this RequestStream requestStream)
    {
        using (var reader = new StreamReader(requestStream))
        {
            return reader.ReadToEnd();
        }
    }
}

Example usage

Post["/body-as-string"] = parameters =>
{
    string content = Request.Body.ReadAsString();
}

Written by pekka on 1/12/2014

GIT

All the pros will kill me for saying this, but merging using normal text editors is painful except if you're one of those Vim -gurus. So to make those merges bit easier I'm going to show you how to configure P4Merge to be used as Git mergetool and difftool.

First download P4Merge from Perforce web site. You only need to install the Visual Merge tool.

Configure

Then open your .gitconfig file and add/replace with following:

[diff]
    tool = p4merge
[merge]
    tool = p4merge
[mergetool "p4merge"]
    trustExitCode = true
    keepBackup = false
[difftool]
    prompt = false

Latest Git version has a native support for p4merge so you don't need to provide anything else.

In Windows .gitconfig file is located at the root of your user profile folder. You do not need to provide the full path to p4merge.exe as it should be on your PATH after the installation.

Next time you get a merge conflict remember to execute git mergetool and you're good to go. You can also get a diff of files by running git difftool

Merging

You're performing a three-way merge where the left side shows theirs, middle is the common base and right side your copy of the file. Bottom part shows the result of the merge. On the right side of bottom pane there are icons which you can use to control what ends up in the resulting merged file. You can also use the top "tree" view to select one of the three copies as the resulting merged file.

Written by pekka on 2/27/2013

Ace editor is a fast code editor for web developed as main editor for Cloud 9 IDE. As it's open source you can easily add it to your own projects.

Following is an AngularJS directive providing ace -attribute for you to use to embed Ace into your own html. It will automatically resize the editor height to fit your content as your write. Besides it you need to reference the required Ace -files in your html. Depending on the mode and theme you want you need to reference different files.

myDirectives.directive('ace', ['$timeout', function ($timeout) {

    var resizeEditor = function(editor, elem) {
        var lineHeight = editor.renderer.lineHeight;
        var rows = editor.getSession().getLength();

        $(elem).height(rows * lineHeight);
        editor.resize();
    };

    return {
        restrict: 'A',
        require: '?ngModel',
        scope: true,
        link: function(scope, elem, attrs, ngModel) {
            var node = elem[0];

            var editor = ace.edit(node);

            editor.setTheme('ace/theme/xcode');

            var MarkdownMode = require('ace/mode/markdown').Mode;
            editor.getSession().setMode(new MarkdownMode());

            // data binding to ngModel
            ngModel.$render = function() {
                editor.setValue(ngModel.$viewValue);
                resizeEditor(editor, elem);
            };

            editor.on('change', function () {
                $timeout(function() {
                    scope.$apply(function () {
                        var value = editor.getValue();
                        ngModel.$setViewValue(value);
                    });
                });

                resizeEditor(editor, elem);
            });
        }
    };
}]);

You can find working demo as fiddle from: Ace editor directive for AngularJS

Written by pekka on 1/15/2013

JavaScript optimization is one of the corner stones of publishing modern web sites. There are many techniques which improve the loading of your rich web site with lots of JavaScript.

Grunt and grunt-usemin

Grunt-usemin task allows concatenation of files using directives in your html files. These directives group file references into new files. Combined with grunt minfication task you can both combine and minify resulting files. Because this process changes the html files we need to target the html -files inside your Release -directory instead of changing the originals in App -directory.

Installation

Grunt-usemin is available as npm -package and can be installed using npm install grunt-usemin command. This will install grunt-usemin into node_modules -directory under the current directory.

Usage

Usage of grunt-usemin is easy. First you define your output scripts inside your html. In following sample I've added angularjs and jquery script references into the index - page of the KnowledgeBase - application. By surrounding them with special comments understood by grunt-usemin I'm telling it to output libraries.js- script and replace the individual references with it.

_HINT: You can use Bower to install scripts into your project_

index.html - before grunt-usemin

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>KnowledgeBase</title>
        <link href="/styles/application.css" rel="stylesheet" type="text/css" /> 
    </head>
    <body>
        <h1>KnowledgeBase application</h1>
        
        <!-- build:js js/libraries.js -->
        <script src="components/jquery/jquery.js"> </script>
        <script src="components/angular/angular.js"> </script>
        <!-- endbuild -->
    </body>
</html>

Before you can run the optimizations you have to modify your Grunt.js to include grunt-usemin configuration and update your defaut - task with grunt-usemin tasks.

Grunt.js

module.exports = function(grunt) {
    // Project configuration.
    grunt.initConfig({
        clean: {
            release: ['Release']
        },
        copy: {            
            release: {
                files: {
                    'Release/': ['App/**']
                }
            }
        },
        compass: {
            release: {
                src: 'App/sass',
                dest: 'Release/styles',
                linecomments: false,
                forcecompile: true,
                debugsass: false,
                relativeassets: true
            }
        },
        useminPrepare: {
            html: ['release/index.html']
        },
        usemin: {
            html: ['release/index.html']
        }
    });

    // Default task.
    grunt.registerTask('default', 'clean copy compass useminPrepare concat min usemin');

    grunt.loadNpmTasks('grunt-contrib');
    grunt.loadNpmTasks('grunt-compass');
    grunt.loadNpmTasks('grunt-usemin');
};

As you can see we're targeting the Release - directory copy of the index.html - file because grunt-usemin tasks will modify the targeted file.

index.html - after grunt-usemin

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>KnowledgeBase</title>
        <link href="/styles/application.css" rel="stylesheet" type="text/css" /> 
    </head>
    <body>
        <h1>KnowledgeBase application</h1>
        
        <script src="js/libraries.js"></script>
    </body>
</html>

If you check the contents of the libraries.js you will notice that it contains both scripts in minified form.

You can find updated sample from https://github.com/pekkah/KnowledgeBase

Written by on 1/2/2013

In the previous part of this series I showed how to clean and copy your application to release directory. In this article I'm going add Compass compilation step into the build configuration.

Compass

Compass is a open source CSS authoring framework which uses sass to make writing CSS fun and productive. To use Compass with Grunt you must first install Compass.

Sass

Sass is a extension to CSS3 extending its syntax to make it more like a proper programming language.

Variables

With variables you can define something once and use it in multiple places. Variables also support basic math.

$primary-color: #E064B7;
$background-color: #FAFAFA;

$margin-large : 36px;
$margin-normal: 16px;
$margin-small: 8px;

$font-size-huge: 48px;
$line-height: 1.1;
$font-weight-normal: 400;

Mixins

Mixins allow you to define whole chunk of CSS and use it inside multiple rules. Mixins can also take parameters.

// mixin
@mixin font($size) {
	color: $primary-color;
	font-size: $size;
	font-weight: $font-weight-normal;
	line-height: $line-height;
}

// usage
h1 {
	@include font($font-size-huge);
}

Grunt and Compass

Grunt-compass plugin allows you to run Compass compilation task.

Compass configuration:

compass: {
    release: {
        src: 'App/sass',
        dest: 'Release/styles',
        linecomments: false,
        forcecompile: true,
        debugsass: false,
        relativeassets: true
    }
}

Example

Following sample extends the sample shown in previous part with Compass compilation task to compile scss -files from App/sass -directory to Release/styles -directory.

/*global module:false*/
module.exports = function(grunt) {
    // Project configuration.
    grunt.initConfig({
        clean: {
            release: ['Release']
        },
        copy: {            
            release: {
                files: {
                    'Release/': ['App/**']
                }
            }
        },
        compass: {
            release: {
                src: 'App/sass',
                dest: 'Release/styles',
                linecomments: false,
                forcecompile: true,
                debugsass: false,
                relativeassets: true
            }
        }
    });

    // Default task.
    grunt.registerTask('default', 'clean copy compass');

    grunt.loadNpmTasks('grunt-contrib');
    grunt.loadNpmTasks('grunt-compass');
};

Deployment to AppHarbor

I mainly use AppHarbor to host my applications due to easy deployment and huge list of available addons. AppHarbor monitors your Git -repository for changes and automatically deploys the latest version upon detecting a change. As I want to deploy the optimized release version of the site I have to do some modification to my project to allow this. Basically I just create another solution named AppHarbor.sln and add a existing web site pointing to my Release -directory. Disabling precompilation on the AppHarbor settings is also required when deploying Web Site -projects.

You can find a sample application from https://github.com/pekkah/KnowledgeBase, live at http://knowledge-base.apphb.com/.

In the next part I'm going to show why we need a separate Release -directory.

Written by pekka on 12/28/2012

Grunt is a task based command line tool for building web sites. It has a very large community writing tasks as plugins for it.

Installing Grunt on Windows

Grunt is available as npm module so the easiest way is to use npm install -g grunt from your command line. Easiest way to get npm installed is to use chocolatey NodeJS -package.

Gruntfile

Grunt looks for gruntfile from the directory it's executed from. You can initialize a gruntfile using the builtin init -task. Most of the time it's best to start with clean configuration using grunt init:gruntfile.

Our sample configuration will have following tasks:

1. Clean the target directory 2. Copy files from App to Release Both of these tasks are part of grunt-contrib project.

Clean

Clean can be used to remove all files and folders from a list of directories. Following configuration will clean a Release -directory of all files and folders.

clean: {
    release: ['Release']
}

Copy

Copy can be used to copy files and folders from source directory to target directory. Following configuration will copy files and folders recursively from App -directory to Release -directory.

copy: {            
    release: {
        files: {
            'Release/': ['App/**']
        } 
    }
}

Example

Following combines the two tasks to first clean the Release -directory and then copy files and directories from App -directory to Release -directory.

module.exports = function(grunt) {
    grunt.initConfig({
        clean: {
            release: ['Release']
        },
        copy: {            
            release: {
                files: {
                    'Release/': ['App/**']
                }
            }
        }
    });

    // Default task.
    grunt.registerTask('default', 'clean copy');
    grunt.loadNpmTasks('grunt-contrib');
};

You can execute Grunt on Windows by running grunt.cmd in the directory containing your grunt.js -configuration file.

This is only the base for future work. In the next part I'm going to add sass compilation using Compass.

Tanka - 0.1.2