Skip to content

Commit

Permalink
Merge pull request #2 from drupal-pattern-lab/develop
Browse files Browse the repository at this point in the history
Merging down latest updates from Develop into Master
  • Loading branch information
sghoweri authored Aug 8, 2017
2 parents 49f6491 + 52f70cb commit 862b9de
Show file tree
Hide file tree
Showing 11 changed files with 514 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.DS_Store
vendor
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2017
Copyright (c) 2017

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
49 changes: 47 additions & 2 deletions README.md
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,2 +1,47 @@
# unified-twig-extensions
Share Pattern Lab's custom Twig extensions with Drupal 8
# Unified Twig Extensions

Share Pattern Lab's custom twigs functions, filters and tags with Drupal 8. Huzzah!


## Getting Started
Simply add to Drupal and enable the `
Unified Twig Extensions` module on the `admin/modules` page to get started.


## Note on Paths
Note: currently looks for compatible extensions in your current active D8 theme path + either the 'pattern-lab/source/_twig-components' or 'source/_twig-components' folders. @TODO: allow users to customized / override this!


## Included Examples
I'm including a couple example twig extensions to add to your existing Pattern Lab-enabled theme to get started:
1. `example/_twig-components/functions/link.function.php` --> example of having Drupal ignore a PL Twig extension given the link function already exists in Drupal.

2. `example/_twig-components/tags/grid.tag.php` and `example/_twig-components/tags/cell.tag.php` --> example of a custom Twig tag that abstracts away some of the markup involved in an ITCSS-based grid system.

To test this out, try adding these two custom Twig tags to your theme's existing _twig-components folder and try adding the following HTML (to both PL's twig templates and/or a Drupal template):

```twig
{% grid 'o-grid--large' %}
{% cell 'u-1/1 u-1/2@small u-2/3@medium' %}
Grid cell
{% endcell %}
{% cell 'u-1/1 u-1/2@small u-1/3@medium' %}
Grid cell
{% endcell %}
{% endgrid %}
```

Everything should be working as expected if you don't encounter any errors and the following HTML gets output (rendered of course):

```html
<div class="o-grid o-grid--large">
<div class="o-grid__item u-1/1 u-1/2@small u-2/3@medium">
Grid cell
</div>

<div class="o-grid__item u-1/1 u-1/2@small u-1/3@medium">
Grid cell
</div>
</div>
```
12 changes: 12 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "drupal-pattern-lab/unified-twig-extensions",
"description": "Share Pattern Lab's custom Twig extensions with Drupal 8.",
"type": "drupal-module",
"support": {
"source": "https://github.com/drupal-pattern-lab/unified-twig-extensions.git"
},
"authors": [{
"name": "Salem Ghoweri",
"role": "Contributor"
}]
}
16 changes: 16 additions & 0 deletions example/_twig-components/functions/link.function.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

if (!class_exists('Drupal')) {
$function = new Twig_SimpleFunction(
'link',
function ($title, $url, $attributes) {
if (isset($attributes) && isset($attributes['class'])) {
$classes = join(' ', $attributes['class']);
return '<a href="' . $url . '" class="' . $classes . '">' . $title . '</a>';
} else {
return '<a href="' . $url . '">' . $title . '</a>';
}
},
array('is_safe' => array('html'))
);
}
120 changes: 120 additions & 0 deletions example/_twig-components/tags/cell.tag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php

// these files are loaded three times and we can't re-set a class
if (!class_exists("Project_cell_Node", false)) {

class Project_cell_Node extends Twig_Node {

private $class = "";

public function setClass($class)
{
$this->class = $class;
}

public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$compiler->write("echo \"<div class='o-grid__item ");

$class = "";
if($this->class instanceof \Twig_Node_Expression_Constant) {
$class = preg_replace("/\b(lg|md|sm|xs)([0-9]+)\b/", 'col-$1-$2', $this->class->getAttribute("value"));
}
$compiler->raw($class);

$compiler->raw("'>\";")->raw(PHP_EOL);
parent::compile($compiler);
$compiler->write("echo \"</div>\";")->raw(PHP_EOL);
}

}

}

// these files are loaded three times and we can't re-set a class
if (!class_exists("Project_cell_TokenParser", false)) {

class Project_cell_TokenParser extends Twig_TokenParser {

public function parse(Twig_Token $token){
$inheritanceIndex = 1;

$stream = $this->parser->getStream();

$nodes = array();
$classes = array();
$returnNode = null;

if($stream->test(Twig_Token::STRING_TYPE)) {
$classes[$inheritanceIndex] = $this->parser->getExpressionParser()->parseStringExpression();
} else {
$classes[$inheritanceIndex] = "col-md-12";
}

$stream->expect(Twig_Token::BLOCK_END_TYPE);

$continue = true;

while($continue) {

$content = $this->parser->subparse(array($this, 'decideMyTagFork'));
$nodes[$inheritanceIndex][] = $content;
$tag = $stream->next()->getValue();

switch($tag) {
case "cell":
$inheritanceIndex++;
if($stream->test(Twig_Token::STRING_TYPE)) {
$classes[$inheritanceIndex] = $this->parser->getExpressionParser()->parseStringExpression();
} else {
$classes[$inheritanceIndex] = "col-md-12";
}
break;
case "endcell":
$currentNodes = $nodes[$inheritanceIndex];
$class = $classes[$inheritanceIndex];
unset($nodes[$inheritanceIndex]);
unset($classes[$inheritanceIndex]);
$inheritanceIndex--;
if($inheritanceIndex == 0) {
$returnNode = new Project_cell_Node($currentNodes);
$returnNode->setClass($class);
$continue = false;
} else {
$node = new Project_cell_Node($currentNodes);
$node->setClass($class);
$nodes[$inheritanceIndex][] = $node;
}
break;
default:
throw new Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "%s" to close the "%s" block started at line %d)', "grid", "endgrid", $this->startLine), -1);
}
$stream->expect(Twig_Token::BLOCK_END_TYPE);
}

return $returnNode;
}

public function getTag()
{
return "cell";
}

/**
* Callback called at each tag name when subparsing, must return
* true when the expected end tag is reached.
*
* @param \Twig_Token $token
* @return bool
*/
public function decideMyTagFork(Twig_Token $token)
{
return $token->test(array("cell", "endcell"));
}

}

}

