---
{.background}
# Rody Davis
## Welcome to my site
This is built with Lit-Element, Parcel and Web Components!
---
Based on md2googleslides this will create a Amp Story from Markdown
export function md2ampstory(src: string, meta: AmpMeta): string { | |
const story: AmpStory = { | |
title: meta.title, | |
pages: [], | |
}; | |
// Create Story | |
const sections = src.split("---"); | |
for (let i = 0; i < sections.length; i++) { | |
const section = sections[i]; | |
if (section.trim().length < 1) continue; | |
const layers: AmpLayer[] = []; | |
let layer: AmpVerticalLayer; | |
for (const line of section.split("\n")) { | |
if (line.trim().length < 1) continue; | |
if (line.match(".background")) { | |
const element = elementMap(line); | |
if (element.kind === "image") { | |
const _layer: AmpLayer = { kind: "fill", element: element }; | |
if (layer != null) { | |
layers.push(layer); | |
} | |
layers.push(_layer); | |
layer == null; | |
continue; | |
} | |
} else { | |
if (layer == null) { | |
layer = { kind: "vertical", elements: [] }; | |
} | |
const element = elementMap(line); | |
layer.elements.push(element); | |
} | |
} | |
if (layer != null) { | |
layers.push(layer); | |
layer = null; | |
} | |
story.pages.push({ id: `page_${i}`, layers: layers }); | |
} | |
return renderStory(story); | |
} | |
function renderStory(story: AmpStory): string { | |
// Render Story | |
let result: string[] = []; | |
result.push( | |
`<!DOCTYPE html> | |
<html ⚡> | |
<head> | |
<meta charset="utf-8" /> | |
<title>${story.title}</title> | |
<link rel="canonical" href="pets.html" /> | |
<meta | |
name="viewport" | |
content="width=device-width,minimum-scale=1,initial-scale=1" | |
/> | |
<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 | |
> | |
<script async src="https://cdn.ampproject.org/v0.js"></script> | |
<script | |
async | |
custom-element="amp-video" | |
src="https://cdn.ampproject.org/v0/amp-video-0.1.js" | |
></script> | |
<script | |
async | |
custom-element="amp-story" | |
src="https://cdn.ampproject.org/v0/amp-story-1.0.js" | |
></script> | |
<link | |
href="https://fonts.googleapis.com/css?family=Oswald:200,300,400" | |
rel="stylesheet" | |
/> | |
<style amp-custom> | |
amp-story { | |
font-family: "Oswald", sans-serif; | |
color: #fff; | |
} | |
amp-story-page { | |
background-color: #000; | |
} | |
h1 { | |
font-weight: bold; | |
font-size: 2.875em; | |
font-weight: normal; | |
line-height: 1.174; | |
} | |
p { | |
font-weight: normal; | |
font-size: 1.3em; | |
line-height: 1.5em; | |
color: #fff; | |
} | |
q { | |
font-weight: 300; | |
font-size: 1.1em; | |
} | |
amp-story-grid-layer.bottom { | |
align-content: end; | |
} | |
amp-story-grid-layer.noedge { | |
padding: 0px; | |
} | |
amp-story-grid-layer.center-text { | |
align-content: center; | |
} | |
.wrapper { | |
display: grid; | |
grid-template-columns: 50% 50%; | |
grid-template-rows: 50% 50%; | |
} | |
.banner-text { | |
text-align: center; | |
background-color: #000; | |
line-height: 2em; | |
} | |
</style> | |
<style> | |
* { | |
text-shadow: 1px 1px black; | |
} | |
</style> | |
</head> | |
<body> | |
<!-- Cover page --> | |
<amp-story | |
standalone | |
title="${story.title}" | |
publisher="Rody Davis" | |
publisher-logo-src="images/banner.jpeg" | |
poster-portrait-src="images/banner.jpg" | |
> | |
` | |
); | |
for (const page of story.pages) { | |
result.push(`<amp-story-page id=${page.id}>`); | |
for (let i = 0; i < page.layers.length; i++) { | |
const layer = page.layers[i]; | |
result.push(`<amp-story-grid-layer template="${layer.kind}">`); | |
if (layer.kind == "vertical" || layer.kind == "horizontal") { | |
for (const element of layer.elements) { | |
addElement(element, result); | |
} | |
} else if (layer.kind == "fill") { | |
addElement(layer.element, result); | |
} | |
result.push(`</amp-story-grid-layer>`); | |
} | |
result.push(`</amp-story-page>`); | |
} | |
result.push( | |
`</amp-story> | |
</body> | |
</html> | |
` | |
); | |
return result.join(""); | |
} | |
function addElement(element: AmpElement, result: string[]) { | |
if (element.kind == "text") { | |
result.push(`<${element.tag}>${element.data}</${element.tag}>`); | |
} | |
if (element.kind == "image") { | |
result.push(`<amp-img | |
src="${element.src}" | |
width="${element.width}" | |
height="${element.height}" | |
layout="responsive"> | |
</amp-img>`); | |
} | |
} | |
function elementMap(line: string): AmpElement { | |
line = line.trimLeft(); | |
// Heading | |
if (line.startsWith("# ")) { | |
return { kind: "text", data: line.replace("# ", ""), tag: "h1" }; | |
} | |
if (line.startsWith("## ")) { | |
return { kind: "text", data: line.replace("## ", ""), tag: "h2" }; | |
} | |
if (line.startsWith("### ")) { | |
return { kind: "text", data: line.replace("### ", ""), tag: "h3" }; | |
} | |
if (line.startsWith("#### ")) { | |
return { kind: "text", data: line.replace("#### ", ""), tag: "h4" }; | |
} | |
if (line.startsWith("##### ")) { | |
return { kind: "text", data: line.replace("##### ", ""), tag: "h5" }; | |
} | |
if (line.startsWith("###### ")) { | |
return { kind: "text", data: line.replace("##### ", ""), tag: "h6" }; | |
} | |
// Image | |
if (line.startsWith("![")) { | |
let start: number, end: number; | |
for (let i = 0; i < line.length; i++) { | |
const char = line[i]; | |
if (char == "(") { | |
start = i + 1; | |
} | |
if (char == ")") { | |
end = i; | |
} | |
} | |
if (start != undefined && end != undefined) { | |
return { | |
kind: "image", | |
src: `${line.substring(start, end)}`, | |
width: 720, | |
height: 1280, | |
}; | |
} | |
} | |
// Fallback to Regular Text | |
return { kind: "text", data: line, tag: "p" }; | |
} | |
export interface AmpMeta { | |
title: string; | |
} | |
interface AmpStory { | |
pages: AmpPage[]; | |
title: string; | |
} | |
interface AmpPage { | |
id: string; | |
layers: AmpLayer[]; | |
} | |
type AmpLayer = | |
| AmpVerticalLayer | |
| AmpHorizontalLayer | |
| AmpFillLayer | |
| AmpThirdsLayer; | |
interface AmpVerticalLayer { | |
kind: "vertical"; | |
elements: AmpElement[]; | |
} | |
interface AmpHorizontalLayer { | |
kind: "horizontal"; | |
elements: AmpElement[]; | |
} | |
interface AmpFillLayer { | |
kind: "fill"; | |
element: AmpImageElement; | |
} | |
interface AmpThirdsLayer { | |
kind: "thirds"; | |
upper: AmpElement[]; | |
middle: AmpElement[]; | |
lower: AmpElement[]; | |
} | |
type AmpElement = AmpTextElement | AmpImageElement; | |
interface AmpTextElement { | |
kind: "text"; | |
tag: string; | |
data: string; | |
} | |
interface AmpImageElement { | |
kind: "image"; | |
src: string; | |
width: number; | |
height: number; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment