Angular HTMLバインディング


840

Angularアプリケーションを作成していて、表示したいHTML応答があります。

それ、どうやったら出来るの?バインディング構文を使用するだけで、{{myVal}}すべてのHTML文字が(もちろん)エンコードされます。

どうにかしてinnerHTMLa divを変数値にバインドする必要があります。


右のHTMLの結合に仕事にコンポーネントで定義されたCSSを取得するための関連のポストstackoverflow.com/questions/36265026/...
y3sh

1
解決策を説明し、例を挙げるためにビデオ応答をまとめました:youtube.com/watch
Caleb Grams

<span [routerLink] = ['some-router']> link </ span>のように、変数が角度タグまたはユーザー定義タグを保持している場合
G. Muqtada

回答:


1337

正しい構文は次のとおりです。

<div [innerHTML]="theHtmlString"></div>

ドキュメントリファレンス



14
angularでそのinnerHTMLの要素にバインディングを実行させる方法はありますか?<a [router-link]="..."> </a>を使用する必要があり、それを外部HTMLから提供したい。
thouliha

4
@thouliha私はあなたの質問に関して新しい投稿を始めることを勧めます。
prolink007 2016年

4
私の場合は文字列をレンダリングしますが、マークアップに対して何かを行います。マークアップの属性を取り除いたようです。私は2.4.6にいます
paqogomez 2017年

2
@paqogomezはい、安全でないと思われるものはすべて削除します
Juan Mendes

312

Angular 2.0.0およびAngular 4.0.0 final

安全なコンテンツのためだけに

<div [innerHTML]="myVal"></div>

DOMSanitizer

安全でない可能性のあるHTMLは、Angulars DOMサニタイザーを使用して信頼できるものとして明示的にマークする必要があるため、コンテンツの安全でない可能性がある部分を削除しません

<div [innerHTML]="myVal | safeHtml"></div>

のようなパイプで

@Pipe({name: 'safeHtml'})
export class Safe {
  constructor(private sanitizer:DomSanitizer){}

  transform(style) {
    return this.sanitizer.bypassSecurityTrustHtml(style);
    //return this.sanitizer.bypassSecurityTrustStyle(style);
    // return this.sanitizer.bypassSecurityTrustXxx(style); - see docs
  }
}

参照してくださいいくつかのスタイルが結合構文を使用して追加することはできませんRC.1で

そしてドキュメント:https : //angular.io/api/platform-b​​rowser/DomSanitizer

セキュリティ警告

ユーザーが追加したHTMLを信頼すると、セキュリティ上のリスクが生じる可能性があります。前に述べたドキュメントの状態:

いずれかのbypassSecurityTrust...APIを呼び出すと、渡された値に対するAngularの組み込みのサニタイズが無効になります。この呼び出しに入るすべての値とコードパスを慎重に確認および監査してください。このセキュリティコンテキストでは、ユーザーデータが適切にエスケープされていることを確認してください。詳細については、 『セキュリティガイド』を参照してください。

角度マークアップ

何かのようなもの

class FooComponent {
  bar = 'bar';
  foo = `<div>{{bar}}</div>
    <my-comp></my-comp>
    <input [(ngModel)]="bar">`;

<div [innerHTML]="foo"></div>

AngularがAngular固有の何かを処理することはありませんfoo。Angularはビルド時にAngular固有のマークアップを生成されたコードで置き換えます。実行時に追加されたマークアップは、Angularによって処理されません

Angular固有のマークアップ(プロパティまたは値のバインディング、コンポーネント、ディレクティブ、パイプなど)を含むHTMLを追加するには、動的モジュールを追加し、実行時にコンポーネントをコンパイルする必要があります。この回答は詳細を提供します動的テンプレートを使用/作成して動的コンポーネントをAngular 2.0でコンパイルするにどうすればよいですか?


13
これが答えになるはずです。コメントアウトされている2行に注意してください。それは実際にはHTMLを処理する2番目のものです。
paqogomez 2017年

8
必ずimport { BrowserModule, DomSanitizer } from '@angular/platform-browser'
paqogomez 2017年

4
またimport { Pipe } from '@angular/core'
Appulus

1
これが答えです、ここです!NG2の何がNG1の$ SCEに置き換わるかについての詳細を探していました。;)
jrista 2017