?>
163 changes: 163 additions & 0 deletions example/_twig-components/tags/grid.tag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<?php

// these files are loaded three times and we can't re-set a class
if (!class_exists("Project_grid_Node", false)) {

class Project_grid_Node extends Twig_Node {

private $class = "";

public function setClass($class){
$this->class = $class;
}


public function compile(Twig_Compiler $compiler){
// $compiler->addDebugInfo($this);
// $compiler->write("echo \"<div class='o-grid'>\";")->raw(PHP_EOL);
// parent::compile($compiler);
// $compiler->write("echo \"</div>\";")->raw(PHP_EOL);


$compiler->addDebugInfo($this);
$compiler->write("echo \"<div class='o-grid ");

$class = " ";
if($this->class instanceof \Twig_Node_Expression_Constant) {
$class = preg_replace("/\b(lg|md|sm|xs)([0-9]+)\b/", 'col-$1-$2', $this->class->getAttribute("value"));
}
$compiler->raw($class);

$compiler->raw("'>\";")->raw(PHP_EOL);
parent::compile($compiler);
$compiler->write("echo \"</div>\";")->raw(PHP_EOL);

}

}

}

// these files are loaded three times and we can't re-set a class
if (!class_exists("Project_grid_TokenParser", false)) {

class Project_grid_TokenParser extends Twig_TokenParser {

public function parse(Twig_Token $token)
{


// $stream = $this->parser->getStream();
// $stream->expect(Twig_Token::BLOCK_END_TYPE);
// $inheritanceIndex = 1;
// $nodes = array();
// $classes = array();
// $returnNode = null;
$inheritanceIndex = 1;

$stream = $this->parser->getStream();

$nodes = array();
$classes = array();
$returnNode = null;



if($stream->test(Twig_Token::STRING_TYPE)) {
$classes[$inheritanceIndex] = $this->parser->getExpressionParser()->parseStringExpression();
} else {
$classes[$inheritanceIndex] = "col-md-12";
}

$stream->expect(Twig_Token::BLOCK_END_TYPE);
$continue = true;



while($continue) {

$content = $this->parser->subparse(array($this, 'decideMyTagFork'));
$nodes[$inheritanceIndex][] = $content;
$tag = $stream->next()->getValue();
// $stream->expect(Twig_Token::BLOCK_END_TYPE);
switch($tag) {
case "grid":
// $inheritanceIndex++;
//
// if($stream->test(Twig_Token::STRING_TYPE)) {
// $classes[$inheritanceIndex] = $this->parser->getExpressionParser()->parseStringExpression();
// } else {
// $classes[$inheritanceIndex] = "col-md-12";
// }
//
// break;
$inheritanceIndex++;
if($stream->test(Twig_Token::STRING_TYPE)) {
$classes[$inheritanceIndex] = $this->parser->getExpressionParser()->parseStringExpression();
} else {
$classes[$inheritanceIndex] = "col-md-12";
}
break;
case "endgrid":
// $currentNodes = $nodes[$inheritanceIndex];
// $class = $classes[$inheritanceIndex];
// unset($nodes[$inheritanceIndex]);
// unset($classes[$inheritanceIndex]);
// $inheritanceIndex--;
// if($inheritanceIndex == 0) {
// $returnNode = new Project_grid_Node($currentNodes);
// $returnNode->setClass($class);
// $continue = false;
// // break 2;
// } else {
// $nodes[$inheritanceIndex][] = new Project_grid_Node($currentNodes);
// $node->setClass($class);
// $nodes[$inheritanceIndex][] = $node;
// }
// break;
$currentNodes = $nodes[$inheritanceIndex];
$class = $classes[$inheritanceIndex];
unset($nodes[$inheritanceIndex]);
unset($classes[$inheritanceIndex]);
$inheritanceIndex--;
if($inheritanceIndex == 0) {
$returnNode = new Project_grid_Node($currentNodes);
$returnNode->setClass($class);
$continue = false;
} else {
$node = new Project_grid_Node($currentNodes);
$node->setClass($class);
$nodes[$inheritanceIndex][] = $node;
}
break;
default:
throw new Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "%s" to close the "%s" block started at line %d)', "endgrid", "grid", $this->startLine), -1);
}
$stream->expect(Twig_Token::BLOCK_END_TYPE);
}

return $returnNode;
}

public function getTag()
{
return "grid";
}

/**
* Callback called at each tag name when subparsing, must return
* true when the expected end tag is reached.
*
* @param \Twig_Token $token
* @return bool
*/
public function decideMyTagFork(Twig_Token $token)
{
return $token->test(array("grid", "endgrid"));
}

}

}

?>
Loading

0 comments on commit 862b9de

Please sign in to comment.