├── test ├── blank.haml ├── blank.html ├── else.html ├── raw.html ├── doctype.haml ├── else.haml ├── meta.haml ├── meta.html ├── self_close.js ├── nanline.html ├── nanline.haml ├── nested_context.js ├── embedded_code.js ├── raw.haml ├── div_nesting.html ├── self_close.html ├── div_nesting.haml ├── nested_context.haml ├── comments.html ├── embedded_code.haml ├── interpolation.html ├── self_close.haml ├── nested_context.html ├── non-string-attribs.html ├── other │ ├── escape_by_default.haml │ ├── custom_escape.html │ ├── escape_by_default.html │ └── custom_escape.haml ├── optional_attribs.html ├── if.html ├── alt_attribs.haml ├── alt_attribs.html ├── embedded_code.html ├── no_self_close_div.haml ├── non-string-attribs.haml ├── foreach.js ├── css.haml ├── css.html ├── raw_complex.html ├── foreach.html ├── no_self_close_div.html ├── escaping.js ├── script_css.haml ├── standard.js ├── optional_attribs.haml ├── escaping.haml ├── interpolation.haml ├── foreach.haml ├── script_css.html ├── standard.haml ├── doctype.html ├── comments.haml ├── escaping.html ├── standard.html ├── whitespace.html ├── test-commonjs.js ├── whitespace.haml ├── if.js ├── if.haml ├── raw_complex.haml └── test.js ├── test.haml ├── package.json ├── lib ├── cli.js └── haml.js ├── LICENSE ├── CHANGELOG.markdown └── README.markdown /test/blank.haml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/blank.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/else.html: -------------------------------------------------------------------------------- 1 |
1+1 != 3
-------------------------------------------------------------------------------- /test.haml: -------------------------------------------------------------------------------- 1 | .class1 2 | .class2#testid -------------------------------------------------------------------------------- /test/raw.html: -------------------------------------------------------------------------------- 1 |Well then <>
Well then <>
This is some text & it is cool.Frank
-------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "haml", 3 | "description": "Haml ported to server-side Javascript. This is a traditional server-side templating language.", 4 | "keywords": ["haml", "template"], 5 | "homepage": "https://github.com/creationix/haml-js", 6 | "main" : "./lib/haml", 7 | "bin": { 8 | "haml-js": "./lib/cli.js" 9 | }, 10 | "author": "Aaron Blohowiak
I want my words to have spaces on the outside So they don't run together. But i also want some to have spaces on the inside and still others to have spaces on either side even if it has code on the line or just code with space on the outside
links that touch their neighbor.
And links that do not
Or a important thing with tons of space
Download the file here now.
"+\n' + JSON.stringify(this.contents.join("\n"))+'+\n""';
405 | }
406 | },
407 |
408 | // declarations
409 | {
410 | name: "doctype",
411 | regexp: /^()!!!(?:\s*(.*))\s*$/,
412 | process: function () {
413 | var line = '';
414 | switch ((this.matches[2] || '').toLowerCase()) {
415 | case '':
416 | // XHTML 1.0 Transitional
417 | line = '';
418 | break;
419 | case 'strict':
420 | case '1.0':
421 | // XHTML 1.0 Strict
422 | line = '';
423 | break;
424 | case 'frameset':
425 | // XHTML 1.0 Frameset
426 | line = '';
427 | break;
428 | case '5':
429 | // XHTML 5
430 | line = '';
431 | break;
432 | case '1.1':
433 | // XHTML 1.1
434 | line = '';
435 | break;
436 | case 'basic':
437 | // XHTML Basic 1.1
438 | line = '';
439 | break;
440 | case 'mobile':
441 | // XHTML Mobile 1.2
442 | line = '';
443 | break;
444 | case 'xml':
445 | // XML
446 | line = "";
447 | break;
448 | case 'xml iso-8859-1':
449 | // XML iso-8859-1
450 | line = "";
451 | break;
452 | }
453 | return JSON.stringify(line + "\n");
454 | }
455 | },
456 |
457 | // Embedded markdown. Needs to be added to exports externally.
458 | {
459 | name: "markdown",
460 | regexp: /^(\s*):markdown\s*$/i,
461 | process: function () {
462 | return parse_interpol(exports.Markdown.encode(this.contents.join("\n")));
463 | }
464 | },
465 |
466 | // script blocks
467 | {
468 | name: "script",
469 | regexp: /^(\s*):(?:java)?script\s*$/,
470 | process: function () {
471 | return parse_interpol('\n\n");
475 | }
476 | },
477 |
478 | // css blocks
479 | {
480 | name: "css",
481 | regexp: /^(\s*):css\s*$/,
482 | process: function () {
483 | return JSON.stringify('");
486 | }
487 | }
488 |
489 | ];
490 |
491 | function compile(lines) {
492 | var block = false,
493 | output = [],
494 | ifConditions = [];
495 |
496 | // If lines is a string, turn it into an array
497 | if (typeof lines === 'string') {
498 | lines = lines.trim().replace(/\n\r|\r/g, '\n').split('\n');
499 | }
500 |
501 | lines.forEach(function(line) {
502 | var match, found = false;
503 |
504 | // Collect all text as raw until outdent
505 | if (block) {
506 | match = block.check_indent.exec(line);
507 | if (match) {
508 | block.contents.push(match[1] || "");
509 | return;
510 | } else {
511 | output.push(block.process());
512 | block = false;
513 | }
514 | }
515 |
516 | matchers.forEach(function (matcher) {
517 | if (!found) {
518 | match = matcher.regexp.exec(line);
519 | if (match) {
520 | block = {
521 | contents: [],
522 | indent_level: (match[1]),
523 | matches: match,
524 | check_indent: new RegExp("^(?:\\s*|" + match[1] + " (.*))$"),
525 | process: matcher.process,
526 | getIfConditions: function() {
527 | return ifConditions;
528 | },
529 | pushIfCondition: function(condition) {
530 | ifConditions.push(condition);
531 | },
532 | popIfCondition: function() {
533 | return ifConditions.pop();
534 | },
535 | render_contents: function () {
536 | return compile(this.contents);
537 | }
538 | };
539 | found = true;
540 | }
541 | }
542 | });
543 |
544 | // Match plain text
545 | if (!found) {
546 | output.push(function () {
547 | // Escaped plain text
548 | if (line[0] === '\\') {
549 | return parse_interpol(line.substr(1, line.length));
550 | }
551 |
552 |
553 | function escapedLine(){
554 | try {
555 | return escaperName+'('+JSON.stringify(JSON.parse(line)) +')';
556 | } catch (e2) {
557 | return escaperName+'(' + line + ')';
558 | }
559 | }
560 |
561 | function unescapedLine(){
562 | try {
563 | return parse_interpol(JSON.parse(line));
564 | } catch (e) {
565 | return line;
566 | }
567 | }
568 |
569 | // always escaped
570 | if((line.substr(0, 2) === "&=")) {
571 | line = line.substr(2, line.length).trim();
572 | return escapedLine();
573 | }
574 |
575 | //never escaped
576 | if((line.substr(0, 2) === "!=")) {
577 | line = line.substr(2, line.length).trim();
578 | return unescapedLine();
579 | }
580 |
581 | // sometimes escaped
582 | if ( (line[0] === '=')) {
583 | line = line.substr(1, line.length).trim();
584 | if(escapeHtmlByDefault){
585 | return escapedLine();
586 | }else{
587 | return unescapedLine();
588 | }
589 | }
590 |
591 | // Plain text
592 | return parse_interpol(line);
593 | }());
594 | }
595 |
596 | });
597 | if (block) {
598 | output.push(block.process());
599 | }
600 |
601 | var txt = output.filter(function (part) { return part && part.length > 0}).join(" +\n");
602 | if(txt.length == 0){
603 | txt = '""';
604 | }
605 | return txt;
606 | };
607 |
608 | function optimize(js) {
609 | var new_js = [], buffer = [], part, end;
610 |
611 | function flush() {
612 | if (buffer.length > 0) {
613 | new_js.push(JSON.stringify(buffer.join("")) + end);
614 | buffer = [];
615 | }
616 | }
617 | js.replace(/\n\r|\r/g, '\n').split('\n').forEach(function (line) {
618 | part = line.match(/^(\".*\")(\s*\+\s*)?$/);
619 | if (!part) {
620 | flush();
621 | new_js.push(line);
622 | return;
623 | }
624 | end = part[2] || "";
625 | part = part[1];
626 | try {
627 | buffer.push(JSON.parse(part));
628 | } catch (e) {
629 | flush();
630 | new_js.push(line);
631 | }
632 | });
633 | flush();
634 | return new_js.join("\n");
635 | };
636 |
637 | function render(text, options) {
638 | options = options || {};
639 | text = text || "";
640 | var js = compile(text, options);
641 | if (options.optimize) {
642 | js = Haml.optimize(js);
643 | }
644 | return execute(js, options.context || Haml, options.locals);
645 | };
646 |
647 | function execute(js, self, locals) {
648 | return (function () {
649 | with(locals || {}) {
650 | try {
651 | var _$output;
652 | eval("_$output =" + js );
653 | return _$output; //set in eval
654 | } catch (e) {
655 | return "\n" + html_escape(e + "\n" + e.stack) + "\n"; 656 | } 657 | 658 | } 659 | }).call(self); 660 | }; 661 | 662 | Haml = function Haml(haml, config) { 663 | if(typeof(config) != "object"){ 664 | forceXML = config; 665 | config = {}; 666 | } 667 | 668 | var escaper; 669 | if(config.customEscape){ 670 | escaper = ""; 671 | escaperName = config.customEscape; 672 | }else{ 673 | escaper = html_escape.toString() + "\n"; 674 | escaperName = "html_escape"; 675 | } 676 | 677 | escapeHtmlByDefault = (config.escapeHtmlByDefault || config.escapeHTML || config.escape_html); 678 | 679 | var js = optimize(compile(haml)); 680 | 681 | var str = "with(locals || {}) {\n" + 682 | " try {\n" + 683 | " var _$output=" + js + ";\n return _$output;" + 684 | " } catch (e) {\n" + 685 | " return \"\\n
\" + "+escaperName+"(e + \"\\n\" + e.stack) + \"\\n\";\n" + 686 | " }\n" + 687 | "}" 688 | 689 | try{ 690 | var f = new Function("locals", escaper + str ); 691 | return f; 692 | }catch(e){ 693 | if ( typeof(console) !== 'undefined' ) { console.error(str); } 694 | throw e; 695 | } 696 | } 697 | 698 | Haml.compile = compile; 699 | Haml.optimize = optimize; 700 | Haml.render = render; 701 | Haml.execute = execute; 702 | Haml.html_escape = html_escape; 703 | }()); 704 | 705 | // Hook into module system 706 | if (typeof module !== 'undefined') { 707 | module.exports = Haml; 708 | } 709 | --------------------------------------------------------------------------------