2
すばらしい答えです。私の問題を解決しました。どうもありがとう。誰かがコンポーネントでパイプを使用する方法がわからない場合(私がそうでしたように):angular.io/guide/pipes対応するモジュールとボイラーの宣言に追加するだけです!
Alejandro Nagy 2017年

169

[innerHtml] ほとんどの場合、これは優れたオプションですが、文字列が非常に大きい場合、またはHTMLでスタイルをハードコーディングする必要がある場合は失敗します。

私は他のアプローチを共有したいと思います:

あなたがする必要があるのは、あなたのhtmlファイルにdivを作成し、それにいくつかのIDを与えることです:

<div #dataContainer></div>

次に、Angular 2コンポーネントで、このオブジェクト(ここではTypeScript)への参照を作成します。

import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
    templateUrl: "some html file"
})
export class MainPageComponent {

    @ViewChild('dataContainer') dataContainer: ElementRef;

    loadData(data) {
        this.dataContainer.nativeElement.innerHTML = data;
    }
}

次に、loadData関数を使用して、html要素にテキストを追加します。

これは、ネイティブのJavaScriptを使用して行う方法と同じですが、Angular環境で使用します。コードが面倒になるのでお勧めしませんが、他のオプションがない場合もあります。

Angular 2-innerHTMLスタイリングも参照してください。


1
他のソリューションとの違いはわかりませんが、あなたの方法はnativeElement直接にのプロパティにアクセスしますが、これは悪い習慣と見なされています。私は間違い[innerHTML]="..."なく同じことを内部で行いますが、Angular2の良い練習方法です。
ギュンターZöchbauer

1
これは、Angular2が機能する方法ではありません。Angular2コンポーネントのテンプレートに追加したHTMLは最初にAngularによって処理され、その後DOMに追加されます。[innerHTML]Angular2 で実際に大きな文字列に問題が発生しましたか?
ギュンターZöchbauer

1
これはバグとして報告されるべきだと思います。結果を投稿していただきありがとうございます。
ギュンターZöchbauer

25
[innerHtml]Htmlにハードコーディングされたスタイルを削除します。wysiwygエディターを統合するために、ここにリストされているアプローチを使用する必要がありました。
ジョニーアダミット

2
私にとって、このソリューションはインラインSVGドキュメントを含めるために機能しました[innerHTML]が、アプローチは機能しませんでした。
Jared Phelps、

54

angular2@2.0.0-alpha.44で:

Html-Bindingはを使用すると機能しません{{interpolation}}。代わりに「式」を使用してください。

無効

<p [innerHTML]="{{item.anleser}}"></p>

->エラーをスローします(予想される式の代わりに補間)

正しい

<p [innerHTML]="item.anleser"></p>

->これが正しい方法です。

次のように、式に要素を追加できます。

<p [innerHTML]="'<b>'+item.anleser+'</b>'"></p>

ヒント

を使用して追加された[innerHTML](またはelement.appenChild()同様の方法で動的に追加された)HTMLは、セキュリティを目的としたサニタイズ以外の方法では、Angularによって処理されません。
このような機能は、HTMLがコンポーネントテンプレートに静的に追加された場合にのみ機能します。これが必要な場合は、動的テンプレートを使用/作成してAngular 2.0で動的コンポーネントをコンパイルする方法で説明されているように、実行時にコンポーネントを作成できます


1
再試行して編集しました。解決策が見つかりました:)
jvoigt

3
3番目の例は機能しません。式は評価されません。出力は単に文字列です... trustedHTMLを別のタグ要素と組み合わせる他の方法はありますか?
KEVIN Vilelaピント

25

AngularのDOMサニタイザーを使用せずに[innerHTML]を直接使用することは、ユーザーが作成したコンテンツが含まれている場合はオプションではありません。@GünterZöchbauer が彼の回答で提案したsafeHtmlパイプは、コンテンツをサニタイズする1つの方法です。次のディレクティブは別のものです。

import { Directive, ElementRef, Input, OnChanges, Sanitizer, SecurityContext,
  SimpleChanges } from '@angular/core';

// Sets the element's innerHTML to a sanitized version of [safeHtml]
@Directive({ selector: '[safeHtml]' })
export class HtmlDirective implements OnChanges {
  @Input() safeHtml: string;

  constructor(private elementRef: ElementRef, private sanitizer: Sanitizer) {}

  ngOnChanges(changes: SimpleChanges): any {
    if ('safeHtml' in changes) {
      this.elementRef.nativeElement.innerHTML =
        this.sanitizer.sanitize(SecurityContext.HTML, this.safeHtml);
    }
  }
}

使用する

<div [safeHtml]="myVal"></div>

これを使用しようとしましたが、次のエラーCan't bind to 'safeHtml' since it isn't a known property of 'div'. ng-version 2.4.4が発生します
LearnToday

1
@ObasiObenyOj限定されたケースであれば、別のディレクティブを使用せずにそれを行うことができconstructor( private sanitizer: Sanitizer) {} 、結果を必要なものにバインドします。また、ElementRefの使用は強くお勧めしません。
ベールスティーブ

22

最新の回答を参考にしてください。

これは私にとってはうまくいきます: <div innerHTML = "{{ myVal }}"></div>うまくいき(Angular2、Alpha 33)

別のSOによると:サーバーからHTMLをangular2(Angular2の一般的なDOM操作)DOMに挿入すると、「inner-html」はAngular 1.Xの「ng-bind-html」に相当します


正しい方法は、{{}}がない場合です。<div innerHTML = "myVal"> </ div>
クリスチャンベンスラー

2
{{interpolation}}の代わりに[property]バインディング構文を使用します
超光速'27年

これは間違いなく間違った方法であり、反対票を投じるべきです。これにより、すべてのhtmlがdiv属性内にレンダリングされます。
AsGoodAsItが

11

完全な答えを出すために、HTMLコンテンツがコンポーネント変数にある場合は、次のものも使用できます。

<div [innerHTML]=componementVariableThatHasTheHtml></div>

10

ここでポイントが欠けていることをお詫びしますが、別のアプローチをお勧めします。

サーバー側のアプリケーションから生データを返し、それをクライアント側のテンプレートにバインドする方が良いと思います。サーバーからjsonを返すだけなので、これにより軽快なリクエストが増えます。

私からは、サーバーからhtmlをフェッチしてDOMに「そのまま」注入するだけの場合、Angularを使用しても意味がないように思えます。

Angular 1.xにHTMLバインディングがあることは知っていますが、Angular 2.0にはまだ対応していません。彼らは後でそれを追加するかもしれません。とにかく、私はまだあなたのAngular 2.0アプリのデータAPIを検討します。

ここにいくつかのサンプルがあります興味がある場合は、いくつかの単純なデータバインディングを使用してください。http//www.syntaxsuccess.com/viewarticle/angular-2.0-examples


28
未加工のhtmlをフェッチして表示したいユースケースは確かにあります。たとえば、リモートからフォーマットされた記事をフェッチします。
Alexander Chen

2
別のよく無視されるシナリオは、テンプレートのビジネスロジックを保護することです。情報を表示するために使用しているロジックを権限のないユーザーに見られたくない場合があるため、サーバー側でビューを準備します
Ayyash

2
また、HTMLメールを表示することもできます-公正なポイント/質問!
ダレン

2
あなたが要点を欠いている場合(あなた自身の承認によると思われます)、なぜ応答を投稿するのですか?明らかにAngularのポイントは、ビューエンジンを使用してデータをバインドおよびレンダリングすることです。しかし、Angularアプリが使用される可能性のあるアプリケーションは無数にあるという事実を考えると、アプリケーションに表示する必要のあるデータの一部が既にフォーマット済みのHTMLである必要があるというアプリケーションが1つまたは2つ必要になる可能性があります。たまたま、開発者がそのコンテンツを制御できない場合もあります。つまり、関連する質問です。
グレゴール2017年

雅私達はちょうど角を捨てとjQueryはこの1つの事良くありませんので、jQueryのを使用する必要があります...
Simon_Weaver

9

簡単な答えはすでにここに提供されています:使用 <div [innerHTML]="yourHtml">バインディングを。

