めろたんのアレ

色々書いてくやつ

CSSのアレをアレコレしてアウトラインを引いて可視化する件について

これをみて、これ便利だよね〜ってなったけど意外とみんなしらない???みたいなアレになったので、どこに需要があるかもわからんが個人的に好きなのでまあ書いておく。 僕のブログだし。

使うときどうやってるか

個人的に使うときはここにざっと書いたけどまあそういうことっすわ。
実際に例を書く。

例えばflocssの設計で書いたとき

github.com

命名規則はレイアウトなら .l-*#hoge で、 コンポーネント.c-*、 プロジェクトは .p-* みたいな感じだね。 じゃあ雑にそれをつかって無を書く。
書いて本題のやつもやる。

やったのが以下

See the Pen cssのプレフィックスつけると便利っていう話 by renyamizuno (@renyamizuno) on CodePen.

はい。

codepenのタブのCSSってのを押すとCSSが見れたりするのでHTMLとか見ながらふむふむしてくれ〜。

[class^="l-"] みたいなセレクタを使うことでクラス名の頭にl-がついているやつ。みたいな選択ができ、そいつにスタイルを当てることができると。 なんかめんどくてborderにしたけどbackground-colorrgba とかつかって少し透過した感じにしたりするとなんかそれっぽくなってオシャレになると思う。*1

と、まあ命名規則ちゃんとしてやるとこういう使い方もできて便利なときは便利だよ〜という話でした。 昨今はなんていうの? css in js ? とかそういうのでコンパイルしちゃって .vthdoi2 みたいなクラス名になっちゃったりしてアレなことが多いかもしれないけど、こういう(古というかなんと言えばいいかわからん。)のも使えるといいんじゃねえかな〜って思ったりするよ〜っていう話でした。

*1:それがメインのやりたいことじゃないのでアレだとは思うけど

今更TypeScriptをやる ぱーと2

前回は下の

merotan.hatenablog.com

これの続きをやっていく。

Interfaces

ダックタイピングとかストラクチャルサブタイピングとかのやつ。 JavaとかのInterfaceと違って、明示的に継承とか実装?(implements だっけ?)とかしてなくても、メンバがアレばよしなに動くよ〜みたいな感じ。

interface Test {
  a: string;
  b: () => string;
}

const f = (t: Test) => {
  console.log(t.a);
  console.log(t.b());
}

f({a: '', b: ()=>('a')});
f({a: 1, b: ()=>('a')}); // エラー。 aはstringでないのでだめ。
f({a: '', b: ()=>(2)}); // エラー。 bの返り値がstringではないのでだめ。

基本はこういう感じかな。

Optional Properties

オプションなやつ。あってもなくてもいいよ〜っていうあれっすね。

interface Test {
  a?: string;
  b?: number;
}


const test = (t: Test) => {
  if (t.a) {
    console.log(t.a);
  }
  if (t.b) {
    console.log(t.b);
  }
}

test({ a: '' });
test({ b: 1 });
test({});
test({ b: ''}); // エラー。bがnumberではない。

なくてもよいよ〜とできる。

Readonly properties

そのままですね。 読み取り専用。 各種viewのフレームワーク?ライブラリのプロパティとかにつけるといいのかな?

interface Test {
  readonly a: string;
  b: number;
}

const test = (t: Test) => {
  t.a = ''; // エラー。読み取り専用なので代入できんよ〜。
  t.b = 1;
}

便利〜

ReadonlyArray とかもあるらしい。 Array を読み取り専用にするものらしい。ほかにも ReadonlyMap とか ReadonlySet とかがある様子。

Excess Property Checks

interface Test {
  a?: string;
  b?: number;
}

const test = (t: Test) => {
  if (t.a) {
    console.log(t.a);
  }
  if (t.b) {
    console.log(t.b);
  }
}

test({ a: '', c: 1}); // エラー。cがあるので型がアレ。

みたいなので c とか他のプロパティもいい感じに許容したいよ〜みたいなアレ。

interface Test {
  a?: string;
  b?: number;
  [propName: string]: any;
}

こうするといい感じになるとかなんとか。 あんまりよくない気がする。

interface Test {
  a?: string;
  b?: number;
}

const test = (t: Test) => {
  if (t.a) {
    console.log(t.a);
  }
  if (t.b) {
    console.log(t.b);
  }
}

const t = { a: '', c: 1};

test(t);

