diff --git a/.eslintrc b/.eslintrc index 0e48c800345d..f650756a2f43 100644 --- a/.eslintrc +++ b/.eslintrc @@ -62,6 +62,7 @@ "no-export-side-effect": 2, "no-extend-native": 2, "no-extra-bind": 2, + "no-extra-semi": 2, "no-for-of-statement": 2, "no-implicit-coercion": [2, { "boolean": false }], "no-implied-eval": 2, diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 16525768b500..eca9aebd2c61 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -16,3 +16,19 @@ Bullet points like really help with making this more readable. Fixes/Closes/Related-to #1 (enter issue number, except in rare cases where none exists). + +It is also helpful to add an emoji before the commit message to identify the kind of work done on a single commit. See the following suggestions below: + +- :bug: - `:bug:` Bug fix +- :sparkles: - `:sparkles:` New feature +- :white_check_mark: - `:white_check_mark:` Tests +- :fire: - `:fire:` P0 +- :rocket: - `:rocket:` Performance improvements +- :crayon: - `:crayon:` CSS / Styling +- :wheelchair: - `:wheelchair:` Accessibility +- :globe_with_meridians: - `:globe_with_meridians:` i18n (Internationalization) +- :book: - `:book:` Documentation +- :recycle: - `:recycle:` Refactoring (like moving around code w/o any changes) +- :building_construction: - `:building_construction:` Infrastructure / Tooling / Builds / CI +- :rewind: - `:rewind:` Revert +- :put_litter_in_its_place: - `:put_litter_in_its_place:` Deleting code diff --git a/3p/ampcontext-lib.js b/3p/ampcontext-lib.js index d1588c8bc01a..e1b63dfbb4ed 100644 --- a/3p/ampcontext-lib.js +++ b/3p/ampcontext-lib.js @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import './polyfills'; + +// src/polyfills.js must be the first import. +import './polyfills'; // eslint-disable-line sort-imports-es6-autofix/sort-imports-es6 + import {AmpContext} from './ampcontext.js'; import {initLogConstructor, setReportError} from '../src/log'; diff --git a/3p/ampcontext.js b/3p/ampcontext.js index 9e8768396e3d..ff82728ef4cc 100644 --- a/3p/ampcontext.js +++ b/3p/ampcontext.js @@ -178,7 +178,7 @@ export class AbstractAmpContext { }); return unlisten; - }; + } /** * Requests HTML snippet from the parent window. @@ -216,7 +216,7 @@ export class AbstractAmpContext { 'width': width, 'height': height, })); - }; + } /** * Allows a creative to set the callback function for when the resize @@ -228,7 +228,7 @@ export class AbstractAmpContext { onResizeSuccess(callback) { this.client_.registerCallback(MessageType.EMBED_SIZE_CHANGED, obj => { callback(obj['requestedHeight'], obj['requestedWidth']); }); - }; + } /** * Allows a creative to set the callback function for when the resize @@ -241,7 +241,7 @@ export class AbstractAmpContext { this.client_.registerCallback(MessageType.EMBED_SIZE_DENIED, obj => { callback(obj['requestedHeight'], obj['requestedWidth']); }); - }; + } /** * Takes the current name on the window, and attaches it to diff --git a/3p/environment.js b/3p/environment.js index e1561b459563..c1350cdc03df 100644 --- a/3p/environment.js +++ b/3p/environment.js @@ -261,4 +261,4 @@ export function installEmbedStateListener() { listenParent(window, 'embed-state', function(data) { inViewport = data.inViewport; }); -}; +} diff --git a/3p/facebook.js b/3p/facebook.js index 066fbf5cfc70..13560355c9e8 100644 --- a/3p/facebook.js +++ b/3p/facebook.js @@ -29,8 +29,8 @@ import {user} from '../src/log'; * @param {!Window} global * @param {function(!Object)} cb */ -function getFacebookSdk(global, cb) { - loadScript(global, 'https://connect.facebook.net/' + dashToUnderline(window.navigator.language) + '/sdk.js', () => { +function getFacebookSdk(global, cb, locale) { + loadScript(global, 'https://connect.facebook.net/' + locale + '/sdk.js', () => { cb(global.FB); }); } @@ -58,6 +58,27 @@ function getPostContainer(global, data) { return container; } +/** + * Create DOM element for the Facebook embedded page plugin. + * Reference: https://developers.facebook.com/docs/plugins/page-plugin + * @param {!Window} global + * @param {!Object} data The element data + * @return {!Element} div + */ +function getPageContainer(global, data) { + const container = global.document.createElement('div'); + container.className = 'fb-page'; + container.setAttribute('data-href', data.href); + container.setAttribute('data-tabs', data.tabs); + container.setAttribute('data-hide-cover', data.hideCover); + container.setAttribute('data-show-facepile', data.showFacePile); + container.setAttribute('data-hide-cta', data.hideCta); + container.setAttribute('data-small-header', data.smallHeader); + container.setAttribute( + 'data-adapt-container-width', data.adaptContainerWidth); + return container; +} + /** * Create DOM element for the Facebook comments plugin: * Reference: https://developers.facebook.com/docs/plugins/comments @@ -104,7 +125,10 @@ function getLikeContainer(global, data) { export function facebook(global, data) { const extension = global.context.tagName; let container; - if (extension === 'AMP-FACEBOOK-LIKE') { + + if (extension === 'AMP-FACEBOOK-PAGE') { + container = getPageContainer(global, data); + } else if (extension === 'AMP-FACEBOOK-LIKE') { container = getLikeContainer(global, data); } else if (extension === 'AMP-FACEBOOK-COMMENTS') { container = getCommentsContainer(global, data); @@ -126,5 +150,5 @@ export function facebook(global, data) { }); FB.init({xfbml: true, version: 'v2.5'}); - }); + }, data.locale ? data.locale : dashToUnderline(window.navigator.language)); } diff --git a/3p/frame-metadata.js b/3p/frame-metadata.js index baae596b103c..2292975e84f2 100644 --- a/3p/frame-metadata.js +++ b/3p/frame-metadata.js @@ -155,7 +155,7 @@ export function getContextState() { startTime: rawContext['startTime'], tagName: rawContext['tagName'], }; -}; +} /** diff --git a/3p/iframe-transport-client-lib.js b/3p/iframe-transport-client-lib.js index 504c072f2a0f..7a635e4a717b 100644 --- a/3p/iframe-transport-client-lib.js +++ b/3p/iframe-transport-client-lib.js @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import './polyfills'; + +// src/polyfills.js must be the first import. +import './polyfills'; // eslint-disable-line sort-imports-es6-autofix/sort-imports-es6 + import {IframeTransportClient} from './iframe-transport-client.js'; import {initLogConstructor, setReportError} from '../src/log'; diff --git a/3p/integration.js b/3p/integration.js index 24788c29ed0e..e697bbb1c298 100644 --- a/3p/integration.js +++ b/3p/integration.js @@ -22,7 +22,9 @@ * https://3p.ampproject.net/$version/f.js */ -import './polyfills'; +// src/polyfills.js must be the first import. +import './polyfills'; // eslint-disable-line sort-imports-es6-autofix/sort-imports-es6 + import {AmpEvents} from '../src/amp-events'; import { IntegrationAmpContext, @@ -460,7 +462,7 @@ export function draw3p(win, data, configCallback) { } else { run(type, win, data); } -}; +} /** * @return {boolean} Whether this is the master iframe. diff --git a/3p/nameframe.max.html b/3p/nameframe.max.html index 49aed4323388..1df56224831e 100644 --- a/3p/nameframe.max.html +++ b/3p/nameframe.max.html @@ -3,26 +3,48 @@
- + + diff --git a/3p/twitter.js b/3p/twitter.js index 362eff28c580..2bedeacc94ac 100644 --- a/3p/twitter.js +++ b/3p/twitter.js @@ -122,4 +122,4 @@ export function cleanupTweetId_(tweetid) { } return tweetid; -}; +} diff --git a/ads/_config.js b/ads/_config.js index a8572ff72e4d..cf0f2253791e 100644 --- a/ads/_config.js +++ b/ads/_config.js @@ -232,6 +232,7 @@ export const adConfig = { appnexus: { prefetch: 'https://acdn.adnxs.com/ast/ast.js', preconnect: 'https://ib.adnxs.com', + renderStartImplemented: true, }, atomx: { diff --git a/ads/google/a4a/docs/a4a-readme.md b/ads/google/a4a/docs/a4a-readme.md index 0e471db1c2fd..918fbf9b0607 100644 --- a/ads/google/a4a/docs/a4a-readme.md +++ b/ads/google/a4a/docs/a4a-readme.md @@ -1,34 +1,34 @@ -# AMP Ads +# AMPHTML ads -AMP Ads applies AMP’s core philosophy of reliable fast performance and great user experience to ads. +AMPHTML ads applies AMP’s core philosophy of reliable fast performance and great user experience to ads. -# AMP Ads +# AMPHTML ads -AMP Ads are written in AMP format - [A4A HTML](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/amp-a4a-format.md) (A variant of AMP HTML) + CSS. This means that ads can no longer have the ability to run arbitrary JavaScript - which is traditionally the number one cause of poor ad performance. Therefore, just like core AMP, the core ads JavaScript use-cases are built right into the AMP Open Source project which guarantees good behavior from ads. +AMPHTML ads are written in AMP format - [A4A HTML](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/amp-a4a-format.md) (A variant of AMP HTML) + CSS. This means that ads can no longer have the ability to run arbitrary JavaScript - which is traditionally the number one cause of poor ad performance. Therefore, just like core AMP, the core ads JavaScript use-cases are built right into the AMP Open Source project which guarantees good behavior from ads. -# Why are AMP Ads better than regular ads? +# Why are AMPHTML ads better than regular ads? ### Faster -AMP Ads are faster because on AMP pages they are requested early while rendering the page and immediately displayed just before the user is about to view the ad. Reduced file size of AMP Ads also increases speed. +AMPHTML ads are faster because on AMP pages they are requested early while rendering the page and immediately displayed just before the user is about to view the ad. Reduced file size of AMPHTML ads also increases speed. ### More Aware -On AMP pages, the AMP runtime can coordinate a mobile phone's limited resources to the right component at the right time to give the best user experience. For example, AMP Ads with animations are paused when not in the current viewport. +On AMP pages, the AMP runtime can coordinate a mobile phone's limited resources to the right component at the right time to give the best user experience. For example, AMPHTML ads with animations are paused when not in the current viewport. ### Lighter -AMP Ads bundle commonly used ad functionality which removes bloat. Once on the page, AMP Ads also consume less resources. For example, instead of 10 trackers requesting their own information in regular ads, AMP Ads collect all the information once and distribute it to any number of interested trackers. +AMPHTML ads bundle commonly used ad functionality which removes bloat. Once on the page, AMPHTML ads also consume less resources. For example, instead of 10 trackers requesting their own information in regular ads, AMPHTML ads collect all the information once and distribute it to any number of interested trackers. ### More Engaging "Users can't tap on ads they can't see". Faster ads lead to higher viewability and therefore higher click through rates, which ultimately leads to higher advertiser conversions. ### Safer -It's impossible to spread malware through advertising with AMP Ads. Not only are visitors safer, but advertiser brand perception cannot be negative.` +It's impossible to spread malware through advertising with AMPHTML ads. Not only are visitors safer, but advertiser brand perception cannot be negative.` ### More Flexible -AMP Ads are designed to work on both AMP and Non-AMP webpages, including desktop where the ad tagging library supports it. (e.g. GPT) +AMPHTML ads are designed to work on both AMP and Non-AMP webpages, including desktop where the ad tagging library supports it. (e.g. GPT) # Current status -The AMP Ads format spec has been [released](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/amp-a4a-format.md) and any creative developer can create AMP Ads. A number of ad providers are working on automatically converting ads to AMP Ads whenever possible. e.g. AdSense. +The AMPHTML ads format spec has been [released](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/amp-a4a-format.md) and any creative developer can create AMPHTML ads. A number of ad providers are working on automatically converting ads to AMPHTML ads whenever possible. e.g. AdSense. Here is how you can participate. If you are: @@ -36,7 +36,7 @@ Here is how you can participate. If you are: If publishers want to serve their direct-sold ad formats they must create the ads in [A4A format](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/amp-a4a-format.md) (or use a creative agency), and deliver them using an AMP Ad supported ad server. -The following adservers support serving AMP Ads at the moment: +The following adservers support serving AMPHTML ads at the moment: 1. DoubleClick for Publishers 2. TripleLift 3. Dianomi @@ -48,7 +48,7 @@ Fast Fetch supports Real Time Config: publisher-specified, multiple, simultaneou ## Creative Agencies -If you are a creative agency, please express interest via [this form](https://goo.gl/forms/P2zpQT3aIEU1UsWj2) so we can include you in any outreach that's AMP Ads-related. +If you are a creative agency, please express interest via [this form](https://goo.gl/forms/P2zpQT3aIEU1UsWj2) so we can include you in any outreach that's AMPHTML-related. ## Ad Networks/ Ad Servers @@ -60,27 +60,27 @@ Ad networks and ad servers can integrate with [Cloudflare](https://blog.cloudfla #### Are there any AMP Ad samples? Yes. A number of great looking ads developed in AMP format can be found [here](https://ampbyexample.com/amp-ads/#amp-ads/experimental_ads). They use advanced components in AMP. They give the user a great experience while ensuring that the performance remains great. -#### Are there any tools to create AMP Ads? -Yes. [Celtra](http://www.prnewswire.com/news-releases/celtra-partners-with-the-amp-project-showcases-amp-ad-creation-at-google-io-event-300459514.html) provides out of the box support for AMP ads in their ad creator platform. Other tools like [Google Web Designer](https://www.google.com/webdesigner/) are also in the process of adding support. +#### Are there any tools to create ads in AMPHTML? +Yes. [Celtra](http://www.prnewswire.com/news-releases/celtra-partners-with-the-amp-project-showcases-amp-ad-creation-at-google-io-event-300459514.html) provides out of the box support for AMPHTML ads in their ad creator platform. Other tools like [Google Web Designer](https://www.google.com/webdesigner/) are also in the process of adding support. #### How can I verify that an AMP Ad is valid? Depending on your development environment, there are a few options: - Use the [AMP validator NPM](https://www.npmjs.com/package/amphtml-validator) module to build your own - Use the [AMP validator](https://validator.ampproject.org/) for one off testing - Partner with [Cloudflare](https://blog.cloudflare.com/firebolt/) and use their public validator end point. -On AMP pages, AMP ads must be valid in order to get them to render quickly. If not, the ads will still render but slower. +On AMP pages, AMPHTML ads must be valid in order to get them to render quickly. If not, the ads will still render but slower. -#### Do AMP Ads support 3rd party verification and viewability detection? +#### Do AMPHTML ads support 3rd party verification and viewability detection? Yes, there is native support for verification and viewability detection using amp-analytics. (e.g. Google’s ActiveView integrates this way). There are also other vendors like MOAT that are actively implementing support for it. -#### Does AMP Ads support timeline based animation? +#### Does AMPHTML ads support timeline based animation? Yes. Learn more about it [here](https://github.com/ampproject/amphtml/blob/master/extensions/amp-animation/amp-animation.md). -#### Most ads have tappable targets and configurable ad exits. Does AMP Ads have a similar mechanism? +#### Most ads have tappable targets and configurable ad exits. Does AMPHTML ads have a similar mechanism? Yes. Learn more about it [here](https://github.com/ampproject/amphtml/blob/master/extensions/amp-ad-exit/amp-ad-exit.md). -#### Where can I learn more about AMP Ads? +#### Where can I learn more about AMPHTML ads? The public [website](https://ampproject.org/ads) is a good place to start. #### I can’t find what I need, where can I ask questions? diff --git a/ads/google/a4a/test/test-performance.js b/ads/google/a4a/test/test-performance.js index ebdaa8cf8117..b4775e78a7e6 100644 --- a/ads/google/a4a/test/test-performance.js +++ b/ads/google/a4a/test/test-performance.js @@ -217,7 +217,7 @@ describe('GoogleAdLifecycleReporter', () => { /&st=30/.test(src)); slotCounts[slotId] = slotCounts[slotId] || 0; ++slotCounts[slotId]; - }; + } // SlotId 0 corresponds to unusedReporter, so ignore it. for (let s = 1; s <= nSlots; ++s) { expect(slotCounts[s], 'slotCounts[' + s + ']').to.equal(nStages); diff --git a/ads/google/a4a/test/test-utils.js b/ads/google/a4a/test/test-utils.js index a59c6a2c2ced..e529debac397 100644 --- a/ads/google/a4a/test/test-utils.js +++ b/ads/google/a4a/test/test-utils.js @@ -34,7 +34,7 @@ import { } from '../utils'; import { MockA4AImpl, -} from '../../../../extensions/amp-a4a/0.1/test/utils';; +} from '../../../../extensions/amp-a4a/0.1/test/utils'; import {Services} from '../../../../src/services'; import {buildUrl} from '../url-builder'; import {createElementWithAttributes} from '../../../../src/dom'; diff --git a/ads/google/a4a/utils.js b/ads/google/a4a/utils.js index 0327de7f143b..23a7f3473209 100644 --- a/ads/google/a4a/utils.js +++ b/ads/google/a4a/utils.js @@ -80,6 +80,11 @@ export const EXPERIMENT_ATTRIBUTE = 'data-experiment-id'; */ export let AmpAnalyticsConfigDef; +/** + * @typedef {{instantLoad: boolean, writeInBody: boolean}} + */ +export let NameframeExperimentConfig; + /** * @const {!./url-builder.QueryParameterDef} * @visibleForTesting @@ -426,7 +431,7 @@ export function additionalDimensions(win, viewportSize) { outerHeight, innerWidth, innerHeight].join(); -}; +} /** * Returns amp-analytics config for a new CSI trigger. @@ -727,7 +732,7 @@ export function getIdentityToken(win, nodeOrDoc) { win['goog_identity_prom'] = win['goog_identity_prom'] || executeIdentityTokenFetch(win, nodeOrDoc); return /** @type {!Promise} */(win['goog_identity_prom']); -}; +} /** * @param {!Window} win @@ -794,7 +799,7 @@ export function getIdentityTokenRequestUrl(win, nodeOrDoc, domain = undefined) { const canonical = parseUrl(Services.documentInfoForDoc(nodeOrDoc).canonicalUrl).hostname; return `https://adservice${domain}/adsid/integrator.json?domain=${canonical}`; -}; +} /** * Returns whether we are running on the AMP CDN. @@ -806,3 +811,19 @@ export function isCdnProxy(win) { /^https:\/\/([a-zA-Z0-9_-]+\.)?cdn\.ampproject\.org((\/.*)|($))+/; return googleCdnProxyRegex.test(win.location.origin); } + +/** + * Populates the fields of the given Nameframe experiment config object. + * @param {!../../../src/service/xhr-impl.FetchResponseHeaders} headers + * @param {!NameframeExperimentConfig} nameframeConfig + */ +export function setNameframeExperimentConfigs(headers, nameframeConfig) { + const nameframeExperimentHeader = headers.get('amp-nameframe-exp'); + if (nameframeExperimentHeader) { + nameframeExperimentHeader.split(';').forEach(config => { + if (config == 'instantLoad' || config == 'writeInBody') { + nameframeConfig[config] = true; + } + }); + } +} diff --git a/ads/google/adsense-amp-auto-ads.js b/ads/google/adsense-amp-auto-ads.js index d71247d1cf47..30fb59389e72 100644 --- a/ads/google/adsense-amp-auto-ads.js +++ b/ads/google/adsense-amp-auto-ads.js @@ -60,4 +60,4 @@ export function getAdSenseAmpAutoAdsExpBranch(win) { randomlySelectUnsetExperiments(win, experiments); return getExperimentBranch(win, ADSENSE_AMP_AUTO_ADS_HOLDOUT_EXPERIMENT_NAME) || null; -}; +} diff --git a/ads/google/imaVideo.js b/ads/google/imaVideo.js index edf32d4842c7..776acfd76778 100644 --- a/ads/google/imaVideo.js +++ b/ads/google/imaVideo.js @@ -812,7 +812,7 @@ function getPagePosition(el) { el != null; lx += el./*OK*/offsetLeft, ly += el./*OK*/offsetTop, el = el./*OK*/offsetParent) - {}; + {} return {x: lx,y: ly}; } diff --git a/ads/google/test/test-doubleclick.js b/ads/google/test/test-doubleclick.js index bbab941a7bcb..c7a8baa8f221 100644 --- a/ads/google/test/test-doubleclick.js +++ b/ads/google/test/test-doubleclick.js @@ -30,7 +30,7 @@ function verifyScript(win, name) { .to.equal(script == name); } }); -}; +} describes.sandboxed('writeAdScript', {}, env => { diff --git a/ads/imedia.js b/ads/imedia.js index f02dd7706221..ef34f61d2453 100644 --- a/ads/imedia.js +++ b/ads/imedia.js @@ -73,4 +73,4 @@ export function imedia(global, data) { return used; // remove (filter) element filled with add }); }); -}; +} diff --git a/ads/ix.js b/ads/ix.js index a7771c5325a7..e0d6d4f81bbd 100644 --- a/ads/ix.js +++ b/ads/ix.js @@ -106,5 +106,5 @@ function reportStats(siteID, slotID, dfpSlot, start, code) { xhttp.open('POST', url, true); xhttp.setRequestHeader('Content-Type', 'application/json'); xhttp.send(stats); - } catch (e) {}; + } catch (e) {} } diff --git a/ads/navegg.js b/ads/navegg.js index 306cc00ed9ef..c936668b2308 100644 --- a/ads/navegg.js +++ b/ads/navegg.js @@ -35,7 +35,7 @@ export function navegg(global, data) { nvg.getProfile(nvgTargeting => { for (seg in nvgTargeting) { data.targeting[seg] = nvgTargeting[seg]; - }; + } doubleclick(global, data); }); }); diff --git a/ads/netletix.js b/ads/netletix.js index ce1df1217a76..23413d7b4ac5 100644 --- a/ads/netletix.js +++ b/ads/netletix.js @@ -73,7 +73,7 @@ export function netletix(global, data) { if (event.data.width && event.data.height && (event.data.width != nxw || event.data.height != nxh)) { global.context.requestResize(event.data.width, event.data.height); - }; + } break; case 'nx-empty': global.context.noContentAvailable(); diff --git a/ads/pubmine.js b/ads/pubmine.js index 9737aa4d7669..c713fdb3d919 100644 --- a/ads/pubmine.js +++ b/ads/pubmine.js @@ -14,10 +14,9 @@ * limitations under the License. */ -import {getSourceOrigin, getSourceUrl} from '../src/url'; import {validateData, writeScript} from '../3p/3p'; -const pubmineOptional = ['adsafe', 'section', 'wordads'], +const pubmineOptional = ['section', 'pt', 'ht'], pubmineRequired = ['siteid'], pubmineURL = 'https://s.pubmine.com/head.js'; @@ -28,28 +27,39 @@ const pubmineOptional = ['adsafe', 'section', 'wordads'], export function pubmine(global, data) { validateData(data, pubmineRequired, pubmineOptional); - global._ipw_custom = { // eslint-disable-line google-camelcase/google-camelcase - adSafe: 'adsafe' in data ? data.adsafe : '0', - amznPay: [], - domain: getSourceOrigin(global.context.location.href), - pageURL: getSourceUrl(global.context.location.href), - wordAds: 'wordads' in data ? data.wordads : '0', + global.__ATA_PP = { renderStartCallback: () => global.context.renderStart(), + pt: 'pt' in data ? data.pt : 1, + ht: 'ht' in data ? data.ht : 1, + tn: 'amp', + amp: true, }; + + global.__ATA = global.__ATA || {}; + global.__ATA.cmd = global.__ATA.cmd || []; + global.__ATA.criteo = global.__ATA.criteo || {}; + global.__ATA.criteo.cmd = global.__ATA.criteo.cmd || []; writeScript(global, pubmineURL); const o = { sectionId: data['siteid'] + ('section' in data ? data.section : '1'), - height: data.height, + height: data.height == 250 ? 250 : data.height - 15, width: data.width, }, wr = global.document.write; wr.call(global.document, - `` + ` ` ); } diff --git a/ads/pubmine.md b/ads/pubmine.md index 033ebf5d6609..3d3aafcd2475 100644 --- a/ads/pubmine.md +++ b/ads/pubmine.md @@ -21,7 +21,7 @@ limitations under the License. ### Basic ```html - block (illustrative, and not always valid)
filteredMarkdown = filteredMarkdown.replace(/(.*?)<\/code>/g, '');
+ // The heroku nightly build page is not always acccessible by the checker.
+ filteredMarkdown = filteredMarkdown.replace(
+ /\(http:\/\/amphtml-nightly.herokuapp.com\/\)/g, '');
+
// After all whitelisting is done, clean up any remaining empty blocks bounded
// by backticks. Otherwise, `` will be treated as the start of a code block
// and confuse the link extractor.
diff --git a/build-system/tasks/lint.js b/build-system/tasks/lint.js
index b4fc78676899..1ca7c31a2eee 100644
--- a/build-system/tasks/lint.js
+++ b/build-system/tasks/lint.js
@@ -58,6 +58,17 @@ function initializeStream(globs, streamOptions) {
return stream;
}
+/**
+ * Logs a message on the same line to indicate progress
+ * @param {string} message
+ */
+function logOnSameLine(message) {
+ process.stdout.moveCursor(0, -1);
+ process.stdout.cursorTo(0);
+ process.stdout.clearLine();
+ log(message);
+}
+
/**
* Runs the linter on the given stream using the given options.
* @param {string} path
@@ -67,12 +78,31 @@ function initializeStream(globs, streamOptions) {
*/
function runLinter(path, stream, options) {
let errorsFound = false;
+ if (!process.env.TRAVIS) {
+ log(colors.green('Starting linter...'));
+ }
return stream.pipe(eslint(options))
.pipe(eslint.formatEach('stylish', function(msg) {
errorsFound = true;
- log(msg);
+ logOnSameLine(colors.red('Linter error:') + msg + '\n');
}))
.pipe(gulpIf(isFixed, gulp.dest(path)))
+ .pipe(eslint.result(function(result) {
+ if (!process.env.TRAVIS) {
+ logOnSameLine(colors.green('Linting: ') + result.filePath);
+ }
+ }))
+ .pipe(eslint.results(function(results) {
+ if (results.errorCount == 0) {
+ if (!process.env.TRAVIS) {
+ logOnSameLine(colors.green('Success: ') + 'No linter errors');
+ }
+ } else {
+ logOnSameLine(colors.red('Error: ') + results.errorCount +
+ ' linter error(s) found.');
+ process.exit(1);
+ }
+ }))
.pipe(eslint.failAfterError())
.on('error', function() {
if (errorsFound && !options.fix) {
diff --git a/build-system/tasks/package.json b/build-system/tasks/package.json
deleted file mode 100644
index 5c91c7998c7f..000000000000
--- a/build-system/tasks/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "dependencies": {
- "markdown-link-check": "^3.0.3"
- }
-}
diff --git a/build-system/tasks/presubmit-checks.js b/build-system/tasks/presubmit-checks.js
index 22ea6e644fd7..ab756776f00d 100644
--- a/build-system/tasks/presubmit-checks.js
+++ b/build-system/tasks/presubmit-checks.js
@@ -90,15 +90,17 @@ const forbiddenTerms = {
' If this is cross domain, overwrite the method directly.',
},
'console\\.\\w+\\(': {
- message: 'If you run against this, use console/*OK*/.log to ' +
+ message: 'If you run against this, use console/*OK*/.[log|error] to ' +
'whitelist a legit case.',
whitelist: [
'build-system/pr-check.js',
'build-system/app.js',
+ 'build-system/check-package-manager.js',
'validator/nodejs/index.js', // NodeJs only.
'validator/engine/parse-css.js',
'validator/engine/validator-in-browser.js',
'validator/engine/validator.js',
+ 'gulpfile.js',
],
checkInTestFolder: true,
},
@@ -514,7 +516,7 @@ const forbiddenTerms = {
message: 'requireLayout is restricted b/c it affects non-contained elements', // eslint-disable-line max-len
whitelist: [
'extensions/amp-animation/0.1/web-animations.js',
- 'extensions/amp-lightbox-viewer/0.1/amp-lightbox-viewer.js',
+ 'extensions/amp-lightbox-gallery/0.1/amp-lightbox-gallery.js',
'src/service/resources-impl.js',
],
},
@@ -575,6 +577,7 @@ const forbiddenTerms = {
'src/worker-error-reporting.js',
'tools/experiments/experiments.js',
'build-system/amp4test.js',
+ 'gulpfile.js',
],
},
'data:image/svg(?!\\+xml;charset=utf-8,)[^,]*,': {
@@ -619,6 +622,7 @@ const forbiddenTerms = {
message: 'Use a line-level "no-unused-vars" rule instead.',
whitelist: [
'viewer-api/swipe-api.js',
+ 'dist.3p/current/integration.js',
],
},
};
@@ -753,7 +757,7 @@ const forbiddenTermsSrcInclusive = {
'extensions/amp-a4a/0.1/amp-a4a.js',
'extensions/amp-ad-network-adsense-impl/0.1/amp-ad-network-adsense-impl.js', // eslint-disable-line max-len
'extensions/amp-ad-network-doubleclick-impl/0.1/amp-ad-network-doubleclick-impl.js', // eslint-disable-line max-len
- 'extensions/amp-lightbox-viewer/0.1/amp-lightbox-viewer.js',
+ 'extensions/amp-lightbox-gallery/0.1/amp-lightbox-gallery.js',
],
},
'loadElementClass': {
@@ -843,6 +847,7 @@ const forbiddenTermsSrcInclusive = {
'validator/webui/serve-standalone.go',
'build-system/tasks/check-links.js',
'build-system/tasks/extension-generator/index.js',
+ 'gulpfile.js',
],
},
'\\<\\<\\<\\<\\<\\<': {
diff --git a/build-system/tasks/runtime-test.js b/build-system/tasks/runtime-test.js
index 9657f96e35b8..244e1dc2b13b 100644
--- a/build-system/tasks/runtime-test.js
+++ b/build-system/tasks/runtime-test.js
@@ -20,15 +20,14 @@ const applyConfig = require('./prepend-global/index.js').applyConfig;
const argv = require('minimist')(process.argv.slice(2));
const colors = require('ansi-colors');
const config = require('../config');
+const exec = require('../exec').exec;
const fs = require('fs');
-const glob = require('glob');
const gulp = require('gulp-help')(require('gulp'));
const Karma = require('karma').Server;
const karmaDefault = require('./karma.conf');
const log = require('fancy-log');
const path = require('path');
const removeConfig = require('./prepend-global/index.js').removeConfig;
-const shuffleSeed = require('shuffle-seed');
const webserver = require('gulp-webserver');
@@ -37,7 +36,8 @@ const yellow = colors.yellow;
const cyan = colors.cyan;
const red = colors.red;
-const preTestTasks = argv.nobuild ? [] : (argv.unit ? ['css'] : ['build']);
+const preTestTasks =
+ argv.nobuild ? [] : ((argv.unit || argv.a4a) ? ['css'] : ['build']);
const ampConfig = (argv.config === 'canary') ? 'canary' : 'prod';
@@ -124,6 +124,11 @@ function getAdTypes() {
return adTypes;
}
+// Mitigates https://github.com/karma-runner/karma-sauce-launcher/issues/117
+// by refreshing the wd cache so that Karma can launch without an error.
+function refreshKarmaWdCache() {
+ exec('node ./node_modules/wd/scripts/build-browser-scripts.js');
+}
/**
* Prints help messages for args if tests are being run for local development.
@@ -146,9 +151,7 @@ function printArgvMessages() {
cyan('gulp build') + ' to have been run first.',
unit: 'Running only the unit tests. Requires ' +
cyan('gulp css') + ' to have been run first.',
- randomize: 'Randomizing the order in which tests are run.',
a4a: 'Running only A4A tests.',
- seed: 'Randomizing test order with seed ' + cyan(argv.seed) + '.',
compiled: 'Running tests against minified code.',
grep: 'Only running tests that match the pattern "' +
cyan(argv.grep) + '".',
@@ -242,30 +245,8 @@ function runTests() {
} else {
c.files = c.files.concat(config.unitTestPaths);
}
-
- } else if (argv.randomize || argv.glob || argv.a4a) {
- const testPaths = argv.a4a ? config.a4aTestPaths : config.basicTestPaths;
-
- let testFiles = [];
- for (const index in testPaths) {
- testFiles = testFiles.concat(glob.sync(testPaths[index]));
- }
-
- if (argv.randomize || argv.a4a) {
- const seed = argv.seed || Math.random();
- log(
- yellow('Randomizing:'),
- cyan('Seeding with value', seed));
- log(
- yellow('To rerun same ordering, append'),
- cyan(`--seed=${seed}`),
- yellow('to your invocation of'),
- cyan('gulp test'));
- testFiles = shuffleSeed.shuffle(testFiles, seed);
- }
-
- testFiles.splice(testFiles.indexOf('test/_init_tests.js'), 1);
- c.files = c.files.concat(config.commonTestPaths.concat(testFiles));
+ } else if (argv.a4a) {
+ c.files = c.files.concat(config.a4aTestPaths);
} else {
c.files = c.files.concat(config.testPaths);
}
@@ -345,6 +326,7 @@ function runTests() {
let resolver;
const deferred = new Promise(resolverIn => {resolver = resolverIn;});
+ refreshKarmaWdCache();
new Karma(c, function(exitCode) {
server.emit('kill');
if (exitCode) {
@@ -412,11 +394,6 @@ gulp.task('test', 'Runs tests', preTestTasks, function() {
'binaries for execution',
'grep': ' Runs tests that match the pattern',
'files': ' Runs tests for specific files',
- 'randomize': ' Runs entire test suite in random order',
- 'seed': ' Seeds the test order randomization. Use with --randomize ' +
- 'or --a4a',
- 'glob': ' Explicitly expands test paths using glob before passing ' +
- 'to Karma',
'nohelp': ' Silence help messages that are printed prior to test run',
'a4a': ' Runs all A4A tests',
'config': ' Sets the runtime\'s AMP config to one of "prod" or "canary"',
diff --git a/builtins/amp-img.js b/builtins/amp-img.js
index 662b9b0f05d1..0db6faabe7be 100644
--- a/builtins/amp-img.js
+++ b/builtins/amp-img.js
@@ -222,7 +222,7 @@ export class AmpImg extends BaseElement {
this.togglePlaceholder(false);
});
}
-};
+}
/**
* @param {!Window} win Destination window for the new element.
diff --git a/caches.json b/caches.json
index fac75defb692..3c4b221b195d 100644
--- a/caches.json
+++ b/caches.json
@@ -5,6 +5,12 @@
"name": "Google AMP Cache",
"docs": "https://developers.google.com/amp/cache/",
"updateCacheApiDomainSuffix": "cdn.ampproject.org"
+ },
+ {
+ "id": "cloudflare",
+ "name": "Cloudflare AMP Cache",
+ "docs": "https://amp.cloudflare.com/",
+ "updateCacheApiDomainSuffix": "amp.cloudflare.com"
}
]
}
diff --git a/contributing/DEVELOPING.md b/contributing/DEVELOPING.md
index 148604d02ec7..d15db4fd895b 100644
--- a/contributing/DEVELOPING.md
+++ b/contributing/DEVELOPING.md
@@ -36,8 +36,12 @@ The Quick Start Guide's [One-time setup](getting-started-quick.md#one-time-setu
| ----------------------------------------------------------------------- | --------------------------------------------------------------------- |
| **`gulp`**[[1]](#footnote-1) | Runs "watch" and "serve". Use this for standard local dev. |
| `gulp --extensions=` | Runs "watch" and "serve", after building only the listed extensions.
+| `gulp --extensions=minimal_set` | Runs "watch" and "serve", after building the extensions needed to load `article.amp.html`.
| `gulp --noextensions` | Runs "watch" and "serve" without building any extensions.
| `gulp dist`[[1]](#footnote-1) | Builds production binaries. |
+| `gulp dist --extensions=` | Builds production binaries, with only the listed extensions.
+| `gulp dist --extensions=minimal_set` | Builds production binaries, with only the extensions needed to load `article.amp.html`.
+| `gulp dist --noextensions` | Builds production binaries without building any extensions.
| `gulp dist --fortesting`[[1]](#footnote-1) | Builds production binaries for local testing. (Allows use cases like ads, tweets, etc. to work with minified sources. Overrides `TESTING_HOST` if specified. Uses the production `AMP_CONFIG` by default.) |
| `gulp dist --fortesting --config=`[[1]](#footnote-1) | Builds production binaries for local testing, with the specified `AMP_CONFIG`. `config` can be `prod` or `canary`. (Defaults to `prod`.) |
| `gulp lint` | Validates against Google Closure Linter. |
@@ -45,12 +49,14 @@ The Quick Start Guide's [One-time setup](getting-started-quick.md#one-time-setu
| `gulp lint --fix` | Fixes simple lint warnings/errors automatically. |
| `gulp build`[[1]](#footnote-1) | Builds the AMP library. |
| `gulp build --extensions=` | Builds the AMP library, with only the listed extensions.
+| `gulp build --extensions=minimal_set` | Builds the AMP library, with only the extensions needed to load `article.amp.html`.
| `gulp build --noextensions` | Builds the AMP library with no extensions.
| `gulp check-links --files foo.md,bar.md` | Reports dead links in `.md` files. |
| `gulp clean` | Removes build output. |
| `gulp css`[[1]](#footnote-1) | Recompiles css to build directory and builds the embedded css into js files for the AMP library. |
| `gulp watch`[[1]](#footnote-1) | Watches for changes in files, re-builds. |
| `gulp watch --extensions=` | Watches for changes in files, re-builds only the listed extensions.
+| `gulp watch --extensions=minimal_set` | Watches for changes in files, re-builds only the extensions needed to load `article.amp.html`.
| `gulp watch --noextensions` | Watches for changes in files, re-builds with no extensions.
| `gulp pr-check`[[1]](#footnote-1) | Runs all the Travis CI checks locally. |
| `gulp pr-check --nobuild`[[1]](#footnote-1) | Runs all the Travis CI checks locally, but skips the `gulp build` step. |
@@ -192,8 +198,6 @@ To run the tests on Sauce Labs:
```
* It may take a few minutes for the tests to start. You can see the status of your tests on the Sauce Labs [Automated Tests](https://saucelabs.com/beta/dashboard/tests) dashboard. (You can also see the status of your proxy on the [Tunnels](https://saucelabs.com/beta/tunnels) dashboard.
-* If you see "Cannot find module '../build/safe-execute'", this is caused by a caching issue - try uninstalling and reinstalling the 'wd' module as described in [karma-sauce-launcher issue #117](https://github.com/karma-runner/karma-sauce-launcher/issues/117).
-
## Visual Diff Tests
**NOTE:** *We are working on giving all `ampproject/amphtml` committers automatic access to visual diff test results. Until this is in place, you can fill out [this](https://docs.google.com/forms/d/e/1FAIpQLScZma6qVJtYUTqSm4KtiF3Zc-n5ukNe2GXNFqnaHxospsz0sQ/viewform) form, and your request should be approved soon.*
diff --git a/contributing/getting-started-e2e.md b/contributing/getting-started-e2e.md
index 233f67f871d0..f84c03260d14 100644
--- a/contributing/getting-started-e2e.md
+++ b/contributing/getting-started-e2e.md
@@ -148,14 +148,21 @@ git remote add upstream git@github.com:ampproject/amphtml.git
Now run `git remote -v` again and notice that you have set up your upstream alias.
+Each branch of your local Git repository can track a branch of a remote repository. Right now, your local `master` branch is tracking `origin/master`, which corresponds to the `master` branch of your GitHub fork. You don't actually want this, though; the upstream `master` branch is constantly being updated, and your fork's `master` branch will rapidly become outdated. Instead, it's best to make your local `master` branch track the upstream `master` branch. You can do this like so:
+
+```
+git branch -u upstream/master master
+```
+
# Building AMP and starting a local server
Now that you have all of the files copied locally you can actually build the code and run a local server to try things out.
amphtml uses Node.js, the Yarn package manager and the Gulp build system to build amphtml and start up a local server that lets you try out your changes. Installing these and getting amphtml built is straightforward:
-* Install [NodeJS](https://nodejs.org/) version >= 6 (which includes npm)
+* Install [Node.js](https://nodejs.org/) version >= 6 (which includes npm).
+ [NVM](https://github.com/creationix/nvm) is a convenient way to do this on Mac and Linux, especially if you have other projects that require different versions of Node.
* Install [Yarn](https://yarnpkg.com/) version >= 1.2.0 (instructions [here](https://yarnpkg.com/en/docs/install), this may require elevated privileges using `sudo` on some platforms)
@@ -169,7 +176,9 @@ amphtml uses Node.js, the Yarn package manager and the Gulp build system to buil
You can do this by adding this line to your hosts file (`/etc/hosts` on Mac or Linux, `%SystemRoot%\System32\drivers\etc\hosts` on Windows):
- ```127.0.0.1 ads.localhost iframe.localhost```
+ ```
+ 127.0.0.1 ads.localhost iframe.localhost
+ ```
* The AMP Project uses Gulp as our build system. Gulp uses a configuration file ([gulpfile.js](https://github.com/ampproject/amphtml/blob/master/gulpfile.js)) to build amphtml (including the amphtml javascript) and to start up the Node.js server with the proper settings. You don't really have to understand exactly what it is doing at this point--you just have to install it and use it.
@@ -220,10 +229,14 @@ By default you'll have a branch named _master_. You can see this if you run the
Although you could do work on the master branch, most people choose to leave the master branch unchanged and create other branches to actually do work in. Creating a branch is easy; simply run:
```
-git branch --track origin/master
+git checkout -b master
```
-Whenever you want to do work in this branch, run the checkout command:
+This will move you to the new branch, which uses `master` as its start point, meaning that it will start out containing the same files as `master`. You can then start working in the new branch.
+
+(You can use a different branch as a start point, like if you want to make one branch based on another. Generally, though, you want `master` as your start point. If you omit the start point, Git will use whichever branch you're currently on.)
+
+Whenever you want to move to a different branch, run the checkout command:
```
git checkout
@@ -235,22 +248,20 @@ You can see a list of your branches and which one you're currently in by running
git branch
```
-When you created the branch the `--track` flag and `origin/master` part are a convenience for telling Git the default place you want to sync with in the future. Remember _origin_ is the alias that was set up for your GitHub fork remote repository. _origin/master_ is "the master branch of the origin repository."
-
Note that currently the branch you just created only exists in your local repository. If you check the list of branches that exist on your GitHub fork at `https://github.com//amphtml/branches/yours`, you won't see this new branch listed. Later on when we want to make the changes in your branch visible to others (e.g. so you can do a pull request) we'll push this branch to your GitHub fork.
# Pull the latest changes from the amphtml repository
Since your local repository is just a copy of the amphtml repository it can quickly become out of date if other people make changes to the amphtml repository. Before you start making changes you'll want to make sure you have the latest version of the code; you'll also want to do this periodically during development, before sending your code for review, etc.
-In the workflow we will be using you'll go to the master branch on your local repository and pull the latest changes in from the remote amphtml repository's master branch. (Remember that you set up the alias _upstream_ to refer to the remote amphtml repository.)
+In the workflow we will be using you'll go to the master branch on your local repository and pull the latest changes in from the remote amphtml repository's master branch. (Remember that you set up the alias _upstream_ to refer to the remote amphtml repository, and you set your local `master` branch to track `upstream/master`.)
```
# make sure you are in your local repo's master branch
git checkout master
# pull in the latest changes from the remote amphtml repository
-git pull upstream master
+git pull
```
If there have been any changes you'll see the details of what changed, otherwise you'll see a message like `Already up-to-date`.
@@ -399,15 +410,21 @@ Before pushing your changes, make sure you have the latest changes in the amphtm
```
git checkout master
-git pull upstream master
+git pull
git checkout
git rebase master
```
-Now push your changes to origin (the alias for your GitHub fork):
+Now push your changes to `origin` (the alias for your GitHub fork):
+
+```
+git push -u origin
+```
+
+`-u origin ` tells Git to create a remote branch with the specified name in `origin` and to make your local branch track that remote branch from now on. You only have to do this the first time you push each branch. For subsequent pushes on the same branch, you can use a shorter command:
```
-git push origin
+git push
```
The changes you've made are now visible on GitHub! Go to your fork on GitHub:
@@ -485,7 +502,7 @@ git checkout master
git branch -D
# delete the branch in your GitHub fork (if you didn't use the UI)
-git push origin --delete
+git push -d origin
```
# See your changes in production
diff --git a/contributing/getting-started-quick.md b/contributing/getting-started-quick.md
index 14d8943cca83..8885f271d01c 100644
--- a/contributing/getting-started-quick.md
+++ b/contributing/getting-started-quick.md
@@ -25,7 +25,7 @@ This Quick Start guide is the TL;DR version of the longer [end-to-end guide](get
* [Install and set up Git](https://help.github.com/articles/set-up-git/); in the "Authenticating" step of that page use SSH instead of HTTPS
-* Install [NodeJS](https://nodejs.org/) version >= 6 (which includes npm)
+* Install [Node.js](https://nodejs.org/) version >= 6 (which includes npm); [NVM](https://github.com/creationix/nvm) is a convenient way to do this on Mac and Linux
* Install [Yarn](https://yarnpkg.com/) version >= 1.2.0 (instructions [here](https://yarnpkg.com/en/docs/install), this may require elevated privileges using `sudo` on some platforms)
@@ -34,18 +34,17 @@ This Quick Start guide is the TL;DR version of the longer [end-to-end guide](get
* Add this line to your hosts file (`/etc/hosts` on Mac or Linux, `%SystemRoot%\System32\drivers\etc\hosts` on Windows):
```
- 127.0.0.1 ads.localhost iframe.localhost
+ 127.0.0.1 ads.localhost iframe.localhost
```
* Fork the [amphtml repository](https://github.com/ampproject/amphtml) by clicking "Fork" in the Web UI.
* Create your local repository: `git clone git@github.com:/amphtml.git`
-* Add an alias: Go to the newly created local repository directory and run `git remote add upstream git@github.com:ampproject/amphtml.git`
+* Add an alias: Go to the newly created local repository directory and run `git remote add upstream git@github.com:ampproject/amphtml.git` and then `git branch -u upstream/master master`
# Branch (do this each time you want a new branch)
-* Create the branch: `git branch --track origin/master`
-* Go to the branch: `git checkout `
+* Create and go to the branch: `git checkout -b master`
# Build AMP & run a local server
@@ -73,7 +72,7 @@ This Quick Start guide is the TL;DR version of the longer [end-to-end guide](get
# Pull the latest changes
* `git checkout master`
-* `git pull upstream master`
+* `git pull`
* `git checkout `
* `git rebase master`
* Note that you may need to resolve conflicting changes at this point
@@ -82,10 +81,11 @@ This Quick Start guide is the TL;DR version of the longer [end-to-end guide](get
* Pull the latest changes as described above
* `git checkout `
-* `git push origin `
+* `git push -u origin `
* Go to [https://github.com/ampproject/amphtml](https://github.com/ampproject/amphtml) and in the banner indicating you've recently pushed a branch, click the "Compare & pull request" (if this banner does not appear, go to your fork at `https://github.com//amphtml`, choose your branch from the "Branch" dropdown and click "New pull request")
* Make sure you've signed the CLA (using the same email address as your git config indicates)
* If your reviewer requests changes make them locally and then repeat the steps in this section to push the changes to your branch back up to GitHub again
+* For pushes after the first, just use `git push`
* If you don't get a new review within 2 business days, feel free to ping the pull request by adding a comment
* Once approved your changes are merged into the amphtml repository by a core committer (you don't do this merge)
@@ -93,7 +93,7 @@ This Quick Start guide is the TL;DR version of the longer [end-to-end guide](get
* Go to the master branch: `git checkout master`
* Delete your local branch: `git branch -D `
-* Delete the GitHub fork branch: `git push origin --delete `
+* Delete the GitHub fork branch: `git push -d origin `
# See your changes in production
diff --git a/examples/amp-byside-content.amp.html b/examples/amp-byside-content.amp.html
new file mode 100644
index 000000000000..eb36c1cdd080
--- /dev/null
+++ b/examples/amp-byside-content.amp.html
@@ -0,0 +1,55 @@
+
+
+
+
+ BySide Content example
+
+
+
+
+
+
+
+
+ Responsive layout content (with restricted max width)
+
+
+
+
+ Fixed height content with overflow
+
+
+ Fixed layout content
+
+
+
diff --git a/examples/amp-story-auto-ads.amp.html b/examples/amp-story-auto-ads.amp.html
new file mode 100644
index 000000000000..dbcd5fee5809
--- /dev/null
+++ b/examples/amp-story-auto-ads.amp.html
@@ -0,0 +1,145 @@
+
+
+
+
+ amp-story
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fade-in
+
+
+
+
+
+
+
+ twirl-in
+
+
+
+
+
+
+
+ fly-in-left
+
+
+
+
+
+
+
+ fly-in-right
+
+
+
+
+
+
+
+ fly-in-top
+
+
+
+
+
+
+
+ fly-in-bottom
+
+
+
+
+
+
+
+ rotate-in-left
+
+
+
+
+
+
+
+ rotate-in-right
+
+
+
+
+
+
+
+ drop-in
+
+
+
+
+
+
+
+ whoosh-in-left
+
+
+
+
+
+
+
+ whoosh-in-right
+
+
+
+
+
+
+
diff --git a/examples/amp-story/bookend.html b/examples/amp-story/bookend.html
index a8b2e9c5ae05..ea84b6a54863 100644
--- a/examples/amp-story/bookend.html
+++ b/examples/amp-story/bookend.html
@@ -18,6 +18,33 @@
background-color: white;
}
+
diff --git a/examples/amp-story/bookend.json b/examples/amp-story/bookend.json
index 711e8d87208b..a182b743cf02 100644
--- a/examples/amp-story/bookend.json
+++ b/examples/amp-story/bookend.json
@@ -7,7 +7,7 @@
{
"title": "This is an example article",
"url": "http://example.com/article.html",
- "image": "http://placehold.it/128x128"
+ "image": "http://placehold.it/256x128"
}
]
}
diff --git a/examples/facebook.amp.html b/examples/facebook.amp.html
index 2308809e931b..46056c1ffa51 100644
--- a/examples/facebook.amp.html
+++ b/examples/facebook.amp.html
@@ -9,6 +9,7 @@
+
@@ -25,6 +26,12 @@ Facebook
More Posts
+
+
+
Comments
data-href="https://developers.facebook.com/docs/plugins/comments">
+
+
+
Like button
Like button
data-href="https://www.facebook.com/testesmegadivertidos/">
+
+
+
Like button with faces
Like button with faces
data-href="https://www.facebook.com/GoogleBrasil">
+Page
+
+
+
+
+
+