ただし、ここで述べた残りのアドバイスは誤解を招く可能性があります。そのようなプロパティにバインドすると、Angularには組み込みのサニタイズメカニズムがあります。Angularは専用のサニタイジングライブラリではないため、不審なコンテンツに対してリスクを負わずに過熱しています。たとえば、すべてのSVGコンテンツを空の文字列にサニタイズします。

メソッドを使用DomSanitizerしてコンテンツを安全であるとマークすることでコンテンツを「サニタイズ」するためのアドバイスを聞くかもしれませんbypassSecurityTrustXXX。それを行うためにパイプを使用する提案もあり、そのパイプはしばしば呼び出されますsafeHtmlます。

これは実際にコンテンツのサニタイズではなくサニタイズをバイパスするため、誤解を招く可能性があります。これは、ユーザーが提供したコンテンツや、わからないことに対してこれを行うと、悪意のあるコードの攻撃にさらされるため、セキュリティ上の問題になる可能性があります。

Angularが組み込みのサニタイズによって必要なものを削除した場合、無効にする代わりにできることは、実際のサニタイズをそのタスクに優れた専用ライブラリに委任することです。たとえば、DOMPurify。

Angularで簡単に使用できるように、ラッパーライブラリを作成しました:https : //github.com/TinkoffCreditSystems/ng-dompurify

また、宣言的にHTMLをサニタイズするパイプもあります。

<div [innerHtml]="value | dompurify"></div>

ここで提案されているパイプとの違いは、実際にDOMPurifyを介してサニタイズを行うため、SVGで機能することです。

DOMPurifyはHTML / SVGのサニタイズには最適ですが、CSSには適していません。したがって、CSSを処理するためにAngularのCSSサニタイザーを提供できます。

import {NgModule, ɵ_sanitizeStyle} from '@angular/core';
import {SANITIZE_STYLE} from '@tinkoff/ng-dompurify';

@NgModule({
    // ...
    providers: [
        {
            provide: SANITIZE_STYLE,
            useValue: ɵ_sanitizeStyle,
        },
    ],
    // ...
})
export class AppModule {}

これは内部的なものです—長いɵ接頭辞ですが、これはAngularチームが独自のパッケージ全体で使用する方法です。そのライブラリは、Angular Universalとサーバー側の再リンク環境でも機能します。


5

以下のようなHTML[innerHTML]属性を使用するだけです。

<div [innerHTML]="myVal"></div>

テンプレートに表示する必要があるhtmlマークアップまたはエンティティを含むプロパティがコンポーネントにありましたか?従来の補間は機能しませんが、innerHTMLプロパティバインディングが役立ちます。

使用{{myVal}} 期待どおりに動作しません!これ<p><strong>などのHTMLタグを取得せず、文字列としてのみ渡します...

コンポーネントに次のコードがあるとします。

const myVal:string ='<strong>Stackoverflow</strong> is <em>helpful!</em>'

を使用{{myVal}}すると、ビューで次のようになります。

<strong>Stackoverflow</strong> is <em>helpful!</em>

しかし、使用[innerHTML]="myVal"すると次のように期待どおりの結果になります:

Stackoverflow役に立ちます!


コンテナーdivなしでコンテンツを表示するには、コンテンツをどのように表示しますか?それは可能ですか?
ΕГИІИО

3

.htmlで次のように、スタイル、リンク、HTMLに複数のパイプを適用できます

<div [innerHTML]="announcementContent | safeUrl| safeHtml">
                    </div>

そして「URL」サニタイザーのための.tsパイプ