これでどうにかなるし、functionの引数を直で書くときはそりゃその引数の型に厳格でいけよ。というだけな気がするし、まあはい。 こういう風に任意のプロパティをアレできるよ〜っていうのは覚えておいたほうが良いねというのはある。

Function Types

functionの型をあれするinterfaceをかくこともできる。

interface Test {
  (a: string): number;
}

interface Test2<T> {
  (a: T): T;
}

let a: Test = (b) => {
  return 1;
}

a = () => (''); // エラー

引数のところでエラーが出てないけどなんでだろ?

JS、引数渡さなかったり、多く渡してもfunctionを実行できたりするからそれ関係でなんかあれなのかな?

arguments とかどうなるんだろ。

interface Test {
  (a: string): number;
}

interface Test2<T> {
  (a: T): T;
}

let a: Test = function () {
  const b = arguments[0];
  return b.length;
}

a('a');

any になったわ。まあそうねという感じ。

Indexable Types

Excess Property Checks のところで出てきた [hoge: string]: string みたいなやつね。

interface Test {
  [index: number]: string;
}

const test = (t: Test) => {
  t[0] = 'asdf';
  t[4] = 'asdf';
  t[5] = 1; // エラー。stringではないから。
};

はい。

index のところの型は stringnumber のみです。

複数定義することも可能。

interface Test {
  [index: number]: string;
  [index: string]: string;
}

ただし、値の型は一致させておく必要があります。 なぜならJSの挙動で、 t[0]t['0'] が同じものを指すので型を違えることはできません。
ベースがJSであるゆえの問題というかなんというか。

まあこんな使い方をすることがなさそうだからなんとアレだけどね。

あと、indexstringを使った場合は他のプロパティもそれの型に合わせる必要があります。

interface Test {
  [index: string]: string;
  x: number; // エラー。stringにしないといけない。
}

理由は上のアレと似たようが話ですね。 t.xt['x'] は同じものを指すので、型を違えることはできないわけですね。

Class Types

クラスに実装(implements)をするぞ〜というアレ。

interface Test {
  a: number;
}

class MyClass implements Test {
  a = 1;
  b = 2;
}

const myClass = new MyClass();

const test = (t: Test) => {
  return t.a;
};

console.log(test(myClass));

こんな感じっすね。

MyClassa を定義しないとエラーになる。

コンストラクタのあれこれもかけるとかなんとか。

interface TestConstructor {
  new (a: number);
}

interface Test {
  a: number;
}

class MyClass implements Test, TestConstructor { // エラー
  a = 1;
  b = 2;

  constructor(a: number){
    this.a = a;
  }
}

こういうふう。 new っていうのを使う。 でこれはエラーになる。

implementsインスタンスの型のチェックになるため、対象のクラスに実装しようとすると変になる。 のでうまくやるには以下のようにする。

interface TestConstructor {
  new (a: number): Test;
}

interface Test {
  a: number;
}

class MyClass implements Test {
  a = 1;
  b = 2;

  constructor(a: number){
    this.a = a;
  }
}

const createMyClass = (t: TestConstructor, a: number) => {
  return new t(a);
}

const test = (t: Test) => {
  return t.a;
};

console.log(test(createMyClass(MyClass, 1)));

こういう感じで別にインスタンスを作るfunctionを定義してよしなに使う感じっぽい。

interface TestConstructor {
  new (a: number): Test;
}

interface Test {
  a: number;
}

const MyClass: TestConstructor = class implements Test {
  a = 1;
  b = 2;

  constructor(a: number){
    this.a = a;
  }
}

const test = (t: Test) => {
  return t.a;
};

const a = new MyClass(1);

console.log(test(a));

こういうふうでも可。

ただ、newインスタンスにしたものの型がnewのところに書いた型になってしまうので、いまいちアレかなぁとおもった。

Extending Interfaces

まあ interface の継承ですね。

interface Test1 {
  a: number;
}

interface Test2 {
  b: string;
}

interface Test3 extends Test1, Test2 {
  c (d: number): number;
}

const test = (t: Test3) => {
  t.a;
  t.b;
  t.c(1);
}

こういう感じ。

Hybrid Types

Function Types といろいろ合体するやつ。

interface Test {
  (a: number): number;
  a: number;
  b: string;
}

const test: Test = (a) => {
  return a;
}

test.a = 1;
test.b = '';

こういう感じ。 ただ、 testaとかが後で追加みたいな感じでちょっとイケてないので、 getTest みたいなのをなんか作ってまとめちゃうとかがいいっぽい。

interface Test {
  (a: number): number;
  a: number;
  b: string;
}

