かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Stylus プロパティ名に変数を使って一緒に"(ダブルコーテーション)や半角スペースを出力したい

Stylus

例えばこんな感じのCSSを出力したくて

[class^="icon-"],
[class*=" icon-"] {
  font-family: 'webfont-icon' !important;
  ... 
}

icon- の部分をを変数にしたい様な時。
変数と一緒に"(ダブルコーテーション)や(半角スペース)を出力させるのが結構落とし穴でした。

Stylusでプロパティ名に変数を使う場合は .color-{$type} の様に{ で変数名を囲ってあげればOKです。(※ Stylusで変数を定義する際に先頭に$は不要ですが、個人的に見やすいので変数名は$始まりにしています。)
[参照] Stylus プロパティの値に変数名を変数で指定したい。 - かもメモ

NG集

変数をそのまま書く
$prefix   = 'icon-'
[class^="{$prefix}"], [class*=" {$prefix}"]
  font-family: 'webfont-icon' !important;

👇

[class^="{$prefix}"],
[class*=" {$prefix}"] {
  font-family: 'webfont-icon' !important;
}

なぜか変数名がそのまま表示される...

一部を文字列結合にしてみる
[class^=" + {$prefix} + "], [class*=" + {$prefix} + "]
  font-family: 'webfont-icon' !important;

👇

[class^=" + {$prefix} + "],
[class*=" + {$prefix} + "] {
  font-family: 'webfont-icon' !important;
}

`"' で囲まれた範囲が、そのまま表示されるっぽい?

プロパティ名全体を文字列結合にしてみる
'[class^="' + {$prefix} + '"]', '[class*=" ' + {$prefix} + '"]'
  font-family: 'webfont-icon' !important;

👇

Plumber found unhandled error:
 ParseError in plugin 'gulp-stylus'

コンパイルエラー

全体が文字列になるのが良くない?
['class^="' + {$prefix} + '"'], ['class*=" '+ {$prefix} + '"']
  font-family: 'webfont-icon' !important;

👇

['class^="'+ icon- + '"'],
['class*=" '+ icon- + '"'] {
  font-family: 'webfont-icon' !important;
}

違うそうじゃない。

{ の中に" を書いてみる
[class^={"$prefix"}], [class*={" $prefix"}]
  font-family: 'webfont-icon' !important;

👇

[class^=$prefix],
[class*= $prefix] {
  font-family: 'webfont-icon' !important;
}

半角スペースは表示されたので惜しい気がする?

{ の中に書いた"\エスケープしてみる
[class^={\"$prefix\"}], [class*={\" $prefix\"}]
  font-family: 'webfont-icon' !important;

👇

[class^="],
[class*="] {
  font-family: 'webfont-icon' !important;
}

違うそうじゃない。。。

{ の中に書いた"\(エスケープ)して文字列結合にしてみる
[class^={\" + $prefix + \"}], [class*={\"  + $prefix + \"}]
  font-family: 'webfont-icon' !important;

👇

[class^="icon-"],
[class*="icon-"] {
  font-family: 'webfont-icon' !important;
}

必要な半角スペースが消えてしまっただけで、非常に惜しい!!

{の中の半角スペースも\(エスケープ)して文字列結合にしてみる
[class^={\" + $prefix + \"}], [class*={\"\ + $prefix + \"}]
  font-family: 'webfont-icon' !important;

👇

[class^="icon-"],
[class*="] {
  font-family: 'webfont-icon' !important;
}

ちょっ、おま……(´・ω・`)

