- Genel Bakış
- Basit bir örnek
- Ayrıntılar
- Durum
- amp-state ile başlangıç durumu
- Durumu yenileme
- Durumu AMP.setState() ile güncelleme
- AMP.pushState() ile geçmişi değiştirme
- İfadeler
- JavaScript'ten farklılıklar
- Örnekler
- Beyaz listedeki işlevler
- Makroları amp-bind-macro ile tanımlama
- Bağlamalar
- Öğeye özel özellikler
- Hata ayıklama
- Uyarılar
- Hatalar
- Hata Ayıklama Durumu
- Ek
- <amp-state> spesifikasyonu
- XHR toplu işlemesi
- Özellikler
- AMP.setState() ile derin birleştirme
- Bir değişkeni kaldırma
- İfade dil bilgisi
amp-bind
Description
Veri bağlama ve basit JS benzeri ifadeler aracılığıyla kullanıcı işlemlerine veya veri değişikliklerine yanıt olarak öğelerin değişmesine olanak tanır.
Required Scripts
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
Veri bağlama ve ifadelerle özel etkileşim özelliği ekler.
Zorunlu Komut Dosyası | <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script> |
Örnekler | |
Eğiticiler | Etkileşimli AMP sayfaları oluşturma |
Genel Bakış
amp-bind
bileşeni, veri bağlama ve JS benzeri ifadeler aracılığıyla AMP sayfalarınıza özel durum bilgili etkileşim özelliği eklemenize olanak tanır.
Basit bir örnek
Aşağıdaki örnekte düğmeye dokunduğunuzda, <p>
öğesinin "Hello World" olan metni "Hello amp-bind" olarak değişir.
<p [text]="'Hello ' + foo">Hello World</p>
<button on="tap:AMP.setState({foo: 'amp-bind'})">Say "Hello amp-bind"</button>
amp-bind
öğesi, sayfa yüklemede ifadeleri değerlendirmez. Bu, görsel öğelere bir varsayılan durum verilmesi ve ilk oluşturma için amp-bind
öğesine güvenilmemesi gerektiği anlamına gelir. İşleyiş şekli
amp-bind
üç ana bileşene sahiptir:
- State: Bir dokümanın kapsamı, değişebilir JSON durumu. Yukarıdaki örnekte, düğmeye dokunmadan önce durum boştur. Düğmeye dokunulduktan sonra, durum
{foo: 'amp-bind'}
olur. - Expressions: Bunlar, state başvurusunda bulunabilen JavaScript benzeri ifadelerdir. Yukarıdaki örnekte, dize değişmez değerini (
'Hello '
) ve durum değişkenini (foo
) birbirine bağlayan tek bir'Hello ' + foo
ifadesi bulunmaktadır. Bir ifade içinde 100 işlenen kullanma sınırı vardır. - Bindings: Bunlar, bir öğenin özelliğini bir expression öğesine bağlayan
[property]
formunun özel özellikleridir. Yukarıdaki örnekte,<p>
öğesinin metnini ifade değeri her değiştiğinde güncelleyen tek bir bağlama ([text]
) bulunmaktadır.
amp-bind
, AMP sayfalarında hız, güvenlik ve performansı sağlamaya özel önem verir.
Biraz daha karmaşık bir örnek
<!-- Store complex nested JSON data in <amp-state> elements. -->
<amp-state id="myAnimals">
<script type="application/json">
{
"dog": {
"imageUrl": "/img/dog.jpg",
"style": "greenBackground"
},
"cat": {
"imageUrl": "/img/cat.jpg",
"style": "redBackground"
}
}
</script>
</amp-state>
<p [text]="'This is a ' + currentAnimal + '.'">This is a dog.</p>
<!-- CSS classes can also be added or removed with [class]. -->
<p class="greenBackground" [class]="myAnimals[currentAnimal].style">
Each animal has a different background color.
</p>
<!-- Or change an image's src with the [src] binding. -->
<amp-img width="300" height="200" src="/img/dog.jpg" [src]="myAnimals[currentAnimal].imageUrl">
</amp-img>
<button on="tap:AMP.setState({currentAnimal: 'cat'})">Set to Cat</button>
Düğmeye basıldığında:
- Durum,
'cat'
olarak tanımlanancurrentAnimal
ile güncellenir. -
currentAnimal
öğesine bağlı ifadeler değerlendirilir:'This is a ' + currentAnimal + '.'
=>'This is a cat.'
myAnimals[currentAnimal].style
=>'redBackground'
myAnimals[currentAnimal].imageUrl
=>/img/cat.jpg
-
Değiştirilen ifadelere bağlı olan bağlamalar güncellenir:
- İlk
<p>
öğesinin metni, "This is a cat" olur. - İkinci
<p>
öğesininclass
özelliği "redBackground" olur. amp-img
öğesi bir kedinin resmini gösterir.
- İlk
Ayrıntılar
Durum
amp-bind
kullanan her AMP dokümanı, doküman kapsamı değişebilir JSON verilerine veya durum bilgisine sahiptir.
amp-state
ile başlangıç durumu
amp-bind
durumu, amp-state
bileşeni ile başlatılabilir:
<amp-state id="myState">
<script type="application/json">
{
"foo": "bar"
}
</script>
</amp-state>
İfadeler, durum değişkenlerine nokta söz dizimi aracılığıyla başvurabilir. Bu örnekte, myState.foo
, "bar"
olarak değerlendirilir.
- Bir
<amp-state>
öğesinin alt JSON'ı en fazla 100 KB olur. - Bir
<amp-state>
öğesi, alt JSON komut dosyası yerine bir CORS URL'si de belirtebilir. Ayrıntılar için Ek bölümüne bakın.
Durumu yenileme
refresh
işlemi bu bileşen tarafından desteklenir ve durum içeriğini yenilemek için kullanılabilir.
<amp-state id="amp-state" ...></amp-state>
<!-- Clicking the button will refresh and refetch the json in amp-state. -->
<button on="tap:amp-state.refresh"></button>
Durumu AMP.setState()
ile güncelleme
AMP.setState()
işlemi, bir nesne değişmez değerini durumla birleştirir. Örneğin, aşağıdaki düğmeye basıldığında AMP.setState()
öğesi, nesne değişmez değerini durum ile derinden birleştirir.
<!-- Like JavaScript, you can reference existing
variables in the values of the object literal. -->
<button on="tap:AMP.setState({foo: 'bar', baz: myAmpState.someVariable})"></button>
Genel olarak, iç içe yerleştirilmiş nesneler en fazla 10 derinlikte birleştirilir. amp-state
tarafından sunulanlar da dahil olmak üzere tüm değişkenler geçersiz kılınabilir.
Belirli etkinlikler tarafından tetiklendiğinde, AMP.setState()
, event
özelliğindeki etkinlikle ilgili verilere de erişebilir.
<!-- The "change" event of this <input> element contains
a "value" variable that can be referenced via "event.value". -->
<input type="range" on="change:AMP.setState({myRangeValue: event.value})">
AMP.pushState()
ile geçmişi değiştirme
AMP.pushState()
işlemi, tarayıcı geçmiş yığınına yeni bir giriş de aktarması haricinde AMP.setState()
işlemine benzer. Bu geçmiş girişine dönülmesi (geri gidilerek), AMP.pushState()
tarafından ayarlanan değişkenlerin önceki değerini geri yükler.
Örneğin:
<button on="tap:AMP.pushState({foo: '123'})">Set 'foo' to 123</button>
- Düğmeye dokunulduğunda
foo
değeri 123 olarak ayarlanır ve yeni bir geçmiş girişi aktarılır. - Geri gidildiğinde
foo
önceki değeri olan "bar" değerine geri yüklenir (AMP.setState({foo: 'bar'})
işleminin çağrılmasıyla eşdeğerdir).
İfadeler
İfadeler, bazı önemli farklılıklarla birlikte JavaScript'e benzer.
JavaScript'ten farklılıklar
- İfadeler yalnızca ifadeleri içeren dokümanın durumuna erişebilir.
- İfadeler,
window
veyadocument
gibi genel öğelere erişmez. - Yalnızca beyaz listedeki işlevler ve operatörler kullanılabilir.
- Özel işlevlere, sınıflara ve döngülere genellikle izin verilmez. Ok işlevlerine parametre olarak izin verilir; ör.
Array.prototype.map
. - Tanımlanmamış değişkenler ve sınırların dışındaki dizi dizini
undefined
değeri döndürmek veya hata bildirmek yerinenull
değerini döndürür. - Performans açısından şu anda tek bir ifade 50 öğe ile sınırlanmıştır. Sizin kullanım alanınız için bu sayı yeterli değilse lütfen bize ulaşın.
Tam ifade dil bilgisi ve uygulaması, bind-expr-impl.jison ve bind-expression.js içinde bulunabilir.
Örnekler
Aşağıdaki ifadelerin tümü geçerlidir:
1 + '1' // 11
1 + (+'1') // 2
!0 // true
null || 'default' // 'default'
Beyaz listedeki işlevler
Nesne türü | Fonksiyonlar | Örnek |
---|---|---|
Array 1 | concat filter includes indexOf join lastIndexOf map reduce slice some sort (not-in-place)splice (not-in-place) | // Returns [1, 2, 3]. [3, 2, 1].sort() // Returns [1, 3, 5]. [1, 2, 3].map((x, i) => x + i) // Returns 6. [1, 2, 3].reduce((x, y) => x + y) |
Number | toExponential toFixed toPrecision toString | // Returns 3. (3.14).toFixed() // Returns '3.14'. (3.14).toString() |
String | charAt charCodeAt concat indexOf lastIndexOf slice split substr substring toLowerCase toUpperCase | // Returns 'abcdef'. abc'.concat('def') |
Math 2 | abs ceil floor max min random round sign | // Returns 1. abs(-1) |
Object 2 | keys values | // Returns ['a', 'b']. keys({a: 1, b: 2}) // Returns [1, 2]. values({a: 1, b: 2} |
Global 2 | encodeURI encodeURIComponent | // Returns 'Hello%20world'. encodeURIComponent('Hello world') |
1Tek parametreli ok işlevlerinde parantez kullanılamaz; örneğin (x) => x + 1
yerine x => x + 1
kullanın. Ayrıca, sort()
ve splice()
, yerinde çalışma yerine değiştirilmiş kopyalar döndürür.
2Statik işlevler ad alanlı değildir; ör. Math.abs(-1)
yerine abs(-1)
işlevini kullanın.
Makroları amp-bind-macro
ile tanımlama
amp-bind
ifade parçaları bir amp-bind-macro
tanımlanarak yeniden kullanılabilir. amp-bind-macro
öğesi, sıfır veya daha fazla bağımsız değişken alan ve geçerli duruma başvuruda bulunan bir ifade tanımlamanıza olanak tanır. Bir makro, dokümanın herhangi bir yerinden id
özelliği değerine başvuruda bulunularak bir işlev gibi çağrılabilir.
<amp-bind-macro id="circleArea" arguments="radius" expression="3.14 * radius * radius"></amp-bind-macro>
<div>
The circle has an area of <span [text]="circleArea(myCircle.radius)">0</span>.
</div>
Bir makro, kendisinden önce tanımlanan diğer makroları da çağırabilir. Bir makro kendini yinelemeli olarak çağıramaz.
Bağlamalar
Bağlama, bir öğenin özelliğini bir ifadeye bağlayan [property]
formunun özel bir özelliğidir. data-amp-bind-property
alternatif, XML uyumlu bir söz dizimi de kullanılabilir.
Durum değiştiğinde, ifadeler yeniden değerlendirilir ve bağlı öğelerin özellikleri yeni ifade sonuçlarıyla güncellenir.
amp-bind
, dört öğe durumu türünde veri bağlamalarını destekler:
Tür | Özellikler | Ayrıntılar |
---|---|---|
Node.textContent | [text] | Çoğu metin öğesinde desteklenir. |
CSS sınıfları | [class] | İfade sonucu, boşlukla ayrılmış bir dize olmalıdır. |
hidden özelliği | [hidden] | Bir boole ifadesi olmalıdır. |
AMP öğelerinin boyutu | [width] [height] | AMP öğesinin genişliğini ve/veya yüksekliğini değiştirir. |
Öğeye özel özellikler | Çeşitli |
Bağlamalar ile ilgili notlar:
- Güvenlik nedeniyle,
innerHTML
öğesine bağlamaya izin verilmez. - Güvenli olmayan değerler (ör.
javascript:
) tüm özellik bağlamalarından temizlenir. - Boole ifadesi sonuçları, boole özelliklerini açar/kapatır. Örneğin:
<amp-video [controls]="expr"...>
.expr
,true
olarak değerlendirildiğinde,<amp-video>
öğesicontrols
özelliğine sahip olur.expr
,false
olarak değerlendirildiğindecontrols
özelliği kaldırılır. - Özellik adlarındaki köşeli parantez karakterleri
[
ve]
XML (ör. XHTML, JSX) veya DOM API'leri aracılığıyla özellikleri yazarken soruna yol açabilir. Bu durumlarda,[x]="foo"
yerine alternatifdata-amp-bind-x="foo"
söz dizimini kullanın.
Öğeye özel özellikler
Yalnızca aşağıdaki bileşenlere ve özelliklere bağlamaya izin verilir:
Bileşen | Özellikler | Davranış |
---|---|---|
<amp-brightcove> | [data-account] [data-embed] [data-player] [data-player-id] [data-playlist-id] [data-video-id] | Görüntülenen Brightcove videosunu değiştirir. |
<amp-carousel type=slides> | [slide] * | Şu anda görüntülenen slayt dizinini değiştirir. Örneğe göz atın. |
<amp-date-picker> | [min] [max] | Seçilebilir en erken tarihi ayarlar Seçilebilir en son tarihi ayarlar |
<amp-google-document-embed> | [src] [title] | Güncellenen URL'deki dokümanı görüntüler. Dokümanın başlığını değiştirir. |
<amp-iframe> | [src] | İframe'in kaynak URL'sini değiştirir. |
<amp-img> | [alt] [attribution] [src] [srcset] | [src] öğesine bağlanırken, bağlamanın önbellekte çalışması için [srcset] öğesine de bağlama yaptığınızdan emin olun.İlgili amp-img özelliklerine bakın. |
<amp-lightbox> | [open] * | Lightbox'ın görüntülenmesini etkinleştirir/devre dışı bırakır. İpucu: Lightbox kapatıldığında değişkenleri güncellemek için on="lightboxClose: AMP.setState(...)" işlemini kullanın. |
<amp-list> | [src] | İfade bir dizeyse dize URL'sinden JSON öğesini getirir ve oluşturur. İfade bir nesne veya diziyse ifade verilerini oluşturur. |
<amp-selector> | [selected] *[disabled] | Geçerli olarak seçilmiş,option özelliği değerlerine göre tanımlanan alt öğeleri değiştirir. Çoklu seçim için virgülle ayrılmış değer listesini destekler. Örneğe göz atın |
<amp-state> | [src] | JSON değerini yeni URL'den alır ve mevcut durumla birleştirir. Aşağıdaki güncellemenin döngüleri önlemek için <amp-state> öğelerini yoksayacağını unutmayın. |
<amp-video> | [alt] [attribution] [controls] [loop] [poster] [preload] [src] | İlgili amp-video özelliklerine bakın. |
<amp-youtube> | [data-videoid] | Görüntülenen YouTube videosunu değiştirir. |
<a> | [href] | Bağlantıyı değiştirir. |
<button> | [disabled] [type] [value] | İlgili button özelliklerine bakın. |
<details> | [open] | İlgili details özelliklerine bakın. |
<fieldset> | [disabled] | Alan grubunu etkinleştirir veya devre dışı bırakır. |
<image> | [xlink:href] | İlgili image özelliklerine bakın. |
<input> | [accept] [accessKey] [autocomplete] [checked] [disabled] [height] [inputmode] [max] [maxlength] [min] [minlength] [multiple] [pattern] [placeholder] [readonly] [required] [selectiondirection] [size] [spellcheck] [step] [type] [value] [width] | İlgili input özelliklerine bakın. |
<option> | [disabled] [label] [selected] [value] | İlgili option özelliklerine bakın. |
<optgroup> | [disabled] [label] | İlgili optgroup özelliklerine bakın |
<select> | [autofocus] [disabled] [multiple] [required] [size] | İlgili select özelliklerine bakın. |
<source> | [src] [type] | İlgili source özelliklerine bakın. |
<track> | [label] [src] [srclang] | İlgili track özelliklerine bakın. |
<textarea> | [autocomplete] [autofocus] [cols] [disabled] [maxlength] [minlength] [placeholder] [readonly] [required] [rows] [selectiondirection] [selectionend] [selectionstart] [spellcheck] [wrap] | İlgili textarea özelliklerine bakın. |
*Bağlanabilir olmayan bir eşdeğeri bulunmayan bağlanabilir özellikleri belirtir.
Hata ayıklama
Geliştirme sırasında ortaya çıkan uyarıları ve hataları vurgulamak ve özel hata ayıklama işlevlerine erişmek için geliştirme modunda (#development=1
URL parçasıyla) test yapın.
Uyarılar
Geliştirme modunda, bir bağlama özelliğinin varsayılan değeri, karşılık gelen ifadenin ilk sonucuyla eşleşmediğinde amp-bind
bir uyarı yayınlar. Bu, diğer durum değişkenlerindeki değişikliklerin neden olduğu istenmeyen dönüşümleri önlemeye yardımcı olabilir. Örneğin:
<!-- The element's default class value ('def') doesn't match the expression result for [class] ('abc'),
so a warning will be issued in development mode. -->
<p class="def" [class]="'abc'"></p>
Geliştirme modunda, amp-bind
, tanımlanmamış değişkenleri veya özellikleri başvurudan kaldırırken bir uyarı da yayınlar. Bu, aynı zamanda null
ifade sonuçları nedeniyle istenmeyen dönüşümleri önlemeye yardımcı olabilir. Örneğin:
<amp-state id="myAmpState">
<script type="application/json">
{ "foo": 123 }
</script>
</amp-state></p>
<!-- The amp-state#myAmpState does not have a `bar` variable, so a warning
will be issued in development mode. -->
<p [text]="myAmpState.bar">Some placeholder text.</p>
Hatalar
amp-bind
ile çalışırken karşılaşabileceğiniz birkaç çalışma zamanı hatası türü vardır.
Tür | Mesaj | Öneri |
---|---|---|
Geçersiz bağlama | <P> öğesinde [someBogusAttribute] özelliğine bağlamaya izin verilmiyor. | Yalnızca beyaz listedeki bağlamaları kullanın. |
Sözdizimi hatası | İfade derleme hatası... | İfadede yazım hataları olmadığını doğrulayın. |
Beyaz listede yer almayan işlevler | uyarı desteklenen bir işlev değildir. | Yalnızca beyaz listedeki işlevleri kullanın. |
Temizlenmiş sonuç | "javascript:alert(1)", [href] için geçerli bir sonuç değil. | Yasaklanmış URL protokollerini veya AMP Doğrulayıcı'da başarısız olacak ifadeleri kullanmaktan kaçının. |
CSP ihlali | 'blob:...' öğesinden bir işçi oluşturulması reddedildi. Aksi takdirde, şu İçerik Güvenliği Politikası kuralı ihlal edilecekti... | Kaynağınızın İçerik Güvenliği Politikası'na default-src blob: öğesini ekleyin. amp-bind , iyi bir performans sağlamak üzere pahalı işler için özel bir Web İşçisine yetki verir. |
Hata Ayıklama Durumu
Geçerli durumu konsola yazdırmak için AMP.printState()
kullanın.
Ek
<amp-state>
spesifikasyonu
Bir amp-state
öğesi, bir alt <script>
öğesi VEYA uzak bir JSON uç noktasının CORS URL'sini içeren bir src
özelliği içerebilir ancak bunların ikisini birden içeremez.
<amp-state id="myLocalState">
<script type="application/json">
{
"foo": "bar"
}
</script>
</amp-state>
<amp-state id="myRemoteState" src="https://data.com/articles.json">
</amp-state>
XHR toplu işlemesi
AMP, XMLHttpRequest öğelerini (XHR'ler) JSON uç noktalarında toplu olarak işler; diğer bir deyişle, bir AMP sayfasında birden çok tüketici (ör. birden fazla amp-state
öğesi) için veri kaynağı olarak tek bir JSON veri isteğini kullanabilirsiniz. Örneğin, amp-state
öğeniz bir uç noktaya XHR gönderirse XHR iletilirken aynı uç noktaya yapılacak sonraki XHR'lerin hiçbiri tetiklenmez ve bunun yerine, ilk XHR'nin sonuçları döndürülür.
Özellikler
src | Bu amp-state öğesini güncelleyecek olan JSON değerini döndürecek uzak uç noktanın URL'si. Bu bir CORS HTTP hizmeti olmalıdır. src özelliği, tüm standart URL değişkeni değişikliklerine izin verir. Daha fazla bilgi için Değişiklik Kılavuzu dokümanına bakın. Uç nokta, AMP'de CORS İstekleri spesifikasyonunda belirtilen gereksinimleri uygulamalıdır.
|
credentials (isteğe bağlı) | Getirme API'si tarafından belirtildiği şekliyle bir credentials seçeneğini tanımlar.
include değerini geçirin. Bu değer ayarlanırsa yanıt, AMP CORS güvenlik yönergelerine uygun olmalıdır. |
AMP.setState()
ile derin birleştirme
AMP.setState()
çağrıldığında, amp-bind
, sağlanan nesneyi değişmez değerini geçerli durumla derin birleştirir. Nesne değişmez değerindeki tüm değişkenler, tekrar eden bir şekilde birleştirilen iç içe yerleştirilmiş nesneler haricinde, doğrudan duruma yazılır. Nesne değişmez değerinde bulunan, temel öğeler ve dizilerle aynı ada sahip değişkenlerin değeri her zaman bunların üzerine yazılır.
Aşağıdaki örneği inceleyin:
{
<!-- State is empty -->
}
<button on="tap:AMP.setState({employee: {name: 'John Smith', age: 47, vehicle: 'Car'}})"...></button>
<button on="tap:AMP.setState({employee: {age: 64}})"...></button>
İlk düğmeye basıldığında durum şu şekilde değişir:
{
employee: {
name: 'John Smith',
age: 47,
vehicle: 'Car',
}
}
İkinci düğmeye basıldığında, amp-bind
nesne değişmez değeri bağımsız değişkenini ({employee: {age: 64}}
) yinelenen bir şekilde mevcut durumla birleştirir.
{
employee: {
name: 'John Smith',
age: 64,
vehicle: 'Car',
}
}
employee.age
güncellenmiş ancak employee.name
ve employee.vehicle
anahtarları değişmemiştir.
AMP.setState()
işlemini döngüsel başvurular içeren bir nesne değişmez değeriyle çağırırsanız amp-bind
öğesinin hata vereceğini lütfen unutmayın.
Bir değişkeni kaldırma
Mevcut bir durum değişkeninin değerini AMP.setState()
işleminde null
olarak ayarlayarak değişkeni kaldırın. Önceki örnekteki durumla başlayarak:
<button on="tap:AMP.setState({employee: {vehicle: null}})"...></button>
Düğmesine basıldığında durum şu şekilde değişir:
{
employee: {
name: 'John Smith',
age: 48,
}
}
Benzer biçimde:
<button on="tap:AMP.setState({employee: null})"...></button>
Düğmesine basıldığında durum şu şekilde değişir:
{
<!-- State is empty -->
}
İfade dil bilgisi
amp-bind
ifadeleri için BNF benzeri dil bilgisi:
expr:
operation
| invocation
| member_access
| '(' expr ')'
| variable
| literal
operation:
'!' expr
| '-' expr
| '+' expr
| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| expr '%' expr
| expr '&&' expr
| expr '||' expr
| expr '<=' expr
| expr '<' expr
| expr '>=' expr
| expr '>' expr
| expr '!=' expr
| expr '==' expr
| expr '?' expr ':' expr
invocation:
expr '.' NAME args
args:
'(' ')'
| '(' array ')'
;
member_access:
expr member
;
member:
'.' NAME
| '[' expr ']'
variable:
NAME
;
literal:
STRING
| NUMBER
| TRUE
| FALSE
| NULL
| object_literal
| array_literal
array_literal:
'[' ']'
| '[' array ']'
array:
expr
| array ',' expr
object_literal:
'{' '}'
| '{' object '}'
object:
key_value
| object ',' key_value
key_value:
expr ':' expr
Bu belgeyi defalarca okudunuz ama tüm sorularınıza tatmin edici bir yanıt bulamadınız mı? Belki başka kişiler de bu şekilde hissetmiştir: Stack Overflow'dan onlara ulaşın.
Stack Overflow'a git Bir hata veya eksik bir özellik mi buldunuz?AMP projesi, katılımınızı ve katkılarınızı güçlü bir şekilde teşvik ediyor! Açık kaynak topluluğumuzun devamlı bir katılımcısı olacağınızı umuyoruz ancak özel olarak ilgilendiğiniz konularla ilgili tek seferlik katkıları da memnuniyetle karşılıyoruz.
GitHub'a git