const getTest = (a: number, b: number): Test => {
  const test: Test = (a) => {
    return a;
  }
  test.a = 1;
  test.b = ''; 

  return test;
}

こういう感じ。

Interfaces Extending Classes

クラスをinterfaceとして扱えるという感じなのかな?

class Test1 {
  private a = 1;
  add(b: number): number {
    return b + 1;
  }
}

interface Test2 extends Test1 {
  sub(c: number): number;
}

class Test3 extends Test1 implements Test2 {
  sub(c) {
    return c - 2;
  }
}

class Test4 implements Test2 { // エラー。 private の a が無いという感じ。
  add(b) {
    return b;
  }
  sub(c) {
    return c;
  }
}

private のプロパティとかを作ると、 interface として扱った場合に、private の宣言がアレするので死ぬ感じっぽい。 なので、使い所はよくよく考えたほうが良い様子。

はい

ガバーっとみた。 なるほどな〜というのと、これは使わないだろうなぁ…というのがあったりした。

また引き続きやっていく。

CSSフレームワーク・ライブラリーを使うなら自前でCSSを書くな!という話

どうも過激派のめろたんです。

タイトル通りで僕はそういうお気持ちで日々過ごしております。

ではなぜそうおもっているのか等々を書いていこうと思います。

なぜそうおもうか。例を添えて

なぜかと言うと、大体腐るからです。クソ雑に言ってるのではて?となるかもしれませんが、僕の語彙ではそういう風にしか表現できない。

まあ実際に例をあげていろいろ書いてみる。

あなたはWebアプリを作っています。 Bootstrapを使っているとしましょう。

getbootstrap.com

便利だよね。わかる。

で開発が進むに連れて、大きいボタンがほしくなりました。 btn-lg のものよりもっと大きいものです。 なおbtn-lgは使っておりません。

ではここでどうしますか?

  1. btn-lg のスタイルを上書きする?
  2. btn-more-lg みたいなのをつくる?
  3. そのページだけ btn-lg のサイズを変えるようにする?

このどれかが取られる選択肢かなぁと思います。それか <button style="width:....."> とか直で書いちゃうとかかな?

まあ直で書いちゃうのは無いでしょ。というので一旦捨て置いて。 では個々に問題を考えていく。

1. btn-lg のスタイルを上書きする? の例

まあ単純に元の btn-lg の大きさで使いたい場合が出てきたときに死ぬよね。

一人で死ぬならまだしも、チーム開発で他メンバーが「Bootstrap使ってるし btn-lg ってのでいい感じの大きさのボタンできるじゃ〜ん。」っていってBootstrapのドキュメント通りに書いたら全然違う結果になった!っていうのが余裕で起こる。

更にここで、どうやってもとの btn-lg を使おうか…となったときに、 btn-origin-lg とか書く?それとも気合で元にもどす?そのときにどこまで影響あるかわかる?この場合おそらく widthheight だけだと思うけど、 line-height 等を使っていた場合どうなるかわかる?

などなど。諸問題が連なって発生する。

ヤバイわよ!

2. btn-more-lg みたいなのをつくる?の例

1の問題は起きない。 可能性が高い 。 バリエーションを増やすと、あれもこれも。となりがち。故に今度はもうちょっと小さいやつがほしい。一番小さいやつよりもっと小さいやつがほしい。そもそも角丸がいらない。真円のボタンが。中にいい感じにアイコンをいれたい。etc