[class^={\" + $prefix + \"}], [class*={\"\s + $prefix + \"}]
  font-family: 'webfont-icon' !important;

※ コレでも同じ 👇

[class^="icon-"],
[class*="] {
  font-family: 'webfont-icon' !important;
}

 

うまくいく方法

1. 別の変数を作ってしまう

$prefix   = 'icon-'

$str1 = '"' + $prefix + '"'
$str2 = '" ' + $prefix + '"'
[class^={$str1}], [class^={$str2}]
  font-family: 'webfont-icon' !important

👇 出力されるCSS

[class^="icon-"],
[class^=" icon-"] {
  font-family: 'webfont-icon' !important;
}

あまりイケてませんが目的は果たせます。

2. { } の中で文字列結合する方法

{ の中での計算は許されているようなので、下記のように囲ってしまえばOKです。

$prefix   = 'icon-'
{'[class^="' + $prefix + '"]'}, {'[class*=" ' + $prefix + '"]'}
  font-family: 'webfont-icon' !important;
$prefix   = 'icon-'
[class^={'"' + $prefix + '"'}], [class*={'" ' + $prefix + '"'}]
  font-family: 'webfont-icon' !important;

👇 出力されるCSS

[class^="icon-"],
[class*=" icon-"] {
  font-family: 'webfont-icon' !important;
}

3. \(エスケープ)を使う方法

プロパティ名内に変数があるとき、\(エスケープ)があるとその直後の文字列はそのまま表示されるようです。

$prefix   = 'icon-'

[class^=\"{$prefix}\"], [class*=\"\ {$prefix}\"]
  font-family: 'webfont-icon' !important

👇 出力されるCSS

[class^="icon-"],
[class*=" icon-"] {
  font-family: 'webfont-icon' !important;
}

これはイイ感じです!
半角スペースの前にも\を付けるのがポイントです。エスケープされてないと半角スペースが消えます(´・ω・`)
 

Stylusでプロパティ名の文字列展開を行う時"など消えてほしくない文字の前には\を書くか、{}の中で計算させると覚えておけば良さそうです!


PugでPHPタグを出力したい

pugはHTMLテンプレートエンジンなのですが gulp などで拡張子をリネームしてしまえば PHPのテンプレートファイルにする事もできます。
ex:

var gulp    = require("gulp"),
    plumber = require("gulp-plumber"),
    rename  = require('gulp-rename'),
    pug     = require("gulp-pug");

gulp.task('pug', function(cb) {
  let options = {
        pretty: true
      };
  return gulp.src( files )
    .pipe( plumber() )
    .pipe( pug(options) )
    .pipe( rename({
      extname: '.php'
    }) )
    .pipe( gulp.dest( destPath ) );
});

こんな時にpugで生成するファイルにPHPタグを出力する方法のメモ。

pugの機能であるHTMLタグなどをエスケープしない Plain Text を利用するとPHPタグを出力することができます。(エスケープされないので、この方法を使うとPHPタグに限らず<script>タグなども出力できます。)

Plain Text
Pug provides four ways of getting plain text
...
And because plain text is not escaped, you can also include literal HTML.
出典: Plain Text – Pug

HTMLのタグ内にPHPを出力する

1行で出力する時はタグの後スペースを置き直接 PHPタグを書く ( Inline in a Tag )

// pug
div <?php the_content(); ?>

// コンパイル後
<div><?php the_content(); ?></div>

 
複数行で出力する場合

1. タグ名 の後に .を置き改行&インデントしてPHPを書く ( Block in a Tag )
// pug
div.
  <?php
    $id = get_the_ID();
    echo get_the_title( $id );
  ?>

// コンパイル後
<div><?php
  $id = get_the_ID();
  echo get_the_title( $id );
?></div>
2. タグ名を書き改行・インデントして行毎に | +スペースに続けてPHPを書く ( Inline in a Tag )
// pug
div
  | <?php
  |   $id = get_the_ID();
  |   echo get_the_title( $id );
  | ?>

// コンパイル後
<div><?php
  $id = get_the_ID();
  echo get_the_title( $id );
?></div>

hrefaltなどの属性の値にPHPを出力する

pugの属性の値はエスケープされるので Inline in a Tag のように書いても上手くコンパイルされません。

// pug
a(href="<?php the_permalink(); ?>") Link Text

// コンパイル後  < > がエスケープされてしまう
<a href="&lt;?php the_permalink(); ?&gt;">Link Text</a> 
!= を使うと属性にPHPタグが出力できる

Using != disables HTML-encoding in attributes.
出典: node.js - Jade: Why && is compiled to &amp; when used in angularjs in Jade template? - Stack Overflow

属性の場合、pugの変数を属性に設定する時と同じように != の後にスペースを開けて"の括った中に出力したいPHPタグを書けばOK。PHPタグを " で囲うことでタグを含む文字列としてそのまま出力させることができます。

// pug
a(href!= "<?php the_permalink(); ?>") Link Text

// コンパイル後
<a href="<?php the_permalink(); ?>">Link Text</a>

HTMLタグ外に直接PHPタグを出力する

PHPファイルの先頭のコメントなど、HTMLタグの外にPHPタグを出力させる方法。
複数行で出力する場合と同じ方法を、先頭にHTMLタグ名無しでも使用することができるようです。

1. . の後に改行したインデント内に記述する方法 ( Block in a Tag )
// pug
.
  <?php
    /**
     * hoge
     */
  ?>

// コンパイル後
<?php
  /**
   * hoge
   */
?>
2. | + スペースで記述する方法 ( Piped Text )
// pug
| <?php
|   /**
|    * fuga
|    */
| ?>

// コンパイル後
<?php
  /**
   * fuga
   */
?>
3. < で始まるタグはプレーンテキストとして解釈される事を利用する ( Literal HTML )

Literal HTML
Whole lines are also treated as plain text when they begin with a left angle bracket (<), ...
出典: Plain Text – Pug

pugは < から始まる行をプレーンテキストとして出力するので、PHPの開始タグに関してはこの方法を利用することができます。

//pug
<?php
.
   /**
    * Mofu
    */
  ?>

// コンパイル後
<?php /**
  * Mofu
  */
?>
//pug
<?php
  |
  | /**
  |  * Bar
  |  */
  | ?>

// コンパイル後
<?php
/**
 * Bar
 */
?>

先頭の <?php だけ Literal HTML で出力し、あとの部分は . block か | を使う必要があるので、全部 . block か | で書いてしまった方が簡単だと思いますが...  

まとめ

pugでPHPタグやhtmlタグを直接出力する時は

  • HTMLタグ内/外 の場合は
    1. . の後に改行しインデントしてタグをそのまま記述する
    2. | に続けて出力するタグをそのまま記述
  • 属性の値として出力する時は != "<?php 出力するコード ?>" の形式で記述

と覚えておけば良さそうです!


[参考]

Pug 変数を返すMixinをつくりたい。


HTMLプリコンパイラのpugを使っていて、引数から計算をして値を返すMixinを作ろうとした所

mixin getCalendarRow(dayNum, start)
  return Math.ceil( (dayNum + start - 1) / 7 );

// 呼び出し側
div(class="row"+ +getMonthRow(30, 6))

👇 次のようなエラーになってしまいました。

Plumber found unhandled error:
 TypeError in plugin 'gulp-pug'
 getCalendarRow is not a function

どうやら、pugのmixinはHTMLとかblockを出力するものでないと、mixinを呼び出した際にエラーになってしまうっぽいです...

function にしてしまえば、変数を返すmixinが作れる!

mixinキーワードでなく-の後に改行とインデントをしてfunctionとして作成すると変数を返すmixinが作成することができるみたいです!!

-
  function getCalendarRow(dayNum, start) {
    return Math.ceil( (dayNum + start - 1) / 7 );
  }

// 呼び出し側 呼び出しは通常の mixin と同じ
div(class="row"+ +getMonthRow(30, 6))

👇 出力

<div class="row5"></div>

(๑˃̵ᴗ˂̵)و ハッピー!

関数を作成する時に - を書いて改行&インデントをするのがポイントです。
- の後にインデントした範囲は普通のjavascriptとして認識されるのかもです。


[参考]