Pull base story layout from layout file

This commit is contained in:
Sam Carlton 2021-03-20 16:21:22 -05:00
parent d90d7f9016
commit e7175d2b76
3 changed files with 331 additions and 372 deletions

View file

@ -9,14 +9,18 @@ console.log('Running Default Layout file')
const year = new Date().getFullYear() const year = new Date().getFullYear()
const makeTag = ( tag, tagName = 'meta') => { export function makeFullUrlFromPath ( path ) {
return `${process.env.URL}${path}`
}
export const makeTag = ( tag, tagName = 'meta') => {
const attributes = Object.entries(tag).map( ([ name, value ]) => `${name}="${value}"` ).join(' ') const attributes = Object.entries(tag).map( ([ name, value ]) => `${name}="${value}"` ).join(' ')
return `<${tagName} ${attributes}>` return `<${tagName} ${attributes}>`
} }
const mapMetaTag = ( tag ) => { export const mapMetaTag = ( tag ) => {
if ( tag.hasOwnProperty('property') ) { if ( tag.hasOwnProperty('property') ) {
return [ return [
@ -40,7 +44,7 @@ const mapMetaTag = ( tag ) => {
} }
} }
const mapLinkTag = ( tag ) => { export const mapLinkTag = ( tag ) => {
return [ return [
`type-${tag.type}`, `type-${tag.type}`,
makeTag(tag, 'link') makeTag(tag, 'link')
@ -54,12 +58,29 @@ const getNuxtDefaultLayoutHtml = () => {
return fileContents return fileContents
} }
const templateVar = string => `--- template-var ${string} ---` export const templateVar = ( string, asComment = true ) => {
if ( asComment === false ) {
return `-- template-var ${string} --`
}
const cleanNuxtLayout = ( layout ) => { return `<!-- template-var ${string} -->`
}
const cleanNuxtLayout = ( layout, options ) => {
const {
excludedElements = [],
replaceElements = {}
} = options
const document = layout.window.document const document = layout.window.document
excludedElements.forEach( selector => {
Array.from( document.querySelectorAll(selector) ).forEach( domNode => {
domNode.remove()
})
})
// Strip out existing meta // Strip out existing meta
Array.from(document.querySelectorAll('head > meta')).forEach( domNode => { Array.from(document.querySelectorAll('head > meta')).forEach( domNode => {
domNode.remove() domNode.remove()
@ -89,7 +110,7 @@ const cleanNuxtLayout = ( layout ) => {
// Set page title // Set page title
document.title = templateVar('title') document.title = templateVar('title', false)
// Set link tags // Set link tags
document.querySelector('title').insertAdjacentHTML('afterend', templateVar('link-tags') ) document.querySelector('title').insertAdjacentHTML('afterend', templateVar('link-tags') )
@ -100,6 +121,12 @@ const cleanNuxtLayout = ( layout ) => {
// Set page css // Set page css
// document.querySelector('head').insertAdjacentHTML('beforeend', this.getCss() ) // document.querySelector('head').insertAdjacentHTML('beforeend', this.getCss() )
// Set header-scripts placeholder
document.querySelector('title').insertAdjacentHTML('afterend', templateVar('header-scripts') )
// Set header-styles placeholder
document.querySelector('title').insertAdjacentHTML('afterend', templateVar('header-styles') )
// Set page content // Set page content
document.querySelector('.app-main').innerHTML = templateVar('main-content')//content document.querySelector('.app-main').innerHTML = templateVar('main-content')//content
@ -107,11 +134,28 @@ const cleanNuxtLayout = ( layout ) => {
// `<script>${ this.getJs() }</script>` // `<script>${ this.getJs() }</script>`
document.querySelector('body').insertAdjacentHTML('beforeend', templateVar('scripts') ) document.querySelector('body').insertAdjacentHTML('beforeend', templateVar('scripts') )
// Run additional replacements
for ( const selector in replaceElements ) {
// console.log('domNode', selector, document.querySelector( selector ), replaceElements[ selector ])
Array.from( document.querySelectorAll( selector ) ).forEach( domNode => {
// console.log('domNode', domNode, replaceElements[ selector ])
domNode.outerHTML = replaceElements[ selector ]
})
}
return layout return layout
} }
let nuxtLayoutHtml = null let nuxtLayoutHtml = null
const parseDefaultLayoutDom = () => { export const parseDefaultLayoutDom = ( options = {} ) => {
// const {
// excludedElements = [],
// replaceElements = {}
// } = options
if ( nuxtLayoutHtml === null ) { if ( nuxtLayoutHtml === null ) {
nuxtLayoutHtml = getNuxtDefaultLayoutHtml() nuxtLayoutHtml = getNuxtDefaultLayoutHtml()
} }
@ -120,7 +164,7 @@ const parseDefaultLayoutDom = () => {
// Build initial dom from the Layout // Build initial dom from the Layout
const dom = new JSDOM( nuxtLayoutHtml ) const dom = new JSDOM( nuxtLayoutHtml )
const cleanedLayout = cleanNuxtLayout( dom ) const cleanedLayout = cleanNuxtLayout( dom, options )
return cleanedLayout return cleanedLayout
} }
@ -201,7 +245,7 @@ class DefaultLayout {
// Set page title // Set page title
// pageTitle // pageTitle
workingLayoutString = workingLayoutString.replace( templateVar('title'), pageTitle ) workingLayoutString = workingLayoutString.replace( templateVar('title', false), pageTitle )
// Set link tags // Set link tags
// this.generateLinkTags() // this.generateLinkTags()

View file

@ -0,0 +1,184 @@
import config from '../nuxt.config'
import {
makeFullUrlFromPath,
mapMetaTag,
mapLinkTag,
parseDefaultLayoutDom,
templateVar
} from './default.11ty.js'
console.log('Running Story Layout file')
// Buld data that only needs to run once
const defaultMeta = Object.fromEntries(config.head.meta.map( mapMetaTag ))
const defaultLinkTags = Object.fromEntries(config.head.link.map( mapLinkTag ))
const masterLayoutDomString = parseDefaultLayoutDom({
replaceElements: {
// Replace root nuxt element
// and get rid of normal layout
'#__nuxt': templateVar('main-content')
}
}).serialize()
class StoryLayout {
generateMetaTags = function ( renderData ) {
const {
title = null,
description = null,
pageMeta = []
} = renderData
// https://amp.dev/documentation/components/amp-story/#metadata-guidelines
const meta = {
...defaultMeta,
'property-twitter:url': /* html */`<meta property="twitter:url" content="${ makeFullUrlFromPath( this.page.url ) }">`,
'amp-story-generator-name': /* html */`<meta name="amp-story-generator-name" content="DoesItARM" />`,
'amp-story-generator-version': /* html */`<meta name="amp-story-generator-version" content="1.0" />`,
'og:url': /* html */`<meta property="og:url" content="${ makeFullUrlFromPath( renderData.page.url ) }" />`,
'twitter:creator': /* html */`<meta property="twitter:site" content="@DoesItARM" />`,
'title': /* html */`<meta property="title" content="${ renderData.title }" />`,
'og:title': /* html */`<meta property="og:title" content="${ renderData.title }" />`,
// 'twitter:title': /* html */`<meta property="twitter:title" content="${ renderData.title }" />`, // Already included
// Example: <meta property="og:modified_time" content="2021-03-13T00:00:00.000Z" />
'og:modified_time': /* html */`<meta property="og:modified_time" content="${ renderData.lastUpdatedDate.toISOString() }" />`,
'og:type': /* html */`<meta property="og:type" content="article" />`,
...Object.fromEntries( pageMeta.map(mapMetaTag) )
}
// if set
// get description from data
if ( description ) {
// Set meta description
meta['name-description'] = `<meta hid="description" name="description" content="${ description }">`
// Set twitter description
meta['property-twitter:description'] = `<meta hid="twitter:description" property="twitter:description" content="${ description }">`
}
// if set
// get title from data
if ( title ) {
// Set twitter title
meta['property-twitter:title'] = `<meta hid="twitter:title" property="twitter:title" content="${ title }">`
}
return Object.values(meta).join('')
}
generateLinkTags = ( pageLinkTags = [] ) => {
const layoutLinkTags = {
ampCorePreload: /* html */`<link href="https://cdn.ampproject.org/v0.js" rel="preload" as="script" />`,
icon: /* html */`<link rel="shortcut icon" href="/images/mark.png" type="image/x-icon" />`,
canonical: /* html */`<link rel="canonical" href="${ makeFullUrlFromPath( this.page.url ) }">`,
ampYoutubeStylesheet: /* html */`<link rel="stylesheet" href="https://cdn.ampproject.org/v0/amp-youtube-1.0.css" />`,
}
const linkTags = {
...defaultLinkTags,
...layoutLinkTags,
...Object.fromEntries(pageLinkTags.map( mapLinkTag ))
}
return Object.values( linkTags ).join('')
}
defaultHeaderScripts = () => {
return {
ampCore: /* html */`<script async src="https://cdn.ampproject.org/v0.js"></script>`,
ampStoryElement: /* html */`<script async custom-element="amp-story" src="https://cdn.ampproject.org/v0/amp-story-1.0.js"></script>`,
ampYoutubeElement: /* html */`<script async custom-element="amp-youtube" src="https://cdn.ampproject.org/v0/amp-youtube-1.0.js"></script>`,
}
}
defaultHeaderStyleTags = () => {
return {
ampBoilerplate: /* html */`<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>`,
// ampCore: /* html */`<script async src="https://cdn.ampproject.org/v0.js"></script>`,
}
}
async render( data ) {
// return nuxtLayoutHtml
// console.log('Running StoryLayout render')
const {
content,
title = null,
headerScripts = {},
jsonLd
// description = null
} = data
const pageTitle = title || this.getNuxt().head.title
const headerScriptsHtml = Object.values( {
...this.defaultHeaderScripts(),
jsonLd: /* html */`<script type="application/ld+json">${ JSON.stringify( jsonLd ) }</script>`
} ).join('')
const headerStylesHtml = Object.values( {
...this.defaultHeaderStyleTags()
} ).join('')
let workingLayoutString = masterLayoutDomString
// Set as an amp html document
workingLayoutString = workingLayoutString.replace( '<html ', '<html amp ' )
// Set page title
// pageTitle
workingLayoutString = workingLayoutString.replace( templateVar('title', false), pageTitle )
// Set link tags
// this.generateLinkTags()
workingLayoutString = workingLayoutString.replace( templateVar('link-tags'), this.generateLinkTags() )
// Add meta tags after title node
// this.generateMetaTags( data )
workingLayoutString = workingLayoutString.replace( templateVar('meta-tags'), this.generateMetaTags( data ) )
// Add header scripts
workingLayoutString = workingLayoutString.replace( templateVar('header-scripts'), headerScriptsHtml )
// Add header-styles
workingLayoutString = workingLayoutString.replace( templateVar('header-styles'), headerStylesHtml )
// Make the Tailwind css our amp-custom style tag
// https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/
workingLayoutString = workingLayoutString.replace( '<style data-vue-ssr-id', '<style amp-custom data-vue-ssr-id' )
// Set page css
// document.querySelector('head').insertAdjacentHTML('beforeend', this.getCss() )
// Set page content
// content
workingLayoutString = workingLayoutString.replace( templateVar('main-content'), content )
// Set js before end of body
// `<script>${ this.getJs() }</script>`
workingLayoutString = workingLayoutString.replace( templateVar('scripts'), `<script>${ this.getJs() }</script>` )
// Return stringified html for page
return workingLayoutString
}
}
module.exports = StoryLayout

View file

@ -5,7 +5,12 @@ import config from '../nuxt.config.js'
import { hasStory, getStoryEndpoint } from '../helpers/app-derived.js' import { hasStory, getStoryEndpoint } from '../helpers/app-derived.js'
import { makeLastUpdatedFriendly } from '../helpers/parse-date' import { makeLastUpdatedFriendly } from '../helpers/parse-date'
import {
makeFullUrlFromPath
} from '../layouts-eleventy/default.11ty.js'
import CoverPage from '../components-eleventy/story/cover.js' import CoverPage from '../components-eleventy/story/cover.js'
import YoutubePage from '../components-eleventy/story/youtube.js'
// import VideoRow from '../components-eleventy/video/row.js' // import VideoRow from '../components-eleventy/video/row.js'
@ -24,10 +29,6 @@ export const makeDescription = function ( app ) {
return `Reported status of ${ app.name } on Apple Silicon and the new Apple Macs. ` return `Reported status of ${ app.name } on Apple Silicon and the new Apple Macs. `
} }
function makeFullUrlFromPath ( path ) {
return `${process.env.URL}${path}`
}
// https://stackoverflow.com/a/34015511/1397641 // https://stackoverflow.com/a/34015511/1397641
function makeJsonLdDate ( dateObject ) { function makeJsonLdDate ( dateObject ) {
return dateObject.toLocaleDateString('en-US') return dateObject.toLocaleDateString('en-US')
@ -106,7 +107,7 @@ export class Story {
// or `get data() {` // or `get data() {`
data () { data () {
return { return {
// layout: 'default.11ty.js', layout: 'story.11ty.js',
pagination: { pagination: {
data: 'eleventy-endpoints', data: 'eleventy-endpoints',
@ -117,7 +118,9 @@ export class Story {
return data.filter( entry => { return data.filter( entry => {
// const appType = getAppType( entry.payload.app ) // const appType = getAppType( entry.payload.app )
return hasStory ( entry.payload.app ) && entry.route === getStoryEndpoint( entry.payload.app ) // return hasStory ( entry.payload.app ) && entry.route === getStoryEndpoint( entry.payload.app )
return entry.route.includes('/photoshop/story/')
}) })
} }
}, },
@ -134,6 +137,8 @@ export class Story {
mainHeading: ({ app: { payload: { app } } }) => { mainHeading: ({ app: { payload: { app } } }) => {
return `Does ${ app.name } work on Apple Silicon?` return `Does ${ app.name } work on Apple Silicon?`
}, },
jsonLd: data => makeJsonLdObject( data ),
lastUpdatedDate: data => new Date( data.app.payload.app.lastUpdated.raw )
}, },
permalink: ({ app }) => { permalink: ({ app }) => {
@ -164,11 +169,21 @@ export class Story {
// Build cover page // Build cover page
pages.push({ pages.push({
template: CoverPage, template: CoverPage,
heading: `${ app.name } has been reported to support Apple Silicon nativelty as of ${lastUpdatedFriendly}!`, heading: `${ app.name } has been reported to support Apple Silicon natively as of ${lastUpdatedFriendly}!`,
headingUrl: '', headingUrl: '',
imageUrl: '/images/backgrounds/liquid-cheese.svg' imageUrl: '/images/backgrounds/liquid-cheese.svg'
}) })
// console.log('app', app)
if (Array.isArray( app.relatedVideos ) && app.relatedVideos.length > 0 ) {
app.relatedVideos.forEach( video => {
pages.push({
template: YoutubePage,
videoId: 'dQw4w9WgXcQ'
})
})
}
return pages return pages
} }
@ -193,7 +208,7 @@ export class Story {
// console.log('video.payload', Object.keys(video.payload)) // console.log('video.payload', Object.keys(video.payload))
const lastUpdatedFriendly = makeLastUpdatedFriendly( app.lastUpdated ) const lastUpdatedFriendly = makeLastUpdatedFriendly( app.lastUpdated )
const jsonLd = JSON.stringify( makeJsonLdObject( data ) ) // const jsonLd = JSON.stringify( makeJsonLdObject( data ) )
const pages = this.buildPages( data ) const pages = this.buildPages( data )
@ -202,373 +217,89 @@ export class Story {
} ).join('') } ).join('')
return /* html */` return /* html */`
<!doctype html>
<html amp lang="en">
<head>
<meta charset="utf-8">
<link href="https://cdn.ampproject.org/v0.js" rel="preload" as="script" />
<script async src="https://cdn.ampproject.org/v0.js"></script>
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<meta name="amp-story-generator-name" content="DoesItARM" />
<meta name="amp-story-generator-version" content="1.0" />
<title>${ pageTitle }</title>
<script async custom-element="amp-story" src="https://cdn.ampproject.org/v0/amp-story-1.0.js"></script>
<meta name="description" property="description" content="${ data.description }">
<link rel="shortcut icon" href="/images/mark.png" type="image/x-icon">
<script type="application/ld+json">${ jsonLd }</script>
<!-- https://amp.dev/documentation/components/amp-story/#metadata-guidelines -->
<meta property="og:url" content="https://doesitarm.com/formula/ack/story" />
<meta property="twitter:site" content="@DoesItARM" />
<meta property="twitter:creator" content="@DoesItARM" />
<meta property="title" content="Does It ARM" />
<meta property="og:title" content="Does It ARM" />
<meta property="twitter:title" content="Does It ARM" />
<meta property="description" content="${ data.description }" />
<meta property="og:description" content="${ data.description }" />
<meta property="twitter:description" content="${ data.description }" />
<meta property="og:published_time" content="2021-03-13T00:00:00.000Z" />
<meta property="og:modified_time" content="2021-03-13T00:00:00.000Z" />
<meta name="twitter:card" content="summary" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://doesitarm.com/formula/ack/story">
<style amp-custom>
.pbxiyzxp amp-img.pbxiyzx > img{
max-width : unset;
max-height : unset;
margin : 0;
height : 100%;
left : 0.00%;
object-fit : cover;
top : 0.00%;
width : 100%;
}
.scrim#vsyyg{
background : no-repeat linear-gradient(0deg, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 30%);
}
.zegok{
color : #fff;
font-family : Inter;
font-size : 3.02em;
font-weight : 300;
left : 10.56%;
letter-spacing : 0.03em;
line-height : 1.4em;
top : 46.50%;
width : 78.61%;
}
.pbgmmaxp amp-img.pbgmmax > img{
max-width : unset;
max-height : unset;
margin : 0;
height : 100%;
left : 0.00%;
object-fit : cover;
top : 0.00%;
width : 100%;
}
.scrim#ptttz{
background : no-repeat linear-gradient(0deg, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 30%);
}
.rqzpl{
color : #fff;
font-family : Inter;
font-size : 3.02em;
font-weight : 300;
left : 10.56%;
letter-spacing : 0.03em;
line-height : 1.4em;
top : 31.50%;
width : 78.61%;
}
.pbxnmpgp amp-img.pbxnmpg > img{
max-width : unset;
max-height : unset;
margin : 0;
height : 100%;
left : 0.00%;
object-fit : cover;
top : 0.00%;
width : 100%;
}
.scrim#zuxpp{
background : no-repeat linear-gradient(0deg, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 30%);
}
.awhlw{
color : #fff;
font-family : Inter;
font-size : 3.02em;
font-weight : 300;
left : 10.56%;
letter-spacing : 0.03em;
line-height : 1.4em;
top : 51.17%;
width : 78.61%;
}
.pbnrcrzp amp-img.pbnrcrz > img{
max-width : unset;
max-height : unset;
margin : 0;
height : 100%;
left : 0.00%;
object-fit : cover;
top : 0.00%;
width : 100%;
}
.scrim#eszze{
background : no-repeat linear-gradient(0deg, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 30%);
}
.vlsci{
color : #fff;
font-family : Inter;
font-size : 3.02em;
font-weight : 700;
left : 8.33%;
letter-spacing : 0.03em;
line-height : 1.4em;
top : 60.00%;
width : 83.33%;
}
.rzjym{
background : #1657cd;
border-radius : 5px;
color : #fff;
font-family : Inter;
font-size : 1.60em;
font-weight : 500;
height : 40px;
left : 8.33%;
line-height : 1.4em;
text-align : center;
top : 60px;
width : 83.33%;
}
amp-img{ position: relative }
.content-block{ padding: 10px 15px }
.block{ position: relative; padding: 5px;word-break: break-word;}
.content-block amp-video{ display: block; margin: 0 auto}
.content-block > hr {padding: 0;margin: 5px 0;border-top: 1px solid #eee}
.block a:not(.cta-a) {color: inherit;text-decoration: none}
p, h1, h2, h3, h4, h5, h6{ padding: 0;margin: 0 }
.cta-a{
text-decoration: none;
display: flex;
align-items: center;
}
.cta-a span{
width:100%;
}
.svg-el svg{
display: block;
width: 100%;
height: 100%;
}
.block .cta-a {
padding: 0.3em 1em;
display: inline-block;
}
*{
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.cta-a amp-img{
width: 100%;
height: 100%;
}
.cta-a amp-img img{
height:100%;
width: 100%;
min-height: unset;
}
.flip-vertically img, .flip-vertically svg{
transform: rotateY(180deg);
}
.flip-horizontally img, .flip-horizontally svg{
transform: rotateX(180deg);
}
.flip-horizontally.flip-vertically img, .flip-horizontally.flip-vertically svg{
transform: rotateX(180deg) rotateY(180deg);
}
.pa{
position: absolute;
word-break: break-word;
}
.txt-hl{
-webkit-box-decoration-break: clone;
-o-box-decoration-break: clone;
box-decoration-break: clone;
}
.img-fill,a.story-tooltip{
top:0;
left:0;
width:100%;
height:100%;
font-size: inherit;
font-weight: inherit;
}
a.story-tooltip{
text-decoration: none;
color: inherit;
}
.offset{
transform: translateX(-50%) translateY(-50%)
}
.oh{
overflow: hidden;
}
.pa.kbimg{
width: 0;
height: 0
}
.pa-list-type{
padding:5px;
padding-left:19px;
margin:5px 0 0 0;
}
ol.pa-list-type{
list-style:lower-alpha;
}
.block .pa-list-type li a{color: #1890ff;}
amp-story{
font-size:3.125vw
}
@media screen and (min-aspect-ratio: 3/5) and (max-aspect-ratio: 5/5){
amp-story {
font-size: 1.875vh
}
.letterbox{
width:60vh;
height: 100vh;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
amp-story-cta-layer .letterbox{
height: 20vh;
}
}
@media screen and (min-width:1024px){
amp-story{font-size:1.8vh}
}
@media screen and (min-width:1024px) and (max-height:660px){
amp-story{font-size:1.8vh}
}
::cue {
background-color: rgba(0, 0, 0, 0.75);
font-size: 24px;
line-height: 1.5;
}
</style>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?display=swap&family=Inter:400,300" media="all">
</head>
<body>
<amp-story standalone poster-portrait-src="/images/poster-portrait.jpeg" publisher-logo-src="/images/mark.png" publisher="Does It ARM" title="Does It ARM" poster-landscape-src="/images/poster-landscape.jpeg" poster-square-src="/images/poster-landscape.jpeg"> <amp-story standalone poster-portrait-src="/images/poster-portrait.jpeg" publisher-logo-src="/images/mark.png" publisher="Does It ARM" title="Does It ARM" poster-landscape-src="/images/poster-landscape.jpeg" poster-square-src="/images/poster-landscape.jpeg">
${ pagesHtml } ${ pagesHtml }
<!-- PAGE 1 STARTS HERE --> <!-- PAGE 1 STARTS HERE -->
<amp-story-page id="jlqerrcdhz" class="jlqerrcdhz ms-st-pg" > <amp-story-page id="jlqerrcdhz" class="jlqerrcdhz ms-st-pg" >
<!-- PAGE BACKGROUND LAYER (jlqerrcdhz) --> <!-- PAGE BACKGROUND LAYER (jlqerrcdhz) -->
<amp-story-grid-layer template="fill" class="pbxiyzxp"> <amp-story-grid-layer template="fill" class="pbxiyzxp">
<amp-img width='720' height='1280' layout='responsive' class='pbxiyzx' id='jlqerrcdhz-bg' src='/images/backgrounds/liquid-cheese.svg' alt='App is now native' ></amp-img> <amp-img width='720' height='1280' layout='responsive' class='pbxiyzx' id='jlqerrcdhz-bg' src='/images/backgrounds/liquid-cheese.svg' alt='App is now native' ></amp-img>
</amp-story-grid-layer> </amp-story-grid-layer>
<!-- PAGE BACKGROUND LAYER (jlqerrcdhz) ENDS --> <!-- PAGE BACKGROUND LAYER (jlqerrcdhz) ENDS -->
<amp-story-grid-layer template="vertical" id="vsyyg" class="scrim"><div class="letterbox"> <amp-story-grid-layer template="vertical" id="vsyyg" class="scrim"><div class="letterbox">
<!-- The best therapist has fur and four legs STARTS HERE --> <!-- The best therapist has fur and four legs STARTS HERE -->
<h1 class='zegok pa' animate-in='fade-in' animate-in-duration='500ms' id='workflow-text' >Ack has&nbsp; been reported to support Apple Silicon nativelty as of ${lastUpdatedFriendly}!<a href='https://doesitarm.com/formula/ack/' role='link' data-tooltip-text='Details' class='story-tooltip pa' data-tooltip-icon='https://www.google.com/s2/favicons?domain=https://doesitarm.com/formula/ack/' data-vars-ctalink='https://doesitarm.com/formula/ack/' ></a></h1> <h1 class='zegok pa' animate-in='fade-in' animate-in-duration='500ms' id='workflow-text' >Ack has&nbsp; been reported to support Apple Silicon natively as of ${lastUpdatedFriendly}!<a href='https://doesitarm.com/formula/ack/' role='link' data-tooltip-text='Details' class='story-tooltip pa' data-tooltip-icon='https://www.google.com/s2/favicons?domain=https://doesitarm.com/formula/ack/' data-vars-ctalink='https://doesitarm.com/formula/ack/' ></a></h1>
<!-- The best therapist has fur and four legs ENDS HERE --> <!-- The best therapist has fur and four legs ENDS HERE -->
</div></amp-story-grid-layer> </div></amp-story-grid-layer>
</amp-story-page> </amp-story-page>
<!-- PAGE 1 ENDS HERE --> <!-- PAGE 1 ENDS HERE -->
<!-- PAGE 2 STARTS HERE --> <!-- PAGE 2 STARTS HERE -->
<amp-story-page id="fbttedbsmc" class="fbttedbsmc ms-st-pg" > <amp-story-page id="fbttedbsmc" class="fbttedbsmc ms-st-pg" >
<!-- PAGE BACKGROUND LAYER (fbttedbsmc) --> <!-- PAGE BACKGROUND LAYER (fbttedbsmc) -->
<amp-story-grid-layer template="fill" class="pbgmmaxp"> <amp-story-grid-layer template="fill" class="pbgmmaxp">
<amp-img width='720' height='1280' layout='responsive' class='pbgmmax' id='fbttedbsmc-bg' src='assets/1.png' alt='App is now native' ></amp-img> <amp-img width='720' height='1280' layout='responsive' class='pbgmmax' id='fbttedbsmc-bg' src='assets/1.png' alt='App is now native' ></amp-img>
</amp-story-grid-layer> </amp-story-grid-layer>
<!-- PAGE BACKGROUND LAYER (fbttedbsmc) ENDS --> <!-- PAGE BACKGROUND LAYER (fbttedbsmc) ENDS -->
<amp-story-grid-layer template="vertical" id="ptttz" class="scrim"><div class="letterbox"> <amp-story-grid-layer template="vertical" id="ptttz" class="scrim"><div class="letterbox">
<!-- The best therapist has fur and four legs STARTS HERE --> <!-- The best therapist has fur and four legs STARTS HERE -->
<h1 class='rqzpl pa' animate-in='fade-in' animate-in-duration='500ms' id='lghxplitnh' >ack has will support Apple Silicon and take full advantage of new higher perfomance Macs.&nbsp;<a href='https://doesitarm.com/formula/ack/' role='link' data-tooltip-text='Details' class='story-tooltip pa' data-tooltip-icon='https://www.google.com/s2/favicons?domain=https://doesitarm.com/formula/ack/' data-vars-ctalink='https://doesitarm.com/formula/ack/' ></a></h1> <h1 class='rqzpl pa' animate-in='fade-in' animate-in-duration='500ms' id='lghxplitnh' >ack has will support Apple Silicon and take full advantage of new higher perfomance Macs.&nbsp;<a href='https://doesitarm.com/formula/ack/' role='link' data-tooltip-text='Details' class='story-tooltip pa' data-tooltip-icon='https://www.google.com/s2/favicons?domain=https://doesitarm.com/formula/ack/' data-vars-ctalink='https://doesitarm.com/formula/ack/' ></a></h1>
<!-- The best therapist has fur and four legs ENDS HERE --> <!-- The best therapist has fur and four legs ENDS HERE -->
</div></amp-story-grid-layer> </div></amp-story-grid-layer>
</amp-story-page> </amp-story-page>
<!-- PAGE 2 ENDS HERE --> <!-- PAGE 2 ENDS HERE -->
<!-- PAGE 3 STARTS HERE --> <!-- PAGE 3 STARTS HERE -->
<amp-story-page id="vkmxqexwmf" class="vkmxqexwmf ms-st-pg" > <amp-story-page id="vkmxqexwmf" class="vkmxqexwmf ms-st-pg" >
<!-- PAGE BACKGROUND LAYER (vkmxqexwmf) --> <!-- PAGE BACKGROUND LAYER (vkmxqexwmf) -->
<amp-story-grid-layer template="fill" class="pbxnmpgp"> <amp-story-grid-layer template="fill" class="pbxnmpgp">
<amp-img width='720' height='1280' layout='responsive' class='pbxnmpg' id='vkmxqexwmf-bg' src='assets/1.png' alt='App is now native' ></amp-img> <amp-img width='720' height='1280' layout='responsive' class='pbxnmpg' id='vkmxqexwmf-bg' src='assets/1.png' alt='App is now native' ></amp-img>
</amp-story-grid-layer> </amp-story-grid-layer>
<!-- PAGE BACKGROUND LAYER (vkmxqexwmf) ENDS --> <!-- PAGE BACKGROUND LAYER (vkmxqexwmf) ENDS -->
<amp-story-grid-layer template="vertical" id="zuxpp" class="scrim"><div class="letterbox"> <amp-story-grid-layer template="vertical" id="zuxpp" class="scrim"><div class="letterbox">
<!-- The best therapist has fur and four legs STARTS HERE --> <!-- The best therapist has fur and four legs STARTS HERE -->
<h1 class='awhlw pa' animate-in='fade-in' animate-in-duration='500ms' id='qwtfraqrbe' >This will apply to ack version 3.0.2 and newer&nbsp;<a href='https://doesitarm.com/formula/ack/' role='link' data-tooltip-text='Details' class='story-tooltip pa' data-tooltip-icon='https://www.google.com/s2/favicons?domain=https://doesitarm.com/formula/ack/' data-vars-ctalink='https://doesitarm.com/formula/ack/' ></a></h1> <h1 class='awhlw pa' animate-in='fade-in' animate-in-duration='500ms' id='qwtfraqrbe' >This will apply to ack version 3.0.2 and newer&nbsp;<a href='https://doesitarm.com/formula/ack/' role='link' data-tooltip-text='Details' class='story-tooltip pa' data-tooltip-icon='https://www.google.com/s2/favicons?domain=https://doesitarm.com/formula/ack/' data-vars-ctalink='https://doesitarm.com/formula/ack/' ></a></h1>
<!-- The best therapist has fur and four legs ENDS HERE --> <!-- The best therapist has fur and four legs ENDS HERE -->
</div></amp-story-grid-layer> </div></amp-story-grid-layer>
</amp-story-page> </amp-story-page>
<!-- PAGE 3 ENDS HERE --> <!-- PAGE 3 ENDS HERE -->
<!-- PAGE 4 STARTS HERE --> <!-- PAGE 4 STARTS HERE -->
<amp-story-page id="ealonwjwyf" class="ealonwjwyf ms-st-pg" > <amp-story-page id="ealonwjwyf" class="ealonwjwyf ms-st-pg" >
<!-- PAGE BACKGROUND LAYER (ealonwjwyf) --> <!-- PAGE BACKGROUND LAYER (ealonwjwyf) -->
<amp-story-grid-layer template="fill" class="pbnrcrzp"> <amp-story-grid-layer template="fill" class="pbnrcrzp">
<amp-img width='720' height='1280' layout='responsive' class='pbnrcrz' id='ealonwjwyf-bg' src='assets/2.jpeg' alt='App is now native' ></amp-img> <amp-img width='720' height='1280' layout='responsive' class='pbnrcrz' id='ealonwjwyf-bg' src='assets/2.jpeg' alt='App is now native' ></amp-img>
</amp-story-grid-layer> </amp-story-grid-layer>
<!-- PAGE BACKGROUND LAYER (ealonwjwyf) ENDS --> <!-- PAGE BACKGROUND LAYER (ealonwjwyf) ENDS -->
<amp-story-grid-layer template="vertical" id="eszze" class="scrim"><div class="letterbox"> <amp-story-grid-layer template="vertical" id="eszze" class="scrim"><div class="letterbox">
<!-- The best therapist has fur and four legs STARTS HERE --> <!-- The best therapist has fur and four legs STARTS HERE -->
<h1 class='vlsci pa' id='yxdyvhijcn' >The best therapist has fur and four legs</h1> <h1 class='vlsci pa' id='yxdyvhijcn' >The best therapist has fur and four legs</h1>
<!-- The best therapist has fur and four legs ENDS HERE --> <!-- The best therapist has fur and four legs ENDS HERE -->
<!-- cta_1 STARTS HERE --> <!-- cta_1 STARTS HERE -->
<!-- cta_1 ENDS HERE --> <!-- cta_1 ENDS HERE -->
</div></amp-story-grid-layer> </div></amp-story-grid-layer>
<amp-story-cta-layer> <amp-story-cta-layer>
<div class="letterbox"> <div class="letterbox">
<a class='rzjym pa cta-a' href='https://www.google.com/search?q=dog+therapy' id='ctaId' data-vars-ctalink='https://www.google.com/search?q=dog+therapy' ><span>Find More</span></a> <a class='rzjym pa cta-a' href='https://www.google.com/search?q=dog+therapy' id='ctaId' data-vars-ctalink='https://www.google.com/search?q=dog+therapy' ><span>Find More</span></a>
</div> </div>
</amp-story-cta-layer> </amp-story-cta-layer>
</amp-story-page> </amp-story-page>
<!-- PAGE 4 ENDS HERE --> <!-- PAGE 4 ENDS HERE -->
<!-- https://amp.dev/documentation/components/amp-story-bookend/ --> <!-- https://amp.dev/documentation/components/amp-story-bookend/ -->
<amp-story-bookend layout="nodisplay"> <amp-story-bookend layout="nodisplay">
<script type="application/json"> <script type="application/json">
${ bookendJson } ${ bookendJson }
</script> </script>
</amp-story-bookend> </amp-story-bookend>
</amp-story> </amp-story>
</body>
</html>
` `
} }
} }