という風になりがち。
結果、どれがBootstrapのものなのか、どれが自前のものなのかわからなくなり死にがち。 ドキュメントに無いぞ!ってなってなにこれ…ってなるやつ。
一人ならわかるかもだけど、チーム開発で…(以下略。

ドキュメントに無いので、書いて良いんだな。となりどんどん書かれる。ちょっとしたスタイル(すこしマージン開けたいとか)がどんどん書かれていく。 結果さらになにがなにかわからなくなる。

ヤバイわよ!

3. そのページだけ btn-lg のサイズを変えるようにする?の例

body.a-page .btn-lg {
}

みたいな書き方のやつね。

これは 1 と 2 の似たような問題が合体して押し寄せてくる。

画面によってバリエーションが発生する。 「このページのこのボタンこのサイズなんだ〜他のページでも同じように使えばいい感じになるかな?」とやってもならない。結果 body のところの指定が増えるまたはそのページの body.a-page クラスがつく。 本当なら .a-page だけのスタイルがここに入ってくるはずなので、 .a-page のアレのスタイル変えよ〜とかなったときに別のページも影響して死ぬ。しかも普通は気付け無い。

ドキュメントに書いてあるが、違う見た目になる場合がある。という地獄のサムシングが爆誕して治安が無になる。 結果死ぬ。

またこれは詳細度が上がる書き方なので、詳細度・ド・バトル が開催され下手をすると !important 先輩が登場する。
結果死ぬ。

ヤバイわよ…。

そして全てに共通する問題

フレームワークのアップデートで死ぬ可能性が限りなく高い。

たとえばBootstrap4はjQueryに依存しているが、5になるとjQueryが要らなくなる。 即座にアップデートしたいであろう。
ところが、上記のような自前CSSを書いていた場合、意図していないスタイルの崩れが発生しうる。

このときに上の例のボタンの大きさを〜というくらいなら良いかもだが、もしレイアウト系のスタイルを触っていた場合どうだろうか?

getbootstrap.com

containerrow 等をいい感じにしたいんだよね〜等で少し触っていた場合、本当に全体に影響がでる。 これらをアップデートしたときに果たしてどうなるのか。

getbootstrap.com

実際に一つ前のバージョンのBootstrapをみると、明らかに色々違う。
レスポンシブ対応が逝く。そもそもクラス名が変わってしまい、何もいじっていなければエディターで一括置き換え等すればいい感じになったかもしれないところが、不要なところまで変わって辛いことになる。等々
色々起きる可能性がある。

これらの問題に関して、「うまく設計し立ち回れば問題ないでしょう。」という意見があるだろうが、それができるならそもそもCSSフレームワークつかうなよ!!!!(過激派

どうすべきと考えているか

です。

こうすれば諸問題は起こり得ないですね。(過激派

真面目な話をすると、

CSSフレームワークを使う際はSCSS等のいわゆるaltCSSを使って必要なものだけをとってきて使うようにする。
最近のものなら各種変数があるはずなのでそれをよしなに変更して、変に別クラスを作るとか上書きをするとかしないようにする。とかかな。

そうすれば概ね問題は回避できるんじゃねえかな…。しらんけど。なぜなら僕はフレームワーク使うなよ勢なので。

あとはTwitterで話してたんだけど

こういうのはありかとおもった。

tailwindcss.com

Tailwindはユーティリティ集のようなCSSフレームワーク(?)で、各種CSSのスタイルの宣言がクラスで書かれている。
mt-4とかだと「上のマージンをサイズを4で取る」というスタイルになる。(サイズ1が0.25rem。その4倍なので1rem。)
このようなクラスがザラーーーーーーーっと大量にある。 自分で書くよりよっぽど安全であろうと思う。
優先度とかは気をつける必要があるが、まあそれくらいだろう。
自分でかいて変に上書きしたり、ドキュメントにありそうな名前で作りあとで混乱したり、変に詳細度を上げてしまい意図しない崩壊が起きたり等は防げるはず。

フレームワークを使っていて、どうしても少し変えたいとかがあればTailwindをおすすめする。

自分で書いてるならTailwind入れなくてもいい。書けばいいんだから。クラスに書くかCSSを書くかの違いでしかないからね。

まとめ

CSSフレームワークを使っているなら自前でCSSを書くな!今の自分が良くても半年後の自分・一週間後の同僚等々が悲しい気持ちになるぞ。
覚悟完了しているならば書いてもよし。

どうしてもちょっと変えないといけない等あれば Tailwind の導入を考えよう。
絶対に自前でCSSを書くなよ!
死ぬぞ!

今更TypeScriptをやる

やる

はじめに

脳死yarn init から yarn add typescript

これで最低限の準備が完了。

webフロントで動かすみたいなのがよくあるアレだけど今回はNodeで動作をみたりする。

のでその辺りは一旦忘れる。

雑に適当なのをかく

type A = 'a' | 'b';

const test = (a:A): void => {
  console.log(a);
};

test('a');

yarn tsc ./src/1.ts とか雑に食わせる。

結果

var test = function (a) {
    console.log(a);
};
test('a');

アイ。

type の定義がきえますね。まあそう。

yarn tsc -t ESNEXT ./src/1.ts とかターゲットのバージョンとかを指定すると結果が変わる。

const test = (a) => {
    console.log(a);
};
test('a');

varconst になった。

型をアレしてみる。

type A = 'a' | 'b';

const test = (a:A): void => {
  console.log(a);
  return a;
};

test('c');
src/1.ts:5:3 - error TS2322: Type 'A' is not assignable to type 'void'.
  Type '"a"' is not assignable to type 'void'.

5   return a;
    ~~~~~~~~~

src/1.ts:8:6 - error TS2345: Argument of type '"c"' is not assignable to parameter of type 'A'.

8 test('c');
       ~~~


Found 2 errors.

error Command failed with exit code 2.

型が違うわい〜という感じのエラーがでましたね。

一応JSも吐き出された。

var test = function (a) {
    console.log(a);
    return a;
};
test('c');

壊れたアレででてますね。

基本的な型とか

www.typescriptlang.org

これ

boolean とか number とか string とかは、まあね。

Array

const arr1: Array<number> = [1, 2];

const arr2: number[] = [1, 2];

まあはい。

特に意味はないけど、ジェネリックで書くほうが好き。 Array<number> これね。

Tuple

タプルだ。

const t:[number, string] = [1, 'merotan'];

はい。 配列のアレだからなんか違和感があってなんか好きくない…。

出力はこう

var t = [1, 'merotan'];

まあそうね。

Enum

enumあったんだ。 しらなかった。

enum Test { a, b, c };

const t: Test = Test.a;

console.log(t);

なるほどな〜という感じ。 a とかでそのまま書けるかなぁとおもったけど、まあむずいか。となった次第。

出力はこう

var Test;
(function (Test) {
    Test[Test["a"] = 0] = "a";
    Test[Test["b"] = 1] = "b";
    Test[Test["c"] = 2] = "c";
})(Test || (Test = {}));
;
var t = Test.a;
console.log(t);

なんかむずいな。

Test["a"]0 が入って、 Test[0]"a" がはいってる。 みたいな感じかな。

最後の console.log あたりを少し書き換えて実行。

node 対象のjs みたいな感じで。

var Test;
(function (Test) {
    Test[Test["a"] = 0] = "a";
    Test[Test["b"] = 1] = "b";
    Test[Test["c"] = 2] = "c";
})(Test || (Test = {}));
;
var t = Test.a;
console.log(Test.a);
console.log(Test[0]);

結果

0
a

結果見る限り、上で書いたようなそういう感じですね。

Any

まあこいつはいいでしょ。

なんでもはいるぞ。ってやつでしょ。(雑

Void

たまに思うけど void とか null とか同じじゃねみたいな気持ちになる(違う)

値を返さない関数の戻り値の型でよく使うみたいなアレ。

onClick とかでなにも返さんわ〜みたいなときに書いたりするよね。

let a:void = null;
a = undefined;
a = 0; // エラー
a = ''; // エラー
a = 1; // エラー

const b = ():void => { };
const c = ():void => ('a'); // エラー

はい〜。

Null and Undefined

まあはい。

Never

neverむずい。 値が変えることが無いとかの関数の返り値の型としてつかわれるようす。

const t = ():never => {
  throw new Error();
};

const r = ():never => {}; // エラー

なるほど。

てっきりこの引数は使いませんよ。という型とかそういうもんかとおもっていたけどはい。

Object

まあはい。

class A {}

const a = new A();

const b = (obj: Object) => {};

b(a);

これは通るんだ。 まあそうか。

Type assertions

as とか。

const a = '';

console.log(a as any as number);

こいつの型はこれっすよ。というアレですね。 any を経由すると無敵。(やってはいけない

const a = '';
const b = <number><any>a;

console.log(b);

こうやって書くこともできるとか。 初めて知った。

はい

きょうはこのあたりで。 またちょっとずつやっていく。

無限ループアラート事件について思うこと

うぇい。

おもしろい(おもしろくないし洒落にならん)事件があったので記事書くぞ〜〜〜〜。

無限ループアラート事件

NHKのニュースでこんなのがありました。

www3.nhk.or.jp

クリックすると同じ画面が表示され、消えなくなる不正なプログラムのアドレスをインターネットの掲示板に書き込んだとして、13歳の女子中学生が兵庫県警に補導されました。

無限にalertを出すプログラムを見つけて、それを拡散したら*1補導された。という事件がありました。

は?

はい。何をいっているんだ?という方もいらっしゃると思いますが、僕もよくわかりません。

f:id:renyamizuno:20190305193555p:plain
Twitterのトレンド(2019年3月5日19時30分頃)

トレンドもこの話題で占拠されてます。

技術者各位の皆さんにはこれは明らかにおかしいだろ。という方が多いかと思われますが、

(自称)ITジャーナリストの方や、デマでとても苦しんだ方ですらちゃんと見ていないあたりなんなのか。という感じですが、 まあそういう感じで今回補導や書類送検された方に対してバッシングのようなことをしている人もいます。

今回のこの件で気になる点がいくつかあるので書いていこうと思います。

何がだめ?

Coinhiveの件でも書きましたが何がダメなのでしょうか。

今回のは「何度消しても無駄だぜ」のような煽り的なメッセージがあったので、まあそういうイタズラサイトなんだなっていうのがわかります。

それで補導・書類送検するのはおかしくないですか?

実害がほぼゼロ*2なのに何で補導なのかまじでわからない。

しかも重要なのが、この3人はプログラムを書いたわけではなく、アドレスを掲示板に書いただけです。

つまり、

Aさん「壁に落書きしてやろ〜〜〜〜〜⤴」

Bさん・Cさん・Dさん「あそこに落書きがある〜。」
Bさん「うわ〜やだな〜。みんなに知らせて、どうにかしてもらおう。」
Cさん「かっこいいじゃん。みんなに知らせて、みんなで見よう。」
Dさん「おもしろいな〜〜〜。みんなに共有しよう。」

警察「B、C、D、お前ら落書きの場所をみんなに教えたな?全員逮捕だ。」

みたいな感じ。

落書き(迷惑行為)をした人物には一切触れず、ただ拡散しただけの人たちを捕まえるというのはなんなんでしょうか。

大体落書きして、そんな力強く逮捕だみたいなの見たこと無いんだけど。まず注意からしない?普通。

www.sanspo.com

また他のニュース記事では家宅捜索とあります。

正気?こんな程度の低いこと*3で家宅捜索されるの?気が狂ってるでしょ。(暴言)

俺もお前らのホームページで意図していないJSが動いてたから家宅捜索すんぞマジで。

悪いとして作者は?

何度も言うようにこの補導や家宅捜索された人たちはあくまで拡散した人たちです。

"不正プログラム"*4を作った人ではありません。

本気でこれが"不正プログラム"だと信じて疑わないなら作者を攻めるべきです。

なぜそれをしないのでしょうか?

レベル的にできないんだったら日本のサイバー捜査(笑)って感じだし、もしあえてしていないのであれば何をしたいの。点数稼ぎかな?

Coinhive事件でもそうですが、作者にたいしてなんのアクションもとっていないように見えるのはなんなんでしょうか。点数稼ぎかな?

点数稼ぎかな?

悪いとしてなにが?

悪いとしましょう。一旦。これは"不正プログラム"です。

ではなにを持ってして"不正プログラム"でしょうか。

今回のコードはマジで程度が低い。14文字くらいで実現できる。*5

また実際に動いていたコードもTwitterにスクショとかで上がってますが、複雑な計算をCPUを食い荒らしてマイニングするぞ〜とかは無いし、個人情報を抜くとかも無い。
ただ14文字くらいでできるコードがあるだけ。

では"不正プログラム"の要件は何でしょうか。

無限ループがあれば?それは無いでしょうね。多分。それだったらいろんなプログラムが"不正"となってしまいますね。

アラートがでる?それも無いでしょうね。編集中ですが前の画面に戻ってもいいですか?とかも"不正"になってしまいます。

たくさんアラートがでる?それだったらエラー項目が沢山あって延々にアラートがでちゃうプログラムも"不正"ですね。

無限にアラートがでる?それだったらバグで無限にでるようになっても"不正"ですね?

バグだったらセーフ?それだったら今回のもバグなんじゃないですか?ちゃんと検証しましたか?

はて?

本当に"容疑"を認めているのか

nlab.itmedia.co.jp

この記事が全てですが、正直なにも信用ならんなぁという気持ちしか無い。

僕が中1のときにこんなのやられたら泣きながらハイハイいって反省してます。認めます。しか言えない。

今回の事件でこういうのがあったかどうかは謎ですが、Coinhiveの一件で実際にあることが完全にわかったのと、ITに疎いとああやって攻めるしかできないんだなぁという印象がついてしまって、「どうせ今回もおなじようなことしたんだろ」と個人的には思ってしまいました。

大体なんの容疑だよ。

まとめ

はい。

今回はCoinhive事件と違い、画面にでてくるもので事件となりました。

で、多くの人がTwitterで書いていたのですが、バグで無限ループアラートを起こしてしまった場合、どうなるのでしょうか。

そのバグを発見して掲示板に「このサイト見てみwwwwwww」とリンクをつけたら、そのリンクを書いた人はどうなるのでしょうか。

誰がどう判断するのでしょうか。

これは偏見なのですが、プログラムを学んだことのある人の多くが無限ループをやったことがあると思っていて、中には今回の事件のようなイタズラ的なものを作ったことがある人もいるでしょう。

その人達は全員"不正プログラム"を作った犯罪者なのでしょうか?

おかしくないでしょうか?

というかこんなんことやるくらいなら悪質な広告(例えばウィルスに感染していますとか)を出してる奴らを先になんとかしろ。そっちのが実害あんぞ。ふざけんな。

とまあブチギレなんですが、Coinhive事件同様、日本のITというかWeb業界を揺るがす事件が起きてしまったなあ、やばいな、もうおわりだなあという気持ちです。
本気で海外移住考えたほうが良いのでは?(日本脱出だよね

*1:「アドレスを掲示板に書き込んだ」とあるので悪意があって書き込んだ可能性はあるが、そうではなく困って人に聞こうとして書き込んだとかの可能性もある

*2:タブを閉じるなり・ブラウザを再起動するなりで止まる

*3:程度の低さを示すためにJSのコードを書こうと思ったのですが、教唆とか幇助とされかねないので書きません。

*4:大体不正プログラムってなによ。

*5:JSのコードを書こうと思ったのですが、教唆とか幇助とされかねないので書きません。(2度目)

CSS Houdini をつかってキミだけの最強レイアウトを組み立てよう!

うぇ〜い

昨日は年を忘れるための飲み会、通称「忘年会」に参加していました。 慌てて記事を書いています。*1

この記事は Misoca+弥生+ALTOA Advent Calendar 2018 - Qiita 8日目の記事です。 昨日はt_haraさんの「Kotlinの.isInitialized呼び出しになぜCallableReferenceの指定が必要なのか」でした。

blog.thara.jp

明日は めろたんさん が「なんかがんばります」だそうです。 これは期待できますよ・・・!

去年と同じパターンだ。

CSS Houdini

皆さんがCSSを書くと、なかなかうまくスタイルを当てることができなかったり、そもそもブラウザによっては対応していないことが多くあると思います。

また少し変えただけのはずが、様々な場所がズレたりしてしまいとてもつらいと感じたことが多々あるでしょう。 まるで"魔法"だな。 と思うことも多々あると思います。

みなさんも魔法使いたいですよね?

そこで Houdini というものがあります!

Houdiniで何ができるかって言うと、ざっくり雑に言うとJSでCSSを拡張できます。 すごいですね。

多くの仕様がまだDraftであったりするので、実戦投入は厳しいですが、面白い技術ではありますし、夢があるので紹介しようかな。と思います。

なにができる?

いろいろあるのですが、

  • CSS の値に型を付ける
  • カスタムプロパティを登録する
    • 型の指定や、デフォルト値の設定等ができる
  • CSS を定義する
  • CSSの レイアウト を定義する
  • アニメーションを制御する

などなどができます。

型をつけるとかはクソ便利なのでさっさと実戦で使えるようになるといいなと思っています。

で今回はそれの説明をしても、あまり映えないのでレイアウトを定義するのをやってみましょう。

キミだけの最強のレイアウト作ろう

でこのレイアウトを定義する仕様が CSS Layout API Level 1 になります。

これはほとんどの?ブラウザで動かないので、Chrome Canary で確認します。

Chrome Canaryを起動後 chrome://flags/, chrome://flags/ にアクセスして Experimental Web Platform features を有効にします。

これで使えるようになるはずです。

ではざっとコードをはります。

index.html

<style>
  .container {
    width: 50px;
    height: 50px;
    display: layout(sample-layout);
    padding: 100px;
    border: solid 2px;
  }
</style>
<div class="container">
  <div>左上</div>
  <div>真ん中</div>
  <div>右下</div>
</div>
<script type="text/javascript">
  CSS.layoutWorklet.addModule('layout.js');
</script>

layout.js

registerLayout('sample-layout', class {
  *intrinsicSizes(children, edges, styleMap) {}

  *layout(children, edges, constraints, styleMap, breakToken) {
    const childFragments = yield children.map((child) => {
      return child.layoutNextFragment(constraints);
    });

    childFragments.forEach((fragment, i) => {
      fragment.inlineOffset = constraints.fixedInlineSize * i / childFragments.length;
      fragment.blockOffset = constraints.fixedBlockSize * i / childFragments.length;
    });

    return {
      childFragments
    };
  }
});

CSS Layout API の使用例
バーン

動かすとこんなかんじになります。

スタイルには対して斜めに配置するようなものは書いていませんが、HoudiniのLayout APIを使うとこういう事ができます。

なにやってるのか簡単に説明

CSS.layoutWorklet.addModule というので指定したファイルを Layout Workletスクリプトとして追加されます。
Worklet というのがメインのJS実行環境とは別に実行されるJSで Web Worker と似たものです。(雑)
ですが、スレッドには依存しなかったり等ちょっと違います。(雑)
詳しくは Worklets Level 1 で。

registerLayout で レイアウト名と実際にどうレイアウトするのかを定義したクラスを渡します。 ここで設定したレイアウトを使うには CSSlayout: 設定したレイアウト名; とすると使えます。

intrinsicSizeslayout がジェネレータ関数として定義されている必要があります。 将来的には Promiseになるかも?みたいな感じっぽいですが、今はジェネレータです。

intrinsicSizes でそのレイアウトのサイズを返します。ですが、今回は特に使わないので無視!

layout で小要素をどうレイアウトしていくかを書いていきます。 今回は引数のうち children, constraints をつかってます。

children が小要素ですね。 constrains はそのレイアウトの制約、利用可能なスペースとかが取得できます。

layoutNextFragmentCSSフラグメント を取得します。 CSSフラグメントには inlineOffset, blockOffset 等があります。 inlineOffset で横の位置、 blockOffset で縦の位置を設定できます。

constrainsfixedInlineSize でそのレイアウトが適用される要素の横幅、 fixedBlockSize でそのレイアウトが適用される要素の縦幅が取得できます。

コードを見ると、

childFragments.forEach((fragment, i) => {
  fragment.inlineOffset = constraints.fixedInlineSize * i / childFragments.length;
  fragment.blockOffset = constraints.fixedBlockSize * i / childFragments.length;
});

とあるので、小要素を順に少しずつずらして言ってることがわかりますね。

これでさっきあったようになるわけですね〜〜

わけわかんない?
僕もよくわかない。

気づいた人もいるかもしれませんがこのレイアウトを当ててる要素にはpaddingがあったのですが、どうみても無視されてますね。
このLayout API を使うとそれらも無視することができます。 強いですね。

まとめ

だいぶたのしいですね。あとCSS Houdini ヤバイ(意味深)という感じがしますね!

とりあえず、こんな感じで自作のレイアウトを組み立てられるので、みなさんも自分の手で

「キミだけの最強レイアウトを組み立てよう!!!」

次回予告

明日は、和食@yoshoku さんが 「Numo::NArrayでなにか実装します」とのことです!
きっとすごいなにかが実装されますよ!!!

余談または蛇足

技術書典5雑に 書いて出しました。

techbookfest.org

150部刷って30部くらいしかでなかったのでめちゃくちゃレアですよ! 欲しい人がいたらリプとかDMください…。

twitter.com

こちらまで

*1:去年と同じことしてる…。学ばないやつだ。

人はどこまでいっても繋がっているのだという話

うぇい〜

最近はちょっとした遠出*1をして良かったなぁ(小並感)となっていたりしています。

最近プライベートなことで色々あったので結構前から思っていることと絡めて書こうかなと思っています。

技術的な話は一切無いし、個人的な感情のアレ(エモ)なので、アレです。

人は"何"と"何"をしているのか

多くの方が一日の1/3近く仕事していたり、学校で勉強していたり、子育てや、その他色々していると思います。

僕はなんと仕事をしているのですが、ほとんどの時間をPCに向き合ってカチャカチャしています。

ですが僕はPCと仕事をしているわけでは無いのです。 あくまでPCを使って仕事をしているわけで、何と仕事しているかというと、同僚であったり、上司であったり、お客さんであったり、 つまりは"人"と仕事をしているんですよ。

結構前に「お前は良いよな。パソコンと仕事してるだけでいいから、人とのいざこざがなくてさ。」みたいな事言われてブチ切れたことがありました。

あくまでPCは道具であり、人と仕事しているのだ。

仕事だけではない。普段の生活でもそうだ。ゴミを出したらちゃんと回収される。電気水道ガスがちゃんと届く。荷物が届く。ちゃんとしたサービスを受けられる。

全部他人がいないとどうにもならない。

どこまでいっても人は人と繋がっていて相互に作用して生きていのだ。

ざつまとめ

何をするにも他人とつながっているのだ。

その繋がりには良い効果も悪い効果もある。

どこまでいっても作用しあうなら良い効果を大きくしたいですね。

*1:隣の県とかだから別にそんなに遠くないんだけど