import { Component, Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({ name: 'safeUrl' })
export class SafeUrlPipe implements PipeTransform {
    constructor(private sanitizer: DomSanitizer) {}
    transform(url) {
        return this.sanitizer.bypassSecurityTrustResourceUrl(url);
    }
}

「HTML」サニタイザーのパイプ

import { Component, Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({
    name: 'safeHtml'
})
export class SafeHtmlPipe implements PipeTransform {
    constructor(private sanitized: DomSanitizer) {}
    transform(value) {
        return this.sanitized.bypassSecurityTrustHtml(value);
    }
}

これは、スタイルやリンククリックイベントを妨げることなく適用されます。


2

 <div [innerHTML]="HtmlPrint"></div><br>

innerHTMLのは、あなたがそれをプログラム的にHTMLコンテンツです設定することを可能にするHTML要素のプロパティです。コンテンツをプレーンテキストとして定義するinnerTextプロパティもあります。

[attributeName]="value"属性を囲むボックスブラケットは、角度入力結合を定義します。つまり、プロパティの値(あなたの場合はinnerHtml)が指定された式にバインドされ、expression-resultが変更されると、プロパティ値も変更されます。

したがって、基本的に[innerHtml]は、指定されたHTML要素のhtml-conentをバインドして動的に変更することができます。


1

では角度2あなたは、バインディングの3種類の操作を行うことができます。

  • [property]="expression"->任意のhtmlプロパティが
    式にリンクできます。この場合、式の変更によりプロパティが更新されますが、これは逆に機能しません。
  • (event)="expression" ->イベントがアクティブになると、式が実行されます。
  • [(ngModel)]="property"->プロパティをjs(またはts)からhtmlにバインドします。このプロパティの更新はどこでも顕著になります。

式には、値、属性、またはメソッドを指定できます。例: '4'、 'controller.var'、 'getValue()'

ここの


0

Angular 2ドキュメントで説明されているように、要素をDOMに動的に追加する方法は、@ Angular / coreのViewContainerRefクラスを使用することです。

あなたがしなければならないのは、ViewContainerRefを実装し、DOMのプレースホルダーのように振る舞うディレクティブを宣言することです。

指令

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[appInject]'
})
export class InjectDirective {

  constructor(public viewContainerRef: ViewContainerRef) { }

}

次に、コンポーネントを挿入するテンプレートで:

HTML

<div class="where_you_want_to_inject">    
  <ng-template appInject></ng-template>
</div>

次に、挿入されたコンポーネントコードから、必要なHTMLを含むコンポーネントを挿入します。

import { Component, OnInit, ViewChild, ComponentFactoryResolver } from '@angular/core';
import { InjectDirective } from '../inject.directive';
import { InjectedComponent } from '../injected/injected.component';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {

  @ViewChild(InjectDirective) injectComp: InjectDirective;

  constructor(private _componentFactoryResolver: ComponentFactoryResolver) {
  }

  ngOnInit() {
  }

  public addComp() {
    const componentFactory = this._componentFactoryResolver.resolveComponentFactory(InjectedComponent);
    const viewContainerRef = this.injectComp.viewContainerRef;
    const componentRef = viewContainerRef.createComponent(componentFactory);
  }

  public removeComp() {
    const componentFactory = this._componentFactoryResolver.resolveComponentFactory(InjectedComponent);
    const viewContainerRef = this.injectComp.viewContainerRef;
    const componentRef = viewContainerRef.remove();
  }

}

Angular 2に完全に機能するデモアプリを追加して、コンポーネントをDOMデモに動的に追加しました


0

ソリューションを実現するには、いくつかのアプローチを使用できます。承認済みの回答ですでに述べたように、次のものを使用できます。

<div [innerHTML]="myVal"></div>

達成しようとしていることに応じて、JavaScript DOMのような他のことも試すことができます(非推奨、DOM操作は遅い):

プレゼンテーション

<div id="test"></test>

成分

var p = document.getElementsById("test");
p.outerHTML = myVal;

プロパティのバインド

JavaScript DOM外部HTML


DOM操作が角度より遅いかどうかに関係なく、getElementsByIdやその他の選択方法を使用してそれを行うと、同じID(または他の基準)の要素が含まれている場合、完全に異なるコンポーネントに属する要素をキャプチャする可能性があるため、不適切です
Aviad P.

さらに、角度ゾーンの外側で完全に機能するため、変更が反映されません。
Philipp Meissner

0

innerHTMLプロパティにHTMLコンテンツを常に渡してHTML動的コンテンツをレンダリングできますが、その動的HTMLコンテンツも感染したり悪意のあるものになる可能性があります。したがって、動的コンテンツを渡す前にinnerHTMLDOMSanitizerすべての悪意のあるコンテンツをエスケープできるように、コンテンツがサニタイズされていることを確認する必要があります(を使用)。

パイプの下を試してください:

import { Pipe, PipeTransform } from "@angular/core";
import { DomSanitizer } from "@angular/platform-browser";

@Pipe({name: 'safeHtml'})
export class SafeHtmlPipe implements PipeTransform {
    constructor(private sanitized: DomSanitizer) {
    }
    transform(value: string) {
        return this.sanitized.bypassSecurityTrustHtml(value);
    }
}

Usage:
<div [innerHTML]="content | safeHtml"></div>

これはあなたがそうではないと思うかもしれないときでも必要です。たとえばstyle: background-color、すべてのものが取り除かれる可能性があるため、最初からこれを使い始めるのが最善です。そうしないと、後で非常に混乱するでしょう。
Simon_Weaver

私が理解しているのは、このスクリプトがすべての悪意のあるコンテンツ(bypassSecurityTrustHtml)を許可することです。これを指摘すると、ソースを信頼しない限り、このパイプは不要だと思います。参照先:angular.io/api/platform-b​​rowser/DomSanitizer#security-risk
Sae

0

Angular 2またはAngular 4でそれが必要で、インラインCSSを保持したい場合は、次を使用できます

<div [innerHTML]="theHtmlString | keepHtml"></div>

これは私にエラーを与えました `Uncaught(in promise):Error:Template parse errors:The pipe 'keepHtml' was not found`
Praveen

「@ angular / core」から{Pipe、PipeTransform}をインポートします。
ジェイ・モマヤ


0

Angular v2.1.1での作業

<div [innerHTML]="variable or htmlString">
</div>

2
これは<div _ngcontent-luf-0=""></div>私のために生成 します。div空です。
Scott Marcus

-2

アンギュラー(または任意のフレームワーク)アプリケーションにテンプレートがあり、HTTP要求/応答を介してバックエンドからHTMLテンプレートを返す場合、フロントエンドとバックエンドの間でテンプレートを混同しています。

フロントエンド(私はそれをお勧めします)またはバックエンド(かなり不透明なimo)にテンプレートの要素を残さないのはなぜですか?

また、テンプレートをフロントエンドに保持している場合は、JSONで応答してバックエンドへのリクエストを送信しないでください。RESTfulな構造を実装する必要さえありませんが、テンプレートを片側に保持することで、コードがより透過的になります。

これは、他の誰かがあなたのコードに対処しなければならない場合(またはあなた自身がしばらくしてから自分のコードを再入力する場合)に返済します!

正しく実行すれば、小さなテンプレートを備えた小さなコンポーネントができます。何よりも、コードがimbaであれば、コーディング言語を知らない人でもテンプレートとロジックを理解できるでしょう。したがって、さらに、関数/メソッドをできる限り小さくしてください。大規模な関数/メソッド/クラスと比較して、機能の維持、リファクタリング、レビュー、追加が簡単で、フロントエンドとバックエンド間でテンプレートとロジックを混同することが、最終的にわかります。フロントエンドをより柔軟にする必要がある場合(例:androidフロントエンドの作成または別のフロントエンドフレームワークへの切り替え)。

哲学、男:)

PS:100%クリーンなコードを実装する必要はありません。これは非常にコストがかかるためです。特に、チームメンバーのやる気を引き出さなければならない場合はそうです;)しかし:クリーンなコードへのアプローチと現在のもの(たぶんそれ)のバランスをとる必要があります。すでにかなりきれいです)

できれば本をチェックして、それをあなたの心に入れてください:https : //de.wikipedia.org/wiki/Clean_Code


SOAPのように古いAPIを扱う場合、サーバー側からHTMLを取得する必要がある場合があります。私はBSC(Bharat Stock Exchange)で私のプロジェクトに取り組んでおり、支払いの際に銀行ページのHTMLコードを返しました。したがって、APIを変更することはできません。それに応じてコードを更新してください。
Mahendra Waykos

SOAP APIを頻繁にクエリするミドルウェアを作成し、抽出された結果をソケットなどで提供できます。石鹸を介して情報を消費および抽出することは、困難な場合があります。
Guntram

生のマークアップの本当に大きな明らかな使用例は、マークアップがCMSからのものであり、WYSIWYGエディターで書かれている場合です。たとえば、ヘッドレスCMSから複数のエンドポイントを提供している場合があります。このようなことが、すべてのテンプレートエンジンに生のマークアップのオプションがある理由です。
gburton 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.